Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix #9071 add advanced options to counter widgets #9536

Merged
merged 2 commits into from
Oct 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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