diff --git a/src/client/actions/index.js b/src/client/actions/index.js index 14e610fe39364a64a32e30d0955b749339477311..fdd7e7fcb862a74c588ada55c1fdcc2e8affc1ca 100644 --- a/src/client/actions/index.js +++ b/src/client/actions/index.js @@ -102,8 +102,9 @@ export const fetchResultsFailed = (error) => ({ }); // Manuscripts -export const fetchManuscripts = () => ({ +export const fetchManuscripts = (page) => ({ type: FETCH_MANUSCRIPTS, + page }); export const updateManuscripts = ({ manuscripts }) => ({ diff --git a/src/client/components/TopBar.js b/src/client/components/TopBar.js index af75db7f6c06d19b5dd245be2da0e7ad792a177d..4e2d74e8c92a119d182aa966511c42512f935677 100644 --- a/src/client/components/TopBar.js +++ b/src/client/components/TopBar.js @@ -68,7 +68,7 @@ class TopBar extends React.Component { }; componentDidMount() { - this.props.fetchManuscripts(); + this.props.fetchManuscripts(1); } handleClick = event => { diff --git a/src/client/epics/index.js b/src/client/epics/index.js index a6344d0a182201196c6e20809a7e15e8ea949ea6..4c4428f045253fe37a8b57a102896abd45f0019d 100644 --- a/src/client/epics/index.js +++ b/src/client/epics/index.js @@ -72,13 +72,11 @@ const getSuggestionsEpic = (action$, store) => { // }); // }; -const getManuscripts = (action$, store) => { +const getManuscripts = (action$) => { const searchUrl = hiplaApiUrl + 'manuscripts'; return action$.ofType(FETCH_MANUSCRIPTS) - .switchMap(() => { - const { datasets } = store.getState().search; - const dsParams = _.map(pickSelectedDatasets(datasets), ds => `dataset=${ds}`).join('&'); - const requestUrl = `${searchUrl}?${dsParams}`; + .switchMap(action => { + const requestUrl = `${searchUrl}?page=${action.page}`; return ajax.getJSON(requestUrl) .map(response => updateManuscripts({ manuscripts: response })) .catch(error => Observable.of({ diff --git a/src/server/index.js b/src/server/index.js index 4ef3bdc9b5c9548400935f7e09d1b8671fb4fec3..7125eef3b6727a3c97ef06dfbb249bfccb707ebd 100644 --- a/src/server/index.js +++ b/src/server/index.js @@ -2,7 +2,7 @@ import express from 'express'; import bodyParser from 'body-parser'; import request from 'superagent'; import _ from 'lodash'; -import sparqlSearchEngine from './sparql/SparqlSearchEngine'; +import { getManuscripts, getPlaces } from './sparql/Manuscripts'; const DEFAULT_PORT = 3001; const app = express(); //const isDevelopment = app.get('env') !== 'production'; @@ -19,44 +19,10 @@ app.use(function(req, res, next) { app.use(express.static(__dirname + './../public/')); -app.get('/suggest', (req, res) => { - // https://softwareengineering.stackexchange.com/questions/233164/how-do-searches-fit-into-a-restful-interface - // example request: http://localhost:3000/search?dataset=warsa_karelian_places&dataset=pnr&q=viip - const queryDatasets = _.castArray(req.query.dataset); - const queryTerm = req.query.q; - // console.log(queryDatasets); - - return sparqlSearchEngine.getFederatedSuggestions(queryTerm, queryDatasets).then((data) => { - // console.log(data); - res.json(data); - }) - .catch((err) => { - console.log(err); - return res.sendStatus(500); - }); -}); - -app.get('/search', (req, res) => { - // https://softwareengineering.stackexchange.com/questions/233164/how-do-searches-fit-into-a-restful-interface - // example request: http://localhost:3000/search?dataset=warsa_karelian_places&dataset=pnr&q=viip - const queryDatasets = _.castArray(req.query.dataset); - const queryTerm = req.query.q; - // console.log(queryDatasets); - - return sparqlSearchEngine.getFederatedResults(queryTerm, queryDatasets).then((data) => { - // console.log(data); - res.json(data); - }) - .catch((err) => { - console.log(err); - return res.sendStatus(500); - }); -}); app.get('/manuscripts', (req, res) => { - const queryDatasets = _.castArray(req.query.dataset); - - return sparqlSearchEngine.getFederatedManuscripts(queryDatasets).then((data) => { + const page = req.query.page || 1; + return getManuscripts(page).then((data) => { // console.log(data); res.json(data); }) @@ -67,9 +33,7 @@ app.get('/manuscripts', (req, res) => { }); app.get('/places', (req, res) => { - const queryDatasets = _.castArray(req.query.dataset); - - return sparqlSearchEngine.getFederatedPlaces(queryDatasets).then((data) => { + return getPlaces().then((data) => { // console.log(data); res.json(data); }) diff --git a/src/server/sparql/Datasets.js b/src/server/sparql/Datasets.js index 3613f4cfee5427d4efdce2130b7b857b31fbedf1..833937c8e0d633d2d554c4c973e24125aad24857 100644 --- a/src/server/sparql/Datasets.js +++ b/src/server/sparql/Datasets.js @@ -63,6 +63,7 @@ module.exports = { } GROUP BY ?id ?manuscriptRecord ORDER BY (!BOUND(?creationPlace)) ?creationPlace + <PAGE> `, 'placeQuery': ` PREFIX skos: <http://www.w3.org/2004/02/skos/core#> diff --git a/src/server/sparql/Manuscripts.js b/src/server/sparql/Manuscripts.js new file mode 100644 index 0000000000000000000000000000000000000000..f12febfccec0ff943de9699008561ddcbda6dd21 --- /dev/null +++ b/src/server/sparql/Manuscripts.js @@ -0,0 +1,73 @@ +import SparqlSearchEngine from './SparqlSearchEngine'; +import datasetConfig from './Datasets'; +import { + mapPlaces, + mapManuscripts +} from './Mappers'; + +const sparqlSearchEngine = new SparqlSearchEngine(); + +export const getManuscripts = (page) => { + let { endpoint, allQuery } = datasetConfig['mmm']; + allQuery = allQuery.replace('<PAGE>', 'LIMIT 25'); + return sparqlSearchEngine.doSearch(allQuery, endpoint, mapManuscripts); +}; + +export const getPlaces = () => { + const { endpoint, placeQuery } = datasetConfig['mmm']; + return sparqlSearchEngine.doSearch(placeQuery, endpoint, mapPlaces); +}; + + +const facetQuery = ` + PREFIX skos: <http://www.w3.org/2004/02/skos/core#> + PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> + PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> + PREFIX crm: <http://www.cidoc-crm.org/cidoc-crm/> + PREFIX owl: <http://www.w3.org/2002/07/owl#> + PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> + PREFIX text: <http://jena.apache.org/text#> + PREFIX dct: <http://purl.org/dc/terms/> + PREFIX geo: <http://www.w3.org/2003/01/geo/wgs84_pos#> + PREFIX sch: <http://schema.org/> + PREFIX geosparql: <http://www.opengis.net/ont/geosparql#> + PREFIX frbroo: <http://erlangen-crm.org/efrbroo/> + SELECT DISTINCT ?cnt ?facet_text ?value + WHERE { + { + { SELECT DISTINCT (count(DISTINCT ?id) as ?cnt) { + ?id a frbroo:F4_Manifestation_Singleton . + ?id skos:prefLabel ?name . + } + } BIND("-- Ei valintaa --" AS ?facet_text) } + UNION + { + SELECT DISTINCT ?cnt ?value ?facet_text { + { SELECT DISTINCT (count(DISTINCT ?id) as ?cnt) ?value { + ?id a frbroo:F4_Manifestation_Singleton . + ?id skos:prefLabel ?name . + ?id ^frbroo:R18_created/crm:P7_took_place_at ?value . + } + GROUP BY ?value + } + FILTER(BOUND(?value)) BIND(COALESCE(?value, <http://ldf.fi/NONEXISTENT_URI>) AS ?labelValue) + OPTIONAL { ?labelValue skos:prefLabel ?lbl . + FILTER(langMatches(lang(?lbl), "fi")) . } + OPTIONAL { ?labelValue rdfs:label ?lbl . + FILTER(langMatches(lang(?lbl), "fi")) . } + OPTIONAL { ?labelValue skos:prefLabel ?lbl . + FILTER(langMatches(lang(?lbl), "en")) . } + OPTIONAL { ?labelValue rdfs:label ?lbl . + FILTER(langMatches(lang(?lbl), "en")) . } + OPTIONAL { ?labelValue skos:prefLabel ?lbl . + FILTER(langMatches(lang(?lbl), "sv")) . } + OPTIONAL { ?labelValue rdfs:label ?lbl . + FILTER(langMatches(lang(?lbl), "sv")) . } + OPTIONAL { ?labelValue skos:prefLabel ?lbl . + FILTER(langMatches(lang(?lbl), "")) . } + OPTIONAL { ?labelValue rdfs:label ?lbl . + FILTER(langMatches(lang(?lbl), "")) . } + BIND(COALESCE(?lbl, IF(!ISURI(?value), ?value, "")) AS ?facet_text) } + } + } +`; diff --git a/src/server/sparql/SparqlSearchEngine.js b/src/server/sparql/SparqlSearchEngine.js index 4d4233312f2c8801bfa3c5a3cac36c2397c933e4..e49c217dd21ba1d2ef004421244f80fa280ea811 100644 --- a/src/server/sparql/SparqlSearchEngine.js +++ b/src/server/sparql/SparqlSearchEngine.js @@ -1,12 +1,5 @@ import _ from 'lodash'; import SparqlApi from './SparqlApi'; -import datasetConfig from './Datasets'; -import { - mergeFederatedResults, - mapPlaces, - mapManuscripts -} from './Mappers'; -//import { makeObjectList } from './SparqlObjectMapper'; class SparqlSearchEngine { @@ -21,67 +14,6 @@ class SparqlSearchEngine { }); } - getAllManuscripts(datasetId) { - const { endpoint, allQuery } = datasetConfig[datasetId]; - return this.doSearch(allQuery, endpoint, mapManuscripts); - } - - getAllPlaces(datasetId) { - const { endpoint, placeQuery } = datasetConfig[datasetId]; - // console.log(allQuery) - return this.doSearch(placeQuery, endpoint, mapPlaces); - } - - getFederatedManuscripts(datasets) { - return Promise.all(datasets.map((datasetId) => - this.getAllManuscripts(datasetId))) - .then(mergeFederatedResults); - // .then((manuscripts) => this.getPlaces(manuscripts)); - } - - getFederatedPlaces(datasets) { - return Promise.all(datasets.map((datasetId) => - this.getAllPlaces(datasetId))) - .then(mergeFederatedResults); - // .then((manuscripts) => this.getPlaces(manuscripts)); - } - - - // - // getPlaces(manuscripts) { - // const { endpoint, placeQuery } = datasetConfig.mmm; - // let placeIds = manuscripts.reduce((places, manuscript) => { - // if (manuscript.creationPlace !== undefined) { - // const creationPlaceArr = manuscript.creationPlace.split(','); - // places = places.concat(creationPlaceArr); - // } - // return places; - // }, []); - // placeIds = Array.from(new Set(placeIds)); //remove duplicates - // return this.doSearch(placeQuery.replace('<ID>', this.uriFy(placeIds)), endpoint, makeDict) - // .then((placeDict) => { - // manuscripts.map((manuscript) => { - // if (manuscript.creationPlace !== undefined) { - // let creationPlaceObjs; - // const creationPlaceArr = manuscript.creationPlace.split(','); - // if (creationPlaceArr.length > 1) { - // creationPlaceObjs = creationPlaceArr.map((place) => { - // return placeDict[place]; - // }); - // } else { - // creationPlaceObjs = placeDict[creationPlaceArr[0]]; - // } - // manuscript.creationPlace = creationPlaceObjs; - // return manuscript; - // } - // }); - // return { - // 'manuscripts': manuscripts, - // 'creationPlaces': placeDict - // }; - // }); - // } - uriFy(id) { if (_.isArray(id)) { return '<' + id.join('> <') + '>'; @@ -92,4 +24,4 @@ class SparqlSearchEngine { } } -export default new SparqlSearchEngine(); +export default SparqlSearchEngine;