diff --git a/config.template.js b/config.template.js index fee5a20b..3d481bad 100644 --- a/config.template.js +++ b/config.template.js @@ -4,7 +4,7 @@ window.env = { ORGANIZATION_API: '$ORGANIZATION_API', SSO_HOST: '$SSO_HOST', CONCEPT_API: '$CONCEPT_API', - SEARCH_FULLTEXT_HOST: '$SEARCH_FULLTEXT_HOST', + SEARCH_SERVICE_HOST: '$SEARCH_SERVICE_HOST', SEARCH_HOST: '$SEARCH_HOST', ADMIN_GUI_HOST: '$ADMIN_GUI_HOST', CATALOG_COMMENTS_SERVICE_HOST: '$CATALOG_COMMENTS_SERVICE_HOST', @@ -12,5 +12,5 @@ window.env = { CATALOG_ADMIN_SERVICE_BASE_URI: '$CATALOG_ADMIN_SERVICE_BASE_URI', CATALOG_ADMIN_BASE_URI: '$CATALOG_ADMIN_BASE_URI', FDK_PORTAL_BASE_URI: '$FDK_PORTAL_BASE_URI', - USE_DEMO_LOGO: '$USE_DEMO_LOGO', + USE_DEMO_LOGO: '$USE_DEMO_LOGO' }; diff --git a/src/api/search-api/concepts.ts b/src/api/search-api/concepts.ts new file mode 100644 index 00000000..f3e7e829 --- /dev/null +++ b/src/api/search-api/concepts.ts @@ -0,0 +1,28 @@ +import { searchApiPost } from './host'; +import { Concept, SearchObject } from '../../types'; + +export const searchConcepts = (body: any) => + searchApiPost('/search/concepts', body); + +const mapFilters = ({ uri }: any) => { + if (uri) { + return { uri: { value: uri } }; + } + + return undefined; +}; + +export const paramsToSearchBody = ({ q, ...params }: any) => { + const body = { + query: q, + filters: mapFilters(params) + }; + return body; +}; + +export const extractConcepts = (searchResponse: any): Promise => + searchResponse?.hits ?? []; + +export const extractInternalConcepts = ( + searchResponse: any +): Promise => searchResponse?.hits ?? []; diff --git a/src/api/search-api/host.ts b/src/api/search-api/host.ts new file mode 100644 index 00000000..c8675e01 --- /dev/null +++ b/src/api/search-api/host.ts @@ -0,0 +1,26 @@ +import axios from 'axios'; +import cleanDeep from 'clean-deep'; +import { getConfig } from '../../config'; + +interface Props { + path: string; + method: any; + params?: any; + data?: any; +} + +export const searchApi = ({ path, method, params, data }: Props) => + axios({ + url: `${getConfig().searchApi.host}${path}`, + method, + params, + data + }) + .then(response => cleanDeep(response.data)) + .catch(() => null); + +export const searchApiPost = (path: string, body: any) => + searchApi({ path, method: 'POST', data: body }); + +export const searchApiGet = (path: string, params: any) => + searchApi({ path, method: 'GET', params }); diff --git a/src/api/search-api/suggestions.ts b/src/api/search-api/suggestions.ts new file mode 100644 index 00000000..ae5f45b6 --- /dev/null +++ b/src/api/search-api/suggestions.ts @@ -0,0 +1,9 @@ +import { searchApiGet } from './host'; +import { SearchObject } from '../../types'; + +export const extractSuggestions = ( + searchResponse: any +): Promise => searchResponse.suggestions ?? []; + +export const getConceptSuggestions = (params: any) => + searchApiGet('/suggestions/concepts', params); diff --git a/src/api/search-fulltext-api/concepts.ts b/src/api/search-fulltext-api/concepts.ts deleted file mode 100644 index 1ac27218..00000000 --- a/src/api/search-fulltext-api/concepts.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { searchFullTextApiPost } from './host'; -import { Concept, SkosConcept } from '../../types'; - -export const searchConcepts = (body: any) => - searchFullTextApiPost('/concepts', body); - -const mapFilters = ({ identifier }: any) => { - const filters: any = []; - if (identifier) { - filters.push({ - collection: { - field: 'identifier.keyword', - values: identifier - } - }); - } - - return filters.length > 0 ? filters : undefined; -}; - -export const paramsToSearchBody = ({ q, ...params }: any) => { - const body = { - q, - filters: mapFilters(params) - }; - return body; -}; - -export const extractConcepts = (searchResponse: any): Promise => - searchResponse?.hits ?? []; - -export const extractInternalConcepts = ( - searchResponse: any -): Promise => searchResponse?.hits ?? []; diff --git a/src/api/search-fulltext-api/host.ts b/src/api/search-fulltext-api/host.ts deleted file mode 100644 index 9423c276..00000000 --- a/src/api/search-fulltext-api/host.ts +++ /dev/null @@ -1,26 +0,0 @@ -import axios from 'axios'; -import cleanDeep from 'clean-deep'; -import { getConfig } from '../../config'; - -interface Props { - path: string; - method: any; - params?: any; - data?: any; -} - -export const searchFullTextApi = ({ path, method, params, data }: Props) => - axios({ - url: `${getConfig().searchFullTextApi.host}${path}`, - method, - params, - data - }) - .then(response => cleanDeep(response.data)) - .catch(() => null); - -export const searchFullTextApiPost = (path: string, body: any) => - searchFullTextApi({ path, method: 'POST', data: body }); - -export const searchFullTextApiGet = (path: string, params: any) => - searchFullTextApi({ path, method: 'GET', params }); diff --git a/src/api/search-fulltext-api/suggestions.ts b/src/api/search-fulltext-api/suggestions.ts deleted file mode 100644 index 6af6fde5..00000000 --- a/src/api/search-fulltext-api/suggestions.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { searchFullTextApiGet } from './host'; -import { SkosConcept } from '../../types'; - -export const extractSuggestions = ( - searchResponse: any -): Promise => searchResponse.suggestions ?? []; - -export const getConceptSuggestions = (params: any) => - searchFullTextApiGet('/suggestion/concepts', params); diff --git a/src/components/header/index.tsx b/src/components/header/index.tsx index 3bc558e6..879c72e6 100644 --- a/src/components/header/index.tsx +++ b/src/components/header/index.tsx @@ -2,12 +2,12 @@ import React, { FC, HTMLAttributes } from 'react'; import HeaderBase from '@fellesdatakatalog/internal-header'; -interface Props extends HTMLAttributes {} - import Link from '@fellesdatakatalog/link'; +import { useLocation } from 'react-router-dom'; import authService from '../../services/auth-service'; import { getConfig } from '../../config'; -import { useLocation } from 'react-router-dom'; + +interface Props extends HTMLAttributes {} const showManageConceptCatalogsUrl = () => { const resourceRoles = authService.getResourceRoles(); @@ -15,10 +15,10 @@ const showManageConceptCatalogsUrl = () => { const pathParts = location.pathname.split('/'); const currentCatalogId = pathParts ? pathParts[1] : undefined; - return resourceRoles.some((role) => { + return resourceRoles.some(role => { const roleOrgNumber = role?.resourceId; return authService.hasOrganizationAdminPermission( - currentCatalogId ? currentCatalogId : roleOrgNumber + currentCatalogId || roleOrgNumber ); }); }; @@ -32,9 +32,9 @@ export const Header: FC = () => ( showManageConceptCatalogsUrl={showManageConceptCatalogsUrl()} manageConceptCatalogsUrl={getConfig().catalogAdminBaseUri} > - Registrere data + Registrere data Høste data - + Søk i Felles datakatalog diff --git a/src/config.ts b/src/config.ts index 92da40ef..4d2f6cde 100644 --- a/src/config.ts +++ b/src/config.ts @@ -15,7 +15,8 @@ const env = (window as any).env || { // env.ORGANIZATION_API = // 'https://organization-catalog.staging.fellesdatakatalog.digdir.no'; // env.CONCEPT_API = 'https://www.staging.fellesdatakatalog.digdir.no'; -// env.SEARCH_FULLTEXT_HOST = 'https://search.staging.fellesdatakatalog.digdir.no'; +// env.SEARCH_SERVICE_HOST = +// 'https://search.api.staging.fellesdatakatalog.digdir.no'; // env.SEARCH_HOST = 'https://www.staging.fellesdatakatalog.digdir.no'; // env.FDK_PORTAL_BASE_URI = 'https://staging.fellesdatakatalog.digdir.no'; // env.ADMIN_GUI_HOST = 'https://admin.staging.fellesdatakatalog.digdir.no'; @@ -52,10 +53,10 @@ const config = { referenceDataApi: { host: env.FDK_PORTAL_BASE_URI }, - searchFullTextApi: { - host: env.SEARCH_FULLTEXT_HOST + searchApi: { + host: env.SEARCH_SERVICE_HOST }, - searchHost: env.SEARCH_HOST || 'https://fellesdatakatalog.digdir.no', + fdkBaseUri: env.SEARCH_HOST || 'https://fellesdatakatalog.digdir.no', adminGui: { host: env.ADMIN_GUI_HOST }, diff --git a/src/features/concept-suggestions/index.ts b/src/features/concept-suggestions/index.ts index 75dd078a..3ebf0b86 100644 --- a/src/features/concept-suggestions/index.ts +++ b/src/features/concept-suggestions/index.ts @@ -4,17 +4,17 @@ import { createEntityAdapter } from '@reduxjs/toolkit'; -import { Concept, SkosConcept } from '../../types'; +import { Concept, SearchObject } from '../../types'; import type { RootState } from '../../app/redux/store'; import { getConceptSuggestions, extractSuggestions -} from '../../api/search-fulltext-api/suggestions'; +} from '../../api/search-api/suggestions'; import { getInternalConceptSuggestions } from '../../api/concept-catalog-api'; interface SuggestionsAttributes { q: string; - publisherId?: string; + org?: string; } interface InternalSuggestionsAttributes { query: string; @@ -22,10 +22,10 @@ interface InternalSuggestionsAttributes { } export const fetchConceptSuggestions = createAsyncThunk< - SkosConcept[], + SearchObject[], SuggestionsAttributes ->('conceptForm/fetchConceptSuggestions', async ({ q, publisherId }) => - getConceptSuggestions({ q, publisherId }).then(extractSuggestions) +>('conceptForm/fetchConceptSuggestions', async ({ q, org }) => + getConceptSuggestions({ q, org }).then(extractSuggestions) ); export const fetchInternalConceptSuggestions = createAsyncThunk< @@ -37,8 +37,8 @@ export const fetchInternalConceptSuggestions = createAsyncThunk< getInternalConceptSuggestions(publisherId, query) ); -const conceptSuggestionsAdapter = createEntityAdapter({ - selectId: concept => concept.identifier +const conceptSuggestionsAdapter = createEntityAdapter({ + selectId: concept => concept.uri }); const internalConceptSuggestionsAdapter = createEntityAdapter({ diff --git a/src/features/concepts/index.ts b/src/features/concepts/index.ts index ca367628..2d1b9122 100644 --- a/src/features/concepts/index.ts +++ b/src/features/concepts/index.ts @@ -4,14 +4,14 @@ import { createEntityAdapter } from '@reduxjs/toolkit'; -import { Concept, SkosConcept } from '../../types'; +import { Concept, SearchObject } from '../../types'; import type { RootState } from '../../app/redux/store'; import { extractConcepts, extractInternalConcepts, paramsToSearchBody, searchConcepts -} from '../../api/search-fulltext-api/concepts'; +} from '../../api/search-api/concepts'; import { searchInternalConcepts } from '../../api/concept-catalog-api'; interface InternalConceptFetchRequest { @@ -19,12 +19,10 @@ interface InternalConceptFetchRequest { values: string[]; } -export const fetchConcepts = createAsyncThunk( +export const fetchConcepts = createAsyncThunk( 'conceptForm/fetchConcepts', - async identifiers => - searchConcepts(paramsToSearchBody({ identifier: identifiers })).then( - extractConcepts - ) + async uris => + searchConcepts(paramsToSearchBody({ uri: uris })).then(extractConcepts) ); export const fetchInternalConcepts = createAsyncThunk< @@ -34,8 +32,8 @@ export const fetchInternalConcepts = createAsyncThunk< searchInternalConcepts(catalogId, values).then(extractInternalConcepts) ); -const conceptsAdapter = createEntityAdapter({ - selectId: concept => concept.identifier +const conceptsAdapter = createEntityAdapter({ + selectId: concept => concept.uri }); const internalConceptsAdapter = createEntityAdapter({ diff --git a/src/pages/concept-registration-page/form-concept/related-concepts/components/relation/index.tsx b/src/pages/concept-registration-page/form-concept/related-concepts/components/relation/index.tsx index 0c4008d7..9a09afb0 100644 --- a/src/pages/concept-registration-page/form-concept/related-concepts/components/relation/index.tsx +++ b/src/pages/concept-registration-page/form-concept/related-concepts/components/relation/index.tsx @@ -140,7 +140,7 @@ const RelationItem: FC = ({ const getLabel = () => fieldName === 'begrepsRelasjon' ? getTranslateText( - relatedConcepts[fieldValue.value[index].relatertBegrep]?.prefLabel + relatedConcepts[fieldValue.value[index].relatertBegrep]?.title ) || 'default' : getTranslateText( relatedInternalConcepts[fieldValue.value[index].relatertBegrep] diff --git a/src/pages/concept-registration-page/form-concept/related-concepts/related-concepts.component.tsx b/src/pages/concept-registration-page/form-concept/related-concepts/related-concepts.component.tsx index f5a29662..ea34a221 100644 --- a/src/pages/concept-registration-page/form-concept/related-concepts/related-concepts.component.tsx +++ b/src/pages/concept-registration-page/form-concept/related-concepts/related-concepts.component.tsx @@ -83,7 +83,7 @@ const RelatedConceptsPure: FC = ({ }, [internSeOgsaaField]); const executeConceptSuggestionSearch = (q: string, publisherId?: string) => { - dispatch(fetchConceptSuggestions({ q, publisherId })); + dispatch(fetchConceptSuggestions({ q, org: publisherId })); }; const executeInternalConceptSuggestionSearch = ( @@ -127,13 +127,13 @@ const RelatedConceptsPure: FC = ({ }; const conceptSuggestionsMap = conceptSuggestions.map( - ({ identifier, prefLabel, definition, publisher }) => + ({ uri, title, description, organization }) => ({ - value: identifier, - label: getTranslateText(prefLabel), - description: getTranslateText(definition?.text), + value: uri, + label: getTranslateText(title), + description: getTranslateText(description), publisher: - getTranslateText(publisher?.prefLabel) ?? publisher?.name ?? '' + getTranslateText(organization?.prefLabel) ?? organization?.name ?? '' } as OptionProps) ); @@ -192,8 +192,7 @@ const RelatedConceptsPure: FC = ({ defaultValue={form?.values?.seOgså?.map(item => ({ value: item, label: - getTranslateText(relatedConcepts[item]?.prefLabel) ?? - 'default' + getTranslateText(relatedConcepts[item]?.title) ?? 'default' }))} isMulti /> diff --git a/src/pages/concept-registration-page/form-concept/validity/validity.component.tsx b/src/pages/concept-registration-page/form-concept/validity/validity.component.tsx index 357b410f..38ce6656 100644 --- a/src/pages/concept-registration-page/form-concept/validity/validity.component.tsx +++ b/src/pages/concept-registration-page/form-concept/validity/validity.component.tsx @@ -72,13 +72,13 @@ export const Validity: FC = ({ catalogId }) => { }, [internErstattesAv.value]); const conceptSuggestionsMap = conceptSuggestions.map( - ({ identifier, prefLabel, definition, publisher }) => + ({ uri, title, description, organization }) => ({ - value: identifier, - label: getTranslateText(prefLabel), - description: getTranslateText(definition?.text), + value: uri, + label: getTranslateText(title), + description: getTranslateText(description), publisher: - getTranslateText(publisher?.prefLabel) ?? publisher?.name ?? '' + getTranslateText(organization?.prefLabel) ?? organization?.name ?? '' } as OptionProps) ); @@ -171,8 +171,7 @@ export const Validity: FC = ({ catalogId }) => { defaultValue={form?.values?.erstattesAv?.map(item => ({ value: item, label: - getTranslateText(relatedConcepts[item]?.prefLabel) ?? - 'default' + getTranslateText(relatedConcepts[item]?.title) ?? 'default' }))} isMulti /> diff --git a/src/types/domain.d.ts b/src/types/domain.d.ts index f75e399f..8c63b79b 100644 --- a/src/types/domain.d.ts +++ b/src/types/domain.d.ts @@ -183,6 +183,7 @@ export interface Publisher { organizationId: string; name?: string; prefLabel?: TekstMedSpraakKode; + orgPath?: string; } export interface CatalogFields { @@ -247,3 +248,11 @@ export type TreeNode = { label: string; children: TreeNode[]; }; + +export interface SearchObject { + id: string; + uri: string; + title: Record; + description: Record; + organization: Publisher; +}