From 50a6695ef62d60bc213b62192d2bb2c960944923 Mon Sep 17 00:00:00 2001 From: esikkala <esko.ikkala@aalto.fi> Date: Mon, 6 May 2019 18:28:05 +0300 Subject: [PATCH] Simplify facet updates --- .../components/facet_bar/ActiveFilters.js | 7 +- src/client/components/facet_bar/ChipsArray.js | 12 ++- src/client/components/facet_bar/FacetBar.js | 11 ++- .../{Tree.js => HierarchicalFacet.js} | 85 +++++++++++-------- src/client/reducers/helpers.js | 10 ++- src/client/reducers/manuscriptsFacets.js | 36 ++++---- 6 files changed, 94 insertions(+), 67 deletions(-) rename src/client/components/facet_bar/{Tree.js => HierarchicalFacet.js} (85%) diff --git a/src/client/components/facet_bar/ActiveFilters.js b/src/client/components/facet_bar/ActiveFilters.js index 3ba78f44..d8bec99b 100644 --- a/src/client/components/facet_bar/ActiveFilters.js +++ b/src/client/components/facet_bar/ActiveFilters.js @@ -8,15 +8,12 @@ const ActiveFilters = props => { <React.Fragment> {Object.keys(uriFilters).map(facetID => { const facetValues = []; - Object.entries(uriFilters[facetID]).forEach(([ key, value]) => { + Object.values(uriFilters[facetID]).forEach(value => { facetValues.push({ facetID: facetID, facetLabel: facets[facetID].label, filterType: 'uriFilter', - value: { - id: key, - label: value.length > 18 ? `${value.substring(0, 18)}...` : value, - } + value: value // a react sortable tree object }); }); return ( diff --git a/src/client/components/facet_bar/ChipsArray.js b/src/client/components/facet_bar/ChipsArray.js index 1512deb9..332b7876 100644 --- a/src/client/components/facet_bar/ChipsArray.js +++ b/src/client/components/facet_bar/ChipsArray.js @@ -21,10 +21,16 @@ class ChipsArray extends React.Component { facetClass: this.props.facetClass, facetID: data.facetID, option: data.filterType, - value: data.value + value: data.value // a react sortable tree object }); }; + generateLabel = (facetLabel, valueLabel) => { + return valueLabel.length > 18 + ? `${facetLabel}: ${valueLabel.substring(0, 18)}...` + : `${facetLabel}: ${valueLabel}`; + } + render() { const { classes, data } = this.props; return ( @@ -33,9 +39,9 @@ class ChipsArray extends React.Component { let icon = null; return ( <Chip - key={item.value.id} + key={item.value.node.id} icon={icon} - label={`${item.facetLabel.toLowerCase()}: ${item.value.label}`} + label={this.generateLabel(item.facetLabel, item.value.node.prefLabel)} onDelete={this.handleDelete(item)} className={classes.chip} /> diff --git a/src/client/components/facet_bar/FacetBar.js b/src/client/components/facet_bar/FacetBar.js index def6e3ae..cdbf8f67 100644 --- a/src/client/components/facet_bar/FacetBar.js +++ b/src/client/components/facet_bar/FacetBar.js @@ -2,7 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { has } from 'lodash'; import { withStyles } from '@material-ui/core/styles'; -import Tree from './Tree'; +import HierarchicalFacet from './HierarchicalFacet'; import DateSlider from './slider/DateSlider'; import Paper from '@material-ui/core/Paper'; import FacetHeader from './FacetHeader'; @@ -60,12 +60,13 @@ class FacetBar extends React.Component { render() { const { classes, facetClass } = this.props; - const { facetUpdateID, updatedFacet, facets } = this.props.facetData; + const { facetUpdateID, updatedFacet, updatedFilter, facets } = this.props.facetData; let uriFilters = {}; let spatialFilters = {}; let activeUriFilters = false; let activeSpatialFilters = false; for (const [key, value] of Object.entries(facets)) { + // if (value.uriFilter !== null) { activeUriFilters = true; uriFilters[key] = value.uriFilter; @@ -113,14 +114,16 @@ class FacetBar extends React.Component { updateFacetOption={this.props.updateFacetOption} /> <div className={classes[facets[id].containerClass]}> - {facets[id].filterType === 'uriFilter' || facets[id].filterType === 'spatialFilter' ? - <Tree + {facets[id].filterType === 'uriFilter' + || facets[id].filterType === 'spatialFilter' ? + <HierarchicalFacet facetID={id} facet={facets[id]} facetClass={this.props.facetClass} resultClass={this.props.resultClass} facetUpdateID={facetUpdateID} updatedFacet={updatedFacet} + updatedFilter={updatedFilter} fetchFacet={this.props.fetchFacet} updateFacetOption={this.props.updateFacetOption} /> : diff --git a/src/client/components/facet_bar/Tree.js b/src/client/components/facet_bar/HierarchicalFacet.js similarity index 85% rename from src/client/components/facet_bar/Tree.js rename to src/client/components/facet_bar/HierarchicalFacet.js index b72fdc45..b440cb62 100644 --- a/src/client/components/facet_bar/Tree.js +++ b/src/client/components/facet_bar/HierarchicalFacet.js @@ -12,7 +12,6 @@ import IconButton from '@material-ui/core/IconButton'; import NavigateNextIcon from '@material-ui/icons/NavigateNext'; import NavigateBeforeIcon from '@material-ui/icons/NavigateBefore'; import Typography from '@material-ui/core/Typography'; -import ChipsArray from './ChipsArray'; const styles = () => ({ facetSearchContainer: { @@ -64,7 +63,7 @@ const styles = () => ({ This component is based on the React Sortable Tree example at: https://frontend-collective.github.io/react-sortable-tree/storybook/?selectedKind=Basics&selectedStory=Search&full=0&addons=0&stories=1&panelRight=0 */ -class Tree extends Component { +class HierarchicalFacet extends Component { constructor(props) { super(props); this.state = { @@ -85,23 +84,32 @@ class Tree extends Component { } componentDidUpdate = prevProps => { - // if (this.props.facetID === 'productionPlace') { - // console.log(this.props.facet.values) - // } - if (prevProps.facet.values != this.props.facet.values) { - this.setState({ - treeData: this.props.facet.values - }); - } - if (this.props.updatedFacet !== null - && this.props.updatedFacet !== this.props.facetID - && prevProps.facetUpdateID !== this.props.facetUpdateID) { - this.props.fetchFacet({ - facetClass: this.props.facetClass, - facetID: this.props.facetID, - }); + if (prevProps.facetUpdateID !== this.props.facetUpdateID) { + // update component state if the user modified this facet + if (this.props.updatedFacet === this.props.facetID ) { + const treeObj = this.props.updatedFilter; + const newTreeData = changeNodeAtPath({ + treeData: this.state.treeData, + getNodeKey: ({ treeIndex }) => treeIndex, + path: treeObj.path, + newNode: { + ...treeObj.node, + selected: treeObj.added ? 'true' : 'false' + }, + }); + this.setState({ treeData: newTreeData }); + } + // else fetch new values, because some other facet was updated + else { + this.props.fetchFacet({ + facetClass: this.props.facetClass, + facetID: this.props.facetID, + }); + } } + + // fetch new values if the user changes the filter type or sort order if (prevProps.facet.filterType !== this.props.facet.filterType && this.props.facet.filterType === 'uriFilter') { this.props.fetchFacet({ @@ -115,27 +123,21 @@ class Tree extends Component { facetID: this.props.facetID, }); } + + // when values have been fetched, update component's state + if (prevProps.facet.values != this.props.facet.values) { + this.setState({ + treeData: this.props.facet.values + }); + } } - handleCheckboxChange = treeObj => event => { - const newTreeData = changeNodeAtPath({ - treeData: this.state.treeData, - getNodeKey: ({ treeIndex }) => treeIndex, - path: treeObj.path, - newNode: { - ...treeObj.node, - selected: event.target.checked ? 'true' : 'false' - }, - }); - this.setState({ treeData: newTreeData }); + handleCheckboxChange = treeObj => () => { this.props.updateFacetOption({ facetClass: this.props.facetClass, facetID: this.props.facetID, option: this.props.facet.filterType, - value: { - id: treeObj.node.id, - label: treeObj.node.prefLabel - } + value: treeObj }); }; @@ -168,6 +170,15 @@ class Tree extends Component { generateLabel = node => { let count = node.totalInstanceCount == null || node.totalInstanceCount == 0 ? node.instanceCount : node.totalInstanceCount; + + if (node.noHits === 'true' || Array.isArray(node.noHits)) { + if (Array.isArray(node.instanceCount) ) { + count = Math.min(...node.instanceCount); + } else { + count = 0; + } + } + return ( <React.Fragment> <a @@ -203,6 +214,10 @@ class Tree extends Component { const { classes, facet } = this.props; const { isFetching, searchField } = facet; + // if (this.props.facetID == 'owner') { + // console.log(this.state.treeData) + // } + // Case insensitive search of `node.title` const customSearchMethod = ({ node, searchQuery }) => { let prefLabel = Array.isArray(node.prefLabel) ? node.prefLabel[0] : node.prefLabel; @@ -226,7 +241,6 @@ class Tree extends Component { : 0, }); - //<ChipsArray data={this.props.facet.uriFilter} />} return ( <React.Fragment> {isFetching ? @@ -302,7 +316,7 @@ class Tree extends Component { } } -Tree.propTypes = { +HierarchicalFacet.propTypes = { classes: PropTypes.object.isRequired, facetID: PropTypes.string.isRequired, facet: PropTypes.object.isRequired, @@ -311,7 +325,8 @@ Tree.propTypes = { fetchFacet: PropTypes.func, updateFacetOption: PropTypes.func, facetUpdateID: PropTypes.number, + updatedFilter: PropTypes.object, updatedFacet: PropTypes.string, }; -export default withStyles(styles)(Tree); +export default withStyles(styles)(HierarchicalFacet); diff --git a/src/client/reducers/helpers.js b/src/client/reducers/helpers.js index 2d4a68eb..9f6b9d08 100644 --- a/src/client/reducers/helpers.js +++ b/src/client/reducers/helpers.js @@ -70,13 +70,16 @@ const updateFacetFilter = (state, action) => { let newFacet = {}; if (oldFacet.filterType === 'uriFilter') { let newUriFilter = oldFacet.uriFilter == null ? {} : oldFacet.uriFilter; - if (has(newUriFilter, value.id)) { - delete newUriFilter[value.id]; + // 'value' is a react sortable tree object + if (has(newUriFilter, value.node.id)) { + value.added = false; + delete newUriFilter[value.node.id]; if (isEmpty(newUriFilter)) { newUriFilter = null; } } else { - newUriFilter[value.id] = value.label; + value.added = true; + newUriFilter[value.node.id] = value; } newFacet = { ...state.facets[facetID], @@ -92,6 +95,7 @@ const updateFacetFilter = (state, action) => { ...state, updatedFacet: facetID, facetUpdateID: ++state.facetUpdateID, + updatedFilter: value, // a react sortable tree object facets: { ...state.facets, [ facetID ]: newFacet diff --git a/src/client/reducers/manuscriptsFacets.js b/src/client/reducers/manuscriptsFacets.js index bcca7273..2d80f22d 100644 --- a/src/client/reducers/manuscriptsFacets.js +++ b/src/client/reducers/manuscriptsFacets.js @@ -14,6 +14,7 @@ import { export const INITIAL_STATE = { updatedFacet: null, facetUpdateID: 0, + updatedFilter: null, facets: { source: { id: 'source', @@ -68,23 +69,23 @@ export const INITIAL_STATE = { // startValue: null, // endValue: null // }, - author: { - id: 'author', - label: 'Author', - // predicate: defined in backend - distinctValueCount: 0, - values: [], - flatValues: [], - sortBy: 'prefLabel', - sortDirection: 'asc', - sortButton: true, - spatialFilterButton: false, - isFetching: false, - searchField: true, - containerClass: 'ten', - filterType: 'uriFilter', - uriFilter: null - }, + // author: { + // id: 'author', + // label: 'Author', + // // predicate: defined in backend + // distinctValueCount: 0, + // values: [], + // flatValues: [], + // sortBy: 'prefLabel', + // sortDirection: 'asc', + // sortButton: true, + // spatialFilterButton: false, + // isFetching: false, + // searchField: true, + // containerClass: 'ten', + // filterType: 'uriFilter', + // uriFilter: null + // }, owner: { id: 'owner', label: 'Owner', @@ -125,6 +126,7 @@ const manuscriptsFacets = (state = INITIAL_STATE, action) => { case UPDATE_FACET_VALUES: return updateFacetValues(state, action); case UPDATE_FACET_OPTION: + // console.log(action) return updateFacetOption(state, action); default: return state; -- GitLab