Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ALCS-2226: Add flagging to apps/NOI's #2079

Merged
merged 13 commits into from
Jan 23, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,24 @@ <h5>Res #{{ decision.resolutionNumber }}/{{ decision.resolutionYear }}</h5>
<app-application-type-pill [type]="releasedDecisionLabel"></app-application-type-pill>
</ng-container>
</div>

<div class="flag-button-container">
<button
type="button"
(click)="decision.isFlagged ? unflag(decision) : flag(decision, false)"
class="flag-button"
[class.flagged]="decision.isFlagged"
[matTooltip]="decision.isFlagged ? 'Click to unflag' : ''"
>
<mat-icon svgIcon="personal_places"></mat-icon>
Flag{{ decision.isFlagged ? 'ged' : '' }} for Condition Follow Up
</button>
</div>

<ng-container *ngIf="decision.isDraft">
<button mat-flat-button color="primary" (click)="onEdit(decision)">Edit Draft</button>
<button class="edit-decision-button" mat-flat-button color="primary" (click)="onEdit(decision)">
Edit Draft
</button>
</ng-container>

<div
Expand Down Expand Up @@ -183,6 +199,28 @@ <h5>Res #{{ decision.resolutionNumber }}/{{ decision.resolutionYear }}</h5>
</button>
</div>
</div>

<ng-container *ngIf="decision.isFlagged">
<section class="flag-details">
<div class="flag-details-header">
<div class="flag-details-flagger">
<mat-icon svgIcon="personal_places"></mat-icon><strong>{{ decision.flaggedBy?.prettyName }}</strong>
</div>
<div><strong>Follow-Up Date:</strong> {{ formatDate(decision.followUpAt) || 'No Data' }}</div>
</div>

<div class="flag-details-body">
<strong>Flagged for condition follow-up because:</strong> {{ decision.reasonFlagged }}
</div>

<div class="flag-details-footer">
<div class="flag-details-edited-details">
{{ formatDate(decision.flagEditedAt, true) }} (Last Edited by {{ decision.flagEditedBy?.prettyName }})
</div>
<button mat-button type="button" (click)="flag(decision, true)">Edit</button>
</div>
</section>
</ng-container>
</section>
<ng-container *ngIf="isSummary">
<!-- Components -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,20 @@ hr {
}

.header {
display: flex;
justify-content: space-between;
display: grid;
grid-template-columns: auto auto auto;
grid-template-rows: auto auto;
row-gap: 10px;
column-gap: 28px;
margin-bottom: 36px;

.title {
display: flex;
align-items: center;
justify-content: space-between;
gap: 28px;
grid-row: 1/2;
grid-column: 1/2;

.days {
display: inline-block;
Expand All @@ -78,6 +83,11 @@ hr {
}
}

.edit-decision-button {
grid-row: 1/2;
grid-column: 3/4;
}

.loading-overlay {
position: absolute;
z-index: 2;
Expand Down Expand Up @@ -187,3 +197,85 @@ hr {
color: colors.$link-color;
}
}

.flag-button-container {
justify-self: end;
grid-row: 2/3;
grid-column: 1/4;

@media screen and (min-width: 1440px) {
grid-row: 1/2;
grid-column: 2/3;
}
}

.flag-button {
display: flex;
align-items: center;
column-gap: 5px;

text-align: left;
font-weight: normal;
text-wrap: nowrap;

background-color: transparent;
padding: 5px;
border: none;
border-radius: 5px;
margin: 0;

&:hover {
background-color: colors.$grey-light;
}

mat-icon {
flex-shrink: 0;
}

&.flagged {
mat-icon {
color: blue;
}
}
}

.flag-details {
background-color: white;
display: flex;
flex-direction: column;
gap: 16px;

padding: 16px;
border: 1px solid colors.$grey;
border-radius: 4px;
}

.flag-details-header {
display: flex;
justify-content: space-between;
align-items: center;
}

.flag-details-flagger {
display: flex;
gap: 5px;

mat-icon {
color: blue;
}
}

.flag-details-body {
line-height: 1.5;
}

.flag-details-footer {
display: flex;
justify-content: space-between;
align-items: flex-end;
}

.flag-details-edited-details {
font-size: 12px;
color: colors.$grey;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@ import {
import { ApplicationDecisionV2Service } from '../../../../services/application/decision/application-decision-v2/application-decision-v2.service';
import { ToastService } from '../../../../services/toast/toast.service';
import { ConfirmationDialogService } from '../../../../shared/confirmation-dialog/confirmation-dialog.service';

import { DecisionV2Component } from './decision-v2.component';
import { HttpClient } from '@angular/common/http';

describe('DecisionV2Component', () => {
let component: DecisionV2Component;
let fixture: ComponentFixture<DecisionV2Component>;
let mockApplicationDecisionService: DeepMocked<ApplicationDecisionV2Service>;
let mockAppDetailService: DeepMocked<ApplicationDetailService>;
let mockApplicationDecisionComponentService: DeepMocked<ApplicationDecisionComponentService>;
let mockHttpClient: DeepMocked<HttpClient>;

beforeEach(async () => {
mockApplicationDecisionService = createMock();
Expand All @@ -36,6 +37,8 @@ describe('DecisionV2Component', () => {

mockApplicationDecisionComponentService = createMock();

mockHttpClient = createMock();

await TestBed.configureTestingModule({
imports: [MatSnackBarModule, MatMenuModule],
declarations: [DecisionV2Component],
Expand Down Expand Up @@ -72,6 +75,10 @@ describe('DecisionV2Component', () => {
provide: ActivatedRoute,
useValue: {},
},
{
provide: HttpClient,
useValue: mockHttpClient,
},
],
schemas: [NO_ERRORS_SCHEMA],
}).compileComponents();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ import { formatDateForApi } from '../../../../shared/utils/api-date-formatter';
import { RevertToDraftDialogComponent } from './revert-to-draft-dialog/revert-to-draft-dialog.component';
import { ApplicationConditionWithStatus, getEndDate } from '../../../../shared/utils/decision-methods';
import { openFileInline } from '../../../../shared/utils/file';
import { UserService } from '../../../../services/user/user.service';
import { UserDto } from '../../../../services/user/user.dto';
import { FlagDialogComponent, FlagDialogIO } from '../../../../shared/flag-dialog/flag-dialog.component';
import { UpdateApplicationDecisionDto } from '../../../../services/application/decision/application-decision-v2/application-decision-v2.dto';
import moment from 'moment';

type LoadingDecision = ApplicationDecisionWithLinkedResolutionDto & {
loading: boolean;
Expand Down Expand Up @@ -67,6 +72,7 @@ export class DecisionV2Component implements OnInit, OnDestroy {
isSummary = false;

conditions: Record<string, ApplicationConditionWithStatus[]> = {};
profile: UserDto | undefined;

constructor(
public dialog: MatDialog,
Expand All @@ -78,6 +84,7 @@ export class DecisionV2Component implements OnInit, OnDestroy {
private router: Router,
private activatedRouter: ActivatedRoute,
private elementRef: ElementRef,
private userService: UserService,
) {}

ngOnInit(): void {
Expand All @@ -90,6 +97,10 @@ export class DecisionV2Component implements OnInit, OnDestroy {
this.application = application;
}
});

this.userService.$userProfile.pipe(takeUntil(this.$destroy)).subscribe((profile) => {
this.profile = profile;
});
}

async loadDecisions(fileNumber: string) {
Expand Down Expand Up @@ -324,4 +335,81 @@ export class DecisionV2Component implements OnInit, OnDestroy {
return DECISION_CONDITION_ONGOING_LABEL;
}
}

async flag(decision: ApplicationDecisionWithLinkedResolutionDto, isEditing: boolean) {
this.dialog
.open(FlagDialogComponent, {
minWidth: '800px',
maxWidth: '800px',
maxHeight: '80vh',
width: '90%',
autoFocus: false,
data: {
isEditing,
decisionNumber: decision.index,
reasonFlagged: decision.reasonFlagged,
followUpAt: decision.followUpAt,
},
})
.beforeClosed()
.subscribe(async ({ isEditing, reasonFlagged, followUpAt, isSaving }: FlagDialogIO) => {
if (isSaving) {
const updateDto: UpdateApplicationDecisionDto = {
isDraft: decision.isDraft,
isFlagged: true,
reasonFlagged,
flagEditedByUuid: this.profile?.uuid,
flagEditedAt: moment().toDate().getTime(),
};

if (!isEditing) {
updateDto.flaggedByUuid = this.profile?.uuid;
}

if (followUpAt !== undefined) {
updateDto.followUpAt = followUpAt;
}

await this.decisionService.update(decision.uuid, updateDto);
await this.loadDecisions(this.fileNumber);
}
});
}

async unflag(decision: ApplicationDecisionWithLinkedResolutionDto) {
this.confirmationDialogService
.openDialog({
title: `Unflag Decision #${decision.index}`,
body: `<strong>Warning:</strong> Only remove if flagged in error.
<br>
<br>
This action will also remove the follow-up date and explanatory text
associated with the flag and cannot be undone.
<br>
<br>
Are you sure you want to remove the flag?`,
})
.subscribe(async (confirmed) => {
if (confirmed) {
await this.decisionService.update(decision.uuid, {
isDraft: decision.isDraft,
isFlagged: false,
reasonFlagged: null,
followUpAt: null,
flaggedByUuid: null,
flagEditedByUuid: null,
flagEditedAt: null,
});
await this.loadDecisions(this.fileNumber);
}
});
}

formatDate(timestamp?: number | null, includeTime = false): string {
if (timestamp === undefined || timestamp === null) {
return '';
}

return moment(new Date(timestamp)).format(`YYYY-MMM-DD ${includeTime ? 'hh:mm:ss A' : ''}`);
}
}
1 change: 1 addition & 0 deletions alcs-frontend/src/app/features/board/board.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,7 @@ export class BoardComponent implements OnInit, OnDestroy {
dateReceived: 0,
isExpired,
isPastDue,
decisionIsFlagged: applicationDecisionCondition.decisionIsFlagged,
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ <h3 class="card-title">
[type]="getStatusPill('RECONSIDERATION')"
></app-application-type-pill>
<app-application-type-pill [type]="getStatusPill('CONDITION')"></app-application-type-pill>

<mat-icon *ngIf="decision.isFlagged" svgIcon="personal_places" class="flag-icon"></mat-icon>
</div>
<div class="header-row">
<div class="left">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,15 @@
.pill-row {
display: flex;
flex-direction: row;
align-items: flex-end;
gap: 1px;
}

.no-data {
color: colors.$grey;
font-weight: 400;
}

.flag-icon {
color: blue;
}
Loading
Loading