aboutsummaryrefslogtreecommitdiffstats
path: root/src/scripts/pages/sheet-map
diff options
context:
space:
mode:
Diffstat (limited to 'src/scripts/pages/sheet-map')
-rw-r--r--src/scripts/pages/sheet-map/download-map-pdf-page-content.html87
-rw-r--r--src/scripts/pages/sheet-map/index.ts185
-rw-r--r--src/scripts/pages/sheet-map/map-plot-number-label-text-element.html3
-rw-r--r--src/scripts/pages/sheet-map/map-plot-polygon-path-element.html1
-rw-r--r--src/scripts/pages/sheet-map/plot-information-element.html6
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>