diff --git a/src/client/actions/index.js b/src/client/actions/index.js index 9d079c6a336f4e4d6a5be90f7547851247601f17..232350a9a1b8e273ffe7f07e25e34e866d90e190 100644 --- a/src/client/actions/index.js +++ b/src/client/actions/index.js @@ -51,6 +51,9 @@ export const CLIENT_FS_UPDATE_RESULTS = 'CLIENT_FS_UPDATE_RESULTS' export const CLIENT_FS_CLEAR_RESULTS = 'CLIENT_FS_CLEAR_RESULTS' export const CLIENT_FS_UPDATE_FACET = 'CLIENT_FS_UPDATE_FACET' export const CLIENT_FS_SORT_RESULTS = 'CLIENT_FS_SORT_RESULTS' +export const FETCH_KNOWLEDGE_GRAPH_METADATA = 'FETCH_KNOWLEDGE_GRAPH_METADATA' +export const FETCH_KNOWLEDGE_GRAPH_METADATA_FAILED = 'FETCH_KNOWLEDGE_GRAPH_METADATA_FAILED' +export const UPDATE_KNOWLEDGE_GRAPH_METADATA = 'UPDATE_KNOWLEDGE_GRAPH_METADATA' export const fetchPaginatedResults = (resultClass, facetClass, sortBy) => ({ type: FETCH_PAGINATED_RESULTS, @@ -328,3 +331,19 @@ export const clientFSSortResults = options => ({ type: CLIENT_FS_SORT_RESULTS, options }) +export const fetchKnowledgeGraphMetadata = ({ resultClass }) => ({ + type: FETCH_KNOWLEDGE_GRAPH_METADATA, + resultClass +}) +export const fetchKnowledgeGraphMetadataFailded = (resultClass, error, message) => ({ + type: FETCH_KNOWLEDGE_GRAPH_METADATA_FAILED, + resultClass, + error, + message +}) +export const updateKnowledgeGraphMetadata = ({ resultClass, data, sparqlQuery }) => ({ + type: UPDATE_KNOWLEDGE_GRAPH_METADATA, + resultClass, + data, + sparqlQuery +}) diff --git a/src/client/components/main_layout/TextPage.js b/src/client/components/main_layout/TextPage.js index a2fc066135ffbbb3c9b44435cb2531dcfbe04c34..9d2ec244437f9087f39bd49bcbfdf36302417b0e 100644 --- a/src/client/components/main_layout/TextPage.js +++ b/src/client/components/main_layout/TextPage.js @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect } from 'react' import PropTypes from 'prop-types' import { makeStyles } from '@material-ui/core/styles' import Paper from '@material-ui/core/Paper' @@ -34,6 +34,12 @@ const useStyles = makeStyles(theme => ({ */ const TextPage = props => { const classes = useStyles() + + useEffect(() => { + props.fetchKnowledgeGraphMetadata({ resultClass: 'perspective1KnowledgeGraphMetadata' }) + }, []) + + // console.log(props.knowledgeGraphMetadata) return ( <div className={classes.root}> <Paper className={classes.layout}> diff --git a/src/client/containers/SemanticPortal.js b/src/client/containers/SemanticPortal.js index 017de65351cd51a57150676c591e9f219a42bdbf..af0886edce2dad5b2639f82b4f6c3134226f24f2 100644 --- a/src/client/containers/SemanticPortal.js +++ b/src/client/containers/SemanticPortal.js @@ -62,7 +62,8 @@ import { clientFSSortResults, clientFSClearResults, clientFSUpdateQuery, - clientFSUpdateFacet + clientFSUpdateFacet, + fetchKnowledgeGraphMetadata } from '../actions' import { filterResults } from '../selectors' @@ -574,7 +575,12 @@ const SemanticPortal = props => { path={`${rootUrlWithLang}/about`} render={() => <div className={classNames(classes.mainContainer, classes.textPageContainer)}> - <TextPage>{intl.getHTML('aboutThePortal')}</TextPage> + <TextPage + fetchKnowledgeGraphMetadata={props.fetchKnowledgeGraphMetadata} + knowledgeGraphMetadata={props.perspective1.knowledgeGraphMetadata} + > + {intl.getHTML('aboutThePortal')} + </TextPage> </div>} /> <Route @@ -654,7 +660,8 @@ const mapDispatchToProps = ({ clientFSClearResults, clientFSSortResults, clientFSUpdateQuery, - clientFSUpdateFacet + clientFSUpdateFacet, + fetchKnowledgeGraphMetadata }) SemanticPortal.propTypes = { diff --git a/src/client/epics/index.js b/src/client/epics/index.js index 0decc95f01bcc96f0b127bc1ca937872e7c71a2f..f476e99363b5635a633b86868252b990626f8038 100644 --- a/src/client/epics/index.js +++ b/src/client/epics/index.js @@ -33,6 +33,8 @@ import { FETCH_FACET_FAILED, FETCH_GEOJSON_LAYERS, FETCH_GEOJSON_LAYERS_BACKEND, + FETCH_KNOWLEDGE_GRAPH_METADATA, + FETCH_KNOWLEDGE_GRAPH_METADATA_FAILED, CLIENT_FS_FETCH_RESULTS, CLIENT_FS_FETCH_RESULTS_FAILED, LOAD_LOCALES, @@ -46,6 +48,7 @@ import { updateFacetValuesConstrainSelf, updateLocale, updateGeoJSONLayers, + updateKnowledgeGraphMetadata, SHOW_ERROR } from '../actions' import { @@ -477,6 +480,33 @@ const fetchGeoJSONLayer = async (layerID, bounds) => { } } +const fetchKnowledgeGraphMetadataEpic = (action$, state$) => action$.pipe( + ofType(FETCH_KNOWLEDGE_GRAPH_METADATA), + withLatestFrom(state$), + mergeMap(([action]) => { + const requestUrl = `${apiUrl}/void/${action.resultClass}` + return ajax({ + url: requestUrl, + method: 'GET' + }).pipe( + map(ajaxResponse => updateKnowledgeGraphMetadata({ + resultClass: action.resultClass, + data: ajaxResponse.response.data || [], + sparqlQuery: ajaxResponse.response.sparqlQuery + })), + catchError(error => of({ + type: FETCH_KNOWLEDGE_GRAPH_METADATA_FAILED, + perspectiveID: action.resultClass, + error: error, + message: { + text: backendErrorText, + title: 'Error' + } + })) + ) + }) +) + const rootEpic = combineEpics( fetchPaginatedResultsEpic, fetchResultsEpic, @@ -489,7 +519,8 @@ const rootEpic = combineEpics( loadLocalesEpic, fetchSimilarDocumentsEpic, fetchGeoJSONLayersEpic, - fetchGeoJSONLayersBackendEpic + fetchGeoJSONLayersBackendEpic, + fetchKnowledgeGraphMetadataEpic ) export default rootEpic diff --git a/src/client/reducers/general/helpers.js b/src/client/reducers/general/helpers.js index 26c5ed2a1b96203ca1f20fc3b83c3466578017af..be6c47ac6e1d5fc0c6e6b2d6feee9aa07d2f1808 100644 --- a/src/client/reducers/general/helpers.js +++ b/src/client/reducers/general/helpers.js @@ -305,3 +305,11 @@ export const updateHeaderExpanded = (state, action) => { } } } + +export const updateKnowledgeGraphMetadata = (state, action) => { + return { + ...state, + knowledgeGraphMetadata: action.data, + fetching: false + } +} diff --git a/src/client/reducers/general/results.js b/src/client/reducers/general/results.js index 9a655cea14b33461eab4bd9d0ad4fc25fcd3f8dd..f221cab9c182c3e1ffc925e1dcd70037e057c4e6 100644 --- a/src/client/reducers/general/results.js +++ b/src/client/reducers/general/results.js @@ -14,7 +14,8 @@ import { UPDATE_PAGE, UPDATE_ROWS_PER_PAGE, SORT_RESULTS, - UPDATE_PERSPECTIVE_HEADER_EXPANDED + UPDATE_PERSPECTIVE_HEADER_EXPANDED, + UPDATE_KNOWLEDGE_GRAPH_METADATA } from '../../actions' import { fetchResults, @@ -29,7 +30,8 @@ import { updateInstanceAnalysisData, updatePage, updateRowsPerPage, - updateHeaderExpanded + updateHeaderExpanded, + updateKnowledgeGraphMetadata } from './helpers' export const handleDataFetchingAction = (state, action) => { @@ -63,6 +65,8 @@ export const handleDataFetchingAction = (state, action) => { return updateRowsPerPage(state, action) case UPDATE_PERSPECTIVE_HEADER_EXPANDED: return updateHeaderExpanded(state, action) + case UPDATE_KNOWLEDGE_GRAPH_METADATA: + return updateKnowledgeGraphMetadata(state, action) default: return state } diff --git a/src/client/reducers/sampo/perspective1.js b/src/client/reducers/sampo/perspective1.js index 33712c85619b6692117424478e8fabb4e9f79497..f62458089d9b49b64dadce49aedd36899cd38b92 100644 --- a/src/client/reducers/sampo/perspective1.js +++ b/src/client/reducers/sampo/perspective1.js @@ -259,7 +259,8 @@ const resultClasses = new Set([ 'perspective1', 'productionTimespanLineChart', 'eventLineChart', - 'manuscriptInstancePageNetwork' + 'manuscriptInstancePageNetwork', + 'perspective1KnowledgeGraphMetadata' ]) const perspective1 = (state = INITIAL_STATE, action) => { diff --git a/src/server/index.js b/src/server/index.js index 3fd6a2aca302a85743d7d52ce3556c620119f677..814a74278f1dac9235f146184f36cf56f0bee800 100644 --- a/src/server/index.js +++ b/src/server/index.js @@ -171,22 +171,6 @@ new OpenApiValidator({ } }) - app.get(`${apiPath}/:resultClass/network/:id`, async (req, res, next) => { - const { params, query } = req - try { - const data = await getByURI({ - backendSearchConfig, - resultClass: params.resultClass, - uri: params.id, - constraints: null, - resultFormat: 'json' - }) - res.json(data) - } catch (error) { - next(error) - } - }) - app.post(`${apiPath}/faceted-search/:facetClass/facet/:id`, async (req, res, next) => { const { params, body } = req try { @@ -262,6 +246,20 @@ new OpenApiValidator({ } }) + app.get(`${apiPath}/void/:resultClass`, async (req, res, next) => { + const { params } = req + try { + const data = await getAllResults({ + backendSearchConfig, + resultClass: params.resultClass, + resultFormat: 'json' + }) + res.json(data) + } catch (error) { + next(error) + } + }) + /* Some example paths for serving individual files: */ // app.get('/robots.txt', (request, response) => { diff --git a/src/server/openapi.yaml b/src/server/openapi.yaml index f2db17d4172b7efd9bd9a9837c83d37895b5d98c..03872e555876bf82e8454f49695b73384a577f22 100644 --- a/src/server/openapi.yaml +++ b/src/server/openapi.yaml @@ -312,41 +312,6 @@ paths: sparqlQuery: type: string description: The SPARQL query that was used for retrieving the metadata - /{resultClass}/network/{id}: - get: - summary: Return a network of a single resource - parameters: - - in: path - name: resultClass - schema: - type: string - required: true - description: The class of the resource - - in: path - name: id - schema: - type: string - required: true - description: The URI of the resource - - in: query - name: limit - schema: - type: string - required: false - description: Limit the number of links, default 1000. - - in: query - name: optimize - schema: - type: string - required: true - description: First performs a query with optimize * limit results, and then densifies the network. Default 1.0. - responses: - '200': - description: Network data - content: - application/json: - schema: - type: object /full-text-search: get: summary: Full text search @@ -438,6 +403,22 @@ paths: application/json: schema: type: array + /void/{perspectiveID}: + get: + summary: Retrieve a VoID description + parameters: + - in: path + name: perspectiveID + schema: + type: string + required: true + responses: + '200': + description: VoID description as JSON. + content: + application/json: + schema: + type: object diff --git a/src/server/sparql/sampo/BackendSearchConfig.js b/src/server/sparql/sampo/BackendSearchConfig.js index 3fa70c70d3eac839500668bf6e1be1b6376df1ff..596852a3c90934ffac8f7ff0de2a12a2e322ad3d 100644 --- a/src/server/sparql/sampo/BackendSearchConfig.js +++ b/src/server/sparql/sampo/BackendSearchConfig.js @@ -13,7 +13,8 @@ import { productionsByDecadeQuery, eventsByDecadeQuery, manuscriptNetworkLinksQuery, - manuscriptNetworkNodesQuery + manuscriptNetworkNodesQuery, + knowledgeGraphMetadataQuery } from './sparql_queries/SparqlQueriesPerspective1' import { workProperties @@ -212,6 +213,11 @@ export const backendSearchConfig = { // filterTarget: 'id', resultMapper: mapMultipleLineChart }, + perspective1KnowledgeGraphMetadata: { + perspectiveID: 'perspective1', + q: knowledgeGraphMetadataQuery, + resultMapper: makeObjectList + }, jenaText: { perspectiveID: 'perspective1', properties: fullTextSearchProperties diff --git a/src/server/sparql/sampo/sparql_queries/SparqlQueriesPerspective1.js b/src/server/sparql/sampo/sparql_queries/SparqlQueriesPerspective1.js index 27428d1173475ca52853c29b188f4ecc5aaaae2e..fd8d6a16efab7dbe14cbc9f371f2ed7534ac2e85 100644 --- a/src/server/sparql/sampo/sparql_queries/SparqlQueriesPerspective1.js +++ b/src/server/sparql/sampo/sparql_queries/SparqlQueriesPerspective1.js @@ -536,3 +536,13 @@ export const eventsByDecadeQuery = ` GROUP BY ?category ORDER BY ?category ` + +export const knowledgeGraphMetadataQuery = ` + SELECT * + WHERE { + ?id a sd:Dataset ; + dct:title ?title ; + dct:publisher ?publisher ; + dct:rightsHolder ?rightsHolder . + } +` diff --git a/src/server/sparql/sampo/sparql_queries/SparqlQueriesPrefixes.js b/src/server/sparql/sampo/sparql_queries/SparqlQueriesPrefixes.js index 0efece9eeabd6b0ec85e5dd9dbcefbf4029c1c1e..696cc16e8cf988b94a155ad15ecfa8f12a555eda 100644 --- a/src/server/sparql/sampo/sparql_queries/SparqlQueriesPrefixes.js +++ b/src/server/sparql/sampo/sparql_queries/SparqlQueriesPrefixes.js @@ -16,4 +16,5 @@ export const prefixes = ` PREFIX wgs84: <http://www.w3.org/2003/01/geo/wgs84_pos#> PREFIX spatial: <http://jena.apache.org/spatial#> PREFIX text: <http://jena.apache.org/text#> + PREFIX sd: <http://www.w3.org/ns/sparql-service-description#> `