diff --git a/example.config.js b/example.config.js index ac443c1..8b0e1ed 100644 --- a/example.config.js +++ b/example.config.js @@ -26,6 +26,7 @@ module.exports = { USE_CATEGORIES: true, CATEGORIES_AS_FILTERS: true, USE_ASSOCIATIONS: true, + USE_ASSOCIATION_DESCRIPTIONS: true, USE_SOURCES: true, USE_COVER: true, USE_SEARCH: false, diff --git a/src/common/utilities.js b/src/common/utilities.js index 2dd4339..acc2f03 100644 --- a/src/common/utilities.js +++ b/src/common/utilities.js @@ -199,18 +199,18 @@ export function binarySearch (ar, el, compareFn) { return -m - 1 } -export const isFilterLeaf = node => (Object.keys(node.children).length === 0) -export const isFilterDuplicate = (node, set) => { return (set.has(node.key)) } +// export const isFilterLeaf = node => (Object.keys(node.children).length === 0) +// export const isFilterDuplicate = (node, set) => { return (set.has(node.key)) } -export function findDescriptionInFilterTree (key, node) { - if (node.key === key) return node.description - if (isFilterLeaf(node)) return false - const descs = Object.keys(node.children) - .map(c => findDescriptionInFilterTree(key, node.children[c])) - .filter(v => !!v) - if (descs.length !== 1) return false - return descs[0] -} +// export function findDescriptionInFilterTree (key, node) { +// if (node.key === key) return node.description +// if (isFilterLeaf(node)) return false +// const descs = Object.keys(node.children) +// .map(c => findDescriptionInFilterTree(key, node.children[c])) +// .filter(v => !!v) +// if (descs.length !== 1) return false +// return descs[0] +// } export function makeNiceDate (datetime) { if (datetime === null) return null diff --git a/src/components/Layout.js b/src/components/Layout.js index e6c794b..2edd211 100644 --- a/src/components/Layout.js +++ b/src/components/Layout.js @@ -40,7 +40,8 @@ class Dashboard extends React.Component { componentDidMount () { if (!this.props.app.isMobile) { this.props.actions.fetchDomain() - .then(domain => this.props.actions.updateDomain({ + .then(domain => + this.props.actions.updateDomain({ domain, features: this.props.features })) diff --git a/src/reducers/validate/validators.js b/src/reducers/validate/validators.js index 8486ea3..4cd1911 100644 --- a/src/reducers/validate/validators.js +++ b/src/reducers/validate/validators.js @@ -29,46 +29,62 @@ function isValidDate (d) { * Traverse a filter tree and check its duplicates. Also recompose as * description if `features.USE_ASSOCIATION_DESCRIPTIONS` is true. */ -function validateFilterTree (node, parent, set, duplicates, hasFilterDescriptions) { - if (hasFilterDescriptions) { - if (node.key === '_root') { - node.isDescription = true // setting first set of nodes to values - } else if (!parent.isDescription) { - node.isDescription = true - } else { - node.isDescription = false - } +// function validateFilterTree (node, parent, set, duplicates, hasAssociationDescriptions) { +// if (hasAssociationDescriptions) { +// if (node.key === '_root') { +// node.isDescription = true // setting first set of nodes to values +// } else if (!parent.isDescription) { +// node.isDescription = true +// } else { +// node.isDescription = false +// } - if (node.isDescription && node.key !== 'root') { - parent.description = node.key - parent.children = node.children - delete parent.isDescription - } - if (isFilterLeaf(node)) { - delete parent.isDescription - } - } +// if (node.isDescription && node.key !== 'root') { +// parent.description = node.key +// parent.children = node.children +// delete parent.isDescription +// } +// if (isFilterLeaf(node)) { +// delete parent.isDescription +// } +// } - if (typeof (node) !== 'object' || typeof (node.children) !== 'object') { - return - } - // If it's a leaf, check that it's not duplicate - if (isFilterLeaf(node)) { - if (isFilterDuplicate(node, set)) { +// if (typeof (node) !== 'object' || typeof (node.children) !== 'object') { +// return +// } +// // If it's a leaf, check that it's not duplicate +// if (isFilterLeaf(node)) { +// if (isFilterDuplicate(node, set)) { +// duplicates.push({ +// id: node.key, +// error: makeError('Filters', node.key, 'filter was found more than once in hierarchy. Ignoring duplicate.') +// }) +// delete parent.children[node.key] +// } else { +// set.add(node.key) +// } +// } else { +// // If it's not a leaf, simply keep going +// Object.values(node.children).forEach((childNode) => { +// validateFilterTree(childNode, node, set, duplicates, hasAssociationDescriptions) +// }) +// } +// } + +function findDuplicateAssociations (associations) { + const seenSet = new Set([]) + const duplicates = [] + associations.forEach(item => { + if (seenSet.has(item.id)) { duplicates.push({ - id: node.key, - error: makeError('Filters', node.key, 'filter was found more than once in hierarchy. Ignoring duplicate.') + id: item.id, + error: makeError('Association', item.id, 'association was found more than once. Ignoring duplicate.') }) - delete parent.children[node.key] } else { - set.add(node.key) + seenSet.add(item.id) } - } else { - // If it's not a leaf, simply keep going - Object.values(node.children).forEach((childNode) => { - validateFilterTree(childNode, node, set, duplicates, hasFilterDescriptions) - }) - } + }) + return duplicates } /* @@ -162,10 +178,10 @@ export function validateDomain (domain, features) { ) // Validate uniqueness of associations - const associationSet = new Set([]) - const duplicateAssociations = [] - validateFilterTree(domain.associations, {}, associationSet, duplicateAssociations, features.USE_ASSOCIATION_DESCRIPTIONS) - + // const associationSet = new Set([]) + // const duplicateAssociations = [] + // validateFilterTree(domain.associations, {}, associationSet, duplicateAssociations, features.USE_ASSOCIATION_DESCRIPTIONS) + const duplicateAssociations = findDuplicateAssociations(domain.associations) // Duplicated associations if (duplicateAssociations.length > 0) { sanitizedDomain.notifications.push({ diff --git a/src/store/initial.js b/src/store/initial.js index 0b6f8e0..8b6d345 100644 --- a/src/store/initial.js +++ b/src/store/initial.js @@ -6,17 +6,16 @@ const initial = { * The Domain or 'domain' of this state refers to the tree of data * available for render and display. * Selections and filters in the 'app' subtree will operate the domain - * in mapStateToProps of the Dashboard, and deterimne which items + * in mapStateToProps of the Dashboard, and determine which items * in the domain will get rendered by React */ domain: { events: [], - narratives: [], locations: [], categories: [], + associations: [], sources: {}, sites: [], - filters: {}, notifications: [] }, @@ -24,7 +23,7 @@ const initial = { * The 'app' subtree of this state determines the data and information to be * displayed. * It may refer to those the user interacts with, by selecting, - * fitlering and so on, which ultimately operate on the data to be displayed. + * filtering and so on, which ultimately operate on the data to be displayed. * Additionally, some of the 'app' flags are determined by the config file * or by the characteristics of the client, browser, etc. */ @@ -137,12 +136,11 @@ const initial = { features: { USE_COVER: false, - USE_FILTERS: false, + USE_ASSOCIATIONS: false, USE_SEARCH: false, USE_SITES: false, USE_SOURCES: false, USE_SHAPES: false, - USE_NARRATIVES: false, GRAPH_NONLOCATED: false, HIGHLIGHT_GROUPS: false }