Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Run SPARQL query enhancements #813

Merged
merged 6 commits into from
Oct 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion app/.env.development
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
DATABASE_URL=postgres://postgres:password@localhost:5432/visualization_tool
ENDPOINT=sparql+https://lindas.admin.ch/query
SPARQL_GEO_ENDPOINT=https://geo.ld.admin.ch/query
SPARQL_EDITOR=https://int.lindas.admin.ch/sparql/
GRAPHQL_ENDPOINT=/api/graphql
WHITELISTED_DATA_SOURCES=["Prod", "Int", "Test"]
54 changes: 28 additions & 26 deletions app/components/chart-footnotes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,33 +17,35 @@ import { makeOpenDataLink } from "@/utils/opendata";

import { useQueryFilters } from "../charts/shared/chart-helpers";

const useStyles = makeStyles((theme: Theme) => ({
actions: {
marginTop: theme.spacing(2),
"--column-gap": "16px",
columnGap: "var(--column-gap)",
rowGap: 1,
display: "flex",
flexDirection: "row",
alignItems: "center",
flexWrap: "wrap",
overflow: "hidden",
export const useFootnotesStyles = makeStyles<Theme, { useMarginTop: boolean }>(
(theme) => ({
actions: {
marginTop: ({ useMarginTop }) => (useMarginTop ? theme.spacing(2) : 0),
"--column-gap": "16px",
columnGap: "var(--column-gap)",
rowGap: 1,
display: "flex",
flexDirection: "row",
alignItems: "center",
flexWrap: "wrap",
overflow: "hidden",

// Separator between flex elements, the trick to have them not displayed
// for each line leftmost element is to have them negatively positioned
// cut by the overflow hidden
"& > *:before": {
content: '" "',
display: "block",
height: "3px",
width: "3px ",
borderRadius: "3px",
position: "relative",
left: "calc(-1 * var(--column-gap) / 2)",
backgroundColor: theme.palette.grey[600],
// Separator between flex elements, the trick to have them not displayed
// for each line leftmost element is to have them negatively positioned
// cut by the overflow hidden
"& > *:before": {
content: '" "',
display: "block",
height: "3px",
width: "3px ",
borderRadius: "3px",
position: "relative",
left: "calc(-1 * var(--column-gap) / 2)",
backgroundColor: theme.palette.grey[600],
},
},
},
}));
})
);

export const ChartFootnotes = ({
dataSetIri,
Expand All @@ -58,7 +60,7 @@ export const ChartFootnotes = ({
configKey?: string;
onToggleTableView: () => void;
}) => {
const classes = useStyles();
const classes = useFootnotesStyles({ useMarginTop: true });
const locale = useLocale();
const [shareUrl, setShareUrl] = useState("");
const { state: isTablePreview, setStateRaw: setIsTablePreview } =
Expand Down
11 changes: 7 additions & 4 deletions app/components/debug-panel/DebugPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Inspector } from "react-inspector";

import { useInteractiveFilters } from "@/charts/shared/use-interactive-filters";
import { DataSource, useConfiguratorState } from "@/configurator";
import { SPARQL_EDITOR } from "@/domain/env";
import { dataSourceToSparqlEditorUrl } from "@/domain/datasource";
import { useDataCubeMetadataWithComponentValuesQuery } from "@/graphql/query-hooks";
import { Icon } from "@/icons";
import { useLocale } from "@/src";
Expand Down Expand Up @@ -80,6 +80,9 @@ const CubeMetadata = ({

const DebugConfigurator = () => {
const [configuratorState] = useConfiguratorState();
const sparqlEditorUrl = dataSourceToSparqlEditorUrl(
configuratorState.dataSource
);

return (
<>
Expand Down Expand Up @@ -107,13 +110,13 @@ const DebugConfigurator = () => {
) : (
<Typography variant="body1">Please select a dataset first</Typography>
)}
{SPARQL_EDITOR && (
{
<Button
component="a"
color="primary"
variant="text"
size="small"
href={`${SPARQL_EDITOR}#query=${encodeURIComponent(
href={`${sparqlEditorUrl}#query=${encodeURIComponent(
`#pragma describe.strategy cbd
#pragma join.hash off

Expand All @@ -125,7 +128,7 @@ DESCRIBE <${configuratorState.dataSet ?? ""}>`
>
<Typography variant="body2">Cube Metadata Query</Typography>
</Button>
)}
}
{configuratorState.dataSet ? (
<CubeMetadata
datasetIri={configuratorState.dataSet}
Expand Down
171 changes: 101 additions & 70 deletions app/configurator/components/dataset-preview.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { Trans } from "@lingui/macro";
import { Box, Button, Paper, Typography } from "@mui/material";
import { Box, Button, Paper, Theme, Typography } from "@mui/material";
import { makeStyles } from "@mui/styles";
import Head from "next/head";
import Link from "next/link";
import * as React from "react";

import { DataDownloadMenu } from "@/components/data-download";
import { useFootnotesStyles } from "@/components/chart-footnotes";
import { DataDownloadMenu, RunSparqlQuery } from "@/components/data-download";
import DebugPanel from "@/components/debug-panel";
import Flex from "@/components/flex";
import { HintRed, Loading, LoadingDataError } from "@/components/hint";
Expand All @@ -14,6 +16,61 @@ import { useDataCubePreviewQuery } from "@/graphql/query-hooks";
import { DataCubePublicationStatus } from "@/graphql/resolver-types";
import { useLocale } from "@/locales/use-locale";

const useStyles = makeStyles<Theme, { descriptionPresent: boolean }>(
(theme) => ({
root: {
flexGrow: 1,
flexDirection: "column",
justifyContent: "space-between",
},
header: {
alignItems: "center",
justifyContent: "space-between",
marginBottom: theme.spacing(6),
},
title: {
color: theme.palette.grey[800],
},
createChartButton: {
marginLeft: theme.spacing(6),
whiteSpace: "nowrap",
flexShrink: 0,
},
paper: {
borderRadius: theme.spacing(4),
paddingLeft: theme.spacing(5),
paddingTop: theme.spacing(6),
paddingRight: theme.spacing(5),
paddingBottom: theme.spacing(6),
},
description: {
marginBottom: theme.spacing(4),
color: theme.palette.grey[600],
},
tableWrapper: {
flexGrow: 1,
width: "100%",
position: "relative",
overflowX: "auto",
marginTop: ({ descriptionPresent }) =>
descriptionPresent ? theme.spacing(6) : 0,
},
footnotesWrapper: {
marginTop: theme.spacing(4),
justifyContent: "space-between",
},
numberOfRows: {
color: theme.palette.grey[600],
},
loadingWrapper: {
flexDirection: "column",
justifyContent: "space-between",
flexGrow: 1,
padding: theme.spacing(5),
},
})
);

export interface Preview {
iri: string;
label: string;
Expand All @@ -26,27 +83,26 @@ export const DataSetPreview = ({
dataSetIri: string;
dataSource: DataSource;
}) => {
const footnotesClasses = useFootnotesStyles({ useMarginTop: false });
const locale = useLocale();
const [{ data: metaData, fetching, error }] = useDataCubePreviewQuery({
const [{ data: metadata, fetching, error }] = useDataCubePreviewQuery({
variables: {
iri: dataSetIri,
sourceType: dataSource.type,
sourceUrl: dataSource.url,
locale,
},
});
const classes = useStyles({
descriptionPresent: !!metadata?.dataCubeByIri?.description,
});

if (metadata?.dataCubeByIri) {
const { dataCubeByIri } = metadata;

if (metaData && metaData.dataCubeByIri) {
const { dataCubeByIri } = metaData;
return (
<Flex
sx={{
flexGrow: 1,
flexDirection: "column",
justifyContent: "space-between",
}}
>
{metaData.dataCubeByIri.publicationStatus ===
<Flex className={classes.root}>
{dataCubeByIri.publicationStatus ===
DataCubePublicationStatus.Draft && (
<Box sx={{ mb: 4 }}>
<HintRed iconName="datasetError" iconSize={64}>
Expand All @@ -58,70 +114,59 @@ export const DataSetPreview = ({
</HintRed>
</Box>
)}
<Flex
sx={{ alignItems: "center", justifyContent: "space-between", mb: 6 }}
>
<Flex className={classes.header}>
<Head>
<title key="title">
{dataCubeByIri.title} - visualize.admin.ch
</title>
</Head>
<Typography component="div" variant="h1" sx={{ color: "grey.800" }}>
<Typography className={classes.title} component="div" variant="h1">
{dataCubeByIri.title}
</Typography>
<Link passHref href={`/create/new?cube=${dataCubeByIri.iri}`}>
<Button
component="a"
sx={{ ml: 6, whiteSpace: "nowrap", flexShrink: 0 }}
>
<Button className={classes.createChartButton} component="a">
<Trans id="browse.dataset.create-visualization">
Create visualization from dataset
</Trans>
</Button>
</Link>
</Flex>
<Paper
elevation={5}
sx={{
borderRadius: 8,
py: 6,
px: 5,
}}
>
<Typography
component="div"
variant="body2"
sx={{ mb: 4, color: "grey.600" }}
>
{dataCubeByIri.description}
</Typography>
<Paper className={classes.paper} elevation={5}>
{dataCubeByIri.description && (
<Typography
className={classes.description}
component="div"
variant="body2"
>
{dataCubeByIri.description}
</Typography>
)}

<Box
sx={{
flexGrow: 1,
width: "100%",
position: "relative",
overflowX: "auto",
mt: 6,
}}
>
<Box className={classes.tableWrapper}>
<DataSetPreviewTable
title={dataCubeByIri.title}
dataSetIri={dataCubeByIri.iri}
dataSource={dataSource}
dimensions={dataCubeByIri.dimensions}
measures={dataCubeByIri.measures}
observations={dataCubeByIri.observations.data}
/>
</Box>
<Flex sx={{ mt: 4, justifyContent: "space-between" }}>
<DataDownloadMenu
dataSetIri={dataSetIri}
dataSource={dataSource}
title={dataCubeByIri.title}
/>
<Flex className={classes.footnotesWrapper}>
<Flex className={footnotesClasses.actions}>
<DataDownloadMenu
dataSetIri={dataSetIri}
dataSource={dataSource}
title={dataCubeByIri.title}
/>
{dataCubeByIri.observations.sparqlEditorUrl && (
<RunSparqlQuery
url={dataCubeByIri.observations.sparqlEditorUrl}
/>
)}
</Flex>
<Typography
className={classes.numberOfRows}
variant="body2"
sx={{ color: "grey.600", fontWeight: "light" }}
sx={{ fontWeight: "light" }}
>
<Trans id="datatable.showing.first.rows">
Showing first 10 rows
Expand All @@ -134,27 +179,13 @@ export const DataSetPreview = ({
);
} else if (fetching) {
return (
<Flex
sx={{
flexDirection: "column",
justifyContent: "space-between",
flexGrow: 1,
p: 5,
}}
>
<Flex className={classes.loadingWrapper}>
<Loading />
</Flex>
);
} else {
return (
<Flex
sx={{
flexDirection: "column",
justifyContent: "space-between",
flexGrow: 1,
p: 5,
}}
>
<Flex className={classes.loadingWrapper}>
<LoadingDataError message={error?.message} />
</Flex>
);
Expand Down
Loading