terriajs
Version:
Geospatial data visualization platform.
209 lines (178 loc) • 8.21 kB
JSX
import React from 'react';
import createReactClass from 'create-react-class';
import PropTypes from 'prop-types';
import defined from 'terriajs-cesium/Source/Core/defined';
import knockout from 'terriajs-cesium/Source/ThirdParty/knockout';
import VarType from '../../Map/VarType';
import ObserveModelMixin from '../ObserveModelMixin';
import CatalogItem from '../DataCatalog/CatalogItem';
import CatalogGroup from '../DataCatalog/CatalogGroup';
import Styles from './parameter-editors.scss';
const RegionDataParameterEditor = createReactClass({
displayName: 'RegionDataParameterEditor',
mixins: [ObserveModelMixin],
propTypes: {
previewed: PropTypes.object,
parameter: PropTypes.object
},
/* eslint-disable-next-line camelcase */
UNSAFE_componentWillMount() {
this.catalogItemDetails = {};
},
/* eslint-disable-next-line camelcase */
UNSAFE_componentWillReceiveProps(nextProps) {
this.catalogItemDetails = {};
},
getValue() {
return this.props.parameter.value;
},
setValue(value) {
this.props.parameter.value = value;
},
regionProvider() {
return this.props.parameter.regionProvider;
},
catalogItemsWithMatchingRegion() {
return this.props.parameter.getEnabledItemsWithMatchingRegionType();
},
toggleActive(catalogItem, column) {
const value = this.getValue();
const newValue = !this.isActive(catalogItem, column);
if (newValue) {
value[column.name] = {
regionProvider: this.regionProvider(),
regionColumn: catalogItem.regionMapping.tableStructure.getColumnWithNameOrId(catalogItem.regionMapping.regionDetails[0].columnName),
valueColumn: column
};
// If only one dataset can be active at a time, deactivate all others.
if (this.props.parameter.singleSelect) {
for (const columnName in value) {
if (value.hasOwnProperty(columnName) && columnName !== column.name) {
value[columnName] = false;
}
}
}
} else {
value[column.name] = false;
this.getCatalogItemDetails(this.catalogItemDetails, catalogItem).isEntirelyActive = false;
}
},
isActive(catalogItem, column) {
let value = this.getValue();
if (!defined(value)) {
value = {};
this.setValue(value);
}
if (!defined(value[column.name])) {
value[column.name] = false;
knockout.track(value, [column.name]);
if (!this.props.parameter.singleSelect || Object.keys(value).length === 1) {
value[column.name] = {
regionProvider: this.regionProvider(),
regionColumn: catalogItem.regionMapping.tableStructure.getColumnWithNameOrId(catalogItem.regionMapping.regionDetails[0].columnName),
valueColumn: column
};
}
}
return defined(value[column.name]) &&
value[column.name] &&
value[column.name].regionColumn === catalogItem.regionMapping.tableStructure.getColumnWithNameOrId(catalogItem.regionMapping.regionDetails[0].columnName) &&
value[column.name].valueColumn === column;
},
getCatalogItemDetails(catalogItemDetails, catalogItem) {
if (!defined(catalogItemDetails[catalogItem.uniqueId])) {
catalogItemDetails[catalogItem.uniqueId] = {
isOpen: true,
isEntirelyActive: true
};
knockout.track(catalogItemDetails, [catalogItem.uniqueId]);
knockout.track(catalogItemDetails[catalogItem.uniqueId], ['isOpen', 'isEntirelyActive']);
}
return catalogItemDetails[catalogItem.uniqueId];
},
toggleEntireCatalogItem(catalogItem) {
const details = this.getCatalogItemDetails(this.catalogItemDetails, catalogItem);
details.isEntirelyActive = !details.isEntirelyActive;
const columns = catalogItem.regionMapping.tableStructure.columns;
for (let i = 0; i < columns.length; ++i) {
const column = columns[i];
if (this.columnIsScalar(catalogItem, column)) {
const isActive = this.isActive(catalogItem, column);
if ((!isActive && details.isEntirelyActive) || (isActive && !details.isEntirelyActive)) {
this.toggleActive(catalogItem, column);
}
}
}
},
catalogItemIsOpen(catalogItem) {
const details = this.getCatalogItemDetails(this.catalogItemDetails, catalogItem);
return details.isOpen;
},
toggleOpenCatalogItem(catalogItem) {
const details = this.getCatalogItemDetails(this.catalogItemDetails, catalogItem);
details.isOpen = !details.isOpen;
},
isEntireCatalogItemActive(catalogItem) {
const details = this.getCatalogItemDetails(this.catalogItemDetails, catalogItem);
return details.isEntirelyActive;
},
render() {
return (
<div className={Styles.parameterEditor}>
{this.renderContent()}
</div>
);
},
renderContent() {
if (this.catalogItemsWithMatchingRegion().length > 0) {
return (
<div className={Styles.data}>
<ul className={Styles.tree}>
<For each="catalogItem" index="i" of={this.catalogItemsWithMatchingRegion()}>
<CatalogGroup
key={catalogItem.uniqueId}
text={catalogItem.name}
topLevel={false}
open={this.catalogItemIsOpen(catalogItem)}
onClick={this.toggleOpenCatalogItem.bind(this, catalogItem)}
loading={false}>
{this.renderItemChildren(catalogItem)}
</CatalogGroup>
</For>
</ul>
</div>
);
}
return (
// Don't break the lines around the link to csv-geo-au, or whitespace stripping will ruin the formatting in
// the rendered version.
<div className={Styles.parameterEditorImportantNote}>
No characteristics are available because you have not added any data to the map for this region
type, {this.regionProvider() ? this.regionProvider().regionType : 'None'}.
You may use your own data with this analysis by creating a CSV following the <a target="_blank" rel="noopener noreferrer" href="https://github.com/TerriaJS/nationalmap/wiki/csv-geo-au">csv-geo-au</a> guidelines
and dragging and dropping it onto the map.
</div>
);
},
renderItemChildren(catalogItem) {
return (
<ul className={Styles.tree}>
{catalogItem.regionMapping.tableStructure.columns.map((column, i)=> {
if (column.type === VarType.SCALAR) {
return (
<CatalogItem
key={column.id}
onTextClick={this.toggleActive.bind(this, catalogItem, column)}
selected={this.isActive(catalogItem, column)}
text={column.name}
onBtnClick={this.toggleActive.bind(this, catalogItem, column)}
btnState={this.isActive(catalogItem, column) ? 'remove' : 'add'}
/>
);
}
})}
</ul>
);
},
});
module.exports = RegionDataParameterEditor;