From 99ab74574c2ca8adb4480502416e636ad3d911c3 Mon Sep 17 00:00:00 2001
From: esikkala <esko.ikkala@aalto.fi>
Date: Fri, 21 Feb 2020 10:14:16 +0200
Subject: [PATCH] Fix full text query

---
 src/client/components/perspectives/mmm/All.js |  4 +-
 .../components/perspectives/sampo/All.js      | 50 +++++++++++
 src/client/containers/SemanticPortal.js       |  3 +-
 src/client/reducers/index.js                  |  2 +-
 .../reducers/sampo/clientSideFacetedSearch.js | 90 +++++++++++++++++++
 src/server/sparql/JenaQuery.js                | 11 +--
 src/server/sparql/SparqlQueriesGeneral.js     | 70 +--------------
 .../sparql/mmm/SparqlQueriesFullText.js       | 71 +++++++++++++++
 8 files changed, 224 insertions(+), 77 deletions(-)
 create mode 100644 src/client/components/perspectives/sampo/All.js
 create mode 100644 src/client/reducers/sampo/clientSideFacetedSearch.js
 create mode 100644 src/server/sparql/mmm/SparqlQueriesFullText.js

diff --git a/src/client/components/perspectives/mmm/All.js b/src/client/components/perspectives/mmm/All.js
index 358b5354..547fa303 100644
--- a/src/client/components/perspectives/mmm/All.js
+++ b/src/client/components/perspectives/mmm/All.js
@@ -11,6 +11,7 @@ const All = props => {
     <>
       <PerspectiveTabs
         routeProps={props.routeProps}
+        screenSize={props.screenSize}
         tabs={[{
           id: 'table',
           label: 'table',
@@ -42,7 +43,8 @@ All.propTypes = {
   clientSideFacetedSearch: PropTypes.object.isRequired,
   updatePage: PropTypes.func,
   sortResults: PropTypes.func,
-  routeProps: PropTypes.object.isRequired
+  routeProps: PropTypes.object.isRequired,
+  screenSize: PropTypes.string.isRequired
 }
 
 export default All
diff --git a/src/client/components/perspectives/sampo/All.js b/src/client/components/perspectives/sampo/All.js
new file mode 100644
index 00000000..547fa303
--- /dev/null
+++ b/src/client/components/perspectives/sampo/All.js
@@ -0,0 +1,50 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { Route, Redirect } from 'react-router-dom'
+import PerspectiveTabs from '../../main_layout/PerspectiveTabs'
+import MaterialTableFullTextResults from '../../facet_results/MaterialTableFullTextResults'
+import CalendarViewDayIcon from '@material-ui/icons/CalendarViewDay'
+
+const All = props => {
+  const perspectiveUrl = '/all'
+  return (
+    <>
+      <PerspectiveTabs
+        routeProps={props.routeProps}
+        screenSize={props.screenSize}
+        tabs={[{
+          id: 'table',
+          label: 'table',
+          icon: <CalendarViewDayIcon />,
+          value: 0
+        }]}
+      />
+      <Route
+        exact path={perspectiveUrl}
+        render={() => <Redirect to={`${perspectiveUrl}/table`} />}
+      />
+      <Route
+        path={`${perspectiveUrl}/table`}
+        render={() => {
+          return (
+            <MaterialTableFullTextResults
+              data={props.clientSideFacetedSearch.results}
+              query={props.clientSideFacetedSearch.query}
+              fetching={props.clientSideFacetedSearch.textResultsFetching}
+            />
+          )
+        }}
+      />
+    </>
+  )
+}
+
+All.propTypes = {
+  clientSideFacetedSearch: PropTypes.object.isRequired,
+  updatePage: PropTypes.func,
+  sortResults: PropTypes.func,
+  routeProps: PropTypes.object.isRequired,
+  screenSize: PropTypes.string.isRequired
+}
+
+export default All
diff --git a/src/client/containers/SemanticPortal.js b/src/client/containers/SemanticPortal.js
index 34fc3a3c..bbca44e2 100644
--- a/src/client/containers/SemanticPortal.js
+++ b/src/client/containers/SemanticPortal.js
@@ -24,7 +24,7 @@ import FacetBar from '../components/facet_bar/FacetBar'
 import Perspective1 from '../components/perspectives/sampo/Perspective1'
 import Perspective2 from '../components/perspectives/sampo/Perspective2'
 import Perspective3 from '../components/perspectives/sampo/Perspective3'
-import All from '../components/perspectives/mmm/All'
+import All from '../components/perspectives/sampo/All'
 import { perspectiveConfig } from '../configs/sampo/PerspectiveConfig'
 import { perspectiveConfigOnlyInfoPages } from '../configs/sampo/PerspectiveConfigOnlyInfoPages'
 import { rootUrl } from '../configs/sampo/GeneralConfig'
@@ -303,6 +303,7 @@ const SemanticPortal = props => {
                     <All
                       clientSideFacetedSearch={props.clientSideFacetedSearch}
                       routeProps={routeProps}
+                      screenSize={screenSize}
                     />
                   </Grid>
                 </Grid>}
diff --git a/src/client/reducers/index.js b/src/client/reducers/index.js
index 66fe5501..6d2715a4 100644
--- a/src/client/reducers/index.js
+++ b/src/client/reducers/index.js
@@ -12,7 +12,7 @@ import perspective3Facets from './sampo/perspective3Facets'
 import places from './sampo/places'
 import leafletMapLayers from './sampo/leafletMapLayers'
 import animation from './mmm/animation'
-import clientSideFacetedSearch from './mmm/clientSideFacetedSearch'
+import clientSideFacetedSearch from './sampo/clientSideFacetedSearch'
 
 const reducer = combineReducers({
   perspective1,
diff --git a/src/client/reducers/sampo/clientSideFacetedSearch.js b/src/client/reducers/sampo/clientSideFacetedSearch.js
new file mode 100644
index 00000000..5335d7fc
--- /dev/null
+++ b/src/client/reducers/sampo/clientSideFacetedSearch.js
@@ -0,0 +1,90 @@
+import {
+  FETCH_RESULTS_CLIENT_SIDE,
+  UPDATE_RESULTS,
+  CLEAR_RESULTS,
+  UPDATE_CLIENT_SIDE_FILTER,
+  SORT_RESULTS
+} from '../../actions'
+
+export const INITIAL_STATE = {
+  query: '',
+  results: [],
+  latestFilter: {
+    id: ''
+  },
+  latestFilterValues: [],
+  resultsFilter: {
+    prefLabel: new Set(),
+    type: new Set()
+  },
+  sortBy: 'prefLabel',
+  sortDirection: 'asc',
+  // groupBy: 'broaderTypeLabel',
+  // groupByLabel: 'Paikanlaji',
+  textResultsFetching: false,
+  spatialResultsFetching: false
+}
+
+const clientSideFacetedSearch = (state = INITIAL_STATE, action) => {
+  if (action.resultClass === 'all') {
+    switch (action.type) {
+      case FETCH_RESULTS_CLIENT_SIDE:
+        return {
+          ...state,
+          [`${action.jenaIndex}ResultsFetching`]: true
+        }
+      case UPDATE_RESULTS:
+        return {
+          ...state,
+          query: action.query,
+          results: action.data,
+          [`${action.jenaIndex}ResultsFetching`]: false
+        }
+      case CLEAR_RESULTS:
+        return {
+          ...state,
+          results: null,
+          fetchingResults: false,
+          query: '',
+          resultsFilter: {
+            prefLabel: new Set(),
+            type: new Set()
+          }
+        }
+      case UPDATE_CLIENT_SIDE_FILTER:
+        return updateResultsFilter(state, action)
+      case SORT_RESULTS:
+        return {
+          ...state,
+          sortBy: action.options.sortBy,
+          sortDirection: action.options.sortDirection
+        }
+      default:
+        return state
+    }
+  } else return state
+}
+
+const updateResultsFilter = (state, action) => {
+  const { property, value, latestValues } = action.filterObj
+  const nSet = state.resultsFilter[property]
+  if (nSet.has(value)) {
+    nSet.delete(value)
+  } else {
+    nSet.add(value)
+  }
+  const newFilter = {
+    ...state.resultsFilter,
+    [property]: nSet
+  }
+  return {
+    ...state,
+    resultsFilter: newFilter,
+    latestFilter: {
+      id: property
+    },
+    latestFilterValues: latestValues
+  }
+}
+
+export default clientSideFacetedSearch
diff --git a/src/server/sparql/JenaQuery.js b/src/server/sparql/JenaQuery.js
index 9875ec31..00fc3dda 100644
--- a/src/server/sparql/JenaQuery.js
+++ b/src/server/sparql/JenaQuery.js
@@ -1,16 +1,17 @@
 import { runSelectQuery } from './SparqlApi'
+import { endpoint } from './sampo/FacetConfigsSampo'
 import { prefixes } from './sampo/SparqlQueriesPrefixes'
-import { endpoint, jenaQuery } from './SparqlQueriesGeneral'
+import { jenaQuery } from './SparqlQueriesGeneral'
 import { makeObjectList } from './SparqlObjectMapper'
+import { fullTextSearchProperties } from './mmm/SparqlQueriesFullText'
 
 export const queryJenaIndex = async ({
   queryTerm,
   resultFormat
 }) => {
   let q = jenaQuery
-  q = q.replace('<QUERY>', `
-  ?id text:query ('${queryTerm.toLowerCase()}' 2000) .
-  `)
+  q = q.replace('<QUERY>', `?id text:query ('${queryTerm.toLowerCase()}' 2000) .`)
+  q = q.replace('<RESULT_SET_PROPERTIES>', fullTextSearchProperties)
   const results = await runSelectQuery({
     query: prefixes + q,
     endpoint,
@@ -18,4 +19,4 @@ export const queryJenaIndex = async ({
     resultFormat
   })
   return results
-};
+}
diff --git a/src/server/sparql/SparqlQueriesGeneral.js b/src/server/sparql/SparqlQueriesGeneral.js
index c2d25642..e75e485e 100644
--- a/src/server/sparql/SparqlQueriesGeneral.js
+++ b/src/server/sparql/SparqlQueriesGeneral.js
@@ -19,75 +19,7 @@ export const jenaQuery = `
   SELECT *
   WHERE {
     <QUERY>
-    {
-      ?id a ?type__id .
-      ?type__id rdfs:label|skos:prefLabel ?type__prefLabel_ .
-      BIND(STR(?type__prefLabel_) AS ?type__prefLabel)  # ignore language tags
-    }
-    UNION
-    {
-      ?id dct:source ?source__id .
-      ?source__id skos:prefLabel ?source__prefLabel .
-      ?source__id mmm-schema:data_provider_url ?source__dataProviderUrl .
-    }
-    UNION
-    {
-      ?id mmm-schema:data_provider_url ?source__id .
-      BIND(?source__id as ?source__dataProviderUrl)
-      BIND(?source__id as ?source__prefLabel)
-    }
-    UNION
-    {
-      ?id a frbroo:F4_Manifestation_Singleton .
-      ?id skos:prefLabel ?prefLabel__id .
-      BIND(?prefLabel__id as ?prefLabel__prefLabel)
-      BIND(CONCAT("/manuscripts/page/", REPLACE(STR(?id), "^.*\\\\/(.+)", "$1")) AS ?prefLabel__dataProviderUrl)
-    }
-    UNION
-    {
-      ?id a frbroo:F1_Work .
-      ?id skos:prefLabel ?prefLabel__id .
-      BIND(?prefLabel__id as ?prefLabel__prefLabel)
-      BIND(CONCAT("/works/page/", REPLACE(STR(?id), "^.*\\\\/(.+)", "$1")) AS ?prefLabel__dataProviderUrl)
-    }
-    UNION
-    {
-      VALUES ?eventClass { crm:E10_Transfer_of_Custody crm:E12_Production crm:E7_Activity crm:E67_Birth crm:E69_Death }
-      ?id a ?eventClass .
-      OPTIONAL { ?id skos:prefLabel ?prefLabel__id_ }
-      BIND(COALESCE(?prefLabel__id_, ?id) as ?prefLabel__id)
-      BIND(?prefLabel__id as ?prefLabel__prefLabel)
-      BIND(CONCAT("/events/page/", REPLACE(STR(?id), "^.*\\\\/(.+)", "$1")) AS ?prefLabel__dataProviderUrl)
-    }
-    UNION
-    {
-      VALUES ?actorClass { crm:E21_Person crm:E74_Group crm:E39_Actor }
-      ?id a ?actorClass .
-      ?id skos:prefLabel ?prefLabel__id .
-      BIND(?prefLabel__id as ?prefLabel__prefLabel)
-      BIND(CONCAT("/actors/page/", REPLACE(STR(?id), "^.*\\\\/(.+)", "$1")) AS ?prefLabel__dataProviderUrl)
-    }
-    UNION
-    {
-      ?id a crm:E53_Place .
-      ?id skos:prefLabel ?prefLabel__id .
-      BIND(?prefLabel__id as ?prefLabel__prefLabel)
-      BIND(CONCAT("/places/page/", REPLACE(STR(?id), "^.*\\\\/(.+)", "$1")) AS ?prefLabel__dataProviderUrl)
-    }
-    UNION
-    {
-      ?id a crm:E78_Collection .
-      ?id skos:prefLabel ?prefLabel__id .
-      BIND(?prefLabel__id as ?prefLabel__prefLabel)
-      BIND(CONCAT("/collections/page/", REPLACE(STR(?id), "^.*\\\\/(.+)", "$1")) AS ?prefLabel__dataProviderUrl)
-    }
-    UNION
-    {
-      ?id a frbroo:F2_Expression .
-      ?id skos:prefLabel ?prefLabel__id .
-      BIND(?prefLabel__id as ?prefLabel__prefLabel)
-      BIND(CONCAT("/expressions/page/", REPLACE(STR(?id), "^.*\\\\/(.+)", "$1")) AS ?prefLabel__dataProviderUrl)
-    }
+    <RESULT_SET_PROPERTIES>
   }
 `
 
diff --git a/src/server/sparql/mmm/SparqlQueriesFullText.js b/src/server/sparql/mmm/SparqlQueriesFullText.js
new file mode 100644
index 00000000..c140a852
--- /dev/null
+++ b/src/server/sparql/mmm/SparqlQueriesFullText.js
@@ -0,0 +1,71 @@
+export const fullTextSearchProperties = `
+{
+    ?id a ?type__id .
+    ?type__id rdfs:label|skos:prefLabel ?type__prefLabel_ .
+    BIND(STR(?type__prefLabel_) AS ?type__prefLabel)  # ignore language tags
+  }
+  UNION
+  {
+    ?id dct:source ?source__id .
+    ?source__id skos:prefLabel ?source__prefLabel .
+    ?source__id mmm-schema:data_provider_url ?source__dataProviderUrl .
+  }
+  UNION
+  {
+    ?id mmm-schema:data_provider_url ?source__id .
+    BIND(?source__id as ?source__dataProviderUrl)
+    BIND(?source__id as ?source__prefLabel)
+  }
+  UNION
+  {
+    ?id a frbroo:F4_Manifestation_Singleton .
+    ?id skos:prefLabel ?prefLabel__id .
+    BIND(?prefLabel__id as ?prefLabel__prefLabel)
+    BIND(CONCAT("/manuscripts/page/", REPLACE(STR(?id), "^.*\\\\/(.+)", "$1")) AS ?prefLabel__dataProviderUrl)
+  }
+  UNION
+  {
+    ?id a frbroo:F1_Work .
+    ?id skos:prefLabel ?prefLabel__id .
+    BIND(?prefLabel__id as ?prefLabel__prefLabel)
+    BIND(CONCAT("/works/page/", REPLACE(STR(?id), "^.*\\\\/(.+)", "$1")) AS ?prefLabel__dataProviderUrl)
+  }
+  UNION
+  {
+    VALUES ?eventClass { crm:E10_Transfer_of_Custody crm:E12_Production crm:E7_Activity crm:E67_Birth crm:E69_Death }
+    ?id a ?eventClass .
+    OPTIONAL { ?id skos:prefLabel ?prefLabel__id_ }
+    BIND(COALESCE(?prefLabel__id_, ?id) as ?prefLabel__id)
+    BIND(?prefLabel__id as ?prefLabel__prefLabel)
+    BIND(CONCAT("/events/page/", REPLACE(STR(?id), "^.*\\\\/(.+)", "$1")) AS ?prefLabel__dataProviderUrl)
+  }
+  UNION
+  {
+    VALUES ?actorClass { crm:E21_Person crm:E74_Group crm:E39_Actor }
+    ?id a ?actorClass .
+    ?id skos:prefLabel ?prefLabel__id .
+    BIND(?prefLabel__id as ?prefLabel__prefLabel)
+    BIND(CONCAT("/actors/page/", REPLACE(STR(?id), "^.*\\\\/(.+)", "$1")) AS ?prefLabel__dataProviderUrl)
+  }
+  UNION
+  {
+    ?id a crm:E53_Place .
+    ?id skos:prefLabel ?prefLabel__id .
+    BIND(?prefLabel__id as ?prefLabel__prefLabel)
+    BIND(CONCAT("/places/page/", REPLACE(STR(?id), "^.*\\\\/(.+)", "$1")) AS ?prefLabel__dataProviderUrl)
+  }
+  UNION
+  {
+    ?id a crm:E78_Collection .
+    ?id skos:prefLabel ?prefLabel__id .
+    BIND(?prefLabel__id as ?prefLabel__prefLabel)
+    BIND(CONCAT("/collections/page/", REPLACE(STR(?id), "^.*\\\\/(.+)", "$1")) AS ?prefLabel__dataProviderUrl)
+  }
+  UNION
+  {
+    ?id a frbroo:F2_Expression .
+    ?id skos:prefLabel ?prefLabel__id .
+    BIND(?prefLabel__id as ?prefLabel__prefLabel)
+    BIND(CONCAT("/expressions/page/", REPLACE(STR(?id), "^.*\\\\/(.+)", "$1")) AS ?prefLabel__dataProviderUrl)
+  }
+  `
-- 
GitLab