diff --git a/app/browse/datatable.tsx b/app/browse/datatable.tsx
index e370b28e1..186524ef8 100644
--- a/app/browse/datatable.tsx
+++ b/app/browse/datatable.tsx
@@ -80,24 +80,16 @@ export const PreviewTable = ({
const [sortDirection, setSortDirection] = useState<"asc" | "desc">();
const formatters = useDimensionFormatters(headers);
const sortedObservations = useMemo(() => {
- if (sortBy === undefined) {
+ if (!sortBy) {
return observations;
}
const compare = sortDirection === "asc" ? ascending : descending;
- const valuesIndex = uniqueMapBy(sortBy.values, (x) => x.label);
+ const valuesIndex = uniqueMapBy(sortBy.values, (d) => d.label);
const convert =
isNumericalMeasure(sortBy) || sortBy.isNumerical
- ? (d: string) => +d
- : (d: string) => {
- const value = valuesIndex.get(d);
-
- if (value?.position) {
- return value.position;
- }
-
- return d;
- };
+ ? (value: string) => +value
+ : (value: string) => valuesIndex.get(value)?.position ?? value;
return [...observations].sort((a, b) =>
compare(
@@ -111,11 +103,7 @@ export const PreviewTable = ({
// Tooltip contained inside the table so as not to overflow when table is scrolled
const tooltipProps = useMemo(
- () => ({
- PopperProps: {
- container: tooltipContainerRef.current,
- },
- }),
+ () => ({ PopperProps: { container: tooltipContainerRef.current } }),
[]
);
diff --git a/app/browser/dataset-preview.tsx b/app/browser/dataset-preview.tsx
index 443235200..856773dd3 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 && (
-
- )}
);
diff --git a/app/domain/data.ts b/app/domain/data.ts
index a4d214200..1fb6b0f0f 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 = {
+ dimensions: Dimension[];
+ measures: Measure[];
+ 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 4cc9c08f2..a278e2e52 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 436d9a706..1acad2aa5 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 1d11d17da..d62abb6e2 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 ca20e7f93..7456b87ce 100644
--- a/app/graphql/resolvers/index.ts
+++ b/app/graphql/resolvers/index.ts
@@ -9,6 +9,7 @@ import {
DataCubeResolvers,
QueryResolvers,
Resolvers,
+ ScaleType,
} from "@/graphql/resolver-types";
import * as RDF from "@/graphql/resolvers/rdf";
import * as SQL from "@/graphql/resolvers/sql";
@@ -37,6 +38,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);
@@ -83,10 +88,10 @@ const DataCube: DataCubeResolvers = {
};
export const resolveDimensionType = (
- component: ResolvedDimension
+ dataKind: ResolvedDimension["data"]["dataKind"] | undefined,
+ scaleType: ScaleType | undefined,
+ related: ResolvedDimension["data"]["related"]
): DimensionType => {
- const { dataKind, scaleType, related } = component.data;
-
if (related.some((d) => d.type === "StandardError")) {
return "StandardErrorDimension";
}
@@ -113,16 +118,14 @@ export const resolveDimensionType = (
};
export const resolveMeasureType = (
- component: ResolvedDimension
+ scaleType: ScaleType | undefined
): MeasureType => {
- const { scaleType } = component.data;
-
return scaleType === "Ordinal" ? "OrdinalMeasure" : "NumericalMeasure";
};
const mkDimensionResolvers = (_: string): Resolvers["Dimension"] => ({
- __resolveType(dimension) {
- return resolveDimensionType(dimension);
+ __resolveType({ data: { dataKind, scaleType, related } }) {
+ return resolveDimensionType(dataKind, scaleType, related);
},
iri: ({ data: { iri } }) => iri,
label: ({ data: { name } }) => name,
@@ -201,8 +204,8 @@ export const resolvers: Resolvers = {
},
},
Dimension: {
- __resolveType(dimension) {
- return resolveDimensionType(dimension);
+ __resolveType({ data: { dataKind, scaleType, related } }) {
+ return resolveDimensionType(dataKind, scaleType, related);
},
},
NominalDimension: {
@@ -273,7 +276,7 @@ export const resolvers: Resolvers = {
},
Measure: {
__resolveType(dimension) {
- return resolveMeasureType(dimension);
+ return resolveMeasureType(dimension.data.scaleType);
},
},
NumericalMeasure: {
diff --git a/app/graphql/resolvers/rdf.ts b/app/graphql/resolvers/rdf.ts
index d59c72a5a..69cd3f3a0 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";
@@ -209,7 +210,7 @@ export const dataCubeComponents: NonNullable<
if (data.isMeasureDimension) {
const result: Measure = {
- __typename: resolveMeasureType(component),
+ __typename: resolveMeasureType(component.data.scaleType),
isCurrency: data.isCurrency,
isDecimal: data.isDecimal,
currencyExponent: data.currencyExponent,
@@ -219,7 +220,12 @@ export const dataCubeComponents: NonNullable<
measures.push(result);
} else {
- const dimensionType = resolveDimensionType(component);
+ const { dataKind, scaleType, related } = component.data;
+ const dimensionType = resolveDimensionType(
+ dataKind,
+ scaleType,
+ related
+ );
const hierarchy = true // TODO: make this configurable
? await queryHierarchy(
component,
@@ -322,6 +328,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 266b60ebc..3316469ec 100644
--- a/app/graphql/resolvers/sql.ts
+++ b/app/graphql/resolvers/sql.ts
@@ -324,3 +324,12 @@ export const dataCubeObservations: NonNullable<
sparqlEditorUrl: "",
};
};
+
+export const dataCubePreview: NonNullable =
+ async () => {
+ return {
+ dimensions: [],
+ measures: [],
+ observations: [],
+ };
+ };
diff --git a/app/graphql/schema.graphql b/app/graphql/schema.graphql
index e8948abb9..eea01b77a 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/parse.ts b/app/rdf/parse.ts
index 96d67c56d..853a6b846 100644
--- a/app/rdf/parse.ts
+++ b/app/rdf/parse.ts
@@ -112,9 +112,9 @@ const timeFormats = new Map([
[ns.xsd.dateTime.value, "%Y-%m-%dT%H:%M:%S"],
]);
-export const getScaleType = (dim: CubeDimension): ScaleType | undefined => {
- const scaleTypeTerm = dim.out(ns.qudt.scaleType).term;
-
+export const getScaleType = (
+ scaleTypeTerm: Term | undefined
+): ScaleType | undefined => {
return scaleTypeTerm?.equals(ns.qudt.NominalScale)
? ScaleType.Nominal
: scaleTypeTerm?.equals(ns.qudt.OrdinalScale)
@@ -126,7 +126,7 @@ export const getScaleType = (dim: CubeDimension): ScaleType | undefined => {
: undefined;
};
-const getDataKind = (term: Term | undefined) => {
+export const getDataKind = (term: Term | undefined) => {
return term?.equals(ns.time.GeneralDateTimeDescription)
? "Time"
: term?.equals(ns.schema.GeoCoordinates)
@@ -228,18 +228,10 @@ export const parseCubeDimension = ({
parseDimensionDatatype(dim);
const isDecimal = dataType?.equals(ns.xsd.decimal) ?? false;
- const isNumerical =
- dataType?.equals(ns.xsd.int) ||
- dataType?.equals(ns.xsd.integer) ||
- isDecimal ||
- dataType?.equals(ns.xsd.float) ||
- dataType?.equals(ns.xsd.double) ||
- false;
-
+ const isNumerical = getIsNumerical(dataType);
const isKeyDimension = dim
.out(ns.rdf.type)
.terms.some((t) => t.equals(ns.cube.KeyDimension));
-
const isMeasureDimension = dim
.out(ns.rdf.type)
.terms.some((t) => t.equals(ns.cube.MeasureDimension));
@@ -248,14 +240,7 @@ export const parseCubeDimension = ({
const unitTerm = dim.out(ns.qudt.unit).term ?? dim.out(ns.qudt.hasUnit).term;
const unit = unitTerm ? units?.get(unitTerm.value) : undefined;
const unitLabel = unit?.label?.value;
-
- const rawOrder = dim.out(ns.sh.order).value;
- const order = rawOrder !== undefined ? parseInt(rawOrder, 10) : undefined;
-
- const resolution =
- dataType?.equals(ns.xsd.int) || dataType?.equals(ns.xsd.integer)
- ? 0
- : undefined;
+ const resolution = parseResolution(dataType);
return {
cube,
@@ -281,15 +266,45 @@ export const parseCubeDimension = ({
currencyExponent: unit?.currencyExponent?.value
? parseInt(unit.currencyExponent.value)
: undefined,
- order,
+ order: parseNumericalTerm(dim.out(ns.sh.order).term),
dataKind: getDataKind(dataKindTerm),
- timeUnit: timeUnits.get(timeUnitTerm?.value ?? ""),
- timeFormat: timeFormats.get(dataType?.value ?? ""),
- scaleType: getScaleType(dim),
+ timeUnit: getTimeUnit(timeUnitTerm),
+ timeFormat: getTimeFormat(dataType),
+ scaleType: getScaleType(dim.out(ns.qudt.scaleType).term),
},
};
};
+export const parseNumericalTerm = (term: Term | undefined) => {
+ return term !== undefined ? parseInt(term.value, 10) : undefined;
+};
+
+export const getTimeUnit = (timeUnitTerm: Term | undefined) => {
+ return timeUnits.get(timeUnitTerm?.value ?? "");
+};
+
+export const getTimeFormat = (dataTypeTerm: Term | undefined) => {
+ return timeFormats.get(dataTypeTerm?.value ?? "");
+};
+
+export const parseResolution = (dataTypeTerm: Term | undefined) => {
+ return dataTypeTerm?.equals(ns.xsd.int) ||
+ dataTypeTerm?.equals(ns.xsd.integer)
+ ? 0
+ : undefined;
+};
+
+export const getIsNumerical = (dataTypeTerm: Term | undefined) => {
+ return (
+ dataTypeTerm?.equals(ns.xsd.int) ||
+ dataTypeTerm?.equals(ns.xsd.integer) ||
+ dataTypeTerm?.equals(ns.xsd.float) ||
+ dataTypeTerm?.equals(ns.xsd.double) ||
+ dataTypeTerm?.equals(ns.xsd.decimal) ||
+ false
+ );
+};
+
const timeIntervals = new Map([
[ns.time.unitYear.value, timeYear],
[ns.time.unitMonth.value, timeMonth],
diff --git a/app/rdf/queries.ts b/app/rdf/queries.ts
index 4b132c2f4..dbac475c0 100644
--- a/app/rdf/queries.ts
+++ b/app/rdf/queries.ts
@@ -400,7 +400,7 @@ export const getCubeDimensionValuesWithMetadata = async ({
const result: DimensionValue[] = [];
if (namedNodes.length > 0) {
- const scaleType = getScaleType(dimension);
+ const scaleType = getScaleType(dimension.out(ns.qudt.scaleType).term);
const [labels, descriptions, literals, unversioned] = await Promise.all([
loadResourceLabels({
ids: namedNodes,
diff --git a/app/rdf/query-cube-preview.spec.ts b/app/rdf/query-cube-preview.spec.ts
new file mode 100644
index 000000000..110a83973
--- /dev/null
+++ b/app/rdf/query-cube-preview.spec.ts
@@ -0,0 +1,111 @@
+import rdf from "rdf-ext";
+import ParsingClient from "sparql-http-client/ParsingClient";
+
+import * as ns from "./namespace";
+import { getCubePreview } from "./query-cube-preview";
+
+jest.mock("rdf-cube-view-query", () => ({}));
+jest.mock("./extended-cube", () => ({}));
+jest.mock("@zazuko/cube-hierarchy-query/index", () => ({}));
+
+describe("dataset preview", () => {
+ const dim = rdf.blankNode();
+ const measure = rdf.blankNode();
+ const observation = rdf.namedNode(
+ "https://environment.ld.admin.ch/foen/gefahren-waldbrand-warnung/observation/336>"
+ );
+ const quads = [
+ rdf.quad(
+ dim,
+ ns.sh.path,
+ rdf.namedNode(
+ "https://environment.ld.admin.ch/foen/gefahren-waldbrand-warnung/region"
+ )
+ ),
+ rdf.quad(dim, ns.schema.name, rdf.literal("Region")),
+ rdf.quad(
+ measure,
+ ns.sh.path,
+ rdf.namedNode(
+ "https://environment.ld.admin.ch/foen/gefahren-waldbrand-warnung/level"
+ )
+ ),
+ rdf.quad(measure, ns.schema.name, rdf.literal("Danger ratings")),
+ rdf.quad(measure, ns.rdf.type, ns.cube.MeasureDimension),
+ rdf.quad(
+ observation,
+ rdf.namedNode(
+ "https://environment.ld.admin.ch/foen/gefahren-waldbrand-warnung/region"
+ ),
+ rdf.namedNode(
+ "https://ld.admin.ch/dimension/bgdi/biota/forestfirewarningregions/1300"
+ )
+ ),
+ rdf.quad(
+ observation,
+ rdf.namedNode(
+ "https://environment.ld.admin.ch/foen/gefahren-waldbrand-warnung/region"
+ ),
+ rdf.literal("Bern")
+ ),
+ rdf.quad(
+ rdf.namedNode(
+ "https://ld.admin.ch/dimension/bgdi/biota/forestfirewarningregions/1300"
+ ),
+ ns.schema.position,
+ rdf.literal("3")
+ ),
+ rdf.quad(
+ observation,
+ rdf.namedNode(
+ "https://environment.ld.admin.ch/foen/gefahren-waldbrand-warnung/level"
+ ),
+ rdf.namedNode(
+ "https://environment.ld.admin.ch/foen/gefahren-waldbrand-warnung/level/1"
+ )
+ ),
+ rdf.quad(
+ observation,
+ rdf.namedNode(
+ "https://environment.ld.admin.ch/foen/gefahren-waldbrand-warnung/level"
+ ),
+ rdf.literal("considerable danger")
+ ),
+ ];
+ const sparqlClient = {
+ query: {
+ construct: async () => Promise.resolve(quads),
+ },
+ } as any as ParsingClient;
+
+ it("should return correct preview", async () => {
+ const { dimensions, measures, observations } = await getCubePreview(
+ "awesome iri",
+ {
+ sparqlClient,
+ locale: "en",
+ latest: true,
+ }
+ );
+ const dim = dimensions[0];
+
+ expect(dim.iri).toEqual(
+ "https://environment.ld.admin.ch/foen/gefahren-waldbrand-warnung/region"
+ );
+ expect(dim.label).toEqual("Region");
+ expect(dim.values).toHaveLength(1);
+ expect(dim.values[0].position).toEqual(3);
+
+ const measure = measures[0];
+
+ expect(measure.iri).toEqual(
+ "https://environment.ld.admin.ch/foen/gefahren-waldbrand-warnung/level"
+ );
+ expect(measure.label).toEqual("Danger ratings");
+
+ const obs = observations[0];
+
+ expect(obs[dim.iri]).toEqual("Bern");
+ expect(obs[measure.iri]).toEqual("considerable danger");
+ });
+});
diff --git a/app/rdf/query-cube-preview.ts b/app/rdf/query-cube-preview.ts
new file mode 100644
index 000000000..fca32b223
--- /dev/null
+++ b/app/rdf/query-cube-preview.ts
@@ -0,0 +1,321 @@
+import groupBy from "lodash/groupBy";
+import uniqBy from "lodash/uniqBy";
+import rdf from "rdf-ext";
+import { NamedNode, Quad } from "rdf-js";
+import ParsingClient from "sparql-http-client/ParsingClient";
+
+import {
+ BaseComponent,
+ BaseDimension,
+ DataCubePreview,
+ Dimension,
+ DimensionValue,
+ Measure,
+ Observation,
+ TemporalDimension,
+} from "@/domain/data";
+import { truthy } from "@/domain/types";
+import { resolveDimensionType, resolveMeasureType } from "@/graphql/resolvers";
+
+import * as ns from "./namespace";
+import {
+ getDataKind,
+ getIsNumerical,
+ getScaleType,
+ getTimeFormat,
+ getTimeUnit,
+ parseNumericalTerm,
+ parseResolution,
+} from "./parse";
+import { buildLocalizedSubQuery } from "./query-utils";
+
+export const getCubePreview = async (
+ iri: string,
+ options: {
+ locale: string;
+ latest: Boolean;
+ sparqlClient: ParsingClient;
+ }
+): Promise => {
+ const { sparqlClient, locale } = options;
+ const qs = await sparqlClient.query.construct(
+ `PREFIX cube:
+PREFIX meta:
+PREFIX qudt:
+PREFIX rdf:
+PREFIX rdfs:
+PREFIX schema:
+PREFIX sh:
+PREFIX time:
+PREFIX xsd:
+
+CONSTRUCT {
+ ?dimension sh:path ?dimensionIri .
+ ?dimension sh:datatype ?dimensionDataType .
+ ?dimension rdf:type ?dimensionType .
+ ?dimension qudt:scaleType ?dimensionScaleType .
+ ?dimension qudt:unit ?dimensionUnit .
+ ?dimensionUnit schema:name ?dimensionUnitLabel .
+ ?dimensionUnit qudt:CurrencyUnit ?dimensionUnitIsCurrency .
+ ?dimensionUnit qudt:currencyExponent ?dimensionUnitCurrencyExponent .
+ ?dimension sh:order ?dimensionOrder .
+ ?dimension meta:dataKind ?dimensionDataKind .
+ ?dimensionDataKind rdf:type ?dimensionDataKindType .
+ ?dimensionDataKind time:unitType ?dimensionTimeUnitType .
+ ?dimension schema:name ?dimensionLabel .
+ ?dimension schema:description ?dimensionDescription .
+
+ ?observation ?observationPredicate ?observationValue .
+ ?observation ?observationPredicate ?observationLabel .
+ ?observationValue schema:position ?observationPosition .
+} WHERE {
+ VALUES ?cube { <${iri}> }
+ FILTER(EXISTS { ?cube a cube:Cube . }) {}
+ UNION {
+ ?cube cube:observationConstraint/sh:property ?dimension .
+ ?dimension sh:path ?dimensionIri .
+ OPTIONAL { ?dimension rdf:type ?dimensionType . }
+ OPTIONAL { ?dimension qudt:scaleType ?dimensionScaleType . }
+ OPTIONAL {
+ { ?dimension qudt:unit ?dimensionUnit . }
+ UNION { ?dimension qudt:hasUnit ?dimensionUnit . }
+ OPTIONAL { ?dimensionUnit rdfs:label ?dimensionUnitRdfsLabel . }
+ OPTIONAL { ?dimensionUnit qudt:symbol ?dimensionUnitSymbol . }
+ OPTIONAL { ?dimensionUnit qudt:ucumCode ?dimensionUnitUcumCode . }
+ OPTIONAL { ?dimensionUnit qudt:expression ?dimensionUnitExpression . }
+ OPTIONAL { ?dimensionUnit ?dimensionUnitIsCurrency qudt:CurrencyUnit . }
+ OPTIONAL { ?dimensionUnit qudt:currencyExponent ?dimensionUnitCurrencyExponent . }
+ BIND(STR(COALESCE(STR(?dimensionUnitSymbol), STR(?dimensionUnitUcumCode), STR(?dimensionUnitExpression), STR(?dimensionUnitRdfsLabel))) AS ?dimensionUnitLabel)
+ FILTER (LANG(?dimensionUnitRdfsLabel) = "en")
+ }
+ OPTIONAL { ?dimension sh:order ?dimensionOrder . }
+ OPTIONAL {
+ ?dimension meta:dataKind ?dimensionDataKind .
+ ?dimensionDataKind rdf:type ?dimensionDataKindType .
+ }
+ OPTIONAL {
+ ?dimension meta:dataKind ?dimensionDataKind .
+ ?dimensionDataKind time:unitType ?dimensionTimeUnitType .
+ }
+ ${buildLocalizedSubQuery("dimension", "schema:name", "dimensionLabel", {
+ locale,
+ })}
+ ${buildLocalizedSubQuery(
+ "dimension",
+ "schema:description",
+ "dimensionDescription",
+ { locale }
+ )}
+ FILTER(?dimensionIri != cube:observedBy && ?dimensionIri != rdf:type)
+ } UNION {
+ ?cube cube:observationConstraint/sh:property/sh:path ?observationPredicate .
+ { SELECT * WHERE {
+ { SELECT * WHERE {
+ ?cube cube:observationSet ?observationSet .
+ ?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 ?observationPredicate ?observationValue .
+ ${buildLocalizedSubQuery(
+ "observationValue",
+ "schema:name",
+ "observationLabel",
+ { locale }
+ )}
+ OPTIONAL { ?observationValue schema:position ?observationPosition . }
+ FILTER(?observationPredicate != cube:observedBy && ?observationPredicate != rdf:type)
+ }}
+ }
+}`,
+ { operation: "postUrlencoded" }
+ );
+
+ if (qs.length === 0) {
+ throw new Error(`No cube found for ${iri}!`);
+ }
+
+ const sQs = groupBy(qs, (q) => q.subject.value);
+ const spQs = Object.fromEntries(
+ Object.entries(sQs).map(([k, v]) => {
+ const pQs = groupBy(v, (q) => q.predicate.value);
+ return [k, pQs];
+ })
+ );
+
+ const dimensions: Dimension[] = [];
+ const measures: Measure[] = [];
+ const observations: Observation[] = [];
+ const qsDims = qs.filter(({ predicate: p }) => p.equals(ns.sh.path));
+ const dimMetadataByDimIri = qsDims.reduce((acc, dim) => {
+ acc[dim.object.value] = {
+ values: [],
+ dataType: rdf.namedNode(""),
+ };
+ return acc;
+ }, {} as Record);
+ // Only take quads that use dimension iris as predicates (observation values)
+ const qUniqueObservations = uniqBy(
+ qs.filter(({ predicate: p }) => qsDims.some((q) => q.object.equals(p))),
+ ({ subject: s }) => s.value
+ );
+ qUniqueObservations.forEach(({ subject: s }) => {
+ const sqDimValues = uniqBy(
+ qsDims
+ .map((quad) => spQs[s.value]?.[quad.object.value])
+ .flat()
+ .filter(truthy),
+ (d) => d.predicate.value
+ );
+ const observation: Observation = {};
+ sqDimValues.forEach((quad) => {
+ const qDimIri = quad.predicate;
+ const dimIri = qDimIri.value;
+ const qDimValue = quad.object;
+ let qPosition: Quad | undefined;
+
+ if (!observation[dimIri]) {
+ // Retrieve the label of the observation value if it's a named node
+ if (qDimValue.termType === "NamedNode") {
+ const sIri = qs.find((q) => q.object.equals(quad.object));
+ const qLabel = qs.find(
+ ({ subject: s, predicate: p, object: o }) =>
+ s.equals(sIri?.subject) &&
+ p.equals(qDimIri) &&
+ o.termType === "Literal"
+ );
+
+ if (qLabel?.object.termType === "Literal") {
+ dimMetadataByDimIri[dimIri].dataType = qLabel.object.datatype;
+ }
+
+ if (sIri?.object.value) {
+ qPosition =
+ spQs[sIri.object.value]?.[ns.schema.position.value]?.[0];
+ }
+
+ observation[qDimIri.value] = qLabel?.object.value ?? qDimValue.value;
+ } else {
+ if (qDimValue.termType === "Literal") {
+ dimMetadataByDimIri[dimIri].dataType = qDimValue.datatype;
+ }
+
+ observation[qDimIri.value] = qDimValue.value;
+ }
+ }
+
+ const dimensionValue: DimensionValue = {
+ value: qDimValue.value,
+ label: `${observation[qDimIri.value]}`,
+ position: qPosition ? +qPosition.object.value : undefined,
+ };
+ dimMetadataByDimIri[dimIri].values.push(dimensionValue);
+ });
+
+ observations.push(observation);
+ });
+
+ for (const dimIri in dimMetadataByDimIri) {
+ dimMetadataByDimIri[dimIri].values = uniqBy(
+ dimMetadataByDimIri[dimIri].values,
+ (d) => d.value
+ ).sort((a, b) =>
+ (a.position ?? a.label) > (b.position ?? b.label) ? 1 : -1
+ );
+ }
+
+ qsDims.map(({ subject: s, object: o }) => {
+ const dimIri = o.value;
+ const qsDim = sQs[s.value];
+ const pQsDim = groupBy(qsDim, (q) => q.predicate.value);
+ const qLabel = pQsDim[ns.schema.name.value]?.[0];
+ const qDesc = pQsDim[ns.schema.description.value]?.[0];
+ const qOrder = pQsDim[ns.sh.order.value]?.[0];
+ const qsType = pQsDim[ns.rdf.type.value];
+ const qScaleType = pQsDim[ns.qudt.scaleType.value]?.[0];
+ const scaleType = getScaleType(qScaleType?.object);
+ const dataType = dimMetadataByDimIri[dimIri].dataType;
+ const qUnit = pQsDim[ns.qudt.unit.value]?.[0];
+ const qUnitLabel = spQs[qUnit?.object.value]?.[ns.schema.name.value]?.[0];
+ const qDataKind = pQsDim[ns.cube("meta/dataKind").value]?.[0];
+ const qDataKindType =
+ spQs[qDataKind?.object.value]?.[ns.rdf.type.value]?.[0];
+ const qTimeUnitType =
+ spQs[qDataKind?.object.value]?.[ns.time.unitType.value]?.[0];
+ const qIsCurrency =
+ spQs[qUnit?.object.value]?.[ns.qudt.CurrencyUnit.value]?.[0];
+ const qCurrencyExponent =
+ spQs[qUnit?.object.value]?.[ns.qudt.currencyExponent.value]?.[0];
+ const isKeyDimension = qsType?.some((q) =>
+ q.object.equals(ns.cube.KeyDimension)
+ );
+ const isMeasureDimension = qsType?.some((q) =>
+ q.object.equals(ns.cube.MeasureDimension)
+ );
+
+ const baseComponent: BaseComponent = {
+ cubeIri: iri,
+ iri: dimIri,
+ label: qLabel?.object.value ?? "",
+ description: qDesc?.object.value,
+ scaleType,
+ unit: qUnitLabel?.object.value,
+ order: parseNumericalTerm(qOrder?.object),
+ isNumerical: false,
+ isKeyDimension,
+ values: dimMetadataByDimIri[dimIri].values,
+ };
+
+ if (isMeasureDimension) {
+ const isDecimal = dataType.equals(ns.xsd.decimal) ?? false;
+ const result: Measure = {
+ ...baseComponent,
+ __typename: resolveMeasureType(scaleType),
+ isCurrency: qIsCurrency ? true : false,
+ isDecimal,
+ currencyExponent: parseNumericalTerm(qCurrencyExponent?.object),
+ resolution: parseResolution(dataType),
+ isNumerical: getIsNumerical(dataType),
+ };
+
+ measures.push(result);
+ } else {
+ const dimensionType = resolveDimensionType(
+ getDataKind(qDataKindType?.object),
+ scaleType,
+ []
+ );
+ const baseDimension: BaseDimension = baseComponent;
+
+ switch (dimensionType) {
+ case "TemporalDimension": {
+ const timeUnit = getTimeUnit(qTimeUnitType?.object);
+ const timeFormat = getTimeFormat(dataType);
+
+ if (!timeFormat || !timeUnit) {
+ throw new Error(
+ `Temporal dimension ${dimIri} has no timeFormat or timeUnit!`
+ );
+ }
+
+ const dimension: TemporalDimension = {
+ ...baseDimension,
+ __typename: dimensionType,
+ timeFormat,
+ timeUnit,
+ };
+ dimensions.push(dimension);
+ break;
+ }
+ default: {
+ const dimension: Exclude = {
+ ...baseDimension,
+ __typename: dimensionType,
+ };
+ dimensions.push(dimension);
+ }
+ }
+ }
+ });
+
+ return { dimensions, measures, observations };
+};
diff --git a/app/rdf/query-utils.ts b/app/rdf/query-utils.ts
index 3200e5519..b38d718fa 100644
--- a/app/rdf/query-utils.ts
+++ b/app/rdf/query-utils.ts
@@ -13,9 +13,11 @@ export const buildLocalizedSubQuery = (
{
locale,
fallbackToNonLocalized,
+ additionalFallbacks,
}: {
locale: string;
fallbackToNonLocalized?: boolean;
+ additionalFallbacks?: string[];
}
) => {
// Include the empty locale as well.
@@ -37,6 +39,10 @@ export const buildLocalizedSubQuery = (
}
BIND(COALESCE(${locales.map((locale) => `?${o}_${locale}`).join(", ")}${
fallbackToNonLocalized ? `, ?${o}_raw` : ``
+ }${
+ additionalFallbacks
+ ? ", " + additionalFallbacks.map((d) => `?${d}`).join(", ")
+ : ""
}) AS ?${o})`;
};
diff --git a/app/scripts/cube.ts b/app/scripts/cube.ts
index 272873439..e897529b0 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 186faf866..af331dbd8 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"