From 645919daa897a7cf23e1ce17942a303c88152751 Mon Sep 17 00:00:00 2001
From: esikkala <esko.ikkala@aalto.fi>
Date: Fri, 28 Jun 2019 09:59:00 +0300
Subject: [PATCH] Streamline API responses

---
 src/client/actions/index.js       | 28 ++++++++++++++++----------
 src/client/epics/index.js         | 33 +++++++++++++++++++++++--------
 src/client/reducers/helpers.js    | 13 ++++++------
 src/server/index.js               | 10 ++++------
 src/server/sparql/FacetResults.js | 19 ++++++++++++------
 src/server/sparql/FacetValues.js  | 14 +++++++++++--
 src/server/sparql/Mappers.js      | 11 ++---------
 src/server/sparql/SparqlApi.js    | 10 +++++++---
 8 files changed, 88 insertions(+), 50 deletions(-)

diff --git a/src/client/actions/index.js b/src/client/actions/index.js
index 83b4477e..d25cdfb4 100644
--- a/src/client/actions/index.js
+++ b/src/client/actions/index.js
@@ -51,17 +51,17 @@ export const fetchResultsFailed = (resultClass, error, message) => ({
   type: FETCH_RESULTS_FAILED,
   resultClass, error, message
 });
-export const updateResultCount = ({ resultClass, count }) => ({
+export const updateResultCount = ({ resultClass, data, sparqlQuery }) => ({
   type: UPDATE_RESULT_COUNT,
-  resultClass, count
+  resultClass, data, sparqlQuery
 });
-export const updatePaginatedResults = ({ resultClass, data }) => ({
+export const updatePaginatedResults = ({ resultClass, page, pagesize, data, sparqlQuery }) => ({
   type: UPDATE_PAGINATED_RESULTS,
-  resultClass, data
+  resultClass, page, pagesize, data, sparqlQuery
 });
-export const updateResults = ({ resultClass, jenaIndex, query, data }) => ({
+export const updateResults = ({ resultClass, data, sparqlQuery }) => ({
   type: UPDATE_RESULTS,
-  resultClass, jenaIndex, query, data
+  resultClass, data, sparqlQuery
 });
 export const sortResults = (resultClass, sortBy) => ({
   type: SORT_RESULTS,
@@ -87,9 +87,9 @@ export const fetchByURIFailed = (resultClass, error, message) => ({
   type: FETCH_RESULTS_FAILED,
   resultClass, error, message
 });
-export const updateInstance = ({ resultClass, instance }) => ({
+export const updateInstance = ({ resultClass, data, sparqlQuery }) => ({
   type: UPDATE_INSTANCE,
-  resultClass, instance
+  resultClass, data, sparqlQuery
 });
 export const fetchFacet = ({ facetClass, facetID }) => ({
   type: FETCH_FACET,
@@ -99,9 +99,17 @@ export const fetchFacetFailed = (facetClass, id, error, message) => ({
   type: FETCH_FACET_FAILED,
   facetClass, id, error, message
 });
-export const updateFacetValues = ({ facetClass, id, distinctValueCount, values, flatValues, min, max }) => ({
+export const updateFacetValues = ({
+  facetClass,
+  id,
+  data,
+  flatValues,
+  min,
+  max,
+  sparqlQuery
+}) => ({
   type: UPDATE_FACET_VALUES,
-  facetClass, id, distinctValueCount, values, flatValues, min, max
+  facetClass, id, data, flatValues, min, max, sparqlQuery
 });
 export const updateFacetOption = ({ facetClass, facetID, option, value }) => ({
   type: UPDATE_FACET_OPTION,
diff --git a/src/client/epics/index.js b/src/client/epics/index.js
index f660a123..707220f4 100644
--- a/src/client/epics/index.js
+++ b/src/client/epics/index.js
@@ -55,7 +55,13 @@ const fetchPaginatedResultsEpic = (action$, state$) => action$.pipe(
     const requestUrl = `${apiUrl}${resultClass}/paginated?${params}`;
     // https://rxjs-dev.firebaseapp.com/api/ajax/ajax
     return ajax.getJSON(requestUrl).pipe(
-      map(response => updatePaginatedResults({ resultClass: resultClass, data: response })),
+      map(response => updatePaginatedResults({
+        resultClass: response.resultClass,
+        page: response.page,
+        pagesize: response.pagesize,
+        data: response.data,
+        sparqlQuery: response.sparqlQuery
+      })),
       // https://redux-observable.js.org/docs/recipes/ErrorHandling.html
       catchError(error => of({
         type: FETCH_PAGINATED_RESULTS_FAILED,
@@ -86,7 +92,11 @@ const fetchResultsEpic = (action$, state$) => action$.pipe(
     });
     const requestUrl = `${apiUrl}${resultClass}/all?${params}`;
     return ajax.getJSON(requestUrl).pipe(
-      map(response => updateResults({ resultClass: resultClass, data: response })),
+      map(response => updateResults({
+        resultClass: resultClass,
+        data: response.data,
+        sparqlQuery: response.sparqlQuery
+      })),
       catchError(error => of({
         type: FETCH_RESULTS_FAILED,
         resultClass: resultClass,
@@ -116,7 +126,11 @@ const fetchResultCountEpic = (action$, state$) => action$.pipe(
     });
     const requestUrl = `${apiUrl}${resultClass}/count?${params}`;
     return ajax.getJSON(requestUrl).pipe(
-      map(response => updateResultCount({ resultClass: resultClass, count: response.count })),
+      map(response => updateResultCount({
+        resultClass: response.resultClass,
+        data: response.data,
+        sparqlQuery: response.sparqlQuery
+      })),
       catchError(error => of({
         type: FETCH_RESULT_COUNT_FAILED,
         resultClass: resultClass,
@@ -179,7 +193,10 @@ const fetchByURIEpic = (action$, state$) => action$.pipe(
     });
     const requestUrl = `${apiUrl}${resultClass}/instance/${encodeURIComponent(uri)}?${params}`;
     return ajax.getJSON(requestUrl).pipe(
-      map(response => updateInstance({ resultClass: resultClass, instance: response })),
+      map(response => updateInstance({
+        resultClass: resultClass,
+        instance: response
+      })),
       catchError(error => of({
         type: FETCH_BY_URI_FAILED,
         resultClass: resultClass,
@@ -215,11 +232,11 @@ const fetchFacetEpic = (action$, state$) => action$.pipe(
       map(res => updateFacetValues({
         facetClass: facetClass,
         id: facetID,
-        distinctValueCount: res.distinctValueCount || 0,
-        values: res.values || [],
-        flatValues: res.flatValues || [],
+        data: res.data || [],
+        flatData: res.flatData || [],
         min: res.min || null,
-        max: res.max || null
+        max: res.max || null,
+        sparqlQuery: res.sparqlQuery
       })),
       catchError(error => of({
         type: FETCH_FACET_FAILED,
diff --git a/src/client/reducers/helpers.js b/src/client/reducers/helpers.js
index 30162e51..7b243250 100644
--- a/src/client/reducers/helpers.js
+++ b/src/client/reducers/helpers.js
@@ -138,7 +138,7 @@ const updateFacetFilter = (state, action) => {
 export const updateResultCount = (state, action) => {
   return {
     ...state,
-    resultCount: parseInt(action.count),
+    resultCount: parseInt(action.data),
     fetchingResultCount: false,
   };
 };
@@ -147,7 +147,7 @@ export const updateResults = (state, action) => {
   return {
     ...state,
     resultsUpdateID: ++state.resultsUpdateID,
-    results: action.data.results,
+    results: action.data,
     fetching: false,
   };
 };
@@ -156,7 +156,7 @@ export const updatePaginatedResults = (state, action) => {
   return {
     ...state,
     resultsUpdateID: ++state.resultsUpdateID,
-    paginatedResults: action.data.results || [],
+    paginatedResults: action.data || [],
     fetching: false
   };
 };
@@ -203,15 +203,16 @@ export const updateFacetValues = (state, action) => {
       }
     };
   } else {
+    console.log(action)
     return {
       ...state,
       facets: {
         ...state.facets,
         [ action.id ]: {
           ...state.facets[action.id],
-          distinctValueCount: action.distinctValueCount || 0,
-          values: action.values || [],
-          flatValues: action.flatValues || [],
+          distinctValueCount: action.data.length || 0,
+          values: action.data || [],
+          flatValues: action.flatData || [],
           isFetching: false
         }
       }
diff --git a/src/server/index.js b/src/server/index.js
index 57baaea9..ea0f3c8b 100644
--- a/src/server/index.js
+++ b/src/server/index.js
@@ -69,9 +69,7 @@ app.get(`${apiPath}/:resultClass/all`, async (req, res, next) => {
       variant: req.query.variant || null,
       resultFormat: req.query.resultFormat == null ? 'json' : req.query.resultFormat
     });
-    res.json({
-      results: data
-    });
+    res.json(data);
   } catch(error) {
     next(error);
   }
@@ -79,12 +77,12 @@ app.get(`${apiPath}/:resultClass/all`, async (req, res, next) => {
 
 app.get(`${apiPath}/:resultClass/count`, async (req, res, next) => {
   try {
-    const count = await getResultCount({
+    const data = await getResultCount({
       resultClass: req.params.resultClass,
       constraints: req.query.constraints == null ? null : JSON.parse(req.query.constraints),
       resultFormat: req.query.resultFormat == null ? 'json' : req.query.resultFormat
     });
-    res.json({ count });
+    res.json(data);
   } catch(error) {
     next(error);
   }
@@ -101,7 +99,7 @@ app.get(`${apiPath}/:resultClass/instance/:uri`, async (req, res, next) => {
       resultFormat: req.query.resultFormat == null ? 'json' : req.query.resultFormat
     });
     // there is always one object in the 'data' array
-    res.json(data[0]);
+    res.json(data);
   } catch(error) {
     next(error);
   }
diff --git a/src/server/sparql/FacetResults.js b/src/server/sparql/FacetResults.js
index 8021c74e..d0655a05 100644
--- a/src/server/sparql/FacetResults.js
+++ b/src/server/sparql/FacetResults.js
@@ -30,7 +30,7 @@ export const getPaginatedResults = async ({
   sortDirection,
   resultFormat
 }) => {
-  const data = await getPaginatedData({
+  const response = await getPaginatedData({
     resultClass,
     page,
     pagesize,
@@ -41,12 +41,14 @@ export const getPaginatedResults = async ({
   });
   if (resultFormat === 'json') {
     return {
-      pagesize: pagesize,
+      resultClass: resultClass,
       page: page,
-      results: data
+      pagesize: pagesize,
+      data: response.data,
+      sparqlQuery: response.sparqlQuery
     };
   } else {
-    return data;
+    return response;
   }
 };
 
@@ -100,7 +102,7 @@ export const getAllResults = ({
   return runSelectQuery(prefixes + q, endpoint, mapper, resultFormat);
 };
 
-export const getResultCount = ({
+export const getResultCount = async ({
   resultClass,
   constraints,
   resultFormat
@@ -118,7 +120,12 @@ export const getResultCount = ({
       facetID: null
     }));
   }
-  return runSelectQuery(prefixes + q, endpoint, mapCount, resultFormat);
+  const response = await runSelectQuery(prefixes + q, endpoint, mapCount, resultFormat);
+  return({
+    resultClass: resultClass,
+    data: response.data,
+    sparqlQuery: response.sparqlQuery
+  });
 };
 
 const getPaginatedData = ({
diff --git a/src/server/sparql/FacetValues.js b/src/server/sparql/FacetValues.js
index 3a3c2fd9..55f6b50c 100644
--- a/src/server/sparql/FacetValues.js
+++ b/src/server/sparql/FacetValues.js
@@ -19,7 +19,7 @@ import {
   mapTimespanFacet
 } from './Mappers';
 
-export const getFacet = ({
+export const getFacet = async ({
   facetClass,
   facetID,
   sortBy,
@@ -105,7 +105,17 @@ export const getFacet = ({
   // if (facetID == 'productionPlace') {
   //   console.log(prefixes + q)
   // }
-  return runSelectQuery(prefixes + q, endpoint, mapper, resultFormat);
+  const response = await runSelectQuery(prefixes + q, endpoint, mapper, resultFormat);
+  console.log(response)
+  return({
+    facetClass: facetClass,
+    id: facetID,
+    data: response.data,
+    flatData: response.flatData || null,
+    min: response.min || null,
+    max: response.max || null,
+    sparqlQuery: response.sparqlQuery
+  });
 };
 
 const generateSelectedBlock = ({
diff --git a/src/server/sparql/Mappers.js b/src/server/sparql/Mappers.js
index 39f9c8fc..eeb81087 100644
--- a/src/server/sparql/Mappers.js
+++ b/src/server/sparql/Mappers.js
@@ -27,10 +27,7 @@ export const mapFacet = sparqlBindings => {
   if (sparqlBindings.length > 0) {
     results = mapFacetValues(sparqlBindings);
   }
-  return {
-    distinctValueCount: results.length,
-    values: results
-  };
+  return results;
 };
 
 export const mapHierarchicalFacet = sparqlBindings => {
@@ -44,11 +41,7 @@ export const mapHierarchicalFacet = sparqlBindings => {
   });
   treeData = recursiveSort(treeData);
   treeData.forEach(node => sumUpAndSelectChildren(node));
-  return {
-    distinctValueCount: results.length,
-    //flatValues: flatResults,
-    values: treeData
-  };
+  return treeData;
 };
 
 export const mapTimespanFacet = sparqlBindings => {
diff --git a/src/server/sparql/SparqlApi.js b/src/server/sparql/SparqlApi.js
index 8cd4c1a1..e40b945f 100644
--- a/src/server/sparql/SparqlApi.js
+++ b/src/server/sparql/SparqlApi.js
@@ -13,19 +13,23 @@ export const runSelectQuery = async (query, endpoint, resultMapper, resultFormat
     'Content-Type': 'application/x-www-form-urlencoded',
     'Accept': MIMEtype
   };
+  const q = querystring.stringify({ query });
   try {
     const response = await axios({
       method: 'post',
       headers: headers,
       url: endpoint,
-      data: querystring.stringify({ query }),
+      data: q,
     });
     if (resultFormat === 'json') {
-      return resultMapper(response.data.results.bindings);
+      const mappedResults = resultMapper(response.data.results.bindings);
+      return {
+        data: mappedResults,
+        sparqlQuery: query
+      };
     } else {
       return response.data;
     }
-
   } catch(error) {
     if (error.response) {
     // The request was made and the server responded with a status code
-- 
GitLab