Skip to content

Commit

Permalink
Ux forbedringer (#3553)
Browse files Browse the repository at this point in the history
* Henter saksbehandler fra global data i stedet for useQuery. Appen rendres ikke før data er på plass der, og den refetcher ikke så da slipper man å tenke på staleTime og at det refetches når man ikke vil

* individuell loading-state for køer som berikes med antall

* try catch på henting av antall

* henter saksbehandlerinfo med react-query overalt, uten refetching

* legger til optional chaining for å fikse test. I appen bør innloggetsaksbehandler aldri være undefined her

* whoops
  • Loading branch information
vebnor authored Dec 19, 2024
1 parent 2e08187 commit 87ee5aa
Show file tree
Hide file tree
Showing 11 changed files with 87 additions and 72 deletions.
5 changes: 3 additions & 2 deletions src/client/app/admin/AdminIndex.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import useTrackRouteParam from 'app/data/trackRouteParam';
import NavAnsatt from 'app/navAnsattTsType';
import { getPanelLocationCreator } from 'app/paths';
import { RestApiGlobalStatePathsKeys } from 'api/k9LosApi';
import { useInnloggetSaksbehandler } from 'api/queries/saksbehandlerQueries';
import useGlobalStateRestApiData from 'api/rest-api-hooks/src/global-data/useGlobalStateRestApiData';
import LoadingPanel from 'sharedComponents/LoadingPanel';
import { parseQueryString } from 'utils/urlUtils';
Expand Down Expand Up @@ -65,9 +66,9 @@ export const AdminIndex: FunctionComponent = () => {
const getDriftsmeldingerPanelLocation = getPanelLocationCreator(location);
const activePanel = activePanelTemp || hentPanelFromUrlOrDefault(location);

const { kanDrifte } = useGlobalStateRestApiData<NavAnsatt>(RestApiGlobalStatePathsKeys.NAV_ANSATT);
const { data: saksbehandler } = useInnloggetSaksbehandler();

if (!kanDrifte) {
if (!saksbehandler.kanDrifte) {
return <IkkeTilgangTilAvdelingslederPanel />;
}
if (activePanel) {
Expand Down
7 changes: 6 additions & 1 deletion src/client/app/api/queries/saksbehandlerQueries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ import { OppgavekøV3Enkel } from 'types/OppgavekøV3Type';
import { axiosInstance } from 'utils/reactQueryConfig';

export const useInnloggetSaksbehandler = (options: UseQueryOptions<NavAnsatt, Error> = {}) =>
useQuery(apiPaths.saksbehandler, options);
useQuery(apiPaths.saksbehandler, {
...options,
staleTime: Infinity,
cacheTime: Infinity,
refetchOnWindowFocus: false,
});
export const useGetAlleSaksbehandlere = (options: UseQueryOptions<SaksbehandlerEnkel[], Error> = {}) =>
useQuery<SaksbehandlerEnkel[], Error>(apiPaths.hentSaksbehandlereSomSaksbehandler, options);

Expand Down
27 changes: 17 additions & 10 deletions src/client/app/app/AppConfigResolver.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { FunctionComponent, ReactElement, useEffect } from 'react';
import useRestApiErrorDispatcher from 'api/error/useRestApiErrorDispatcher';
import { RestApiGlobalStatePathsKeys, k9LosApi } from 'api/k9LosApi';
import { useInnloggetSaksbehandler } from 'api/queries/saksbehandlerQueries';
import { useGlobalStateRestApi } from 'api/rest-api-hooks';
import RestApiState from 'api/rest-api-hooks/src/RestApiState';
import LoadingPanel from 'sharedComponents/LoadingPanel';
Expand All @@ -15,26 +16,32 @@ const AppConfigResolver: FunctionComponent<OwnProps> = ({ children }) => {
k9LosApi().setAddErrorMessageHandler(addErrorMessage);
}, []);

const { state: stateNavAnsatt } = useGlobalStateRestApi(RestApiGlobalStatePathsKeys.NAV_ANSATT);
const {
data: innloggetSaksbehandler,
isSuccess: harHentetInnloggetSaksbehandler,
isLoading: isLoadingSaksbehandler,
} = useInnloggetSaksbehandler();

const { state: stateK9sakUrl } = useGlobalStateRestApi(RestApiGlobalStatePathsKeys.K9SAK_URL, undefined, {
suspendRequest: stateNavAnsatt !== RestApiState.SUCCESS,
updateTriggers: [stateNavAnsatt],
suspendRequest: !harHentetInnloggetSaksbehandler,
updateTriggers: [innloggetSaksbehandler],
});
const { state: stateKodeverk } = useGlobalStateRestApi(RestApiGlobalStatePathsKeys.KODEVERK, undefined, {
suspendRequest: stateNavAnsatt !== RestApiState.SUCCESS,
updateTriggers: [stateNavAnsatt],
suspendRequest: !harHentetInnloggetSaksbehandler,
updateTriggers: [innloggetSaksbehandler],
});
const { state: stateSseUrl } = useGlobalStateRestApi(RestApiGlobalStatePathsKeys.REFRESH_URL, undefined, {
suspendRequest: stateNavAnsatt !== RestApiState.SUCCESS,
updateTriggers: [stateNavAnsatt],
suspendRequest: !harHentetInnloggetSaksbehandler,
updateTriggers: [innloggetSaksbehandler],
});
const { state: stateK9punsjUrl } = useGlobalStateRestApi(RestApiGlobalStatePathsKeys.PUNSJ_URL, undefined, {
suspendRequest: stateNavAnsatt !== RestApiState.SUCCESS,
updateTriggers: [stateNavAnsatt],
suspendRequest: !harHentetInnloggetSaksbehandler,
updateTriggers: [innloggetSaksbehandler],
});

if (
[stateK9sakUrl, stateNavAnsatt, stateKodeverk, stateSseUrl, stateK9punsjUrl].some((v) => v === RestApiState.LOADING)
isLoadingSaksbehandler ||
[stateK9sakUrl, stateKodeverk, stateSseUrl, stateK9punsjUrl].some((v) => v === RestApiState.LOADING)
) {
return <LoadingPanel />;
}
Expand Down
21 changes: 10 additions & 11 deletions src/client/app/app/components/HeaderWithErrorPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ import Endringslogg from '@navikt/familie-endringslogg';
import { BoxedListWithLinks, Header, Popover, SystemButton, UserPanel } from '@navikt/ft-plattform-komponenter';
import DriftsmeldingPanel from 'app/components/DriftsmeldingPanel';
import ErrorFormatter from 'app/feilhandtering/ErrorFormatter';
import NavAnsatt from 'app/navAnsattTsType';
import { RETTSKILDE_URL, SHAREPOINT_URL } from 'api/eksterneLenker';
import useRestApiError from 'api/error/useRestApiError';
import useRestApiErrorDispatcher from 'api/error/useRestApiErrorDispatcher';
import { K9LosApiKeys, RestApiGlobalStatePathsKeys } from 'api/k9LosApi';
import { useGlobalStateRestApiData } from 'api/rest-api-hooks';
import { K9LosApiKeys } from 'api/k9LosApi';
import { useInnloggetSaksbehandler } from 'api/queries/saksbehandlerQueries';
import useRestApi from 'api/rest-api-hooks/src/local-data/useRestApi';
import { Driftsmelding } from '../../admin/driftsmeldinger/driftsmeldingTsType';
import ErrorMessagePanel from './ErrorMessagePanel';
Expand Down Expand Up @@ -70,7 +69,7 @@ const HeaderWithErrorPanel: FunctionComponent<OwnProps> = ({ queryStrings, crash
const navigate = useNavigate();
const intl = useIntl();

const navAnsatt = useGlobalStateRestApiData<NavAnsatt>(RestApiGlobalStatePathsKeys.NAV_ANSATT);
const { data: innloggetSaksbehandler } = useInnloggetSaksbehandler();
const { data: driftsmeldinger = [] } = useRestApi<Driftsmelding[]>(K9LosApiKeys.DRIFTSMELDINGER);

const errorMessages = useRestApiError() || [];
Expand All @@ -86,7 +85,7 @@ const HeaderWithErrorPanel: FunctionComponent<OwnProps> = ({ queryStrings, crash
setLenkePanelApent,
setAvdelingerPanelApent,
);
const brukerPanel = <UserPanel name={navAnsatt.navn} />;
const brukerPanel = <UserPanel name={innloggetSaksbehandler?.navn} />;
const fixedHeaderRef = useRef(null);

const goTilAvdelingslederPanel = () => {
Expand All @@ -109,20 +108,20 @@ const HeaderWithErrorPanel: FunctionComponent<OwnProps> = ({ queryStrings, crash
};

const visAvdelingslederKnapp = (): boolean => {
if (!navAnsatt.kanOppgavestyre) {
if (!innloggetSaksbehandler?.kanOppgavestyre) {
return false;
}
if (navAnsatt.kanOppgavestyre && window.location.href.includes('avdelingsleder')) {
if (innloggetSaksbehandler?.kanOppgavestyre && window.location.href.includes('avdelingsleder')) {
return false;
}
return true;
};

const visAdminKnapp = (): boolean => {
if (!navAnsatt.kanDrifte) {
if (!innloggetSaksbehandler?.kanDrifte) {
return false;
}
if (navAnsatt.kanDrifte && window.location.href.includes('admin')) {
if (innloggetSaksbehandler?.kanDrifte && window.location.href.includes('admin')) {
return false;
}
return true;
Expand Down Expand Up @@ -187,10 +186,10 @@ const HeaderWithErrorPanel: FunctionComponent<OwnProps> = ({ queryStrings, crash
https://github.com/navikt/familie-endringslogg
For å nå backend lokalt må man være tilkoblet naisdevice og kjøre opp k9-sak-web på port 8000 pga CORS
*/}
{navAnsatt?.brukerIdent && window.location.hostname.includes('nav') && (
{innloggetSaksbehandler?.brukerIdent && window.location.hostname.includes('nav') && (
<div className={styles['endringslogg-container']}>
<Endringslogg
userId={navAnsatt.brukerIdent}
userId={innloggetSaksbehandler?.brukerIdent}
appId="K9_SAK"
appName="K9 Sak"
backendUrl={
Expand Down
12 changes: 5 additions & 7 deletions src/client/app/app/components/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ import { useQuery, useQueryClient } from 'react-query';
import { Route, Routes } from 'react-router-dom';
import { withSentryReactRouterV6Routing } from '@sentry/react';
import AppContext from 'app/AppContext';
import NavAnsatt from 'app/navAnsattTsType';
import apiPaths from 'api/apiPaths';
import { RestApiGlobalStatePathsKeys } from 'api/k9LosApi';
import { useGlobalStateRestApiData } from 'api/rest-api-hooks';
import { useInnloggetSaksbehandler } from 'api/queries/saksbehandlerQueries';
import AvdelingslederIndex from 'avdelingsleder/AvdelingslederIndex';
import { Oppgavefelt } from 'filter/filterTsTypes';
import SaksbehandlerIndex from 'saksbehandler/SaksbehandlerIndex';
Expand All @@ -23,18 +21,18 @@ import MissingPage from './MissingPage';
const SentryRoutes = withSentryReactRouterV6Routing(Routes);
const Home: FunctionComponent = () => {
const { data } = useQuery<{ felter: Oppgavefelt[] }>(apiPaths.hentOppgaveFelter);
const { kanOppgavestyre, brukerIdent } = useGlobalStateRestApiData<NavAnsatt>(RestApiGlobalStatePathsKeys.NAV_ANSATT);
const { data: saksbehandler } = useInnloggetSaksbehandler();

const queryClient = useQueryClient();

useEffect(() => {
if (brukerIdent) {
if (kanOppgavestyre) {
if (saksbehandler.brukerIdent) {
if (saksbehandler.kanOppgavestyre) {
queryClient.prefetchQuery(apiPaths.hentSaksbehandlereAvdelingsleder);
}
queryClient.prefetchQuery(apiPaths.hentSaksbehandlereSomSaksbehandler);
}
}, [queryClient, brukerIdent, kanOppgavestyre]);
}, [queryClient, saksbehandler.brukerIdent, saksbehandler.kanOppgavestyre]);

const contextValues = useMemo(() => ({ felter: data ? data.felter : [] }), [data]);

Expand Down
1 change: 1 addition & 0 deletions src/client/app/app/navAnsattTsType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type NavAnsatt = Readonly<{
kanReservere: boolean;
funksjonellTid: string;
kanDrifte: boolean;
finnesISaksbehandlerTabell: boolean;
}>;

export default NavAnsatt;
9 changes: 4 additions & 5 deletions src/client/app/avdelingsleder/AvdelingslederIndex.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@ import {
import { BodyShort, Heading } from '@navikt/ds-react';
import useTrackRouteParam from 'app/data/trackRouteParam';
import { avdelingslederTilgangTilNyeKoer } from 'app/envVariablesUtils';
import NavAnsatt from 'app/navAnsattTsType';
import { getPanelLocationCreator } from 'app/paths';
import { K9LosApiKeys, RestApiGlobalStatePathsKeys } from 'api/k9LosApi';
import useGlobalStateRestApiData from 'api/rest-api-hooks/src/global-data/useGlobalStateRestApiData';
import { K9LosApiKeys } from 'api/k9LosApi';
import { useInnloggetSaksbehandler } from 'api/queries/saksbehandlerQueries';
import useRestApiRunner from 'api/rest-api-hooks/src/local-data/useRestApiRunner';
import DagensTallPanel from 'avdelingsleder/dagensTall/DagensTallPanel';
import ApneBehandlinger from 'avdelingsleder/dagensTall/apneBehandlingerTsType';
Expand Down Expand Up @@ -137,12 +136,12 @@ export const AvdelingslederIndex: FunctionComponent = () => {
return panelFromUrl.avdelingsleder ? panelFromUrl.avdelingsleder : AvdelingslederPanels.BEHANDLINGSKOER;
};

const { kanOppgavestyre } = useGlobalStateRestApiData<NavAnsatt>(RestApiGlobalStatePathsKeys.NAV_ANSATT);
const { data: innnloggetSaksbehandler } = useInnloggetSaksbehandler();

const getAvdelingslederPanelLocation = getPanelLocationCreator(location);
const activeAvdelingslederPanel = activeAvdelingslederPanelTemp || getPanelFromUrlOrDefault(location);

if (!kanOppgavestyre) {
if (!innnloggetSaksbehandler.kanOppgavestyre) {
return <IkkeTilgangTilAvdelingslederPanel />;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { Fragment, useState } from 'react';
import { useQuery } from 'react-query';
import React, { useState } from 'react';
import { useQueries } from 'react-query';
import dayjs from 'dayjs';
import { PlusCircleIcon } from '@navikt/aksel-icons';
import { Button, Loader, Skeleton, Table } from '@navikt/ds-react';
Expand All @@ -26,26 +26,34 @@ function scrollToId(id: string) {
intervalId = setInterval(scroll, 100);
}

const berikMedAntallOppgaver = (køArray: OppgavekøV3Enkel[]) =>
useQuery(
['beriketAntallOppgaver', køArray],
async () => {
const requests = køArray.map(async () => {
const berikMedAntallOppgaverIndividuelt = (køArray: OppgavekøV3Enkel[]) => {
const queries = useQueries(
køArray.map(() => ({
queryKey: ['antallOppgaver', .id],
queryFn: async () => {
try {
const { data } = await axiosInstance.get(apiPaths.antallOppgaverIKoV3(.id));
return { ..., ...data };
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (error) {
console.error('Error fetching antallOppgaver', error);
return { ... };
}
});
return Promise.all(requests);
},
{
enabled: !!køArray,
},
},
enabled: !!køArray.length,
})),
);

const isSuccess = queries.every((query) => query.isSuccess);
const results = queries.map((query, index) => ({
...(køArray[index] || {}),
...query.data,
isLoading: query.isLoading,
isError: query.isError,
}));

return { results, isSuccess };
};

const Row = ({
,
ekspandert,
Expand Down Expand Up @@ -82,11 +90,9 @@ const Row = ({
);
const BehandlingskoerIndex = () => {
const { data: initielleKøer, isLoading, error } = useAlleKoer();
const {
data: køerMedAntallOppgaver,
isLoading: isLoadingAntallOppgaver,
isSuccess: harHentetAntallOppgaver,
} = berikMedAntallOppgaver(initielleKøer);
const { results: køerMedAntallOppgaver, isSuccess: isSuccessAll } = berikMedAntallOppgaverIndividuelt(
initielleKøer || [],
);
const [visNyKøModal, setVisNyKøModal] = useState(false);
const [sort, setSort] = useState(null);
const [ekspanderteKøer, setEkspanderteKøer] = useState([]);
Expand Down Expand Up @@ -160,7 +166,7 @@ const BehandlingskoerIndex = () => {
<Table.ColumnHeader sortKey="antallSaksbehandlere" sortable scope="col">
Saksbehandlere
</Table.ColumnHeader>
<Table.ColumnHeader sortKey="antallUtenReserverte" sortable={harHentetAntallOppgaver} scope="col">
<Table.ColumnHeader sortKey="antallUtenReserverte" sortable={isSuccessAll} scope="col">
Antall oppgaver (med reserverte)
</Table.ColumnHeader>
<Table.ColumnHeader sortKey="sistEndret" sortable scope="col">
Expand All @@ -174,7 +180,7 @@ const BehandlingskoerIndex = () => {
<Row
key={.id}
={}
isLoadingAntallOppgaver={isLoadingAntallOppgaver}
isLoadingAntallOppgaver={.isLoading}
ekspandert={ekspanderteKøer.includes(.id)}
toggleExpand={() => toggleExpand(.id)}
/>
Expand Down
8 changes: 3 additions & 5 deletions src/client/app/saksbehandler/SaksbehandlerIndex.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import React from 'react';
import NavAnsatt from 'app/navAnsattTsType';
import { RestApiGlobalStatePathsKeys } from 'api/k9LosApi';
import useGlobalStateRestApiData from 'api/rest-api-hooks/src/global-data/useGlobalStateRestApiData';
import { useInnloggetSaksbehandler } from 'api/queries/saksbehandlerQueries';
import IkkeTilgangTilAvdelingslederPanel from 'avdelingsleder/components/IkkeTilgangTilAvdelingslederPanel';
import SaksbehandlerDashboard from './components/SaksbehandlerDashboard';

Expand All @@ -10,8 +8,8 @@ import SaksbehandlerDashboard from './components/SaksbehandlerDashboard';
*/

const SaksbehandlerIndex = () => {
const { kanSaksbehandle } = useGlobalStateRestApiData<NavAnsatt>(RestApiGlobalStatePathsKeys.NAV_ANSATT);
if (!kanSaksbehandle) {
const { data: saksbehandler } = useInnloggetSaksbehandler();
if (!saksbehandler.kanSaksbehandle) {
return <IkkeTilgangTilAvdelingslederPanel />;
}
return <SaksbehandlerDashboard />;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { FunctionComponent } from 'react';
import Panel from 'nav-frontend-paneler';
import { sokeboksNyeKoer } from 'app/envVariablesUtils';
import { RestApiGlobalStatePathsKeys } from 'api/k9LosApi';
import { useInnloggetSaksbehandler } from 'api/queries/saksbehandlerQueries';
import useGlobalStateRestApiData from 'api/rest-api-hooks/src/global-data/useGlobalStateRestApiData';
import { Søkeboks } from 'saksbehandler/sokeboks/Søkeboks';
import BehandlingskoerIndex from '../behandlingskoer/BehandlingskoerIndex';
Expand All @@ -15,6 +16,7 @@ import * as styles from './saksbehandlerDashboard.css';
export const SaksbehandlerDashboard: FunctionComponent = () => {
const k9sakUrl = useGlobalStateRestApiData<{ verdi?: string }>(RestApiGlobalStatePathsKeys.K9SAK_URL);
const k9punsjUrl = useGlobalStateRestApiData<{ verdi?: string }>(RestApiGlobalStatePathsKeys.PUNSJ_URL);
const { data: saksbehandler } = useInnloggetSaksbehandler();

return (
<div>
Expand All @@ -28,11 +30,13 @@ export const SaksbehandlerDashboard: FunctionComponent = () => {
<FagsakSearchIndex k9punsjUrl={k9punsjUrl.verdi} k9sakUrl={k9sakUrl.verdi} />
)}
</Panel>
<div>
<Panel className={styles.sakslistePanel}>
<BehandlingskoerIndex k9sakUrl={k9sakUrl.verdi} k9punsjUrl={k9punsjUrl.verdi} />
</Panel>
</div>
{saksbehandler.finnesISaksbehandlerTabell && (
<div>
<Panel className={styles.sakslistePanel}>
<BehandlingskoerIndex k9sakUrl={k9sakUrl.verdi} k9punsjUrl={k9punsjUrl.verdi} />
</Panel>
</div>
)}
</div>
<div className={styles.rightColumn}>
<Panel>
Expand Down
7 changes: 2 additions & 5 deletions src/client/app/saksbehandler/sokeboks/OppgaveModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ const åpneOppgave = (oppgave: SøkeboksOppgaveDto) => {
};

export function OppgaveModal(props: { oppgave: SøkeboksOppgaveDto; open: boolean; closeModal: () => void }) {
const { isFetched: isFetchedSaksbehandler, data: innloggetSaksbehandler } = useInnloggetSaksbehandler();
const { data: innloggetSaksbehandler } = useInnloggetSaksbehandler();

const { isLoading: isLoadingEndreReservasjoner, mutate: endreReservasjoner } = useEndreReservasjoner(() =>
åpneOppgave(props.oppgave),
);
Expand All @@ -25,10 +26,6 @@ export function OppgaveModal(props: { oppgave: SøkeboksOppgaveDto; open: boolea
props.closeModal,
);

if (!isFetchedSaksbehandler) {
return null;
}

const { visÅpneOgReserverKnapp, visÅpneOgEndreReservasjonKnapp, visLeggTilbakeIKøKnapp, heading, modaltekst } =
modalInnhold(props.oppgave, innloggetSaksbehandler);

Expand Down

0 comments on commit 87ee5aa

Please sign in to comment.