diff --git a/bundles/admin/admin-layereditor/resources/locale/en.js b/bundles/admin/admin-layereditor/resources/locale/en.js index ca00704b6b..041ad88722 100644 --- a/bundles/admin/admin-layereditor/resources/locale/en.js +++ b/bundles/admin/admin-layereditor/resources/locale/en.js @@ -110,6 +110,19 @@ Oskari.registerLocalization( "globalWithStyles": "The layer has more than one style available in the service. However, the layer has been defined with a single default legend. Consider removing the current default legend to be able to use the style based legends." } }, + "attributes": { + "label": "Attributes", + "geometryType": { + "label": "Geometry type", + "sourceAttributes": "Source: layer attributes", + "sourceCapabilities": "Source: layer capabilities", + "unknown":"Unknown", + "point": "Point", + "line": "Line", + "area":"Area", + "collection":"Collection" + } + }, "styles": { "default": "Default style", "desc": "Select a default style from the list. If there are several options, users can select a theme in the ‘Selected Layers’ menu.", @@ -159,7 +172,6 @@ Oskari.registerLocalization( "gfiTypeDesc": "Select a format for Get Feature Information (GFI). Possible formats are fetched automatically from the GetCapabilities response.", "gfiStyle": "GFI style (XSLT)", "gfiStyleDesc": "Define a style for Get Feature Information (GFI) as XSLT transformation.", - "attributes": "Attributes", "clusteringDistance": "Point distance in cluster", "forcedSRS": "Forced SRS", "forcedSRSInfo": "View projections override compared to capabilities", diff --git a/bundles/admin/admin-layereditor/resources/locale/fi.js b/bundles/admin/admin-layereditor/resources/locale/fi.js index dbf9b1a91f..07d84e8016 100644 --- a/bundles/admin/admin-layereditor/resources/locale/fi.js +++ b/bundles/admin/admin-layereditor/resources/locale/fi.js @@ -111,6 +111,19 @@ Oskari.registerLocalization( "globalWithStyles": "Tasolle on määritetty vain yksi yleinen oletuskarttaselite, vaikka sillä olisi rajapintapalvelusta useita tyylejä käytettävissä. Poista oletuskarttaselite ja määritä mahdolliset tyylikohtaiset karttaselitteet." } }, + "attributes": { + "label": "Attribuutit", + "geometryType": { + "label": "Geometriatyyppi", + "sourceAttributes": "Lähde: tason attribuutit", + "sourceCapabilities": "Lähde: tason Capabilities-tiedot", + "unknown":"Ei tiedossa", + "point": "Piste", + "line": "Viiva", + "area":"Alue", + "collection":"Kaikki" + } + }, "styles": { "default": "Oletustyyli", "desc": "Taso lisätään kartalle oletustyylillä. Käyttäjä voi vaihtaa tyyliä ”Valitut tasot”-valikon kautta.", @@ -160,7 +173,6 @@ Oskari.registerLocalization( "gfiTypeDesc": "Valitse listalta formaatti, jossa kohdetiedot (GFI) haetaan. Mahdolliset formaatit on määritelty WMS-palvelun GetCapabilities-vastausviestissä.", "gfiStyle": "GFI-tyyli (XSLT)", "gfiStyleDesc": "Määrittele kohdetietojen esitystapa XSLT-muunnoksen avulla.", - "attributes": "Attribuutit", "clusteringDistance": "Pisteiden etäisyys klusteroidessa", "forcedSRS": "Pakotetut projektiot", "forcedSRSInfo": "Pakotetut projektiot verrattuna GetCapabilites-määritykseen", diff --git a/bundles/admin/admin-layereditor/resources/locale/sv.js b/bundles/admin/admin-layereditor/resources/locale/sv.js index 5af2b1ece7..91946c2256 100644 --- a/bundles/admin/admin-layereditor/resources/locale/sv.js +++ b/bundles/admin/admin-layereditor/resources/locale/sv.js @@ -109,6 +109,19 @@ Oskari.registerLocalization( "globalWithStyles": "Till kartlagret har endast en standard teckenförklaring fastställts, men det finns ytterliga stilar med förklaringar tillgängliga på gränssnittet. Du kan ta bort standardvalet för att kunna utnyttja dessa." } }, + "attributes": { + "label": "Attribut", + "geometryType": { + "label": "Typ av geometri", + "sourceAttributes": "Källa: kartlagrets attribut", + "sourceCapabilities": "Källa: kartlagrets capabilities", + "unknown":"Okänd", + "point": "Punkten", + "line": "Linje", + "area":"Området", + "collection":"All" + } + }, "styles": { "default": "Förvald utseende", "desc": "Välj en standardstil från listan. Om det finns flera alternativ kan användare välja ett tema i menyn 'Valda lager'.", @@ -157,7 +170,6 @@ Oskari.registerLocalization( "gfiTypeDesc": "Svarets typ dvs Get Feature Info (GFI)", "gfiStyle": "GFI stil", "gfiStyleDesc": "GFI stil (XSLT)", - "attributes": "Attribut", "clusteringDistance": "Punktavstånd i kluster", "forcedSRS": "Tvingade SRS", "forcedSRSInfo": "Tvångs SRS jämfört med GetCapabilites", diff --git a/bundles/admin/admin-layereditor/view/AdminLayerForm/AdditionalTabPane/AdditionalTabPane.jsx b/bundles/admin/admin-layereditor/view/AdminLayerForm/AdditionalTabPane/AdditionalTabPane.jsx index 2ee4c466ac..9a96d27312 100644 --- a/bundles/admin/admin-layereditor/view/AdminLayerForm/AdditionalTabPane/AdditionalTabPane.jsx +++ b/bundles/admin/admin-layereditor/view/AdminLayerForm/AdditionalTabPane/AdditionalTabPane.jsx @@ -8,6 +8,7 @@ import { GfiType } from './GfiType'; import { GfiContent } from './GfiContent'; import { GfiStyle } from './GfiStyle'; import { Attributes } from './Attributes'; +import { VectorLayerAttributes } from './VectorLayerAttributes'; import { Attributions } from './Attributions'; import { MetadataId } from './MetadataId'; import { Capabilities } from './Capabilities'; @@ -24,7 +25,8 @@ const { GFI_TYPE, GFI_XSLT, ATTRIBUTIONS, - ATTRIBUTES + ATTRIBUTES, + VECTOR_LAYER } = LayerComposingModel; export const AdditionalTabPane = ({ layer, propertyFields, metadata, controller }) => { @@ -62,6 +64,9 @@ export const AdditionalTabPane = ({ layer, propertyFields, metadata, controller { isQueryable && propertyFields.includes(GFI_XSLT) && } + { propertyFields.includes(VECTOR_LAYER) && + + } { propertyFields.includes(ATTRIBUTES) && } diff --git a/bundles/admin/admin-layereditor/view/AdminLayerForm/AdditionalTabPane/Attributes.jsx b/bundles/admin/admin-layereditor/view/AdminLayerForm/AdditionalTabPane/Attributes.jsx index 75d510ea9f..d91ac00919 100644 --- a/bundles/admin/admin-layereditor/view/AdminLayerForm/AdditionalTabPane/Attributes.jsx +++ b/bundles/admin/admin-layereditor/view/AdminLayerForm/AdditionalTabPane/Attributes.jsx @@ -31,7 +31,7 @@ export const Attributes = ({ layer, controller }) => { } return ( - + { !isValid && } { + const geometryTypeSource = layer.attributes.data?.geometryType ? 'Attributes' : 'Capabilities'; + const onGeometryTypeChange = value => { + if (GEOMETRY_TYPES[0] === value) { + controller.setAttributesData('geometryType'); + } else { + controller.setAttributesData('geometryType', value); + } + }; + return ( + + + + + + + + ); +}; + +VectorLayerAttributes.propTypes = { + layer: PropTypes.object.isRequired, + controller: PropTypes.instanceOf(Controller).isRequired +}; diff --git a/bundles/admin/admin-layereditor/view/AdminLayerForm/AdminLayerFormHandler.js b/bundles/admin/admin-layereditor/view/AdminLayerForm/AdminLayerFormHandler.js index c6aa1a4fb5..3944938823 100644 --- a/bundles/admin/admin-layereditor/view/AdminLayerForm/AdminLayerFormHandler.js +++ b/bundles/admin/admin-layereditor/view/AdminLayerForm/AdminLayerFormHandler.js @@ -290,6 +290,17 @@ class UIHandler extends StateHandler { this.updateLayerAttributes(attributes, layer); } + setAttributesData (key, value) { + const layer = { ...this.getState().layer }; + const { data = {} } = layer.attributes || {}; + if (typeof value === 'undefined') { + delete data[key]; + } else { + data[key] = value; + } + this.updateLayerAttributes({ ...layer.attributes, data }, layer); + } + setLocalizedNames (locale) { this.updateState({ layer: { ...this.getState().layer, locale } @@ -452,7 +463,7 @@ class UIHandler extends StateHandler { } // Delete missing attibute keys but keep managed attributes - const managedAttributes = ['forcedSRS']; + const managedAttributes = ['forcedSRS', 'data']; Object.keys(layer.attributes) .filter(key => !managedAttributes.includes(key)) .forEach(key => delete layer.attributes[key]); @@ -1190,6 +1201,7 @@ const wrapped = controllerMixin(UIHandler, [ 'removeVectorStyleFromLayer', 'saveVectorStyleToLayer', 'setAttributes', + 'setAttributesData', 'setAttributionsJSON', 'setCapabilitiesUpdateRate', 'setClusteringDistance', diff --git a/bundles/admin/admin-layereditor/view/AdminLayerForm/VisualizationTabPane/VectorStyle.jsx b/bundles/admin/admin-layereditor/view/AdminLayerForm/VisualizationTabPane/VectorStyle.jsx index 8870716731..1311970605 100644 --- a/bundles/admin/admin-layereditor/view/AdminLayerForm/VisualizationTabPane/VectorStyle.jsx +++ b/bundles/admin/admin-layereditor/view/AdminLayerForm/VisualizationTabPane/VectorStyle.jsx @@ -11,6 +11,8 @@ import { StyleEditor } from 'oskari-ui/components/StyleEditor'; import styled from 'styled-components'; import { ThemeConsumer } from 'oskari-ui/util'; import { generateBlankStyle } from 'oskari-ui/components/StyleEditor/index'; +import { SUPPORTED_FORMATS } from 'oskari-ui/components/StyleEditor/constants'; +import { getGeometryType } from '../../LayerHelper'; const FullWidthSpace = styled(Space)` & { @@ -109,6 +111,8 @@ export const VectorStyle = ThemeConsumer(LocaleConsumer(({ theme = {}, layer, ge }; const visible = !!state.modal; const externalType = external ? getExternalStyleType(layer) : null; + const geometryType = getGeometryType(layer); + const styleTabs = SUPPORTED_FORMATS.includes(geometryType) ? [geometryType] : SUPPORTED_FORMATS; return ( @@ -153,6 +157,7 @@ export const VectorStyle = ThemeConsumer(LocaleConsumer(({ theme = {}, layer, ge { state.modal === 'editor' && updateStyle({ featureStyle })} /> } diff --git a/bundles/admin/admin-layereditor/view/LayerHelper.js b/bundles/admin/admin-layereditor/view/LayerHelper.js index c85d9ae299..a38bfa0b24 100644 --- a/bundles/admin/admin-layereditor/view/LayerHelper.js +++ b/bundles/admin/admin-layereditor/view/LayerHelper.js @@ -1,3 +1,20 @@ +export const GEOMETRY_TYPES = ['unknown', 'point', 'line', 'area', 'collection']; +const AREA_TYPES = ['surface', 'polygon']; + +export const getGeometryType = layer => { + const { attributes, capabilities } = layer; + if (attributes?.data?.geometryType) { + return attributes.data.geometryType; + } + const { geomName, featureProperties = [] } = capabilities; + const capaType = featureProperties.find(prop => prop.name === geomName)?.type.toLowerCase() || ''; + // SurfacePropertyType, GeometryPropertyType, PointPropertyType, MultiLineStringPropertyType, MultiPolygon,... + if (AREA_TYPES.find(type => capaType.includes(type))) { + return 'area'; + } + return GEOMETRY_TYPES.find(type => capaType.includes(type)) || 'unknown'; +}; + // keys are the server side expected keys and values are the keys used by frontend const APIMapping = { dataprovider_id: 'dataProviderId', diff --git a/bundles/mapping/mapmodule/domain/LayerComposingModel.js b/bundles/mapping/mapmodule/domain/LayerComposingModel.js index 408cebeb55..b9ffbd1147 100644 --- a/bundles/mapping/mapmodule/domain/LayerComposingModel.js +++ b/bundles/mapping/mapmodule/domain/LayerComposingModel.js @@ -31,7 +31,8 @@ const PROPERTY_FIELDS = [ 'URL', 'VERSION', 'WFS_RENDER_MODE', - 'DECLUTTER' + 'DECLUTTER', + 'VECTOR_LAYER' ]; // Common fields are enforced on composing model. diff --git a/bundles/mapping/mapmodule/plugin/vectortilelayer/VectorTileLayerPlugin.js b/bundles/mapping/mapmodule/plugin/vectortilelayer/VectorTileLayerPlugin.js index 777ff0d491..0a4c8792b3 100644 --- a/bundles/mapping/mapmodule/plugin/vectortilelayer/VectorTileLayerPlugin.js +++ b/bundles/mapping/mapmodule/plugin/vectortilelayer/VectorTileLayerPlugin.js @@ -46,7 +46,8 @@ class VectorTileLayerPlugin extends AbstractVectorLayerPlugin { LayerComposingModel.VECTOR_STYLES, LayerComposingModel.TILE_GRID, LayerComposingModel.URL, - LayerComposingModel.DECLUTTER + LayerComposingModel.DECLUTTER, + LayerComposingModel.VECTOR_LAYER ], null, [LayerComposingModel.NAME]); // common field name is not used in vectortilelayers so it is skipped on LayerComposingModel mapLayerService.registerLayerModel(this.layertype + 'layer', this._getLayerModelClass(), composingModel); diff --git a/bundles/mapping/mapwfs2/plugin/WfsVectorLayerPlugin.ol.js b/bundles/mapping/mapwfs2/plugin/WfsVectorLayerPlugin.ol.js index 59056fb8f6..cab5ecceb3 100644 --- a/bundles/mapping/mapwfs2/plugin/WfsVectorLayerPlugin.ol.js +++ b/bundles/mapping/mapwfs2/plugin/WfsVectorLayerPlugin.ol.js @@ -91,7 +91,8 @@ export class WfsVectorLayerPlugin extends AbstractVectorLayerPlugin { LayerComposingModel.VECTOR_STYLES, LayerComposingModel.URL, LayerComposingModel.VERSION, - LayerComposingModel.WFS_RENDER_MODE + LayerComposingModel.WFS_RENDER_MODE, + LayerComposingModel.VECTOR_LAYER ], ['1.1.0', '2.0.0', '3.0.0']); const layerClass = 'Oskari.mapframework.bundle.mapwfs2.domain.WFSLayer'; diff --git a/bundles/mapping/tiles3d/plugin/Tiles3DLayerPlugin.js b/bundles/mapping/tiles3d/plugin/Tiles3DLayerPlugin.js index 3b34f1c114..4247241d03 100644 --- a/bundles/mapping/tiles3d/plugin/Tiles3DLayerPlugin.js +++ b/bundles/mapping/tiles3d/plugin/Tiles3DLayerPlugin.js @@ -60,7 +60,8 @@ Oskari.clazz.define('Oskari.mapframework.mapmodule.Tiles3DLayerPlugin', LayerComposingModel.SRS, LayerComposingModel.VECTOR_STYLES, LayerComposingModel.EXTERNAL_VECTOR_STYLES, - LayerComposingModel.URL + LayerComposingModel.URL, + LayerComposingModel.VECTOR_LAYER ]); mapLayerService.registerLayerModel(registerType, clazz, composingModel); mapLayerService.registerLayerModelBuilder(registerType, new Tiles3DModelBuilder());