Skip to content

Commit

Permalink
feat: add relation section to dataset form (#884)
Browse files Browse the repository at this point in the history
  • Loading branch information
hegeaal authored Dec 2, 2024
1 parent 7595171 commit c6e0e29
Show file tree
Hide file tree
Showing 11 changed files with 396 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { getDatasetById } from '../../../../../actions/actions';
import { DatasetForm } from '../../../../../../components/dataset-form';

import { Params } from 'next/dist/shared/lib/router/utils/route-matcher';
import { getTranslateText, localization } from '@catalog-frontend/utils';
import { getTranslateText, getValidSession, localization } from '@catalog-frontend/utils';
import { Organization } from '@catalog-frontend/types';
import {
getAllDatasetSeries,
getDatasetTypes,
getDataThemes,
getFrequencies,
Expand All @@ -21,6 +22,9 @@ export default async function EditDatasetPage({ params }: Params) {
const referenceDataEnv = process.env.FDK_BASE_URI ?? '';
const dataset = await getDatasetById(catalogId, datasetId);
const organization: Organization = await getOrganization(catalogId).then((res) => res.json());
const session = await getValidSession();
const accessToken = session?.accessToken;
const datasetSeries = await getAllDatasetSeries(catalogId, accessToken).then((res) => res.json());

const [
losThemesResponse,
Expand Down Expand Up @@ -79,6 +83,7 @@ export default async function EditDatasetPage({ params }: Params) {
searchEnv={searchEnv}
referenceDataEnv={referenceDataEnv}
referenceData={referenceData}
datasetSeries={datasetSeries._embedded.datasets}
></DatasetForm>
</div>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import { Breadcrumbs, BreadcrumbType, PageBanner } from '@catalog-frontend/ui';
import { DatasetForm } from '../../../../../components/dataset-form';
import { datasetToBeCreatedTemplate } from '../../../../../components/dataset-form/utils/dataset-initial-values';
import { Params } from 'next/dist/shared/lib/router/utils/route-matcher';
import { getTranslateText, localization } from '@catalog-frontend/utils';
import { getTranslateText, getValidSession, localization } from '@catalog-frontend/utils';
import { Organization } from '@catalog-frontend/types';
import {
getAllDatasetSeries,
getDatasetTypes,
getDataThemes,
getFrequencies,
Expand All @@ -20,6 +21,9 @@ export default async function NewDatasetPage({ params }: Params) {
const organization: Organization = await getOrganization(catalogId).then((res) => res.json());
const searchEnv = process.env.FDK_SEARCH_SERVICE_BASE_URI ?? '';
const referenceDataEnv = process.env.FDK_BASE_URI ?? '';
const session = await getValidSession();
const accessToken = session?.accessToken;
const datasetSeries = await getAllDatasetSeries(catalogId, accessToken).then((res) => res.json());

const [
losThemesResponse,
Expand Down Expand Up @@ -74,6 +78,7 @@ export default async function NewDatasetPage({ params }: Params) {
referenceData={referenceData}
searchEnv={searchEnv}
referenceDataEnv={referenceDataEnv}
datasetSeries={datasetSeries._embedded.datasets}
></DatasetForm>
</div>
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
import { useState } from 'react';
import { Dataset, DatasetSeries } from '@catalog-frontend/types';
import { AddButton, DeleteButton, FormContainer } from '@catalog-frontend/ui';
import { getTranslateText, localization } from '@catalog-frontend/utils';
import { Heading, Combobox, Textfield } from '@digdir/designsystemet-react';
import { Field, FieldArray, useFormikContext } from 'formik';
import relations from '../utils/relations.json';
import { useSearchDatasetsByUri, useSearchDatasetSuggestions } from '../../../hooks/useSearchService';

type TitleSectionProps = {
searchEnv: string;
datasetSeries: DatasetSeries[];
};

export const RelationsSection = ({ searchEnv, datasetSeries }: TitleSectionProps) => {
const { setFieldValue, values, errors } = useFormikContext<Dataset>();
const [searchQuery, setSearchQuery] = useState('');

const getUriList = () => {
return values.references?.map((reference) => reference.source.uri).filter((uri) => uri) ?? [];
};

const { data: searchHits, isLoading: searching } = useSearchDatasetSuggestions(searchEnv, searchQuery);
const { data: selectedValues, isLoading } = useSearchDatasetsByUri(searchEnv, getUriList());

const comboboxOptions = [
...new Map(
[
...(searchHits ?? []),
...(selectedValues ?? []),
...(getUriList() ?? []).map((uri) => {
const foundItem =
searchHits?.find((item) => item.uri === uri) || selectedValues?.find((item) => item.uri === uri);

return {
uri,
title: foundItem?.title ?? null,
};
}),
].map((option) => [option.uri, option]),
).values(),
];

return (
<div>
<Heading
size='sm'
spacing
>
{localization.datasetForm.heading.relations}
</Heading>
<FormContainer>
<FormContainer.Header
title={localization.datasetForm.heading.relationsDataset}
subtitle={localization.datasetForm.helptext.relationsDataset}
/>

<FieldArray name='references'>
{({ remove, push }) => (
<div>
{values.references?.map((_, index) => (
<div key={index}>
<Combobox
label={localization.datasetForm.fieldLabel.relationType}
onValueChange={(value) =>
setFieldValue(`references[${index}].referenceType.code`, value.toString())
}
value={
values.references?.[index]?.referenceType?.code
? [values.references?.[index]?.referenceType?.code]
: []
}
placeholder={`${localization.datasetForm.fieldLabel.choseRelation}...`}
>
<Combobox.Empty>{localization.search.noHits}</Combobox.Empty>
{relations.map((relation) => (
<Combobox.Option
key={relation?.code}
value={relation?.code}
description={`${relation?.uriAsPrefix} (${relation?.uri})`}
>
{getTranslateText(relation?.label)}
</Combobox.Option>
))}
</Combobox>

{!isLoading && (
<Combobox
label={localization.datasetForm.fieldLabel.dataset}
onChange={(input: any) => setSearchQuery(input.target.value)}
onValueChange={(value) => {
setFieldValue(`references.${[index]}.source.uri`, value.toString());
}}
loading={searching}
value={values.references?.[index]?.source?.uri ? [values.references?.[index]?.source?.uri] : []}
placeholder={`${localization.search.search}...`}
>
<Combobox.Empty>{localization.search.noHits}</Combobox.Empty>
{comboboxOptions?.map((dataset) => (
<Combobox.Option
key={dataset.uri}
value={dataset.uri}
>
{dataset?.title ? getTranslateText(dataset?.title) : dataset.uri}
</Combobox.Option>
))}
</Combobox>
)}
<DeleteButton onClick={() => remove(index)}></DeleteButton>
</div>
))}

<AddButton onClick={() => push({ type: { code: '' }, source: { uri: '' } })}></AddButton>
</div>
)}
</FieldArray>
<FormContainer.Header
title={localization.datasetForm.heading.relationDatasetSeries}
subtitle={localization.datasetForm.helptext.relationDatasetSeries}
/>
{datasetSeries && (
<Combobox
label={localization.datasetForm.fieldLabel.datasetSeries}
onValueChange={(value) => setFieldValue('inSeries', value.toString())}
value={values.inSeries ? [values.inSeries] : []}
initialValue={values?.inSeries ? [values?.inSeries] : []}
placeholder={`${localization.search.search}...`}
>
<Combobox.Empty>{localization.search.noHits}</Combobox.Empty>
{datasetSeries.map((dataset) => (
<Combobox.Option
value={dataset.id}
key={dataset.id}
>
{getTranslateText(dataset.title)}
</Combobox.Option>
))}
</Combobox>
)}

<FormContainer.Header
title={localization.datasetForm.heading.relatedResources}
subtitle={localization.datasetForm.helptext.relatedResources}
/>
<FieldArray name='relations'>
{({ push, remove }) => (
<div>
{values.relations?.map((_, index) => (
<div key={index}>
<Field
as={Textfield}
label={localization.title}
name={`relations[${index}].prefLabel.nb`}
/>
<Field
as={Textfield}
label={localization.link}
name={`relations[${index}].uri`}
// @ts-expect-error uri exsists in object relations
error={errors?.relations?.[index].uri}
/>

<DeleteButton onClick={() => remove(index)}></DeleteButton>
</div>
))}

<AddButton
onClick={() =>
push({
prefLabel: { nb: '' },
uri: '',
})
}
></AddButton>
</div>
)}
</FieldArray>
</FormContainer>
</div>
);
};
22 changes: 20 additions & 2 deletions apps/dataset-catalog/components/dataset-form/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client';
import { localization, trimObjectWhitespace } from '@catalog-frontend/utils';
import { Button } from '@digdir/designsystemet-react';
import { Dataset, DatasetToBeCreated, ReferenceData } from '@catalog-frontend/types';
import { Dataset, DatasetSeries, DatasetToBeCreated, ReferenceData } from '@catalog-frontend/types';
import { FormLayout, useWarnIfUnsavedChanges } from '@catalog-frontend/ui';
import { Formik, Form } from 'formik';
import { useParams } from 'next/navigation';
Expand All @@ -20,16 +20,25 @@ import { GeographySection } from './components/dataset-form-geography-section';
import { InformationModelSection } from './components/dataset-form-information-model-section';
import { QualifiedAttributionsSection } from './components/dataset-form-qualified-attributions-section';
import { ExampleDataSection } from './components/dataset-form-example-data-section';
import { RelationsSection } from './components/dataset-form-relations-section';

type Props = {
initialValues: DatasetToBeCreated | Dataset;
submitType: 'create' | 'update';
searchEnv: string; // Environment variable to search service
referenceDataEnv: string; // Environment variable to reference data
referenceData: ReferenceData;
datasetSeries: DatasetSeries[];
};

export const DatasetForm = ({ initialValues, submitType, referenceData, searchEnv, referenceDataEnv }: Props) => {
export const DatasetForm = ({
initialValues,
submitType,
referenceData,
searchEnv,
referenceDataEnv,
datasetSeries,
}: Props) => {
const { catalogId, datasetId } = useParams();
const [isDirty, setIsDirty] = useState(false);
const { losThemes, dataThemes, provenanceStatements, datasetTypes, frequencies, languages } = referenceData;
Expand Down Expand Up @@ -196,6 +205,15 @@ export const DatasetForm = ({ initialValues, submitType, referenceData, searchEn
>
<ExampleDataSection referenceDataEnv={referenceDataEnv} />
</FormLayout.Section>
<FormLayout.Section
id='relation-section'
title={localization.datasetForm.heading.relations}
>
<RelationsSection
searchEnv={searchEnv}
datasetSeries={datasetSeries}
/>
</FormLayout.Section>
</FormLayout>
</Form>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const datasetTemplate = (dataset: Dataset): Dataset => {
landingPage:
dataset.landingPage && dataset?.landingPage?.length > 0 && dataset.landingPage.every((page) => page !== null)
? dataset.landingPage
: [''],
: [],
losThemeList: dataset.theme ? dataset.theme.filter((t) => t.uri && t.uri.includes('/los/')).map((t) => t.uri) : [],
euThemeList: dataset.theme
? dataset.theme.filter((t) => t.uri && t.uri.includes('/data-theme/')).map((t) => t.uri)
Expand Down Expand Up @@ -55,6 +55,9 @@ export const datasetTemplate = (dataset: Dataset): Dataset => {
mediaType: [],
},
],
references: dataset.references ?? [{ source: { uri: '' }, referenceType: { code: '' } }],
relations: dataset.relations ?? [{ uri: '', prefLabel: { nb: '' } }],
inSeries: dataset.inSeries ?? '',
};
};

Expand All @@ -71,7 +74,7 @@ export const datasetToBeCreatedTemplate = (): DatasetToBeCreated => {
en: '',
},
registrationStatus: PublicationStatus.DRAFT,
landingPage: [''],
landingPage: [],
accessRights: { uri: '' },
legalBasisForAccess: [{ uri: '', prefLabel: { nb: '' } }],
legalBasisForProcessing: [{ uri: '', prefLabel: { nb: '' } }],
Expand Down Expand Up @@ -108,5 +111,8 @@ export const datasetToBeCreatedTemplate = (): DatasetToBeCreated => {
mediaType: [],
},
],
references: [{ source: { uri: '' }, referenceType: { code: '' } }],
relations: [{ uri: '', prefLabel: { nb: '' } }],
inSeries: '',
};
};
Loading

0 comments on commit c6e0e29

Please sign in to comment.