diff options
| author | Arpit Chakladar <arpitchakladar+git@gmail.com> | 2026-07-13 20:49:57 +0530 |
|---|---|---|
| committer | Arpit Chakladar <arpitchakladar+git@gmail.com> | 2026-07-13 20:49:57 +0530 |
| commit | 6f6c263a072c9df4e826d8ebb2035c82a87be7e0 (patch) | |
| tree | c8b944fe53b660d9d58b5559b10f4c73141e7559 /src/scripts/pages/sheet-map | |
| parent | bc4eb3606afbbc4b54fbb3b4ef81badd06cde525 (diff) | |
| download | banglar-bhumi-utils-6f6c263a072c9df4e826d8ebb2035c82a87be7e0.tar.gz banglar-bhumi-utils-6f6c263a072c9df4e826d8ebb2035c82a87be7e0.zip | |
refactor: organised the scripts into a more well defined structure
now all scripts that are common to all pages lie in src/scripts/common
each page gets its own folder in src/pages and different parts of the
page's configuration are separated in separated folders which are all
finally imported in src/pages/*/index.ts
Diffstat (limited to 'src/scripts/pages/sheet-map')
5 files changed, 282 insertions, 0 deletions
diff --git a/src/scripts/pages/sheet-map/download-map-pdf-page-content.html b/src/scripts/pages/sheet-map/download-map-pdf-page-content.html new file mode 100644 index 0000000..da765ec --- /dev/null +++ b/src/scripts/pages/sheet-map/download-map-pdf-page-content.html @@ -0,0 +1,87 @@ +<style> + body { + margin: 0; + padding: 0; + } + svg { + display: block; + max-width: 100%; + max-height: 100%; + } + text { + font-family: "BNB-TTBidisha", sans-serif; + font-weight: bold; + font-size: 2; + fill: blue; + text-anchor: middle; + } + path { + fill-rule: evenodd; + fill: #ffcc66; + fill-opacity: 0.8; + stroke: #cc6633; + stroke-opacity: 0.8; + stroke-width: 0.2; + stroke-linecap: round; + stroke-linejoin: round; + } + .details { + font-size: 1.3rem; + display: flex; + width: 100%; + padding: 0 1rem 1rem 1rem; + border-bottom: 2px solid black; + justify-content: space-around; + margin-bottom: 0.2rem; + } +</style> +<div class="details"> + <div> + DISTRICT: $district$ + </div> + <div> + BLOCK: $block$ + </div> + <div> + MOUZA: $mouza$ + </div> +</div> +<svg> + $mapContent$ +</svg> +<script> + let minx = Infinity; + let miny = Infinity; + let maxx = 0; + let maxy = 0; + const paths = document.querySelectorAll("path"); + + for (const p of paths) { + const b = p.getBBox(); + minx = b.x < minx ? b.x : minx; + miny = b.y < miny ? b.y : miny; + maxx = maxx < b.x + b.width ? b.x + b.width : maxx; + maxy = maxy < b.y + b.height ? b.y + b.height : maxy; + } + + for (const p of paths) { + const m = "M " + p.getAttribute("d").substr(2).split(",").map(cood => { + cood = cood.trim().split(" "); + return cood[0] + " " + (miny + maxy - parseFloat(cood[1])).toString(); + }).join(", "); + p.setAttribute("d", m); + } + + for (const t of document.querySelectorAll("text")) { + t.setAttribute("y", (miny + maxy - parseFloat(t.getAttribute("y"))).toString()); + } + + document.querySelector("svg") + .setAttribute( + "viewBox", + [minx, miny, maxx - minx, maxy - miny] + .map(e => e.toString()).join(" ") + ); + window.addEventListener("afterprint", window.close); + window.print(); +</script> diff --git a/src/scripts/pages/sheet-map/index.ts b/src/scripts/pages/sheet-map/index.ts new file mode 100644 index 0000000..a4e45b0 --- /dev/null +++ b/src/scripts/pages/sheet-map/index.ts @@ -0,0 +1,185 @@ +import { generateWebPage } from "@/shared/generate-web-page"; +import getDownloadMapPDFPageContent from "@/scripts/pages/sheet-map/download-map-pdf-page-content.html"; +import getMapPlotPolygonPathElement from "@/scripts/pages/sheet-map/map-plot-polygon-path-element.html"; +import getMapPlotNumberLabelTextElement from "@/scripts/pages/sheet-map/map-plot-number-label-text-element.html"; +import getPlotInformationElement from "@/scripts/pages/sheet-map/plot-information-element.html"; + +interface PlotPolygon { + plotArea: number; + plotno: string; + polygon: string; +}; + +interface PlotNumberLabel { + plotno: string; + point: string; +} + +const headerElement = document.querySelector("#headerTable > tbody > tr")!; +const plotNumberInput = document.querySelector<HTMLInputElement>("#txtPlotNo")!; +const plotInformation = document.createElement("div") as HTMLDivElement; +let plotPolygonPathElements = ""; +let plotNumberLabelTextElements = ""; + +document.body.appendChild(plotInformation); + +/** + * Creates a header toolbar button and appends it to the page header. + * The button starts hidden and is shown when data is ready. + * + * @param text - The button label text. + * @returns The created button element. + */ +const createHeaderButton = (text: string) => { + const buttonContainer = document.createElement("td"); + const button = document.createElement("button"); + button.innerHTML = text; + button.style.display = "none"; + buttonContainer.appendChild(button); + headerElement.appendChild(buttonContainer); + return button; +}; + +/** + * Displays the area and plot number for the given polygon in a floating + * info panel, or shows "0.000" / empty if no polygon is selected. + * + * @param plotPolygon - The selected plot's data, or `null`/`undefined` to clear. + */ +const setPlotInformation = (plotPolygon: PlotPolygon | null | undefined = null) => { + plotInformation.innerHTML = plotPolygon ? getPlotInformationElement({ + area: (plotPolygon.plotArea/1000).toFixed(3), + plotNumber: plotPolygon.plotno + }) : getPlotInformationElement({ + area: "0.000", + plotNumber: "" + }); +}; + +/** + * Opens a new window with a printable PDF view of the map, optionally + * including plot-number labels. + * + * @param labelPoints - Whether to include plot number text labels. + */ +const downloadPDF = (labelPoints: boolean = true) => { + /** Extracts a detail value (district/block/mouza) from the header table by column index. */ + const _getMapDetail = (i: number) => { + const detail = document.querySelector(`#headerTable > tbody > tr > td:nth-child(${i})`)! + .innerHTML + .split("[")[1] + .trim(); + return detail.substring(0, detail.length - 1); + }; + generateWebPage( + getDownloadMapPDFPageContent({ + district: _getMapDetail(1), + block: _getMapDetail(2), + mouza: _getMapDetail(3), + mapContent: plotPolygonPathElements + (labelPoints ? plotNumberLabelTextElements : "") + }), + "map" + ); +}; + +const downloadPDFButton = createHeaderButton("SAVE PDF"); +const downloadPDFNoLabelButton = createHeaderButton("SAVE PDF (NO LABEL)"); + +downloadPDFButton.addEventListener("click", e => { + e.preventDefault(); + downloadPDF(); +}); + +downloadPDFNoLabelButton.addEventListener("click", e => { + e.preventDefault(); + downloadPDF(false); +}); + +setPlotInformation(); + +(async () => { + const searchParams = new URLSearchParams(window.location.search); + const response1 = await fetch( + "/BanglarBhumi/sheetMap_populateLayerData?lstSheetNo=" + searchParams.get("lstSheetNo"), + { + method: "POST" + }); + const plotPolygonList: PlotPolygon[] = (await response1.json()).features; + const response2 = await fetch( + "/BanglarBhumi/sheetMap_populateCentroidData?lstSheetNo=" + searchParams.get("lstSheetNo"), + { + method: "POST" + }); + const plotNumberLabelList: PlotNumberLabel[] = (await response2.json()).features; + let plotPolygons: { [key: string]: PlotPolygon } = {}; + + for (const plotPolygon of plotPolygonList) { + const plotPolygonPoints = plotPolygon.polygon.split("(((")[1].split(")))")[0]; + plotPolygonPathElements += getMapPlotPolygonPathElement({ + polygonVertices: plotPolygonPoints + }); + } + + for (const plotNumberLabel of plotNumberLabelList) { + const plotNumberLabelPoint = plotNumberLabel.point.split("(")[1].split(")")[0].split(" "); + plotNumberLabelTextElements += getMapPlotNumberLabelTextElement({ + x: plotNumberLabelPoint[0], + y: plotNumberLabelPoint[1], + plotNumber: plotNumberLabel.plotno + }); + } + + downloadPDFButton.style.display = "inherit"; + downloadPDFNoLabelButton.style.display = "inherit"; + + document.querySelector("#btnSearch")!.addEventListener("click", () => { + let plotPolygon; + for (const p of plotPolygonList) { + if (p.plotno === plotNumberInput.value) { + plotPolygon = p; + break; + } + } + setPlotInformation(plotPolygon); + }); + + await new Promise<void>((resolve, _reject) => { + const plotElementIdsControl = setInterval(() => { + let plotElements = document.querySelector("#OpenLayers_Layer_Vector_25_vroot")?.children || []; + if (plotElements.length) { + clearInterval(plotElementIdsControl); + for (let i = 0; i < plotElements.length; i++) { + plotPolygons[plotElements[i].id] = plotPolygonList[i]; + } + resolve(); + } + }, 50); + }); + + setInterval(() => { + for (const plotElementId in plotPolygons) { + const e = document.getElementById(plotElementId); + if (e) { + e.removeEventListener("click", handlePlotClick); + e.addEventListener("click", handlePlotClick); + } + } + }, 300); + + /** + * Highlights the clicked plot on the SVG map and shows its + * information in the info panel. + * + * @param e - The mouse click event. + */ + const handlePlotClick = (e: MouseEvent) => { + document.querySelectorAll("path").forEach(e => { + e.setAttribute("fill", "#ffcc66"); + }); + + const target = e.target as SVGPathElement; + + target.setAttribute("fill", "#8aeeef"); + setPlotInformation(plotPolygons[target.id]); + }; +})(); diff --git a/src/scripts/pages/sheet-map/map-plot-number-label-text-element.html b/src/scripts/pages/sheet-map/map-plot-number-label-text-element.html new file mode 100644 index 0000000..d220367 --- /dev/null +++ b/src/scripts/pages/sheet-map/map-plot-number-label-text-element.html @@ -0,0 +1,3 @@ +<text x="$x$" y="$y$"> + <tspan baseline-shift="-35%" x="$x$" dy="0em">$plotNumber$</tspan> +</text> diff --git a/src/scripts/pages/sheet-map/map-plot-polygon-path-element.html b/src/scripts/pages/sheet-map/map-plot-polygon-path-element.html new file mode 100644 index 0000000..d4d38a6 --- /dev/null +++ b/src/scripts/pages/sheet-map/map-plot-polygon-path-element.html @@ -0,0 +1 @@ +<path d="M $polygonVertices$"></path> diff --git a/src/scripts/pages/sheet-map/plot-information-element.html b/src/scripts/pages/sheet-map/plot-information-element.html new file mode 100644 index 0000000..fd740a8 --- /dev/null +++ b/src/scripts/pages/sheet-map/plot-information-element.html @@ -0,0 +1,6 @@ +<div> + Plot Number: $plotNumber$ +</div> +<div> + Area: $area$ acres +</div> |
