From 1caf7a5fe564e7e8a3abd180f9e99b0e6d919067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sindre=20Dahl=20L=C3=B8ken?= Date: Tue, 17 Oct 2023 14:12:58 +0200 Subject: [PATCH] Filtere i post request og sokId (#1170) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * mye virk * rydding * trolig mye vrik nå * litt rydding * bruker currentPage fra context og bruker nettressurs ku i avtaleoversikt * rydding av ubrukt og utkommentert kode * fikser sammenligning av søk fra backend og filtere slik at ting kan legges til i useEffect dep array * Rettet opp i useEffects som klaget på manglende dependencies. lagt til alle deps den ber om og håndtert at den trigger ved flere ting * rydding * støtte for arbeidsgivervisning. setter bedriftNr på filter når man endrer i menyen i stedet for magisk queryparam lytting * flytter ut hjelpefunksjon * fikser arbeidsgiver bedriftvelger inn i filteret og fikset håndtering av ugyldig sokId * skriveleif * fjerner unødvendig bedrift-mapping i rest-service og fikset bedrift filteret * ryddet opp i rest-kallene * 95% virk * rydding * masse virk * alt virker * mye arbeidsgiver virk * oppgradert bedriftsmenyen, skrudd av automatisk setting av bedrift i quertparametere og håndterer litt div sånt selv * Litt mer virk * ryddet kommentar * mer rydding * tesy * ny testt * fjerner test som feiler - den gir uansett ingen verdi pt. * lagt til useEffect dependency og fjernet ubrukt variabel * Fiks logikk dersom sok er ugyldig * Ved initiell POST, nullstill page * Initiell last + sorteringskolonne * Bevare sorteringskolonne ved initiell last * replacer url for å muliggjøre navigering * rydding --------- Co-authored-by: Odd Andreas Sørsæther --- package.json | 2 +- src/AvtaleOversikt/AvtaleOversikt.tsx | 126 +++++++++++++----- src/AvtaleOversikt/Avtaler.tsx | 12 +- .../Filtrering/DeltakerOgBedriftFilter.tsx | 32 +++-- .../Filtrering/FiltreringProvider.tsx | 72 ++++++++-- src/AvtaleOversikt/Filtrering/useFilter.ts | 59 ++++---- .../IngenAvtaler/IngenAvtaler.tsx | 12 +- src/AvtaleSide/AvtaleSide.tsx | 14 +- src/komponenter/Banner/Banner.spec.tsx | 8 -- src/komponenter/Banner/Banner.tsx | 37 ++++- src/services/rest-service.ts | 22 +++ src/types/avtale.ts | 16 +++ src/types/innlogget-bruker.ts | 2 +- src/utils/stringUtils.ts | 11 ++ yarn.lock | 32 ++++- 15 files changed, 334 insertions(+), 123 deletions(-) delete mode 100644 src/komponenter/Banner/Banner.spec.tsx diff --git a/package.json b/package.json index c8a676e01..edba570ea 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "@formatjs/intl-pluralrules": "^4.1.3", "@formatjs/intl-relativetimeformat": "^9.2.3", "@navikt/arbeidsgiver-notifikasjon-widget": "^6.3.9", - "@navikt/bedriftsmeny": "^6.4.3", + "@navikt/bedriftsmeny": "^6.11.0", "@navikt/ds-css": "^5.2.1", "@navikt/ds-icons": "^3.4.3", "@navikt/ds-react": "^5.2.1", diff --git a/src/AvtaleOversikt/AvtaleOversikt.tsx b/src/AvtaleOversikt/AvtaleOversikt.tsx index 37f19dffb..56600e1f9 100644 --- a/src/AvtaleOversikt/AvtaleOversikt.tsx +++ b/src/AvtaleOversikt/AvtaleOversikt.tsx @@ -1,26 +1,34 @@ -import { ReactComponent as PlussIkon } from '@/assets/ikoner/pluss-tegn.svg'; +import AvtaleOversiktArbeidsgiverInformasjon from '@/AvtaleOversikt/AvtaleOversiktArbeidsgiverInformasjon'; import Avtaler from '@/AvtaleOversikt/Avtaler'; +import ArbeidsgiverFiltrering from '@/AvtaleOversikt/Filtrering/ArbeidsgiverFiltrering'; import VeilederFiltrering from '@/AvtaleOversikt/Filtrering/VeilederFiltrering'; +import { useFilter } from '@/AvtaleOversikt/Filtrering/useFilter'; import LesMerOmLøsningen from '@/AvtaleOversikt/LesMerOmLøsningen/LesMerOmLøsningen'; import useAvtaleOversiktLayout from '@/AvtaleOversikt/useAvtaleOversiktLayout'; import { InnloggetBrukerContext } from '@/InnloggingBoundary/InnloggingBoundary'; +import { ReactComponent as PlussIkon } from '@/assets/ikoner/pluss-tegn.svg'; +import Banner from '@/komponenter/Banner/Banner'; import BannerNAVAnsatt from '@/komponenter/Banner/BannerNAVAnsatt'; import Dokumenttittel from '@/komponenter/Dokumenttittel'; import VerticalSpacer from '@/komponenter/layout/VerticalSpacer'; +import LenkeKnapp from '@/komponenter/lenkeknapp/LenkeKnapp'; import { pathTilOpprettAvtale, pathTilOpprettAvtaleArbeidsgiver } from '@/paths'; -import { hentAvtalerForInnloggetBruker, hentUlesteVarsler } from '@/services/rest-service'; +import { + hentAvtalerForInnloggetBrukerMedPost, + hentAvtalerForInnloggetBrukerMedSokId, + hentUlesteVarsler, +} from '@/services/rest-service'; +import { Avtale, PageableAvtale } from '@/types/avtale'; +import { Status } from '@/types/nettressurs'; import { Varsel } from '@/types/varsel'; import BEMHelper from '@/utils/bem'; +import { fjernTommeFelterFraObjekt } from '@/utils/stringUtils'; import { Pagination } from '@navikt/ds-react'; -import React, { FunctionComponent, useContext, useEffect, useState } from 'react'; -import { useFilter } from '@/AvtaleOversikt/Filtrering/useFilter'; -import Banner from '@/komponenter/Banner/Banner'; -import ArbeidsgiverFiltrering from '@/AvtaleOversikt/Filtrering/ArbeidsgiverFiltrering'; -import LenkeKnapp from '@/komponenter/lenkeknapp/LenkeKnapp'; +import _ from 'lodash'; +import { FunctionComponent, useContext, useEffect, useState } from 'react'; +import { useSearchParams } from 'react-router-dom'; import './AvtaleOversikt.less'; -import { Status } from '@/types/nettressurs'; -import { AvtalelisteRessurs, PageableAvtale } from '@/types/avtale'; -import AvtaleOversiktArbeidsgiverInformasjon from '@/AvtaleOversikt/AvtaleOversiktArbeidsgiverInformasjon'; +import { FiltreringContext } from './Filtrering/FiltreringProvider'; const cls = BEMHelper('avtaleoversikt'); const clsPagination = BEMHelper('avtaleoversikt-pagination'); @@ -30,17 +38,74 @@ const AvtaleOversikt: FunctionComponent = () => { const [varsler, setVarsler] = useState([]); const { filtre, endreFilter } = useFilter(); - const [currentPage, setCurrentPage] = useState(); - const [nettressurs, setNettressurs] = useState({ status: Status.IkkeLastet }); + const [searchParams, setSearchParams] = useSearchParams(); + const [, , nettressursCtx, setNettressursCtx] = useContext(FiltreringContext); + useEffect(() => { - setNettressurs({ status: Status.LasterInn }); - const page = parseInt(filtre.page ? filtre.page : '1', 10) - hentAvtalerForInnloggetBruker(filtre, 10, page - 1).then((pagableAvtale: PageableAvtale) => { - setCurrentPage(pagableAvtale); - setNettressurs({ status: Status.Lastet, data: pagableAvtale.avtaler }); - }); - }, [filtre]); + if (nettressursCtx.status !== Status.Lastet) return; + + const filtreUtenPage = _.omit(filtre, 'page', 'sorteringskolonne'); + const erFiltreLikeNettressursFiltre = _.isEqual(fjernTommeFelterFraObjekt(nettressursCtx.data.sokeParametere), fjernTommeFelterFraObjekt(filtreUtenPage)); + + const filterPage = parseInt(filtre.page ? filtre.page : '1'); + const sammePageIDataOgFilter = nettressursCtx.data.currentPage === (filterPage - 1); + const sammeSorteringIUrlOgFilter = searchParams.get('sorteringskolonne') === filtre.sorteringskolonne; + const sammeSokId = searchParams.get('sokId') === nettressursCtx.data.sokId; + const sammePageIUrlOgFilter = searchParams.get('page') === '' + (filterPage); + const sammeSorteringIDataOgFilter = nettressursCtx.data.sorteringskolonne === filtre.sorteringskolonne; + + // console.log('\nsorteringIData:', nettressursCtx.data.sorteringskolonne, '\nsorteringFilter:', filtre.sorteringskolonne, '\nsorteringUrl:', searchParams.get('sorteringskolonne'), '\nsammeSorteringIUrlOgFilter:', sammeSorteringIUrlOgFilter, + // "\nsammeSokId", sammeSokId); + // console.log('innloggetBruker.rolle:', innloggetBruker.rolle); + + // Hvis alt er likt i url, filter og data fra backend - ikke gjør noe. + if (sammePageIDataOgFilter && erFiltreLikeNettressursFiltre && sammeSorteringIDataOgFilter && sammeSokId && sammePageIUrlOgFilter && sammeSorteringIUrlOgFilter) return; + + setNettressursCtx({ status: Status.LasterInn }); + if (!erFiltreLikeNettressursFiltre) { + // Filteret er endret - Nytt POST-søk + hentAvtalerForInnloggetBrukerMedPost(filtre, 3, filterPage - 1).then((pagableAvtale: PageableAvtale) => { + if (innloggetBruker.rolle === 'ARBEIDSGIVER') { + // Håndtering valg i bedriftsmyen som arbeidsgiver + setSearchParams(fjernTommeFelterFraObjekt({ sokId: pagableAvtale.sokId, page: '' + (pagableAvtale.currentPage + 1), sorteringskolonne: filtre.sorteringskolonne, bedrift: pagableAvtale.sokeParametere.bedriftNr })); + } else { + setSearchParams(fjernTommeFelterFraObjekt({ sokId: pagableAvtale.sokId, page: '' + (pagableAvtale.currentPage + 1), sorteringskolonne: filtre.sorteringskolonne })); + } + setNettressursCtx({ status: Status.Lastet, data: pagableAvtale }); + }); + } else if (!sammePageIDataOgFilter || !sammeSorteringIDataOgFilter) { + // page/sortering er endret - Nytt GET-søk + hentAvtalerForInnloggetBrukerMedSokId(searchParams.get('sokId')!, 3, filterPage - 1, filtre.sorteringskolonne || undefined).then( + (pagableAvtale: PageableAvtale) => { + if (innloggetBruker.rolle === 'ARBEIDSGIVER') { + setSearchParams(fjernTommeFelterFraObjekt({ sokId: pagableAvtale.sokId, page: '' + (pagableAvtale.currentPage + 1), sorteringskolonne: pagableAvtale.sorteringskolonne, bedrift: pagableAvtale.sokeParametere.bedriftNr })); + } else { + setSearchParams(fjernTommeFelterFraObjekt({ sokId: pagableAvtale.sokId, page: '' + (pagableAvtale.currentPage + 1), sorteringskolonne: pagableAvtale.sorteringskolonne })); + } + setNettressursCtx({ status: Status.Lastet, data: pagableAvtale }); + } + ); + } else if (!sammeSokId || !sammePageIUrlOgFilter || !sammeSorteringIUrlOgFilter) { + // sokId/page/sortering endret i en navigering - Nytt GET-søk + // vi må da gjøre GET med sokId/page/sortering fra url, ikke fra filteret + // Vi setter heller ingenting i searchParams her, da det er her endringen skjer via en frem/tilbake navigering, vi må derimot sette filter, da endringen ikke kommer herfra, men fra url'en. + const sokIdFraUrl = searchParams.get('sokId')!; + const pageFraUrl = parseInt(searchParams.get('page') || '1'); + const sorteringFraUrl = searchParams.get('sorteringskolonne') as keyof Avtale || ''; + hentAvtalerForInnloggetBrukerMedSokId(sokIdFraUrl, 3, pageFraUrl - 1, sorteringFraUrl || undefined).then( + (pagableAvtale: PageableAvtale) => { + // const eksisterendeSearchParams = lagObjektAvSearchParams(searchParams); + // if (eksisterendeSearchParams.bedrift) setSearchParams({...eksisterendeSearchParams, bedrift: pagableAvtale.sokeParametere.bedriftNr}); + + setNettressursCtx({ status: Status.Lastet, data: pagableAvtale }); + endreFilter({ page: '' + (pagableAvtale.currentPage + 1), sorteringskolonne: pagableAvtale.sorteringskolonne, ...pagableAvtale.sokeParametere}); + } + ); + } + + }, [filtre, nettressursCtx, setNettressursCtx, searchParams, setSearchParams, endreFilter, innloggetBruker.rolle]); + useEffect(() => { hentUlesteVarsler() @@ -52,12 +117,12 @@ const AvtaleOversikt: FunctionComponent = () => { const harTilgangerSomArbeidsgiver = innloggetBruker.rolle === 'ARBEIDSGIVER' && - filtre.bedrift && - innloggetBruker.tilganger[filtre.bedrift]?.length > 0; + filtre.bedriftNr && + innloggetBruker.tilganger[filtre.bedriftNr]?.length > 0; const antallAvtalerSuffiks = - currentPage && (currentPage?.totalItems > 1 || currentPage?.totalItems === 0) ? ' avtaler' : ' avtale'; - const antallAvtalerTekst = currentPage?.totalItems ? `(${currentPage?.totalItems} ${antallAvtalerSuffiks})` : '' + nettressursCtx.status === Status.Lastet && (nettressursCtx.data.totalItems > 1 || nettressursCtx.data.totalItems === 0) ? ' avtaler' : ' avtale'; + const antallAvtalerTekst = nettressursCtx.status === Status.Lastet && nettressursCtx.data.totalItems ? `(${nettressursCtx.data.totalItems} ${antallAvtalerSuffiks})` : ''; const oversiktTekst = `Tiltaksoversikt ${antallAvtalerTekst}`; const pageNumber = parseInt(filtre.page || '1'); @@ -66,8 +131,8 @@ const AvtaleOversikt: FunctionComponent = () => { <> { - //parseWindowLocationSearch(); + byttetOrg={(org) => { + endreFilter({bedriftNr: org}); }} tekst={oversiktTekst} /> @@ -93,7 +158,7 @@ const AvtaleOversikt: FunctionComponent = () => { )} {innloggetBruker.rolle === 'ARBEIDSGIVER' && innloggetBruker.altinnOrganisasjoner.length > 0 && - innloggetBruker.tilganger[filtre.bedrift!] && ( + innloggetBruker.tilganger[filtre.bedriftNr!] && ( )}
- +
- {nettressurs.status === Status.LasterInn && } - {pageNumber && nettressurs.status === Status.Lastet && currentPage!.totalPages > 0 && ( + {nettressursCtx.status === Status.LasterInn && } + {pageNumber && nettressursCtx.status === Status.Lastet && nettressursCtx.data.totalPages > 0 && ( { endreFilter({ page: '' + x }); + }} - count={currentPage!.totalPages} + count={nettressursCtx.data.totalPages} boundaryCount={1} siblingCount={1} /> diff --git a/src/AvtaleOversikt/Avtaler.tsx b/src/AvtaleOversikt/Avtaler.tsx index 50b5eb5fa..28dc499d5 100644 --- a/src/AvtaleOversikt/Avtaler.tsx +++ b/src/AvtaleOversikt/Avtaler.tsx @@ -4,15 +4,15 @@ import AvtaleTabell from '@/AvtaleOversikt/AvtaleTabell'; import IngenAvtaler from '@/AvtaleOversikt/IngenAvtaler/IngenAvtaler'; import useAvtaleOversiktLayout from '@/AvtaleOversikt/useAvtaleOversiktLayout'; import { FeilVarselContext } from '@/FeilVarselProvider'; -import { AvtalelisteRessurs } from '@/types/avtale'; +import { PageableAvtalelisteRessurs } from '@/types/avtale'; import { InnloggetBruker } from '@/types/innlogget-bruker'; import { Status } from '@/types/nettressurs'; import { Varsel } from '@/types/varsel'; import { handterFeil } from '@/utils/apiFeilUtils'; -import React, { FunctionComponent, useContext } from 'react'; +import { FunctionComponent, useContext } from 'react'; type Props = { - avtalelisteRessurs: AvtalelisteRessurs; + avtalelisteRessurs: PageableAvtalelisteRessurs; innloggetBruker: InnloggetBruker; varsler: Varsel[]; }; @@ -23,18 +23,18 @@ export const Avtaler: FunctionComponent = (props) => { if (props.avtalelisteRessurs.status === Status.LasterInn) { return ; - } else if (props.avtalelisteRessurs.status === Status.Lastet && props.avtalelisteRessurs.data.length === 0) { + } else if (props.avtalelisteRessurs.status === Status.Lastet && props.avtalelisteRessurs.data.avtaler.length === 0) { return ; } else if (props.avtalelisteRessurs.status === Status.Lastet) { return layout.erNokPlassTilTabell ? ( ) : ( diff --git a/src/AvtaleOversikt/Filtrering/DeltakerOgBedriftFilter.tsx b/src/AvtaleOversikt/Filtrering/DeltakerOgBedriftFilter.tsx index c3b51c0ee..21e9920d9 100644 --- a/src/AvtaleOversikt/Filtrering/DeltakerOgBedriftFilter.tsx +++ b/src/AvtaleOversikt/Filtrering/DeltakerOgBedriftFilter.tsx @@ -1,11 +1,12 @@ import { Filter } from '@/AvtaleOversikt/Filtrering/Filter'; import { SøkeInput } from '@/AvtaleOversikt/Filtrering/SøkeInput'; +import { useFilter } from '@/AvtaleOversikt/Filtrering/useFilter'; import { InnloggetBrukerContext } from '@/InnloggingBoundary/InnloggingBoundary'; import { validerFnr } from '@/utils/fnrUtils'; import { validerOrgnr } from '@/utils/orgnrUtils'; import { Radio, RadioGroup, Select } from '@navikt/ds-react'; -import React, { FormEvent, Fragment, FunctionComponent, useContext, useState } from 'react'; -import { useFilter } from '@/AvtaleOversikt/Filtrering/useFilter'; +import { isNil } from 'lodash'; +import { FormEvent, Fragment, FunctionComponent, useCallback, useContext, useEffect, useState } from 'react'; type Validering = (verdi: string) => string | undefined; @@ -21,29 +22,38 @@ export const DeltakerOgBedriftFilter: FunctionComponent = () => { const innloggetBruker = useContext(InnloggetBrukerContext); const { endreFilter, filtre } = useFilter(); - const aktivSøketypeFraFiltre = (): Søketype => { - if (filtre.veilederNavIdent !== undefined && filtre.veilederNavIdent !== innloggetBruker.identifikator) { + const aktivSøketypeFraFiltre = useCallback((): Søketype => { + + if (!isNil(filtre.veilederNavIdent) && filtre.veilederNavIdent !== innloggetBruker.identifikator) { return 'veileder'; } - if (filtre.erUfordelt !== undefined) { + if (!isNil(filtre.erUfordelt)) { return 'ufordelte'; } - if (filtre.deltakerFnr !== undefined) { + if (!isNil(filtre.deltakerFnr)) { return 'deltaker'; } - if (filtre.navEnhet !== undefined) { + if (!isNil(filtre.navEnhet)) { return 'avtaleVedEnhet'; } - if (filtre.bedriftNr !== undefined) { + if (!isNil(filtre.bedriftNr)) { return 'bedrift'; } - if (filtre.avtaleNr !== undefined) { + if (!isNil(filtre.avtaleNr)) { return 'avtaleNr'; } return innloggetBruker.rolle === 'BESLUTTER' ? 'alle' : 'egne'; - }; + }, [filtre, innloggetBruker]); + + const [aktivSøketype, setAktivSøkeType] = useState(aktivSøketypeFraFiltre()); + useEffect(() => { + setAktivSøkeType(aktivSøketypeFraFiltre()); + }, [filtre, aktivSøketypeFraFiltre]) + + + const tomt = { avtaleNr: undefined, deltakerFnr: '', @@ -97,7 +107,7 @@ export const DeltakerOgBedriftFilter: FunctionComponent = () => { maxLength: 6, validering: () => void 0, søkeinput: filtre.avtaleNr, - utførSøk: (søkeord: number) => endreFilter({ ...tomt, avtaleNr: søkeord }), + utførSøk: (søkeord: string) => endreFilter({ ...tomt, avtaleNr: parseInt(søkeord) }), }, avtaleVedEnhet: { placeholder: '', diff --git a/src/AvtaleOversikt/Filtrering/FiltreringProvider.tsx b/src/AvtaleOversikt/Filtrering/FiltreringProvider.tsx index 8dbe23ad0..5b2ebef05 100644 --- a/src/AvtaleOversikt/Filtrering/FiltreringProvider.tsx +++ b/src/AvtaleOversikt/Filtrering/FiltreringProvider.tsx @@ -1,16 +1,70 @@ -import React, { createContext, FunctionComponent, useState,PropsWithChildren } from 'react'; import { Filtrering } from '@/AvtaleOversikt/Filtrering/filtrering'; +import { InnloggetBrukerContext } from '@/InnloggingBoundary/InnloggingBoundary'; +import { hentAvtalerForInnloggetBrukerMedPost, hentAvtalerForInnloggetBrukerMedSokId } from '@/services/rest-service'; +import { Avtale, PageableAvtale, PageableAvtalelisteRessurs } from '@/types/avtale'; +import { Status } from '@/types/nettressurs'; +import { fjernTommeFelterFraObjekt } from '@/utils/stringUtils'; +import { Dispatch, FunctionComponent, PropsWithChildren, SetStateAction, createContext, useContext, useEffect, useState } from 'react'; +import { useSearchParams } from 'react-router-dom'; -export const FiltreringContext = createContext<[Filtrering, React.Dispatch>]>([ - {}, - () => null, -]); +export const FiltreringContext = createContext< + [Filtrering, Dispatch>, PageableAvtalelisteRessurs, Dispatch>] +>([{}, () => null, { status: Status.IkkeLastet }, () => null]); export const FiltreringProvider: FunctionComponent = (props) => { + const innloggetBruker = useContext(InnloggetBrukerContext); + const [searchParams, setSearchParams] = useSearchParams(); + const [nettressursCtx, setNettressursCtx] = useState({ status: Status.IkkeLastet }); const params: any = {}; - for (const [k, v] of new URLSearchParams(window.location.search)) { - params[k] = v; - } const [filtre, setFiltre] = useState(params); - return {props.children}; + + useEffect(() => { + // KJØR EN GANG PÅ OPPSTART + if (nettressursCtx.status !== Status.IkkeLastet) return; + if (innloggetBruker.rolle === 'BESLUTTER') return; + if (innloggetBruker.rolle === 'ARBEIDSGIVER' && !filtre.bedriftNr) return; + + const tekniskPage = searchParams.get('page') ? (parseInt(searchParams.get('page')!) - 1) : 0; + let resultat; + setNettressursCtx({ status: Status.LasterInn }); + const sorteringskolonne = searchParams.get('sorteringskolonne') as keyof Avtale || 'sistEndret'; + let erGet = false; + if (searchParams.get('sokId')) { + const sokId = searchParams.get('sokId')!; + resultat = hentAvtalerForInnloggetBrukerMedSokId(sokId, 3, tekniskPage, sorteringskolonne); + erGet = true; + } else { + resultat = hentAvtalerForInnloggetBrukerMedPost({ sorteringskolonne: sorteringskolonne, ...filtre }, 3, 0); + erGet = false; + } + resultat.then((pagableAvtale: PageableAvtale) => { + if (pagableAvtale.sokId === "") { + // ugyldig sokId - Utfører blankt søk. + hentAvtalerForInnloggetBrukerMedPost(filtre, 3, 0).then((pagableAvtale: PageableAvtale) => { + setNettressursCtx({ status: Status.Lastet, data: pagableAvtale }); + setSearchParams({ sokId: pagableAvtale.sokId, page: '' + (pagableAvtale.currentPage + 1), sorteringskolonne: pagableAvtale.sorteringskolonne }); + setFiltre({ ...pagableAvtale.sokeParametere, page: (pagableAvtale.currentPage + 1) + '', sorteringskolonne: pagableAvtale.sorteringskolonne }); + }); + } else { + if (innloggetBruker.rolle === 'ARBEIDSGIVER') { + if (!erGet) { + const sokeParams = fjernTommeFelterFraObjekt({ sokId: pagableAvtale.sokId, page: '' + (pagableAvtale.currentPage + 1), sorteringskolonne: pagableAvtale.sorteringskolonne, bedrift: pagableAvtale.sokeParametere.bedriftNr }); + setSearchParams(sokeParams, { replace: true }); + } + } else { + const sokeParams = fjernTommeFelterFraObjekt({ sokId: pagableAvtale.sokId, page: '' + (pagableAvtale.currentPage + 1), sorteringskolonne: pagableAvtale.sorteringskolonne }); + setSearchParams(sokeParams, { replace: true }); + } + setNettressursCtx({ status: Status.Lastet, data: pagableAvtale }); + setFiltre({ ...pagableAvtale.sokeParametere, page: (pagableAvtale.currentPage + 1) + '', sorteringskolonne: pagableAvtale.sorteringskolonne }); + } + }); + + }, [filtre, nettressursCtx.status, searchParams, setSearchParams, innloggetBruker.rolle]); + + return ( + + {props.children} + + ); }; diff --git a/src/AvtaleOversikt/Filtrering/useFilter.ts b/src/AvtaleOversikt/Filtrering/useFilter.ts index 7b1a45543..85b512761 100644 --- a/src/AvtaleOversikt/Filtrering/useFilter.ts +++ b/src/AvtaleOversikt/Filtrering/useFilter.ts @@ -1,56 +1,47 @@ -import { useContext, useEffect } from 'react'; -import { useSearchParams } from 'react-router-dom'; import { FiltreringContext } from '@/AvtaleOversikt/Filtrering/FiltreringProvider'; import { Filtrering } from '@/AvtaleOversikt/Filtrering/filtrering'; import _ from 'lodash'; +import { useContext } from 'react'; -const toObject = (params: URLSearchParams) => Object.fromEntries(params.entries()); - -const updateOrDeleteKey = (params: URLSearchParams, filter: Filtrering, key: keyof Filtrering) => { - if (filter.hasOwnProperty(key)) { - if (!filter[key]) { - params.delete(key); +const updateOrDeleteKeyFromObject = (filterobject: any, filterEndring: Filtrering, key: keyof Filtrering) => { + if (filterEndring.hasOwnProperty(key)) { + if (!filterEndring[key]) { + delete filterobject[key]; } else { - params.set(key, filter[key] as string); + filterobject[key] = filterEndring[key]; } } -}; +} export const useFilter = () => { const [filtre, setFiltre] = useContext(FiltreringContext); - const [searchParams, setSearchParams] = useSearchParams(); - - useEffect(() => { - const newParams = toObject(searchParams); - if (!_.isEqual(newParams, filtre)) { - setFiltre(newParams); - } - }, [searchParams, filtre, setFiltre]); const endreFilter = (endring: Filtrering) => { - const newSearchParams = new URLSearchParams(searchParams); - - updateOrDeleteKey(newSearchParams, endring, "avtaleNr"); - updateOrDeleteKey(newSearchParams, endring, "veilederNavIdent"); - updateOrDeleteKey(newSearchParams, endring, "deltakerFnr"); - updateOrDeleteKey(newSearchParams, endring, "bedriftNr"); - updateOrDeleteKey(newSearchParams, endring, "navEnhet"); - updateOrDeleteKey(newSearchParams, endring, "erUfordelt"); - updateOrDeleteKey(newSearchParams, endring, "status"); - updateOrDeleteKey(newSearchParams, endring, "sorteringskolonne"); - updateOrDeleteKey(newSearchParams, endring, "tilskuddPeriodeStatus"); - updateOrDeleteKey(newSearchParams, endring, "tiltakstype"); + const obj = {...filtre}; + + updateOrDeleteKeyFromObject(obj, endring, "avtaleNr"); + updateOrDeleteKeyFromObject(obj, endring, "veilederNavIdent"); + updateOrDeleteKeyFromObject(obj, endring, "deltakerFnr"); + updateOrDeleteKeyFromObject(obj, endring, "bedriftNr"); + updateOrDeleteKeyFromObject(obj, endring, "navEnhet"); + updateOrDeleteKeyFromObject(obj, endring, "erUfordelt"); + updateOrDeleteKeyFromObject(obj, endring, "status"); + updateOrDeleteKeyFromObject(obj, endring, "sorteringskolonne"); + updateOrDeleteKeyFromObject(obj, endring, "tilskuddPeriodeStatus"); + updateOrDeleteKeyFromObject(obj, endring, "tiltakstype"); // Alle endringer som ikke er en endring i paginering/sortering, bør nullstille pagineringen const changedKeys = Object.keys(endring); if (changedKeys.filter(k => !['page', 'sorteringskolonne'].includes(k)).length > 0) { - newSearchParams.delete("page"); + delete obj["page"]; } if (endring.hasOwnProperty('page')) { - newSearchParams.set("page", '' + endring.page); + obj["page"] = endring.page; + } + + if (!_.isEqual(obj, filtre)) { + setFiltre(obj); } - - setSearchParams(newSearchParams); }; return { filtre, endreFilter }; diff --git a/src/AvtaleOversikt/IngenAvtaler/IngenAvtaler.tsx b/src/AvtaleOversikt/IngenAvtaler/IngenAvtaler.tsx index dcd3c9670..96fecf610 100644 --- a/src/AvtaleOversikt/IngenAvtaler/IngenAvtaler.tsx +++ b/src/AvtaleOversikt/IngenAvtaler/IngenAvtaler.tsx @@ -1,16 +1,16 @@ +import { useFilter } from '@/AvtaleOversikt/Filtrering/useFilter'; +import { InnloggetBrukerContext } from '@/InnloggingBoundary/InnloggingBoundary'; +import { INNLOGGET_PART } from '@/RedirectEtterLogin'; import { ReactComponent as InfoIkon } from '@/assets/ikoner/info.svg'; import Innholdsboks from '@/komponenter/Innholdsboks/Innholdsboks'; import VerticalSpacer from '@/komponenter/layout/VerticalSpacer'; -import { INNLOGGET_PART } from '@/RedirectEtterLogin'; import BEMHelper from '@/utils/bem'; -import classNames from 'classnames'; import { BodyShort, Heading, Ingress } from '@navikt/ds-react'; -import React, { FunctionComponent, useContext } from 'react'; +import classNames from 'classnames'; +import { FunctionComponent, useContext } from 'react'; import { useCookies } from 'react-cookie'; import './IngenAvtaler.less'; import IngenAvtalerArbeidsgiver from './arbeidsgiver/IngenAvtalerArbeidsgiver'; -import { InnloggetBrukerContext } from '@/InnloggingBoundary/InnloggingBoundary'; -import { useFilter } from '@/AvtaleOversikt/Filtrering/useFilter'; const cls = BEMHelper('ingenAvtaler'); @@ -75,7 +75,7 @@ const IngenAvtaler: FunctionComponent = () => { case InnloggetPart.deltaker: return ; case InnloggetPart.arbeidsgiver: - return ; + return ; case InnloggetPart.mentor: return ; default: diff --git a/src/AvtaleSide/AvtaleSide.tsx b/src/AvtaleSide/AvtaleSide.tsx index ffab3efc0..24f41d757 100644 --- a/src/AvtaleSide/AvtaleSide.tsx +++ b/src/AvtaleSide/AvtaleSide.tsx @@ -4,18 +4,17 @@ import { InnloggetBrukerContext } from '@/InnloggingBoundary/InnloggingBoundary' import Banner from '@/komponenter/Banner/Banner'; import BannerNAVAnsatt from '@/komponenter/Banner/BannerNAVAnsatt'; import Dokumenttittel from '@/komponenter/Dokumenttittel'; +import Dialog from '@/komponenter/brukerdialog/Dialog'; import { avtaleTittel } from '@/messages'; import { pathTilOversikt } from '@/paths'; import BEMHelper from '@/utils/bem'; import hentAvtaleSteg from '@/utils/hentAvtaleSteg'; import React, { FunctionComponent, useContext, useEffect, useState } from 'react'; -import { useNavigate } from 'react-router-dom'; -import { useParams } from 'react-router-dom'; +import { useNavigate, useParams } from 'react-router-dom'; +import './AvtaleSide.less'; import DesktopAvtaleSide from './DesktopAvtaleSide/DesktopAvtaleSide'; import MobilAvtaleSide from './MobilAvtaleSide/MobilAvtaleSide'; import VarselModal from './VarselModal/VarselModal'; -import './AvtaleSide.less'; -import Dialog from '@/komponenter/brukerdialog/Dialog'; const cls = BEMHelper('avtaleside'); @@ -76,10 +75,13 @@ const AvtaleSide: FunctionComponent = () => { { - if (avtale.bedriftNr !== org.OrganizationNumber) { + const searchParams = new URLSearchParams(window.location.search); + searchParams.set('bedrift', org); + searchParams.delete('sokId'); + if (avtale.bedriftNr !== org) { navigate({ pathname: pathTilOversikt, - search: window.location.search, + search: searchParams.toString(), }); } }} diff --git a/src/komponenter/Banner/Banner.spec.tsx b/src/komponenter/Banner/Banner.spec.tsx deleted file mode 100644 index 9cd6bfb86..000000000 --- a/src/komponenter/Banner/Banner.spec.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import React from 'react'; -import { shallow } from 'enzyme'; -import Banner from './Banner'; - -test('Test that renders correctly', () => { - const wrapper = shallow(); - expect(wrapper).toHaveLength(1); -}); diff --git a/src/komponenter/Banner/Banner.tsx b/src/komponenter/Banner/Banner.tsx index 153839a18..a2dc25fdc 100644 --- a/src/komponenter/Banner/Banner.tsx +++ b/src/komponenter/Banner/Banner.tsx @@ -1,29 +1,56 @@ import { InnloggetBrukerContext } from '@/InnloggingBoundary/InnloggingBoundary'; import { NotifikasjonWidget } from '@navikt/arbeidsgiver-notifikasjon-widget'; -import Bedriftsmeny from '@navikt/bedriftsmeny'; +import Bedriftsmeny, { Organisasjon } from '@navikt/bedriftsmeny'; import '@navikt/bedriftsmeny/lib/bedriftsmeny.css'; -import { Organisasjon } from '@navikt/bedriftsmeny/lib/organisasjon'; import { Detail, Heading } from '@navikt/ds-react'; -import React, { useContext } from 'react'; +import React, { useCallback, useContext } from 'react'; +import { useSearchParams } from 'react-router-dom'; import VerticalSpacer from '../layout/VerticalSpacer'; import './Banner.less'; interface Props { tekst: string; - byttetOrg?: (org: Organisasjon) => void; + byttetOrg?: (org: string) => void; undertittel?: string; } + + const Banner: React.FunctionComponent = (props) => { const innloggetBruker = useContext(InnloggetBrukerContext); + const [searchParams] = useSearchParams(); + const bedriftParam = searchParams.get('bedrift'); + + const useOrgnrHook2: () => [string | null, (orgnr: string) => void] = + useCallback(() => { + const currentOrgnr = bedriftParam || null; + + return [ + currentOrgnr, + (orgnr: string) => { + if (currentOrgnr !== orgnr) { + if (orgnr === null) { + //push(""); + } else { + //push(`?bedrift=${orgnr}`); + if (props.byttetOrg) { + props.byttetOrg(orgnr); + } + + } + } + }, + ]; + }, [bedriftParam, props]); switch (innloggetBruker.rolle) { case 'ARBEIDSGIVER': return ( { if (props.byttetOrg) { - props.byttetOrg(org); + props.byttetOrg(org.OrganizationNumber); } }} organisasjoner={innloggetBruker.altinnOrganisasjoner} diff --git a/src/services/rest-service.ts b/src/services/rest-service.ts index 4f249d3e0..f3391ba68 100644 --- a/src/services/rest-service.ts +++ b/src/services/rest-service.ts @@ -110,6 +110,28 @@ export const hentAvtalerForInnloggetBruker = async ( return response.data; }; +export const hentAvtalerForInnloggetBrukerMedSokId = async ( + sokId: string, + size: number = 2, + page: number = 0, + sorteringskolonne: keyof Avtale = 'sistEndret', +): Promise => { + const queryParam = new URLSearchParams(removeEmpty({ size, page, sokId, sorteringskolonne })); + const response = await api.get(`/avtaler/sok?${queryParam}`); + return response.data; +}; + +export const hentAvtalerForInnloggetBrukerMedPost = async ( + søkekriterier: Filtrering, + size: number = 2, + page: number = 0, +): Promise => { + const postBody = removeEmpty(søkekriterier); + const queryParam = new URLSearchParams(removeEmpty({ page, size, sorteringskolonne: søkekriterier.sorteringskolonne })); + const response = await api.post(`/avtaler/sok?${queryParam}`, postBody); + return response.data; +}; + export const hentAvtalerForInnloggetBeslutter = async ( søkekriterier: Filtrering, size: number = 2, diff --git a/src/types/avtale.ts b/src/types/avtale.ts index 6f548a47e..d0b4035f4 100644 --- a/src/types/avtale.ts +++ b/src/types/avtale.ts @@ -1,3 +1,4 @@ +import { Filtrering } from '@/AvtaleOversikt/Filtrering/filtrering'; import { Formidlingsgruppe } from '@/AvtaleSide/steg/BeregningTilskudd/Formidlingsgruppe'; import { Kvalifiseringsgruppe } from '@/AvtaleSide/steg/BeregningTilskudd/Kvalifiseringsgruppe'; import { Nettressurs } from '@/types/nettressurs'; @@ -16,6 +17,9 @@ export interface PageableAvtale { size: number; totalItems: number; totalPages: number; + sokId: string; + sokeParametere: Filtrering; + sorteringskolonne: keyof Avtale; } export interface PageableAvtaleMinimalForBeslutter { @@ -26,6 +30,17 @@ export interface PageableAvtaleMinimalForBeslutter { totalPages: number; } +export interface PageableAvtaleMinimal { + currentPage: number; + avtaler: AvtaleMinimalListeVisning[]; + size: number; + totalItems: number; + totalPages: number; + sokId: string; + sokeParametere: Filtrering; + sorteringskolonne: keyof Avtale; +} + export type AvtaleMinimalListeVisning = { id: string; deltakerFornavn: string; @@ -364,6 +379,7 @@ export type InnholdType = export type AvtaleVersjon = Avtaleinnhold & { id: string; versjon: number; innholdType?: InnholdType } & Godkjenninger; export type AvtalelisteRessurs = Nettressurs; +export type PageableAvtalelisteRessurs = Nettressurs; export type AvtalelisteMinimalForBeslutterRessurs = Nettressurs; export type EndreKontaktInfo = { diff --git a/src/types/innlogget-bruker.ts b/src/types/innlogget-bruker.ts index 175beaf5e..9e2490914 100644 --- a/src/types/innlogget-bruker.ts +++ b/src/types/innlogget-bruker.ts @@ -1,5 +1,5 @@ import { TiltaksType } from '@/types/avtale'; -import { Organisasjon as AltinnOrganisasjon } from '@navikt/bedriftsmeny/lib/organisasjon'; +import { Organisasjon as AltinnOrganisasjon } from '@navikt/bedriftsmeny'; export interface Innloggingskilde { tittel: string; diff --git a/src/utils/stringUtils.ts b/src/utils/stringUtils.ts index 75be22c07..c58bc600e 100644 --- a/src/utils/stringUtils.ts +++ b/src/utils/stringUtils.ts @@ -1,3 +1,4 @@ +import _ from 'lodash'; export const storForbokstav = (tekst: string) => { return tekst ? tekst.toLowerCase().replace(/\b\w/, v => v.toUpperCase()) : tekst; }; @@ -8,3 +9,13 @@ export const litenForbokstav = (tekst: string) => { // https://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex export const escapeRegExp = (streng: string) => streng.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + +export const fjernTommeFelterFraObjekt = (objekt: any) => _.pickBy(objekt); + +export const lagObjektAvSearchParams = (searchParams: URLSearchParams) => { + const objekt: any = {}; + searchParams.forEach((value, key) => { + objekt[key] = value; + }); + return objekt; +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 10c11983a..ed660f056 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2091,12 +2091,12 @@ casual "^1.6.2" graphql "^16.6.0" -"@navikt/bedriftsmeny@^6.4.3": - version "6.4.3" - resolved "https://registry.yarnpkg.com/@navikt/bedriftsmeny/-/bedriftsmeny-6.4.3.tgz#cf0cba649f5e1a0a01992c5a13f233dbbffb1983" - integrity sha512-sMis0btzUFtsqSO3YIrcan/4sV4HbhtGYF1/vnBjQSJEP+Icoay3n1Ib1uGeijty1FYGJzsU/3sY7HM+wRUU5g== +"@navikt/bedriftsmeny@^6.11.0": + version "6.11.0" + resolved "https://registry.yarnpkg.com/@navikt/bedriftsmeny/-/bedriftsmeny-6.11.0.tgz#9594fc5965192e2e8da440fd53805d98b8243c87" + integrity sha512-XCevbGofG8gGttXuRno/lCeXoNXZhIEgkKiZ0MakNYw7uQo438I+NBDmCrZ1bbtKXK/+bU2hxDCNHwupkgdpWA== dependencies: - "@types/amplitude-js" "^8.9.4" + focus-trap-react "^10.2.2" fuzzysort "^1.1.4" history "^4.10.1" @@ -2739,7 +2739,7 @@ dependencies: "@types/node" "*" -"@types/amplitude-js@^8.0.1", "@types/amplitude-js@^8.9.4": +"@types/amplitude-js@^8.0.1": version "8.16.2" resolved "https://registry.yarnpkg.com/@types/amplitude-js/-/amplitude-js-8.16.2.tgz#2cfb850a01a4171e632498821f92e45bef23c952" integrity sha512-a+tb/CEQOlrHRvEvAuYNOcoUy1POERANnAhfKgiTmsy0eACj3eukGP0ucA9t115QOPzVUhbnUfZqtyHp99IZyA== @@ -6234,6 +6234,21 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== +focus-trap-react@^10.2.2: + version "10.2.2" + resolved "https://registry.yarnpkg.com/focus-trap-react/-/focus-trap-react-10.2.2.tgz#3b57cdee506e16c3cb75d2cb939b2d509b450489" + integrity sha512-ktfVCuRyT2fikb1De8u5bs3afdqFTJu6Hl1iGThwmo++k2+/n78DapitplvHGZ0hkDPlyHvAWGQsR74KF30zxw== + dependencies: + focus-trap "^7.5.3" + tabbable "^6.2.0" + +focus-trap@^7.5.3: + version "7.5.3" + resolved "https://registry.yarnpkg.com/focus-trap/-/focus-trap-7.5.3.tgz#fbb39af6ef2e19aa10707e28583fdccf91a4243d" + integrity sha512-7UsT/eSJcTPF0aZp73u7hBRTABz26knRRTJfoTGFCQD5mUImLIIOwWWCrtoQdmWa7dykBi6H+Cp5i3S/kvsMeA== + dependencies: + tabbable "^6.2.0" + follow-redirects@^1.0.0, follow-redirects@^1.14.0: version "1.15.2" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" @@ -11171,6 +11186,11 @@ tabbable@^6.0.1: resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-6.1.1.tgz#40cfead5ed11be49043f04436ef924c8890186a0" integrity sha512-4kl5w+nCB44EVRdO0g/UGoOp3vlwgycUVtkk/7DPyeLZUCuNFFKCFG6/t/DgHLrUPHjrZg6s5tNm+56Q2B0xyg== +tabbable@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-6.2.0.tgz#732fb62bc0175cfcec257330be187dcfba1f3b97" + integrity sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew== + tailwindcss@^3.0.2: version "3.3.1" resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.3.1.tgz#b6662fab6a9b704779e48d083a9fef5a81d2b81e"