From 2884a3d90eaf14fc9565be0db544baa1cb24146c Mon Sep 17 00:00:00 2001 From: JeremiahUy Date: Tue, 5 Mar 2024 13:06:51 +0100 Subject: [PATCH 001/107] FEATURE: new krav priority list data with less complicated logic --- .../common/security/WebSecurityConfig.java | 2 + .../storage/domain/TypeRegistration.java | 2 + .../KravPriorityListController.java | 73 +++++++++++++++++++ .../KravPriorityListService.java | 50 +++++++++++++ .../domain/KravPriorityList.java | 43 +++++++++++ .../domain/KravPriorityListRepo.java | 23 ++++++ .../dto/KravPriorityListRequest.java | 43 +++++++++++ .../dto/KravPriorityListResponse.java | 24 ++++++ 8 files changed, 260 insertions(+) create mode 100644 apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListController.java create mode 100644 apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListService.java create mode 100644 apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/domain/KravPriorityList.java create mode 100644 apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/domain/KravPriorityListRepo.java create mode 100644 apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/dto/KravPriorityListRequest.java create mode 100644 apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/dto/KravPriorityListResponse.java diff --git a/apps/backend/src/main/java/no/nav/data/common/security/WebSecurityConfig.java b/apps/backend/src/main/java/no/nav/data/common/security/WebSecurityConfig.java index bbb9debe7..3aaf142e5 100644 --- a/apps/backend/src/main/java/no/nav/data/common/security/WebSecurityConfig.java +++ b/apps/backend/src/main/java/no/nav/data/common/security/WebSecurityConfig.java @@ -61,6 +61,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti "/settings/**", "/codelist/**", "/krav/**", + "/kravprioritylist/**", "/kravprioritering/**", "/etterlevelse/**", "/etterlevelsedokumentasjon/**", @@ -89,6 +90,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti http.authorizeHttpRequests(auth -> auth.requestMatchers(antMatcher("/tilbakemelding/**")).hasAnyRole(AppRole.WRITE.name(), AppRole.ADMIN.name(), AppRole.KRAVEIER.name())); http.authorizeHttpRequests(auth -> auth.requestMatchers(antMatcher("/tilbakemelding/status/**")).hasAnyRole(AppRole.ADMIN.name(), AppRole.KRAVEIER.name())); http.authorizeHttpRequests(auth -> auth.requestMatchers(antMatcher("/export/**")).hasAnyRole(AppRole.WRITE.name(), AppRole.ADMIN.name(), AppRole.KRAVEIER.name())); + http.authorizeHttpRequests(auth -> auth.requestMatchers(antMatcher("/kravprioritylist/**")).hasAnyRole(AppRole.KRAVEIER.name(), AppRole.ADMIN.name())); http.authorizeHttpRequests(auth -> auth.requestMatchers(antMatcher("/kravprioritering/**")).hasAnyRole(AppRole.KRAVEIER.name(), AppRole.ADMIN.name())); http.authorizeHttpRequests(auth -> auth.requestMatchers(antMatcher("/etterlevelse/**")).hasAnyRole(AppRole.WRITE.name(), AppRole.KRAVEIER.name(), AppRole.ADMIN.name())); http.authorizeHttpRequests(auth -> auth.requestMatchers(antMatcher("/behandling/**")).hasAnyRole(AppRole.WRITE.name(), AppRole.KRAVEIER.name(), AppRole.ADMIN.name())); diff --git a/apps/backend/src/main/java/no/nav/data/common/storage/domain/TypeRegistration.java b/apps/backend/src/main/java/no/nav/data/common/storage/domain/TypeRegistration.java index 4805cf8b1..372ba685f 100644 --- a/apps/backend/src/main/java/no/nav/data/common/storage/domain/TypeRegistration.java +++ b/apps/backend/src/main/java/no/nav/data/common/storage/domain/TypeRegistration.java @@ -10,6 +10,7 @@ import no.nav.data.etterlevelse.krav.domain.KravImage; import no.nav.data.etterlevelse.krav.domain.Tilbakemelding; import no.nav.data.etterlevelse.kravprioritering.domain.KravPrioritering; +import no.nav.data.etterlevelse.kravprioritylist.domain.KravPriorityList; import no.nav.data.etterlevelse.melding.domain.Melding; import no.nav.data.etterlevelse.virkemiddel.domain.Virkemiddel; import org.springframework.util.Assert; @@ -28,6 +29,7 @@ public final class TypeRegistration { static { addDomainClass(Krav.class, true); + addDomainClass(KravPriorityList.class, true); addDomainClass(KravPrioritering.class, true); addDomainClass(Etterlevelse.class, true); addDomainClass(EtterlevelseMetadata.class, true); diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListController.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListController.java new file mode 100644 index 000000000..c28f5dd2a --- /dev/null +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListController.java @@ -0,0 +1,73 @@ +package no.nav.data.etterlevelse.kravprioritylist; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import no.nav.data.common.exceptions.ValidationException; +import no.nav.data.common.rest.PageParameters; +import no.nav.data.common.rest.RestResponsePage; +import no.nav.data.etterlevelse.codelist.CodelistService; +import no.nav.data.etterlevelse.codelist.domain.ListName; +import no.nav.data.etterlevelse.kravprioritylist.domain.KravPriorityList; +import no.nav.data.etterlevelse.kravprioritylist.dto.KravPriorityListResponse; +import org.springframework.data.domain.Page; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Slf4j +@RequiredArgsConstructor +@RestController +@RequestMapping("/kravprioritylist") +@Tag(name = "KravPriorityList", description = "Prioriterings rekkefølge for krav") +public class KravPriorityListController { + + private final KravPriorityListService service; + private final CodelistService codelistService; + + @Operation(summary = "Get all krav prioritering") + @ApiResponse(description = "ok") + @GetMapping + public ResponseEntity> getAll( + PageParameters pageParameters + ) { + log.info("Get all krav prioriteringer"); + Page page = service.getAll(pageParameters); + return ResponseEntity.ok(new RestResponsePage<>(page).convert(KravPriorityList::toResponse)); + } + + + @Operation(summary = "Get krav prioritering by tema code") + @ApiResponse(description = "ok") + @GetMapping("/tema/{temacode}") + public ResponseEntity getByTemaCode(@PathVariable String temacode) { + log.info("Get krav prioritering for tema={}", temacode); + if(temacode.length() < 3) { + throw new ValidationException("Tema code must be more than 3 characters"); + } + + codelistService.validateListNameAndCode(ListName.TEMA.name(), temacode); + + KravPriorityList kravPriorityList = service.getByTema(temacode); + return ResponseEntity.ok(kravPriorityList.toResponse()); + } + + @Operation(summary = "Get krav prioritery by tema code and krav nummer") + @ApiResponse(description = "ok") + @GetMapping("/tema/{temacode}/{kravnummer}") + public ResponseEntity getByTemaCodeAndKravNummer(@PathVariable String temacode, @PathVariable Integer kravnummer) { + log.info("Get krav prioritering for tema={}", temacode); + if(temacode.length() < 3) { + throw new ValidationException("Tema code must be more than 3 characters"); + } + + codelistService.validateListNameAndCode(ListName.TEMA.name(), temacode); + + Integer kravPriority = service.getPriorityForKravByTema(temacode, kravnummer); + return ResponseEntity.ok(kravPriority); + } +} diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListService.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListService.java new file mode 100644 index 000000000..f470bc37c --- /dev/null +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListService.java @@ -0,0 +1,50 @@ +package no.nav.data.etterlevelse.kravprioritylist; + +import no.nav.data.common.rest.PageParameters; +import no.nav.data.common.storage.domain.GenericStorage; +import no.nav.data.etterlevelse.common.domain.DomainService; +import no.nav.data.etterlevelse.kravprioritylist.domain.KravPriorityList; +import no.nav.data.etterlevelse.kravprioritylist.domain.KravPriorityListRepo; +import no.nav.data.etterlevelse.kravprioritylist.dto.KravPriorityListRequest; +import org.springframework.data.domain.Page; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +import java.util.UUID; + +@Service +public class KravPriorityListService extends DomainService { + + private final KravPriorityListRepo repo; + + public KravPriorityListService(KravPriorityListRepo repo) { + this.repo = repo; + } + + public Page getAll(PageParameters pageParameters) { + return repo.findAll(pageParameters.createPage()).map(GenericStorage::getDomainObjectData); + } + + public KravPriorityList getByTema(String tema) { + return repo.findByTema(tema).getDomainObjectData(); + } + + public Integer getPriorityForKravByTema(String tema, Integer kravNummer){ + KravPriorityList kravPriorityList = getByTema(tema); + return kravPriorityList.getPriorityList().stream().toList().indexOf(kravNummer); + } + + public KravPriorityList save(KravPriorityListRequest request) { + + var kravPriorityList = request.isUpdate() ? storage.get(request.getIdAsUUID()) : new KravPriorityList(); + kravPriorityList.convert(request); + + return storage.save(kravPriorityList); + } + + @Transactional(propagation = Propagation.REQUIRED) + public KravPriorityList delete(UUID id) { + return storage.delete(id); + } +} diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/domain/KravPriorityList.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/domain/KravPriorityList.java new file mode 100644 index 000000000..7f4c2f297 --- /dev/null +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/domain/KravPriorityList.java @@ -0,0 +1,43 @@ +package no.nav.data.etterlevelse.kravprioritylist.domain; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; +import no.nav.data.common.storage.domain.DomainObject; +import no.nav.data.etterlevelse.kravprioritylist.dto.KravPriorityListRequest; +import no.nav.data.etterlevelse.kravprioritylist.dto.KravPriorityListResponse; + +import java.util.List; + +import static no.nav.data.common.utils.StreamUtils.copyOf; + + +@Data +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class KravPriorityList extends DomainObject { + private String temaId; + private List priorityList; + + public KravPriorityList convert(KravPriorityListRequest request) { + temaId = request.getTemaId(); + priorityList = copyOf(request.getPriorityList()); + return this; + } + + public KravPriorityListResponse toResponse() { + return KravPriorityListResponse.builder() + .id(id) + .changeStamp(convertChangeStampResponse()) + .version(version) + + .temaId(temaId) + .priorityList(priorityList) + .build(); + } + +} diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/domain/KravPriorityListRepo.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/domain/KravPriorityListRepo.java new file mode 100644 index 000000000..a59462b53 --- /dev/null +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/domain/KravPriorityListRepo.java @@ -0,0 +1,23 @@ +package no.nav.data.etterlevelse.kravprioritylist.domain; + +import no.nav.data.common.storage.domain.GenericStorage; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import java.util.UUID; + +public interface KravPriorityListRepo extends JpaRepository, UUID> { + + @Override + @Query(value = "select * from generic_storage where type = 'KravPriorityList' order by data -> 'temaId'", + countQuery = "select count(1) from generic_storage where type = 'KravPriorityList'", + nativeQuery = true) + Page> findAll(Pageable page); + + @Query(value = "select * from generic_storage where data ->> 'temaId' ilike %?1% and type = 'KravPriorityList'", nativeQuery = true) + GenericStorage findByTema(String tema); + + +} diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/dto/KravPriorityListRequest.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/dto/KravPriorityListRequest.java new file mode 100644 index 000000000..51923a927 --- /dev/null +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/dto/KravPriorityListRequest.java @@ -0,0 +1,43 @@ +package no.nav.data.etterlevelse.kravprioritylist.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.FieldNameConstants; +import no.nav.data.common.validator.RequestElement; +import no.nav.data.common.validator.Validator; +import no.nav.data.etterlevelse.codelist.domain.ListName; + +import java.util.List; + +import static org.apache.commons.lang3.StringUtils.trimToNull; + +@Data +@Builder +@FieldNameConstants +@NoArgsConstructor +@AllArgsConstructor +public class KravPriorityListRequest implements RequestElement { + + private String id; + + private String temaId; + private List priorityList; + + private Boolean update; + + @Override + public void format() { + setId(trimToNull(id)); + setTemaId(trimToNull(temaId)); + } + + @Override + public void validateFieldValues(Validator validator) { + validator.checkUUID(KravPriorityListRequest.Fields.id, id); + validator.checkId(this); + validator.checkNull(Fields.temaId, temaId); + validator.checkCodelist(Fields.temaId, temaId, ListName.TEMA); + } +} diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/dto/KravPriorityListResponse.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/dto/KravPriorityListResponse.java new file mode 100644 index 000000000..275e2b00b --- /dev/null +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/dto/KravPriorityListResponse.java @@ -0,0 +1,24 @@ +package no.nav.data.etterlevelse.kravprioritylist.dto; + +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import no.nav.data.common.rest.ChangeStampResponse; + +import java.util.List; +import java.util.UUID; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@JsonPropertyOrder({"id", "temaId"}) +public class KravPriorityListResponse { + private UUID id; + private ChangeStampResponse changeStamp; + private Integer version; + private String temaId; + private List priorityList; +} From aaecc707d9e23ecf6625154a609af177f11f6999 Mon Sep 17 00:00:00 2001 From: JeremiahUy Date: Tue, 5 Mar 2024 13:35:49 +0100 Subject: [PATCH 002/107] UPDATE: code logic for returning empty or not found --- .../KravPriorityListController.java | 16 +++++++++++++--- .../KravPriorityListService.java | 10 +++------- .../domain/KravPriorityListRepo.java | 3 ++- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListController.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListController.java index c28f5dd2a..0f7252de5 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListController.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListController.java @@ -19,6 +19,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.Optional; + @Slf4j @RequiredArgsConstructor @RestController @@ -52,8 +54,9 @@ public ResponseEntity getByTemaCode(@PathVariable Stri codelistService.validateListNameAndCode(ListName.TEMA.name(), temacode); - KravPriorityList kravPriorityList = service.getByTema(temacode); - return ResponseEntity.ok(kravPriorityList.toResponse()); + Optional kravPriorityList = service.getByTema(temacode).map(KravPriorityList::toResponse); + return kravPriorityList.map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.notFound().build()); + } @Operation(summary = "Get krav prioritery by tema code and krav nummer") @@ -67,7 +70,14 @@ public ResponseEntity getByTemaCodeAndKravNummer(@PathVariable String t codelistService.validateListNameAndCode(ListName.TEMA.name(), temacode); - Integer kravPriority = service.getPriorityForKravByTema(temacode, kravnummer); + Optional kravPriorityList = service.getByTema(temacode).map(KravPriorityList::toResponse); + + if(kravPriorityList.isEmpty()) { + ResponseEntity.notFound().build(); + } + + Integer kravPriority = kravPriorityList.get().getPriorityList().indexOf(kravnummer); + return ResponseEntity.ok(kravPriority); } } diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListService.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListService.java index f470bc37c..befe31aa7 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListService.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListService.java @@ -11,6 +11,7 @@ import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; +import java.util.Optional; import java.util.UUID; @Service @@ -26,13 +27,8 @@ public Page getAll(PageParameters pageParameters) { return repo.findAll(pageParameters.createPage()).map(GenericStorage::getDomainObjectData); } - public KravPriorityList getByTema(String tema) { - return repo.findByTema(tema).getDomainObjectData(); - } - - public Integer getPriorityForKravByTema(String tema, Integer kravNummer){ - KravPriorityList kravPriorityList = getByTema(tema); - return kravPriorityList.getPriorityList().stream().toList().indexOf(kravNummer); + public Optional getByTema(String tema) { + return repo.findByTema(tema).map(GenericStorage::getDomainObjectData); } public KravPriorityList save(KravPriorityListRequest request) { diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/domain/KravPriorityListRepo.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/domain/KravPriorityListRepo.java index a59462b53..87d94c058 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/domain/KravPriorityListRepo.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/domain/KravPriorityListRepo.java @@ -6,6 +6,7 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; +import java.util.Optional; import java.util.UUID; public interface KravPriorityListRepo extends JpaRepository, UUID> { @@ -17,7 +18,7 @@ public interface KravPriorityListRepo extends JpaRepository> findAll(Pageable page); @Query(value = "select * from generic_storage where data ->> 'temaId' ilike %?1% and type = 'KravPriorityList'", nativeQuery = true) - GenericStorage findByTema(String tema); + Optional>findByTema(String tema); } From a8ec415fa948e4a760a428192125847f28bbf895 Mon Sep 17 00:00:00 2001 From: JeremiahUy Date: Tue, 5 Mar 2024 14:19:10 +0100 Subject: [PATCH 003/107] UPDATE: code logic for returning empty or not found --- .../kravprioritylist/KravPriorityListController.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListController.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListController.java index 0f7252de5..21642c68b 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListController.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListController.java @@ -76,7 +76,15 @@ public ResponseEntity getByTemaCodeAndKravNummer(@PathVariable String t ResponseEntity.notFound().build(); } - Integer kravPriority = kravPriorityList.get().getPriorityList().indexOf(kravnummer); + int kravPriority = -1; + + if(kravPriorityList.isPresent() && !kravPriorityList.get().getPriorityList().isEmpty()) { + kravPriority = kravPriorityList.get().getPriorityList().indexOf(kravnummer); + } + + if(kravPriority < 0) { + ResponseEntity.notFound().build(); + } return ResponseEntity.ok(kravPriority); } From eeebe37901c76af6ed4f9612476155e9b7e64e4e Mon Sep 17 00:00:00 2001 From: JeremiahUy Date: Tue, 5 Mar 2024 14:37:16 +0100 Subject: [PATCH 004/107] FIX: if clause and return value --- .../kravprioritylist/KravPriorityListController.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListController.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListController.java index 21642c68b..8c1506ac4 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListController.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListController.java @@ -73,17 +73,17 @@ public ResponseEntity getByTemaCodeAndKravNummer(@PathVariable String t Optional kravPriorityList = service.getByTema(temacode).map(KravPriorityList::toResponse); if(kravPriorityList.isEmpty()) { - ResponseEntity.notFound().build(); + return ResponseEntity.notFound().build(); } int kravPriority = -1; - if(kravPriorityList.isPresent() && !kravPriorityList.get().getPriorityList().isEmpty()) { + if(!kravPriorityList.get().getPriorityList().isEmpty()) { kravPriority = kravPriorityList.get().getPriorityList().indexOf(kravnummer); } if(kravPriority < 0) { - ResponseEntity.notFound().build(); + return ResponseEntity.notFound().build(); } return ResponseEntity.ok(kravPriority); From e6963a6e744d05619efe514d1b4f678983db7b36 Mon Sep 17 00:00:00 2001 From: Farjam Movafagh <45848158+farjamm@users.noreply.github.com> Date: Tue, 5 Mar 2024 16:09:31 +0100 Subject: [PATCH 005/107] =?UTF-8?q?Format,=20fikset=20bruk=20av=20ObjectMa?= =?UTF-8?q?pper,=20bedre=20transaksjonsh=C3=A5ndtering,=20kodekvalitet,=20?= =?UTF-8?q?mm.=20(#855)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/no/nav/data/common/CommonConfig.java | 9 +++-- .../common/auditing/AuditVersionListener.java | 9 +++-- .../common/auditing/domain/AuditVersion.java | 10 ++++-- .../auditing/domain/MailLogRepository.java | 4 +-- .../nav/data/common/jpa/JsonbOMSupplier.java | 4 ++- .../data/common/mail/EmailServiceImpl.java | 23 ++++++------ .../nav/data/common/rest/PageParameters.java | 1 + .../AADStatelessAuthenticationFilter.java | 2 +- .../data/common/storage/StorageService.java | 20 +++++------ .../common/storage/domain/GenericStorage.java | 2 ++ .../common/utils/CollectionDifference.java | 3 -- .../no/nav/data/common/utils/JsonUtils.java | 27 +++----------- .../no/nav/data/common/utils/MdcExecutor.java | 3 +- .../nav/data/common/validator/Validator.java | 6 ++-- .../arkivering/EtterlevelseArkivService.java | 17 ++++----- .../EtterlevelseArkivToDocService.java | 7 ++-- .../arkivering/domain/EtterlevelseArkiv.java | 6 ++-- .../codelist/codeusage/CodeUsageService.java | 2 +- .../etterlevelse/EtterlevelseService.java | 12 +++---- .../etterlevelse/domain/Etterlevelse.java | 3 +- .../SuksesskriterieBegrunnelseRequest.java | 2 +- .../EtterlevelseDokumentasjonController.java | 1 - .../EtterlevelseDokumentasjonService.java | 30 ++++++---------- .../domain/EtterlevelseDokumentasjon.java | 4 +-- .../EtterlevelseDokumentasjonRepoImpl.java | 2 +- .../EtterlevelseMetadataController.java | 2 +- .../EtterlevelseMetadataService.java | 10 +++--- .../domain/EtterlevelseMetadata.java | 5 ++- .../domain/EtterlevelseMetadataRepo.java | 2 +- .../data/etterlevelse/krav/KravService.java | 16 ++++----- .../krav/TilbakemeldingService.java | 11 ++---- .../data/etterlevelse/krav/domain/Krav.java | 7 ++-- .../krav/domain/Suksesskriterie.java | 2 +- .../krav/dto/SuksesskriterieRequest.java | 1 - .../krav/dto/TilbakemeldingResponse.java | 1 + .../KravPrioriteringController.java | 3 +- .../KravPrioriteringService.java | 16 ++++----- .../domain/KravPrioritering.java | 4 +-- .../domain/KravPrioriteringRepo.java | 2 -- .../etterlevelse/melding/MeldingService.java | 9 +++-- .../etterlevelse/melding/domain/Melding.java | 3 +- .../statistikk/StatistikkService.java | 30 ++++------------ .../domain/BehandlingStatistikk.java | 36 +++++++++---------- .../virkemiddel/VirkemiddelService.java | 12 +++---- .../virkemiddel/domain/Virkemiddel.java | 3 +- .../behandling/BehandlingService.java | 1 + .../codelist/CodelistControllerIT.java | 3 +- .../no/nav/data/graphql/GraphQLTestBase.java | 9 +++-- 48 files changed, 176 insertions(+), 221 deletions(-) diff --git a/apps/backend/src/main/java/no/nav/data/common/CommonConfig.java b/apps/backend/src/main/java/no/nav/data/common/CommonConfig.java index 6cff05683..a55b5f39d 100644 --- a/apps/backend/src/main/java/no/nav/data/common/CommonConfig.java +++ b/apps/backend/src/main/java/no/nav/data/common/CommonConfig.java @@ -20,10 +20,15 @@ @Configuration public class CommonConfig { + private static ObjectMapper omForHttpMessageConverter = JsonUtils.createObjectMapper(); + @Primary @Bean public ObjectMapper objectMapper() { - return JsonUtils.getObjectMapper(); + // ObjectMapper oppfører seg ikke-deterministisk hvis flere tråder bruker den samtidig, og der minst en av dem konfigurerer den. + // Dessuten kan forskjellige klienter konfigurere den på hver sin måte, noe som vil sabotere for andre. + // OM er kostbare å konstruere, men her skal vi ikke returnere en delt OM. + return JsonUtils.createObjectMapper(); } @Bean @@ -44,7 +49,7 @@ public RestTemplate externalRestTemplate(RestTemplateBuilder builder) { @Bean public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() { MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter(); - jsonConverter.setObjectMapper(objectMapper()); + jsonConverter.setObjectMapper(omForHttpMessageConverter); return jsonConverter; } diff --git a/apps/backend/src/main/java/no/nav/data/common/auditing/AuditVersionListener.java b/apps/backend/src/main/java/no/nav/data/common/auditing/AuditVersionListener.java index b1f297cd2..b507a05c7 100644 --- a/apps/backend/src/main/java/no/nav/data/common/auditing/AuditVersionListener.java +++ b/apps/backend/src/main/java/no/nav/data/common/auditing/AuditVersionListener.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.FilterProvider; @@ -41,7 +42,7 @@ public class AuditVersionListener { static { FilterProvider filters = new SimpleFilterProvider().addFilter("relationFilter", new RelationFilter()); - var om = JsonUtils.createObjectMapper(); + ObjectMapper om = JsonUtils.createObjectMapper(); om.setVisibility(PropertyAccessor.ALL, Visibility.NONE); om.setVisibility(PropertyAccessor.FIELD, Visibility.ANY); wr = om.writer(filters); @@ -68,7 +69,7 @@ public void preRemove(Object entity) { private void audit(Object entity, Action action) { Assert.isTrue(entity instanceof Auditable, "Invalid object"); - if (entity instanceof GenericStorage gs && !isAudited((gs).getType())) { + if (entity instanceof GenericStorage gs && !isAudited(gs.getType())) { return; } AuditVersion auditVersion = convertAuditVersion(entity, action); @@ -79,13 +80,11 @@ private void audit(Object entity, Action action) { public static AuditVersion convertAuditVersion(Object entity, Action action) { try { - String tableName; + String tableName = AuditVersion.tableNameFor(entity); int version; if (entity instanceof GenericStorage gs) { - tableName = gs.getType(); version = gs.getVersion() == null ? 0 : gs.getVersion() + 1; } else { - tableName = AuditVersion.tableName(((Auditable) entity).getClass()); version = -1; } String id = getIdForObject(entity); diff --git a/apps/backend/src/main/java/no/nav/data/common/auditing/domain/AuditVersion.java b/apps/backend/src/main/java/no/nav/data/common/auditing/domain/AuditVersion.java index 1f05890a4..436fd33e0 100644 --- a/apps/backend/src/main/java/no/nav/data/common/auditing/domain/AuditVersion.java +++ b/apps/backend/src/main/java/no/nav/data/common/auditing/domain/AuditVersion.java @@ -42,6 +42,7 @@ public class AuditVersion { @Column(name = "ACTION", nullable = false, updatable = false) private Action action; + // This is the type of the audited entity. See tableNameFor(...) to be slightly less confused. @Column(name = "TABLE_NAME", nullable = false, updatable = false) private String table; @@ -89,8 +90,13 @@ public AuditResponse toResponse() { .build(); } - public static String tableName(Class aClass) { - return aClass.getAnnotation(Table.class).name(); + public static String tableNameFor(Object entity) { + if (entity instanceof GenericStorage gs) { + return gs.getType(); + } else if (entity instanceof Auditable au) { + return au.getClass().getAnnotation(Table.class).name(); + } + throw new IllegalArgumentException("Should not audit entities of type " + entity.getClass().getSimpleName()); } } diff --git a/apps/backend/src/main/java/no/nav/data/common/auditing/domain/MailLogRepository.java b/apps/backend/src/main/java/no/nav/data/common/auditing/domain/MailLogRepository.java index 3bca24372..ab9d8ac3b 100644 --- a/apps/backend/src/main/java/no/nav/data/common/auditing/domain/MailLogRepository.java +++ b/apps/backend/src/main/java/no/nav/data/common/auditing/domain/MailLogRepository.java @@ -13,8 +13,8 @@ public interface MailLogRepository extends JpaRepository, UUID> { @Query(value = "select * from generic_storage where type = 'MailLog' order by created_date desc", - countQuery = "select count(1) from generic_storage where type = 'MailLog'" - , nativeQuery = true) + countQuery = "select count(1) from generic_storage where type = 'MailLog'", + nativeQuery = true) Page> findAll(Pageable pageable); @Query(value = "select * from generic_storage where type = 'MailLog' and data ->> 'to' = ?1 order by created_date desc", nativeQuery = true) diff --git a/apps/backend/src/main/java/no/nav/data/common/jpa/JsonbOMSupplier.java b/apps/backend/src/main/java/no/nav/data/common/jpa/JsonbOMSupplier.java index 6d3408984..f13855e30 100644 --- a/apps/backend/src/main/java/no/nav/data/common/jpa/JsonbOMSupplier.java +++ b/apps/backend/src/main/java/no/nav/data/common/jpa/JsonbOMSupplier.java @@ -6,8 +6,10 @@ public class JsonbOMSupplier implements ObjectMapperSupplier { + private static final ObjectMapper objectMapper = JsonUtils.createObjectMapper(); + @Override public ObjectMapper get() { - return JsonUtils.getObjectMapper(); + return objectMapper; } } diff --git a/apps/backend/src/main/java/no/nav/data/common/mail/EmailServiceImpl.java b/apps/backend/src/main/java/no/nav/data/common/mail/EmailServiceImpl.java index ba428add5..484b3d550 100644 --- a/apps/backend/src/main/java/no/nav/data/common/mail/EmailServiceImpl.java +++ b/apps/backend/src/main/java/no/nav/data/common/mail/EmailServiceImpl.java @@ -1,24 +1,21 @@ package no.nav.data.common.mail; +import lombok.RequiredArgsConstructor; import net.javacrumbs.shedlock.spring.annotation.SchedulerLock; import no.nav.data.common.security.SecurityProperties; import no.nav.data.common.storage.StorageService; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service +@RequiredArgsConstructor public class EmailServiceImpl implements EmailService { private final StorageService storage; private final EmailProvider emailProvider; private final SecurityProperties securityProperties; - public EmailServiceImpl(StorageService storage, EmailProvider emailProvider, SecurityProperties securityProperties) { - this.storage = storage; - this.emailProvider = emailProvider; - this.securityProperties = securityProperties; - } - @Override public void sendMail(MailTask mailTask) { var toSend = securityProperties.isDev() ? mailTask.withSubject("[DEV] " + mailTask.getSubject()) : mailTask; @@ -26,6 +23,7 @@ public void sendMail(MailTask mailTask) { } @Override + @Transactional public void scheduleMail(MailTask mailTask) { storage.save(mailTask); } @@ -34,10 +32,13 @@ public void scheduleMail(MailTask mailTask) { @Scheduled(initialDelayString = "PT2M", fixedRateString = "PT1M") public void sendMail() { var tasks = storage.getAll(MailTask.class); - - tasks.forEach(task -> { - sendMail(task); - storage.delete(task); - }); + tasks.forEach(this::sendMailAndDelete); + } + + @Transactional + private void sendMailAndDelete(MailTask task) { + sendMail(task); + storage.delete(task); } + } diff --git a/apps/backend/src/main/java/no/nav/data/common/rest/PageParameters.java b/apps/backend/src/main/java/no/nav/data/common/rest/PageParameters.java index 993ce8360..cb98043a1 100644 --- a/apps/backend/src/main/java/no/nav/data/common/rest/PageParameters.java +++ b/apps/backend/src/main/java/no/nav/data/common/rest/PageParameters.java @@ -21,6 +21,7 @@ public class PageParameters { @Schema(defaultValue = "0", minimum = "0") private int pageNumber = 0; + @Schema(defaultValue = "20", minimum = "1", maximum = "250") private int pageSize = 20; diff --git a/apps/backend/src/main/java/no/nav/data/common/security/azure/AADStatelessAuthenticationFilter.java b/apps/backend/src/main/java/no/nav/data/common/security/azure/AADStatelessAuthenticationFilter.java index fb92daa2e..67cca4070 100644 --- a/apps/backend/src/main/java/no/nav/data/common/security/azure/AADStatelessAuthenticationFilter.java +++ b/apps/backend/src/main/java/no/nav/data/common/security/azure/AADStatelessAuthenticationFilter.java @@ -237,7 +237,7 @@ private ConfigurableJWTProcessor getAadJwtTokenValidator(JWSAlg new JWSVerificationKeySelector<>(jwsAlgorithm, keySource); jwtProcessor.setJWSKeySelector(keySelector); - jwtProcessor.setJWTClaimsSetVerifier(new DefaultJWTClaimsVerifier<>() { + jwtProcessor.setJWTClaimsSetVerifier(new DefaultJWTClaimsVerifier<>(null, null, null, null) { @Override public void verify(JWTClaimsSet claimsSet, SecurityContext ctx) throws BadJWTException { super.verify(claimsSet, ctx); diff --git a/apps/backend/src/main/java/no/nav/data/common/storage/StorageService.java b/apps/backend/src/main/java/no/nav/data/common/storage/StorageService.java index efe89f5b2..e2924792f 100644 --- a/apps/backend/src/main/java/no/nav/data/common/storage/StorageService.java +++ b/apps/backend/src/main/java/no/nav/data/common/storage/StorageService.java @@ -1,5 +1,6 @@ package no.nav.data.common.storage; +import lombok.RequiredArgsConstructor; import no.nav.data.common.exceptions.NotFoundException; import no.nav.data.common.storage.domain.DomainObject; import no.nav.data.common.storage.domain.GenericStorage; @@ -18,22 +19,20 @@ import static no.nav.data.common.utils.StreamUtils.convert; @Service -@Transactional +@RequiredArgsConstructor public class StorageService { private final GenericStorageRepository repository; - public StorageService(GenericStorageRepositoryrepository) { - this.repository = repository; - } - public T get(UUID uuid) { + if (uuid == null || !exists(uuid)) return null; return getStorage(uuid).getDomainObjectData(); } /** * Batch save, does not work for existing objects */ + @Transactional public List> saveAll(Collection objects) { Assert.isTrue(objects.stream().noneMatch(o -> o.getId() != null), "Cannot use saveAll on existing object"); var storages = convert(objects, o -> new GenericStorage().generateId().setDomainObjectData(o)); @@ -42,6 +41,7 @@ public List> saveAll(Collection objects) { return storageList; } + @Transactional public T save(T object) { GenericStorage storage = object.getId() != null ? (GenericStorage) getStorage(object.getId()) : new GenericStorage().generateId(); storage.setDomainObjectData(object); @@ -50,6 +50,7 @@ public T save(T object) { return saved.getDomainObjectData(); } + @Transactional public void deleteAll(List objects) { repository.deleteAll(convert(objects, DomainObject::getId)); } @@ -63,18 +64,13 @@ public boolean exists(UUID uuid) { return repository.existsById(uuid); } - /** - * Will not throw if object does not exist - */ - public void softDelete(UUID id, Class type) { - repository.deleteByIdAndType(id, TypeRegistration.typeOf(type)); - } - + @Transactional public T delete(T item) { repository.deleteById(item.getId()); return item; } + @Transactional public T delete(UUID id) { var storage = getStorage(id); repository.delete(storage); diff --git a/apps/backend/src/main/java/no/nav/data/common/storage/domain/GenericStorage.java b/apps/backend/src/main/java/no/nav/data/common/storage/domain/GenericStorage.java index 16c1c1a39..219468276 100644 --- a/apps/backend/src/main/java/no/nav/data/common/storage/domain/GenericStorage.java +++ b/apps/backend/src/main/java/no/nav/data/common/storage/domain/GenericStorage.java @@ -58,6 +58,7 @@ public GenericStorage generateId() { Assert.isTrue(id == null, "id already set"); id = UUID.randomUUID(); // TODO: Setter IKKE id på domainObjectCache. Må sjekke at dette er riktig oppførsel + // Se https://trello.com/c/rP0Ln2zc/358-synkronisering-av-felles-felter-domainobject-vs-genericstorage return this; } @@ -66,6 +67,7 @@ public GenericStorage generateId() { */ public GenericStorage setDomainObjectData(T domainObject) { // TODO: Setter IKKE changeStamp på this fra domainObject. Må sjekkes at dette er riktig oppførsel. + // Se https://trello.com/c/rP0Ln2zc/358-synkronisering-av-felles-felter-domainobject-vs-genericstorage Assert.isTrue(id != null, "id not set"); domainObject.setId(id); type = domainObject.type(); diff --git a/apps/backend/src/main/java/no/nav/data/common/utils/CollectionDifference.java b/apps/backend/src/main/java/no/nav/data/common/utils/CollectionDifference.java index aaa119034..40884f7ce 100644 --- a/apps/backend/src/main/java/no/nav/data/common/utils/CollectionDifference.java +++ b/apps/backend/src/main/java/no/nav/data/common/utils/CollectionDifference.java @@ -20,7 +20,4 @@ public class CollectionDifference { private List shared; private List added; - public String changeString() { - return "removed=" + removed + ", added=" + added; - } } diff --git a/apps/backend/src/main/java/no/nav/data/common/utils/JsonUtils.java b/apps/backend/src/main/java/no/nav/data/common/utils/JsonUtils.java index fc5cce29c..1be7aee59 100644 --- a/apps/backend/src/main/java/no/nav/data/common/utils/JsonUtils.java +++ b/apps/backend/src/main/java/no/nav/data/common/utils/JsonUtils.java @@ -5,41 +5,32 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import no.nav.data.common.exceptions.TechnicalException; -import org.springframework.core.ParameterizedTypeReference; import java.io.IOException; -import java.util.List; -import java.util.Map; public final class JsonUtils { - public static final ParameterizedTypeReference> STRING_LIST = new ParameterizedTypeReference<>() { - }; - public static final ParameterizedTypeReference> INT_LIST = new ParameterizedTypeReference<>() { - }; - private JsonUtils() { } private static final ObjectMapper objectMapper = createObjectMapper(); - private static final TypeReference> MAP_TYPE_REFERENCE = new TypeReference<>() { - }; public static ObjectMapper createObjectMapper() { - var om = new ObjectMapper(); + ObjectMapper om = new ObjectMapper(); om.registerModule(new JavaTimeModule()); om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); om.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); return om; } - public static ObjectMapper getObjectMapper() { - return objectMapper; + public static ObjectReader getObjectReader() { + return objectMapper.reader(); } - + public static JsonNode toJsonNode(String json) { try { return objectMapper.readTree(json); @@ -48,10 +39,6 @@ public static JsonNode toJsonNode(String json) { } } - public static Map toMap(Object object) { - return objectMapper.convertValue(object, MAP_TYPE_REFERENCE); - } - public static T toObject(String jsonPayload, Class type) { try { return objectMapper.readValue(jsonPayload, type); @@ -88,8 +75,4 @@ public static JsonNode toJsonNode(Object object) { return objectMapper.valueToTree(object); } - @SuppressWarnings("unchecked") - public static T cloneObject(T object) { - return (T) toObject(toJsonNode(object), object.getClass()); - } } diff --git a/apps/backend/src/main/java/no/nav/data/common/utils/MdcExecutor.java b/apps/backend/src/main/java/no/nav/data/common/utils/MdcExecutor.java index c88ff508f..bf48cdc27 100644 --- a/apps/backend/src/main/java/no/nav/data/common/utils/MdcExecutor.java +++ b/apps/backend/src/main/java/no/nav/data/common/utils/MdcExecutor.java @@ -28,7 +28,8 @@ public void execute(Runnable command) { super.execute(wrap(command, parentContext)); } - // TODO: Denne skal fjernes. Se ListenableFutureCallback for hvordan dette kalles erstattes. + // TODO: Denne skal fjernes. Se ListenableFutureCallback for hvordan dette kallet erstattes. + // Se https://trello.com/c/iSysbdus/356-fjerne-bruk-av-listenablefuturecallback @Deprecated(forRemoval = true) public static ListenableFutureCallback wrap(Consumer onSuccessCallback, Consumer onErrorCallback) { var parentContext = MDC.getCopyOfContextMap(); diff --git a/apps/backend/src/main/java/no/nav/data/common/validator/Validator.java b/apps/backend/src/main/java/no/nav/data/common/validator/Validator.java index 2e718090e..e84c87366 100644 --- a/apps/backend/src/main/java/no/nav/data/common/validator/Validator.java +++ b/apps/backend/src/main/java/no/nav/data/common/validator/Validator.java @@ -3,7 +3,6 @@ import lombok.Getter; import lombok.extern.slf4j.Slf4j; import no.nav.data.common.exceptions.ValidationException; -import no.nav.data.common.storage.StorageService; import no.nav.data.common.storage.domain.DomainObject; import no.nav.data.etterlevelse.codelist.CodelistService; import no.nav.data.etterlevelse.codelist.domain.ListName; @@ -75,11 +74,10 @@ public Validator(T item, String parentField) { this.item = item; } - // TODO: Det skal ikke være en avhengighet til StorageService fra denne klassen - public static Validator validate(R item, StorageService storage) { + public static Validator validate(R item, Function getDomainObjectForUuid) { Validator validator = validate(item); UUID uuid = item.getIdAsUUID(); - validator.domainItem = uuid != null && storage.exists(uuid) ? storage.get(uuid) : null; + validator.domainItem = getDomainObjectForUuid.apply(uuid); validator.validateRepositoryValues(item, validator.domainItem != null); return validator; } diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/arkivering/EtterlevelseArkivService.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/arkivering/EtterlevelseArkivService.java index 6aabf7498..5b47319c7 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/arkivering/EtterlevelseArkivService.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/arkivering/EtterlevelseArkivService.java @@ -1,6 +1,7 @@ package no.nav.data.etterlevelse.arkivering; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import no.nav.data.common.rest.PageParameters; import no.nav.data.common.storage.domain.GenericStorage; @@ -23,14 +24,10 @@ @Service @Slf4j +@RequiredArgsConstructor public class EtterlevelseArkivService extends DomainService { private final EtterlevelseArkivRepo repo; - - public EtterlevelseArkivService(EtterlevelseArkivRepo repo) { - this.repo = repo; - } - public Page getAll(PageParameters pageParameters) { return repo.findAll(pageParameters.createPage()).map(GenericStorage::getDomainObjectData); } @@ -47,6 +44,7 @@ public List getByEtterlevelseDokumentasjon(String etterlevels return convertToDomaionObject(repo.findByEtterlevelseDokumentsjonId(etterlevelseDokumentasjonId)); } + @Transactional(propagation = Propagation.REQUIRED) public List setStatusToArkivert() { LocalDateTime arkiveringDato = LocalDateTime.now(); List tilArkivertStatus = getByStatus(EtterlevelseArkivStatus.BEHANDLER_ARKIVERING.name()); @@ -69,6 +67,7 @@ public List setStatusToArkivert() { return arkivert; } + @Transactional(propagation = Propagation.REQUIRED) public List setStatusToBehandler_arkivering() { List tilArkivering = getByStatus(EtterlevelseArkivStatus.TIL_ARKIVERING.name()); List behandlerArkivering = new ArrayList<>(); @@ -89,6 +88,7 @@ public List setStatusToBehandler_arkivering() { return behandlerArkivering; } + @Transactional(propagation = Propagation.REQUIRED) public void setStatusWithEtterlevelseDokumentasjonId(EtterlevelseArkivStatus newStatus, String etterlevelseDokumentasjonId) { List arkiveringTilNyStatus = getByEtterlevelseDokumentasjon(etterlevelseDokumentasjonId); arkiveringTilNyStatus.forEach(e -> @@ -106,14 +106,15 @@ public void setStatusWithEtterlevelseDokumentasjonId(EtterlevelseArkivStatus new ); } + @Transactional(propagation = Propagation.REQUIRED) public EtterlevelseArkiv save(EtterlevelseArkivRequest request) { var etterlevelseArkiv = request.isUpdate() ? storage.get(request.getIdAsUUID()) : new EtterlevelseArkiv(); - etterlevelseArkiv.convert(request); - + etterlevelseArkiv.merge(request); return storage.save(etterlevelseArkiv); } - public void deleteByEtterlevelseDokumentsjonId(String etterlevelseDokumentasjonId){ + @Transactional(propagation = Propagation.REQUIRED) + public void deleteByEtterlevelseDokumentsjonId(String etterlevelseDokumentasjonId) { List etterlevelseArkiver = convertToDomaionObject(repo.findByEtterlevelseDokumentsjonId(etterlevelseDokumentasjonId)); etterlevelseArkiver.forEach(ea -> log.info("deleting etterlevelse arkiv with id={}, connected to etterlevelse dokumentasjon with id={}", ea.getId(), etterlevelseDokumentasjonId)); storage.deleteAll(etterlevelseArkiver); diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/arkivering/EtterlevelseArkivToDocService.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/arkivering/EtterlevelseArkivToDocService.java index 9efc3421c..78870f276 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/arkivering/EtterlevelseArkivToDocService.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/arkivering/EtterlevelseArkivToDocService.java @@ -1,5 +1,6 @@ package no.nav.data.etterlevelse.arkivering; +import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import no.nav.data.common.utils.ZipUtils; import no.nav.data.etterlevelse.arkivering.domain.ArchiveFile; @@ -30,16 +31,12 @@ import java.util.UUID; @Service +@RequiredArgsConstructor public class EtterlevelseArkivToDocService extends DomainService { private final EtterlevelseDokumentasjonService etterlevelseDokumentasjonService; private final EtterlevelseDokumentasjonToDoc etterlevelseDokumentasjonToDoc; - public EtterlevelseArkivToDocService(EtterlevelseDokumentasjonService etterlevelseDokumentasjonService, EtterlevelseDokumentasjonToDoc etterlevelseDokumentasjonToDoc) { - this.etterlevelseDokumentasjonService = etterlevelseDokumentasjonService; - this.etterlevelseDokumentasjonToDoc = etterlevelseDokumentasjonToDoc; - } - public byte[] getEtterlevelserArchiveZip(List etterlevelseArkivList) throws IOException { SimpleDateFormat formatter = new SimpleDateFormat("yyyy'-'MM'-'dd'_'HH'-'mm'-'ss"); SimpleDateFormat xmlDateFormatter = new SimpleDateFormat("YYYYMMdd_HHmmss"); diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/arkivering/domain/EtterlevelseArkiv.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/arkivering/domain/EtterlevelseArkiv.java index 89c7b5592..dc9f44717 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/arkivering/domain/EtterlevelseArkiv.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/arkivering/domain/EtterlevelseArkiv.java @@ -28,10 +28,10 @@ public class EtterlevelseArkiv extends DomainObject { private LocalDateTime arkiveringAvbruttDato; private String webSakNummer; - - public EtterlevelseArkiv convert(EtterlevelseArkivRequest request) { - behandlingId = request.getBehandlingId(); + // Updates all fields from the request except id, version and changestamp + public EtterlevelseArkiv merge(EtterlevelseArkivRequest request) { etterlevelseDokumentasjonId = request.getEtterlevelseDokumentasjonId(); + behandlingId = request.getBehandlingId(); arkiveringDato = request.getArkiveringDato(); arkivertAv = request.getArkivertAv(); tilArkiveringDato = request.getTilArkiveringDato(); diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/codelist/codeusage/CodeUsageService.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/codelist/codeusage/CodeUsageService.java index ea5952bbc..39c909d95 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/codelist/codeusage/CodeUsageService.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/codelist/codeusage/CodeUsageService.java @@ -36,7 +36,6 @@ import static no.nav.data.etterlevelse.codelist.CodelistService.getCodelist; @Service -@Transactional public class CodeUsageService { private final KravRepo kravRepo; @@ -90,6 +89,7 @@ public CodeUsage findCodeUsage(ListName listName, String code) { }); } + @Transactional public CodeUsage replaceUsage(ListName listName, String oldCode, String newCode) { var usage = findCodeUsage(listName, oldCode); if (usage.isInUse()) { diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelse/EtterlevelseService.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelse/EtterlevelseService.java index 806d67c0d..675573be8 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelse/EtterlevelseService.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelse/EtterlevelseService.java @@ -1,5 +1,6 @@ package no.nav.data.etterlevelse.etterlevelse; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import no.nav.data.common.rest.PageParameters; import no.nav.data.common.storage.domain.GenericStorage; @@ -28,14 +29,11 @@ @Service @Slf4j +@RequiredArgsConstructor public class EtterlevelseService extends DomainService { private final EtterlevelseRepo repo; - public EtterlevelseService(EtterlevelseRepo repo) { - this.repo = repo; - } - Page getAll(PageParameters pageParameters) { return repo.findAll(pageParameters.createPage()).map(GenericStorage::getDomainObjectData); } @@ -63,17 +61,19 @@ public Map> getByEtterlevelseDokumentasjoner(Collecti return groupBy(convertToDomaionObject(repo.findByEtterlevelseDokumentasjoner(new ArrayList<>(etterlevelseDokumentasjonIds))), Etterlevelse::getEtterlevelseDokumentasjonId); } + @Transactional(propagation = Propagation.REQUIRED) public Etterlevelse save(EtterlevelseRequest request) { - Validator.validate(request, storage) + Validator.validate(request, storage::get) .addValidations(this::validateKrav) .ifErrorsThrowValidationException(); var etterlevelse = request.isUpdate() ? storage.get(request.getIdAsUUID()) : new Etterlevelse(); - etterlevelse.convert(request); + etterlevelse.merge(request); return storage.save(etterlevelse); } + @Transactional(propagation = Propagation.REQUIRED) public void deleteByEtterlevelseDokumentasjonId(String etterlevelseDokumentasjonId) { List etterlevelser = convertToDomaionObject(etterlevelseRepo.findByEtterlevelseDokumensjon(etterlevelseDokumentasjonId)); etterlevelser.forEach(e -> log.info("deleting etterlevelse with id={}, connected to etterlevelse dokumentasjon with id={}", e.getId(), etterlevelseDokumentasjonId)); diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelse/domain/Etterlevelse.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelse/domain/Etterlevelse.java index fa1d89e5e..c3dc48b39 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelse/domain/Etterlevelse.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelse/domain/Etterlevelse.java @@ -37,7 +37,8 @@ public class Etterlevelse extends DomainObject implements KravId { private EtterlevelseStatus status; private List suksesskriterieBegrunnelser; - public Etterlevelse convert(EtterlevelseRequest request) { + // Updates all fields from the request except id, version and changestamp + public Etterlevelse merge(EtterlevelseRequest request) { behandlingId = request.getBehandlingId(); etterlevelseDokumentasjonId = request.getEtterlevelseDokumentasjonId(); kravNummer = request.getKravNummer(); diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelse/dto/SuksesskriterieBegrunnelseRequest.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelse/dto/SuksesskriterieBegrunnelseRequest.java index a82f66c7d..2f86c3fc3 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelse/dto/SuksesskriterieBegrunnelseRequest.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelse/dto/SuksesskriterieBegrunnelseRequest.java @@ -17,9 +17,9 @@ @NoArgsConstructor @AllArgsConstructor public class SuksesskriterieBegrunnelseRequest implements Validated { + private int suksesskriterieId; private String begrunnelse; - private SuksesskriterieStatus suksesskriterieStatus; @Override diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelseDokumentasjon/EtterlevelseDokumentasjonController.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelseDokumentasjon/EtterlevelseDokumentasjonController.java index daf6bd26e..46fb2f45f 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelseDokumentasjon/EtterlevelseDokumentasjonController.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelseDokumentasjon/EtterlevelseDokumentasjonController.java @@ -37,7 +37,6 @@ public class EtterlevelseDokumentasjonController { private final EtterlevelseDokumentasjonService etterlevelseDokumentasjonService; - @Operation(summary = "Get All Etterlevelse Dokumentasjon") @ApiResponse(description = "ok") @GetMapping diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelseDokumentasjon/EtterlevelseDokumentasjonService.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelseDokumentasjon/EtterlevelseDokumentasjonService.java index 1d930ca39..d8fd92927 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelseDokumentasjon/EtterlevelseDokumentasjonService.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelseDokumentasjon/EtterlevelseDokumentasjonService.java @@ -1,5 +1,6 @@ package no.nav.data.etterlevelse.etterlevelseDokumentasjon; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import no.nav.data.common.rest.PageParameters; import no.nav.data.common.storage.domain.GenericStorage; @@ -34,6 +35,7 @@ @Slf4j @Service +@RequiredArgsConstructor public class EtterlevelseDokumentasjonService extends DomainService { private final BehandlingService behandlingService; @@ -42,14 +44,6 @@ public class EtterlevelseDokumentasjonService extends DomainService getAll(PageParameters pageParameters) { return etterlevelseDokumentasjonRepo.findAll(pageParameters.createPage()).map(GenericStorage::getDomainObjectData); } @@ -59,7 +53,7 @@ public List getEtterlevelseDokumentasjonerByTeam(Stri } public List searchEtterlevelseDokumentasjon(String searchParam) { - if(searchParam.toLowerCase().matches("e[0-9]+(.*)")) { + if (searchParam.toLowerCase().matches("e[0-9]+(.*)")) { return convertToDomaionObject(etterlevelseDokumentasjonRepo.searchEtterlevelseDokumentasjon(searchParam.substring(1))); } else { return convertToDomaionObject(etterlevelseDokumentasjonRepo.searchEtterlevelseDokumentasjon(searchParam)); @@ -93,16 +87,13 @@ public List getByFilter(EtterlevelseDokumentasjonFilt return convertToDomaionObject(etterlevelseDokumentasjonRepo.findBy(filter)); } + @Transactional(propagation = Propagation.REQUIRED) public EtterlevelseDokumentasjon save(EtterlevelseDokumentasjonRequest request) { - - var etterlevelseDokumentasjon = request.isUpdate() ? storage.get(request.getIdAsUUID()) : new EtterlevelseDokumentasjon(); - - etterlevelseDokumentasjon.convert(request); - + EtterlevelseDokumentasjon etterlevelseDokumentasjon = request.isUpdate() ? storage.get(request.getIdAsUUID()) : new EtterlevelseDokumentasjon(); + etterlevelseDokumentasjon.merge(request); if (!request.isUpdate()) { etterlevelseDokumentasjon.setEtterlevelseNummer(etterlevelseDokumentasjonRepo.nextEtterlevelseDokumentasjonNummer()); } - return storage.save(etterlevelseDokumentasjon); } @@ -146,8 +137,9 @@ public Page getAll(Pageable pageable) { return storage.getAll(EtterlevelseDokumentasjon.class, pageable); } - public EtterlevelseDokumentasjonResponse addBehandlingAndTeamsData(EtterlevelseDokumentasjonResponse etterlevelseDokumentasjonResponse){ - if(etterlevelseDokumentasjonResponse.getBehandlingIds() != null && !etterlevelseDokumentasjonResponse.getBehandlingIds().isEmpty()) { + // Does not update DB + public EtterlevelseDokumentasjonResponse addBehandlingAndTeamsData(EtterlevelseDokumentasjonResponse etterlevelseDokumentasjonResponse) { + if (etterlevelseDokumentasjonResponse.getBehandlingIds() != null && !etterlevelseDokumentasjonResponse.getBehandlingIds().isEmpty()) { List behandlingList = new ArrayList<>(); etterlevelseDokumentasjonResponse.getBehandlingIds().forEach((behandlingId) -> { try { @@ -162,11 +154,11 @@ public EtterlevelseDokumentasjonResponse addBehandlingAndTeamsData(EtterlevelseD }); etterlevelseDokumentasjonResponse.setBehandlinger(behandlingList); } - if(etterlevelseDokumentasjonResponse.getTeams() != null && !etterlevelseDokumentasjonResponse.getTeams().isEmpty()){ + if (etterlevelseDokumentasjonResponse.getTeams() != null && !etterlevelseDokumentasjonResponse.getTeams().isEmpty()) { List teamsData = new ArrayList<>(); etterlevelseDokumentasjonResponse.getTeams().forEach((teamId) -> { var teamData = teamcatTeamClient.getTeam(teamId); - if(teamData.isPresent()){ + if (teamData.isPresent()) { teamsData.add(teamData.get().toResponse()); } else { var emptyTeamData = new TeamResponse(); diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelseDokumentasjon/domain/EtterlevelseDokumentasjon.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelseDokumentasjon/domain/EtterlevelseDokumentasjon.java index 9f1a4c917..92daa78d4 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelseDokumentasjon/domain/EtterlevelseDokumentasjon.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelseDokumentasjon/domain/EtterlevelseDokumentasjon.java @@ -43,8 +43,8 @@ public List irrelevantForAsCodes() { return CodelistService.getCodelistResponseList(ListName.RELEVANS, irrelevansFor); } - - public void convert(EtterlevelseDokumentasjonRequest request) { + // Updates all fields from the request except id, version and changestamp + public void merge(EtterlevelseDokumentasjonRequest request) { etterlevelseNummer = request.getEtterlevelseNummer(); title = request.getTitle(); behandlingIds = copyOf(request.getBehandlingIds()); diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelseDokumentasjon/domain/EtterlevelseDokumentasjonRepoImpl.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelseDokumentasjon/domain/EtterlevelseDokumentasjonRepoImpl.java index 617bed396..760df6b97 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelseDokumentasjon/domain/EtterlevelseDokumentasjonRepoImpl.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelseDokumentasjon/domain/EtterlevelseDokumentasjonRepoImpl.java @@ -38,7 +38,7 @@ public List> getEtterlevelseDokumentas } @Override - public List> findByBehandlingIds(List ids){ + public List> findByBehandlingIds(List ids) { var query = "select * from generic_storage where type = 'EtterlevelseDokumentasjon' and data -> 'behandlingIds' ??| array[ :behandlingIds ]"; var par = new MapSqlParameterSource(); par.addValue("behandlingIds", ids); diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelsemetadata/EtterlevelseMetadataController.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelsemetadata/EtterlevelseMetadataController.java index f75939f38..92c7c551e 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelsemetadata/EtterlevelseMetadataController.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelsemetadata/EtterlevelseMetadataController.java @@ -126,7 +126,7 @@ public ResponseEntity deleteEtterlevelseMetadata(@ return ResponseEntity.ok(etterlevelseMetadata.toResponse()); } + // Used only for unittests static class EtterlevelseMetadataPage extends RestResponsePage { - } } diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelsemetadata/EtterlevelseMetadataService.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelsemetadata/EtterlevelseMetadataService.java index db1e21473..4c6188301 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelsemetadata/EtterlevelseMetadataService.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelsemetadata/EtterlevelseMetadataService.java @@ -1,5 +1,6 @@ package no.nav.data.etterlevelse.etterlevelsemetadata; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import no.nav.data.common.rest.PageParameters; import no.nav.data.common.storage.domain.GenericStorage; @@ -19,15 +20,12 @@ import static no.nav.data.common.storage.domain.GenericStorage.convertToDomaionObject; @Service +@RequiredArgsConstructor @Slf4j public class EtterlevelseMetadataService extends DomainService { private final EtterlevelseMetadataRepo repo; - public EtterlevelseMetadataService(EtterlevelseMetadataRepo repo) { - this.repo = repo; - } - public Page getAll(PageParameters pageParameters){ return repo.findAll(pageParameters.createPage()).map(GenericStorage::getDomainObjectData); } @@ -58,14 +56,16 @@ public List getByEtterlevelseDokumentasjonAndKrav(String e return convertToDomaionObject(repo.findByEtterlevelseDokumentasjonAndKrav(etterlevelseDokumentasjonId, kravNummer, kravVersjon)); } + @Transactional(propagation = Propagation.REQUIRED) public EtterlevelseMetadata save(EtterlevelseMetadataRequest request) { var etterlevelseMetadata = request.isUpdate() ? storage.get(request.getIdAsUUID()) : new EtterlevelseMetadata(); - etterlevelseMetadata.convert(request); + etterlevelseMetadata.merge(request); return storage.save(etterlevelseMetadata); } + @Transactional(propagation = Propagation.REQUIRED) public void deleteByEtterlevelseDokumentasjonId(String etterlevelseDokumentasjonId){ List etterlevelseMetadataer = convertToDomaionObject(etterlevelseMetadataRepo.findByEtterlevelseDokumentasjon(etterlevelseDokumentasjonId)); etterlevelseMetadataer.forEach(em -> log.info("deleting etterlevelse metadata with id={}, connected to etterlevelse dokumentasjon with id={}", em.getId(), etterlevelseDokumentasjonId)); diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelsemetadata/domain/EtterlevelseMetadata.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelsemetadata/domain/EtterlevelseMetadata.java index f7fa61485..5cbe91e2e 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelsemetadata/domain/EtterlevelseMetadata.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelsemetadata/domain/EtterlevelseMetadata.java @@ -28,7 +28,10 @@ public class EtterlevelseMetadata extends DomainObject implements KravId { private List tildeltMed; private String notater; - public EtterlevelseMetadata convert(EtterlevelseMetadataRequest request) { + // Updates all fields from the request except id, version and changestamp + // TODO: behandlingId blir IKKE merget. Er dette riktig? Hvis ja: oppdater kommentaren over. Hvis nei: fiks + // Se https://trello.com/c/lJlryZIG/357-felter-blir-ignorert-ved-konvertering-av-request + public EtterlevelseMetadata merge(EtterlevelseMetadataRequest request) { kravNummer = request.getKravNummer(); kravVersjon = request.getKravVersjon(); etterlevelseDokumentasjonId = request.getEtterlevelseDokumentasjonId(); diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelsemetadata/domain/EtterlevelseMetadataRepo.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelsemetadata/domain/EtterlevelseMetadataRepo.java index 1455bcb4f..3581e174f 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelsemetadata/domain/EtterlevelseMetadataRepo.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/etterlevelsemetadata/domain/EtterlevelseMetadataRepo.java @@ -10,7 +10,7 @@ import java.util.UUID; public interface EtterlevelseMetadataRepo extends JpaRepository, UUID> { - @Override + @Query(value = "select * from generic_storage where type = 'EtterlevelseMetadata' order by data -> 'kravNummer', data -> 'kravVersjon'", countQuery = "select count(1) from generic_storage where type = 'EtterlevelseMetadata'", nativeQuery = true) diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/krav/KravService.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/krav/KravService.java index 1f48d83f4..ca6f9edbf 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/krav/KravService.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/krav/KravService.java @@ -1,5 +1,6 @@ package no.nav.data.etterlevelse.krav; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import net.javacrumbs.shedlock.spring.annotation.SchedulerLock; import no.nav.data.common.storage.StorageService; @@ -13,7 +14,6 @@ import no.nav.data.etterlevelse.krav.dto.KravRequest; import no.nav.data.etterlevelse.krav.dto.KravRequest.Fields; import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.scheduling.annotation.Scheduled; @@ -34,13 +34,10 @@ @Slf4j @Service +@RequiredArgsConstructor public class KravService extends DomainService { - @Autowired - protected StorageService imageStorage; - - public KravService() { - } + protected final StorageService imageStorage; public Page getAll(Pageable page) { Page> all; @@ -94,8 +91,9 @@ public List searchByNumber(String number) { return convert(byNumberContaining, GenericStorage::getDomainObjectData); } + @Transactional(propagation = Propagation.REQUIRED) public Krav save(KravRequest request) { - Validator.validate(request, storage) + Validator.validate(request, storage::get) .addValidations(this::validateName) .addValidations(this::validateStatus) .addValidations(this::validateKravNummerVersjon) @@ -104,7 +102,7 @@ public Krav save(KravRequest request) { var krav = request.isUpdate() ? storage.get(request.getIdAsUUID()) : new Krav(); - krav.convert(request); + krav.merge(request); if (request.isNyKravVersjon()) { krav.setKravNummer(request.getKravNummer()); @@ -154,6 +152,7 @@ public List findForEtterlevelseDokumentasjonIrrelevans(String etterlevelse return getByFilter(KravFilter.builder().etterlevelseDokumentasjonId(etterlevelseDokumentasjonId).virkemiddelId(virkemiddelId).etterlevelseDokumentasjonIrrevantKrav(true).build()); } + @Transactional(propagation = Propagation.REQUIRED) public List saveImages(List images) { return convert(imageStorage.saveAll(images), GenericStorage::getDomainObjectData); } @@ -208,6 +207,7 @@ private void validateBegreper(Validator validator) { @SchedulerLock(name = "clean_krav_images", lockAtLeastFor = "PT5M") @Scheduled(initialDelayString = "PT5M", fixedRateString = "PT1H") + @Transactional(propagation = Propagation.REQUIRED) public void cleanupImages() { var deletes = kravRepo.cleanupImages(); log.info("Deleted {} unused krav images", deletes); diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/krav/TilbakemeldingService.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/krav/TilbakemeldingService.java index 75aca5501..afb5033bb 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/krav/TilbakemeldingService.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/krav/TilbakemeldingService.java @@ -1,5 +1,6 @@ package no.nav.data.etterlevelse.krav; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import no.nav.data.common.mail.EmailService; import no.nav.data.common.mail.MailTask; @@ -33,6 +34,7 @@ @Slf4j @Service +@RequiredArgsConstructor public class TilbakemeldingService extends DomainService { private final TeamcatResourceClient resourceClient; @@ -42,15 +44,6 @@ public class TilbakemeldingService extends DomainService { private final TilbakemeldingRepo tilbakemeldingRepo; - public TilbakemeldingService(TeamcatResourceClient resourceClient, EmailService emailService, SlackClient slackClient, - UrlGenerator urlGenerator, TilbakemeldingRepo tilbakemeldingRepo) { - this.urlGenerator = urlGenerator; - this.resourceClient = resourceClient; - this.emailService = emailService; - this.slackClient = slackClient; - this.tilbakemeldingRepo = tilbakemeldingRepo; - } - public List getForKravByNumberAndVersion(int kravNummer, int kravVersjon) { return convertToDomaionObject(tilbakemeldingRepo.findByKravNummerAndVersion(kravNummer, kravVersjon)); } diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/krav/domain/Krav.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/krav/domain/Krav.java index 837504334..1cccb88c4 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/krav/domain/Krav.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/krav/domain/Krav.java @@ -65,7 +65,10 @@ public class Krav extends DomainObject implements KravId { @Default private KravStatus status = KravStatus.UTKAST; - public Krav convert(KravRequest request) { + // Updates all fields from the request except id, version and changestamp + // TODO: kravNummer og kravVersjon blir IKKE merget. Er dette riktig? Hvis ja: oppdater kommentaren over. Hvis nei: fiks + // Se https://trello.com/c/lJlryZIG/357-felter-blir-ignorert-ved-konvertering-av-request + public Krav merge(KravRequest request) { navn = request.getNavn(); beskrivelse = request.getBeskrivelse(); hensikt = request.getHensikt(); @@ -88,7 +91,7 @@ public Krav convert(KravRequest request) { notat = request.getNotat(); varselMelding = request.getVarselMelding(); - suksesskriterier = StreamUtils.convert(request.getSuksesskriterier(), Suksesskriterie::convert); + suksesskriterier = StreamUtils.convert(request.getSuksesskriterier(), Suksesskriterie::fromRequest); kravIdRelasjoner = copyOf(request.getKravIdRelasjoner()); aktivertDato = request.getAktivertDato(); diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/krav/domain/Suksesskriterie.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/krav/domain/Suksesskriterie.java index def7a66e3..673601bd1 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/krav/domain/Suksesskriterie.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/krav/domain/Suksesskriterie.java @@ -20,7 +20,7 @@ public class Suksesskriterie { private boolean behovForBegrunnelse = true; - public static Suksesskriterie convert(SuksesskriterieRequest request) { + public static Suksesskriterie fromRequest(SuksesskriterieRequest request) { return Suksesskriterie.builder() .id(request.getId()) .navn(request.getNavn()) diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/krav/dto/SuksesskriterieRequest.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/krav/dto/SuksesskriterieRequest.java index e27e7e76d..9e33827c2 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/krav/dto/SuksesskriterieRequest.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/krav/dto/SuksesskriterieRequest.java @@ -23,7 +23,6 @@ public class SuksesskriterieRequest implements Validated { private String beskrivelse; private boolean behovForBegrunnelse; - @Override public void format() { setNavn(trimToNull(navn)); diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/krav/dto/TilbakemeldingResponse.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/krav/dto/TilbakemeldingResponse.java index 8454f6a9d..49cbc79f7 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/krav/dto/TilbakemeldingResponse.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/krav/dto/TilbakemeldingResponse.java @@ -32,6 +32,7 @@ public class TilbakemeldingResponse { private List meldinger; private TilbakemeldingStatus status; private boolean endretKrav; + @Data @Builder @NoArgsConstructor diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritering/KravPrioriteringController.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritering/KravPrioriteringController.java index b249c2e10..363bc4350 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritering/KravPrioriteringController.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritering/KravPrioriteringController.java @@ -41,7 +41,6 @@ @Tag(name = "KravPrioritering", description = "prioriterings rekkefølge for krav") public class KravPrioriteringController { - private final KravPrioriteringService service; private final CodelistService codelistService; @@ -99,7 +98,7 @@ public ResponseEntity> getByFilter( .kravStatus(kravStatus) .build(); log.info("Get krav prioritering with filter={}", filter); - if(filter.getTemaCode() != null) { + if (filter.getTemaCode() != null) { codelistService.validateListNameAndCode(ListName.TEMA.name(), filter.getTemaCode()); } return ResponseEntity.ok(new RestResponsePage<>(service.getByFilter(filter))); diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritering/KravPrioriteringService.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritering/KravPrioriteringService.java index 31c616f11..72c284d69 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritering/KravPrioriteringService.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritering/KravPrioriteringService.java @@ -1,5 +1,6 @@ package no.nav.data.etterlevelse.kravprioritering; +import lombok.RequiredArgsConstructor; import no.nav.data.common.rest.PageParameters; import no.nav.data.common.storage.domain.GenericStorage; import no.nav.data.etterlevelse.common.domain.DomainService; @@ -25,16 +26,12 @@ import static no.nav.data.common.storage.domain.GenericStorage.convertToDomaionObject; @Service +@RequiredArgsConstructor public class KravPrioriteringService extends DomainService { private final KravPrioriteringRepo repo; private final KravService kravService; - public KravPrioriteringService(KravPrioriteringRepo repo, KravService kravService) { - this.repo = repo; - this.kravService = kravService; - } - public Page getAll(PageParameters pageParameters) { return repo.findAll(pageParameters.createPage()).map(GenericStorage::getDomainObjectData); } @@ -67,7 +64,7 @@ public List getByFilter(KravPrioriteringFilter filter) List kravPrioriteringList = convertToDomaionObject(repo.findByKravNummer(filter.getKravNummer())).stream().map(KravPrioritering::toResponse).toList(); kravPrioriteringList.forEach(this::setKravStatus); return filterForKravStatus(kravPrioriteringList, filter); - } else if(filter.getTemaCode() != null) { + } else if (filter.getTemaCode() != null) { List kravPrioriteringerResp = convertToDomaionObject(repo.findByTema(filter.getTemaCode().substring(0, 3))).stream().map(KravPrioritering::toResponse).toList(); kravPrioriteringerResp.forEach(this::setKravStatus); return filterForKravStatus(kravPrioriteringerResp, filter); @@ -80,7 +77,7 @@ public List getByFilter(KravPrioriteringFilter filter) } private List filterForKravStatus(List kravPrioriteringResponse, KravPrioriteringFilter filter) { - if(filter.getKravStatus() != null) { + if (filter.getKravStatus() != null) { return kravPrioriteringResponse.stream().filter(kp-> kp.getKravStatus().equals(filter.getKravStatus())).toList(); } return kravPrioriteringResponse; @@ -88,17 +85,18 @@ private List filterForKravStatus(List krav = kravService.getByKravNummer(kravPrioriteringResponse.getKravNummer(), kravPrioriteringResponse.getKravVersjon()); - if(krav.isPresent()) { + if (krav.isPresent()) { kravPrioriteringResponse.setKravStatus(krav.get().getStatus()); } else { kravPrioriteringResponse.setKravStatus(KravStatus.UTGAATT); } } + @Transactional(propagation = Propagation.REQUIRED) public KravPrioritering save(KravPrioriteringRequest request) { var kravprioritering = request.isUpdate() ? storage.get(request.getIdAsUUID()) : new KravPrioritering(); - kravprioritering.convert(request); + kravprioritering.merge(request); return storage.save(kravprioritering); } diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritering/domain/KravPrioritering.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritering/domain/KravPrioritering.java index f459987f9..a8d7f5ee7 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritering/domain/KravPrioritering.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritering/domain/KravPrioritering.java @@ -22,8 +22,8 @@ public class KravPrioritering extends DomainObject implements KravId { private Integer kravVersjon; private String prioriteringsId; - - public KravPrioritering convert(KravPrioriteringRequest request) { + // Updates all fields from the request except id, version and changestamp + public KravPrioritering merge(KravPrioriteringRequest request) { kravNummer = request.getKravNummer(); kravVersjon = request.getKravVersjon(); prioriteringsId = request.getPrioriteringsId(); diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritering/domain/KravPrioriteringRepo.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritering/domain/KravPrioriteringRepo.java index 2e6e0e7a2..2efcb0de1 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritering/domain/KravPrioriteringRepo.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritering/domain/KravPrioriteringRepo.java @@ -1,6 +1,5 @@ package no.nav.data.etterlevelse.kravprioritering.domain; -import jakarta.transaction.Transactional; import no.nav.data.common.storage.domain.GenericStorage; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -32,7 +31,6 @@ public interface KravPrioriteringRepo extends JpaRepository> getAll(); @Modifying(clearAutomatically = true) - @Transactional @Query(value = "update generic_storage set DATA = jsonb_set(DATA, '{kravVersjon}', to_jsonb(?1) , false ) where data -> 'kravNummer' = to_jsonb(?2) and type = 'KravPrioritering'", nativeQuery = true) void transferPriority(int newKravVersjon, int kravNummer); } diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/melding/MeldingService.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/melding/MeldingService.java index 1b9a62a19..0c001f2cd 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/melding/MeldingService.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/melding/MeldingService.java @@ -1,5 +1,6 @@ package no.nav.data.etterlevelse.melding; +import lombok.RequiredArgsConstructor; import no.nav.data.common.rest.PageParameters; import no.nav.data.common.storage.domain.GenericStorage; import no.nav.data.etterlevelse.common.domain.DomainService; @@ -17,14 +18,11 @@ import static no.nav.data.common.storage.domain.GenericStorage.convertToDomaionObject; @Service +@RequiredArgsConstructor public class MeldingService extends DomainService { private final MeldingRepo repo; - public MeldingService(MeldingRepo repo) { - this.repo = repo; - } - public Page getAll(PageParameters pageParameters) { return repo.findAll(pageParameters.createPage()).map(GenericStorage::getDomainObjectData); } @@ -37,9 +35,10 @@ public List getByMeldingStatus(String meldingStatus) { return convertToDomaionObject(repo.findByMeldingStatus(meldingStatus)); } + @Transactional(propagation = Propagation.REQUIRED) public Melding save(MeldingRequest request) { var melding = request.isUpdate() ? storage.get(request.getIdAsUUID()) : new Melding(); - melding.convert(request); + melding.merge(request); return storage.save(melding); } diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/melding/domain/Melding.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/melding/domain/Melding.java index 5ba8ae854..4b1c0f57f 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/melding/domain/Melding.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/melding/domain/Melding.java @@ -23,7 +23,8 @@ public class Melding extends DomainObject { private MeldingStatus meldingStatus; private AlertType alertType; - public Melding convert(MeldingRequest request) { + // Updates all fields from the request except id, version and changestamp + public Melding merge(MeldingRequest request) { melding = request.getMelding(); secondaryTittel = request.getSecondaryTittel(); secondaryMelding = request.getSecondaryMelding(); diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/statistikk/StatistikkService.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/statistikk/StatistikkService.java index ec3c5466f..b196fb404 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/statistikk/StatistikkService.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/statistikk/StatistikkService.java @@ -1,5 +1,6 @@ package no.nav.data.etterlevelse.statistikk; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import no.nav.data.common.auditing.domain.Action; import no.nav.data.common.auditing.domain.AuditVersion; @@ -51,6 +52,7 @@ @Slf4j @Service +@RequiredArgsConstructor public class StatistikkService { private final TilbakemeldingService tilbakemeldingService; private final BehandlingService behandlingService; @@ -61,27 +63,11 @@ public class StatistikkService { private final AuditVersionRepository auditVersionRepository; - public StatistikkService(TilbakemeldingService tilbakemeldingService, - BehandlingService behandlingService, - KravService kravService, - EtterlevelseService etterlevelseService, - EtterlevelseDokumentasjonService etterlevelseDokumentasjonService, - TeamcatTeamClient teamService, - AuditVersionRepository auditVersionRepository) { - this.tilbakemeldingService = tilbakemeldingService; - this.behandlingService = behandlingService; - this.kravService = kravService; - this.etterlevelseService = etterlevelseService; - this.etterlevelseDokumentasjonService = etterlevelseDokumentasjonService; - this.teamService = teamService; - this.auditVersionRepository = auditVersionRepository; - } - - public int getAntallIkkeFiltrertKrav(List aktivKravList, EtterlevelseDokumentasjon etterlevelseDokumentasjon, List etterlevelseList) { - List valgteKrav = aktivKravList.stream().filter(krav -> !new HashSet<>(etterlevelseDokumentasjon.getIrrelevansFor()).containsAll(krav.getRelevansFor()) || krav.getRelevansFor().isEmpty() - ).toList(); + List valgteKrav = aktivKravList.stream() + .filter(krav -> !new HashSet<>(etterlevelseDokumentasjon.getIrrelevansFor()).containsAll(krav.getRelevansFor()) || krav.getRelevansFor().isEmpty()) + .toList(); return valgteKrav.size() + etterlevelseList.stream() @@ -242,7 +228,7 @@ public EtterlevelseStatistikkResponse toEtterlevelseStatistikkResponse(Etterleve String temaName = "Ingen"; var krav = kravService.getByKravNummer(etterlevelse.getKravNummer(), etterlevelse.getKravVersjon()); - if(krav.isPresent()) { + if (krav.isPresent()) { var regelverkResponse = StreamUtils.convert(krav.get().getRegelverk(), Regelverk::toResponse); if (!regelverkResponse.isEmpty()) { var temaData = CodelistService.getCodelist(ListName.TEMA, regelverkResponse.get(0).getLov().getData().get("tema").textValue()); @@ -252,9 +238,6 @@ public EtterlevelseStatistikkResponse toEtterlevelseStatistikkResponse(Etterleve } } - - - return EtterlevelseStatistikkResponse.builder() .id(etterlevelse.getId()) .etterlevelseDokumentasjonId(etterlevelse.getEtterlevelseDokumentasjonId()) @@ -333,7 +316,6 @@ public KravStatistikkResponse toKravStatestikkResponse(Krav krav) { } } - return KravStatistikkResponse.builder() .id(krav.getId()) .lastModifiedDate(krav.getChangeStamp().getLastModifiedDate().withNano(0)) diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/statistikk/domain/BehandlingStatistikk.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/statistikk/domain/BehandlingStatistikk.java index 9eca8f4b4..38f52f4e1 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/statistikk/domain/BehandlingStatistikk.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/statistikk/domain/BehandlingStatistikk.java @@ -30,22 +30,22 @@ public class BehandlingStatistikk { private Integer antallUnderArbeid; private Integer antallFerdigDokumentert; -public BehandligStatistikkResponse toResponse() { - return BehandligStatistikkResponse.builder() - .etterlevelseDokumentasjonsId(etterlevelseDokumentasjonsId) - .etterlevelseDokumentasjonTittel(etterlevelseDokumentasjonTittel) - .behandlingId(behandlingId) - .behandlingNavn(behandlingNavn) - .team(copyOf(team)) - .teamId(copyOf(teamId)) - .opprettetDato(opprettetDato) - .endretDato(endretDato) - .totalKrav(totalKrav) - .antallIkkeFiltrertKrav(antallIkkeFiltrertKrav) - .antallBortfiltrertKrav(antallBortfiltrertKrav) - .antallIkkePaabegynt(antallIkkePaabegynt) - .antallUnderArbeid(antallUnderArbeid) - .antallFerdigDokumentert(antallFerdigDokumentert) - .build(); -} + public BehandligStatistikkResponse toResponse() { + return BehandligStatistikkResponse.builder() + .etterlevelseDokumentasjonsId(etterlevelseDokumentasjonsId) + .etterlevelseDokumentasjonTittel(etterlevelseDokumentasjonTittel) + .behandlingId(behandlingId) + .behandlingNavn(behandlingNavn) + .team(copyOf(team)) + .teamId(copyOf(teamId)) + .opprettetDato(opprettetDato) + .endretDato(endretDato) + .totalKrav(totalKrav) + .antallIkkeFiltrertKrav(antallIkkeFiltrertKrav) + .antallBortfiltrertKrav(antallBortfiltrertKrav) + .antallIkkePaabegynt(antallIkkePaabegynt) + .antallUnderArbeid(antallUnderArbeid) + .antallFerdigDokumentert(antallFerdigDokumentert) + .build(); + } } diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/virkemiddel/VirkemiddelService.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/virkemiddel/VirkemiddelService.java index e7d39843f..89ae25e99 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/virkemiddel/VirkemiddelService.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/virkemiddel/VirkemiddelService.java @@ -1,5 +1,6 @@ package no.nav.data.etterlevelse.virkemiddel; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import no.nav.data.common.storage.domain.GenericStorage; import no.nav.data.common.validator.Validator; @@ -25,16 +26,12 @@ @Slf4j @Service +@RequiredArgsConstructor public class VirkemiddelService extends DomainService { private final EtterlevelseDokumentasjonService etterlevelseDokumentasjonService; private final KravService kravService; - public VirkemiddelService(EtterlevelseDokumentasjonService etterlevelseDokumentasjonService, KravService kravService) { - this.etterlevelseDokumentasjonService = etterlevelseDokumentasjonService; - this.kravService = kravService; - } - private void validateVirkemiddelIsNotInUse(UUID virkemiddelId) { Virkemiddel virkemiddel = storage.get(virkemiddelId); List etterlevelseDokumentasjonList = etterlevelseDokumentasjonService.getByVirkemiddelId(List.of(virkemiddelId.toString())).stream().map((e)-> 'E' + e.getEtterlevelseNummer().toString()).toList(); @@ -61,14 +58,15 @@ public List getByVirkemiddelType(String code) { return convert(virkemiddelRepo.findByVirkemiddelType(code), GenericStorage::getDomainObjectData); } + @Transactional(propagation = Propagation.REQUIRED) public Virkemiddel save(VirkemiddelRequest request) { - Validator.validate(request, storage) + Validator.validate(request, storage::get) .addValidations(this::validateName) .ifErrorsThrowValidationException(); var virkemiddel = request.isUpdate() ? storage.get(request.getIdAsUUID()) : new Virkemiddel(); - virkemiddel.convert(request); + virkemiddel.merge(request); return storage.save(virkemiddel); } diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/virkemiddel/domain/Virkemiddel.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/virkemiddel/domain/Virkemiddel.java index 219fbde69..3c0a246f1 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/virkemiddel/domain/Virkemiddel.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/virkemiddel/domain/Virkemiddel.java @@ -31,7 +31,8 @@ public class Virkemiddel extends DomainObject { private List regelverk; private String livsSituasjon; - public Virkemiddel convert(VirkemiddelRequest request) { + // Updates all fields from the request except id, version and changestamp + public Virkemiddel merge(VirkemiddelRequest request) { navn = request.getNavn(); virkemiddelType = request.getVirkemiddelType(); regelverk = StreamUtils.convert(request.getRegelverk(), Regelverk::convert); diff --git a/apps/backend/src/main/java/no/nav/data/integration/behandling/BehandlingService.java b/apps/backend/src/main/java/no/nav/data/integration/behandling/BehandlingService.java index 143eab90d..9baf6cc6f 100644 --- a/apps/backend/src/main/java/no/nav/data/integration/behandling/BehandlingService.java +++ b/apps/backend/src/main/java/no/nav/data/integration/behandling/BehandlingService.java @@ -20,6 +20,7 @@ public class BehandlingService { private final BkatClient bkatClient; + public Behandling getBehandling(String id) { BkatProcess process = bkatClient.getProcess(id); if (process == null) { diff --git a/apps/backend/src/test/java/no/nav/data/etterlevelse/codelist/CodelistControllerIT.java b/apps/backend/src/test/java/no/nav/data/etterlevelse/codelist/CodelistControllerIT.java index c569ef54f..e6350f106 100644 --- a/apps/backend/src/test/java/no/nav/data/etterlevelse/codelist/CodelistControllerIT.java +++ b/apps/backend/src/test/java/no/nav/data/etterlevelse/codelist/CodelistControllerIT.java @@ -35,7 +35,6 @@ class CodelistControllerIT extends IntegrationTestBase { private static final ParameterizedTypeReference> CODELIST_LIST_RESP = new ParameterizedTypeReference<>() { }; - private static final String ERROR_IMMUTABLE_CODELIST = "%s is an immutable type of codelist. For amendments, please contact team #dataplatform"; @Autowired protected TestRestTemplate restTemplate; @@ -248,7 +247,7 @@ void shouldThrowCodelistNotErasableException_whenCodelistToBeDeletedIsStillInUse ResponseEntity responseEntity = restTemplate.exchange("/codelist/RELEVANS/DELETE_CODE", HttpMethod.DELETE, HttpEntity.EMPTY, String.class); - assertThat(responseEntity.getStatusCodeValue()).isEqualTo(HttpStatus.CONFLICT.value()); + assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.CONFLICT); assertThat(responseEntity.getBody()).contains("The code DELETE_CODE in list RELEVANS cannot be erased."); assertTrue(repository.findByListAndCode(ListName.RELEVANS, "DELETE_CODE").isPresent()); } diff --git a/apps/backend/src/test/java/no/nav/data/graphql/GraphQLTestBase.java b/apps/backend/src/test/java/no/nav/data/graphql/GraphQLTestBase.java index 01b5f043a..717eef609 100644 --- a/apps/backend/src/test/java/no/nav/data/graphql/GraphQLTestBase.java +++ b/apps/backend/src/test/java/no/nav/data/graphql/GraphQLTestBase.java @@ -1,6 +1,6 @@ package no.nav.data.graphql; -import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; import com.fasterxml.jackson.databind.node.ObjectNode; import com.graphql.spring.boot.test.GraphQLTestTemplate; import no.nav.data.IntegrationTestBase; @@ -11,17 +11,16 @@ public abstract class GraphQLTestBase extends IntegrationTestBase { - private final ObjectMapper om = JsonUtils.getObjectMapper(); - @Autowired protected GraphQLTestTemplate graphQLTestTemplate; protected ObjectNode vars() { - return om.createObjectNode(); + ObjectReader or = JsonUtils.getObjectReader(); + return or.getConfig().getNodeFactory().objectNode(); } protected ObjectNode vars(Map map) { - var on = om.createObjectNode(); + var on = vars(); map.forEach((key, val) -> on.set(key, JsonUtils.toJsonNode(val))); return on; } From 5c91112ade3c21e313d159e83f2dfccf228125ed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Mar 2024 04:57:27 +0000 Subject: [PATCH 006/107] Bump org.testcontainers:testcontainers in /apps/backend Bumps [org.testcontainers:testcontainers](https://github.com/testcontainers/testcontainers-java) from 1.19.6 to 1.19.7. - [Release notes](https://github.com/testcontainers/testcontainers-java/releases) - [Changelog](https://github.com/testcontainers/testcontainers-java/blob/main/CHANGELOG.md) - [Commits](https://github.com/testcontainers/testcontainers-java/compare/1.19.6...1.19.7) --- updated-dependencies: - dependency-name: org.testcontainers:testcontainers dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- apps/backend/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/backend/pom.xml b/apps/backend/pom.xml index 0bc5289be..157d5a8bb 100644 --- a/apps/backend/pom.xml +++ b/apps/backend/pom.xml @@ -37,7 +37,7 @@ 24.1.0 - 1.19.6 + 1.19.7 2.27.2 11.4.9 From 41f56679907743b723029bdef3c0129fbdd752bd Mon Sep 17 00:00:00 2001 From: JeremiahUy Date: Wed, 6 Mar 2024 10:01:49 +0100 Subject: [PATCH 007/107] UPDATE: constructor requirements --- .../kravprioritylist/KravPriorityListService.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListService.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListService.java index befe31aa7..2e178a6b3 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListService.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListService.java @@ -1,5 +1,6 @@ package no.nav.data.etterlevelse.kravprioritylist; +import lombok.RequiredArgsConstructor; import no.nav.data.common.rest.PageParameters; import no.nav.data.common.storage.domain.GenericStorage; import no.nav.data.etterlevelse.common.domain.DomainService; @@ -15,14 +16,11 @@ import java.util.UUID; @Service +@RequiredArgsConstructor public class KravPriorityListService extends DomainService { private final KravPriorityListRepo repo; - public KravPriorityListService(KravPriorityListRepo repo) { - this.repo = repo; - } - public Page getAll(PageParameters pageParameters) { return repo.findAll(pageParameters.createPage()).map(GenericStorage::getDomainObjectData); } From 70339ef3b61fc9c7bddef04a7942ea3de5da27ea Mon Sep 17 00:00:00 2001 From: JeremiahUy Date: Wed, 6 Mar 2024 10:18:57 +0100 Subject: [PATCH 008/107] ADD: constant and api for krav priority list --- apps/frontend/src/api/KravPriorityListApi.ts | 86 ++++++++++++++++++++ apps/frontend/src/constants.ts | 6 ++ 2 files changed, 92 insertions(+) create mode 100644 apps/frontend/src/api/KravPriorityListApi.ts diff --git a/apps/frontend/src/api/KravPriorityListApi.ts b/apps/frontend/src/api/KravPriorityListApi.ts new file mode 100644 index 000000000..07f445604 --- /dev/null +++ b/apps/frontend/src/api/KravPriorityListApi.ts @@ -0,0 +1,86 @@ +import axios from 'axios' +import { IKravPriorityList, IPageResponse } from '../constants' +import { env } from '../util/env' + +export const getAllKravPriorityList = async () => { + const PAGE_SIZE = 100 + const firstPage = await getKravPriorityListPage(0, PAGE_SIZE) + if (firstPage.pages === 1) { + return firstPage.content.length > 0 ? [...firstPage.content] : [] + } else { + let allKravPrioritering: IKravPriorityList[] = [...firstPage.content] + for (let currentPage = 1; currentPage < firstPage.pages; currentPage++) { + allKravPrioritering = [ + ...allKravPrioritering, + ...(await getKravPriorityListPage(currentPage, PAGE_SIZE)).content, + ] + } + return allKravPrioritering + } +} + +export const getKravPriorityListPage = async (pageNumber: number, pageSize: number) => { + return ( + await axios.get>( + `${env.backendBaseUrl}/kravprioritylist?pageNumber=${pageNumber}&pageSize=${pageSize}` + ) + ).data +} + +export const getKravPriorityList = async (id: string) => { + return (await axios.get(`${env.backendBaseUrl}/kravprioritylist/${id}`)).data +} + +export const getKravPriorityListByTemaCode = async (temaCode: string) => { + return await axios + .get(`${env.backendBaseUrl}/kravprioritylist/tema/${temaCode}`) + .then((resp) => { + return resp.data + }) + .catch(() => { + return undefined + }) +} + +export const getKravPriorityListByKravNummerAndTemaCode = async ( + temaCode: string, + kravNummer: number +) => { + return await axios.get>( + `${env.backendBaseUrl}/kravprioritylist/tema/${temaCode}/${kravNummer}` + ) +} + +export const createKravPriorityList = async (kravPrioritering: IKravPriorityList) => { + const dto = kravPrioriteringToDto(kravPrioritering) + return (await axios.post(`${env.backendBaseUrl}/kravprioritylist`, dto)).data +} + +export const updateKravPriorityList = async (kravPrioritering: IKravPriorityList) => { + const dto = kravPrioriteringToDto(kravPrioritering) + return ( + await axios.put( + `${env.backendBaseUrl}/kravprioritylist/${kravPrioritering.id}`, + dto + ) + ).data +} + +function kravPrioriteringToDto(kravPrioriteringToDto: IKravPriorityList): IKravPriorityList { + const dto = { + ...kravPrioriteringToDto, + } as any + delete dto.changeStamp + delete dto.version + return dto +} + +export const kravPrioritingMapToFormValue = ( + kravprioritylist: Partial +): IKravPriorityList => ({ + id: kravprioritylist.id || '', + temaId: kravprioritylist.temaId || '', + priorityList: kravprioritylist.priorityList || [], + changeStamp: kravprioritylist.changeStamp || { lastModifiedDate: '', lastModifiedBy: '' }, + version: -1, +}) diff --git a/apps/frontend/src/constants.ts b/apps/frontend/src/constants.ts index 804a45745..d715a8f87 100644 --- a/apps/frontend/src/constants.ts +++ b/apps/frontend/src/constants.ts @@ -170,6 +170,12 @@ export interface IKravPrioritering extends IDomainObject { prioriteringsId: string } +export interface IKravPriorityList extends IDomainObject { + id: string + temaId: string + priorityList: number[] +} + export interface IBreadCrumbPath { href: string pathName: string From 30250e71a31c897814a69e4915053be7242af832 Mon Sep 17 00:00:00 2001 From: JeremiahUy Date: Wed, 6 Mar 2024 10:44:06 +0100 Subject: [PATCH 009/107] UPDATE: controller to have crud operations --- .../KravPriorityListController.java | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListController.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListController.java index 8c1506ac4..51c3441c0 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListController.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListController.java @@ -3,6 +3,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import no.nav.data.common.exceptions.ValidationException; @@ -11,15 +12,23 @@ import no.nav.data.etterlevelse.codelist.CodelistService; import no.nav.data.etterlevelse.codelist.domain.ListName; import no.nav.data.etterlevelse.kravprioritylist.domain.KravPriorityList; +import no.nav.data.etterlevelse.kravprioritylist.dto.KravPriorityListRequest; import no.nav.data.etterlevelse.kravprioritylist.dto.KravPriorityListResponse; import org.springframework.data.domain.Page; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.Objects; import java.util.Optional; +import java.util.UUID; @Slf4j @RequiredArgsConstructor @@ -88,4 +97,44 @@ public ResponseEntity getByTemaCodeAndKravNummer(@PathVariable String t return ResponseEntity.ok(kravPriority); } + + @Operation(summary = "Get one krav priority list") + @ApiResponse(description = "ok") + @GetMapping("/{id}") + public ResponseEntity getById(@PathVariable UUID id) { + log.info("Get krav priority list id={}", id); + return ResponseEntity.ok(service.get(id).toResponse()); + } + + @Operation(summary = "Create krav prioritering") + @ApiResponse(description = "ok") + @PostMapping + public ResponseEntity createKravPriorityList(@RequestBody KravPriorityListRequest request) { + log.info("Create krav priority list"); + var kravPriorityList = service.save(request); + return new ResponseEntity<>(kravPriorityList.toResponse(), HttpStatus.CREATED); + } + + @Operation(summary = "Update krav prioritering") + @ApiResponse(description = "ok") + @PutMapping("/{id}") + public ResponseEntity updateKravPriorityList(@PathVariable UUID id,@Valid @RequestBody KravPriorityListRequest request) { + log.info("Update krav priority list id={}", id); + + if (!Objects.equals(id, request.getIdAsUUID())) { + throw new ValidationException(String.format("id mismatch in request %s and path %s", request.getId(), id)); + } + + var kravPriorityList = service.save(request); + return ResponseEntity.ok(kravPriorityList.toResponse()); + } + + @Operation(summary = "Delete krav prioritering") + @ApiResponse(description = "ok") + @DeleteMapping("/{id}") + public ResponseEntity deleteKravPriorityList(@PathVariable UUID id) { + log.info("Delete krav priority list id={}", id); + var kravPriorityList = service.delete(id); + return ResponseEntity.ok(kravPriorityList.toResponse()); + } } From 0c83304031b4f06d318cde644f802e8d0e3421e9 Mon Sep 17 00:00:00 2001 From: JeremiahUy Date: Wed, 6 Mar 2024 11:22:32 +0100 Subject: [PATCH 010/107] ADD: krav priority list to audit list --- apps/frontend/src/components/admin/audit/AuditTypes.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/frontend/src/components/admin/audit/AuditTypes.ts b/apps/frontend/src/components/admin/audit/AuditTypes.ts index c0f57be42..96e0a2509 100644 --- a/apps/frontend/src/components/admin/audit/AuditTypes.ts +++ b/apps/frontend/src/components/admin/audit/AuditTypes.ts @@ -24,6 +24,7 @@ export enum EAuditAction { export enum EObjectType { Codelist = 'CODELIST', Krav = 'Krav', + KravPriorityList = 'KravPriorityList', Etterlevelse = 'Etterlevelse', Behandling = 'Behandling', EtterlevelseDokumentasjon = 'EtterlevelseDokumentasjon', From b48d18566e2af094483066406deb30837f34db40 Mon Sep 17 00:00:00 2001 From: JeremiahUy Date: Wed, 6 Mar 2024 11:23:06 +0100 Subject: [PATCH 011/107] ADD: hook for using krav priority list --- apps/frontend/src/api/KravPriorityListApi.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/apps/frontend/src/api/KravPriorityListApi.ts b/apps/frontend/src/api/KravPriorityListApi.ts index 07f445604..b980b1e9a 100644 --- a/apps/frontend/src/api/KravPriorityListApi.ts +++ b/apps/frontend/src/api/KravPriorityListApi.ts @@ -1,4 +1,5 @@ import axios from 'axios' +import { useEffect, useState } from 'react' import { IKravPriorityList, IPageResponse } from '../constants' import { env } from '../util/env' @@ -66,6 +67,23 @@ export const updateKravPriorityList = async (kravPrioritering: IKravPriorityList ).data } +export const useKravPriorityList = (temaCode: string) => { + const [data, setData] = useState(kravPrioritingMapToFormValue({})) + const [loading, setLoading] = useState(false) + + useEffect(() => { + setLoading(true) + getKravPriorityListByTemaCode(temaCode).then((response: IKravPriorityList | undefined) => { + if (response) { + setData(kravPrioritingMapToFormValue(response)) + } + }) + setLoading(false) + }, [temaCode]) + + return [data, loading] as [IKravPriorityList, boolean] +} + function kravPrioriteringToDto(kravPrioriteringToDto: IKravPriorityList): IKravPriorityList { const dto = { ...kravPrioriteringToDto, From dacff5fd1e9c2ae238bd186b0f766bb3708aeb3c Mon Sep 17 00:00:00 2001 From: JeremiahUy Date: Wed, 6 Mar 2024 11:23:43 +0100 Subject: [PATCH 012/107] UPDATE: implement copying of krav priority --- .../src/components/kravList/TemaList.tsx | 5 ++- .../kravList/edit/EditPriorityModal.tsx | 43 +++++++++++++++++-- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/apps/frontend/src/components/kravList/TemaList.tsx b/apps/frontend/src/components/kravList/TemaList.tsx index da1a3f1c6..e290abb0a 100644 --- a/apps/frontend/src/components/kravList/TemaList.tsx +++ b/apps/frontend/src/components/kravList/TemaList.tsx @@ -64,6 +64,7 @@ export const TemaList = () => { @@ -122,11 +123,12 @@ const getKravTemaRowsWithLabel = (kravListe: IKrav[], tema: string) => { const KravTemaList = (props: { activeKraver: IKrav[] tema: string + temaCode: string refresh: () => void draftKrav: IKrav[] }) => { const [isEditPriorityModalOpen, setIsEditPriorityModalOpen] = React.useState(false) - const { activeKraver, tema, refresh, draftKrav } = props + const { activeKraver, tema, temaCode, refresh, draftKrav } = props return (
@@ -142,6 +144,7 @@ const KravTemaList = (props: { {activeKraver && isEditPriorityModalOpen && ( > kravListe: IKrav[] tema: string + temaCode: string refresh: () => void }) => { - const { isOpen, setIsOpen, kravListe, tema, refresh } = props + const { isOpen, setIsOpen, kravListe, tema, temaCode, refresh } = props const [loading, setLoading] = React.useState(false) + const [kravPriorityList, kravPriorityLoading] = useKravPriorityList(temaCode) + const setPriority = (kravListe: IKrav[]) => { const pattern = new RegExp(tema.substr(0, 3).toUpperCase() + '[0-9]+') @@ -65,7 +73,9 @@ export const EditPriorityModal = (props: { } else { return { ...krav, - prioriteringsId: krav.prioriteringsId.concat(tema.substring(0, 3).toUpperCase() + number), + prioriteringsId: krav.prioriteringsId.concat( + tema.substring(0, 3).toUpperCase() + number + ), } } } @@ -74,6 +84,29 @@ export const EditPriorityModal = (props: { const submit = ({ krav }: { krav: IKrav[] }) => { setLoading(true) + + if (!kravPriorityLoading) { + if (kravPriorityList && kravPriorityList.id) { + ;(async () => + await updateKravPriorityList({ + id: kravPriorityList.id, + temaId: temaCode, + priorityList: krav.map((krav) => krav.kravNummer), + changeStamp: kravPriorityList.changeStamp, + version: kravPriorityList.version, + }))() + } else { + ;(async () => + await createKravPriorityList({ + id: '', + temaId: temaCode, + priorityList: krav.map((krav) => krav.kravNummer), + changeStamp: { lastModifiedDate: '', lastModifiedBy: '' }, + version: -1, + }))() + } + } + const updateKravPriorityPromise: Promise[] = [] const kravMedPrioriteting = setPriority([...krav]) kravMedPrioriteting.forEach((kmp) => { @@ -130,7 +163,11 @@ export const EditPriorityModal = (props: { {!loading && kravListe && (
- {(fieldArrayRenderProps: FieldArrayRenderProps) => } + + {(fieldArrayRenderProps: FieldArrayRenderProps) => ( + + )} +
)} From 1f772f8944eaf15fad352be9deb843207d8ab11e Mon Sep 17 00:00:00 2001 From: JeremiahUy Date: Wed, 6 Mar 2024 11:26:39 +0100 Subject: [PATCH 013/107] FIX: key error on list --- apps/frontend/src/components/kravList/TemaList.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/frontend/src/components/kravList/TemaList.tsx b/apps/frontend/src/components/kravList/TemaList.tsx index e290abb0a..5974bf31b 100644 --- a/apps/frontend/src/components/kravList/TemaList.tsx +++ b/apps/frontend/src/components/kravList/TemaList.tsx @@ -53,7 +53,7 @@ export const TemaList = () => { .includes(tema.code) }) return activeKraver && activeKraver.length > 0 ? ( - + { ) : ( - + From 67f5468d732a8558ffc8f8f391f22fc49f102256 Mon Sep 17 00:00:00 2001 From: JeremiahUy Date: Wed, 6 Mar 2024 11:32:20 +0100 Subject: [PATCH 014/107] REMOVE: tema code length validation --- .../kravprioritylist/KravPriorityListController.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListController.java b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListController.java index 51c3441c0..b782c557b 100644 --- a/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListController.java +++ b/apps/backend/src/main/java/no/nav/data/etterlevelse/kravprioritylist/KravPriorityListController.java @@ -57,9 +57,6 @@ public ResponseEntity> getAll( @GetMapping("/tema/{temacode}") public ResponseEntity getByTemaCode(@PathVariable String temacode) { log.info("Get krav prioritering for tema={}", temacode); - if(temacode.length() < 3) { - throw new ValidationException("Tema code must be more than 3 characters"); - } codelistService.validateListNameAndCode(ListName.TEMA.name(), temacode); @@ -73,9 +70,6 @@ public ResponseEntity getByTemaCode(@PathVariable Stri @GetMapping("/tema/{temacode}/{kravnummer}") public ResponseEntity getByTemaCodeAndKravNummer(@PathVariable String temacode, @PathVariable Integer kravnummer) { log.info("Get krav prioritering for tema={}", temacode); - if(temacode.length() < 3) { - throw new ValidationException("Tema code must be more than 3 characters"); - } codelistService.validateListNameAndCode(ListName.TEMA.name(), temacode); From 4f54306df506f0a14a9edbb74a50616ec2dd3c8d Mon Sep 17 00:00:00 2001 From: Jeremiah Uy Date: Thu, 7 Mar 2024 11:33:06 +0100 Subject: [PATCH 015/107] Remove baseui (#859) * Remove baseui * Remove: unused settings page * Remove: unused settings page Co-authored-by: Jeremiah Uy * Remove: unused baseui custom button Co-authored-by: Jeremiah Uy * Remove: customized link Co-authored-by: Jeremiah Uy * Remove: baseui and unused code. Co-authored-by: Jeremiah Uy * Remove: baseui and customizedSelect Co-authored-by: Jeremiah Uy * Remove: icon, PanelLink, TeamaCardEtterlevelseDokumentasjon, TemaPage Co-authored-by: Jeremiah Uy * Update: import Co-authored-by: Jeremiah Uy * Update: ArkiveringModal to use nav design system. Co-authored-by: Jeremiah Uy * Remove: unsed code utils.tsx Co-authored-by: Jeremiah Uy * Remove: unused code Co-authored-by: Jeremiah Uy * Change: baseui to nav desgin system Co-authored-by: Jeremiah Uy Co-authored-by: Rebecca Gjerstad * REMOVE: unused component and theme clean up * REMOVE: unused component and hooks clean up * REMOVE: baseui from edit virkemiddel modal * REMOVE: unused burger menu * REMOVE: fix more hooks import and update option type * Change: baseui to nav desgin system Co-authored-by: Jeremiah Uy Co-authored-by: Rebecca Gjerstad * REMOVE: unused export in image * REMOVE: fix more hooks import and remove unused files * REMOVE: fix more hooks import and remove unused files * REMOVE: unused files * REMOVE: unused files * Update: Hook import Co-authored-by: Jeremiah Uy Co-authored-by: Rebecca Gjerstad * REMOVE: unused files * REMOVE: fix more hooks import * Update: Hook import Co-authored-by: Jeremiah Uy Co-authored-by: Rebecca Gjerstad * UPDATE: option field logic to use value vs id * FIX: empty input field on submit * FIX: option typing and small styling on admin pages Co-authored-by: andregroseth Co-authored-by: beeccy --------- Co-authored-by: Lord Andre Groseth Co-authored-by: Rebecca Gjerstad Co-authored-by: andregroseth --- apps/frontend/package.json | 1 - apps/frontend/src/AppRoutes.tsx | 6 - apps/frontend/src/api/BehandlingApi.ts | 2 +- apps/frontend/src/api/TeamApi.ts | 11 +- apps/frontend/src/api/VirkemiddelApi.ts | 2 +- apps/frontend/src/components/Chart.tsx | 316 ---------- apps/frontend/src/components/Header.tsx | 2 +- apps/frontend/src/components/Images.tsx | 46 -- apps/frontend/src/components/Lov.tsx | 9 +- .../components/Navigation/Burger/index.tsx | 265 -------- .../admin/CodeList/CodelistPage.tsx | 6 +- .../src/components/admin/audit/AuditPage.tsx | 2 +- .../admin/audit/AuditRecentTable.tsx | 6 +- .../src/components/admin/audit/AuditView.tsx | 2 +- .../components/admin/settings/SettingsApi.ts | 14 - .../admin/settings/SettingsPage.tsx | 93 --- .../src/components/behandling/utils.tsx | 66 -- .../frontend/src/components/common/Button.tsx | 213 ------- .../components/common/CustomizedAccordion.tsx | 125 ---- .../src/components/common/CustomizedInput.tsx | 23 - .../src/components/common/CustomizedLink.tsx | 19 - .../src/components/common/CustomizedModal.tsx | 46 -- .../components/common/CustomizedSelect.tsx | 50 -- .../common/CustomizedStatefulTooltip.tsx | 33 - .../src/components/common/CustomizedTabs.tsx | 143 ----- .../src/components/common/CustomizedTag.tsx | 29 - .../components/common/CustomizedTextarea.tsx | 29 - apps/frontend/src/components/common/Icon.tsx | 12 +- .../frontend/src/components/common/Inputs.tsx | 95 +-- .../src/components/common/PanelLink.tsx | 594 ------------------ .../components/common/RearrangeButtons.tsx | 9 +- .../src/components/common/RouteLink.tsx | 3 +- .../src/components/common/SimpleTag.tsx | 50 -- .../common/TextEditor/TextEditor.tsx | 2 +- .../Edit/SuksesskriterieBegrunnelseEdit.tsx | 2 +- .../ArkiveringModal.tsx | 20 +- .../HeaderContent.tsx | 67 -- .../KravPanelHeader.tsx | 83 --- .../TemaCardEtterlevelseDokumentasjon.tsx | 163 ----- .../common/utils.tsx | 230 +------ .../tabs/AlleEtterlevelsesDokumentasjoner.tsx | 2 +- .../tabs/MineEtterlevelseDokumentasjoner.tsx | 4 +- .../tabs/SisteEtterlevelseDokumentasjoner.tsx | 5 +- .../KravList.tsx | 95 --- .../etterlevelseMetadata/EditNotatfelt.tsx | 2 +- .../etterlevelseMetadata/TildeltPopover.tsx | 126 ---- .../export/ExportEtterlevelseModal.tsx | 45 +- .../krav/Edit/KravEditVirkemidler.tsx | 22 +- .../krav/Edit/KravSuksesskriterieEdit.tsx | 2 +- .../krav/tilbakemelding/Tilbakemelding.tsx | 2 +- .../src/components/kravList/AllKrav.tsx | 37 +- .../src/components/varslinger/EditMelding.tsx | 2 +- .../varslinger/EditOmEtterlevelse.tsx | 2 +- .../virkemiddel/edit/EditVirkemiddelModal.tsx | 74 +-- .../virkemiddelList/AllVirkemiddel.tsx | 2 +- apps/frontend/src/constants.ts | 2 +- apps/frontend/src/main.tsx | 6 +- apps/frontend/src/pages/ArkivAdminPage.tsx | 13 +- apps/frontend/src/pages/KravPage.tsx | 2 +- apps/frontend/src/pages/TemaPage.tsx | 120 +--- apps/frontend/src/services/Codelist.ts | 6 +- apps/frontend/src/services/User.ts | 2 +- apps/frontend/src/util/hooks/index.ts | 2 - apps/frontend/src/util/hooks/table.ts | 216 ------- apps/frontend/src/util/index.tsx | 3 - apps/frontend/src/util/intl/intl.ts | 2 +- apps/frontend/src/util/theme.ts | 204 ------ 67 files changed, 148 insertions(+), 3741 deletions(-) delete mode 100644 apps/frontend/src/components/Chart.tsx delete mode 100644 apps/frontend/src/components/Navigation/Burger/index.tsx delete mode 100644 apps/frontend/src/components/admin/settings/SettingsApi.ts delete mode 100644 apps/frontend/src/components/admin/settings/SettingsPage.tsx delete mode 100644 apps/frontend/src/components/behandling/utils.tsx delete mode 100644 apps/frontend/src/components/common/Button.tsx delete mode 100644 apps/frontend/src/components/common/CustomizedAccordion.tsx delete mode 100644 apps/frontend/src/components/common/CustomizedInput.tsx delete mode 100644 apps/frontend/src/components/common/CustomizedLink.tsx delete mode 100644 apps/frontend/src/components/common/CustomizedModal.tsx delete mode 100644 apps/frontend/src/components/common/CustomizedSelect.tsx delete mode 100644 apps/frontend/src/components/common/CustomizedStatefulTooltip.tsx delete mode 100644 apps/frontend/src/components/common/CustomizedTabs.tsx delete mode 100644 apps/frontend/src/components/common/CustomizedTag.tsx delete mode 100644 apps/frontend/src/components/common/CustomizedTextarea.tsx delete mode 100644 apps/frontend/src/components/common/PanelLink.tsx delete mode 100644 apps/frontend/src/components/common/SimpleTag.tsx delete mode 100644 apps/frontend/src/components/etterlevelseDokumentasjon/HeaderContent.tsx delete mode 100644 apps/frontend/src/components/etterlevelseDokumentasjon/TemaCardEtterlevelseDokumentasjon.tsx delete mode 100644 apps/frontend/src/components/etterlevelseDokumentasjonTema/KravList.tsx delete mode 100644 apps/frontend/src/components/etterlevelseMetadata/TildeltPopover.tsx delete mode 100644 apps/frontend/src/util/hooks/index.ts delete mode 100644 apps/frontend/src/util/hooks/table.ts delete mode 100644 apps/frontend/src/util/index.tsx diff --git a/apps/frontend/package.json b/apps/frontend/package.json index 52a39fb87..96118879b 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -19,7 +19,6 @@ "@types/react-draft-wysiwyg": "^1.13.5", "amplitude-js": "^8.21.9", "axios": "^1.5.1", - "baseui": "^13.0.0", "core-js": "^3.32.2", "depcheck": "^1.4.7", "draft-js": "^0.11.7", diff --git a/apps/frontend/src/AppRoutes.tsx b/apps/frontend/src/AppRoutes.tsx index 12e19a7fe..d5657ec8d 100644 --- a/apps/frontend/src/AppRoutes.tsx +++ b/apps/frontend/src/AppRoutes.tsx @@ -5,7 +5,6 @@ import { searchEtterlevelsedokumentasjonByBehandlingId } from './api/Etterlevels import CodeListPage from './components/admin/CodeList/CodelistPage' import { AuditPage } from './components/admin/audit/AuditPage' import { MailLogPage } from './components/admin/maillog/MailLogPage' -import { SettingsPage } from './components/admin/settings/SettingsPage' import { KravCreatePage } from './components/krav/Edit/KravCreatePage' import { KravEditPage } from './components/krav/Edit/KravEditPage' import { KravNyVersjonPage } from './components/krav/Edit/KravNyVersjonPage' @@ -177,11 +176,6 @@ const AppRoutes = (): JSX.Element => { caseSensitive={true} /> - } adminPage />} - caseSensitive={true} - /> } adminPage />} diff --git a/apps/frontend/src/api/BehandlingApi.ts b/apps/frontend/src/api/BehandlingApi.ts index ab51cc64d..d20885c55 100644 --- a/apps/frontend/src/api/BehandlingApi.ts +++ b/apps/frontend/src/api/BehandlingApi.ts @@ -2,7 +2,7 @@ import axios from 'axios' import { useEffect, useState } from 'react' import { IBehandling, IPageResponse } from '../constants' import { env } from '../util/env' -import { useSearch } from '../util/hooks' +import { useSearch } from '../util/hooks/customHooks' export const getBehandling = async (id: string) => { return (await axios.get(`${env.backendBaseUrl}/behandling/${id}`)).data diff --git a/apps/frontend/src/api/TeamApi.ts b/apps/frontend/src/api/TeamApi.ts index 00fc01f41..ca6199954 100644 --- a/apps/frontend/src/api/TeamApi.ts +++ b/apps/frontend/src/api/TeamApi.ts @@ -1,6 +1,5 @@ import axios from 'axios' -import { Option } from 'baseui/select' -import { Dispatch, SetStateAction, useEffect, useState } from 'react' +import { useEffect, useState } from 'react' import { IPageResponse, IProductArea, @@ -11,7 +10,7 @@ import { } from '../constants' import { user } from '../services/User' import { env } from '../util/env' -import { useForceUpdate, useSearch } from '../util/hooks' +import { useForceUpdate, useSearch } from '../util/hooks/customHooks' export const getResourceById = async (resourceId: string) => { return (await axios.get(`${env.backendBaseUrl}/team/resource/${resourceId}`)).data @@ -170,7 +169,9 @@ export const useMyTeams = () => { if (teamListe.length === 0) { getAllTeams().then((response) => { const teamList = productAreas - .map((productArea) => response.filter((team) => productArea.id === team.productAreaId)) + .map((productArea) => + response.filter((team) => productArea.id === team.productAreaId) + ) .flat() const uniqueValuesSet = new Set() @@ -220,8 +221,6 @@ export const useMyProductAreas = () => { return [data, loading] as [IProductArea[], boolean] } -export type TSearchType = [Option[], Dispatch>, boolean] - export const usePersonSearch = async (searchParam: string) => { if (searchParam && searchParam.replace(/ /g, '').length > 2) { const searchResult = await searchResourceByName(searchParam) diff --git a/apps/frontend/src/api/VirkemiddelApi.ts b/apps/frontend/src/api/VirkemiddelApi.ts index 01d189cd6..de75b80e7 100644 --- a/apps/frontend/src/api/VirkemiddelApi.ts +++ b/apps/frontend/src/api/VirkemiddelApi.ts @@ -2,7 +2,7 @@ import axios from 'axios' import { useEffect, useState } from 'react' import { IPageResponse, IVirkemiddel, emptyPage } from '../constants' import { env } from '../util/env' -import { useDebouncedState } from '../util/hooks' +import { useDebouncedState } from '../util/hooks/customHooks' export const getAllVirkemiddel = async () => { const PAGE_SIZE = 100 diff --git a/apps/frontend/src/components/Chart.tsx b/apps/frontend/src/components/Chart.tsx deleted file mode 100644 index 4eaa13dd7..000000000 --- a/apps/frontend/src/components/Chart.tsx +++ /dev/null @@ -1,316 +0,0 @@ -/* eslint-disable jsx-a11y/mouse-events-have-key-events */ - -/* eslint-disable jsx-a11y/no-static-element-interactions */ - -/* eslint-disable jsx-a11y/click-events-have-key-events */ -import { faChartBar, faChartPie, faCircle } from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { Block } from 'baseui/block' -import { Card } from 'baseui/card' -import { StatefulTooltip } from 'baseui/tooltip' -import { LabelLarge } from 'baseui/typography' -import * as _ from 'lodash' -import React, { useReducer, useState } from 'react' -import { theme } from '../util' -import { cardShadow, marginAll } from './common/Style' - -const cursor = { cursor: 'pointer' } - -interface IChartData { - label: string - size: number - onClick?: () => void -} - -interface IChartDataExpanded extends IChartData { - color: string - fraction: number - sizeFraction: number - start: number -} - -type TChartType = 'pie' | 'bar' - -interface IChartProps { - title: string - leftLegend?: boolean - total?: number - data: IChartData[] - size: number - type?: TChartType -} - -export const Chart = (props: IChartProps) => { - const { size, total, data, title, leftLegend } = props - const totSize = data.map((chartData) => chartData.size).reduce((a, b) => a + b, 0) - const totalFraction = total !== undefined ? total : totSize - - const colorsBase = [ - '#a6cee3', - '#1f78b4', - '#b2df8a', - '#33a02c', - '#fb9a99', - '#e31a1c', - '#fdbf6f', - '#ff7f00', - '#cab2d6', - '#6a3d9a', - '#ffff99', - '#b15928', - ] - - const splice = Math.random() * colorsBase.length - const colors = [...colorsBase.slice(splice), ...colorsBase.slice(0, splice)] - - let s = 0 - const expData: IChartDataExpanded[] = data.map((d, idx) => { - // last color can't be same color as first color, as they are next to each other - const colorIndex = data.length - 1 === colors.length && idx >= data.length - 1 ? idx + 1 : idx - const pieData = { - ...d, - color: colors[colorIndex % colors.length], - start: s, - sizeFraction: totSize === 0 ? 0 : d.size / totSize, - fraction: totalFraction === 0 ? 0 : d.size / totalFraction, - } - s += pieData.sizeFraction - return pieData - }) - - return ( - - ) -} - -type TVisualizationProps = { - data: IChartDataExpanded[] - size: number - title: string - leftLegend: boolean - type: TChartType -} - -const Visualization = (props: TVisualizationProps) => { - const { size, data, title, leftLegend } = props - const [hover, setHover] = useState(-1) - const [type, toggle] = useReducer((old) => (old === 'bar' ? 'pie' : 'bar'), props.type) - - return ( - - -
setHover(-1)}> - - {!!data.length && ( - - {type === 'pie' && ( - - )} - {type === 'bar' && ( - - )} - - )} - {!data.length && } - - {title} - {data.map((d, idx) => ( -
setHover(idx)} onClick={d.onClick}> - - - - {d.size} - - - {(d.fraction * 100).toFixed(0)}% - - - {d.label} - - -
- ))} -
-
-
-
- -
- - - - - -
-
- ) -} - -const BarChart = (props: { - data: IChartDataExpanded[] - size: number - hover: number - setHover: (i: number) => void -}) => { - const { data, size, hover, setHover } = props - const max = _.max(data.map((d) => d.sizeFraction))! - const maxVal = _.max(data.map((d) => d.size))! - return ( - - - - - - - {_.range(0, 11).map((i) => ( - - - {(maxVal * i * 0.1).toFixed(0)} - - - - ))} - - {data.map((d, idx) => ( - setHover(idx)} - onClick={d.onClick} - /> - ))} - - ) -} - -const Bar = (props: TPartProps) => { - const { idx, size, color, totalSize, hover, onClick } = props - const width = 1000 / (totalSize * 1.3) - const d = ` - M ${120 + (idx / totalSize) * 1000} 100 - l 0 ${1000 * size} - l ${width} 0 - l 0 ${-1000 * size} - ` - const dHover = ` - M ${120 + (idx / totalSize) * 1000} 100 - l 0 ${1050} - l ${width} 0 - l 0 ${-1050} - ` - return ( - <> - - - - ) -} - -const PieChart = (props: { - data: IChartDataExpanded[] - radius: number - hover: number - setHover: (i: number) => void -}) => { - const { data, radius, hover, setHover } = props - return ( - - {data.map((d, idx) => ( - setHover(idx)} - onClick={d.onClick} - hover={idx === hover} - /> - ))} - - ) -} - -const pi = 3.1415926 -const tau = 2 * pi - -type TPartProps = { - idx: number - totalSize: number - - size: number - start: number - color: string - hover: boolean - onMouseOver: () => void - onClick?: () => void -} - -const Wedge = (props: TPartProps) => { - const { size, start, color, hover, onClick } = props - const scale = hover ? 1.05 : 1 - const d = ` - M ${Math.cos(start * tau) * scale} ${Math.sin(start * tau) * scale} - A ${scale} ${scale} 0 ${size >= 0.5 ? 1 : 0} 1 ${Math.cos((start + size) * tau) * scale} ${ - Math.sin((start + size) * tau) * scale - } - L 0 0 - ` - return ( - - ) -} diff --git a/apps/frontend/src/components/Header.tsx b/apps/frontend/src/components/Header.tsx index 7824f25ba..1444d28af 100644 --- a/apps/frontend/src/components/Header.tsx +++ b/apps/frontend/src/components/Header.tsx @@ -18,7 +18,7 @@ import { getMeldingByType } from '../api/MeldingApi' import { EAlertType, EMeldingStatus, EMeldingType, IMelding } from '../constants' import { ampli } from '../services/Amplitude' import { user } from '../services/User' -import { useQueryParam } from '../util/hooks' +import { useQueryParam } from '../util/hooks/customHooks' import { intl } from '../util/intl/intl' import { informationIcon, warningAlert } from './Images' import { Markdown } from './common/Markdown' diff --git a/apps/frontend/src/components/Images.tsx b/apps/frontend/src/components/Images.tsx index ff5690435..c3378acb4 100644 --- a/apps/frontend/src/components/Images.tsx +++ b/apps/frontend/src/components/Images.tsx @@ -70,8 +70,6 @@ import moneyImage from '../resources/img/money.png' import navImage from '../resources/img/nav-logo-red.svg' import peopleImage from '../resources/img/people.png' import scalesImage from '../resources/img/scales.png' -import { EListName, TLovCode, TTemaCode, codelist } from '../services/Codelist' -import { theme } from '../util' export { angleIcon, @@ -151,47 +149,3 @@ export const temaBilder: { [id: string]: string } = { CAMERA: cameraImage, GUARDIAN: guardianImage, } - -const bildeForLov = (code: TLovCode) => bildeForTema(code.data?.tema) - -const bildeForTema = (code?: string) => { - const temaCode = codelist.getCode(EListName.TEMA, code) - const imageCode = temaCode?.data?.image - return imageCode ? temaBilder[imageCode] || bookImage : bookImage -} - -export const LovBilde = (props: { code: TLovCode } & TBildeProps) => ( - -) - -export const TemaBilde = (props: { code: TTemaCode } & TBildeProps) => ( - -) - -type TBildeProps = { - width?: string - height?: string - ellipse?: boolean -} - -const Bilde = (props: { src: string; alt: string } & TBildeProps) => ( - {props.alt} -) diff --git a/apps/frontend/src/components/Lov.tsx b/apps/frontend/src/components/Lov.tsx index 0444d9837..9f0a2caaa 100644 --- a/apps/frontend/src/components/Lov.tsx +++ b/apps/frontend/src/components/Lov.tsx @@ -1,5 +1,4 @@ import { Link } from '@navikt/ds-react' -import { Block } from 'baseui/block' import { IRegelverk } from '../constants' import { EListName, codelist } from '../services/Codelist' import { env } from '../util/env' @@ -13,13 +12,13 @@ const processString = reactProcessString as ( ) => (input?: string) => JSX.Element[] export const LovViewList = (props: { regelverkListe: IRegelverk[]; openOnSamePage?: boolean }) => ( - +
{props.regelverkListe.map((regelverk, index) => ( - +
- +
))} -
+
) export const LovView = (props: { regelverk?: IRegelverk; openOnSamePage?: boolean }) => { diff --git a/apps/frontend/src/components/Navigation/Burger/index.tsx b/apps/frontend/src/components/Navigation/Burger/index.tsx deleted file mode 100644 index 0d4fe407f..000000000 --- a/apps/frontend/src/components/Navigation/Burger/index.tsx +++ /dev/null @@ -1,265 +0,0 @@ -import { faBars, faTimes } from '@fortawesome/free-solid-svg-icons' -import { Block } from 'baseui/block' -import { ANCHOR, Drawer } from 'baseui/drawer' -import { StyledLink } from 'baseui/link' -import { HeadingXLarge, ParagraphMedium } from 'baseui/typography' -import * as React from 'react' -import { useLocation } from 'react-router-dom' -import { useStyletron } from 'styletron-react' -import { user } from '../../../services/User' -import { theme } from '../../../util' -import { env } from '../../../util/env' -import { ettlevColors } from '../../../util/theme' -import { arkPennIcon, exitIcon, grafIcon, husIcon, paragrafIcon } from '../../Images' -import Button from '../../common/Button' -import RouteLink from '../../common/RouteLink' - -const Brand = () => ( - - Støtte til etterlevelse - -) - -const MenuItem = (props: { - to: string - text: string - icon: string - setShowMenu: React.Dispatch> -}) => ( - - props.setShowMenu(false)}> - - - {props.icon && ( - - {'link - - )} - {props.text} - - - - -) - -const LoginButton = (props: { location: string }) => { - const [useCss] = useStyletron() - const linkCss = useCss({ textDecoration: 'none', color: 'white' }) - return ( - - - - ) -} - -const SignOutButton = (props: { location: string }) => { - const [useCss] = useStyletron() - const linkCss = useCss({ textDecoration: 'none', color: 'white' }) - return ( - - - - ) -} - -const BurgerMenu = () => { - const location = useLocation() - const [showMenu, setShowMenu] = React.useState(false) - const [url, setUrl] = React.useState(window.location.href) - - React.useEffect(() => { - if (showMenu) setShowMenu(false) - setUrl(window.location.href) - }, [location.pathname]) - - return ( - - {!showMenu && ( - - )} - - {showMenu && ( - setShowMenu(false)} - anchor={ANCHOR.top} - overrides={{ - DrawerContainer: { - style: () => { - return { - backgroundColor: ettlevColors.white, - height: '100vh', - } - }, - }, - Close: { - style: { - display: 'none', - }, - }, - }} - > - - - - - - - - - - - - - - - - - - - - - - {/* - {user.isAdmin() && ( - <> - - - - )} - */} - - - {!user.isLoggedIn() && } - - {user.isLoggedIn() && ( - <> - - - - {user.getIdent()}: {user.getName()} - - - - - - - - )} - - - {/* - - - - slack logo - #etterlevelse - - - - - - - Dokumentasjon - - - - - - NAV logo - */} - - - )} - - ) -} - -export default BurgerMenu diff --git a/apps/frontend/src/components/admin/CodeList/CodelistPage.tsx b/apps/frontend/src/components/admin/CodeList/CodelistPage.tsx index 6a30296b6..5eae01605 100644 --- a/apps/frontend/src/components/admin/CodeList/CodelistPage.tsx +++ b/apps/frontend/src/components/admin/CodeList/CodelistPage.tsx @@ -6,7 +6,7 @@ import { useNavigate, useParams } from 'react-router-dom' import { createCodelist } from '../../../api/CodelistApi' import { ICode, ICodeListFormValues, codelist } from '../../../services/Codelist' import { user } from '../../../services/User' -import { useAwait, useForceUpdate } from '../../../util/hooks' +import { useAwait, useForceUpdate } from '../../../util/hooks/customHooks' import { PageLayout } from '../../scaffold/Page' import CodeListTable from './CodeListStyledTable' import ModalCreateCodeList from './ModalCreateCodeList' @@ -75,9 +75,9 @@ const CodeListPage = () => { onChange={(e) => setListname(e.target.value)} > - {codelist.makeIdLabelForAllCodeLists().map((codeLabel, index) => { + {codelist.makeValueLabelForAllCodeLists().map((codeLabel, index) => { return ( - ) diff --git a/apps/frontend/src/components/admin/audit/AuditPage.tsx b/apps/frontend/src/components/admin/audit/AuditPage.tsx index 763c4483c..4caf682b9 100644 --- a/apps/frontend/src/components/admin/audit/AuditPage.tsx +++ b/apps/frontend/src/components/admin/audit/AuditPage.tsx @@ -3,7 +3,7 @@ import _ from 'lodash' import { useEffect, useState } from 'react' import { useNavigate, useParams } from 'react-router-dom' import { getAuditLog } from '../../../api/AuditApi' -import { useDebouncedState } from '../../../util/hooks' +import { useDebouncedState } from '../../../util/hooks/customHooks' import { intl } from '../../../util/intl/intl' import { PageLayout } from '../../scaffold/Page' import { AuditLabel } from './AuditComponents' diff --git a/apps/frontend/src/components/admin/audit/AuditRecentTable.tsx b/apps/frontend/src/components/admin/audit/AuditRecentTable.tsx index 0d0526205..a253f8cda 100644 --- a/apps/frontend/src/components/admin/audit/AuditRecentTable.tsx +++ b/apps/frontend/src/components/admin/audit/AuditRecentTable.tsx @@ -35,7 +35,7 @@ const CodeView = ({ audit }: { audit: IAuditItem }) => { open={modalOpen} onClose={() => setModalOpen(false)} className="max-h-[75%] overflow-y-scroll" - header={{heading: "Data visning"}} + header={{ heading: 'Data visning' }} > @@ -86,7 +86,7 @@ export const AuditRecentTable = (props: { show: boolean; tableType?: EObjectType return null } - const tableOptions = Object.keys(EObjectType).map((ot) => ({ id: ot, label: ot })) + const tableOptions = Object.keys(EObjectType).map((ot) => ({ value: ot, label: ot })) return (
@@ -110,7 +110,7 @@ export const AuditRecentTable = (props: { show: boolean; tableType?: EObjectType > {tableOptions.map((tableOption, index) => ( - ))} diff --git a/apps/frontend/src/components/admin/audit/AuditView.tsx b/apps/frontend/src/components/admin/audit/AuditView.tsx index 582f2e86d..c8c353f5a 100644 --- a/apps/frontend/src/components/admin/audit/AuditView.tsx +++ b/apps/frontend/src/components/admin/audit/AuditView.tsx @@ -4,7 +4,7 @@ import { Differ, Viewer } from 'json-diff-kit' import moment from 'moment' import { useEffect, useState } from 'react' import { JsonView } from 'react-json-view-lite' -import { useRefs } from '../../../util/hooks' +import { useRefs } from '../../../util/hooks/customHooks' import { intl } from '../../../util/intl/intl' import { ObjectLink } from '../../common/RouteLink' import { AuditActionIcon, AuditLabel } from './AuditComponents' diff --git a/apps/frontend/src/components/admin/settings/SettingsApi.ts b/apps/frontend/src/components/admin/settings/SettingsApi.ts deleted file mode 100644 index 39565a093..000000000 --- a/apps/frontend/src/components/admin/settings/SettingsApi.ts +++ /dev/null @@ -1,14 +0,0 @@ -import axios from 'axios' -import { env } from '../../../util/env' - -export const getSettings = async () => { - return (await axios.get(`${env.backendBaseUrl}/settings`)).data -} - -export const writeSettings = async (settings: ISettings) => { - return (await axios.post(`${env.backendBaseUrl}/settings`, settings)).data -} - -export interface ISettings { - frontpageMessage: string -} diff --git a/apps/frontend/src/components/admin/settings/SettingsPage.tsx b/apps/frontend/src/components/admin/settings/SettingsPage.tsx deleted file mode 100644 index 9b68b5424..000000000 --- a/apps/frontend/src/components/admin/settings/SettingsPage.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import { Block } from 'baseui/block' -import { Spinner } from 'baseui/spinner' -import { HeadingMedium, LabelMedium } from 'baseui/typography' -import React, { FormEvent, useState } from 'react' -import { Helmet } from 'react-helmet' -import { theme } from '../../../util' -import { intl } from '../../../util/intl/intl' -import { ettlevColors, responsivePaddingSmall, responsiveWidthSmall } from '../../../util/theme' -import Button from '../../common/Button' -import { CustomizedStatefulTextarea } from '../../common/CustomizedTextarea' -import { Markdown } from '../../common/Markdown' -import { ISettings, getSettings, writeSettings } from './SettingsApi' - -export const SettingsPage = () => { - const [loading, setLoading] = React.useState(true) - const [error, setError] = useState() - const [settings, setSettings] = useState() - - const load = async () => { - setLoading(true) - setSettings(await getSettings()) - setLoading(false) - } - - const save = async () => { - if (settings) { - setLoading(true) - try { - setSettings(await writeSettings(settings)) - } catch (e: any) { - setError(e) - } - setLoading(false) - } - } - - return ( - - - - Innstillinger - - {intl.settings} - {loading && } - {(error || !settings) && error} - {!loading && !(error || !settings) && ( - - setSettings({ ...settings, frontpageMessage })} - /> - - - - - - - )} - - ) -} - -const FrontpageMessage = (props: { message?: string; setMessage: (message: string) => void }) => { - return ( - - - Forsidemelding - - - - props.setMessage((event as FormEvent).currentTarget.value) - } - /> - - - - - - - - ) -} diff --git a/apps/frontend/src/components/behandling/utils.tsx b/apps/frontend/src/components/behandling/utils.tsx deleted file mode 100644 index ea145fbe0..000000000 --- a/apps/frontend/src/components/behandling/utils.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import moment from 'moment' -import { EEtterlevelseStatus } from '../../constants' -import { ettlevColors } from '../../util/theme' - -export const getEtterlevelseStatus = (status?: EEtterlevelseStatus, frist?: string) => { - switch (status) { - case EEtterlevelseStatus.UNDER_REDIGERING: - return 'Under arbeid' - case EEtterlevelseStatus.FERDIG: - return 'Under arbeid' - case EEtterlevelseStatus.IKKE_RELEVANT: - return 'Ikke relevant' - case EEtterlevelseStatus.IKKE_RELEVANT_FERDIG_DOKUMENTERT: - return 'Ikke relevant' - case EEtterlevelseStatus.FERDIG_DOKUMENTERT: - return 'Ferdig utfylt' - case EEtterlevelseStatus.OPPFYLLES_SENERE: - if (frist) { - return 'Utsatt til: ' + moment(frist).format('ll') - } else { - return 'Utsatt' - } - default: - return '' - } -} - -export const getStatusLabelColor = (status: EEtterlevelseStatus) => { - switch (status) { - case EEtterlevelseStatus.UNDER_REDIGERING: - return { - background: ettlevColors.white, - border: '#0B483F', - } - case EEtterlevelseStatus.FERDIG: - return { - background: ettlevColors.white, - border: '#0B483F', - } - case EEtterlevelseStatus.IKKE_RELEVANT: - return { - background: ettlevColors.grey50, - border: ettlevColors.grey200, - } - case EEtterlevelseStatus.IKKE_RELEVANT_FERDIG_DOKUMENTERT: - return { - background: ettlevColors.grey50, - border: ettlevColors.grey200, - } - case EEtterlevelseStatus.FERDIG_DOKUMENTERT: - return { - background: ettlevColors.green50, - border: ettlevColors.green400, - } - case EEtterlevelseStatus.OPPFYLLES_SENERE: - return { - background: ettlevColors.warning50, - border: '#D47B00', - } - default: - return { - background: ettlevColors.white, - border: ettlevColors.green400, - } - } -} diff --git a/apps/frontend/src/components/common/Button.tsx b/apps/frontend/src/components/common/Button.tsx deleted file mode 100644 index 3f459a158..000000000 --- a/apps/frontend/src/components/common/Button.tsx +++ /dev/null @@ -1,213 +0,0 @@ -import { IconDefinition } from '@fortawesome/fontawesome-svg-core' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { Block } from 'baseui/block' -import { Button as BaseUIButton, KIND, SHAPE, SIZE } from 'baseui/button' -import { Override } from 'baseui/overrides' -import { PLACEMENT, StatefulTooltip } from 'baseui/tooltip' -import _ from 'lodash' -import * as React from 'react' -import { ReactNode } from 'react' -import { StyleObject } from 'styletron-react' -import { theme } from '../../util' -import { ettlevColors } from '../../util/theme' -import { ExternalLink } from './RouteLink' -import { borderColor, borderRadius, borderStyle, borderWidth, padding, paddingAll } from './Style' - -export type TButtonKind = (typeof KIND)[keyof typeof KIND] | 'outline' | 'underline-hover' - -interface IButtonProps { - kind?: TButtonKind - type?: 'submit' | 'reset' | 'button' - size?: (typeof SIZE)[keyof typeof SIZE] - shape?: (typeof SHAPE)[keyof typeof SHAPE] - icon?: IconDefinition - iconEnd?: IconDefinition - inline?: boolean - tooltip?: string - children?: ReactNode - onClick?: () => void - startEnhancer?: ReactNode - disabled?: boolean - $style?: StyleObject - marginRight?: boolean - marginLeft?: boolean - label?: string - hidePadding?: boolean - notBold?: boolean -} - -interface ITooltipProps { - tooltip?: string - children: React.ReactElement -} - -const Tooltip = (props: ITooltipProps) => - props.tooltip ? ( - - {props.children} - - ) : ( - props.children - ) - -// outline button is a secondary button, but with a border -const outlineWidth = '2px' -const outlineStyle = 'solid' -const outlineOverride = { - ...borderColor(ettlevColors.green600), - backgroundColor: 'inherit', - ...borderWidth(outlineWidth), - ...borderStyle(outlineStyle), -} - -// underline-hover button is a tertiary with underline as hover effect -const underlineOverride = { - ...paddingAll('0'), - textDecorationThickness: '3px', - ':hover': { - textDecorationLine: 'underline', - backgroundColor: 'inherit', - }, - ':focus': { - textDecorationLine: 'underline', - backgroundColor: 'inherit', - }, -} - -export const buttonContentStyle = { - fontSize: '18px', - ...padding('10px', '12px'), -} - -export const primaryFocusBorder = { - ':focus': { - outlineStyle: 'solid', - outlineWidth: '2px', - }, -} - -export const Button = (props: IButtonProps) => { - const baseuiKind = - props.kind === 'outline' - ? KIND.secondary - : props.kind === 'underline-hover' - ? KIND.tertiary - : props.kind - - const boxShadow = - !props.kind || props.kind === 'primary' || props.kind === 'secondary' - ? { - style: { - ...buttonContentStyle, - boxShadow: - '0 3px 1px -2px rgba(0, 0, 0, .2), 0 2px 2px 0 rgba(0, 0, 0, .14), 0 1px 2px 0 rgba(0, 0, 0, .12)', - ':hover': { - boxShadow: - '0 2px 4px -1px rgba(0, 0, 0, .2), 0 4px 5px 0 rgba(0, 0, 0, .14), 0 1px 3px 0 rgba(0, 0, 0, .12)', - }, - ':active': { - boxShadow: - '0 2px 1px -2px rgba(0, 0, 0, .2), 0 1px 1px 0 rgba(0, 0, 0, .14), 0 1px 1px 0 rgba(0, 0, 0, .12)', - }, - ':focus': { - boxShadow: - '0 2px 4px -1px rgba(0, 0, 0, .2), 0 4px 5px 0 rgba(0, 0, 0, .14), 0 1px 3px 0 rgba(0, 0, 0, .12)', - outlineWidth: '3px', - outlineStyle: 'solid', - outlineColor: ettlevColors.focusOutline, - outlineOffset: props.kind === 'primary' ? '2px' : undefined, - }, - }, - } - : { - style: { - buttonContentStyle, - }, - } - - const overrides: Override = boxShadow - overrides.style = _.merge(overrides.style, props.kind === 'outline' ? outlineOverride : {}) - overrides.style = _.merge( - overrides.style, - props.kind === 'underline-hover' ? underlineOverride : {} - ) - overrides.style = _.merge(overrides.style, props.kind === 'secondary' ? buttonBorderStyle : {}) - overrides.style = _.merge(overrides.style, props.hidePadding ? paddingAll('0') : {}) - overrides.style = _.merge( - overrides.style, - props.inline ? { paddingTop: theme.sizing.scale100, paddingBottom: theme.sizing.scale100 } : {} - ) - overrides.style = _.merge(overrides.style, props.$style || {}) - - return ( - <> - - - props.onClick?.()} - overrides={{ BaseButton: overrides }} - startEnhancer={props.startEnhancer} - disabled={props.disabled} - type={props.type} - aria-label={props.label} - > - {props.icon && ( - - )} - {props.notBold ? props.children : {props.children}} - {props.iconEnd && ( - - )} - - - - - ) -} - -export default Button - -// Må gjøres properly, laget denne for å unngå tusenvis av react warnings -export const buttonBorderStyle = { - ...borderColor(ettlevColors.green600), - ...borderStyle('solid'), - ...borderWidth('2px'), - ...borderRadius('4px'), -} - -export const ExternalButton = ({ - href, - children, - underlineHover, - size, - openOnSamePage, - kind, -}: { - href: string - children: React.ReactNode - underlineHover?: boolean - size?: (typeof SIZE)[keyof typeof SIZE] - openOnSamePage?: boolean - kind?: TButtonKind -}) => { - const underlineStyle = underlineHover ? 'underline-hover' : 'outline' - const actualSize = size || 'compact' - return ( - - - - ) -} diff --git a/apps/frontend/src/components/common/CustomizedAccordion.tsx b/apps/frontend/src/components/common/CustomizedAccordion.tsx deleted file mode 100644 index 193300854..000000000 --- a/apps/frontend/src/components/common/CustomizedAccordion.tsx +++ /dev/null @@ -1,125 +0,0 @@ -import { faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { Accordion, AccordionProps, Panel, PanelOverrides, PanelProps } from 'baseui/accordion' -import { Block } from 'baseui/block' -import { HeadingLarge } from 'baseui/typography' -import _ from 'lodash' -import * as React from 'react' -import { ettlevColors, theme } from '../../util/theme' -import { borderColor, borderRadius, borderStyle, borderWidth, paddingAll } from './Style' - -export const CustomizedAccordion = (props: Partial) => { - return -} - -interface ICustomizedPanelProps { - HeaderBackgroundColor?: string - HeaderActiveBackgroundColor?: string - noUnderLine?: boolean - toggleIcon?: { expanded: React.ReactElement; unexpanded: React.ReactElement } -} - -type TCustomProps = ICustomizedPanelProps & PanelProps - -export const CustomizedPanel = (props: TCustomProps) => { - const { expanded } = props - - const customOverrides: PanelOverrides = { - ToggleIcon: { - component: () => { - if (props.toggleIcon) { - return expanded ? props.toggleIcon.expanded : props.toggleIcon.unexpanded - } else { - return expanded ? ( - - ) : ( - - ) - } - }, - }, - Header: { - style: { - backgroundColor: ettlevColors.white, - ...borderRadius('4px'), - paddingTop: theme.sizing.scale300, - paddingBottom: theme.sizing.scale300, - ':hover': { - textDecoration: props.noUnderLine ? 'none' : 'underline', - color: ettlevColors.green800, - ...(expanded - ? { - boxShadow: 'none', - } - : { - boxShadow: '0px 3px 4px rgba(0, 0, 0, 0.12)', - }), - }, - }, - }, - ContentAnimationContainer: { - style: { - overflow: 'visible', // fix box shadows of content - }, - }, - Content: { - style: { - ...borderRadius('4px'), - backgroundColor: ettlevColors.grey50, - ...paddingAll('0px'), - overflow: 'visible', // fix box shadows of content - }, - }, - PanelContainer: { - style: { - ...(expanded - ? { - ...borderColor(ettlevColors.grey200), - } - : { - ...borderColor(ettlevColors.grey100), - }), - ...borderStyle('solid'), - ...borderWidth('1px'), - ...borderRadius('4px'), - marginBottom: theme.sizing.scale200, - backgroundColor: ettlevColors.white, - }, - }, - } - - const overrides = _.merge(customOverrides, props.overrides) - - const getTitle = () => { - if (typeof props.title !== 'string') { - return props.title - } else { - return ( - - - {props.title} - - - ) - } - } - - return -} - -export const CustomPanelDivider = (props: { children: React.ReactNode; fullWidth?: boolean }) => ( - - - {props.children} - -) diff --git a/apps/frontend/src/components/common/CustomizedInput.tsx b/apps/frontend/src/components/common/CustomizedInput.tsx deleted file mode 100644 index b05d9a7b5..000000000 --- a/apps/frontend/src/components/common/CustomizedInput.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { Input, InputOverrides, InputProps } from 'baseui/input' -import _ from 'lodash' -import { ettlevColors } from '../../util/theme' - -export const CustomizedInput = (props: InputProps) => { - const customOverrides: InputOverrides = { - InputContainer: { - style: { - boxShadow: '0 2px 2px 0 rgba(0, 0, 0, .12), 0 2px 1px -1px rgba(0, 0, 0, .2)', - ':hover': { - backgroundColor: ettlevColors.green50, - boxShadow: '0px 1px 1px rgba(0, 0, 0, 0.12), 0px 1px 1px -1px rgba(0, 0, 0, 0.2)', - }, - }, - }, - } - - const overrides = _.merge(customOverrides, props.overrides) - - return -} - -export default CustomizedInput diff --git a/apps/frontend/src/components/common/CustomizedLink.tsx b/apps/frontend/src/components/common/CustomizedLink.tsx deleted file mode 100644 index 3371032bc..000000000 --- a/apps/frontend/src/components/common/CustomizedLink.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { LinkProps, StyledLink } from 'baseui/link' -import _ from 'lodash' - -const CustomizedLink = (props: LinkProps) => { - const { style, ...restProps } = props - const customStyle = { - fontWeight: 'normal', - } - - const mergedStyle = _.merge(customStyle, style) - - return ( - - {props.children} - - ) -} - -export default CustomizedLink diff --git a/apps/frontend/src/components/common/CustomizedModal.tsx b/apps/frontend/src/components/common/CustomizedModal.tsx deleted file mode 100644 index c3d760652..000000000 --- a/apps/frontend/src/components/common/CustomizedModal.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { Modal, ModalProps, SIZE } from 'baseui/modal' -import _ from 'lodash' -import { maxPageWidth } from '../../util/theme' - -type TCustomModalProps = { - closeIconColor?: string - closeIconHoverColor?: string - disableCloseIcon?: boolean -} - -const CuztomizedModal = (props: TCustomModalProps & ModalProps) => { - const { closeIconColor, closeIconHoverColor, disableCloseIcon, ...otherProps } = props - - const customOverrides = { - Dialog: { - style: { - backgroundColor: '#F8F8F8', - maxWidth: `calc(${maxPageWidth} - 80px)`, - width: '100%', - }, - }, - DialogContainer: { - style: { - paddingLeft: '10px', - paddingRight: '10px', - width: 'calc(100% - 20px)', - }, - }, - Close: { - style: { - display: disableCloseIcon ? 'none' : undefined, - color: closeIconColor ? closeIconColor : undefined, - ':hover': { - color: closeIconHoverColor ? closeIconHoverColor : undefined, - }, - }, - }, - } - - const mergedOverrides = _.merge(customOverrides, props.overrides) - - return ( - - ) -} -export default CuztomizedModal diff --git a/apps/frontend/src/components/common/CustomizedSelect.tsx b/apps/frontend/src/components/common/CustomizedSelect.tsx deleted file mode 100644 index a125ba45d..000000000 --- a/apps/frontend/src/components/common/CustomizedSelect.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { - Select, - SelectOverrides, - SelectProps, - StatefulSelect, - StatefulSelectProps, -} from 'baseui/select' -import _ from 'lodash' -import { ettlevColors } from '../../util/theme' -import { navChevronDownIcon } from '../Images' -import { borderWidth } from './Style' - -const customOverrides: SelectOverrides = { - ControlContainer: { - style: { - ...borderWidth('1px'), - ':hover': { - backgroundColor: ettlevColors.green50, - }, - }, - }, - SelectArrow: { - component: ({ $isOpen }: { $isOpen: boolean }) => - $isOpen ? ( - Chevron opp - ) : ( - Chevron ned - ), - }, - DropdownListItem: { - style: { - fontSize: '18px', - marginTop: '4px', - marginBottom: '4px', - }, - }, -} - -export const CustomizedStatefulSelect = (props: StatefulSelectProps) => { - const overrides = _.merge(customOverrides, props.overrides) - - return -} - -export const CustomizedSelect = (props: SelectProps) => { - const overrides = _.merge(customOverrides, props.overrides) - - return