Skip to content

Commit

Permalink
DMP-4506 Courthouse fields updated across admin, portal (#1757)
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidTMann authored Jan 8, 2025
1 parent 67bd192 commit 81c9dcf
Show file tree
Hide file tree
Showing 13 changed files with 91 additions and 51 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Courthouse } from '@admin-types/courthouses/courthouse.type';
import { TranscriptionSearchFormValues } from '@admin-types/index';
import { CommonModule, NgIf } from '@angular/common';
import { Component, DestroyRef, effect, inject, input, model, output } from '@angular/core';
Expand All @@ -6,7 +7,7 @@ import { CourthouseComponent } from '@common/courthouse/courthouse.component';
import { DatepickerComponent } from '@common/datepicker/datepicker.component';
import { SpecificOrRangeDatePickerComponent } from '@common/specific-or-range-date-picker/specific-or-range-date-picker.component';
import { TranscriptSearchFormErrorMessages } from '@constants/transcript-search-form-error-messages';
import { CourthouseData, ErrorSummaryEntry } from '@core-types/index';
import { ErrorSummaryEntry } from '@core-types/index';
import { FormService } from '@services/form/form.service';
import { defaultFormValues } from '@services/transcription-admin/transcription-admin.service';
import { dateRangeValidator } from '@validators/date-range.validator';
Expand Down Expand Up @@ -40,7 +41,7 @@ export class SearchTranscriptsFormComponent {
formService = inject(FormService);

isCompletedTranscriptSearch = input(false);
courthouses = input<CourthouseData[]>([]);
courthouses = input<Courthouse[]>([]);
formValues = model<TranscriptionSearchFormValues>(defaultFormValues);

form = this.fb.group({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ describe('TranscriptsComponent', () => {

const fakeCourthouseService = {
getCourthouses: jest.fn().mockReturnValue(of([])),
mapCourthouseDataToCourthouses: jest.fn().mockReturnValue([]),
} as unknown as CourthouseService;

beforeEach(async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ export class TranscriptsComponent {
router = inject(Router);
errors: { fieldId: string; message: string }[] = [];

courthouses$ = this.courthouseService.getCourthouses().pipe(shareReplay(1));
courthouses$ = this.courthouseService.getCourthouses().pipe(
map((data) => this.courthouseService.mapCourthouseDataToCourthouses(data)),
shareReplay(1)
);
transcriptionStatuses$ = this.transcriptService.getTranscriptionStatuses().pipe(shareReplay(1));

search$ = new Subject<TranscriptionSearchFormValues | null>();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Courthouse } from '@admin-types/courthouses/courthouse.type';
import { TransformedMediaSearchFormValues } from '@admin-types/transformed-media/transformed-media-search-form.values';
import { CommonModule, NgIf } from '@angular/common';
import {
Expand All @@ -17,7 +18,7 @@ import { CourthouseComponent } from '@common/courthouse/courthouse.component';
import { DatepickerComponent } from '@common/datepicker/datepicker.component';
import { SpecificOrRangeDatePickerComponent } from '@common/specific-or-range-date-picker/specific-or-range-date-picker.component';
import { TransformedMediaSearchFormErrorMessages } from '@constants/transformed-media-search-form-error-messages';
import { CourthouseData, ErrorSummaryEntry } from '@core-types/index';
import { ErrorSummaryEntry } from '@core-types/index';
import { FormService } from '@services/form/form.service';
import { defaultFormValues } from '@services/transformed-media/transformed-media.service';
import { dateRangeValidator } from '@validators/date-range.validator';
Expand Down Expand Up @@ -51,7 +52,7 @@ export class SearchTransformedMediaFormComponent {
formService = inject(FormService);
formValues = input<TransformedMediaSearchFormValues>({ ...defaultFormValues });

@Input() courthouses: CourthouseData[] = [];
@Input() courthouses: Courthouse[] = [];

form = this.fb.group({
requestId: ['', [Validators.pattern(/^-?[0-9]*$/), Validators.min(1), Validators.max(2147483647)]],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ export class SearchTransformedMediaComponent {
scrollService = inject(ScrollService);

errors = signal<ErrorSummaryEntry[]>([]);
courthouses$ = this.courthouseService.getCourthouses();
courthouses$ = this.courthouseService
.getCourthouses()
.pipe(map((data) => this.courthouseService.mapCourthouseDataToCourthouses(data)));
isLoading = signal<boolean>(false);

onErrors(errors: ErrorSummaryEntry[]) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Courthouse } from '@admin-types/courthouses/courthouse.type';
import { Transcription, TranscriptionStatus } from '@admin-types/transcription';
import { CommonModule, NgClass } from '@angular/common';
import { Component, EventEmitter, OnInit, Output, inject } from '@angular/core';
Expand All @@ -8,7 +9,7 @@ import { GovukHeadingComponent } from '@common/govuk-heading/govuk-heading.compo
import { GovukTagComponent } from '@common/govuk-tag/govuk-tag.component';
import { LoadingComponent } from '@common/loading/loading.component';
import { transcriptStatusTagColours } from '@constants/transcript-status-tag-colours';
import { CourthouseData, DatatableColumn } from '@core-types/index';
import { DatatableColumn } from '@core-types/index';
import { TableRowTemplateDirective } from '@directives/table-row-template.directive';
import { LuxonDatePipe } from '@pipes/luxon-date.pipe';
import { TranscriptStatus } from '@portal-types/index';
Expand Down Expand Up @@ -48,7 +49,10 @@ export class UserTranscriptsComponent implements OnInit {
statusColours = transcriptStatusTagColours;

showAll$!: Observable<boolean>;
courthouses$: Observable<CourthouseData[]> = this.courthouseService.getCourthouses().pipe(shareReplay(1));
courthouses$: Observable<Courthouse[]> = this.courthouseService.getCourthouses().pipe(
map((data) => this.courthouseService.mapCourthouseDataToCourthouses(data)),
shareReplay(1)
);
transcriptionStatuses$: Observable<TranscriptionStatus[]> = this.transcriptionAdminService
.getTranscriptionStatuses()
.pipe(shareReplay(1));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Courthouse } from '@admin-types/courthouses/courthouse.type';
import { FileHideOrDeleteFormValues } from '@admin-types/hidden-reasons/file-hide-or-delete-form-values';
import { HiddenReason } from '@admin-types/hidden-reasons/hidden-reason';
import { HiddenReasonData } from '@admin-types/hidden-reasons/hidden-reason-data.interface';
Expand All @@ -16,7 +17,6 @@ import { DatePipe } from '@angular/common';
import { provideHttpClient } from '@angular/common/http';
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
import { TestBed, fakeAsync, tick } from '@angular/core/testing';
import { CourthouseData } from '@core-types/index';
import { LuxonDatePipe } from '@pipes/luxon-date.pipe';
import { TranscriptStatus } from '@portal-types/index';
import { DateTime } from 'luxon';
Expand Down Expand Up @@ -710,9 +710,9 @@ describe('TranscriptionAdminService', () => {
] as unknown as Transcription[];

const courthouses = [
{ id: 1, display_name: 'Courthouse 1', courthouse_name: 'Main Courthouse' },
{ id: 2, display_name: 'Courthouse 2', courthouse_name: 'Secondary Courthouse' },
] as CourthouseData[];
{ id: 1, displayName: 'Courthouse 1', courthouseName: 'Main Courthouse' },
{ id: 2, displayName: 'Courthouse 2', courthouseName: 'Secondary Courthouse' },
] as Courthouse[];

const statuses = [
{ id: 1, type: 'Requested', displayName: 'Status 1' },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Courthouse } from '@admin-types/courthouses/courthouse.type';
import { FileHide } from '@admin-types/hidden-reasons/file-hide';
import { FileHideData } from '@admin-types/hidden-reasons/file-hide-data.interface';
import { FileHideOrDeleteFormValues } from '@admin-types/hidden-reasons/file-hide-or-delete-form-values';
Expand Down Expand Up @@ -28,7 +29,6 @@ import { TranscriptionWorkflow } from '@admin-types/transcription/transcription-
import { TranscriptionWorkflowData } from '@admin-types/transcription/transcription-workflow-data.interface';
import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http';
import { Injectable, inject, signal } from '@angular/core';
import { CourthouseData } from '@core-types/index';
import { LuxonDatePipe } from '@pipes/luxon-date.pipe';
import { TranscriptStatus } from '@portal-types/transcriptions/transcript-status.type';
import { GET_SECURITY_GROUPS_PATH } from '@services/courthouses/courthouses.service';
Expand Down Expand Up @@ -301,20 +301,16 @@ export class TranscriptionAdminService {
};
}

mapResults(
results: Transcription[],
courthouses: CourthouseData[],
statuses: TranscriptionStatus[]
): Transcription[] {
mapResults(results: Transcription[], courthouses: Courthouse[], statuses: TranscriptionStatus[]): Transcription[] {
return results.map((result) => {
const courthouse = courthouses.find((c) => c.id === result.courthouse.id);
const status = statuses.find((s) => s.id === result.status.id);
return {
...result,
courthouse: {
id: courthouse?.id,
displayName: courthouse?.display_name,
courthouseName: courthouse?.courthouse_name,
displayName: courthouse?.displayName,
courthouseName: courthouse?.courthouseName,
},
status: {
id: status?.id,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import { Courthouse } from '@admin-types/courthouses/courthouse.type';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { CourthouseData } from '@core-types/index';
import { DateTime } from 'luxon';
import { CourthouseComponent } from './courthouse.component';

describe('CourthouseComponent', () => {
let component: CourthouseComponent;
let fixture: ComponentFixture<CourthouseComponent>;

const courts = [
{ courthouse_name: 'Reading', id: 0, created_date_time: 'mock' },
{ courthouse_name: 'Slough', id: 1, created_date_time: 'mock' },
{ courthouse_name: 'Ascot', id: 2, created_date_time: 'mock' },
] as CourthouseData[];
{ courthouseName: 'Reading', id: 0, createdDateTime: DateTime.now() },
{ courthouseName: 'Slough', id: 1, createdDateTime: DateTime.now() },
{ courthouseName: 'Ascot', id: 2, createdDateTime: DateTime.now() },
] as Courthouse[];

beforeEach(() => {
TestBed.configureTestingModule({
Expand All @@ -30,15 +31,15 @@ describe('CourthouseComponent', () => {
describe('AccessibleAutocomplete props', () => {
it('should have correct default properties', () => {
fixture.detectChanges();
expect(component.props.id).toBe('courthouse');
expect(component.props.name).toBe('courthouse');
expect(component.props.minLength).toBe(1);
expect(component.props?.id).toBe('courthouse');
expect(component.props?.name).toBe('courthouse');
expect(component.props?.minLength).toBe(1);
});

it('has correct default value if courthouse is pre-populated', () => {
component.courthouse = 'Swansea';
fixture.detectChanges();
expect(component.props.defaultValue).toBe('Swansea');
expect(component.props?.defaultValue).toBe('Swansea');
});
});

Expand Down
50 changes: 33 additions & 17 deletions src/app/core/components/common/courthouse/courthouse.component.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
import { Courthouse } from '@admin-types/courthouses/courthouse.type';
import { NgFor, NgIf } from '@angular/common';
import { AfterViewInit, Component, ElementRef, EventEmitter, Input, OnChanges, Output, ViewChild } from '@angular/core';
import { CourthouseData } from '@core-types/index';
import {
AfterViewInit,
Component,
ElementRef,
EventEmitter,
Input,
OnChanges,
OnInit,
Output,
ViewChild,
} from '@angular/core';
import accessibleAutocomplete, { AccessibleAutocompleteProps } from 'accessible-autocomplete';

@Component({
Expand All @@ -10,27 +20,33 @@ import accessibleAutocomplete, { AccessibleAutocompleteProps } from 'accessible-
templateUrl: './courthouse.component.html',
styleUrls: ['./courthouse.component.scss'],
})
export class CourthouseComponent implements AfterViewInit, OnChanges {
export class CourthouseComponent implements AfterViewInit, OnChanges, OnInit {
@ViewChild('courthouseAutocomplete') autocompleteContainer!: ElementRef<HTMLElement>;

@Input() courthouses: CourthouseData[] = [];
@Input() courthouses: Courthouse[] = [];
@Input() courthouse = '';
@Input() label = 'Courthouse';
@Input() isInvalid = false;
@Input() showAllValues = true;
@Input() errors: string[] = [];
@Output() courthouseSelect = new EventEmitter<string>();

props: AccessibleAutocompleteProps = {
id: 'courthouse',
source: [],
minLength: 1,
name: 'courthouse',
onConfirm: () => {
// have to grab input value like this due to onConfirm(courthouse) emitting undefined onBlur
const inputValue = (document.querySelector('input[name=courthouse]') as HTMLInputElement).value;
this.courthouseSelect.emit(inputValue);
},
};
props: AccessibleAutocompleteProps | null = null;

ngOnInit(): void {
this.props = {
id: 'courthouse',
source: [],
minLength: 1,
name: 'courthouse',
showAllValues: this.showAllValues,
onConfirm: () => {
// have to grab input value like this due to onConfirm(courthouse) emitting undefined onBlur
const inputValue = (document.querySelector('input[name=courthouse]') as HTMLInputElement).value;
this.courthouseSelect.emit(inputValue);
},
};
}

ngOnChanges(): void {
if (document.querySelector('input[name=courthouse]')) {
Expand All @@ -47,9 +63,9 @@ export class CourthouseComponent implements AfterViewInit, OnChanges {
}

ngAfterViewInit(): void {
if (this.courthouses.length) {
if (this.courthouses.length && this.props) {
this.props.element = this.autocompleteContainer.nativeElement;
this.props.source = this.courthouses.map((courthouse) => courthouse.display_name);
this.props.source = this.courthouses.map((courthouse) => courthouse.displayName);
this.props.defaultValue = this.courthouse;
accessibleAutocomplete(this.props);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { Courthouse } from '@admin-types/courthouses/courthouse.type';
import { NgClass, NgFor, NgIf } from '@angular/common';
import { Component, DestroyRef, inject, input, model, OnInit, output, signal, ViewChild } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { NonNullableFormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
import { CourthouseComponent } from '@common/courthouse/courthouse.component';
import { SpecificOrRangeDatePickerComponent } from '@common/specific-or-range-date-picker/specific-or-range-date-picker.component';
import { CaseSearchFormErrorMessages } from '@constants/case-search-form-error-messages';
import { CourthouseData, ErrorSummaryEntry } from '@core-types/index';
import { ErrorSummaryEntry } from '@core-types/index';
import { NestedKeys } from '@core-types/utils/nested-keys.type';
import { CaseSearchForm, CaseSearchFormValues } from '@portal-types/index';
import { ErrorMessageService } from '@services/error/error-message.service';
Expand All @@ -32,7 +33,7 @@ export class CaseSearchFormComponent implements OnInit {
errorMsgService = inject(ErrorMessageService);

formValues = input<CaseSearchFormValues | null>(null);
courthouses = input<CourthouseData[]>([]);
courthouses = input<Courthouse[]>([]);

isSubmitted = model(false);
isAdvancedSearch = model(false);
Expand Down
12 changes: 10 additions & 2 deletions src/app/portal/components/search/search.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Courthouse } from '@admin-types/courthouses/courthouse.type';
import { provideHttpClient } from '@angular/common/http';
import { signal } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
Expand All @@ -11,12 +12,18 @@ import { CaseSearchService } from '../../services/case-search/case-search.servic
import { CaseSearchResultsComponent } from './case-search-results/case-search-results.component';
import { SearchComponent } from './search.component';

const mockCourthouses = [
const mockCourthousesData = [
{ courthouse_name: 'Reading', id: 0 },
{ courthouse_name: 'Slough', id: 1 },
{ courthouse_name: 'Ascot', id: 2 },
] as CourthouseData[];

const mockCourthouses = [
{ courthouseName: 'Reading', id: 0 },
{ courthouseName: 'Slough', id: 1 },
{ courthouseName: 'Ascot', id: 2 },
] as Courthouse[];

const mockFormValues: CaseSearchFormValues = {
caseNumber: '1',
courthouse: 'Reading',
Expand Down Expand Up @@ -48,7 +55,8 @@ describe('SearchComponent', () => {
} as unknown as CaseSearchService;

const fakeCourtHouseService = {
getCourthouses: jest.fn().mockReturnValue(of(mockCourthouses)),
getCourthouses: jest.fn().mockReturnValue(of(mockCourthousesData)),
mapCourthouseDataToCourthouses: jest.fn().mockReturnValue(mockCourthouses),
} as unknown as CourthouseService;

const fakeErrorMsgService = {
Expand Down
8 changes: 7 additions & 1 deletion src/app/portal/components/search/search.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { CaseSearchService } from '@services/case-search/case-search.service';
import { CourthouseService } from '@services/courthouses/courthouses.service';
import { ErrorMessageService } from '@services/error/error-message.service';
import { ScrollService } from '@services/scroll/scroll.service';
import { map } from 'rxjs';
import { CaseSearchFormComponent } from './case-search-form/case-search-form.component';
import { CaseSearchResultsComponent } from './case-search-results/case-search-results.component';
import { SearchErrorComponent } from './search-error/search-error.component';
Expand All @@ -35,7 +36,12 @@ export class SearchComponent {
errorMsgService = inject(ErrorMessageService);
scrollService = inject(ScrollService);

courthouses = toSignal(this.courthouseService.getCourthouses(), { initialValue: [] });
courthouses = toSignal(
this.courthouseService
.getCourthouses()
.pipe(map((data) => this.courthouseService.mapCourthouseDataToCourthouses(data))),
{ initialValue: [] }
);
errorSummary = signal<ErrorSummaryEntry[]>([]);

results = toSignal(this.caseSearchService.results$, { initialValue: null });
Expand Down

0 comments on commit 81c9dcf

Please sign in to comment.