Skip to content

Commit bbdd20d

Browse files
committed
Legg til mulighet for å ignorere ekstern state
Brukes i oversiktsbilder der man ikke har bruker i kontekst men fortsatt vil kunne bruke søkefeltet til å navigere til "person" side.
1 parent 682eacd commit bbdd20d

File tree

7 files changed

+82
-21
lines changed

7 files changed

+82
-21
lines changed

Migrating-v3.md

+11-9
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,14 @@ konfigurasjonen til å passe v3.
6262

6363
**Nye props**
6464

65-
| v3 | Kommentar |
66-
| ------------------------- | ---------------------------------------------------------------------- |
67-
| `showHotkeys: boolean` | Vis knapp som åpner modal med liste om registrete hotkeys. |
68-
| `environment` | Hvilket miljø appen kjører i |
69-
| `urlFormat` | Hvilket URL format som brukes (ansatt eller intern) |
70-
| `fetchActiveUserOnMount` | Om bruker fra context skal hentes dersom `fnr` er `undefined` |
71-
| `fetchActiveEnhetOnMount` | Om enhet fra context skal hentes dersom `enhet` er `undefined` |
72-
| `enableHotkeys` | Skru på hotkeys (NB: ikke på by default) |
73-
| `includeCredentials` | Sett `credentials: "include"` på outgoing requests til contextholderen |
65+
| v3 | Kommentar |
66+
| ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
67+
| `showHotkeys: boolean` | Vis knapp som åpner modal med liste om registrete hotkeys. |
68+
| `environment` | Hvilket miljø appen kjører i |
69+
| `urlFormat` | Hvilket URL format som brukes (ansatt eller intern) |
70+
| `fetchActiveUserOnMount` | Om bruker fra context skal hentes dersom `fnr` er `undefined` |
71+
| `fetchActiveEnhetOnMount` | Om enhet fra context skal hentes dersom `enhet` er `undefined` |
72+
| `fnrSyncMode` | "sync" eller "writeOnly". Styrer om state skal synkroniseres eller om endringer kun skal gå en vei. Brukes for oversikts apper der man ikke har bruker i kontekst men ønsker å kunne navigere til personview med søkefeltet |
73+
| `enhetSyncMode` | Fungerer likt som `fnrSyncMode` men for brukers enhet |
74+
| `enableHotkeys` | Skru på hotkeys (NB: ikke på by default) |
75+
| `includeCredentials` | Sett `credentials: "include"` på outgoing requests til contextholderen |

README.md

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
# Dekoratør for interne arbeidsflater V3
22

3-
> [!NOTE]
4-
> v2.1 kjører fortsatt i prod. Du kan finne denne i [v2.1 branchen](https://github.com/navikt/internarbeidsflatedecorator/tree/v2.1)
5-
63
**[Migrasjonsguide for V3](./Migrating-v3.md)**
74

85
Dekoratøren er en navigasjonsmeny som skal kunne brukes på tvers av fagapplikasjoner i NAV.
@@ -60,7 +57,6 @@ function App() {
6057
### Manuelt oppsett
6158

6259
Om man ikke bruker react så kan man fortsatt ta ibruk decoratoren, men man må da kalle render-funksjonen selv.
63-
Ett eksempel på hvordan dette kan gjøres kan ses i [index.html](../public/index.html).
6460

6561
## Konfigurasjon
6662

@@ -74,6 +70,8 @@ export interface DecoratorProps {
7470
enableHotkeys?: boolean | undefined; // Aktivere hurtigtaster
7571
fetchActiveEnhetOnMount?: boolean | undefined; // Om enhet er undefined fra container appen, og denne er satt til true, henter den sist aktiv enhet og bruker denne.
7672
fetchActiveUserOnMount?: boolean | undefined; // Om fnr er undefined fra container appen, og denne er satt til true for at den skal hente siste aktiv fnr.
73+
fnrSyncMode?: 'sync' | 'writeOnly'; // Modus til fnr state management. "sync" er default. "writeOnly" gjør at endringer aldri hentes men vil settes dersom det oppdateres lokalt i appen
74+
enhetSyncMode?: 'sync' | 'writeOnly'; // Samme som fnrSyncMode, men for enhet state.
7775
onEnhetChanged: (enhetId?: string | null, enhet?: Enhet) => void; // Kalles når enheten endres
7876
onFnrChanged: (fnr?: string | null) => void; // Kalles når fnr enheten endres
7977
onLinkClick?: (link: { text: string; url: string }) => void; // Kan brukes for å legge til callbacks ved klikk på lenker i menyen. Merk at callbacken ikke kan awaites og man må selv håndtere at siden lukkes. Nyttig for å f.eks tracke navigasjon events i amplitude
@@ -108,7 +106,7 @@ export type Environment =
108106
| 'local'
109107
| 'mock';
110108

111-
export type UrlFormat = 'LOCAL' | 'NAV_NO' | 'ANSATT'; // UrlFormat. Brukes om proxy ikke er satt & i url til websocket.
109+
export type UrlFormat = 'LOCAL' | 'NAV_NO' | 'ANSATT'; // UrlFormat. Brukes til lenker i menyen & WS urlen
112110

113111
export interface HotkeyObject {
114112
char: string;

packages/internarbeidsflate-decorator-v3/src/Decorator.tsx

+13-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import React, { PropsWithChildren } from 'react';
22
import './index.css';
3-
import { AppProps } from './types/AppProps';
43
import useAppLogic from './hooks/useAppLogic';
54
import Banner from './components/Banner';
65
import Menu from './components/Menu';
@@ -9,9 +8,20 @@ import NewEnhetModal from './components/modals/NewEnhetModal';
98
import ErrorMessage from './components/ErrorMessageDisplay';
109
import { useOnOutsideClick } from './hooks/useOnOutsideClick';
1110
import { useAppState } from './states/AppState';
11+
import { DecoratorProps } from './types/AppProps';
12+
13+
const Decorator: React.FC<PropsWithChildren<DecoratorProps>> = (props) => {
14+
useAppLogic({
15+
...props,
16+
ignoreExternalFnr: props.fnrSyncMode === 'writeOnly',
17+
fetchActiveUserOnMount:
18+
props.fnrSyncMode === 'writeOnly' || props.fetchActiveUserOnMount,
19+
20+
ignoreExternalEnhet: props.fnrSyncMode === 'writeOnly',
21+
fetchActiveEnhetOnMount:
22+
props.enhetSyncMode === 'writeOnly' || props.fetchActiveEnhetOnMount,
23+
});
1224

13-
const Decorator: React.FC<PropsWithChildren<AppProps>> = (props) => {
14-
useAppLogic(props);
1525
const ref = useOnOutsideClick<HTMLElement>(() =>
1626
useAppState.setState({ open: false }),
1727
);

packages/internarbeidsflate-decorator-v3/src/hooks/useSyncStore.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ import StoreHandler from '../store/StoreHandler';
44

55
export const useSyncStore = (appProps: AppProps) => {
66
useEffect(() => {
7-
StoreHandler.propsUpdateHandler.onPropsUpdated(appProps);
7+
void StoreHandler.propsUpdateHandler.onPropsUpdated(appProps);
88
}, [appProps]);
99
};

packages/internarbeidsflate-decorator-v3/src/store/EventHandler.ts

+24-3
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,19 @@ import { FnrValueManager } from './FnrValueManager';
88
import { StoreProps } from './StoreHandler';
99
import { SubstateHandler, SubstateHandlerProps } from './SubstateHandler';
1010

11+
export type EventHandlerOptions = {
12+
ignoreExternalFnr?: boolean | undefined;
13+
ignoreExternalEnhet?: boolean | undefined;
14+
};
15+
1116
export class EventHandler extends SubstateHandler {
1217
#webSocketWrapper?: WebSocketWrapper | undefined;
1318
#errorMessageManager: ErrorMessageManager;
1419
#fnrValueManager: FnrValueManager;
1520
#enhetValueManager: EnhetValueManager;
1621

22+
#options: EventHandlerOptions = {};
23+
1724
constructor(
1825
substateProps: SubstateHandlerProps,
1926
fnrValueManager: FnrValueManager,
@@ -25,7 +32,14 @@ export class EventHandler extends SubstateHandler {
2532
this.#enhetValueManager = enhetValueManager;
2633
this.#errorMessageManager = errorMessageManager;
2734
}
28-
initialize = ({ wsUrl, environment, veileder }: StoreProps) => {
35+
36+
initialize = ({
37+
wsUrl,
38+
environment,
39+
veileder,
40+
ignoreExternalEnhet,
41+
ignoreExternalFnr,
42+
}: StoreProps) => {
2943
this.#webSocketWrapper = new WebSocketWrapper(
3044
`${wsUrl}${veileder.ident}`,
3145
environment,
@@ -36,14 +50,17 @@ export class EventHandler extends SubstateHandler {
3650
);
3751
this.#webSocketWrapper.open();
3852
this.registerShutdown('websocketwrapper', this.#webSocketWrapper.close);
53+
54+
this.#options.ignoreExternalFnr = ignoreExternalFnr;
55+
this.#options.ignoreExternalEnhet = ignoreExternalEnhet;
3956
};
4057

4158
#onWSMessage = (message: MessageEvent<WebSocketMessage>) => {
4259
const data = message.data;
4360
if (data === 'NY_AKTIV_BRUKER') {
44-
this.#handleFnrChangedExternally();
61+
void this.#handleFnrChangedExternally();
4562
} else if (data === 'NY_AKTIV_ENHET') {
46-
this.#handleEnhetChangedExternally();
63+
void this.#handleEnhetChangedExternally();
4764
}
4865
};
4966

@@ -55,6 +72,8 @@ export class EventHandler extends SubstateHandler {
5572
};
5673

5774
#handleFnrChangedExternally = async () => {
75+
if (this.#options.ignoreExternalFnr) return;
76+
5877
const response = await this.contextHolderApi.getVeiledersActiveFnr();
5978
if (response.error || !response.data || !response.data.aktivBruker) {
6079
this.#errorMessageManager.addErrorMessage(
@@ -75,6 +94,8 @@ export class EventHandler extends SubstateHandler {
7594
};
7695

7796
#handleEnhetChangedExternally = async () => {
97+
if (this.#options.ignoreExternalEnhet) return;
98+
7899
const response = await this.contextHolderApi.getVeiledersActiveEnhet();
79100
if (response.error || !response.data || !response.data.aktivEnhet) {
80101
this.#errorMessageManager.addErrorMessage(

packages/internarbeidsflate-decorator-v3/src/store/__test__/StoreHandler.test.ts

+21
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,27 @@ describe('StoreHandler test', () => {
133133
expect(storeHandler.state.veileder).toStrictEqual(mockMe);
134134
});
135135

136+
it('skal ignorere events fra websocket om igoreExternalFnr er true', async () => {
137+
const storeHandler = new StoreHandler();
138+
updateMockContext({ aktivBruker: '07063000250' });
139+
storeHandler.propsUpdateHandler.onPropsUpdated({
140+
enhet: '0118',
141+
fnr: undefined,
142+
ignoreExternalFnr: true,
143+
...defaultProps,
144+
});
145+
await ws.connected;
146+
sendWSMessage('NY_AKTIV_BRUKER');
147+
await awaitTimeout(100, 'for å la staten bli propagert');
148+
expect(storeHandler.state.fnr.value).toBe(undefined);
149+
expect(storeHandler.state.fnr.showModal).toBeFalsy();
150+
151+
updateMockContext({ aktivEnhet: '0219' });
152+
sendWSMessage('NY_AKTIV_ENHET');
153+
await awaitTimeout(100, 'for å la staten bli propagert');
154+
expect(storeHandler.state.enhet.showModal).toBeTruthy();
155+
});
156+
136157
it('skal vise modal om bruker endrer aktiv enhet i annet vindu, gitt at det ikke er samme enhet', async () => {
137158
const storeHandler = new StoreHandler();
138159

packages/internarbeidsflate-decorator-v3/src/types/AppProps.ts

+9
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,15 @@ interface DomainProps {
1515
onFnrChanged: (fnr?: string | null) => void;
1616
onLinkClick?: (link: { text: string; url: string }) => void;
1717
websocketUrl?: string | undefined;
18+
19+
ignoreExternalFnr?: boolean;
20+
ignoreExternalEnhet?: boolean;
1821
}
1922

2023
export interface AppProps extends DomainProps, Omit<AppState, 'open'> {}
24+
25+
export interface DecoratorProps
26+
extends Omit<AppProps, 'ignoreExternalFnr' | 'ignoreExternalEnhet'> {
27+
fnrSyncMode?: 'writeOnly' | 'sync';
28+
enhetSyncMode?: 'writeOnly' | 'sync';
29+
}

0 commit comments

Comments
 (0)