diff --git a/apps/dataset-catalog/app/context/themes/index.tsx b/apps/dataset-catalog/app/context/themes/index.tsx new file mode 100644 index 000000000..40c048ba7 --- /dev/null +++ b/apps/dataset-catalog/app/context/themes/index.tsx @@ -0,0 +1,57 @@ +'use client'; +import { getLosThemes, getDataThemes } from '@catalog-frontend/data-access'; +import { LosTheme, DataTheme } from '@catalog-frontend/types'; +import React, { createContext, useEffect, useState, ReactNode } from 'react'; + +type ThemesContextType = { + losThemes: LosTheme[]; + dataThemes: DataTheme[]; + loading: boolean; + error: string | null; +}; + +const ThemesContext = createContext(undefined); + +export const ThemesProvider = ({ children }: { children: ReactNode }) => { + const [losThemes, setLosThemes] = useState([]); + const [dataThemes, setDataThemes] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + const fetchThemes = async () => { + setLoading(true); + try { + const [los, data] = await Promise.all([getLosThemes(), getDataThemes()]); + const losThemesData = await los.json(); + const dataThemesData = await data.json(); + + setLosThemes(losThemesData.losNodes.flat()); + setDataThemes(dataThemesData.dataThemes); + } catch (err) { + console.error(`Failed to fetch reference-data, ${err}`); + } finally { + setLoading(false); + } + }; + + fetchThemes(); + }, []); + + const value = { + losThemes, + dataThemes, + loading, + error, + }; + + return {children}; +}; + +export const useThemes = () => { + const context = React.useContext(ThemesContext); + if (context === undefined) { + throw new Error('useThemes must be used within a ThemesProvider'); + } + return context; +}; diff --git a/apps/dataset-catalog/app/layout.tsx b/apps/dataset-catalog/app/layout.tsx index 7918c7069..d0b1060d1 100644 --- a/apps/dataset-catalog/app/layout.tsx +++ b/apps/dataset-catalog/app/layout.tsx @@ -1,6 +1,7 @@ import { Layout, NextAuthProvider, ReactQueryClientProvider } from '@catalog-frontend/ui'; import { localization } from '@catalog-frontend/utils'; import { Metadata } from 'next'; +import { ThemesProvider } from './context/themes'; export const metadata: Metadata = { title: localization.catalogType.dataset, diff --git a/apps/dataset-catalog/components/dataset-form/dataset-form-tema-section.tsx b/apps/dataset-catalog/components/dataset-form/dataset-form-tema-section.tsx new file mode 100644 index 000000000..120295a88 --- /dev/null +++ b/apps/dataset-catalog/components/dataset-form/dataset-form-tema-section.tsx @@ -0,0 +1,124 @@ +import { Dataset, Option } from '@catalog-frontend/types'; +import { FormContainer, TitleWithTag } from '@catalog-frontend/ui'; +import { useThemes } from '../../app/context/themes/index'; +import { Combobox, Spinner } from '@digdir/designsystemet-react'; +import { getTranslateText, localization } from '@catalog-frontend/utils'; +import { Field, FormikErrors, useFormikContext } from 'formik'; +import styles from './dataset-form.module.css'; + +export const TemaSection = () => { + const { losThemes, dataThemes, loading } = useThemes(); + const { setFieldValue, values, errors } = useFormikContext(); + + const getNameFromLosPath = (path: string): string | string[] => { + const obj = losThemes?.find((obj) => obj.losPaths.includes(path)); + return obj ? getTranslateText(obj.name) : []; + }; + + const getParentNames = (inputPaths: string[]): string => { + const results: string[] = []; + + inputPaths.forEach((path) => { + const parts = path.split('/').slice(0, -1); + const parentPath = parts.slice(0, -1).join('/'); + const childPath = parts.join('/'); + + const parentName = getNameFromLosPath(parentPath); + const childName = getNameFromLosPath(childPath); + + const formattedResult = `${parentName} - ${childName}`; + results.push(formattedResult); + }); + + return `${localization.datasetForm.helptext.parentTheme}: ${results.join('; ')}`; + }; + + const containsFilter = (inputValue: string, option: Option): boolean => { + return option.label.toLowerCase().includes(inputValue.toLowerCase()); + }; + + return ( + + + <> +
+ + {loading ? ( +
+ +
+ ) : ( + setFieldValue('losThemeList', values)} + > + {localization.search.noHits} + {losThemes?.map((theme) => ( + + {getTranslateText(theme.name)} + + ))} + + )} +
+ + + <> +
+ + {loading ? ( +
+ +
+ ) : ( + setFieldValue('euThemeList', values)} + > + {localization.search.noHits} + {dataThemes && + dataThemes.map((eutheme) => ( + + {getTranslateText(eutheme.label)} + + ))} + + )} +
+ +
+ ); +}; + +export default TemaSection; diff --git a/libs/data-access/src/index.ts b/libs/data-access/src/index.ts index 69d5b73a7..762e9bb81 100644 --- a/libs/data-access/src/index.ts +++ b/libs/data-access/src/index.ts @@ -5,7 +5,7 @@ export * from './lib/catalog-history/api'; export * from './lib/concept/api'; export * from './lib/organization/api'; export * from './lib/reference-data/api'; -export * from './lib/reference-data/generated/graphql'; +export * as ReferenceDataGraphql from './lib/reference-data/generated/graphql'; export * from './lib/search/api'; export * from './lib/code-list/api'; export * from './lib/users/api'; @@ -17,6 +17,6 @@ export * from './lib/statuses/api'; export * from './lib/datasets/api'; export * from './lib/data-service/api'; export * from './lib/records-of-processing-activities/api'; -export * from './lib/strapi/generated/graphql'; +export * as StrapiGraphql from './lib/strapi/generated/graphql'; export * from './lib/strapi/service-messages'; export * from './lib/enhetsregisteret'; diff --git a/libs/data-access/src/lib/themes/api/index.tsx b/libs/data-access/src/lib/themes/api/index.tsx new file mode 100644 index 000000000..05d0ce8f5 --- /dev/null +++ b/libs/data-access/src/lib/themes/api/index.tsx @@ -0,0 +1,19 @@ +export const getLosThemes = async () => { + const resource = `https://staging.fellesdatakatalog.digdir.no/reference-data/los/themes-and-words`; //env-variabel kommer i neste PR + const options = { + headers: { + 'Content-Type': 'application/json', + }, + }; + return await fetch(resource, options); +}; + +export const getDataThemes = async () => { + const resource = `https://staging.fellesdatakatalog.digdir.no/reference-data/eu/data-themes`; //env-variabel kommer i neste PR + const options = { + headers: { + 'Content-Type': 'application/json', + }, + }; + return await fetch(resource, options); +}; diff --git a/libs/types/src/lib/theme.ts b/libs/types/src/lib/theme.ts new file mode 100644 index 000000000..1077842a6 --- /dev/null +++ b/libs/types/src/lib/theme.ts @@ -0,0 +1,24 @@ +import { UriWIthLabel } from './dataset'; +import { LocalizedStrings } from './localization'; + +export interface LosTheme { + children?: null; + parents?: string[]; + isTheme?: boolean; + losPaths: string[]; + name?: LocalizedStrings; + definition?: null; + uri: string; + synonyms?: string[]; + relatedTerms?: null; + theme?: boolean; + internalId: null; +} + +export interface DataTheme { + uri: string; + code?: string; + label: LocalizedStrings; + startUse?: string; + conceptSchema?: UriWIthLabel; +}