Skip to content

Commit

Permalink
fix (concept): import type check, error handling and new fields
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffreiffers committed Nov 14, 2023
1 parent cb29056 commit ffff9d6
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ export const ChangeRequestForm = ({
key={language}
fieldName={`merknad.tekst.${language}`}
fieldType={loc.concept.note.toLowerCase()}
originalText={originalConcept?.merknad?.get(language)?.at(0)}
originalText={originalConcept?.merknad?.get(language)}
language={language}
rows={6}
showOriginal={showOriginal}
Expand Down
4 changes: 1 addition & 3 deletions apps/concept-catalog/app/[catalogId]/search-page-client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,7 @@ export const SearchPageClient = ({
};

const onImportUpload = (event) => {
event.target.files[0].text().then((text) => {
importConcepts.mutate(text);
});
importConcepts.mutate(event.target.files[0], { onError: (error) => alert('Import failed: ' + error) });
};

const onCreateConceptClick = () => {
Expand Down
8 changes: 7 additions & 1 deletion apps/concept-catalog/app/api/concepts/[slug]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@ export const POST = async (req: NextRequest, { params }: { params: { slug: strin
try {
const concepts = await req.json();
const response = await importConcepts(concepts, session?.accessToken);
return new Response(JSON.stringify(response), { status: response.status });

if (response.status > 399) {
const error = await response.json();
return new Response(error?.message ?? 'Failed to import concept', { status: response.status });
} else {
return new Response('', { status: response.status });
}
} catch (error) {
console.error(error);
return new Response('Failed to import concept', { status: 500 });
Expand Down
79 changes: 45 additions & 34 deletions apps/concept-catalog/hooks/import.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { readString } from 'react-papaparse';
import type { ParseResult } from 'papaparse';

import { Concept } from '@catalog-frontend/types';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { validOrganizationNumber } from '@catalog-frontend/utils';
Expand All @@ -16,7 +15,7 @@ const mapToSingleValue = (csvMap: Record<string, string[]>, key: string) => {

const mapRowToLanguageValue = (csvMap: Record<string, string[]>, columnName: string): Record<string, string> => {
return Object.entries(csvMap).reduce((prev, [key, [value]]) => {
if (value && key.startsWith(columnName)) {
if (value && key.startsWith(`${columnName}:`)) {
const [field, language] = key.split(':');

return { ...prev, ...(field && { [language ?? 'nb']: value }) };
Expand All @@ -28,7 +27,7 @@ const mapRowToLanguageValue = (csvMap: Record<string, string[]>, columnName: str

const mapRowToLanguageValueList = (csvMap: Record<string, string[]>, columnName: string): Record<string, string[]> => {
return Object.entries(csvMap).reduce((prev, [key, [value]]) => {
if (value && key.startsWith(columnName)) {
if (value && key.startsWith(`${columnName}:`)) {
const [field, language] = key.split(':');

return {
Expand Down Expand Up @@ -58,17 +57,17 @@ const createCsvMap = (header: string[], data: string[]) => {

const mapKilde = (
csvMap: Record<string, string[]>,
type: 'definisjon' | 'definisjonForAllmennheten' | 'definisjonForSpesialister',
type: 'definisjon' | 'definisjon_for_allmennheten' | 'definisjon_for_spesialister',
) => {
const forholdTilKilde = mapToSingleValue(csvMap, `${type}Forholdtilkilde`);
const forholdTilKilde = mapToSingleValue(csvMap, `${type}:forhold_til_kilde`);
if (forholdTilKilde && forholdTilKilde?.toLowerCase() === 'egendefinert') {
return {
forholdTilKilde,
kilde: [],
};
}

const formatterteKilder = csvMap[`${type}Kilde`]?.map((kilde) => {
const formatterteKilder = csvMap[`${type}:kilde`]?.map((kilde) => {
const [tekst, uri] = kilde.split('|');
if (!tekst && !uri) {
throw new Error(`Kilder skal være på følgende format "kilde|uri", men var følgende: ${kilde}`);
Expand All @@ -85,46 +84,47 @@ const mapKilde = (

const mapCsvTextToConcept = (columnHeaders: string[], data: string[]): Omit<Concept, 'id' | 'ansvarligVirksomhet'> => {
const csvMap = createCsvMap(columnHeaders, data);
const version = mapToSingleValue(csvMap, 'versjon') || '0.1.0';

return {
originaltBegrep: mapToSingleValue(csvMap, 'originaltBegrep') ?? '',
originaltBegrep: mapToSingleValue(csvMap, 'originalt_begrep') ?? '',
versjonsnr: {
major: parseInt(mapToSingleValue(csvMap, 'major') ?? '0', 10),
minor: parseInt(mapToSingleValue(csvMap, 'minor') ?? '0', 10),
patch: parseInt(mapToSingleValue(csvMap, 'patch') ?? '0', 10),
major: parseInt(version.split('.')?.[0] ?? '0', 10),
minor: parseInt(version.split('.')?.[1] ?? '0', 10),
patch: parseInt(version.split('.')?.[2] ?? '0', 10),
},
revisjonAv: mapToSingleValue(csvMap, 'revisjonAv') ?? '',
anbefaltTerm: { navn: mapRowToLanguageValue(csvMap, 'anbefaltterm') },
tillattTerm: mapRowToLanguageValueList(csvMap, 'tillattterm'),
frarådetTerm: mapRowToLanguageValueList(csvMap, 'frarådetterm'),
anbefaltTerm: { navn: mapRowToLanguageValue(csvMap, 'anbefalt_term') },
tillattTerm: mapRowToLanguageValueList(csvMap, 'tillatt_term'),
frarådetTerm: mapRowToLanguageValueList(csvMap, 'frarådet_term'),
definisjon: {
tekst: mapRowToLanguageValue(csvMap, 'definisjon'),
kildebeskrivelse: mapKilde(csvMap, 'definisjon'),
},
definisjonForAllmennheten: {
tekst: mapRowToLanguageValue(csvMap, 'definisjonForAllmennheten'),
kildebeskrivelse: mapKilde(csvMap, 'definisjonForAllmennheten'),
tekst: mapRowToLanguageValue(csvMap, 'definisjon_for_allmennheten'),
kildebeskrivelse: mapKilde(csvMap, 'definisjon_for_allmennheten'),
},
definisjonForSpesialister: {
tekst: mapRowToLanguageValue(csvMap, 'definisjonForSpesialister'),
kildebeskrivelse: mapKilde(csvMap, 'definisjonForSpesialister'),
tekst: mapRowToLanguageValue(csvMap, 'definisjon_for_spesialister'),
kildebeskrivelse: mapKilde(csvMap, 'definisjon_for_spesialister'),
},
merknad: mapRowToLanguageValueList(csvMap, 'merknad'),
eksempel: mapRowToLanguageValueList(csvMap, 'eksempel'),
merknad: mapRowToLanguageValue(csvMap, 'merknad'),
eksempel: mapRowToLanguageValue(csvMap, 'eksempel'),
fagområde: mapRowToLanguageValueList(csvMap, 'fagområde'),
bruksområde: mapRowToLanguageValueList(csvMap, 'bruksområde'),
gyldigFom: mapToSingleValue(csvMap, 'gyldigfom'),
gyldigTom: mapToSingleValue(csvMap, 'gyldigtom'),
gyldigFom: mapToSingleValue(csvMap, 'gyldig_fom'),
gyldigTom: mapToSingleValue(csvMap, 'gyldig_tom'),

omfang: {
uri: mapToSingleValue(csvMap, 'omfang_uri'),
tekst: mapToSingleValue(csvMap, 'omfang_tekst'),
uri: mapToSingleValue(csvMap, 'verdiområde:uri'),
tekst: mapToSingleValue(csvMap, 'verdiområde:tekst'),
},
seOgså: csvMap?.seogså?.[0]?.split('|') ?? [],
seOgså: mapToSingleValue(csvMap, 'se_også')?.split('|') ?? [],
kontaktpunkt: {
harEpost: mapToSingleValue(csvMap, 'kontaktpunkt_epost'),
harTelefon: mapToSingleValue(csvMap, 'kontaktpunkt_telefon'),
harEpost: mapToSingleValue(csvMap, 'kontaktpunkt:epost'),
harTelefon: mapToSingleValue(csvMap, 'kontaktpunkt:telefon'),
},
assignedUser: mapToSingleValue(csvMap, 'tildeltBruker_id') ?? '',
assignedUser: mapToSingleValue(csvMap, 'tildelt_bruker_id') ?? '',
};
};

Expand Down Expand Up @@ -164,15 +164,21 @@ export const useImportConcepts = (catalogId: string) => {
const queryClient = useQueryClient();
return useMutation({
mutationKey: ['importConcepts'],
mutationFn: async (content: string) => {
mutationFn: async (file: File) => {
if (!validOrganizationNumber(catalogId)) {
return Promise.reject('Invalid catalog id');
}

const parsedText =
(await attemptToParseJsonFile(content)) ??
(await attemptToParseCsvFile(content)) ??
(await Promise.resolve([]));
const content = await file.text();
let parsedText = [];
if (file.type === 'application/json') {
parsedText = await attemptToParseJsonFile(content);
} else if (file.type === 'text/csv') {
parsedText = await attemptToParseCsvFile(content);
} else {
Promise.reject('Invalid file type');
}

const concepts = parsedText?.map(
(concept) =>
({
Expand All @@ -192,7 +198,12 @@ export const useImportConcepts = (catalogId: string) => {
return Promise.reject('Unauthorized');
}

return response;
if (response.status > 399) {
const errorMessage = await response.text();
return Promise.reject(errorMessage);
}

return Promise.resolve();
}

return Promise.reject('Canceled');
Expand Down
5 changes: 2 additions & 3 deletions libs/types/src/lib/concept.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,11 @@ export interface Concept {
definisjonForAllmennheten?: Definisjon;
definisjonForSpesialister?: Definisjon;
ansvarligVirksomhet: { id: string };
merknad?: Record<string, string[]>;
merknad?: Record<string, string>;
merkelapp?: string[];
eksempel?: Record<string, string[]>;
eksempel?: Record<string, string>;
fagområde?: Record<string, string[]>;
fagområdeKoder?: string[];
bruksområde?: Record<string, string[]>;
omfang?: UriText | null;
tillattTerm?: Record<string, string[]>;
frarådetTerm?: Record<string, string[]>;
Expand Down
7 changes: 6 additions & 1 deletion libs/ui/src/lib/button/upload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ const UploadButton: FC<UploadButtonProps> = ({ children, allowedMimeTypes, onUpl
id={buttonId}
aria-controls={ref.current?.id}
aria-haspopup='true'
onClick={() => ref.current?.click()}
onClick={() => {
if (ref.current) {
ref.current.value = '';
ref.current.click();
}
}}
>
{children}
</Button>
Expand Down

0 comments on commit ffff9d6

Please sign in to comment.