mirror of
https://github.com/mickael-kerjean/filestash
synced 2026-01-02 13:57:00 +01:00
feature (shp): native shp handling
This commit is contained in:
parent
c1aead5916
commit
866cda05c3
5 changed files with 2803 additions and 32 deletions
|
|
@ -7,6 +7,8 @@ export function isSDK() {
|
|||
}
|
||||
|
||||
export function urlSDK(url) {
|
||||
if (url.startsWith("blob:")) return url;
|
||||
|
||||
const importURL = new URL(import.meta.url);
|
||||
if (new RegExp("^/").test(url) === false) {
|
||||
url = "/" + url;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { isSDK, urlSDK } from "../helpers/sdk.js";
|
|||
export default function(opts) {
|
||||
if (typeof opts === "string") opts = { url: opts, withCredentials: true };
|
||||
else if (typeof opts !== "object") throw new Error("unsupported call");
|
||||
|
||||
if (!opts.headers) opts.headers = {};
|
||||
opts.headers["X-Requested-With"] = "XmlHttpRequest";
|
||||
if (window.BEARER_TOKEN) opts.headers["Authorization"] = `Bearer ${window.BEARER_TOKEN}`;
|
||||
|
|
@ -14,13 +15,17 @@ export default function(opts) {
|
|||
opts.url = urlSDK(opts.url);
|
||||
}
|
||||
|
||||
return ajax({ withCredentials: true, ...opts, responseType: "text" }).pipe(
|
||||
const responseType = opts.responseType === "json" ? "text" : opts.responseType;
|
||||
return ajax({
|
||||
withCredentials: true,
|
||||
...opts,
|
||||
responseType,
|
||||
}).pipe(
|
||||
rxjs.map((res) => {
|
||||
const result = res.xhr.responseText;
|
||||
if (opts.responseType === "json") {
|
||||
const json = JSON.parse(result);
|
||||
res.responseJSON = json;
|
||||
if (json.status !== "ok") {
|
||||
const result = res.xhr.responseText;
|
||||
res.responseJSON = JSON.parse(result);
|
||||
if (res.responseJSON.status !== "ok") {
|
||||
throw new AjaxError("Oups something went wrong", result);
|
||||
}
|
||||
}
|
||||
|
|
@ -31,6 +36,14 @@ export default function(opts) {
|
|||
}
|
||||
|
||||
function processError(xhr, err) {
|
||||
let responseText = "";
|
||||
try {
|
||||
responseText = xhr?.responseText;
|
||||
} catch (err) {
|
||||
if (err.name === "InvalidStateError") {} // InvalidStateError: Failed to read the 'responseText' property from 'XMLHttpRequest': The value is only accessible if the object's 'responseType' is '' or 'text' (was 'arraybuffer').
|
||||
else throw err;
|
||||
}
|
||||
|
||||
const response = (function(content) {
|
||||
let message = content;
|
||||
try {
|
||||
|
|
@ -46,10 +59,9 @@ function processError(xhr, err) {
|
|||
};
|
||||
}
|
||||
return message || { message: "empty response" };
|
||||
})(xhr?.responseText || "");
|
||||
})(responseText);
|
||||
|
||||
const message = response.message || null;
|
||||
|
||||
if (window.navigator.onLine === false) {
|
||||
return new AjaxError("Connection Lost", err, "NO_INTERNET");
|
||||
}
|
||||
|
|
@ -85,14 +97,14 @@ function processError(xhr, err) {
|
|||
err, "CONFLICT"
|
||||
);
|
||||
case 0:
|
||||
switch (xhr?.responseText) {
|
||||
switch (responseText) {
|
||||
case "":
|
||||
return new AjaxError(
|
||||
"Service unavailable, if the problem persist, contact your administrator",
|
||||
err, "INTERNAL_SERVER_ERROR"
|
||||
);
|
||||
default:
|
||||
return new AjaxError(xhr.responseText, err, "INTERNAL_SERVER_ERROR");
|
||||
return new AjaxError(responseText, err, "INTERNAL_SERVER_ERROR");
|
||||
}
|
||||
default:
|
||||
return new AjaxError(message || "Oups something went wrong", err);
|
||||
|
|
|
|||
2742
public/assets/lib/vendor/shp-to-geojson.browser.js
vendored
Normal file
2742
public/assets/lib/vendor/shp-to-geojson.browser.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,12 +1,13 @@
|
|||
import { createElement } from "../../lib/skeleton/index.js";
|
||||
import rxjs from "../../lib/rx.js";
|
||||
import { createElement, nop } from "../../lib/skeleton/index.js";
|
||||
import rxjs, { effect } from "../../lib/rx.js";
|
||||
import { qs } from "../../lib/dom.js";
|
||||
import { extname } from "../../lib/path.js";
|
||||
import ajax from "../../lib/ajax.js";
|
||||
import { loadCSS, loadJS } from "../../helpers/loader.js";
|
||||
import { getFilename, getDownloadUrl } from "./common.js";
|
||||
import { createLoader } from "../../components/loader.js";
|
||||
|
||||
import { renderMenubar, buttonDownload } from "./component_menubar.js";
|
||||
import { cat } from "./model_files.js";
|
||||
import ctrlError from "../ctrl_error.js";
|
||||
|
||||
const DEFAULT_TILE_SERVER = "https://tile.openstreetmap.org/{z}/{x}/{y}.png"; // "https://cartodb-basemaps-a.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png",
|
||||
|
||||
|
|
@ -15,10 +16,10 @@ const PLUGINS = [
|
|||
// ... add more plugins via frontend override
|
||||
];
|
||||
|
||||
export default async function(render) {
|
||||
export default async function(render, { mime, getDownloadUrl = nop, getFilename = nop }) {
|
||||
const $page = createElement(`
|
||||
<div class="component_map">
|
||||
<component-menubar></component-menubar>
|
||||
<component-menubar filename="${getFilename() || ""}"></component-menubar>
|
||||
<div id="map"></div>
|
||||
</div>
|
||||
`);
|
||||
|
|
@ -29,20 +30,18 @@ export default async function(render) {
|
|||
);
|
||||
|
||||
const map = window.L.map("map");
|
||||
|
||||
const fileview = [getFilename()];
|
||||
for (let i=0; i<fileview.length; i++) {
|
||||
await cat(fileview[i]).pipe(rxjs.mergeMap(async(content) => {
|
||||
switch (extname(fileview[i])) {
|
||||
case "geojson":
|
||||
return loadGeoJSON(map, content);
|
||||
case "wms":
|
||||
return loadWMS(map, content);
|
||||
default:
|
||||
throw new Error("Not Supported");
|
||||
}
|
||||
})).toPromise();
|
||||
}
|
||||
const removeLoader = createLoader(qs($page, "#map"));
|
||||
await effect(ajax({ url: getDownloadUrl(), responseType: "arraybuffer" }).pipe(
|
||||
rxjs.map(({ response }) => response),
|
||||
rxjs.mergeMap(async(data) => { switch(mime) {
|
||||
case "application/geo+json": return loadGeoJSON(map, JSON.parse(new TextDecoder().decode(data)));
|
||||
case "application/vnd.ogc.wms_xml": return loadWMS(map, new TextDecoder().decode(data));
|
||||
case "application/vnd.shp": return await loadSHP(map, data);
|
||||
default: throw new Error(`Insupported mime type: '${mime}'`);
|
||||
}}),
|
||||
removeLoader,
|
||||
rxjs.catchError(ctrlError()),
|
||||
));
|
||||
|
||||
for (let i=0; i<PLUGINS.length; i++) {
|
||||
await import(`./application_map/${PLUGINS[i]}.js`)
|
||||
|
|
@ -50,11 +49,17 @@ export default async function(render) {
|
|||
}
|
||||
}
|
||||
|
||||
export async function init() {
|
||||
export async function init($root) {
|
||||
const priors = ($root && [
|
||||
$root.classList.add("component_page_viewerpage"),
|
||||
loadCSS(import.meta.url, "./component_menubar.css"),
|
||||
loadCSS(import.meta.url, "../ctrl_viewerpage.css"),
|
||||
]);
|
||||
await Promise.all([
|
||||
loadJS(import.meta.url, "../../lib/vendor/leaflet/leaflet.js"),
|
||||
loadCSS(import.meta.url, "../../lib/vendor/leaflet/leaflet.css"),
|
||||
loadCSS(import.meta.url, "./application_map.css"),
|
||||
...priors,
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -63,7 +68,7 @@ function loadGeoJSON(map, content) {
|
|||
|
||||
const overlay = { global: window.L.layerGroup([]) };
|
||||
let n = 0;
|
||||
const geojson = window.L.geoJSON(JSON.parse(content), {
|
||||
const geojson = window.L.geoJSON(content, {
|
||||
onEachFeature: (feature, shape) => {
|
||||
n += 1;
|
||||
if (n > 10000) return;
|
||||
|
|
@ -129,3 +134,13 @@ function loadWMS(map, content) {
|
|||
window.L.tileLayer.wms(svcURL, { layers: _layer }).addTo(map);
|
||||
window.L.control.layers(baseLayers, {}).addTo(map);
|
||||
}
|
||||
|
||||
async function loadSHP(map, content) {
|
||||
const module = await import("../../lib/vendor/shp-to-geojson.browser.js");
|
||||
const shp = new module.default({});
|
||||
shp._shpBuffer = module.Buffer.from(content);
|
||||
shp._tableBuffer = module.Buffer.from(new ArrayBuffer(16));
|
||||
shp._init();
|
||||
await shp.load();
|
||||
loadGeoJSON(map, shp.getGeoJson());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ export function opener(file = "", mimes) {
|
|||
return ["audio", { mime }];
|
||||
} else if (mime === "application/x-form") {
|
||||
return ["form", { mime }];
|
||||
} else if (mime === "application/geo+json" || mime === "application/vnd.ogc.wms_xml") {
|
||||
} else if (mime === "application/geo+json" || mime === "application/vnd.ogc.wms_xml" || mime === "application/vnd.shp") {
|
||||
return ["map", { mime }];
|
||||
} else if (type === "video" || mime === "application/ogg") {
|
||||
return ["video", { mime }];
|
||||
|
|
|
|||
Loading…
Reference in a new issue