diff --git a/front-end/src/app/app.module.ts b/front-end/src/app/app.module.ts index 6bf791367e..bb5aeb430d 100644 --- a/front-end/src/app/app.module.ts +++ b/front-end/src/app/app.module.ts @@ -15,6 +15,8 @@ import { spinnerReducer } from './store/spinner.reducer'; import { CommitteeAccountEffects } from './store/committee-account.effects'; import { LoginEffects } from './store/login.effects'; import { AppState } from './store/app-state.model'; +import { labelLookupReducer } from './store/label-lookup.reducer'; +import { LabelLookupEffects } from './store/label-lookup.effects'; // PrimeNG import { ConfirmationService, MessageService } from 'primeng/api'; @@ -45,7 +47,7 @@ import { HttpErrorInterceptor } from './shared/interceptors/http-error.intercept // Save ngrx store to localStorage dynamically function localStorageSyncReducer(reducer: ActionReducer): ActionReducer { return localStorageSync({ - keys: ['committeeAccount', 'spinnerOn', 'userLoginData'], + keys: ['committeeAccount', 'spinnerOn', 'userLoginData', 'reportCodeLabelList'], storageKeySerializer: (key) => `fecfile_online_${key}`, rehydrate: true, })(reducer); @@ -77,10 +79,11 @@ const metaReducers: Array> = [localStorageSyncRedu committeeAccount: committeeAccountReducer, spinnerOn: spinnerReducer, userLoginData: loginReducer, + reportCodeLabelList: labelLookupReducer, }, { metaReducers } ), - EffectsModule.forRoot([CommitteeAccountEffects, LoginEffects]), + EffectsModule.forRoot([CommitteeAccountEffects, LoginEffects, LabelLookupEffects]), MenubarModule, MenuModule, PanelModule, diff --git a/front-end/src/app/reports/report-list/report-list.component.html b/front-end/src/app/reports/report-list/report-list.component.html index 2063129488..cb8cbe1108 100644 --- a/front-end/src/app/reports/report-list/report-list.component.html +++ b/front-end/src/app/reports/report-list/report-list.component.html @@ -38,8 +38,8 @@
Recent reports
Form type - - Type of report + + Type of report Coverage dates @@ -59,7 +59,7 @@
Recent reports
{{ item.form_type | label: f3xFormTypeLabels }} - {{ item.report_code | label: f3xReportCodeLabels }} + {{ (this.reportCodeLabelList$ | async | findOnReportCodePipe: item.report_code)?.label }} {{ item.coverage_from_date | fecDate }} - {{ item.coverage_through_date | fecDate }} { +export class ReportListComponent extends TableListBaseComponent implements OnInit { f3xFormTypeLabels: LabelList = F3xFormTypeLabels; - f3xReportCodeLabels: LabelList = F3xReportCodeLabels; f3xFormVerionLabels: LabelList = F3xFormVersionLabels; + reportCodeLabelList$: Observable = new Observable(); constructor( + private store: Store, protected override messageService: MessageService, protected override confirmationService: ConfirmationService, protected override elementRef: ElementRef, @@ -31,6 +32,13 @@ export class ReportListComponent extends TableListBaseComponent { super(messageService, confirmationService, elementRef); } + override ngOnInit() { + this.loading = true; + this.loadItemService(this.itemService); + this.reportCodeLabelList$ = this.store.select(selectReportCodeLabelList); + this.store.dispatch(updateLabelLookupAction()); + } + protected getEmptyItem(): F3xSummary { return new F3xSummary(); } diff --git a/front-end/src/app/shared/pipes/report-code-label-list.pipe.spec.ts b/front-end/src/app/shared/pipes/report-code-label-list.pipe.spec.ts new file mode 100644 index 0000000000..0e8f34c763 --- /dev/null +++ b/front-end/src/app/shared/pipes/report-code-label-list.pipe.spec.ts @@ -0,0 +1,37 @@ +import { ReportCodeLabelList } from '../utils/reportCodeLabels.utils'; +import { FindOnReportCodePipe } from './report-code-label-list.pipe'; + +describe('FindOnReportCodePipe', () => { + const labelList: ReportCodeLabelList = [ + { + label: 'Quarter 1', + report_code: 'Q1', + }, + { + label: 'Quarter 2', + report_code: 'Q2', + }, + ]; + let pipe: FindOnReportCodePipe; + + beforeEach(() => { + pipe = new FindOnReportCodePipe(); + }); + + it('create an instance', () => { + expect(pipe).toBeTruthy(); + }); + + it('transforms should return a ReportCodeLabel object', () => { + expect(pipe.transform(labelList, 'Q1')).toEqual({ label: 'Quarter 1', report_code: 'Q1' }); + expect(pipe.transform(labelList, 'Q2')).toEqual({ label: 'Quarter 2', report_code: 'Q2' }); + }); + + it('transforms should return empty ReportCodeLabel object if no label found', () => { + expect(pipe.transform(labelList, 'does-not-exist')).toBe(undefined); + }); + + it('transforms should return an empty ReportCodeLabel object if the labelList is null', () => { + expect(pipe.transform(null, 'Q1')).toBe(undefined); + }); +}); diff --git a/front-end/src/app/shared/pipes/report-code-label-list.pipe.ts b/front-end/src/app/shared/pipes/report-code-label-list.pipe.ts new file mode 100644 index 0000000000..5a876e109b --- /dev/null +++ b/front-end/src/app/shared/pipes/report-code-label-list.pipe.ts @@ -0,0 +1,14 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import { ReportCodeLabelList, ReportCodeLabel } from '../utils/reportCodeLabels.utils'; + +@Pipe({ name: 'findOnReportCodePipe' }) +export class FindOnReportCodePipe implements PipeTransform { + transform(list: ReportCodeLabelList | null, reportCode: string): ReportCodeLabel | undefined { + let label: ReportCodeLabel | undefined = undefined; + + if (list != undefined && list?.length > 0) { + label = list.find((item) => item.report_code == reportCode); + } + return label; + } +} diff --git a/front-end/src/app/shared/shared.module.ts b/front-end/src/app/shared/shared.module.ts index 35582096eb..ab676d54de 100644 --- a/front-end/src/app/shared/shared.module.ts +++ b/front-end/src/app/shared/shared.module.ts @@ -1,12 +1,13 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { LabelPipe } from './pipes/label.pipe'; +import { FindOnReportCodePipe } from './pipes/report-code-label-list.pipe'; import { ErrorMessagesComponent } from './components/error-messages/error-messages.component'; import { FecDatePipe } from './pipes/fec-date.pipe'; @NgModule({ imports: [CommonModule], - declarations: [LabelPipe, ErrorMessagesComponent, FecDatePipe], - exports: [FecDatePipe, LabelPipe, ErrorMessagesComponent], + declarations: [LabelPipe, ErrorMessagesComponent, FecDatePipe, FindOnReportCodePipe], + exports: [FecDatePipe, LabelPipe, ErrorMessagesComponent, FindOnReportCodePipe], }) export class SharedModule {} diff --git a/front-end/src/app/shared/utils/label.utils.ts b/front-end/src/app/shared/utils/label.utils.ts index a8f348b456..78511fac40 100644 --- a/front-end/src/app/shared/utils/label.utils.ts +++ b/front-end/src/app/shared/utils/label.utils.ts @@ -1,5 +1,4 @@ export type LabelList = string[][]; - export type PrimeOptions = { name: string; code: string }[]; /** diff --git a/front-end/src/app/shared/utils/reportCodeLabels.utils.ts b/front-end/src/app/shared/utils/reportCodeLabels.utils.ts new file mode 100644 index 0000000000..f2e11bdc88 --- /dev/null +++ b/front-end/src/app/shared/utils/reportCodeLabels.utils.ts @@ -0,0 +1,2 @@ +export type ReportCodeLabel = { report_code: string; label: string }; +export type ReportCodeLabelList = ReportCodeLabel[]; diff --git a/front-end/src/app/store/app-state.model.ts b/front-end/src/app/store/app-state.model.ts index 5ca2e602f3..49b7e42da7 100644 --- a/front-end/src/app/store/app-state.model.ts +++ b/front-end/src/app/store/app-state.model.ts @@ -1,8 +1,10 @@ import { CommitteeAccount } from 'app/shared/models/committee-account.model'; import { UserLoginData } from 'app/shared/models/user.model'; +import { ReportCodeLabelList } from '../shared/utils/reportCodeLabels.utils'; export interface AppState { committeeAccount: CommitteeAccount; spinnerOn: boolean; userLoginData: UserLoginData; + reportCodeLabelList: ReportCodeLabelList; } diff --git a/front-end/src/app/store/label-lookup.actions.ts b/front-end/src/app/store/label-lookup.actions.ts new file mode 100644 index 0000000000..3e4d808350 --- /dev/null +++ b/front-end/src/app/store/label-lookup.actions.ts @@ -0,0 +1,10 @@ +import { createAction, props } from '@ngrx/store'; +import { ReportCodeLabelList } from '../shared/utils/reportCodeLabels.utils'; + +export const setLabelLookupAction = createAction( + '[Label Lookup] Report Code Labels Retrieved', + props<{ payload: ReportCodeLabelList }>() +); + +export const errorRetrievingLabelLookupAction = createAction('[Label Lookup] Report Code Labels Retrieval Error'); +export const updateLabelLookupAction = createAction('[Label List] Update Report Code Labels'); diff --git a/front-end/src/app/store/label-lookup.effects.ts b/front-end/src/app/store/label-lookup.effects.ts new file mode 100644 index 0000000000..26d0f75b3e --- /dev/null +++ b/front-end/src/app/store/label-lookup.effects.ts @@ -0,0 +1,32 @@ +import { Injectable } from '@angular/core'; +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { first, of } from 'rxjs'; +import { map, mergeMap, catchError } from 'rxjs/operators'; +import { + setLabelLookupAction, + errorRetrievingLabelLookupAction, + updateLabelLookupAction, +} from './label-lookup.actions'; +import { ApiService } from '../shared/services/api.service'; +import { ReportCodeLabelList } from '../shared/utils/reportCodeLabels.utils'; + +@Injectable() +export class LabelLookupEffects { + constructor(private actions$: Actions, private apiService: ApiService) {} + + loadLabelLookup$ = createEffect(() => + this.actions$.pipe( + ofType(updateLabelLookupAction.type), + first(), + mergeMap(() => + this.apiService.get('/report-code-labels').pipe( + map((reportCodeLabelList: ReportCodeLabelList) => ({ + type: setLabelLookupAction.type, + payload: reportCodeLabelList, + })), + catchError(() => of({ type: errorRetrievingLabelLookupAction.type })) + ) + ) + ) + ); +} diff --git a/front-end/src/app/store/label-lookup.reducer.ts b/front-end/src/app/store/label-lookup.reducer.ts new file mode 100644 index 0000000000..02512965b2 --- /dev/null +++ b/front-end/src/app/store/label-lookup.reducer.ts @@ -0,0 +1,14 @@ +import { createReducer, on, Action } from '@ngrx/store'; +import { setLabelLookupAction } from './label-lookup.actions'; +import { ReportCodeLabelList } from '../shared/utils/reportCodeLabels.utils'; + +export const initialState: ReportCodeLabelList = []; + +const _labelLookupReducer = createReducer( + initialState, + on(setLabelLookupAction, (_state, update) => update.payload) +); + +export function labelLookupReducer(state: ReportCodeLabelList | undefined, action: Action) { + return _labelLookupReducer(state, action); +} diff --git a/front-end/src/app/store/label-lookup.selectors.ts b/front-end/src/app/store/label-lookup.selectors.ts new file mode 100644 index 0000000000..b78ad5abce --- /dev/null +++ b/front-end/src/app/store/label-lookup.selectors.ts @@ -0,0 +1,4 @@ +import { createFeatureSelector } from '@ngrx/store'; +import { ReportCodeLabelList } from '../shared/utils/reportCodeLabels.utils'; + +export const selectReportCodeLabelList = createFeatureSelector('reportCodeLabelList');