From c0cb2c3549a18dd4ed1fa7c09b6cf779dd239b17 Mon Sep 17 00:00:00 2001
From: Esko Ikkala <esko.ikkala@aalto.fi>
Date: Fri, 28 Sep 2018 16:43:12 +0300
Subject: [PATCH] Adjust layout, link to sdbm places and names, update
 selectors

---
 src/client/components/VirtualizedTable.js | 96 ++++++++++++++---------
 src/client/components/map/LeafletMap.js   |  4 +-
 src/client/containers/MapApp.js           | 24 +++---
 src/client/reducers/search.js             | 12 ++-
 src/client/selectors/index.js             |  4 +-
 src/server/sparql/Datasets.js             |  8 +-
 src/server/sparql/Mappers.js              | 21 ++++-
 7 files changed, 100 insertions(+), 69 deletions(-)

diff --git a/src/client/components/VirtualizedTable.js b/src/client/components/VirtualizedTable.js
index 7b129fa2..fac86f31 100644
--- a/src/client/components/VirtualizedTable.js
+++ b/src/client/components/VirtualizedTable.js
@@ -84,41 +84,64 @@ class VirtualizedTable extends React.PureComponent {
     this._sort = this._sort.bind(this);
   }
 
-  render() {
-    const { classes, list } = this.props;
-    const rowGetter = ({index}) => this._getDatum(list, index);
+  idRenderer = ({cellData, rowData}) => {
+    if (cellData == null) return '';
+    let sdbmUrl = '';
+    let id = '';
+    if (rowData.manuscriptRecord == '-') {
+      id = cellData.replace('orphan_', '');
+      sdbmUrl = 'https://sdbm.library.upenn.edu/entries/' + id;
+    } else {
+      id = cellData;
+      sdbmUrl = rowData.manuscriptRecord;
+    }
+    id = id.replace('part_', '');
+    const idLink = <a target='_blank' rel='noopener noreferrer' href={sdbmUrl}>{id}</a>;
+    return (
+      <div key={cellData}>
+        {idLink}
+      </div>
+    );
+  };
 
-    const idRenderer = ({cellData, rowData}) => {
-      if (cellData == null) return '';
-      let sdbmUrl = '';
-      let id = '';
-      if (rowData.manuscriptRecord == '-') {
-        id = cellData.replace('orphan_', '');
-        sdbmUrl = 'https://sdbm.library.upenn.edu/entries/' + id;
-      } else {
-        id = cellData;
-        sdbmUrl = rowData.manuscriptRecord;
-      }
-      id = id.replace('part_', '');
-      const idLink = <a target='_blank' rel='noopener noreferrer' href={sdbmUrl}>{id}</a>;
+  objectListRenderer = ({cellData}) => {
+    if (cellData == null || cellData === '-' ) {
+      return ( <div key={cellData}>{'-'}</div>
+      );
+    } else {
       return (
         <div key={cellData}>
-          {idLink}
+          {cellData.map((item, i) => <span key={i}>
+            {!!i && <br />}
+            <a target='_blank' rel='noopener noreferrer'
+              href={'https://sdbm.library.upenn.edu/' + item.sdbmType + '/' + item.id}>{item.prefLabel}
+            </a>
+          </span>)}
         </div>
       );
-    };
+    }
+  };
 
-    const valueFromArray = (property, rowData) => {
-      if (rowData[property] === '-') {
-        return rowData[property];
-      } else {
-        return rowData[property].map((item => item.split(';')[1])).join(' | ');
-      }
-    };
+  stringListRenderer = ({cellData}) => {
+    if (cellData == null || cellData === '-' ) {
+      return ( <div key={cellData}>{'-'}</div>
+      );
+    } else {
+      return (
+        <div key={cellData}>
+          {cellData.map((item, i) => <span key={i}>
+            {!!i && <br />}
+            {item}
+          </span>)}
+        </div>
+      );
+    }
+  };
 
 
-    // sort={this._sort}
-    // sortBy={this.props.search.sortBy}
+  render() {
+    const { classes, list } = this.props;
+    const rowGetter = ({index}) => this._getDatum(list, index);
 
     return (
       <div className={classes.root}>
@@ -132,10 +155,9 @@ class VirtualizedTable extends React.PureComponent {
                 {({ height, width }) => (
                   <Table
                     overscanRowCount={10}
-                    rowHeight={40}
+                    rowHeight={150}
                     rowGetter={rowGetter}
                     rowCount={this.props.list.size}
-
                     sortDirection={this.props.search.sortDirection.toUpperCase()}
                     width={width}
                     height={height}
@@ -148,28 +170,28 @@ class VirtualizedTable extends React.PureComponent {
                       label="ID"
                       cellDataGetter={({rowData}) => rowData.id.replace('http://ldf.fi/mmm/manifestation_singleton/', '')}
                       dataKey="id"
-                      cellRenderer={idRenderer}
+                      cellRenderer={this.idRenderer}
                       width={70}
                     />
                     <Column
                       label="Title"
                       cellDataGetter={({rowData}) => rowData.prefLabel}
                       dataKey="prefLabel"
-
-                      width={300}
+                      cellRenderer={this.stringListRenderer}
+                      width={400}
                     />
                     <Column
                       label="Author"
-                      cellDataGetter={({rowData}) => valueFromArray('author', rowData)}
+                      cellDataGetter={({rowData}) => rowData.author}
                       dataKey="author"
-
+                      cellRenderer={this.objectListRenderer}
                       width={300}
                     />
                     <Column
                       label="Creation place"
-                      cellDataGetter={({rowData}) => valueFromArray('creationPlace', rowData)}
+                      cellDataGetter={({rowData}) => rowData.creationPlace}
                       dataKey="creationPlace"
-
+                      cellRenderer={this.objectListRenderer}
                       width={300}
                     />
                   </Table>
@@ -225,7 +247,7 @@ VirtualizedTable.propTypes = {
   classes: PropTypes.object.isRequired,
   list: PropTypes.instanceOf(Immutable.List).isRequired,
   search: PropTypes.object.isRequired,
-  resultValues: PropTypes.object.isRequired,
+  manuscriptsPropertyValues: PropTypes.object.isRequired,
   sortResults: PropTypes.func.isRequired,
   updateResultsFilter: PropTypes.func.isRequired,
   updateQuery: PropTypes.func.isRequired,
diff --git a/src/client/components/map/LeafletMap.js b/src/client/components/map/LeafletMap.js
index a2232403..58d00fc1 100644
--- a/src/client/components/map/LeafletMap.js
+++ b/src/client/components/map/LeafletMap.js
@@ -68,8 +68,8 @@ class LeafletMap extends React.Component {
 
     // create map
     this.leafletMap = L.map('map', {
-      center: [42.94, 20.57],
-      zoom: 2,
+      center: [22.43,10.37],
+      zoom: 3,
       layers: [
         OSMBaseLayer,
         this.resultMarkerLayer,
diff --git a/src/client/containers/MapApp.js b/src/client/containers/MapApp.js
index b35fb14b..9fa22fcc 100644
--- a/src/client/containers/MapApp.js
+++ b/src/client/containers/MapApp.js
@@ -15,7 +15,7 @@ import CircularProgress from '@material-ui/core/CircularProgress';
 import purple from '@material-ui/core/colors/purple';
 
 import {
-  //getVisibleResults,
+  getVisibleResults,
   getVisibleValues
 } from '../selectors';
 
@@ -71,7 +71,7 @@ const styles = theme => ({
 
   },
   resultTableOneColumn: {
-    width: 1024,
+    width: '100%',
     height: 'calc(100% - 5px)',
   },
   rightColumn: {
@@ -135,16 +135,12 @@ const styles = theme => ({
 });
 
 let MapApp = (props) => {
-  const { classes, options, browser, search, map, manuscripts, creationPlaces, resultValues } = props;
+  const { classes, options, browser, search, map, manuscripts, creationPlaces, manuscriptsPropertyValues } = props;
   //error,
 
-  let oneColumnView = browser.lessThan.extraLarge;
+  let oneColumnView = true;
 
-  // console.log('oneColumnView', oneColumnView)
-  // console.log('resultFormat', resultFormat)
-  // console.log('mapMode', mapMode)
-  //console.log(props.results)
-  //console.log(manuscripts)
+  console.log(manuscripts)
 
   let table = '';
   if (search.fetchingManuscripts) {
@@ -162,7 +158,7 @@ let MapApp = (props) => {
         <div className={oneColumnView ? classes.resultTableOneColumn : classes.resultTable}>
           <VirtualizedTable
             list={Immutable.List(manuscripts)}
-            resultValues={resultValues}
+            manuscriptsPropertyValues={manuscriptsPropertyValues}
             search={search}
             sortResults={props.sortResults}
             updateResultsFilter={props.updateResultsFilter}
@@ -294,11 +290,9 @@ const mapStateToProps = (state) => {
     browser: state.browser,
     search: state.search,
     map: state.map,
-    // results: getVisibleResults(state.search),
-    manuscripts: state.search.manuscripts,
+    manuscripts: getVisibleResults(state.search),
+    manuscriptsPropertyValues: getVisibleValues(state.search),
     creationPlaces: state.search.places,
-    //resultValues: getVisibleValues(state.search),
-    resultValues: {},
   };
 };
 
@@ -332,7 +326,7 @@ MapApp.propTypes = {
   map: PropTypes.object.isRequired,
   manuscripts: PropTypes.array,
   creationPlaces: PropTypes.array,
-  resultValues: PropTypes.object,
+  manuscriptsPropertyValues: PropTypes.object.isRequired,
 
   updateQuery: PropTypes.func.isRequired,
   toggleDataset: PropTypes.func.isRequired,
diff --git a/src/client/reducers/search.js b/src/client/reducers/search.js
index 4a5e4fb3..d88799e9 100644
--- a/src/client/reducers/search.js
+++ b/src/client/reducers/search.js
@@ -35,14 +35,12 @@ export const INITIAL_STATE = {
   fetchingSuggestions: false,
   manuscripts: [],
   places: [],
-  resultsFilter: {
-    'id': new Set(),
-    'label': new Set(),
-    'author': new Set(),
-    'timespan': new Set(),
+  manuscriptsFilter: {
+    //'author': new Set(),
+    //'timespan': new Set(),
     'creationPlace': new Set(),
-    'material': new Set(),
-    'language': new Set(),
+    //'material': new Set(),
+    //'language': new Set(),
   },
   sortBy: 'author',
   sortDirection: 'asc',
diff --git a/src/client/selectors/index.js b/src/client/selectors/index.js
index 9fb1e838..b8b96caa 100644
--- a/src/client/selectors/index.js
+++ b/src/client/selectors/index.js
@@ -3,8 +3,8 @@ import _ from 'lodash';
 
 // https://redux.js.org/recipes/computing-derived-data
 
-const getResultsFilter = (state) => state.resultsFilter;
-const getResults = (state) => state.results;
+const getResultsFilter = (state) => state.manuscriptsFilter;
+const getResults = (state) => state.manuscripts;
 const getSortBy = (state) => state.sortBy;
 const getSortDirection = (state) => state.sortDirection;
 
diff --git a/src/server/sparql/Datasets.js b/src/server/sparql/Datasets.js
index 4b273080..aa77a95d 100644
--- a/src/server/sparql/Datasets.js
+++ b/src/server/sparql/Datasets.js
@@ -29,7 +29,6 @@ module.exports = {
       WHERE {
         ?id a frbroo:F4_Manifestation_Singleton .
         ?id skos:prefLabel ?prefLabel_ .
-
         OPTIONAL { ?id crm:P45_consists_of ?material_ . }
         ?expression_creation frbroo:R18_created ?id .
         OPTIONAL {
@@ -37,7 +36,11 @@ module.exports = {
           ?authorId skos:prefLabel ?authorLabel
           BIND(CONCAT(STR(?authorId), ";", STR(?authorLabel)) AS ?author_)
         }
-        OPTIONAL { ?expression_creation crm:P4_has_time_span ?timespan_ . }
+        OPTIONAL {
+          ?expression_creation crm:P4_has_time_span ?timespanId .
+          ?timespanId skos:prefLabel ?timespanLabel .
+          BIND(CONCAT(STR(?timespanId), ";", STR(?timespanLabel)) AS ?timespan_)
+        }
         OPTIONAL {
           ?expression_creation crm:P7_took_place_at ?creationPlaceId .
           ?creationPlaceId skos:prefLabel ?creationPlaceLabel .
@@ -51,6 +54,7 @@ module.exports = {
       }
       GROUP BY ?id ?manuscriptRecord ?entry
       ORDER BY DESC(?creationPlace)
+      LIMIT 2000
       `,
     'placeQuery': `
       PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
diff --git a/src/server/sparql/Mappers.js b/src/server/sparql/Mappers.js
index f37006b5..05935ab9 100644
--- a/src/server/sparql/Mappers.js
+++ b/src/server/sparql/Mappers.js
@@ -51,10 +51,10 @@ export const mapManuscripts = (sparqlBindings) => {
     return {
       id: b.id.value,
       manuscriptRecord: _.has(b, 'manuscriptRecord') ? b.manuscriptRecord.value : '-',
-      prefLabel: b.prefLabel.value,
-      author: _.has(b, 'author',) ? b.author.value.split('|') : '-',
-      timespan: _.has(b, 'timespan',) ? b.timespan.value.split('|') : '-',
-      creationPlace: _.has(b, 'creationPlace',) ? b.creationPlace.value.split('|') : '-',
+      prefLabel: b.prefLabel.value.split('|'),
+      author: _.has(b, 'author',) ? createObjectList(b.author.value, 'names') : '-',
+      timespan: _.has(b, 'timespan',) ? createObjectList(b.timespan.value) : '-',
+      creationPlace: _.has(b, 'creationPlace',) ? createObjectList(b.creationPlace.value, 'places') : '-',
       material: _.has(b, 'material',) ? b.material.value.split('|') : '-',
       language: _.has(b, 'language',) ? b.language.value.split('|') : '-',
     };
@@ -62,6 +62,19 @@ export const mapManuscripts = (sparqlBindings) => {
   return results;
 };
 
+const createObjectList = (str, sdbmType) => {
+  const strings = str.split('|');
+  return strings.map(s => {
+    const values = s.split(';');
+    return {
+      id: values[0].substring(values[0].lastIndexOf('/') + 1),
+      //id: values[0],
+      prefLabel: values[1],
+      sdbmType: sdbmType
+    };
+  });
+};
+
 export const mapPlaces = (sparqlBindings) => {
   //console.log(sparqlBindings);
   const results = sparqlBindings.map(b => {
-- 
GitLab