Move initi18n. Update search component

This commit is contained in:
Fuhrmann 2023-09-29 13:18:55 +02:00
parent c8046c39f1
commit a810f87461
7 changed files with 124 additions and 114 deletions

View File

@ -1,7 +1,6 @@
import { useRef, useEffect, RefObject } from 'react';
import { useRef, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import initI18n from './i18n';
import MapView from '@arcgis/core/views/MapView';
import Basemap from '@arcgis/core/Basemap';
@ -13,13 +12,6 @@ import TileLayer from '@arcgis/core/layers/TileLayer';
const BEVURL = 'https://maps.bev.gv.at/tiles/{z}/{x}/{y}.png';
// load localized strings
const match = location.pathname.match(/\/(\w+)/);
if (match && match.length > 1) {
const locale = match[1];
initI18n(locale);
}
export default function Basemaps({ view }: { view: MapView }) {
const basemapGalleryContainer = useRef<HTMLDivElement | null>(null);
const rendered = useRef<boolean>(false);

View File

@ -4,7 +4,7 @@ import { initReactI18next } from 'react-i18next';
import deJSON from './dictionaries/de.json';
import enJSON from './dictionaries/en.json';
// the translations
// define translations
const resources = {
en: {
translation: enJSON,
@ -14,15 +14,14 @@ const resources = {
},
};
// initialize i18n with given locale
const initI18n = (locale) =>
i18n
.use(initReactI18next) // passes i18n down to react-i18next
.init({
resources,
lng: locale,
interpolation: {
escapeValue: false, // react already safes from xss
},
});
i18n.use(initReactI18next).init({
resources,
lng: locale,
interpolation: {
escapeValue: false,
},
});
export default initI18n;

View File

@ -1,7 +1,6 @@
import { useRef, useEffect, RefObject } from 'react';
import { useRef, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import initI18n from './i18n';
import MapView from '@arcgis/core/views/MapView';
import LayerList from '@arcgis/core/widgets/LayerList';
@ -11,14 +10,7 @@ import MapImageLayer from '@arcgis/core/layers/MapImageLayer';
import Sublayer from '@arcgis/core/layers/support/Sublayer';
import ButtonMenuItem from '@arcgis/core/widgets/FeatureTable/Grid/support/ButtonMenuItem';
// load localized strings
const match = location.pathname.match(/\/(\w+)/);
if (match && match.length > 1) {
const locale = match[1];
initI18n(locale);
}
export default function Layers({ view, tableRoot }: { view: MapView; tableRoot: RefObject<HTMLDivElement> }) {
export default function Layers({ view, tableRoot }: { view: MapView; tableRoot: HTMLDivElement }) {
const htmlDiv = useRef<HTMLDivElement>(null);
const featureTable = useRef<FeatureTable | null>(null);
const rendered = useRef<boolean>(false);
@ -33,9 +25,9 @@ export default function Layers({ view, tableRoot }: { view: MapView; tableRoot:
const tableContainer = document.createElement('div');
tableContainer.className = 'h-full w-full';
if (tableRoot && tableRoot.current) {
tableRoot.current.classList.remove('hidden');
tableRoot.current.append(tableContainer);
if (tableRoot) {
tableRoot.classList.remove('hidden');
tableRoot.append(tableContainer);
}
const featureLayer = await layer.createFeatureLayer();
@ -51,8 +43,8 @@ export default function Layers({ view, tableRoot }: { view: MapView; tableRoot:
iconClass: 'esri-icon-close',
clickFunction: function () {
featureTable.current?.destroy();
if (tableRoot && tableRoot.current) {
tableRoot.current.classList.add('hidden');
if (tableRoot) {
tableRoot.classList.add('hidden');
}
},
} as unknown as ButtonMenuItem,

View File

@ -1,15 +1,15 @@
import { useRef, useState, useEffect, lazy } from 'react';
import { Root, createRoot } from 'react-dom/client';
import { useRef, useState, useEffect } from 'react';
import { createRoot } from 'react-dom/client';
import dynamic from 'next/dynamic';
import { useTranslation } from 'react-i18next';
import initI18n from './i18n';
import MapView from '@arcgis/core/views/MapView';
import WebMap from '@arcgis/core/WebMap';
import esriConfig from '@arcgis/core/config';
import ScaleBar from '@arcgis/core/widgets/ScaleBar';
import Legend from '@arcgis/core/widgets/Legend';
import WMTSLayer from '@arcgis/core/layers/WMTSLayer';
import VectorTileLayer from '@arcgis/core/layers/VectorTileLayer';
import TileLayer from '@arcgis/core/layers/TileLayer';
import Map from '@arcgis/core/Map.js';
@ -23,11 +23,11 @@ esriConfig.assetsPath = './assets';
const webMapDEID = '7d0768f73d3e4be2b32c22274c600cb3';
const webMapENID = 'dbf5532d06954c6a989d4f022de83f70';
// lazy load print component
const Print = lazy(() => import('./print'));
const Layers = lazy(() => import('./layer-list'));
const Basemaps = lazy(() => import('./basemap-list'));
const Search = lazy(() => import('./search'));
// lazy load components
const Print = dynamic(() => import('./print'));
const Layers = dynamic(() => import('./layer-list'));
const Basemaps = dynamic(() => import('./basemap-list'));
const Search = dynamic(() => import('./search'));
// import Calcite components
import '@esri/calcite-components/dist/calcite/calcite.css';
@ -49,15 +49,8 @@ import {
CalcitePanel,
} from '@esri/calcite-components-react';
// load localized strings
const match = location.pathname.match(/\/(\w+)/);
if (match && match.length > 1) {
const locale = match[1];
initI18n(locale);
}
export default function MapComponent({ locale }: { locale: string }) {
const printRoot = useRef<Root | null>(null);
const legendRoot = useRef<HTMLDivElement>(null);
const maskRoot = useRef<HTMLDivElement>(null);
const tableRoot = useRef<HTMLDivElement>(null);
const mapView = useRef<MapView | null>(null);
@ -81,14 +74,6 @@ export default function MapComponent({ locale }: { locale: string }) {
},
});
// const wmtsLayer = new WMTSLayer({
// url: 'https://mapsneu.wien.gv.at/basemapneu',
// });
// const basemap = new Basemap({
// baseLayers: [wmtsLayer],
// });
const lightgrayBase = new VectorTileLayer({
url: 'https://gis.geosphere.at/portal/sharing/rest/content/items/291da5eab3a0412593b66d384379f89f/resources/styles/root.json',
opacity: 0.5,
@ -124,6 +109,7 @@ export default function MapComponent({ locale }: { locale: string }) {
width: 5000,
},
},
dockEnabled: true,
},
extent: {
ymax: 6424330,
@ -144,6 +130,7 @@ export default function MapComponent({ locale }: { locale: string }) {
createRoot(document.createElement('div')).render(<Search view={view}></Search>);
});
// add further map related UI components
const scaleBar = new ScaleBar({
view: view,
unit: 'metric',
@ -151,10 +138,12 @@ export default function MapComponent({ locale }: { locale: string }) {
view.ui.add([scaleBar], 'bottom-left');
new Legend({
view: view,
container: 'legend-container',
});
if (legendRoot.current) {
new Legend({
view: view,
container: legendRoot.current,
});
}
}
return () => {};
@ -211,7 +200,6 @@ export default function MapComponent({ locale }: { locale: string }) {
return (
<div>
<CalciteShell contentBehind>
<h2 id="header-title" slot="header"></h2>
<CalciteShellPanel slot="panel-start" displayMode="float">
<CalciteActionBar
slot="action-bar"
@ -246,7 +234,9 @@ export default function MapComponent({ locale }: { locale: string }) {
</CalciteActionBar>
<CalcitePanel data-panel-id="layers" heading={t('layers.title')} hidden>
{mapView.current && <Layers view={mapView.current} tableRoot={tableRoot}></Layers>}
{mapView.current && tableRoot.current && (
<Layers view={mapView.current} tableRoot={tableRoot.current}></Layers>
)}
</CalcitePanel>
<CalcitePanel data-panel-id="basemaps" heading={t('basemaps.title')} hidden>
@ -254,11 +244,11 @@ export default function MapComponent({ locale }: { locale: string }) {
</CalcitePanel>
<CalcitePanel data-panel-id="legend" heading={t('legend.title')} hidden>
<div id="legend-container"></div>
<div ref={legendRoot}></div>
</CalcitePanel>
<CalcitePanel data-panel-id="print" heading={t('print.heading')} hidden>
{mapView.current && <Print view={mapView.current} maskRoot={maskRoot}></Print>}
{mapView.current && maskRoot.current && <Print view={mapView.current} maskRoot={maskRoot.current}></Print>}
</CalcitePanel>
<CalcitePanel data-panel-id="info" heading="Info" hidden>

View File

@ -1,9 +1,11 @@
'use client';
import dynamic from 'next/dynamic';
import initI18n from './i18n';
const Map = dynamic(() => import('./map'), { ssr: false });
export default function Home({ params: { locale } }: { params: { locale: string } }) {
initI18n(locale);
return <Map locale={locale}></Map>;
}

View File

@ -1,7 +1,6 @@
import { useRef, useState, useEffect, RefObject } from 'react';
import { useRef, useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import initI18n from './i18n';
import MapView from '@arcgis/core/views/MapView';
import esriConfig from '@arcgis/core/config.js';
@ -64,14 +63,9 @@ const formats: Format = {
'A3 Querformat mit Legende': [400, 215],
};
// load localized strings
const match = location.pathname.match(/\/(\w+)/);
if (match && match.length > 1) {
const locale = match[1];
initI18n(locale);
}
export default function Print({ view, maskRoot }: { view: MapView; maskRoot: HTMLDivElement }) {
const { t } = useTranslation();
export default function Print({ view, maskRoot }: { view: MapView; maskRoot: RefObject<HTMLDivElement> }) {
const [title, setTitle] = useState<string>('GeoSphere Austria');
const [format, setFormat] = useState<string>(Object.keys(formats)[0]);
const [scale, setScale] = useState<number>(scales[0]);
@ -79,8 +73,6 @@ export default function Print({ view, maskRoot }: { view: MapView; maskRoot: Ref
const rendered = useRef<boolean>(false);
const { t } = useTranslation();
const currentScale = useRef<number>();
currentScale.current = scale;
@ -191,11 +183,11 @@ export default function Print({ view, maskRoot }: { view: MapView; maskRoot: Ref
const maskWidth = clamp(Math.round(lowerRight.x - upperLeft.x), 0, view.width);
const maskHeight = clamp(Math.round(lowerRight.y - upperLeft.y), 0, view.height);
if (maskRoot && maskRoot.current) {
maskRoot.current.style.left = left + 'px';
maskRoot.current.style.top = top + 'px';
maskRoot.current.style.width = maskWidth + 'px';
maskRoot.current.style.height = maskHeight + 'px';
if (maskRoot) {
maskRoot.style.left = left + 'px';
maskRoot.style.top = top + 'px';
maskRoot.style.width = maskWidth + 'px';
maskRoot.style.height = maskHeight + 'px';
}
}
};

View File

@ -2,7 +2,6 @@ import { useRef, useState, useEffect } from 'react';
import { Root, createRoot } from 'react-dom/client';
import { useTranslation } from 'react-i18next';
import initI18n from './i18n';
// import Calcite components
import '@esri/calcite-components/dist/calcite/calcite.css';
@ -37,13 +36,19 @@ import Polygon from '@arcgis/core/geometry/Polygon';
import { geodesicBuffer } from '@arcgis/core/geometry/geometryEngine';
import MapImageLayer from '@arcgis/core/layers/MapImageLayer';
import SimpleFillSymbol from '@arcgis/core/symbols/SimpleFillSymbol';
import SimpleLineSymbol from '@arcgis/core/symbols/SimpleLineSymbol';
import SimpleMarkerSymbol from '@arcgis/core/symbols/SimpleMarkerSymbol';
import Sublayer from '@arcgis/core/layers/support/Sublayer';
import PopupTemplate from '@arcgis/core/PopupTemplate';
// create feaure layer from URL of data index layer
const datenIndexURL = 'https://gis.geosphere.at/maps/rest/services/datenindex/raster_5000/MapServer/0';
const indexLayer = new FeatureLayer({ url: datenIndexURL, title: 'Datenindex 1:5.000', opacity: 0 });
const indexLayer = new FeatureLayer({
url: datenIndexURL,
title: 'Datenindex 1:5.000',
opacity: 0,
legendEnabled: false,
});
// custom type definitions
interface CustomLayer {
@ -65,13 +70,6 @@ interface LayerToFeaturesMap {
[key: string]: string[];
}
// load localized strings
const match = location.pathname.match(/\/(\w+)/);
if (match && match.length > 1) {
const locale = match[1];
initI18n(locale);
}
// custom React component
export default function SearchComponent({ view }: { view: MapView }) {
const [currentTarget, setCurrentTarget] = useState<Graphic | null>(null);
@ -140,34 +138,78 @@ export default function SearchComponent({ view }: { view: MapView }) {
const sr = mapImageLayer?.spatialReference;
const geometry = json.feature?.geometry;
if (geometry.x && geometry.y) {
view.goTo(
new Point({
x: geometry.x,
y: geometry.y,
spatialReference: sr,
})
);
view.graphics.removeAll();
const higlightOptions = view.highlightOptions;
if (geometry.x && geometry.y && higlightOptions && higlightOptions.color && higlightOptions.fillOpacity) {
const point = new Point({
x: geometry.x,
y: geometry.y,
spatialReference: sr,
});
const graphic = new Graphic({
geometry: point,
symbol: {
type: 'simple-marker',
style: 'circle',
size: '8px',
color: [
higlightOptions.color.r,
higlightOptions.color.g,
higlightOptions.color.b,
higlightOptions.fillOpacity,
],
outline: {
color: [higlightOptions.color.r, higlightOptions.color.g, higlightOptions.color.b, higlightOptions.color.a],
width: 1,
},
} as unknown as SimpleMarkerSymbol,
});
view.graphics.add(graphic);
view.goTo(geodesicBuffer(point, 1000, 'meters'));
return;
}
if (geometry.paths) {
view.goTo(
new Polyline({
paths: geometry.paths,
spatialReference: sr,
})
);
if (geometry.paths && higlightOptions && higlightOptions.color && higlightOptions.fillOpacity) {
const polyline = new Polyline({
paths: geometry.paths,
spatialReference: sr,
});
const graphic = new Graphic({
geometry: polyline,
symbol: {
type: 'simple-line',
color: [higlightOptions.color.r, higlightOptions.color.g, higlightOptions.color.b],
width: '2px',
} as unknown as SimpleLineSymbol,
});
view.graphics.add(graphic);
view.goTo(geodesicBuffer(polyline.extent.center, 5000, 'meters'));
return;
}
if (geometry.rings) {
view.goTo(
new Polygon({
rings: geometry.rings,
spatialReference: sr,
})
);
if (geometry.rings && higlightOptions && higlightOptions.color && higlightOptions.fillOpacity) {
const polygon = new Polygon({
rings: geometry.rings,
spatialReference: sr,
});
const graphic = new Graphic({
geometry: polygon,
symbol: {
type: 'simple-fill',
color: [
higlightOptions.color.r,
higlightOptions.color.g,
higlightOptions.color.b,
higlightOptions.fillOpacity,
],
outline: {
color: [higlightOptions.color.r, higlightOptions.color.g, higlightOptions.color.b, higlightOptions.color.a],
width: 1,
},
} as unknown as SimpleFillSymbol,
});
view.graphics.add(graphic);
view.goTo(polygon);
return;
}
};
@ -587,6 +629,7 @@ export default function SearchComponent({ view }: { view: MapView }) {
} else {
location = currentGraphicRef.current?.geometry;
}
view.openPopup({
title: t('search.popup-title'),
content: contentDiv,