From 829251d80518c16462fc9914f6c28d272423a87b Mon Sep 17 00:00:00 2001
From: esikkala <esko.ikkala@aalto.fi>
Date: Tue, 11 Dec 2018 14:38:55 +0200
Subject: [PATCH] Checkbox facet for source

---
 src/client/components/CheckboxesGroup.js | 73 ++++++++++++++++++++++++
 src/client/components/FacetDialog.js     | 36 +++++++-----
 src/client/components/ResultTableHead.js |  3 +-
 src/client/reducers/facet.js             | 14 ++++-
 src/server/sparql/Datasets.js            |  5 +-
 src/server/sparql/Manuscripts.js         | 16 ++++--
 6 files changed, 120 insertions(+), 27 deletions(-)
 create mode 100644 src/client/components/CheckboxesGroup.js

diff --git a/src/client/components/CheckboxesGroup.js b/src/client/components/CheckboxesGroup.js
new file mode 100644
index 00000000..727360bf
--- /dev/null
+++ b/src/client/components/CheckboxesGroup.js
@@ -0,0 +1,73 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+// import FormLabel from '@material-ui/core/FormLabel';
+import FormControl from '@material-ui/core/FormControl';
+import FormGroup from '@material-ui/core/FormGroup';
+import FormControlLabel from '@material-ui/core/FormControlLabel';
+// import FormHelperText from '@material-ui/core/FormHelperText';
+import Checkbox from '@material-ui/core/Checkbox';
+
+const styles = theme => ({
+  root: {
+    display: 'flex',
+  },
+  formControl: {
+    margin: theme.spacing.unit * 3,
+  },
+});
+
+class CheckboxesGroup extends React.Component {
+
+  constructor(props) {
+    super(props);
+    //console.log(this.props.data)
+    let o = this.props.data.reduce((obj, item) => {
+      obj[item.id] = item;
+      return obj;
+    },{});
+    this.state = o;
+  }
+
+  handleChange = name => event => {
+    const newObj = this.state[name];
+    newObj.selected = event.target.checked;
+    this.props.updateFilter({
+      property: 'source',
+      value: name
+    });
+    this.setState(
+      { [name]: newObj }
+    );
+  };
+
+  render() {
+    const { classes } = this.props;
+    //console.log(this.state)
+    return (
+      <div className={classes.root}>
+        <FormControl component="fieldset" className={classes.formControl}>
+          <FormGroup>
+            {Object.values(this.state).map(o =>
+              <FormControlLabel
+                key={o.id}
+                control={
+                  <Checkbox checked={o.selected == null ? false : o.selected} onChange={this.handleChange(o.id)} value={o.id} />
+                }
+                label={`${o.prefLabel} (${o.instanceCount})`}
+              />
+            )}
+          </FormGroup>
+        </FormControl>
+      </div>
+    );
+  }
+}
+
+CheckboxesGroup.propTypes = {
+  classes: PropTypes.object.isRequired,
+  data: PropTypes.array.isRequired,
+  updateFilter: PropTypes.func.isRequired
+};
+
+export default withStyles(styles)(CheckboxesGroup);
diff --git a/src/client/components/FacetDialog.js b/src/client/components/FacetDialog.js
index 3c0413e7..cec6445a 100644
--- a/src/client/components/FacetDialog.js
+++ b/src/client/components/FacetDialog.js
@@ -9,6 +9,7 @@ import EnhancedTable from './EnhancedTable';
 import CircularProgress from '@material-ui/core/CircularProgress';
 import purple from '@material-ui/core/colors/purple';
 import Typography from '@material-ui/core/Typography';
+import CheckboxesGroup from './CheckboxesGroup';
 
 const styles = () => ({
   dialogPaper: {
@@ -30,19 +31,27 @@ class FacetDialog extends React.Component {
 
   facetRenderer = facetValues => {
     const { activeFacet, facetOptions } = this.props.facet;
-    const hierarchical = facetOptions[activeFacet] == null ? null : facetOptions[activeFacet].hierarchical;
-    if (activeFacet != '' && hierarchical) {
-      return (
-        <Tree
-          data={facetValues}
-          updateFilter={this.props.updateFilter}
-        />
-      );
-    } else if (activeFacet != '') {
-      return <EnhancedTable
-        data={facetValues}
-        updateFilter={this.props.updateFilter}
-      />;
+    const facetType = facetOptions[activeFacet] == null ? null : facetOptions[activeFacet].type;
+    if (activeFacet != '') {
+      switch(facetType) {
+        case 'hierarchical':
+          return (
+            <Tree
+              data={facetValues}
+              updateFilter={this.props.updateFilter}
+            />
+          );
+        case 'table':
+          return <EnhancedTable
+            data={facetValues}
+            updateFilter={this.props.updateFilter}
+          />;
+        case 'checkboxes':
+          return <CheckboxesGroup
+            data={facetValues}
+            updateFilter={this.props.updateFilter}
+          />;
+      }
     } else {
       return '';
     }
@@ -52,7 +61,6 @@ class FacetDialog extends React.Component {
     const { classes, facet } = this.props;
     const label = facet.facetOptions[facet.activeFacet] == null ? '' : facet.facetOptions[facet.activeFacet].label;
     const facetValues = facet.facetValues[facet.activeFacet] == null ? [] : facet.facetValues[facet.activeFacet];
-
     return (
       <Dialog
         classes={{ paper: classes.dialogPaper }}
diff --git a/src/client/components/ResultTableHead.js b/src/client/components/ResultTableHead.js
index 14ed5b91..950fc0e3 100644
--- a/src/client/components/ResultTableHead.js
+++ b/src/client/components/ResultTableHead.js
@@ -68,7 +68,8 @@ const columns = [
   {
     label: 'Source',
     property: 'source',
-    desc: 'Source description'
+    desc: 'Source description',
+    filter: true
   },
 ];
 
diff --git a/src/client/reducers/facet.js b/src/client/reducers/facet.js
index eb0fa072..b9de6d34 100644
--- a/src/client/reducers/facet.js
+++ b/src/client/reducers/facet.js
@@ -12,22 +12,30 @@ export const INITIAL_STATE = {
       id: 'productionPlace',
       label: 'Production place',
       //predicate: defined in backend
-      hierarchical: true,
+      type: 'hierarchical',
     },
     author: {
       id: 'author',
       label: 'Author',
       // predicate: defined in backend
-      hierarchical: false
+      type: 'table'
+    },
+    source: {
+      id: 'source',
+      label: 'Source',
+      // predicate: defined in backend
+      type: 'checkboxes'
     }
   },
   facetValues : {
     productionPlace: [],
-    author: []
+    author: [],
+    source: []
   },
   facetFilters: {
     productionPlace: new Set(),
     author: new Set(),
+    source: new Set(),
   },
   fetchingFacet : false,
   facetDialogOpen: false,
diff --git a/src/server/sparql/Datasets.js b/src/server/sparql/Datasets.js
index bb6f9b0f..f263cc12 100644
--- a/src/server/sparql/Datasets.js
+++ b/src/server/sparql/Datasets.js
@@ -218,9 +218,8 @@ module.exports = {
           {
             ?instance a frbroo:F4_Manifestation_Singleton .
             <FILTER>
-            #?value dct:source mmm-schema:Bodley .
             ?instance <PREDICATE> ?id .
-            ?id dct:source ?source .
+            OPTIONAL { ?id dct:source ?source }
             OPTIONAL { ?id crm:P89_falls_within ?parent_ }
             BIND(COALESCE(?parent_, '0') as ?parent)
           }
@@ -228,8 +227,6 @@ module.exports = {
           ORDER BY DESC(?instanceCount)
         }
         FILTER(BOUND(?id))
-        #<SELECTED_VALUES>
-        #VALUES ?selectedValues { <http://ldf.fi/mmm/place/926> }
         ?id skos:prefLabel ?prefLabel_
         BIND(STR(?prefLabel_) AS ?prefLabel)
       }
diff --git a/src/server/sparql/Manuscripts.js b/src/server/sparql/Manuscripts.js
index f52a03fa..5effa949 100644
--- a/src/server/sparql/Manuscripts.js
+++ b/src/server/sparql/Manuscripts.js
@@ -13,14 +13,20 @@ const facetConfigs = {
     id: 'productionPlace',
     label: 'Production place',
     predicate: '^crm:P108_has_produced/crm:P7_took_place_at',
-    hierarchical: true,
+    type: 'hierarchical',
   },
   author: {
     id: 'author',
     label: 'Author',
     predicate: 'crm:P128_carries/^frbroo:R17_created/frbroo:R19_created_a_realisation_of/^frbroo:R16_initiated/mmm-schema:carried_out_by_as_author',
-    hierarchical: false
-  }
+    type: 'table'
+  },
+  source: {
+    id: 'source',
+    label: 'Source',
+    predicate: 'dct:source',
+    type: 'checkboxes',
+  },
 };
 
 export const getManuscripts = (page, pagesize, filters) => {
@@ -93,8 +99,8 @@ const getFacet = (facetConfig, filters) => {
     facetQuery = facetQuery.replace('<FILTER>', generateFacetFilter(facetConfig, filters));
   }
   facetQuery = facetQuery.replace('<PREDICATE>', facetConfig.predicate);
-  //console.log(facetQuery)
-  let mapper = facetConfig.hierarchical ? mapHierarchicalFacet : makeObjectList;
+  console.log(facetQuery)
+  let mapper = facetConfig.type === 'hierarchical' ? mapHierarchicalFacet : makeObjectList;
   return sparqlSearchEngine.doSearch(facetQuery, endpoint, mapper);
 };
 
-- 
GitLab