Skip to content

Commit

Permalink
add edit button to list of styles (GeoNode#672)
Browse files Browse the repository at this point in the history
  • Loading branch information
stefano bovio authored Dec 16, 2021
1 parent 606fedf commit 665ca6e
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 40 deletions.
8 changes: 4 additions & 4 deletions geonode_mapstore_client/client/js/epics/visualstyleeditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ function getGnStyleQueryParams(style, styleService) {
}).then(updatedStyles => {
const { metadata = {}, code: updateStyleCode, format, languageVersion } = updatedStyles || {};
const metadataObj = parseMetadata(metadata);
return { msEditorType, msStyleJSON, ...metadataObj, code: updateStyleCode, format, languageVersion };
return { msEditorType: metadataObj?.msEditorType, msStyleJSON: metadataObj?.msStyleJSON, code: updateStyleCode, format, languageVersion };
}).catch(() => ({ msEditorType, msStyleJSON, code}));
}

Expand All @@ -93,8 +93,8 @@ function getGeoNodeStyles({ layer, styleService }) {
const metadata = {
title: layerName,
description: '',
msStyleJSON: msStyleJSON || null,
msEditorType: msEditorType || 'visual',
msStyleJSON: msStyleJSON,
msEditorType: msEditorType,
gnDatasetPk: layer?.extendedParams?.mapLayer?.dataset?.pk
};
return StylesAPI.createStyle({
Expand All @@ -121,7 +121,7 @@ export const gnRequestDatasetAvailableStyles = (action$, store) =>
const styleService = action?.options?.styleService || styleServiceSelector(state);
return Observable.defer(() => getGeoNodeStyles({ layer: action.layer, styleService }))
.switchMap(([styles, update]) => {
const style = styles?.[0]?.name;
const style = action?.options?.style || styles?.[0]?.name;
return Observable.concat(
Observable.of(setControlProperty('visualStyleEditor', 'enabled', true)),
Observable.defer(() => StylesAPI.getStylesInfo({
Expand Down
27 changes: 25 additions & 2 deletions geonode_mapstore_client/client/js/plugins/LayerSettings.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,20 @@ import { getTitle } from '@mapstore/framework/utils/TOCUtils';
import GroupSettings from '@js/plugins/layersettings/GroupSettings';
import BaseLayerSettings from '@js/plugins/layersettings/BaseLayerSettings';
import WMSLayerSettings from '@js/plugins/layersettings/WMSLayerSettings';
import GeoNodeStyleSelector from '@js/plugins/layersettings/GeoNodeStyleSelector';
import usePluginItems from '@js/hooks/usePluginItems';

const settingsForms = {
group: GroupSettings,
baseLayer: BaseLayerSettings,
wms: WMSLayerSettings
};

const ConnectedGeoNodeStyleSelector = connect(
createSelector([], () => ({})),
{}
)(GeoNodeStyleSelector);

/**
* @module plugins/LayerSettings
*/
Expand All @@ -47,8 +54,13 @@ function LayerSettings({
style,
selectedNodes,
onClose,
items = [],
...props
}) {
}, context) {


const { loadedPlugins } = context;
const configuredItems = usePluginItems({ items, loadedPlugins });

if (isEmpty(node)) {
return null;
Expand All @@ -61,6 +73,11 @@ function LayerSettings({
: settingsForms[node?.type] || settingsForms.baseLayer;

const title = node?.title && getTitle(node.title, props.currentLocale) || node.name;

function handleChange(properties) {
onChange(node.id, isGroup ? 'groups' : 'layers', properties);
}

return (
<div
className="gn-layer-settings"
Expand All @@ -76,7 +93,13 @@ function LayerSettings({
<Settings
{...props}
node={node}
onChange={(properties) => onChange(node.id, isGroup ? 'groups' : 'layers', properties)}
onChange={handleChange}
styleSelectorComponent={<ConnectedGeoNodeStyleSelector
{...props}
node={node}
onChange={handleChange}
buttons={(configuredItems || []).filter(({ target }) => target === 'style-button')}
/>}
/>
</div>
</div>
Expand Down
23 changes: 19 additions & 4 deletions geonode_mapstore_client/client/js/plugins/VisualStyleEditor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -383,22 +383,33 @@ function StyleEditorTocButton({
status,
onClick = () => {},
enabled,
isNew
isNew,
btnProps = {},
hide,
selectedStyle
}) {

if (!(status === 'LAYER' && layer?.extendedParams?.mapLayer && (enabled || isNew))) {
if (!(!hide && status === 'LAYER' && layer?.extendedParams?.mapLayer && (enabled || isNew))) {
return null;
}

function handleClick() {
onClick(layer);
function handleClick(event) {
event.stopPropagation();
event.preventDefault();
onClick(layer, { style: selectedStyle });
}
function handleMouseDown(event) {
event.stopPropagation();
event.preventDefault();
}

return (
<Button
variant="primary"
className="square-button-md"
{...btnProps}
onClick={handleClick}
onMouseDown={handleMouseDown}
>
<Glyphicon glyph="dropper"/>
</Button>
Expand Down Expand Up @@ -427,6 +438,10 @@ export default createPlugin('VisualStyleEditor', {
TOC: {
target: 'toolbar',
Component: ConnectedStyleEditorTocButton
},
LayerSettings: {
target: 'style-button',
Component: ConnectedStyleEditorTocButton
}
},
reducers: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Copyright 2021, GeoSolutions Sas.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/

import React from 'react';
import { FormGroup, ControlLabel } from 'react-bootstrap';
import Message from '@mapstore/framework/components/I18N/Message';
import Select from 'react-select';

import { cleanStyles } from '@js/utils/ResourceUtils';

function getStyleOptions(layer) {
const mapLayerStyles = (layer?.extendedParams?.mapLayer?.extra_params?.styles || [])
.map((style) => ({ ...style, canEdit: true }));
const datasetStyles = layer?.extendedParams?.mapLayer?.dataset?.styles || [];
const defaultStyle = layer?.extendedParams?.mapLayer?.dataset?.default_style;
const availableStyles = layer?.availableStyles || [];
return cleanStyles([
...(defaultStyle ? [defaultStyle] : []),
...datasetStyles,
...mapLayerStyles,
...availableStyles
]).map(({ name, title, canEdit }) => ({
value: name,
label: title,
canEdit
}));
}

function OptionLabel({
canEdit,
label,
style,
value,
buttons = []
}) {
return (
<div style={{ display: 'flex', width: '100%', alignItems: 'center', ...style }}>
<div style={{ overflow: 'hidden', textOverflow: 'ellipsis' }}>{label}</div>
{buttons.map(({ Component, name }) =>
<Component
key={name}
status="LAYER"
btnProps={{
variant: 'default',
className: '',
size: ''
}}
hide={!canEdit}
selectedStyle={value}
/>
)}
</div>
);
}

function GeoNodeStyleSelector({
node,
onChange,
buttons
}) {

const options = getStyleOptions(node);
const currentStyle = options.find(({ value }) => value === node.style) || { };

if (!node?.extendedParams?.mapLayer) {
return null;
}

return (

<FormGroup>
<ControlLabel><Message msgId="gnviewer.style" /></ControlLabel>
<Select
key="style-selector"
clearable={false}
options={options.map(({ value, label, canEdit }) => ({
value,
label: <OptionLabel value={value} label={label} canEdit={canEdit} buttons={buttons}/>
}))}
value={{
value: node.style,
label: <OptionLabel {...currentStyle} style={{ width: 'calc(100% - 16px)' }} buttons={buttons}/>
}}
onChange={({ value }) => onChange({ style: value })}/>
</FormGroup>
);
}

export default GeoNodeStyleSelector;
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,6 @@ import GeneralSettings from '@js/plugins/layersettings/GeneralSettings';
import VisibilitySettings from '@js/plugins/layersettings/VisibilitySettings';
import SettingsSection from '@js/plugins/layersettings/SettingsSection';
import useLocalStorage from '@js/hooks/useLocalStorage';
import { cleanStyles } from '@js/utils/ResourceUtils';

function getStyleOptions(layer) {
const mapLayerStyles = layer?.extendedParams?.mapLayer?.extra_params?.styles || [];
const datasetStyles = layer?.extendedParams?.mapLayer?.dataset?.styles || [];
const defaultStyle = layer?.extendedParams?.mapLayer?.dataset?.default_style;
const availableStyles = layer?.availableStyles || [];
return cleanStyles([
...(defaultStyle ? [defaultStyle] : []),
...datasetStyles,
...mapLayerStyles,
...availableStyles
]).map(({ name, title }) => ({
value: name,
label: title
}));
}

function WMSLayerSettings({
node = {},
Expand All @@ -50,7 +33,8 @@ function WMSLayerSettings({
isLocalizedLayerStylesEnabled,
currentLocaleLanguage,
groups = [],
currentLocale
currentLocale,
styleSelectorComponent
}) {

const {
Expand Down Expand Up @@ -166,15 +150,7 @@ function WMSLayerSettings({
expanded={settingsSections?.style}
onChange={handleChangeSection.bind(null, 'style')}
>
{node?.extendedParams?.mapLayer && <FormGroup>
<ControlLabel><Message msgId="gnviewer.style" /></ControlLabel>
<Select
key="style-selector"
clearable={false}
options={getStyleOptions(node)}
value={node.style}
onChange={({ value }) => onChange({ style: value })}/>
</FormGroup>}
{styleSelectorComponent}
<FormGroup validationState={isLegendOptionValid('legendWidth')}>
<ControlLabel><Message msgId="gnviewer.legendWidth" /></ControlLabel>
<IntlNumberFormControl
Expand Down
6 changes: 4 additions & 2 deletions geonode_mapstore_client/client/js/utils/ResourceUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -381,11 +381,12 @@ export function parseStyleName({ workspace, name }) {

export function cleanStyles(styles = [], excluded = []) {
return uniqBy(styles
.map(({ name, sld_title: sldTitle, title, workspace, metadata, format }) => ({
.map(({ name, sld_title: sldTitle, title, workspace, metadata, format, canEdit }) => ({
name: parseStyleName({ workspace, name }),
title: sldTitle || title || name,
metadata,
format
format,
canEdit
})), 'name')
.filter(({ name }) => !excluded.includes(name));
}
Expand All @@ -401,6 +402,7 @@ export function getGeoNodeMapLayers(data) {
extra_params: {
msId: layer.id,
styles: cleanStyles(layer?.availableStyles)
.map(({ canEdit, metadata, ...style }) => ({ ...style }))
},
current_style: layer.style || '',
name: layer.name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ describe('Test Resource Utils', () => {
pk: 10,
extra_params: {
msId: '03',
styles: [{ name: 'custom:style', title: 'My Style', format: 'css', metadata: {} }]
styles: [{ name: 'custom:style', title: 'My Style', format: 'css' }]
},
current_style: 'geonode:style',
name: 'geonode:layer'
Expand Down

0 comments on commit 665ca6e

Please sign in to comment.