diff --git a/frisk.config.tsx b/frisk.config.tsx index d67208d..0ce8744 100644 --- a/frisk.config.tsx +++ b/frisk.config.tsx @@ -7,11 +7,21 @@ import { } from "@/services/backend"; import { getRegelrettClientId, getregelrettFrontendUrl } from "@/config"; import { object, string, array, type z } from "zod"; -import { Button, FormControl, FormLabel, Select } from "@kvib/react"; +import { + Button, + Flex, + FormControl, + FormLabel, + IconButton, + Link, + Select, + useDisclosure, +} from "@kvib/react"; import type { useFunction } from "@/hooks/use-function"; -import type { useMetadata } from "@/hooks/use-metadata"; import { msalInstance } from "@/services/msal"; import { InteractionRequiredAuthError } from "@azure/msal-browser"; +import type { useMetadata } from "@/hooks/use-metadata"; +import { DeleteMetadataModal } from "@/components/delete-metadata-modal"; export async function getConfig(): Promise { const schemas = await getSchemasFromRegelrett(); @@ -74,34 +84,6 @@ export async function getConfig(): Promise { return { displayValue: "Utviklerportalen" }; }, }, - ...schemas.map( - (schema): InputMetadata => ({ - key: schema.id, - type: "text", - displayName: schema.name, - label: "Regelrett skjema", - show: (mode, hasAccess) => mode === "read" && hasAccess, - isRequired: false, - placeholder: "Sett inn skjema", - inheritFromParent: false, - getDisplayValue: async (input) => { - const contextId = input.value; - const searchParams = new URLSearchParams({ - redirectBackUrl: window.location.href, - redirectBackTitle: "Funksjonsregisteret", - }); - const url = `${getregelrettFrontendUrl()}/context/${contextId}?${searchParams.toString()}`; - return { - displayValue: schema.name, - value: url, - displayOptions: { - type: "url", - isExternal: false, - }, - }; - }, - }), - ), { key: "dependencies", type: "select", @@ -126,6 +108,41 @@ export async function getConfig(): Promise { placeholder: "Søk etter funksjoner", inheritFromParent: false, }, + ...schemas.map( + (schema): InputMetadata => ({ + key: schema.id, + type: "text", + displayName: schema.name, + label: "Regelrett skjema", + show: (mode, hasAccess) => mode === "read" && hasAccess, + isRequired: false, + placeholder: "Sett inn skjema", + inheritFromParent: false, + getDisplayValue: async (input) => { + const contextId = input.value; + const searchParams = new URLSearchParams({ + redirectBackUrl: window.location.href, + redirectBackTitle: "Funksjonsregisteret", + }); + const url = `${getregelrettFrontendUrl()}/context/${contextId}?${searchParams.toString()}`; + return { + displayValue: "Skjema", + displayOptions: { + type: "custom", + component: ( + + ), + }, + }; + }, + }), + ), ], logo: { @@ -191,7 +208,12 @@ type GeneralMetadataContent = { * you can use this function to get the display value. Often used together with inputType: "select" since * selects has both a value, and a name. */ - getDisplayValue?: (input: { key: string; value: string }) => Promise<{ + getDisplayValue?: (input: { + key: string; + value: string; + functionId: number; + id: number; + }) => Promise<{ displayValue: string; value?: string; displayOptions?: @@ -204,6 +226,10 @@ type GeneralMetadataContent = { | { type: "url"; isExternal: boolean; + } + | { + type: "custom"; + component: React.ReactNode; }; }>; }; @@ -320,6 +346,74 @@ function createSchemaComponent(schemas: RegelrettSchema[]) { }; } +type Schema = { + id: string; + name: string; +}; + +type SchemaDisplayProps = { + schema: Schema; + url: string; + functionId: number; + metadataId: number; +}; + +function SchemaDisplay({ + schema, + url, + functionId, + metadataId, +}: SchemaDisplayProps) { + const { isOpen, onOpen, onClose } = useDisclosure(); + + return ( + + + + { + e.stopPropagation(); + onOpen(); + }} + /> + + + ); +} + const REGELRETT_BACKEND_URL = `${getregelrettFrontendUrl()}/api`; async function getSchemasFromRegelrett() { diff --git a/src/components/delete-metadata-modal.tsx b/src/components/delete-metadata-modal.tsx index d4fe5f5..7349d3b 100644 --- a/src/components/delete-metadata-modal.tsx +++ b/src/components/delete-metadata-modal.tsx @@ -53,7 +53,7 @@ export function DeleteMetadataModal({ colorScheme="red" leftIcon="delete" onClick={async (e) => { - e.preventDefault(); + e.stopPropagation(); removeMetadata.mutateAsync({ id: metadataId, functionId: functionId, diff --git a/src/components/metadata/metadata-view.tsx b/src/components/metadata/metadata-view.tsx index ecdb3b3..fe0d0b8 100644 --- a/src/components/metadata/metadata-view.tsx +++ b/src/components/metadata/metadata-view.tsx @@ -58,10 +58,6 @@ export function MetadataView({ metadata, functionId }: Props) { ) : null} {displayValues.map((dv, i) => { const isDisplayValueLoading = dv.isLoading; - const displayValue = - dv.data?.displayValue ?? metadataToDisplay?.[i]?.value; - const metadataDisplayType = dv.data?.displayOptions?.type; - const metadataType = metadata.type; const metaDataValue = dv.data?.value ?? metadataToDisplay?.[i]?.value; const metadataId = metadataToDisplay?.[i]?.id; const isLoading = isCurrentMetadataLoading || isDisplayValueLoading; @@ -69,12 +65,12 @@ export function MetadataView({ metadata, functionId }: Props) { if (isNoMetadata) return null; - switch (metadataDisplayType) { + switch (dv.data?.displayOptions?.type) { case "text": return ( ); @@ -83,8 +79,8 @@ export function MetadataView({ metadata, functionId }: Props) { ); + case "custom": + return dv.data.displayOptions.component; case undefined: - switch (metadataType) { + switch (metadata.type) { case "select": case "number": case "text": return ( ); @@ -118,7 +116,7 @@ export function MetadataView({ metadata, functionId }: Props) { ); default: - metadataType satisfies never; + metadata satisfies never; console.error("Unsupported data type"); return null; } default: - metadataDisplayType satisfies never; + dv.data?.displayOptions satisfies undefined; console.error("Unsupported data type"); return null; }