diff --git a/CHANGELOG.md b/CHANGELOG.md index c5418620c..ea3847d48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,6 @@ ## [Unreleased] -### Added - -- WMTS Services are now supported as custom user layers. - ### Changed - Updated the style of bulk edit form. diff --git a/src/client/cypress/e2e/settings/mapSettings.cy.js b/src/client/cypress/e2e/settings/mapSettings.cy.js deleted file mode 100644 index 528c4ff19..000000000 --- a/src/client/cypress/e2e/settings/mapSettings.cy.js +++ /dev/null @@ -1,51 +0,0 @@ -import { goToRouteAndAcceptTerms } from "../helpers/testHelpers.js"; - -describe("map settings", () => { - it("Adds wms and wmts to user maps", () => { - goToRouteAndAcceptTerms("/setting"); - - const wmsName = "Army logistics centres (ALC)"; - const wmtsName = "Wetness potential agricultural land"; - - cy.contains("Map").click(); - // Add WMS - cy.get('[data-cy="load-layers-button"]').click(); - cy.get('[data-cy="wms-list-box"]').contains(wmsName); - cy.get('[data-cy="maps-for-user-box"]').should("not.exist"); - cy.get('[data-cy="add-layer-button"]').eq(1).click(); - cy.wait("@setting"); - cy.get('[data-cy="maps-for-user-box"]').contains(wmsName); - - // Select WMTS from Dropdown - cy.get('[role="combobox"]').click(); - cy.get('div[role="option"]').last().click(); - - // Add WMTS - cy.get('[data-cy="load-layers-button"]').click(); - cy.get('[data-cy="wmts-list-box"]').contains(wmtsName); - cy.get('[data-cy="add-layer-button"]').first().click(); - cy.wait("@setting"); - cy.get('[data-cy="maps-for-user-box"]').contains(wmtsName); - - // Verify layers are added to overview map - cy.contains("h3", "Done").click(); - cy.get('[data-cy="layers-button"]').click(); - cy.contains(wmsName); - cy.contains(wmtsName); - - // Remove layers - cy.get('[data-cy="settings-button"]').click(); - cy.contains("Map").click(); - cy.get('[data-cy="maps-for-user-box"]').contains(wmtsName); - cy.get('[data-cy="maps-for-user-box"]').contains(wmsName); - cy.get('[data-cy="delete-user-map-button"]').eq(0).click(); - cy.wait("@setting"); - cy.wait("@setting"); - cy.wait("@setting"); //¯\_(ツ)_/¯ - - cy.get('[data-cy="maps-for-user-box"]').should("not.contain", wmsName); - - cy.get('[data-cy="delete-user-map-button"]').eq(0).click(); - cy.get('[data-cy="maps-for-user-box"]').should("not.exist"); - }); -}); diff --git a/src/client/package-lock.json b/src/client/package-lock.json index c844a05cd..1efe7489e 100644 --- a/src/client/package-lock.json +++ b/src/client/package-lock.json @@ -16,7 +16,6 @@ "@mui/system": "^5.16.5", "@mui/x-data-grid": "^7.11.1", "@react-hook/resize-observer": "^1.2.6", - "@types/proj4": "^2.5.5", "axios": "^1.7.1", "d3": "^7.9.0", "date-fns": "^2.30.0", @@ -2400,11 +2399,6 @@ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" }, - "node_modules/@types/proj4": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/@types/proj4/-/proj4-2.5.5.tgz", - "integrity": "sha512-y4tHUVVoMEOm2nxRLQ2/ET8upj/pBmoutGxFw2LZJTQWPgWXI+cbxVEUFFmIzr/bpFR83hGDOTSXX6HBeObvZA==" - }, "node_modules/@types/prop-types": { "version": "15.7.12", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", diff --git a/src/client/package.json b/src/client/package.json index a250d80d0..51be17141 100644 --- a/src/client/package.json +++ b/src/client/package.json @@ -31,7 +31,6 @@ "@mui/system": "^5.16.5", "@mui/x-data-grid": "^7.11.1", "@react-hook/resize-observer": "^1.2.6", - "@types/proj4": "^2.5.5", "axios": "^1.7.1", "d3": "^7.9.0", "date-fns": "^2.30.0", diff --git a/src/client/public/locale/de/common.json b/src/client/public/locale/de/common.json index 7d45c2e7c..f11b5f1b5 100644 --- a/src/client/public/locale/de/common.json +++ b/src/client/public/locale/de/common.json @@ -337,8 +337,6 @@ "nothingToShow": "Nichts zu zeigen", "np": "Keine Angabe", "oneSelected": "Ein Bohrung ausgewählt", - "onlyEPSG2056Supported": "Nur EPSG:2056 wird unterstützt.", - "onlyWmsAndWmtsSupported": "Nur Web Map Services (WMS) und Web Map Tile Services (WMTS) werden unterstützt.", "openBorehole": "offenes Bohrloch", "order": "Reihenfolge", "organic_component": "Organische Komponenten", diff --git a/src/client/public/locale/en/common.json b/src/client/public/locale/en/common.json index c26f507c0..ad5a683ef 100644 --- a/src/client/public/locale/en/common.json +++ b/src/client/public/locale/en/common.json @@ -337,8 +337,6 @@ "nothingToShow": "Nothing to display", "np": "Not specified", "oneSelected": "One borehole selected", - "onlyEPSG2056Supported": "Only EPSG:2056 is supported", - "onlyWmsAndWmtsSupported": "Sono supportati solo i servizi WMS (Web Map Services) e WMTS (Web Map Tile Services).", "openBorehole": "open hole", "order": "Order", "organic_component": "Organic components", diff --git a/src/client/public/locale/fr/common.json b/src/client/public/locale/fr/common.json index 8e756b1cd..a63eaece9 100644 --- a/src/client/public/locale/fr/common.json +++ b/src/client/public/locale/fr/common.json @@ -337,8 +337,6 @@ "nothingToShow": "Rien à montrer", "np": "Sans indication", "oneSelected": "Un forage sélectionné", - "onlyEPSG2056Supported": "Seulement le système de coordonnées EPSG:2056 est pris en charge.", - "onlyWmsAndWmtsSupported": "Seulement Web Map Services (WMS) et Web Map Tile Services (WMTS) sont pris en charge.", "openBorehole": "forage ouvert", "order": "Ordre", "organic_component": "Composants organiques", diff --git a/src/client/public/locale/it/common.json b/src/client/public/locale/it/common.json index b74291f3b..e9db2f249 100644 --- a/src/client/public/locale/it/common.json +++ b/src/client/public/locale/it/common.json @@ -337,8 +337,6 @@ "nothingToShow": "Niente da mostrare", "np": "Senza indicazioni", "oneSelected": "Una perforazione selezionata", - "onlyEPSG2056Supported": "È supportato solo EPSG:2056.", - "onlyWmsAndWmtsSupported": "Seulement Web Map Services (WMS) et Web Map Tile Services (WMTS) sont pris en charge.", "openBorehole": "perforazione aperta", "order": "Ordine", "organic_component": "Componenti organici", diff --git a/src/client/src/api-lib/ReduxStateInterfaces.ts b/src/client/src/api-lib/ReduxStateInterfaces.ts index 483eb4a9c..ba939e848 100644 --- a/src/client/src/api-lib/ReduxStateInterfaces.ts +++ b/src/client/src/api-lib/ReduxStateInterfaces.ts @@ -14,7 +14,6 @@ export interface Setting { } export interface SettingData { - efilter: string; map: { explorer: string; }; diff --git a/src/client/src/api-lib/actions/settings.js b/src/client/src/api-lib/actions/settings.js index d581cf501..bdf5fd0f5 100644 --- a/src/client/src/api-lib/actions/settings.js +++ b/src/client/src/api-lib/actions/settings.js @@ -12,7 +12,7 @@ export function patchSettings(tree, value, key = null) { tree: tree, value: value, }; - if (key) { + if (key !== null) { payload.key = key; } return fetch("/setting", payload); diff --git a/src/client/src/components/map/mapComponent.jsx b/src/client/src/components/map/mapComponent.jsx index 0594df739..41abd03d6 100644 --- a/src/client/src/components/map/mapComponent.jsx +++ b/src/client/src/components/map/mapComponent.jsx @@ -18,6 +18,7 @@ import { Cluster } from "ol/source"; import TileWMS from "ol/source/TileWMS"; import VectorSource from "ol/source/Vector"; import WMTS from "ol/source/WMTS"; +import WMTSTileGrid from "ol/tilegrid/WMTS"; import proj4 from "proj4"; import PropTypes from "prop-types"; import { getGeojson } from "../../api-lib"; @@ -222,6 +223,8 @@ class MapComponent extends React.Component { opacity: 1, source: new WMTS({ ...layer.conf, + projection: getProjection(layer.conf.projection), + tileGrid: new WMTSTileGrid(layer.conf.tileGrid), }), zIndex: layer.position + 1, }); diff --git a/src/client/src/pages/settings/components/editorSettingList/editorSettingList.jsx b/src/client/src/pages/settings/components/editorSettingList/editorSettingList.jsx index 9846c2c98..0177f0993 100644 --- a/src/client/src/pages/settings/components/editorSettingList/editorSettingList.jsx +++ b/src/client/src/pages/settings/components/editorSettingList/editorSettingList.jsx @@ -6,7 +6,18 @@ import TranslationText from "../../../../components/legacyComponents/translation import * as Styled from "./styles"; const EditorSettingList = props => { - const { data, toggleFilter, attribute, toggleField, listName, codes, toggleFieldArray, toggleFilterArray } = props; + const { + data, + toggleFilter, + attribute, + toggleField, + listName, + geocode, + codes, + toggleFieldArray, + toggleFilterArray, + type, + } = props; const { t } = useTranslation(); @@ -22,8 +33,15 @@ const EditorSettingList = props => { for (let idx = 0; idx < codes.data.layer_kind.length; idx++) { const element = codes.data.layer_kind[idx]; - if (element.code === "Geol") { - return element.conf.fields[field]; + if (element.code === geocode) { + if (type === "editor" && _.isObject(element.conf) && _.has(element.conf, `fields.${field}`)) { + return element.conf.fields[field]; + } + if (type === "viewer" && _.isObject(element.conf) && _.has(element.conf, `viewerFields.${field}`)) { + return element.conf.viewerFields[field]; + } else { + return false; + } } } } diff --git a/src/client/src/pages/settings/components/editorSettingList/mapSettings.jsx b/src/client/src/pages/settings/components/editorSettingList/mapSettings.jsx index 41d741e02..da029262f 100644 --- a/src/client/src/pages/settings/components/editorSettingList/mapSettings.jsx +++ b/src/client/src/pages/settings/components/editorSettingList/mapSettings.jsx @@ -1,12 +1,13 @@ -import { useContext, useEffect, useState } from "react"; +import { useContext } from "react"; import Highlighter from "react-highlight-words"; import { useTranslation } from "react-i18next"; -import { Button, CircularProgress, IconButton, Stack } from "@mui/material"; +import { Button, CircularProgress, IconButton } from "@mui/material"; import { Divider, Dropdown, Input, Label, Popup, Segment } from "semantic-ui-react"; import { Plus, Trash2 } from "lucide-react"; import _ from "lodash"; import WMSCapabilities from "ol/format/WMSCapabilities"; import WMTSCapabilities from "ol/format/WMTSCapabilities"; +import { getWms } from "../../../../api-lib/index"; import { theme } from "../../../../AppTheme"; import { AlertContext } from "../../../../components/alert/alertContext"; @@ -14,149 +15,30 @@ const MapSettings = props => { const { showAlert } = useContext(AlertContext); const { setting, i18n, rmExplorerMap, addExplorerMap, handleAddItem, handleOnChange, state, setState } = props; const { t } = useTranslation(); - const [mapSettings, setMapSettings] = useState(setting.data.map.explorer); - - useEffect(() => { - setMapSettings(setting.data.map.explorer); - }, [setting.data.map.explorer]); function getIconButton(layer, layerType) { return ( { e.stopPropagation(); - const identifier = layerType === "WMS" ? layer.Name : layer.Identifier; - if (_.has(mapSettings, identifier)) { - layer.Identifier = identifier; + if (_.has(setting.data.map.explorer, layerType === "WMS" ? layer.Name : layer.identifier)) { rmExplorerMap(layer); } else { - const service = layerType === "WMS" ? state.wms : state.wmts; - addExplorerMap(layer, layerType, service, _.values(mapSettings).length); + addExplorerMap(layer, layerType, state.wms, _.values(setting.data.map.explorer).length); } }} - color={_.has(mapSettings, layer.Name) ? "error" : "primary"}> - {_.has(mapSettings, layer.Name) ? : } + color={_.has(setting.data.map.explorer, layer.Name) ? "error" : "primary"}> + {_.has(setting.data.map.explorer, layer.Name) ? : } ); } - function getLayerList(layers, search, layerType) { - return layers.map((layer, idx) => { - const identifier = layerType === "WMS" ? layer.Name : layer.Identifier; - - return search === "" || - (Object.prototype.hasOwnProperty.call(layer, "Title") && layer.Title.toLowerCase().search(search) >= 0) || - (Object.prototype.hasOwnProperty.call(layer, "Abstract") && layer.Abstract.toLowerCase().search(search) >= 0) || - (Object.prototype.hasOwnProperty.call(layer, "Name") && identifier.toLowerCase().search(search) >= 0) ? ( -
- -
- -
-
{getIconButton(layer, layerType)}
-
-
- {layer.queryable === true && layerType === "WMS" ? ( - - } - /> - ) : null} - -
-
- -
-
- ) : null; - }); - } - - function fetchCapabilitiesForService() { - const isWms = setting.selectedWMS.startsWith("https://wms"); - const languageParam = `${isWms ? "&lang=" : "?lang="}${i18n.language}`; - fetch(setting.selectedWMS + languageParam).then(response => { - response.text().then(data => { - // Check if WMS or WMTS - if (/<(WMT_MS_Capabilities|WMS_Capabilities)/.test(data)) { - const wms = new WMSCapabilities().read(data); - setState({ - ...state, - wmsFetch: false, - wms: wms, - wmts: null, - }); - } else if (/ { - if (!search) return true; - const searchLower = search.toLowerCase(); - return ( - (layer.Title && layer.Title.toLowerCase().includes(searchLower)) || - (layer.Abstract && layer.Abstract.toLowerCase().includes(searchLower)) || - (layer.Identifier && layer.Identifier.toLowerCase().includes(searchLower)) - ); - }; - return ( <>
{ setState({ - ...state, map: !state.map, }); }} @@ -227,15 +109,45 @@ const MapSettings = props => { @@ -246,7 +158,6 @@ const MapSettings = props => { icon="search" onChange={e => { setState({ - ...state, searchWmts: e.target.value.toLowerCase(), }); }} @@ -260,7 +171,6 @@ const MapSettings = props => { icon="search" onChange={e => { setState({ - ...state, searchWms: e.target.value.toLowerCase(), }); }} @@ -275,8 +185,117 @@ const MapSettings = props => { border: state.wms === null && state.wmts === null ? null : "thin solid #cecece", marginTop: state.wms === null && state.wmts === null ? null : "1em", }}> - {state.wms && getLayerList(state.wms.Capability.Layer.Layer, state.searchWms, "WMS")} - {state.wmts && getLayerList(state.wmts.Contents.Layer, state.searchWmts, "WMTS")} + {state.wms === null + ? null + : state.wms.Capability.Layer.Layer.map((layer, idx) => + state.searchWms === "" || + (Object.prototype.hasOwnProperty.call(layer, "Title") && + layer.Title.toLowerCase().search(state.searchWms) >= 0) || + (Object.prototype.hasOwnProperty.call(layer, "Abstract") && + layer.Abstract.toLowerCase().search(state.searchWms) >= 0) || + (Object.prototype.hasOwnProperty.call(layer, "Name") && + layer.Name.toLowerCase().search(state.searchWms) >= 0) ? ( +
+
+
+ +
+
{getIconButton(layer, "WMS")}
+
+
+ {layer.queryable === true ? ( + + } + /> + ) : null} + +
+
+ +
+
+ ) : null, + )} + {state.wmts === null + ? null + : state.wmts.Contents.Layer.map((layer, idx) => { + return state.searchWmts === "" || + (Object.prototype.hasOwnProperty.call(layer, "Title") && + layer.Title.toLowerCase().search(state.searchWmts) >= 0) || + (Object.prototype.hasOwnProperty.call(layer, "Abstract") && + layer.Abstract.toLowerCase().search(state.searchWmts) >= 0) || + (Object.prototype.hasOwnProperty.call(layer, "Identifier") && + layer.Identifier.toLowerCase().search(state.searchWmts) >= 0) ? ( +
+
+
+ +
+
{getIconButton(layer, "WMTS")}
+
+
+ +
+
+ +
+
+ ) : null; + })}
{ icon="search" onChange={e => { setState({ - ...state, searchWmtsUser: e.target.value.toLowerCase(), }); }} @@ -317,21 +335,35 @@ const MapSettings = props => { flex: "1 1 100%", border: "thin solid #cecece", }}> - {mapSettings && - Object.entries(mapSettings).map(([key, layer], index) => { - return filterBySearchTerm(layer, state.searchWmtsUser) ? ( + {_.values(setting.data.map.explorer) + .sort((a, b) => { + if (a.position < b.position) { + return 1; + } else if (a.position > b.position) { + return -1; + } + return 0; + }) + .map((layer, idx) => + state.searchWmtsUser === "" || + (Object.prototype.hasOwnProperty.call(layer, "Title") && + layer.Title.toLowerCase().search(state.searchWmtsUser) >= 0) || + (Object.prototype.hasOwnProperty.call(layer, "Abstract") && + layer.Abstract.toLowerCase().search(state.searchWmtsUser) >= 0) || + (Object.prototype.hasOwnProperty.call(layer, "Identifier") && + layer.Identifier.toLowerCase().search(state.searchWmtsUser) >= 0) ? (
-
{
{ e.stopPropagation(); - if (_.has(mapSettings, key)) { - layer.Identifier = key; + if (_.has(setting.data.map.explorer, layer.Identifier)) { rmExplorerMap(layer); } }} @@ -353,7 +383,7 @@ const MapSettings = props => {
-
+
{
- ) : null; - })} + ) : null, + )} diff --git a/src/client/src/pages/settings/editorSettings.jsx b/src/client/src/pages/settings/editorSettings.jsx new file mode 100644 index 000000000..ff2ef97ac --- /dev/null +++ b/src/client/src/pages/settings/editorSettings.jsx @@ -0,0 +1,377 @@ +import React from "react"; +import { withTranslation } from "react-i18next"; +import { connect } from "react-redux"; +import { Button } from "@mui/material"; +import { Divider } from "semantic-ui-react"; +import _ from "lodash"; +import { register } from "ol/proj/proj4"; +import { optionsFromCapabilities } from "ol/source/WMTS"; +import proj4 from "proj4"; +import PropTypes from "prop-types"; +import { patchCodeConfig, patchSettings } from "../../api-lib/index"; +import { theme } from "../../AppTheme"; +import TranslationText from "../../components/legacyComponents/translationText.jsx"; +import EditorSettingList from "./components/editorSettingList/editorSettingList"; +import MapSettings from "./components/editorSettingList/mapSettings"; +import { boreholeEditorData } from "./data/boreholeEditorData"; +import { lithologyFieldEditorData } from "./data/lithologyFieldEditorData"; +import { lithologyFilterEditorData } from "./data/lithologyFilterEditorData"; +import { locationEditorData } from "./data/locationEditorData"; +import { registrationEditorData } from "./data/registrationEditorData"; + +const projections = { + "EPSG:21781": + "+proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 +k_0=1 +x_0=600000 +y_0=200000 +ellps=bessel +towgs84=674.4,15.1,405.3,0,0,0,0 +units=m +no_defs", + "EPSG:2056": + "+proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 +k_0=1 +x_0=2600000 +y_0=1200000 +ellps=bessel +towgs84=674.374,15.056,405.346,0,0,0,0 +units=m +no_defs", + "EPSG:21782": + "+proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 +k_0=1 +x_0=0 +y_0=0 +ellps=bessel +towgs84=674.4,15.1,405.3,0,0,0,0 +units=m +no_defs", + "EPSG:4149": "+proj=longlat +ellps=bessel +towgs84=674.4,15.1,405.3,0,0,0,0 +no_defs", + "EPSG:4150": "+proj=longlat +ellps=bessel +towgs84=674.374,15.056,405.346,0,0,0,0 +no_defs", +}; + +class EditorSettings extends React.Component { + constructor(props) { + super(props); + _.forEach(projections, function (proj, srs) { + proj4.defs(srs, proj); + }); + register(proj4); + this.setStateBound = this.setState.bind(this); + this.state = { + fields: false, + identifiers: false, + codeLists: false, + searchFiltersBoreholes: false, + searchFiltersLayers: false, + map: false, + + wmtsFetch: false, + searchWmts: "", + searchWmtsUser: "", + wmts: null, + + wmsFetch: false, + searchWms: "", + searchWmsUser: "", + wms: null, + searchList: [ + { + id: 0, + name: "location", + translationId: "searchFilterLocation", + isSelected: false, + }, + { + id: 1, + name: "borehole", + translationId: "searchFiltersBoreholes", + isSelected: false, + }, + + { + id: 2, + name: "lithology", + translationId: "searchFiltersLayers", + isSelected: false, + }, + { + id: 3, + name: "lithologyfields", + translationId: "lithologyfields", + isSelected: false, + }, + { + id: 4, + name: "registration", + translationId: "searchFilterRegistration", + isSelected: false, + }, + ], + }; + } + + isVisible(field) { + const { geocode, codes } = this.props; + if (_.has(codes, "data.layer_kind") && _.isArray(codes.data.layer_kind)) { + for (let idx = 0; idx < codes.data.layer_kind.length; idx++) { + const element = codes.data.layer_kind[idx]; + if (element.code === geocode) { + if (_.isObject(element.conf) && _.has(element.conf, `fields.${field}`)) { + return element.conf.fields[field]; + } else { + return false; + } + } + } + } + return false; + } + + handleButtonSelected(name, isSelected) { + let selectedData; + if (name === "location" && isSelected) { + selectedData = locationEditorData; + } else if (name === "borehole" && isSelected) { + selectedData = boreholeEditorData; + } else if (name === "lithology" && isSelected) { + selectedData = lithologyFilterEditorData; + } else if (name === "lithologyfields" && isSelected) { + selectedData = lithologyFieldEditorData; + } else if (name === "registration" && isSelected) { + selectedData = registrationEditorData; + } else { + selectedData = null; + } + return selectedData; + } + + render() { + const { + addExplorerMap, + rmExplorerMap, + setting, + i18n, + toggleFilter, + toggleFieldArray, + toggleFilterArray, + toggleField, + t, + } = this.props; + return ( +
+ { + this.setState( + { + wmsFetch: false, + wms: null, + wmts: null, + }, + () => { + this.props.handleAddItem(value); + }, + ); + }} + handleOnChange={value => { + this.setState( + { + wmsFetch: false, + wms: null, + wmts: null, + }, + () => { + this.props.handleOnChange(value); + }, + ); + }} + state={this.state} + setState={this.setStateBound}> + + {this.state?.searchList?.map((filter, idx) => ( +
+
{ + this.setState(prevState => ({ + ...prevState, + // update an array of objects: + searchList: prevState.searchList.map(obj => + obj.id === idx ? { ...obj, isSelected: !obj.isSelected } : { ...obj }, + ), + })); + }} + style={{ + flexDirection: "row", + display: "flex", + cursor: "pointer", + backgroundColor: filter.isSelected + ? theme.palette.background.lightgrey + : theme.palette.background.default, + padding: 10, + }}> +
+ +
+
+ +
+
+ {filter.isSelected === true && this.handleButtonSelected(filter.name, filter.isSelected) !== null ? ( + + ) : ( + + )} +
+ ))} +
+ ); + } +} + +EditorSettings.propTypes = { + codes: PropTypes.object, + geocode: PropTypes.string, + setting: PropTypes.object, + t: PropTypes.func, + toggleField: PropTypes.func, + toggleFieldArray: PropTypes.func, + toggleFilter: PropTypes.func, + toggleFilterArray: PropTypes.func, +}; + +EditorSettings.defaultProps = { + geocode: "Geol", +}; + +const mapStateToProps = state => { + return { + setting: state.setting, + codes: state.core_domain_list, + user: state.core_user, + }; +}; + +const mapDispatchToProps = dispatch => { + return { + dispatch: dispatch, + toggleFieldArray: (filter, enabled) => { + const newFilter = []; + filter.forEach(element => { + newFilter.push(`fields.${element}`); + }); + dispatch(patchCodeConfig(newFilter, enabled)); + }, + toggleFilterArray: (filter, enabled) => { + const newFilter = []; + filter.forEach(element => { + newFilter.push(`efilter.${element}`); + }); + dispatch(patchSettings(newFilter, enabled)); + }, + toggleField: (filter, enabled) => { + dispatch(patchCodeConfig(`fields.${filter}`, enabled)); + }, + toggleFilter: (filter, enabled) => { + dispatch(patchSettings(`efilter.${filter}`, enabled)); + }, + addExplorerMap: (layer, type, result, position = 0) => { + if (type === "WMS") { + if (!layer.CRS.includes("EPSG:2056")) { + this.context.showAlert("Only EPSG:2056 is supported", "error"); + } else { + dispatch( + patchSettings( + "map.explorer", + { + Identifier: layer.Name, + Abstract: layer.Abstract, + position: position, + Title: layer.Title, + transparency: 0, + type: "WMS", + url: result.Service.OnlineResource, + visibility: true, + queryable: layer.queryable, + }, + layer.Name, + ), + ); + } + } else if (type === "WMTS") { + const conf = optionsFromCapabilities(result, { + layer: layer.Identifier, + }); + if (Object.prototype.hasOwnProperty.call(conf, "matrixSet") && !conf.matrixSet.includes("2056")) { + this.context.showAlert("Only EPSG:2056 is supported", "error"); + } else { + dispatch( + patchSettings( + "map.explorer", + { + Identifier: layer.Identifier, + Abstract: layer.Abstract, + position: position, + Title: layer.Title, + transparency: 0, + type: "WMTS", + url: conf.urls, + visibility: true, + queryable: false, + conf: { + ...conf, + projection: { + code: conf.projection.code_, + units: conf.projection.units_, + extent: conf.projection.extent_, + axisOrientation: conf.projection.axisOrientation_, + global: conf.projection.global_, + metersPerUnit: conf.projection.metersPerUnit_, + worldExtent: conf.projection.worldExtent_, + }, + tileGrid: { + extent: conf.tileGrid.extent_, + origin: conf.tileGrid.origin_, + origins: conf.tileGrid.origins_, + resolutions: conf.tileGrid.resolutions_, + matrixIds: conf.tileGrid.matrixIds_, + tileSize: conf.tileGrid.tileSize_, + tileSizes: conf.tileGrid.tileSizes_, + }, + }, + }, + layer.Identifier, + ), + ); + } + } + }, + rmExplorerMap: config => { + dispatch(patchSettings("map.explorer", null, config.Identifier)); + }, + + handleAddItem: value => { + dispatch({ + type: "WMS_ADDED", + url: value, + }); + }, + handleOnChange: value => { + dispatch({ + type: "WMS_SELECTED", + url: value, + }); + }, + }; +}; + +const ConnectedEditorSettings = connect(mapStateToProps, mapDispatchToProps)(withTranslation("common")(EditorSettings)); +export default ConnectedEditorSettings; diff --git a/src/client/src/pages/settings/editorSettings.tsx b/src/client/src/pages/settings/editorSettings.tsx deleted file mode 100644 index 4dac65100..000000000 --- a/src/client/src/pages/settings/editorSettings.tsx +++ /dev/null @@ -1,286 +0,0 @@ -import { useContext, useState } from "react"; -import { useTranslation } from "react-i18next"; -import { useDispatch, useSelector } from "react-redux"; -import { Button } from "@mui/material"; -import { Divider } from "semantic-ui-react"; -import _ from "lodash"; -import { register } from "ol/proj/proj4"; -import { Options, optionsFromCapabilities } from "ol/source/WMTS"; -import proj4 from "proj4"; -import { patchCodeConfig, patchSettings } from "../../api-lib"; -import { ReduxRootState } from "../../api-lib/ReduxStateInterfaces.ts"; -import { useDomains } from "../../api/fetchApiV2"; -import { theme } from "../../AppTheme"; -import { AlertContext } from "../../components/alert/alertContext"; -import TranslationText from "../../components/legacyComponents/translationText.jsx"; -import EditorSettingList from "./components/editorSettingList/editorSettingList"; -import MapSettings from "./components/editorSettingList/mapSettings"; -import { boreholeEditorData } from "./data/boreholeEditorData"; -import { lithologyFieldEditorData } from "./data/lithologyFieldEditorData"; -import { lithologyFilterEditorData } from "./data/lithologyFilterEditorData"; -import { locationEditorData } from "./data/locationEditorData"; -import { registrationEditorData } from "./data/registrationEditorData"; -import { Layer } from "./layerInterface.ts"; - -const projections = { - "EPSG:21781": - "+proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 +k_0=1 +x_0=600000 +y_0=200000 +ellps=bessel +towgs84=674.4,15.1,405.3,0,0,0,0 +units=m +no_defs", - "EPSG:2056": - "+proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 +k_0=1 +x_0=2600000 +y_0=1200000 +ellps=bessel +towgs84=674.374,15.056,405.346,0,0,0,0 +units=m +no_defs", - "EPSG:21782": - "+proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 +k_0=1 +x_0=0 +y_0=0 +ellps=bessel +towgs84=674.4,15.1,405.3,0,0,0,0 +units=m +no_defs", - "EPSG:4149": "+proj=longlat +ellps=bessel +towgs84=674.4,15.1,405.3,0,0,0,0 +no_defs", - "EPSG:4150": "+proj=longlat +ellps=bessel +towgs84=674.374,15.056,405.346,0,0,0,0 +no_defs", -}; - -const EditorSettings = () => { - const { showAlert } = useContext(AlertContext); - const { i18n, t } = useTranslation(); - - const setting = useSelector((state: ReduxRootState) => state.setting); - const { data: domains } = useDomains(); - - const dispatch = useDispatch(); - const toggleFieldArray = (filter: string[], enabled: boolean) => { - const newFilter: string[] = []; - filter.forEach(element => { - newFilter.push(`fields.${element}`); - }); - dispatch(patchCodeConfig(newFilter, enabled)); - }; - - const toggleFilterArray = (filter: string[], enabled: boolean) => { - const newFilter: string[] = []; - filter.forEach(element => { - newFilter.push(`efilter.${element}`); - }); - dispatch(patchSettings(newFilter, enabled)); - }; - - const toggleField = (filter: string, enabled: boolean) => { - dispatch(patchCodeConfig(`fields.${filter}`, enabled)); - }; - const toggleFilter = (filter: string, enabled: boolean) => { - dispatch(patchSettings(`efilter.${filter}`, enabled)); - }; - - const dispatchMapSettings = ( - layer: Layer, - type: "WMS" | "WMTS", - url: string | undefined, - conf: Options | null, - position: number, - queryable: boolean, - ) => { - dispatch( - patchSettings( - "map.explorer", - { - Identifier: layer.Identifier, - Abstract: layer.Abstract, - position: position, - Title: layer.Title, - transparency: 0, - type: type, - url: url, - visibility: true, - queryable: queryable, - conf: conf, - }, - // @ts-expect-error typing not complete - type === "WMTS" ? layer?.Identifier : layer?.Name, - ), - ); - }; - - /* eslint-disable @typescript-eslint/no-explicit-any */ - const addExplorerMap = (layer: Layer, type: "WMS" | "WMTS", result: any, position = 0) => { - if (type === "WMS") { - if (!layer.CRS.includes("EPSG:2056")) { - showAlert(t("onlyEPSG2056Supported"), "error"); - } else { - dispatchMapSettings(layer, type, result.Service.OnlineResource, null, position, layer.queryable); - } - } else if (type === "WMTS") { - const conf: Options | null = optionsFromCapabilities(result, { - layer: layer.Identifier, - }); - if (conf) { - if (Object.prototype.hasOwnProperty.call(conf, "matrixSet") && !conf.matrixSet.includes("2056")) { - showAlert(t("onlyEPSG2056Supported"), "error"); - } else { - dispatchMapSettings(layer, type, conf.urls?.[0], conf, position, false); - } - } - } - }; - - const rmExplorerMap = (config: Layer) => { - // @ts-expect-error typing not complete - dispatch(patchSettings("map.explorer", null, config.Identifier)); - }; - - const handleAddItem = (value: string) => { - dispatch({ - type: "WMS_ADDED", - url: value, - }); - }; - const handleOnChange = (value: string) => { - dispatch({ - type: "WMS_SELECTED", - url: value, - }); - }; - - _.forEach(projections, function (proj, srs) { - proj4.defs(srs, proj); - }); - register(proj4); - const [searchList, setSearchList] = useState([ - { - id: 0, - name: "location", - translationId: "searchFilterLocation", - isSelected: false, - }, - { - id: 1, - name: "borehole", - translationId: "searchFiltersBoreholes", - isSelected: false, - }, - - { - id: 2, - name: "lithology", - translationId: "searchFiltersLayers", - isSelected: false, - }, - { - id: 3, - name: "lithologyfields", - translationId: "lithologyfields", - isSelected: false, - }, - { - id: 4, - name: "registration", - translationId: "searchFilterRegistration", - isSelected: false, - }, - ]); - const [state, setState] = useState({ - fields: false, - identifiers: false, - codeLists: false, - searchFiltersBoreholes: false, - searchFiltersLayers: false, - map: false, - - wmtsFetch: false, - searchWmts: "", - searchWmtsUser: "", - wmts: null, - - wmsFetch: false, - searchWms: "", - searchWmsUser: "", - wms: null, - }); - - const handleButtonSelected = (name: string, isSelected: boolean) => { - let selectedData; - if (name === "location" && isSelected) { - selectedData = locationEditorData; - } else if (name === "borehole" && isSelected) { - selectedData = boreholeEditorData; - } else if (name === "lithology" && isSelected) { - selectedData = lithologyFilterEditorData; - } else if (name === "lithologyfields" && isSelected) { - selectedData = lithologyFieldEditorData; - } else if (name === "registration" && isSelected) { - selectedData = registrationEditorData; - } else { - selectedData = null; - } - return selectedData; - }; - - return ( -
- { - setState({ ...state, wmsFetch: false, wms: null, wmts: null }); - handleAddItem(value); - }} - handleOnChange={(value: string) => { - setState({ ...state, wmsFetch: false, wms: null, wmts: null }); - handleOnChange(value); - }} - state={state} - setState={setState}> - - {searchList?.map((filter, idx) => ( -
-
{ - setSearchList( - searchList.map(obj => (obj.id === idx ? { ...obj, isSelected: !obj.isSelected } : { ...obj })), - ); - }} - style={{ - flexDirection: "row", - display: "flex", - cursor: "pointer", - backgroundColor: filter.isSelected - ? theme.palette.background.lightgrey - : theme.palette.background.default, - padding: 10, - }}> -
- -
-
- -
-
- {filter.isSelected && handleButtonSelected(filter.name, filter.isSelected) !== null ? ( - - ) : ( - - )} -
- ))} -
- ); -}; - -export default EditorSettings; diff --git a/src/client/src/pages/settings/layerInterface.ts b/src/client/src/pages/settings/layerInterface.ts deleted file mode 100644 index e541e3fe2..000000000 --- a/src/client/src/pages/settings/layerInterface.ts +++ /dev/null @@ -1,8 +0,0 @@ -export interface Layer { - queryable: boolean; - CRS: string[]; - Title: string; - Abstract: string; - Name?: string; - Identifier?: string; -} diff --git a/src/client/src/pages/settings/settingState.js b/src/client/src/pages/settings/settingState.js index d68ebb5ee..3009c9f06 100644 --- a/src/client/src/pages/settings/settingState.js +++ b/src/client/src/pages/settings/settingState.js @@ -13,6 +13,11 @@ const initialState = { text: "https://wms.geo.admin.ch?request=getCapabilities&service=WMS", value: "https://wms.geo.admin.ch?request=getCapabilities&service=WMS", }, + { + key: "https://wms-inspire.geo.admin.ch/?SERVICE=WMS&request=getCapabilities", + text: "https://wms-inspire.geo.admin.ch/?SERVICE=WMS&request=getCapabilities", + value: "https://wms-inspire.geo.admin.ch/?SERVICE=WMS&request=getCapabilities", + }, { key: "https://wmts.geo.admin.ch/EPSG/2056/1.0.0/WMTSCapabilities.xml", text: "https://wmts.geo.admin.ch/EPSG/2056/1.0.0/WMTSCapabilities.xml", diff --git a/src/client/src/pages/settings/settingsPage.jsx b/src/client/src/pages/settings/settingsPage.jsx index 17aaf86ea..ffa895bd9 100644 --- a/src/client/src/pages/settings/settingsPage.jsx +++ b/src/client/src/pages/settings/settingsPage.jsx @@ -4,7 +4,7 @@ import { Box } from "@mui/material"; import { useAuth } from "../../auth/useBdmsAuth"; import AboutSettings from "./aboutSettings"; import AdminSettings from "./admin/adminSettings"; -import EditorSettings from "./editorSettings.tsx"; +import EditorSettings from "./editorSettings"; import MenuSettings from "./menuSettings"; import TermSettings from "./termSettings";