Skip to content

Commit

Permalink
fix #9071 add advanced options to counter widgets (#9536)
Browse files Browse the repository at this point in the history
* #9071 add advanced options to coutner widgets

* fix retrocompatibility issue with uom
  • Loading branch information
MV88 authored Oct 5, 2023
1 parent c09bf13 commit 2e09d7f
Show file tree
Hide file tree
Showing 9 changed files with 291 additions and 64 deletions.
6 changes: 5 additions & 1 deletion web/client/components/charts/WidgetChart.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,11 @@ export const toPlotly = (props) => {
* @prop {number} [xAxisOpts.nTicks] max number of ticks. Can be used to force to display all labels, instead of skipping.
* @prop {number} [xAxisAngle] the angle, in degrees, of xAxisAngle.
* @prop {object|boolean} [yAxis=true] if false, hide the yAxis. true by default. (should contain future options for yAxis)
* @prop {object} [yAxisOpts] options for yAxis: `type`, `tickPrefix`, `tickPostfix`, `format`, `formula`
* @prop {object} [counterOpts] options for counter widgets that manipulates the value: `tickPrefix`, `tickPostfix`, `format`, `formula`)
* @prop {string} [counterOpts.format] format. See {@link https://d3-wiki.readthedocs.io/zh_CN/master/Formatting/}
* @prop {string} [counterOpts.tickPrefix] the prefix.
* @prop {string} [counterOpts.tickSuffix] the suffix.
* @prop {object} [yAxisOpts] options for yAxis: `type`, `tickPrefix`, `tickPostfix`, `format`, `formula`)
* @prop {string} [yAxisOpts.type] determine the type of the y axis of `date`, `-` (automatic), `log`, `linear`, `category`, `date`.
* @prop {string} [yAxisOpts.format] format for y axis value. See {@link https://d3-wiki.readthedocs.io/zh_CN/master/Formatting/}
* @prop {string} [yAxisOpts.tickPrefix] the prefix on y value
Expand Down
22 changes: 21 additions & 1 deletion web/client/components/widgets/builder/wizard/CounterWizard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import {isNil} from 'lodash';
import React from 'react';
import { compose, lifecycle } from 'recompose';
import PropTypes from 'prop-types';

import loadingEnhancer from '../../../misc/enhancers/loadingState';
import {wizardHandlers} from '../../../misc/wizard/enhancers';
Expand Down Expand Up @@ -70,7 +71,14 @@ const Wizard = wizardHandlers(WizardContainer);


const Preview = enhancePreview(Counter);
const CounterPreview = ({ data = {}, layer, dependencies = {}, valid, setValid = () => { }, hasAggregateProcess }) =>
const CounterPreview = ({
data = {},
layer,
dependencies = {},
valid,
setValid = () => {},
hasAggregateProcess
}) =>
!isCounterOptionsValid(data.options, { hasAggregateProcess })
? <Counter
{...sampleProps}
Expand All @@ -85,6 +93,8 @@ const CounterPreview = ({ data = {}, layer, dependencies = {}, valid, setValid =
dependencies={dependencies}
setValid={setValid}
type={data.type}
counterOpts={data.counterOpts}
formula={data.formula}
legend={data.legend}
layer={data.layer || layer}
filter={data.filter}
Expand Down Expand Up @@ -138,3 +148,13 @@ export default enhanceWizard(({ onChange = () => { }, onFinish = () => { }, setP
setValid={v => setValid(v && isCounterOptionsValid(data.options, { hasAggregateProcess }))} />}
/>
</Wizard>));

CounterPreview.propTypes = {
data: PropTypes.object,
dependencies: PropTypes.object,
hasAggregateProcess: PropTypes.bool,
layer: PropTypes.object,
setValid: PropTypes.func,
valid: PropTypes.bool,
value: PropTypes.string
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,14 @@ import React, { useState } from 'react';
import { isNil } from 'lodash';
import Select from 'react-select';
import { Col, FormGroup, FormControl, ControlLabel } from 'react-bootstrap';
import PropTypes from 'prop-types';

import Message from '../../../../I18N/Message';
import HTML from '../../../../I18N/HTML';

import Slider from '../../../../misc/Slider';
import InfoPopover from '../../../widget/InfoPopover';
import DisposablePopover from '../../../../misc/popover/DisposablePopover';
import FormulaInput from './FormulaInput';

import Format from './Format';
import Formula from './Formula';

import SwitchPanel from '../../../../misc/switch/SwitchPanel';
import SwitchButton from '../../../../misc/switch/SwitchButton';
Expand Down Expand Up @@ -60,7 +59,7 @@ function Header({}) {
</span>);
}

export default function ChartAdvancedOptions({
function ChartAdvancedOptions({
classificationAttribute,
data,
onChange = () => {}
Expand Down Expand Up @@ -132,29 +131,8 @@ export default function ChartAdvancedOptions({
onChange={(val) => { onChange("yAxis", !val); }}
/>
</Col>
<Col componentClass={ControlLabel} sm={12}>
<Message msgId="widgets.advanced.format" />
</Col>
<Col sm={4}>
<ControlLabel>
<Message msgId="widgets.advanced.prefix" />
<FormControl placeholder="e.g.: ~" disabled={data.yAxis === false} value={data?.yAxisOpts?.tickPrefix} type="text" onChange={e => onChange("yAxisOpts.tickPrefix", e.target.value)} />
</ControlLabel>
</Col>
<Col sm={4}>
<ControlLabel>
<Message msgId="widgets.advanced.format" />
</ControlLabel>
<DisposablePopover placement="top" title={<Message msgId="widgets.advanced.examples"/>} text={<HTML msgId="widgets.advanced.formatExamples" />} />
<FormControl placeholder="e.g.: .2s" disabled={data.yAxis === false} value={data?.yAxisOpts?.format} type="text" onChange={e => onChange("yAxisOpts.format", e.target.value)} />
</Col>
<Col sm={4}>
<ControlLabel><Message msgId="widgets.advanced.suffix" /></ControlLabel>
<FormControl placeholder="e.g.: W" disabled={data.yAxis === false} value={data?.yAxisOpts?.tickSuffix} type="text" onChange={e => onChange("yAxisOpts.tickSuffix", e.target.value)} />
</Col>
<Col sm={12}>
<FormulaInput disabled={data.yAxis === false} value={data.formula} type="text" onChange={e => onChange("formula", e.target.value)} />
</Col>
<Format data={data} onChange={onChange}/>
<Formula data={data} onChange={onChange}/>
{/* X AXIS */}
<Col componentClass={"label"} sm={12}>
<Message msgId="widgets.advanced.xAxis" />
Expand Down Expand Up @@ -240,3 +218,11 @@ export default function ChartAdvancedOptions({
</FormGroup>
</SwitchPanel>);
}

ChartAdvancedOptions.propTypes = {
classificationAttribute: PropTypes.string, // [ ] verify is a string
data: PropTypes.object,
onChange: PropTypes.func
};

export default ChartAdvancedOptions;
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2020, 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 } from 'react-bootstrap';
import PropTypes from 'prop-types';

import Message from '../../../../I18N/Message';
import Format from './Format';
import Formula from './Formula';
import SwitchPanel from '../../../../misc/switch/SwitchPanel';

function Header({}) {
return (<span>
<span style={{ cursor: "pointer" }}><Message msgId="widgets.advanced.title"/></span>
</span>);
}

function CounterAdvancedOptions({
data,
onChange = () => {}
}) {
return (<SwitchPanel id="displayCartesian"
header={<Header data={data}/>}
collapsible
expanded={data.panel}
onSwitch={(val) => { onChange("panel", val); }}
>
<FormGroup controlId="AdvancedOptions">
<Format prefix="counterOpts" data={data} onChange={onChange}/>
<Formula data={data} onChange={onChange}/>
</FormGroup>
</SwitchPanel>);
}

CounterAdvancedOptions.propTypes = {
data: PropTypes.object,
onChange: PropTypes.func
};

export default CounterAdvancedOptions;
53 changes: 53 additions & 0 deletions web/client/components/widgets/builder/wizard/common/Format.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright 2023, 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 { Col, FormControl, ControlLabel } from 'react-bootstrap';
import PropTypes from 'prop-types';

import Message from '../../../../I18N/Message';
import HTML from '../../../../I18N/HTML';
import DisposablePopover from '../../../../misc/popover/DisposablePopover';

const Format = ({
data,
onChange = () => {},
prefix = "yAxisOpts"
}) => {

return (
<>
<Col componentClass={ControlLabel} sm={12}>
<Message msgId="widgets.advanced.format" />
</Col>
<Col sm={4}>
<ControlLabel>
<Message msgId="widgets.advanced.prefix" />
<FormControl placeholder="e.g.: ~" disabled={data.yAxis === false} value={data?.[prefix]?.tickPrefix} type="text" onChange={e => onChange(prefix + ".tickPrefix", e.target.value)} />
</ControlLabel>
</Col>
<Col sm={4}>
<ControlLabel>
<Message msgId="widgets.advanced.format" />
</ControlLabel>
<DisposablePopover placement="top" title={<Message msgId="widgets.advanced.examples"/>} text={<HTML msgId="widgets.advanced.formatExamples" />} />
<FormControl placeholder="e.g.: .2s" disabled={data.yAxis === false} value={data?.[prefix]?.format} type="text" onChange={e => onChange(prefix + ".format", e.target.value)} />
</Col>
<Col sm={4}>
<ControlLabel><Message msgId="widgets.advanced.suffix" /></ControlLabel>
<FormControl placeholder="e.g.: W" disabled={data.yAxis === false} value={data?.[prefix]?.tickSuffix || data?.options?.seriesOptions?.[0].uom} type="text" onChange={e => onChange(prefix + ".tickSuffix", e.target.value)} />
</Col>

</>);
};
Format.propTypes = {
data: PropTypes.object,
onChange: PropTypes.func,
prefix: PropTypes.string
};

export default Format;
31 changes: 31 additions & 0 deletions web/client/components/widgets/builder/wizard/common/Formula.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright 2023, 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 PropTypes from 'prop-types';
import { Col } from 'react-bootstrap';

import FormulaInput from './FormulaInput';


const Formula = ({
data,
onChange = () => {}
}) => {
return (
<Col sm={12}>
<FormulaInput disabled={data.yAxis === false} value={data.formula} type="text" onChange={e => onChange("formula", e.target.value)} />
</Col>
);
};

Formula.propTypes = {
data: PropTypes.object,
onChange: PropTypes.func
};

export default Formula;
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,22 @@
import React, {useEffect, useState} from 'react';
import { head, get} from 'lodash';
import { Row, Col, Form, FormGroup, FormControl, ControlLabel, Glyphicon, OverlayTrigger, Tooltip } from 'react-bootstrap';
import Message from '../../../../I18N/Message';
import PropTypes from 'prop-types';
import Select from 'react-select';
import classNames from 'classnames';
import uuid from 'uuid';

import Message from '../../../../I18N/Message';
import ColorRamp from '../../../../styleeditor/ColorRamp';
import { generateRandomHexColor } from '../../../../../utils/ColorUtils';
import Button from '../../../../misc/Button';
import ConfirmModal from '../../../../../components/resources/modals/ConfirmModal';
import StepHeader from '../../../../misc/wizard/StepHeader';
import SwitchButton from '../../../../misc/switch/SwitchButton';
import ChartAdvancedOptions from './ChartAdvancedOptions';
import CounterAdvancedOptions from './CounterAdvancedOptions';
import ColorClassModal from '../chart/ColorClassModal';
import { defaultColorGenerator } from '../../../../charts/WidgetChart';
import classNames from 'classnames';
import uuid from 'uuid';

const DEFAULT_CUSTOM_COLOR_OPTIONS = {
base: 190,
Expand Down Expand Up @@ -101,7 +104,7 @@ const formatAutoColorOptions = (classification, attributeType) => (
))
);

export default ({
const WPSWidgetOptions = ({
hasAggregateProcess,
data = { options: {}, autoColorOptions: {} },
onChange = () => { },
Expand All @@ -116,7 +119,8 @@ export default ({
},
aggregationOptions = [],
sampleChart,
layer }) => {
layer
}) => {

const [showModal, setShowModal] = useState(false);
const [showConfirmModal, setShowConfirmModal] = useState(false);
Expand Down Expand Up @@ -346,12 +350,34 @@ export default ({
</Col>
</FormGroup> : null}
{formOptions.advancedOptions && data.widgetType === "chart" && (data.type === "bar" || data.type === "line")
? <ChartAdvancedOptions data={data} classificationAttribute={classificationAttribute} onChange={onChange} />
? <ChartAdvancedOptions
data={data}
classificationAttribute={classificationAttribute}
onChange={onChange}
/>
: null}
{formOptions.advancedOptions && data.widgetType === "counter"
? <CounterAdvancedOptions
data={data}
onChange={onChange}
/>
: null}

</Form>

</Col>
</Row>
);
};

WPSWidgetOptions.propTypes = {
aggregationOptions: PropTypes.array,
data: PropTypes.object,
formOptions: PropTypes.object,
hasAggregateProcess: PropTypes.bool,
layer: PropTypes.object,
onChange: PropTypes.func,
options: PropTypes.array,
sampleChart: PropTypes.node,
showTitle: PropTypes.bool
};
export default WPSWidgetOptions;
Loading

0 comments on commit 2e09d7f

Please sign in to comment.