Skip to content

Commit

Permalink
Download OK, move API download to another server
Browse files Browse the repository at this point in the history
  • Loading branch information
Alf-Anas committed Jul 27, 2023
1 parent 9f9c411 commit d8c0192
Show file tree
Hide file tree
Showing 12 changed files with 473 additions and 127 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
API_BASE_URL = https://example.com/api/batas-admin/
36 changes: 9 additions & 27 deletions component/map/MainMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import { ReactNode, useContext, useEffect, useRef, useState } from "react";
import maplibregl, { Map, StyleSpecification } from "maplibre-gl";
import "maplibre-gl/dist/maplibre-gl.css";
import classes from "./MainMap.module.css";
import { getPolygonBoundingBox, propertiesTableDiv } from "@/utils/map";
import {
getPolygonBoundingBox,
propertiesTableDiv,
wktToGeoJson,
} from "@/utils/map";
import { Spin } from "antd";
import { INITIAL_MAP, LAYER_ID, LAYER_SRC, OSM_STYLE } from "./constant";
import { MainContext } from "@/container/HomePage";
import { parse as WKTParse } from "wellknown";
import { getValObject } from "@/pages/api/utils";
import * as turf from "@turf/turf";

export default function MainMap({
Expand Down Expand Up @@ -150,26 +152,14 @@ export default function MainMap({
LAYER_SRC.ADMIN_CENTROID
);
if (adminSource) {
const listPolygon = polygons.map((item) => {
const polygon = WKTParse(getValObject(item, "WKT_GEOMETRY", ""));
const { WKT_GEOMETRY, ogc_fid, ...props } = item;
return {
type: "Feature",
properties: props,
geometry: polygon,
};
});
const geoPolygon = wktToGeoJson(polygons, selected.properties.NAMA);

const mData = {
type: "FeatureCollection",
features: listPolygon,
};
adminSource
// @ts-ignore
.setData(mData);
.setData(geoPolygon.geojson);

if (adminCentroidSource) {
const listCentroid = listPolygon.map((item) => {
const listCentroid = geoPolygon.listFeature.map((item) => {
const center = turf.centerOfMass(item.geometry);
return {
...center,
Expand All @@ -184,15 +174,7 @@ export default function MainMap({
// @ts-ignore
.setData(mDataPoint);
}
setGeojson({
type: "FeatureCollection",
name: selected.properties.NAMA,
crs: {
type: "name",
properties: { name: "urn:ogc:def:crs:OGC:1.3:CRS84" },
},
features: listPolygon,
});
setGeojson(geoPolygon.geojson);
}
}
}, [polygons]);
Expand Down
3 changes: 2 additions & 1 deletion configs/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ const API = {
name,
},
}),
getSearchId: ({ fid = "", type = "" }) =>
getSearchId: ({ fid = "", type = "", level = "" }) =>
HOST.get(`api/search/${fid}`, {
params: {
type,
level,
},
}),
};
Expand Down
153 changes: 112 additions & 41 deletions container/HomePage/DownloadButton.tsx
Original file line number Diff line number Diff line change
@@ -1,69 +1,125 @@
import { Button, Form, Modal, Radio, Space, Typography } from "antd";
import classes from "./DownloadButton.module.css";
import { useContext, useState } from "react";
import { useContext, useEffect, useState } from "react";
import { MainContext } from ".";
import { DownloadOutlined } from "@ant-design/icons";
import { downloadFile } from "@/utils";
// @ts-ignore
import shpwrite from "shp-write";
// @ts-ignore
import tokml from "tokml";
import { FEATURE_TYPE, getTypeFeature, getValObject } from "@/pages/api/utils";
import {
TYPE_DOWNLOAD,
getOneLevelDown,
saveSpatialFile,
wktToGeoJson,
} from "@/utils/map";
import useAPI from "@/hooks/useAPI";
import API from "@/configs/api";
import { ObjectLiteral } from "@/pages/api/utils/geojson.interface";

const TYPE_DOWNLOAD = {
GEOJSON: "GeoJSON",
SHP: "ShapeFile (SHP)",
KML: "Keyhole Markup Language (KML)",
};
const LIST_TYPE_DOWNLOAD = [
TYPE_DOWNLOAD.GEOJSON,
TYPE_DOWNLOAD.SHP,
TYPE_DOWNLOAD.KML,
];

const BATAS_ADMIN_LEVEL = {
PROVINSI: { ID: FEATURE_TYPE.PROV, LABEL: "Provinsi" },
KAB_KOTA: { ID: FEATURE_TYPE.KAB_KOTA, LABEL: "Kabupaten / Kota" },
KECAMATAN: { ID: FEATURE_TYPE.KECAMATAN, LABEL: "Kecamatan" },
KEL_DESA: { ID: FEATURE_TYPE.KEL_DESA, LABEL: "Kelurahan / Desa" },
};

function getListBatasAdminLevel(featureType: string) {
switch (featureType) {
case FEATURE_TYPE.PROV:
return [
BATAS_ADMIN_LEVEL.PROVINSI,
BATAS_ADMIN_LEVEL.KAB_KOTA,
BATAS_ADMIN_LEVEL.KECAMATAN,
BATAS_ADMIN_LEVEL.KEL_DESA,
];
case FEATURE_TYPE.KAB_KOTA:
return [
BATAS_ADMIN_LEVEL.KAB_KOTA,
BATAS_ADMIN_LEVEL.KECAMATAN,
BATAS_ADMIN_LEVEL.KEL_DESA,
];
case FEATURE_TYPE.KECAMATAN:
return [BATAS_ADMIN_LEVEL.KECAMATAN, BATAS_ADMIN_LEVEL.KEL_DESA];
case FEATURE_TYPE.KEL_DESA:
return [BATAS_ADMIN_LEVEL.KEL_DESA];
default:
return [];
}
}

export default function DownloadButton() {
const { geojson, selected } = useContext(MainContext);
const [openModal, setOpenModal] = useState(false);
const [isDownloading, setIsDownloading] = useState(false);
const [typeDownload, setTypeDownload] = useState(TYPE_DOWNLOAD.GEOJSON);
const [typeLevel, setTypeLevel] = useState("");
const [selectedLevel, setSelectedLevel] = useState("");
const [downloadGeojson, setDownloadGeojson] = useState<ObjectLiteral>({});
const apiData = useAPI(API.getSearchId);

function onDownloadFile() {
setIsDownloading(true);
if (typeDownload === TYPE_DOWNLOAD.GEOJSON) {
downloadFile(
JSON.stringify(geojson),
"application/json",
selected.properties.NAMA,
"geojson"
);
} else if (typeDownload === TYPE_DOWNLOAD.SHP) {
const options = {
folder: selected.properties.NAMA,
types: {
point: selected.properties.NAMA + "_PT",
polygon: selected.properties.NAMA + "_PL",
line: selected.properties.NAMA + "_LN",
},
};
const shpZip = shpwrite.zip(geojson, options);
downloadFile(
shpZip,
"data:text/plain;base64,",
selected.properties.NAMA,
"zip",
false

const eGeoJson = downloadGeojson[typeLevel];
if (getValObject(eGeoJson, "type", null)) {
saveSpatialFile(
typeDownload,
eGeoJson,
typeLevel,
selected.properties.NAMA
);
} else if (typeDownload === TYPE_DOWNLOAD.KML) {
const kml = tokml(geojson, {
name: "nama",
description: "label",
} else {
apiData.call({
fid:
selectedLevel === FEATURE_TYPE.PROV
? getValObject(selected.properties, "PROVINSI")
: getValObject(selected.properties, "KODE_KD") ||
selected.properties.FID ||
"",
level: typeLevel,
type: selectedLevel,
});
downloadFile(kml, "text/plain", selected.properties.NAMA, "kml");
}

setTimeout(() => {
setIsDownloading(false);
}, 1500);
}

useEffect(() => {
if (selected.properties) {
const mSelected = getTypeFeature(selected.properties);
setSelectedLevel(mSelected);
setTypeLevel(getOneLevelDown(mSelected));
}
}, [selected]);

useEffect(() => {
if (!geojson.type || !selectedLevel) return;
setDownloadGeojson({
[getOneLevelDown(selectedLevel)]: geojson,
});
}, [geojson, selectedLevel]);

useEffect(() => {
if (!apiData.data) return;
const eData = getValObject(apiData.data, "data", []);
const geoPolygon = wktToGeoJson(eData, selected.properties.NAMA);
setDownloadGeojson((oldState) => {
return { ...oldState, [typeLevel]: geoPolygon.geojson };
});
saveSpatialFile(
typeDownload,
geoPolygon.geojson,
typeLevel,
selected.properties.NAMA
);
}, [apiData.data]);

return (
<>
<Form.Item className={classes.custom_download_box}>
Expand All @@ -83,9 +139,24 @@ export default function DownloadButton() {
onOk={onDownloadFile}
onCancel={() => setOpenModal(false)}
okText="Download"
confirmLoading={isDownloading}
confirmLoading={isDownloading || apiData.loading}
>
<Typography.Title level={5}>File Type : </Typography.Title>
<Typography.Title level={5}>Level Batas Adminitrasi :</Typography.Title>
<Radio.Group
onChange={(e) => setTypeLevel(e.target.value)}
value={typeLevel}
>
<Space direction="vertical">
{getListBatasAdminLevel(selectedLevel).map((item, idx) => {
return (
<Radio key={idx} value={item.ID}>
{item.LABEL}
</Radio>
);
})}
</Space>
</Radio.Group>
<Typography.Title level={5}>File Type :</Typography.Title>
<Radio.Group
onChange={(e) => setTypeDownload(e.target.value)}
value={typeDownload}
Expand Down
6 changes: 3 additions & 3 deletions container/HomePage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import {
} from "@/pages/api/utils/geojson.interface";
import useAPI from "@/hooks/useAPI";
import API from "@/configs/api";
import { getValObject } from "@/pages/api/utils";
import { FEATURE_TYPE, getTypeFeature } from "@/utils/map";
import { FEATURE_TYPE, getTypeFeature, getValObject } from "@/pages/api/utils";
import DownloadButton from "./DownloadButton";
import { getOneLevelDown } from "@/utils/map";

export type MainContextType = {
selected: Feature;
Expand Down Expand Up @@ -46,14 +46,14 @@ export default function HomePage() {
: getValObject(selected.properties, "KODE_KD") ||
selected.properties.FID ||
"",
level: getOneLevelDown(typeFeature),
type: typeFeature,
});
}, [selected]);

useEffect(() => {
if (!apiData.data) return;
setPolygons(getValObject(apiData.data, "data", []));
const size = new TextEncoder().encode(JSON.stringify(apiData.data)).length;
}, [apiData.data]);

return (
Expand Down
4 changes: 2 additions & 2 deletions next.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
}
};

module.exports = nextConfig
module.exports = nextConfig;
Loading

0 comments on commit d8c0192

Please sign in to comment.