From c742930c376bac7f4e868d031e27f4cd15a99f50 Mon Sep 17 00:00:00 2001 From: Bartosz Prusinowski Date: Tue, 12 Dec 2023 17:30:05 +0100 Subject: [PATCH] WIP: Add initial improved DataCubePreview --- app/browser/dataset-preview.tsx | 84 +++++++---------- app/domain/data.ts | 36 ++++--- app/graphql/queries/data-cubes.graphql | 46 +++------ app/graphql/query-hooks.ts | 82 ++++++++-------- app/graphql/resolver-types.ts | 28 +++++- app/graphql/resolvers/index.ts | 4 + app/graphql/resolvers/rdf.ts | 13 +++ app/graphql/resolvers/sql.ts | 8 ++ app/graphql/schema.graphql | 13 ++- app/rdf/query-cube-preview.ts | 124 +++++++++++++++++++++++++ app/scripts/cube.ts | 5 +- codegen.yml | 2 + 12 files changed, 302 insertions(+), 143 deletions(-) create mode 100644 app/rdf/query-cube-preview.ts diff --git a/app/browser/dataset-preview.tsx b/app/browser/dataset-preview.tsx index 4432352009..d19266c39e 100644 --- a/app/browser/dataset-preview.tsx +++ b/app/browser/dataset-preview.tsx @@ -7,13 +7,15 @@ import * as React from "react"; import { DataSetPreviewTable } from "@/browse/datatable"; import { useFootnotesStyles } from "@/components/chart-footnotes"; -import { DataDownloadMenu, RunSparqlQuery } from "@/components/data-download"; +import { DataDownloadMenu } from "@/components/data-download"; import Flex from "@/components/flex"; import { HintRed, Loading, LoadingDataError } from "@/components/hint"; import { DataSource } from "@/config-types"; import { sourceToLabel } from "@/domain/datasource"; -import { useDataCubesComponentsQuery } from "@/graphql/hooks"; -import { useDataCubePreviewQuery } from "@/graphql/query-hooks"; +import { + useDataCubeMetadataQuery, + useDataCubePreviewQuery, +} from "@/graphql/query-hooks"; import { DataCubePublicationStatus } from "@/graphql/resolver-types"; import { useLocale } from "@/locales/use-locale"; @@ -93,55 +95,38 @@ export const DataSetPreview = ({ }) => { const footnotesClasses = useFootnotesStyles({ useMarginTop: false }); const locale = useLocale(); - const cubeFilters = [{ iri: dataSetIri }]; + const variables = { + sourceType: dataSource.type, + sourceUrl: dataSource.url, + locale, + cubeFilter: { iri: dataSetIri }, + }; + const [{ data: metadata, fetching: fetchingMetadata, error: metadataError }] = + useDataCubeMetadataQuery({ variables }); const [ { data: previewData, fetching: fetchingPreview, error: previewError }, - ] = useDataCubePreviewQuery({ - variables: { - iri: dataSetIri, - sourceType: dataSource.type, - sourceUrl: dataSource.url, - locale, - }, - }); - const [ - { - data: componentsData, - fetching: fetchingComponents, - error: componentsError, - }, - ] = useDataCubesComponentsQuery({ - variables: { - sourceType: dataSource.type, - sourceUrl: dataSource.url, - locale, - cubeFilters, - }, - }); + ] = useDataCubePreviewQuery({ variables }); const classes = useStyles({ - descriptionPresent: !!previewData?.dataCubeByIri?.description, + descriptionPresent: !!metadata?.dataCubeMetadata.description, }); React.useEffect(() => { window.scrollTo({ top: 0 }); }, []); - if (fetchingPreview || fetchingComponents) { + if (fetchingMetadata || fetchingPreview) { return ( ); - } else if ( - previewData?.dataCubeByIri && - componentsData?.dataCubesComponents - ) { - const { dataCubeByIri } = previewData; - const { dataCubesComponents } = componentsData; + } else if (metadata?.dataCubeMetadata && previewData?.dataCubePreview) { + const { dataCubeMetadata } = metadata; + const { dataCubePreview } = previewData; return ( - {dataCubeByIri.publicationStatus === + {dataCubeMetadata.publicationStatus === DataCubePublicationStatus.Draft && ( @@ -156,15 +141,15 @@ export const DataSetPreview = ({ - {dataCubeByIri.title} - visualize.admin.ch + {dataCubeMetadata.title} - visualize.admin.ch - {dataCubeByIri.title} + {dataCubeMetadata.title} - {dataCubeByIri.description && ( + {dataCubeMetadata.description && ( - {dataCubeByIri.description} + {dataCubeMetadata.description} )} - {dataCubeByIri.observations.sparqlEditorUrl && ( + {/* {dataCubeByIri.observations.sparqlEditorUrl && ( - )} + )} */} ); diff --git a/app/domain/data.ts b/app/domain/data.ts index a4d214200a..75879dc8b9 100644 --- a/app/domain/data.ts +++ b/app/domain/data.ts @@ -40,21 +40,6 @@ export type HierarchyValue = { children?: HierarchyValue[]; }; -export type Observation = Record; - -export type DataCubeObservations = { - data: Observation[]; - sparqlEditorUrl: string; -}; - -export type DataCubesObservations = { - data: Observation[]; - sparqlEditorUrls: { - cubeIri: string; - url: string; - }[]; -}; - export type DataCubeComponents = { dimensions: Dimension[]; measures: Measure[]; @@ -82,6 +67,27 @@ export type DataCubeMetadata = { workExamples?: string[]; }; +export type Observation = Record; + +export type DataCubeObservations = { + data: Observation[]; + sparqlEditorUrl: string; +}; + +export type DataCubesObservations = { + data: Observation[]; + sparqlEditorUrls: { + cubeIri: string; + url: string; + }[]; +}; + +export type DataCubePreview = { + // FIXME: define type + components: any[]; + observations: Observation[]; +}; + export type Component = Dimension | Measure; export type BaseComponent = { diff --git a/app/graphql/queries/data-cubes.graphql b/app/graphql/queries/data-cubes.graphql index 4cc9c08f2f..a278e2e526 100644 --- a/app/graphql/queries/data-cubes.graphql +++ b/app/graphql/queries/data-cubes.graphql @@ -40,6 +40,20 @@ query DataCubeObservations( ) } +query DataCubePreview( + $sourceType: String! + $sourceUrl: String! + $locale: String! + $cubeFilter: DataCubePreviewFilter! +) { + dataCubePreview( + sourceType: $sourceType + sourceUrl: $sourceUrl + locale: $locale + cubeFilter: $cubeFilter + ) +} + query SearchCubes( $sourceType: String! $sourceUrl: String! @@ -64,38 +78,6 @@ query SearchCubes( } } -query DataCubePreview( - $iri: String! - $sourceType: String! - $sourceUrl: String! - $locale: String! - $latest: Boolean - $disableValuesLoad: Boolean = true -) { - dataCubeByIri( - iri: $iri - sourceType: $sourceType - sourceUrl: $sourceUrl - locale: $locale - latest: $latest - disableValuesLoad: $disableValuesLoad - ) { - iri - title - description - publicationStatus - observations( - sourceType: $sourceType - sourceUrl: $sourceUrl - preview: true - limit: 10 - ) { - data - sparqlEditorUrl - } - } -} - query GeoCoordinatesByDimensionIri( $dataCubeIri: String! $dimensionIri: String! diff --git a/app/graphql/query-hooks.ts b/app/graphql/query-hooks.ts index 436d9a7067..1acad2aa53 100644 --- a/app/graphql/query-hooks.ts +++ b/app/graphql/query-hooks.ts @@ -1,6 +1,7 @@ import { DataCubeComponents } from '../domain/data'; import { DataCubeMetadata } from '../domain/data'; import { DataCubeObservations } from '../domain/data'; +import { DataCubePreview } from '../domain/data'; import { DimensionValue } from '../domain/data'; import { Filters } from '../configurator'; import { HierarchyValue } from '../domain/data'; @@ -24,6 +25,7 @@ export type Scalars = { DataCubeComponents: DataCubeComponents; DataCubeMetadata: DataCubeMetadata; DataCubeObservations: DataCubeObservations; + DataCubePreview: DataCubePreview; DimensionValue: DimensionValue; FilterValue: any; Filters: Filters; @@ -111,7 +113,6 @@ export type DataCubeMetadataFilter = { export type DataCubeObservationFilter = { iri: Scalars['String']; latest?: Maybe; - preview?: Maybe; filters?: Maybe; componentIris?: Maybe>; joinBy?: Maybe; @@ -124,6 +125,12 @@ export type DataCubeOrganization = { label?: Maybe; }; + +export type DataCubePreviewFilter = { + iri: Scalars['String']; + latest?: Maybe; +}; + export enum DataCubePublicationStatus { Draft = 'DRAFT', Published = 'PUBLISHED' @@ -384,6 +391,7 @@ export type Query = { dataCubeComponents: Scalars['DataCubeComponents']; dataCubeMetadata: Scalars['DataCubeMetadata']; dataCubeObservations: Scalars['DataCubeObservations']; + dataCubePreview: Scalars['DataCubePreview']; dataCubeByIri?: Maybe; possibleFilters: Array; searchCubes: Array; @@ -414,6 +422,14 @@ export type QueryDataCubeObservationsArgs = { }; +export type QueryDataCubePreviewArgs = { + sourceType: Scalars['String']; + sourceUrl: Scalars['String']; + locale: Scalars['String']; + cubeFilter: DataCubePreviewFilter; +}; + + export type QueryDataCubeByIriArgs = { sourceType: Scalars['String']; sourceUrl: Scalars['String']; @@ -613,30 +629,28 @@ export type DataCubeObservationsQueryVariables = Exact<{ export type DataCubeObservationsQuery = { __typename: 'Query', dataCubeObservations: DataCubeObservations }; -export type SearchCubesQueryVariables = Exact<{ +export type DataCubePreviewQueryVariables = Exact<{ sourceType: Scalars['String']; sourceUrl: Scalars['String']; locale: Scalars['String']; - query?: Maybe; - order?: Maybe; - includeDrafts?: Maybe; - filters?: Maybe | SearchCubeFilter>; + cubeFilter: DataCubePreviewFilter; }>; -export type SearchCubesQuery = { __typename: 'Query', searchCubes: Array<{ __typename: 'SearchCubeResult', highlightedTitle?: Maybe, highlightedDescription?: Maybe, cube: SearchCube }> }; +export type DataCubePreviewQuery = { __typename: 'Query', dataCubePreview: DataCubePreview }; -export type DataCubePreviewQueryVariables = Exact<{ - iri: Scalars['String']; +export type SearchCubesQueryVariables = Exact<{ sourceType: Scalars['String']; sourceUrl: Scalars['String']; locale: Scalars['String']; - latest?: Maybe; - disableValuesLoad?: Maybe; + query?: Maybe; + order?: Maybe; + includeDrafts?: Maybe; + filters?: Maybe | SearchCubeFilter>; }>; -export type DataCubePreviewQuery = { __typename: 'Query', dataCubeByIri?: Maybe<{ __typename: 'DataCube', iri: string, title: string, description?: Maybe, publicationStatus: DataCubePublicationStatus, observations: { __typename: 'ObservationsQuery', data: Array, sparqlEditorUrl?: Maybe } }> }; +export type SearchCubesQuery = { __typename: 'Query', searchCubes: Array<{ __typename: 'SearchCubeResult', highlightedTitle?: Maybe, highlightedDescription?: Maybe, cube: SearchCube }> }; export type GeoCoordinatesByDimensionIriQueryVariables = Exact<{ dataCubeIri: Scalars['String']; @@ -715,6 +729,20 @@ export const DataCubeObservationsDocument = gql` export function useDataCubeObservationsQuery(options: Omit, 'query'> = {}) { return Urql.useQuery({ query: DataCubeObservationsDocument, ...options }); }; +export const DataCubePreviewDocument = gql` + query DataCubePreview($sourceType: String!, $sourceUrl: String!, $locale: String!, $cubeFilter: DataCubePreviewFilter!) { + dataCubePreview( + sourceType: $sourceType + sourceUrl: $sourceUrl + locale: $locale + cubeFilter: $cubeFilter + ) +} + `; + +export function useDataCubePreviewQuery(options: Omit, 'query'> = {}) { + return Urql.useQuery({ query: DataCubePreviewDocument, ...options }); +}; export const SearchCubesDocument = gql` query SearchCubes($sourceType: String!, $sourceUrl: String!, $locale: String!, $query: String, $order: SearchCubeResultOrder, $includeDrafts: Boolean, $filters: [SearchCubeFilter!]) { searchCubes( @@ -736,36 +764,6 @@ export const SearchCubesDocument = gql` export function useSearchCubesQuery(options: Omit, 'query'> = {}) { return Urql.useQuery({ query: SearchCubesDocument, ...options }); }; -export const DataCubePreviewDocument = gql` - query DataCubePreview($iri: String!, $sourceType: String!, $sourceUrl: String!, $locale: String!, $latest: Boolean, $disableValuesLoad: Boolean = true) { - dataCubeByIri( - iri: $iri - sourceType: $sourceType - sourceUrl: $sourceUrl - locale: $locale - latest: $latest - disableValuesLoad: $disableValuesLoad - ) { - iri - title - description - publicationStatus - observations( - sourceType: $sourceType - sourceUrl: $sourceUrl - preview: true - limit: 10 - ) { - data - sparqlEditorUrl - } - } -} - `; - -export function useDataCubePreviewQuery(options: Omit, 'query'> = {}) { - return Urql.useQuery({ query: DataCubePreviewDocument, ...options }); -}; export const GeoCoordinatesByDimensionIriDocument = gql` query GeoCoordinatesByDimensionIri($dataCubeIri: String!, $dimensionIri: String!, $sourceType: String!, $sourceUrl: String!, $locale: String!, $latest: Boolean) { dataCubeByIri( diff --git a/app/graphql/resolver-types.ts b/app/graphql/resolver-types.ts index 1d11d17da9..d62abb6e28 100644 --- a/app/graphql/resolver-types.ts +++ b/app/graphql/resolver-types.ts @@ -1,6 +1,7 @@ import { DataCubeComponents } from '../domain/data'; import { DataCubeMetadata } from '../domain/data'; import { DataCubeObservations } from '../domain/data'; +import { DataCubePreview } from '../domain/data'; import { DimensionValue } from '../domain/data'; import { Filters } from '../configurator'; import { HierarchyValue } from '../domain/data'; @@ -25,6 +26,7 @@ export type Scalars = { DataCubeComponents: DataCubeComponents; DataCubeMetadata: DataCubeMetadata; DataCubeObservations: DataCubeObservations; + DataCubePreview: DataCubePreview; DimensionValue: DimensionValue; FilterValue: any; Filters: Filters; @@ -112,7 +114,6 @@ export type DataCubeMetadataFilter = { export type DataCubeObservationFilter = { iri: Scalars['String']; latest?: Maybe; - preview?: Maybe; filters?: Maybe; componentIris?: Maybe>; joinBy?: Maybe; @@ -125,6 +126,12 @@ export type DataCubeOrganization = { label?: Maybe; }; + +export type DataCubePreviewFilter = { + iri: Scalars['String']; + latest?: Maybe; +}; + export enum DataCubePublicationStatus { Draft = 'DRAFT', Published = 'PUBLISHED' @@ -385,6 +392,7 @@ export type Query = { dataCubeComponents: Scalars['DataCubeComponents']; dataCubeMetadata: Scalars['DataCubeMetadata']; dataCubeObservations: Scalars['DataCubeObservations']; + dataCubePreview: Scalars['DataCubePreview']; dataCubeByIri?: Maybe; possibleFilters: Array; searchCubes: Array; @@ -415,6 +423,14 @@ export type QueryDataCubeObservationsArgs = { }; +export type QueryDataCubePreviewArgs = { + sourceType: Scalars['String']; + sourceUrl: Scalars['String']; + locale: Scalars['String']; + cubeFilter: DataCubePreviewFilter; +}; + + export type QueryDataCubeByIriArgs = { sourceType: Scalars['String']; sourceUrl: Scalars['String']; @@ -661,6 +677,8 @@ export type ResolversTypes = ResolversObject<{ DataCubeObservationFilter: DataCubeObservationFilter; DataCubeObservations: ResolverTypeWrapper; DataCubeOrganization: ResolverTypeWrapper; + DataCubePreview: ResolverTypeWrapper; + DataCubePreviewFilter: DataCubePreviewFilter; DataCubePublicationStatus: DataCubePublicationStatus; DataCubeTheme: ResolverTypeWrapper; Dimension: ResolverTypeWrapper; @@ -710,6 +728,8 @@ export type ResolversParentTypes = ResolversObject<{ DataCubeObservationFilter: DataCubeObservationFilter; DataCubeObservations: Scalars['DataCubeObservations']; DataCubeOrganization: DataCubeOrganization; + DataCubePreview: Scalars['DataCubePreview']; + DataCubePreviewFilter: DataCubePreviewFilter; DataCubeTheme: DataCubeTheme; Dimension: ResolvedDimension; DimensionValue: Scalars['DimensionValue']; @@ -784,6 +804,10 @@ export type DataCubeOrganizationResolvers; }>; +export interface DataCubePreviewScalarConfig extends GraphQLScalarTypeConfig { + name: 'DataCubePreview'; +} + export type DataCubeThemeResolvers = ResolversObject<{ iri?: Resolver; label?: Resolver, ParentType, ContextType>; @@ -961,6 +985,7 @@ export type QueryResolvers>; dataCubeMetadata?: Resolver>; dataCubeObservations?: Resolver>; + dataCubePreview?: Resolver>; dataCubeByIri?: Resolver, ParentType, ContextType, RequireFields>; possibleFilters?: Resolver, ParentType, ContextType, RequireFields>; searchCubes?: Resolver, ParentType, ContextType, RequireFields>; @@ -1052,6 +1077,7 @@ export type Resolvers = ResolversObject<{ DataCubeMetadata?: GraphQLScalarType; DataCubeObservations?: GraphQLScalarType; DataCubeOrganization?: DataCubeOrganizationResolvers; + DataCubePreview?: GraphQLScalarType; DataCubeTheme?: DataCubeThemeResolvers; Dimension?: DimensionResolvers; DimensionValue?: GraphQLScalarType; diff --git a/app/graphql/resolvers/index.ts b/app/graphql/resolvers/index.ts index ca20e7f939..fca9fcff50 100644 --- a/app/graphql/resolvers/index.ts +++ b/app/graphql/resolvers/index.ts @@ -37,6 +37,10 @@ export const Query: QueryResolvers = { const source = getSource(args.sourceType); return await source.dataCubeObservations(parent, args, context, info); }, + dataCubePreview: async (parent, args, context, info) => { + const source = getSource(args.sourceType); + return await source.dataCubePreview(parent, args, context, info); + }, dataCubeByIri: async (parent, args, context, info) => { const source = getSource(args.sourceType); return await source.dataCubeByIri(parent, args, context, info); diff --git a/app/graphql/resolvers/rdf.ts b/app/graphql/resolvers/rdf.ts index d59c72a5a4..ebc7187689 100644 --- a/app/graphql/resolvers/rdf.ts +++ b/app/graphql/resolvers/rdf.ts @@ -30,6 +30,7 @@ import { getLatestCube, } from "@/rdf/queries"; import { getCubeMetadata } from "@/rdf/query-cube-metadata"; +import { getCubePreview } from "@/rdf/query-cube-preview"; import { unversionObservation } from "@/rdf/query-dimension-values"; import { queryHierarchy } from "@/rdf/query-hierarchies"; import { SearchResult, searchCubes as _searchCubes } from "@/rdf/query-search"; @@ -322,6 +323,18 @@ export const dataCubeObservations: NonNullable< }; }; +export const dataCubePreview: NonNullable = + async (_, { locale, cubeFilter }, { setup }, info) => { + const { sparqlClient } = await setup(info); + const { iri, latest } = cubeFilter; + + return await getCubePreview(iri, { + locale, + latest: !!latest, + sparqlClient, + }); + }; + export const dataCubeDimensions: NonNullable = async ({ cube, locale }, { componentIris }, { setup }, info) => { const { sparqlClient, cache } = await setup(info); diff --git a/app/graphql/resolvers/sql.ts b/app/graphql/resolvers/sql.ts index 266b60ebc4..70f197b133 100644 --- a/app/graphql/resolvers/sql.ts +++ b/app/graphql/resolvers/sql.ts @@ -324,3 +324,11 @@ export const dataCubeObservations: NonNullable< sparqlEditorUrl: "", }; }; + +export const dataCubePreview: NonNullable = + async () => { + return { + components: [], + observations: [], + }; + }; diff --git a/app/graphql/schema.graphql b/app/graphql/schema.graphql index e8948abb9b..eea01b77a3 100644 --- a/app/graphql/schema.graphql +++ b/app/graphql/schema.graphql @@ -354,15 +354,20 @@ input DataCubeMetadataFilter { input DataCubeObservationFilter { iri: String! latest: Boolean - preview: Boolean filters: Filters componentIris: [String!] joinBy: String } +input DataCubePreviewFilter { + iri: String! + latest: Boolean +} + scalar DataCubeComponents scalar DataCubeMetadata scalar DataCubeObservations +scalar DataCubePreview # The "Query" type is special: it lists all of the available queries that # clients can execute, along with the return type for each. @@ -385,6 +390,12 @@ type Query { locale: String! cubeFilter: DataCubeObservationFilter! ): DataCubeObservations! + dataCubePreview( + sourceType: String! + sourceUrl: String! + locale: String! + cubeFilter: DataCubePreviewFilter! + ): DataCubePreview! dataCubeByIri( sourceType: String! sourceUrl: String! diff --git a/app/rdf/query-cube-preview.ts b/app/rdf/query-cube-preview.ts new file mode 100644 index 0000000000..e432b1a8fa --- /dev/null +++ b/app/rdf/query-cube-preview.ts @@ -0,0 +1,124 @@ +import { Quad } from "rdf-js"; +import ParsingClient from "sparql-http-client/ParsingClient"; + +import { DataCubePreview } from "@/domain/data"; + +export const getCubePreview = async ( + iri: string, + options: { + locale: string; + latest: Boolean; + sparqlClient: ParsingClient; + } +): Promise => { + const { sparqlClient } = options; + const results: Quad[] = await sparqlClient.query.construct( + `PREFIX rdf: +PREFIX xsd: +PREFIX schema: +PREFIX sh: +PREFIX cube: + +CONSTRUCT { + ?cube schema:version ?cubeVersion . + + ?dimension sh:path ?dimensionIri . + ?dimension schema:name ?dimensionLabel . + ?dimension schema:description ?dimensionDescription . + ?dimension sh:order ?dimensionOrder . + ?dimension sh:datatype ?dimensionDataType . + ?dimensionDataKind rdf:type ?dimensionDataKindType . + + ?observation ?dimensionIri ?observationValue . + ?observation ?dimensionIri ?observationValueLabel . +} WHERE { + VALUES ?cube { } + FILTER(EXISTS { ?cube a cube:Cube . }) {} + UNION { + ?cube cube:observationConstraint/sh:property ?dimension . + ?dimension sh:path ?dimensionIri . + + OPTIONAL { ?dimension schema:name ?dimensionLabel_de . FILTER(LANG(?dimensionLabel_de) = "de") } + OPTIONAL { ?dimension schema:name ?dimensionLabel_fr . FILTER(LANG(?dimensionLabel_fr) = "fr") } + OPTIONAL { ?dimension schema:name ?dimensionLabel_it . FILTER(LANG(?dimensionLabel_it) = "it") } + OPTIONAL { ?dimension schema:name ?dimensionLabel_en . FILTER(LANG(?dimensionLabel_en) = "en") } + OPTIONAL { ?dimension schema:name ?dimensionLabel_ . FILTER(LANG(?dimensionLabel_) = "") } + BIND(COALESCE(?dimensionLabel_de, ?dimensionLabel_fr, ?dimensionLabel_it, ?dimensionLabel_en, ?dimensionLabel_) AS ?dimensionLabel) + + OPTIONAL { ?dimension schema:description ?dimensionDescription_de . FILTER(LANG(?dimensionDescription_de) = "de") } + OPTIONAL { ?dimension schema:description ?dimensionDescription_fr . FILTER(LANG(?dimensionDescription_fr) = "fr") } + OPTIONAL { ?dimension schema:description ?dimensionDescription_it . FILTER(LANG(?dimensionDescription_it) = "it") } + OPTIONAL { ?dimension schema:description ?dimensionDescription_en . FILTER(LANG(?dimensionDescription_en) = "en") } + OPTIONAL { ?dimension schema:description ?dimensionDescription_ . FILTER(LANG(?dimensionDescription_) = "") } + BIND(COALESCE(?dimensionDescription_de, ?dimensionDescription_fr, ?dimensionDescription_it, ?dimensionDescription_en, ?dimensionDescription_) AS ?dimensionDescription) + + OPTIONAL { ?dimension sh:order ?dimensionOrder . } + OPTIONAL { ?dimension sh:datatype ?dimensionDataType . } + OPTIONAL { + ?dimension ?dimensionDataKind . + ?dimensionDataKind rdf:type ?dimensionDataKindType . + } + } UNION { + ?cube cube:observationConstraint/sh:property/sh:path ?dimensionIri . + + { + SELECT * WHERE { + ?cube cube:observationSet/cube:observation ?observation . + FILTER(NOT EXISTS { ?cube cube:observationConstraint/sh:property/sh:datatype cube:Undefined . } && NOT EXISTS { ?observation ?p ""^^cube:Undefined . }) + } + LIMIT 10 + } + + ?observation ?dimensionIri ?observationValue . + + OPTIONAL { ?observationValue schema:name ?observationValueLabel_de . FILTER(LANG(?observationValueLabel_de) = "de") } + OPTIONAL { ?observationValue schema:name ?observationValueLabel_fr . FILTER(LANG(?observationValueLabel_fr) = "fr") } + OPTIONAL { ?observationValue schema:name ?observationValueLabel_it . FILTER(LANG(?observationValueLabel_it) = "it") } + OPTIONAL { ?observationValue schema:name ?observationValueLabel_en . FILTER(LANG(?observationValueLabel_en) = "en") } + OPTIONAL { ?observationValue schema:name ?observationValueLabel_ . FILTER(LANG(?observationValueLabel_) = "") } + BIND(COALESCE(?observationValueLabel_de, ?observationValueLabel_fr, ?observationValueLabel_it, ?observationValueLabel_en, ?observationValueLabel_) AS ?observationValueLabel) + } + }`, + { operation: "postUrlencoded" } + ); + + if (results.length === 0) { + throw new Error(`No cube found for ${iri}!`); + } + + const groupedResults = groupResults(results); + parseResults; + // console.log(JSON.stringify(groupedResults)); + // fs.writeFileSync("groupedResults.json", JSON.stringify(groupedResults)); + + return groupedResults as any; +}; + +const groupResults = (results: Quad[]) => { + let groupedResults: { + [key: string | number]: { + [key: string | number]: string | number | object; + }; + } = {}; + // Quad schema + // {subject: string, predicate: string, object: string, graph: string} + // convert to + // {subject: {predicate: object}} + results.forEach((quad) => { + if (groupedResults[quad.subject.value]) { + groupedResults[quad.subject.value][quad.predicate.value] = quad.object; + } else { + groupedResults[quad.subject.value] = {}; + groupedResults[quad.subject.value][quad.predicate.value] = quad.object; + } + }); + + return groupedResults; +}; + +const parseResults = (): DataCubePreview => { + return { + components: [], + observations: [], + }; +}; diff --git a/app/scripts/cube.ts b/app/scripts/cube.ts index 2728734395..e897529b09 100644 --- a/app/scripts/cube.ts +++ b/app/scripts/cube.ts @@ -130,11 +130,10 @@ const previewCube = async ({ .query( DataCubePreviewDocument, { - iri, sourceType, sourceUrl, locale, - latest, + cubeFilter: { iri, latest }, } ) .toPromise(); @@ -143,7 +142,7 @@ const previewCube = async ({ throw new Error(res.error.message); } - report(res.data?.dataCubeByIri?.observations); + report(res.data?.dataCubePreview?.observations); }; const main = async () => { diff --git a/codegen.yml b/codegen.yml index 186faf866b..af331dbd8d 100644 --- a/codegen.yml +++ b/codegen.yml @@ -25,6 +25,7 @@ generates: DataCubeComponents: "../domain/data#DataCubeComponents" DataCubeMetadata: "../domain/data#DataCubeMetadata" DataCubeObservations: "../domain/data#DataCubeObservations" + DataCubePreview: "../domain/data#DataCubePreview" app/graphql/resolver-types.ts: plugins: - "typescript" @@ -45,6 +46,7 @@ generates: DataCubeComponents: "../domain/data#DataCubeComponents" DataCubeMetadata: "../domain/data#DataCubeMetadata" DataCubeObservations: "../domain/data#DataCubeObservations" + DataCubePreview: "../domain/data#DataCubePreview" mappers: DataCube: "./shared-types#ResolvedDataCube" ObservationsQuery: "./shared-types#ResolvedObservationsQuery"