Skip to content

Commit

Permalink
geosolutions-it#8588 - Chart switcher for Chart widget (geosolutions-…
Browse files Browse the repository at this point in the history
…it#8684)

(cherry picked from commit 20bba55)
  • Loading branch information
dsuren1 committed Nov 3, 2022
1 parent b23c4fd commit 998f61e
Show file tree
Hide file tree
Showing 64 changed files with 1,847 additions and 363 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/user-guide/img/widgets/chart-options.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/user-guide/img/widgets/widget-options.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 13 additions & 7 deletions docs/user-guide/widgets.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,24 +29,30 @@ From here the user can choose between four different types of widget:

### Chart

Selecting *Chart* option the following window opens:
Charts widget allow multi-selection of layer to create a widget that allows user to configure chart options for each layer. And switch between multiple charts in a widget.

<img src="../img/widgets/chart-types.jpg" class="ms-docimage" style="max-width:450px;"/>
<img src="../img/widgets/chart-layer-selection.jpg" class="ms-docimage" style="max-width:450px;"/>

From here it is possible to choose between *Bar Chart*, *Pie Chart* or *Line Chart*, or simply go back to widget type selection through the <img src="../img/button/back.jpg" class="ms-docbutton"/> button. <br>
If a chart type is selected, it can display similar the following (in this case a *Bar Chart*):
Selecting a *Layer* or *Layers*, the following *Chart* options is presented to user:

<img src="../img/widgets/chart-options.jpg" class="ms-docimage" style="max-width:450px;"/>

<img src="../img/widgets/configure-chart.jpg" class="ms-docimage" style="max-width:450px;"/>
From here it is possible to choose between *Bar Chart*, *Pie Chart* or *Line Chart*, or simply go back to widget type selection through the <img src="../img/button/back.jpg" class="ms-docbutton"/> button. <br>
By default, the bar chart is selected.

From the toolbar of this panel <img src="../img/widgets/widget-options.jpg" class="ms-docbutton"/> the user is allowed to:

* Go back to the chart type selection with the <img src="../img/button/back.jpg" class="ms-docbutton"/> button

* Connect <img src="../img/button/connect-widget.jpg" class="ms-docbutton"/> or disconnect <img src="../img/button/disconnect-widget.jpg" class="ms-docbutton"/> the widget to the map. When a widget is connected to the map, the information displayed in the widget are automatically filtered with the map viewport. When a widget is not linked, it otherwise shows all the elements of that level regardless of the map viewport

* Configure a filter <img src="../img/button/filter-icon.jpg" class="ms-docbutton"/> for the widget data (more information on how to configure a filter can be found in [Filtering Layers](filtering-layers.md#filtering-layers) section)
* Configure a filter <img src="../img/button/filter-icon.jpg" class="ms-docbutton"/> for the widget data (more information on how to configure a filter can be found in [Filtering Layers](filtering-layers.md#filtering-layers) section).

* Add new layers <img src="../img/button/+++.jpg" class="ms-docbutton"/> to existing chart configuration

* Delete the current layer <img src="../img/button/delete_button.jpg" class="ms-docbutton"/> and it's related chart configuration from the wizard

* Move forward <img src="../img/button/next.jpg" class="ms-docbutton"/> to the next step when the settings are completed
* Move forward <img src="../img/button/next.jpg" class="ms-docbutton"/> to the next step when the settings are completed. The button prohibits the user from proceeding further when some chart is invalid

Just below the chart's preview, the following configurations are available:

Expand Down
1 change: 1 addition & 0 deletions web/client/actions/widgets.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export const DEFAULT_TARGET = "floating";
export const DEPENDENCY_SELECTOR_KEY = "dependencySelector";
export const WIDGETS_REGEX = /^widgets\["?([^"\]]*)"?\]\.?(.*)$/;
export const MAPS_REGEX = /^maps\["?([^"\]]*)"?\]\.?(.*)$/;
export const CHARTS_REGEX = /^charts\["?([^"\]]*)"?\]\.?(.*)$/;
export const WIDGETS_MAPS_REGEX = /^widgets\["?([^"\]]*)"?\]\.maps\["?([^"\]]*)"?\]\.?(.*)$/;

export const TOGGLE_COLLAPSE = "WIDGET:TOGGLE_COLLAPSE";
Expand Down
23 changes: 12 additions & 11 deletions web/client/components/catalog/CompactCatalog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ const loadPage = ({text, catalog = {}}, page = 0) => {
.map(({records, result}) => resToProps({records, result, catalog}));
};
const scrollSpyOptions = {querySelector: ".ms2-border-layout-body .ms2-border-layout-content", pageSize: PAGE_SIZE};
const getCatalogItems = (items = [], selected = {}) => items.map(i =>
(i === selected || selected && i && i.record && selected.identifier === i.record?.identifier)
? {...i, selected: true}
: i
);
/**
* Compat catalog : Reusable catalog component, with infinite scroll.
* You can simply pass the catalog to browse and the handler onRecordSelected.
Expand Down Expand Up @@ -116,14 +121,16 @@ export default compose(
.ignoreElements() // don't want to emit props
))),
withPropsOnChange(['selectedService'], props => {
const service = props.services[props.selectedService];
const service = props.services?.[props.selectedService];
if (!isEmpty(service)) {
props.loadFirst({text: props.searchText || "", catalog: service});
}
})
)(({ setSearchText = () => { }, selected, onRecordSelected, loading, searchText, items = [], total, catalog, services, title, showCatalogSelector = true, error,
)(({ setSearchText = () => { }, selected, onRecordSelected, loading, searchText, items = [], total, catalog, services = {}, title, showCatalogSelector = true, error,
onChangeSelectedService = () => {},
selectedService, onChangeCatalogMode = () => {}}) => {
selectedService, onChangeCatalogMode = () => {},
getItems = (_items) => getCatalogItems(_items, selected),
onItemClick = ({record} = {}) => onRecordSelected(record, catalog)}) => {
return (<BorderLayout
className="compat-catalog"
header={<CatalogForm onChangeCatalogMode={onChangeCatalogMode} onChangeSelectedService={onChangeSelectedService}
Expand All @@ -137,15 +144,9 @@ export default compose(
{!isNil(total) ? <span className="res-info"><Message msgId="catalog.pageInfoInfinite" msgParams={{loaded: items.length, total}}/></span> : null}
</div>}>
<SideGrid
items={items.map(i =>
i === selected
|| selected
&& i && i.record
&& selected.identifier === i.record.identifier
? {...i, selected: true}
: i)}
items={getItems(items)}
loading={loading}
error={error}
onItemClick={({record} = {}) => onRecordSelected(record, catalog)}/>
onItemClick={onItemClick}/>
</BorderLayout>);
});
15 changes: 8 additions & 7 deletions web/client/components/misc/wizard/WizardContainer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ class WizardComponent extends React.Component {
onPrevPage: PropTypes.func,
buttonType: PropTypes.node,
onFinish: PropTypes.func,
isStepValid: PropTypes.func
isStepValid: PropTypes.func,
className: PropTypes.string
};
static defaultProps = {
step: 0,
Expand All @@ -50,29 +51,29 @@ class WizardComponent extends React.Component {
renderButtons = () => {
let buttons = [];
const {isStepValid, children = []} = this.props;
const childrenLenght = children.length >= 0 ? children.length : 1;
const childrenLength = children.length >= 0 ? children.length : 1;
if (this.props.hideButtons) return null;
if (this.props.step > 0) {
buttons.push(<Button key="prev" className="ms-wizard-prev" onClick={() => this.props.onPrevPage()} ><Message msgId="wizard.prev" /></Button>);
}
if ( this.props.step >= childrenLenght - 1) {
if ( this.props.step >= childrenLength - 1) {
buttons.push(<Button key="finish" className="ms-wizard-finish" onClick={() => this.props.onFinish()} ><Message msgId="wizard.finish" /></Button>);
} else if (this.props.step < childrenLenght - 1 && childrenLenght > 1) {
} else if (this.props.step < childrenLength - 1 && childrenLength > 1) {
buttons.push(<Button key="next" className="ms-wizard-next" disabled={!isStepValid(this.props.step)} onClick={() => this.props.onNextPage()} ><Message msgId="wizard.next" /></Button>);
}
return buttons;

};
render() {
const children = this.props.children || [];
const childrenLenght = children.length >= 0 ? children.length : 1;
const childrenLength = children.length >= 0 ? children.length : 1;
return (
<div key="wizard-pages" className="ms-wizard map-options">
<div key="wizard-pages" className={`ms-wizard ${this.props.className || ''}`}>
{React.Children.map(children, (child, i) => {
if (i === this.props.step) {
return React.cloneElement(child, {
key: `wizard-component-${i}`,
onNextPage: this.props.step === childrenLenght - 1 ? this.props.onFinish : this.props.onNextPage,
onNextPage: this.props.step === childrenLength - 1 ? this.props.onFinish : this.props.onNextPage,
onPrevPage: this.props.onPrevPage
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@ describe('WidgetsBuilder component', () => {
ReactDOM.render(<WidgetBuilder />, document.getElementById("container"));
const container = document.getElementById('container');
const el = container.querySelector('.ms-wizard');
expect(el).toExist();
expect(container.querySelector('.chart-options-form')).toNotExist();
expect(el).toBeTruthy();
});
it('WidgetsBuilder rendering chart options', () => {
ReactDOM.render(<WidgetBuilder step={1} />, document.getElementById("container"));
ReactDOM.render(<WidgetBuilder step={0} />, document.getElementById("container"));
const container = document.getElementById('container');
const el = container.querySelector('.chart-options-form');
expect(el).toExist();
const elChartOption = container.querySelector('.chart-options');
expect(elChartOption).toBeTruthy();
const elChartOptionForm = container.querySelector('.chart-options-form');
expect(elChartOptionForm).toBeTruthy();
});
});
Loading

0 comments on commit 998f61e

Please sign in to comment.