Skip to content

Commit

Permalink
Automatically insert fullmektig info (if needed) alongside other labe…
Browse files Browse the repository at this point in the history
…l-content
  • Loading branch information
eriksson-daniel committed Nov 26, 2024
1 parent 6aa17db commit 9f16daf
Show file tree
Hide file tree
Showing 20 changed files with 320 additions and 24 deletions.
4 changes: 2 additions & 2 deletions frontend/src/components/smart-editor/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export const COMMENT_PREFIX = 'commentThreadId_';

export const MALTEKST_SECTION_NAMES: Record<TemplateSections, string> = {
[TemplateSections.TITLE]: 'Dokumenttittel',
[TemplateSections.INTRODUCTION]: 'Introduksjon (gammel)',
[TemplateSections.INTRODUCTION_V1]: 'Introduksjon (gammel)',
[TemplateSections.INTRODUCTION_V2]: 'Introduksjon v2',
[TemplateSections.AVGJOERELSE]: 'Avgjørelse',
[TemplateSections.ANFOERSLER]: 'Anførsler',
Expand All @@ -16,7 +16,7 @@ export const MALTEKST_SECTION_NAMES: Record<TemplateSections, string> = {
[TemplateSections.SAKSKOSTNADER]: 'Sakskostnader',
[TemplateSections.REGELVERK_TITLE]: 'Regelverktittel',
[TemplateSections.FREMLEGG]: 'Fremlegg',
[TemplateSections.TILSVARSRETT]: 'Tilsvarsrett (gammel)',
[TemplateSections.TILSVARSRETT_V1]: 'Tilsvarsrett (gammel)',
[TemplateSections.TILSVARSRETT_V2]: 'Tilsvarsrett v2',
[TemplateSections.VEDLEGG]: 'Vedlegg med forklaring',
[TemplateSections.SVAR_FRA_ROL]: 'Svar fra ROL',
Expand Down
158 changes: 158 additions & 0 deletions frontend/src/plate/components/fullmektig.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import { useOppgave } from '@app/hooks/oppgavebehandling/use-oppgave';
import { ELEMENT_PLACEHOLDER } from '@app/plate/plugins/element-types';
import { FULLMEKTIG_LABEL_PLACEHOLDER, FULLMEKTIG_VALUE_PLACEHOLDER } from '@app/plate/plugins/fullmektig';
import { type FullmektigElement, type PlaceholderElement, useMyPlateEditorRef } from '@app/plate/types';
import { isOfElementType } from '@app/plate/utils/queries';
import { ArrowUndoIcon } from '@navikt/aksel-icons';
import { Button, Loader } from '@navikt/ds-react';
import { findDescendant, replaceNodeChildren, withoutSavingHistory } from '@udecode/plate-common';
import { PlateElement, type PlateElementProps, findNodePath } from '@udecode/plate-common/react';
import { useEffect } from 'react';
import { setNodes, withoutNormalizing } from 'slate';
import { styled } from 'styled-components';

export const Fullmektig = (props: PlateElementProps<FullmektigElement>) => {
const { data: oppgave, isLoading, isSuccess } = useOppgave();
const { element, children } = props;
const { id, show } = element;
const editor = useMyPlateEditorRef();

const at = findNodePath(editor, element);

const valueEntry = findDescendant<PlaceholderElement>(editor, {
at,
match: (n) =>
isOfElementType<PlaceholderElement>(n, ELEMENT_PLACEHOLDER) && n.placeholder === FULLMEKTIG_VALUE_PLACEHOLDER,
});

useEffect(() => {
if (!isSuccess) {
return;
}

const { prosessfullmektig } = oppgave;

const noFullmektigOk = prosessfullmektig === null && id === undefined && !show;
const fullmektigOk = prosessfullmektig !== null && id === prosessfullmektig.id && show;

if (noFullmektigOk || fullmektigOk) {
return;
}

if (valueEntry === undefined) {
return;
}

const [, valueAt] = valueEntry;

if (prosessfullmektig === null) {
return withoutSavingHistory(editor, () => {
withoutNormalizing(editor, () => {
setNodes<FullmektigElement>(editor, { id: undefined, show: false }, { at });
replaceNodeChildren(editor, { at: valueAt, nodes: [{ text: '' }] });
});
});
}

withoutSavingHistory(editor, () => {
withoutNormalizing(editor, () => {
setNodes<FullmektigElement>(editor, { id: prosessfullmektig.id, show: true }, { at });
replaceNodeChildren(editor, { at: valueAt, nodes: [{ text: prosessfullmektig.name ?? '' }] });
});
});
}, [editor, isSuccess, oppgave, id, valueEntry, at, show]);

if (isLoading) {
return <Loader />;
}

if (!isSuccess) {
return null;
}

const { prosessfullmektig } = oppgave;

if (prosessfullmektig === null) {
return null;
}

return (
<PlateElement<FullmektigElement> asChild {...props}>
<span>
<NonEditable>{children[0]}</NonEditable>
<PlaceholderContainer>
<StyledButton
contentEditable
suppressContentEditableWarning
$align="left"
variant="tertiary"
size="small"
title='Tilbakestill til navn "Fullmektig"'
onClick={() => {
const labelEntry = findDescendant<PlaceholderElement>(editor, {
at,
match: (n) =>
isOfElementType<PlaceholderElement>(n, ELEMENT_PLACEHOLDER) &&
n.placeholder === FULLMEKTIG_LABEL_PLACEHOLDER,
});

if (labelEntry === undefined) {
return;
}

replaceNodeChildren(editor, { at: labelEntry[1], nodes: [{ text: 'Fullmektig', bold: true }] });
}}
icon={<ArrowUndoIcon aria-hidden />}
/>
<Editable>{children[1]}</Editable>
</PlaceholderContainer>
<NonEditable>: </NonEditable>
<NonEditable>{children[2]}</NonEditable>
<PlaceholderContainer>
<StyledButton
$align="right"
variant="tertiary"
size="small"
title="Tilbakestill til navn fra behandlingen"
onClick={() => {
if (valueEntry === undefined) {
return;
}

replaceNodeChildren(editor, { at: valueEntry[1], nodes: [{ text: prosessfullmektig.name ?? '' }] });
}}
icon={<ArrowUndoIcon aria-hidden />}
/>
<Editable>{children[3]}</Editable>
</PlaceholderContainer>
<NonEditable>{children[4]}</NonEditable>
<br />
</span>
</PlateElement>
);
};

const Editable = ({ children }: { children: React.ReactNode }) => (
<span style={{ outline: 'none' }} contentEditable suppressContentEditableWarning>
{children}
</span>
);

const NonEditable = ({ children }: { children: React.ReactNode }) => <span contentEditable={false}>{children}</span>;

const StyledButton = styled(Button)<{ $align: 'left' | 'right' }>`
display: none;
position: absolute;
left: ${({ $align }) => ($align === 'right' ? '100%' : 'auto')};
right: ${({ $align }) => ($align === 'left' ? '100%' : 'auto')};
top: 50%;
transform: translateY(-50%);
`;

const PlaceholderContainer = styled.span`
position: relative;
&:hover ${StyledButton} {
display: block;
}
`;
6 changes: 5 additions & 1 deletion frontend/src/plate/components/placeholder/placeholder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,11 @@ const Placeholder = ({ canManage, ...props }: PlaceholderProps) => {
const hideDeleteButton = useMemo(() => {
const path = findNodePath(editor, element);

return !(canManage && hasNoVisibleText) || lonePlaceholderInMaltekst(editor, element, path);
return (
!(canManage && hasNoVisibleText) ||
lonePlaceholderInMaltekst(editor, element, path) ||
element.deletable === false
);
}, [editor, element, hasNoVisibleText, canManage]);

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ export const Wrapper = styled.span`
content: attr(data-placeholder);
user-select: none;
}
`;
7 changes: 6 additions & 1 deletion frontend/src/plate/plugins/element-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const ELEMENT_REGELVERK_CONTAINER = 'regelverk-container';
export const ELEMENT_HEADER = 'header';
export const ELEMENT_FOOTER = 'footer';
export const ELEMENT_LABEL_CONTENT = 'label-content';
export const ELEMENT_FULLMEKTIG = 'fullmektig';
export const ELEMENT_SIGNATURE = 'signature';
export const ELEMENT_EMPTY_VOID = 'empty-void';

Expand All @@ -22,6 +23,10 @@ export const UNCHANGEABLE = [
ELEMENT_REGELVERK,
];

export const UNDELETABLE_BUT_REDIGERBAR = [ELEMENT_REDIGERBAR_MALTEKST, ELEMENT_REGELVERK_CONTAINER];
export const UNDELETABLE_BUT_REDIGERBAR = [
ELEMENT_REDIGERBAR_MALTEKST,
ELEMENT_REGELVERK_CONTAINER,
ELEMENT_FULLMEKTIG,
];
export const UNDELETABLE = [...UNCHANGEABLE, ...UNDELETABLE_BUT_REDIGERBAR, ELEMENT_MALTEKSTSEKSJON];
export const UNINTERACTIONABLE = [ELEMENT_HEADER, ELEMENT_FOOTER, ELEMENT_CURRENT_DATE];
16 changes: 16 additions & 0 deletions frontend/src/plate/plugins/fullmektig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Fullmektig } from '@app/plate/components/fullmektig';
import { createPlatePlugin } from '@udecode/plate-core/react';
import { ELEMENT_FULLMEKTIG } from './element-types';

export const FullmektigPlugin = createPlatePlugin({
key: ELEMENT_FULLMEKTIG,
node: {
isElement: true,
isVoid: false,
isInline: true,
component: Fullmektig,
},
});

export const FULLMEKTIG_LABEL_PLACEHOLDER = 'Fullmektigetikett';
export const FULLMEKTIG_VALUE_PLACEHOLDER = 'Fullmektig';
2 changes: 2 additions & 0 deletions frontend/src/plate/plugins/plugin-sets/saksbehandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { BookmarkPlugin } from '@app/plate/plugins/bookmark';
import { CommentsPlugin } from '@app/plate/plugins/comments';
import { CurrentDatePlugin } from '@app/plate/plugins/current-date';
import { EmptyVoidPlugin } from '@app/plate/plugins/empty-void';
import { FullmektigPlugin } from '@app/plate/plugins/fullmektig';
import { FooterPlugin, HeaderPlugin } from '@app/plate/plugins/header-footer';
import { LabelContentPlugin } from '@app/plate/plugins/label-content';
import { MaltekstPlugin } from '@app/plate/plugins/maltekst';
Expand Down Expand Up @@ -61,6 +62,7 @@ export const saksbehandlerPlugins = [
HeaderPlugin,
FooterPlugin,
LabelContentPlugin,
FullmektigPlugin,
SignaturePlugin,
EmptyVoidPlugin,
CommentsPlugin,
Expand Down
43 changes: 43 additions & 0 deletions frontend/src/plate/plugins/prohibit-deletion/fullmektig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { ELEMENT_FULLMEKTIG, ELEMENT_PLACEHOLDER } from '@app/plate/plugins/element-types';
import { findNode, isEndPoint, isStartPoint } from '@udecode/plate-common';
import type { PlateEditor } from '@udecode/plate-core/react';

export const handleDeleteBackwardInFullmektig = (editor: PlateEditor): boolean => {
if (editor.selection === null) {
return false;
}

const fullmektig = findNode(editor, { match: { type: ELEMENT_FULLMEKTIG } });

if (fullmektig === undefined) {
return false;
}

const placeholder = findNode(editor, { match: { type: ELEMENT_PLACEHOLDER } });

if (placeholder === undefined) {
return false;
}

return isStartPoint(editor, editor.selection.focus, placeholder[1]);
};

export const handleDeleteForwardInFullmektig = (editor: PlateEditor): boolean => {
if (editor.selection === null) {
return false;
}

const fullmektig = findNode(editor, { match: { type: ELEMENT_FULLMEKTIG } });

if (fullmektig === undefined) {
return false;
}

const placeholder = findNode(editor, { match: { type: ELEMENT_PLACEHOLDER } });

if (placeholder === undefined) {
return false;
}

return isEndPoint(editor, editor.selection.focus, placeholder[1]);
};
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import {
handleDeleteBackwardInFullmektig,
handleDeleteForwardInFullmektig,
} from '@app/plate/plugins/prohibit-deletion/fullmektig';
import {
handleDeleteBackwardIntoUnchangeable,
handleDeleteForwardIntoUnchangeable,
Expand All @@ -12,7 +16,7 @@ import { type PlateEditor, createPlatePlugin } from '@udecode/plate-core/react';
import type { EditorFragmentDeletionOptions, TextUnit } from 'slate';

const withOverrides = (editor: PlateEditor) => {
const { deleteBackward, deleteForward, deleteFragment, insertFragment, insertText, addMark } = editor;
const { deleteBackward, deleteForward, deleteFragment, insertFragment, insertText, addMark, delete: del } = editor;

editor.insertText = (text, options) => {
if (isUnchangeable(editor)) {
Expand All @@ -30,6 +34,20 @@ const withOverrides = (editor: PlateEditor) => {
return addMark(key, value);
};

editor.delete = (options) => {
const backward = options?.reverse === true;

if (backward) {
if (handleDeleteBackwardInFullmektig(editor)) {
return;
}
} else if (handleDeleteForwardInFullmektig(editor)) {
return;
}

return del(options);
};

editor.deleteBackward = (unit: TextUnit) => {
if (handleDeleteInsideUnchangeable(editor, 'backward', unit)) {
return;
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/plate/template-sections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
*/
export enum TemplateSections {
TITLE = 'section-esel',
INTRODUCTION = 'section-rev',
INTRODUCTION_V1 = 'section-rev',
INTRODUCTION_V2 = 'section-rev-v2',
ANKEINFO = 'section-ape',
ANFOERSLER = 'section-ulv',
Expand All @@ -24,7 +24,7 @@ export enum TemplateSections {
REGELVERK_TITLE = 'section-gnu',
SAKSKOSTNADER = 'section-gris',
FREMLEGG = 'section-geit',
TILSVARSRETT = 'section-hund',
TILSVARSRETT_V1 = 'section-hund',
TILSVARSRETT_V2 = 'section-hund-v2',
VEDLEGG = 'section-katt',
SVAR_FRA_ROL = 'section-emu',
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/plate/templates/ankevedtak.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { TemplateSections } from '@app/plate/template-sections';
import {
createCurrentDate,
createFooter,
createFullmektig,
createHeader,
createLabelContent,
createMaltekstseksjon,
Expand Down Expand Up @@ -31,11 +32,12 @@ const INITIAL_SLATE_VALUE: Value = [
createLabelContent(Source.SAKEN_GJELDER_IF_DIFFERENT_FROM_KLAGER_NAME, 'Saken gjelder'),
createLabelContent(Source.SAKEN_GJELDER_FNR, 'Fødselsnummer'),
createLabelContent(Source.KLAGER_IF_DIFFERENT_FROM_SAKEN_GJELDER_NAME, 'Den ankende part'),
createFullmektig(),
createLabelContent(Source.SAKSNUMMER, 'Saksnummer'),
],
},

createMaltekstseksjon(TemplateSections.INTRODUCTION),
createMaltekstseksjon(TemplateSections.INTRODUCTION_V2),
createMaltekstseksjon(TemplateSections.AVGJOERELSE),
createMaltekstseksjon(TemplateSections.ANFOERSLER),
createMaltekstseksjon(TemplateSections.OPPLYSNINGER),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { TemplateSections } from '@app/plate/template-sections';
import {
createCurrentDate,
createFooter,
createFullmektig,
createHeader,
createLabelContent,
createMaltekstseksjon,
Expand Down Expand Up @@ -31,11 +32,12 @@ const INITIAL_SLATE_VALUE: Value = [
createLabelContent(Source.SAKEN_GJELDER_IF_DIFFERENT_FROM_KLAGER_NAME, 'Saken gjelder'),
createLabelContent(Source.SAKEN_GJELDER_FNR, 'Fødselsnummer'),
createLabelContent(Source.KLAGER_IF_DIFFERENT_FROM_SAKEN_GJELDER_NAME, 'Klager'),
createFullmektig(),
createLabelContent(Source.SAKSNUMMER, 'Saksnummer'),
],
},

createMaltekstseksjon(TemplateSections.INTRODUCTION),
createMaltekstseksjon(TemplateSections.INTRODUCTION_V2),
createMaltekstseksjon(TemplateSections.AVGJOERELSE),
createMaltekstseksjon(TemplateSections.ANFOERSLER),
createMaltekstseksjon(TemplateSections.OPPLYSNINGER),
Expand Down
Loading

0 comments on commit 9f16daf

Please sign in to comment.