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

Bugfix/alcs 1038 home page for notifications #1009

Merged
merged 3 commits into from
Sep 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,9 @@ <h4>Cards Assigned to Me: {{ totalFiles }}</h4>
<div class="subheading2">Non-Applications</div>
<app-assigned-table [assignedFiles]="nonApplications"></app-assigned-table>
</section>

<section *ngIf="notifications.length">
<div class="subheading2">Notifications</div>
<app-assigned-table [assignedFiles]="notifications"></app-assigned-table>
</section>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ import { CovenantDto } from '../../../services/covenant/covenant.dto';
import { HomeService } from '../../../services/home/home.service';
import { NoticeOfIntentModificationDto } from '../../../services/notice-of-intent/notice-of-intent-modification/notice-of-intent-modification.dto';
import { NoticeOfIntentDto } from '../../../services/notice-of-intent/notice-of-intent.dto';
import { NotificationDto } from '../../../services/notification/notification.dto';
import { PlanningReviewDto } from '../../../services/planning-review/planning-review.dto';
import {
COVENANT_TYPE_LABEL,
MODIFICATION_TYPE_LABEL,
NOTIFICATION_LABEL,
PLANNING_TYPE_LABEL,
RECON_TYPE_LABEL,
RETROACTIVE_TYPE_LABEL,
Expand All @@ -26,6 +28,7 @@ export class AssignedComponent implements OnInit {
noticeOfIntents: AssignedToMeFile[] = [];
applications: AssignedToMeFile[] = [];
nonApplications: AssignedToMeFile[] = [];
notifications: AssignedToMeFile[] = [];
totalFiles = 0;

constructor(private homeService: HomeService, private applicationService: ApplicationService) {}
Expand All @@ -44,6 +47,7 @@ export class AssignedComponent implements OnInit {
covenants,
noticeOfIntents,
noticeOfIntentModifications,
notifications,
} = await this.homeService.fetchAssignedToMe();

this.noticeOfIntents = [
Expand Down Expand Up @@ -110,7 +114,19 @@ export class AssignedComponent implements OnInit {
.sort((a, b) => a.date! - b.date!),
];

this.totalFiles = this.applications.length + this.nonApplications.length + this.noticeOfIntents.length;
this.notifications = [
...notifications
.filter((r) => r.card.highPriority)
.map((r) => this.mapNotifications(r))
.sort((a, b) => a.date! - b.date!),
...notifications
.filter((r) => !r.card.highPriority)
.map((r) => this.mapNotifications(r))
.sort((a, b) => a.date! - b.date!),
];

this.totalFiles =
this.applications.length + this.nonApplications.length + this.noticeOfIntents.length + this.notifications.length;
}

private mapCovenant(c: CovenantDto): AssignedToMeFile {
Expand Down Expand Up @@ -193,4 +209,15 @@ export class AssignedComponent implements OnInit {
: [MODIFICATION_TYPE_LABEL],
};
}

private mapNotifications(a: NotificationDto) {
return {
title: `${a.fileNumber} (${a.applicant})`,
type: a.card!.type,
card: a.card,
date: a.dateSubmittedToAlc,
highPriority: a.card!.highPriority,
labels: [NOTIFICATION_LABEL],
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@
[type]="PLANNING_TYPE_LABEL"
>
</app-application-type-pill>
<app-application-type-pill
[useShortLabel]="true"
*ngIf="element.parentType === 'notification'"
[type]="NOTIFICATION_LABEL"
>
</app-application-type-pill>

</td>
</ng-container>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { AssigneeDto, UserDto } from '../../../../services/user/user.dto';
import {
COVENANT_TYPE_LABEL,
MODIFICATION_TYPE_LABEL,
NOTIFICATION_LABEL,
PLANNING_TYPE_LABEL,
RECON_TYPE_LABEL,
} from '../../../../shared/application-type-pill/application-type-pill.constants';
Expand All @@ -25,6 +26,7 @@ export class SubtaskTableComponent {
PLANNING_TYPE_LABEL = PLANNING_TYPE_LABEL;
COVENANT_TYPE_LABEL = COVENANT_TYPE_LABEL;
RECON_TYPE_LABEL = RECON_TYPE_LABEL;
NOTIFICATION_LABEL = NOTIFICATION_LABEL;

constructor(private router: Router, private cardSubtaskService: CardSubtaskService) {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,8 @@ <h4>{{ subtaskLabel }} Subtasks: {{ totalSubtaskCount }}</h4>
<div class="subheading2">Non-Applications</div>
<app-subtask-table [subtasks]="nonApplicationSubtasks" [users]="users"></app-subtask-table>
</section>
<section *ngIf="notificationSubtasks.length">
<div class="subheading2">Notifications</div>
<app-subtask-table [subtasks]="notificationSubtasks" [users]="users"></app-subtask-table>
</section>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export class SubtaskComponent implements OnInit, OnDestroy {
applicationSubtasks: HomepageSubtaskDto[] = [];
noticeOfIntentSubtasks: HomepageSubtaskDto[] = [];
nonApplicationSubtasks: HomepageSubtaskDto[] = [];
notificationSubtasks: HomepageSubtaskDto[] = [];

showNoi = true;
showAppAndNonApp = true;
Expand Down Expand Up @@ -59,6 +60,7 @@ export class SubtaskComponent implements OnInit, OnDestroy {
const covenants = allSubtasks.filter((s) => s.card.type === CardType.COV);
const nois = allSubtasks.filter((s) => s.card.type === CardType.NOI);
const noiModifications = allSubtasks.filter((s) => s.card.type === CardType.NOI_MODI);
const notifications = allSubtasks.filter((s) => s.card.type === CardType.NOTIFICATION);

this.applicationSubtasks = [
...applications.filter((a) => a.card.highPriority).sort((a, b) => b.activeDays! - a.activeDays!),
Expand All @@ -83,6 +85,10 @@ export class SubtaskComponent implements OnInit, OnDestroy {
...covenants.filter((r) => !r.card.highPriority).sort((a, b) => a.createdAt! - b.createdAt!),
];

this.notificationSubtasks = [
...notifications.filter((r) => !r.card.highPriority).sort((a, b) => a.createdAt! - b.createdAt!),
];

if (this.showNoi) {
this.totalSubtaskCount = this.noticeOfIntentSubtasks.length;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export interface HomepageSubtaskDto extends CardSubtaskDto {
activeDays?: number;
paused: boolean;
appType?: ApplicationTypeDto;
parentType: 'application' | 'reconsideration' | 'covenant' | 'modification' | 'planning-review';
parentType: 'application' | 'reconsideration' | 'covenant' | 'modification' | 'planning-review' | 'notification';
}

export enum CARD_SUBTASK_TYPE {
Expand Down
2 changes: 2 additions & 0 deletions alcs-frontend/src/app/services/home/home.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { CARD_SUBTASK_TYPE, HomepageSubtaskDto } from '../card/card-subtask/card
import { CovenantDto } from '../covenant/covenant.dto';
import { NoticeOfIntentModificationDto } from '../notice-of-intent/notice-of-intent-modification/notice-of-intent-modification.dto';
import { NoticeOfIntentDto } from '../notice-of-intent/notice-of-intent.dto';
import { NotificationDto } from '../notification/notification.dto';
import { PlanningReviewDto } from '../planning-review/planning-review.dto';

@Injectable({
Expand All @@ -27,6 +28,7 @@ export class HomeService {
covenants: CovenantDto[];
noticeOfIntents: NoticeOfIntentDto[];
noticeOfIntentModifications: NoticeOfIntentModificationDto[];
notifications: NotificationDto[];
}>(`${environment.apiUrl}/home/assigned`)
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,11 @@ export const DECISION_CONDITION_SUPERSEDED_LABEL = {
borderColor: '#C08106',
textColor: '#000',
};

export const NOTIFICATION_LABEL = {
label: 'Statutory Right of Way',
shortLabel: 'SRW',
backgroundColor: '#fff',
borderColor: '#59ADFA',
textColor: '#313132',
};
57 changes: 56 additions & 1 deletion services/apps/alcs/src/alcs/home/home.controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { ApplicationSubtaskProfile } from '../../common/automapper/application-s
import { ApplicationProfile } from '../../common/automapper/application.automapper.profile';
import { CardProfile } from '../../common/automapper/card.automapper.profile';
import { CovenantProfile } from '../../common/automapper/covenant.automapper.profile';
import { NotificationProfile } from '../../common/automapper/notification.automapper.profile';
import { UserProfile } from '../../common/automapper/user.automapper.profile';
import { ApplicationModificationService } from '../application-decision/application-modification/application-modification.service';
import { ApplicationReconsiderationService } from '../application-decision/application-reconsideration/application-reconsideration.service';
Expand All @@ -30,6 +31,8 @@ import { NoticeOfIntentModification } from '../notice-of-intent-decision/notice-
import { NoticeOfIntentModificationService } from '../notice-of-intent-decision/notice-of-intent-modification/notice-of-intent-modification.service';
import { NoticeOfIntent } from '../notice-of-intent/notice-of-intent.entity';
import { NoticeOfIntentService } from '../notice-of-intent/notice-of-intent.service';
import { Notification } from '../notification/notification.entity';
import { NotificationService } from '../notification/notification.service';
import { PlanningReview } from '../planning-review/planning-review.entity';
import { PlanningReviewService } from '../planning-review/planning-review.service';
import { HomeController } from './home.controller';
Expand All @@ -45,6 +48,7 @@ describe('HomeController', () => {
let mockApplicationTimeTrackingService: DeepMocked<ApplicationTimeTrackingService>;
let mockNoticeOfIntentService: DeepMocked<NoticeOfIntentService>;
let mockNoticeOfIntentModificationService: DeepMocked<NoticeOfIntentModificationService>;
let mockNotificationService: DeepMocked<NotificationService>;

beforeEach(async () => {
mockApplicationService = createMock();
Expand All @@ -56,6 +60,7 @@ describe('HomeController', () => {
mockCovenantService = createMock();
mockNoticeOfIntentService = createMock();
mockNoticeOfIntentModificationService = createMock();
mockNotificationService = createMock();

const module: TestingModule = await Test.createTestingModule({
imports: [
Expand Down Expand Up @@ -109,11 +114,16 @@ describe('HomeController', () => {
provide: NoticeOfIntentModificationService,
useValue: mockNoticeOfIntentModificationService,
},
{
provide: NotificationService,
useValue: mockNotificationService,
},
ApplicationProfile,
ApplicationSubtaskProfile,
CovenantProfile,
UserProfile,
CardProfile,
NotificationProfile,
...mockKeyCloakProviders,
],
}).compile();
Expand All @@ -134,6 +144,8 @@ describe('HomeController', () => {
mockNoticeOfIntentService.mapToDtos.mockResolvedValue([]);
mockNoticeOfIntentModificationService.getBy.mockResolvedValue([]);
mockNoticeOfIntentModificationService.mapToDtos.mockResolvedValue([]);
mockNotificationService.getBy.mockResolvedValue([]);
mockNotificationService.mapToDtos.mockResolvedValue([]);

mockApplicationTimeTrackingService.fetchActiveTimes.mockResolvedValue(
new Map(),
Expand All @@ -159,14 +171,17 @@ describe('HomeController', () => {
mockNoticeOfIntentModificationService.getWithIncompleteSubtaskByType.mockResolvedValue(
[],
);
mockNotificationService.getWithIncompleteSubtaskByType.mockResolvedValue(
[],
);
});

it('should be defined', () => {
expect(controller).toBeDefined();
});

describe('Assigned To Me', () => {
it('should call ApplicationService with the correct filter for assigned', async () => {
it('should call Application, NOI, Notification services with the correct filter for assigned', async () => {
const userId = 'fake-user-id';
await controller.getAssignedToMe({
user: {
Expand Down Expand Up @@ -201,6 +216,23 @@ describe('HomeController', () => {
expect(mockPlanningReviewService.getBy.mock.calls[0][0]).toEqual(
filterCondition,
);

expect(mockNoticeOfIntentService.getBy).toHaveBeenCalledTimes(1);
expect(mockNoticeOfIntentService.getBy.mock.calls[0][0]).toEqual(
filterCondition,
);

expect(mockNoticeOfIntentModificationService.getBy).toHaveBeenCalledTimes(
1,
);
expect(
mockNoticeOfIntentModificationService.getBy.mock.calls[0][0],
).toEqual(filterCondition);

expect(mockNotificationService.getBy).toHaveBeenCalledTimes(1);
expect(mockNotificationService.getBy.mock.calls[0][0]).toEqual(
filterCondition,
);
});
});

Expand Down Expand Up @@ -382,5 +414,28 @@ describe('HomeController', () => {
mockNoiModification.noticeOfIntent.applicant,
);
});

it('should call Notification Service and map it', async () => {
const mockNotification = new Notification({
applicant: 'fake-applicant',
fileNumber: 'fileNumber',
card: initCardMockEntity('222'),
});
mockNotificationService.getWithIncompleteSubtaskByType.mockResolvedValue([
mockNotification,
]);

const res = await controller.getIncompleteSubtasksByType(
CARD_SUBTASK_TYPE.PEER_REVIEW,
);

expect(res.length).toEqual(1);
expect(
mockNotificationService.getWithIncompleteSubtaskByType,
).toHaveBeenCalledTimes(1);

expect(res[0].title).toContain(mockNotification.fileNumber);
expect(res[0].title).toContain(mockNotification.applicant);
});
});
});
40 changes: 40 additions & 0 deletions services/apps/alcs/src/alcs/home/home.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import { NoticeOfIntentModificationService } from '../notice-of-intent-decision/
import { NoticeOfIntentDto } from '../notice-of-intent/notice-of-intent.dto';
import { NoticeOfIntent } from '../notice-of-intent/notice-of-intent.entity';
import { NoticeOfIntentService } from '../notice-of-intent/notice-of-intent.service';
import { Notification } from '../notification/notification.entity';
import { NotificationService } from '../notification/notification.service';
import { PlanningReviewDto } from '../planning-review/planning-review.dto';
import { PlanningReview } from '../planning-review/planning-review.entity';
import { PlanningReviewService } from '../planning-review/planning-review.service';
Expand All @@ -59,6 +61,7 @@ export class HomeController {
private covenantService: CovenantService,
private noticeOfIntentService: NoticeOfIntentService,
private noticeOfIntentModificationService: NoticeOfIntentModificationService,
private notificationService: NotificationService,
) {}

@Get('/assigned')
Expand Down Expand Up @@ -107,6 +110,10 @@ export class HomeController {
const noticeOfIntentModifications =
await this.noticeOfIntentModificationService.getBy(assignedFindOptions);

const notifications = await this.notificationService.getBy(
assignedFindOptions,
);

const result = {
noticeOfIntents: await this.noticeOfIntentService.mapToDtos(
noticeOfIntents,
Expand All @@ -124,6 +131,7 @@ export class HomeController {
),
modifications: await this.modificationService.mapToDtos(modifications),
covenants: await this.covenantService.mapToDtos(covenants),
notifications: await this.notificationService.mapToDtos(notifications),
};

return result;
Expand Down Expand Up @@ -191,6 +199,15 @@ export class HomeController {
noiModificationsWithSubtasks,
);

const notificationsWithSubtasks =
await this.notificationService.getWithIncompleteSubtaskByType(
subtaskType,
);

const notificationSubtasks = this.mapNotificationsToDtos(
notificationsWithSubtasks,
);

return [
...noticeOfIntentSubtasks,
...applicationSubtasks,
Expand All @@ -199,6 +216,7 @@ export class HomeController {
...planningReviewSubtasks,
...covenantReviewSubtasks,
...noiModificationsSubtasks,
...notificationSubtasks,
];
}

Expand Down Expand Up @@ -369,4 +387,26 @@ export class HomeController {
}
return result;
}

private mapNotificationsToDtos(notifications: Notification[]) {
const result: HomepageSubtaskDTO[] = [];
for (const notification of notifications) {
if (notification.card) {
for (const subtask of notification.card.subtasks) {
result.push({
type: subtask.type,
createdAt: subtask.createdAt.getTime(),
assignee: this.mapper.map(subtask.assignee, User, AssigneeDto),
uuid: subtask.uuid,
card: this.mapper.map(notification.card, Card, CardDto),
completedAt: subtask.completedAt?.getTime(),
paused: false,
title: `${notification.fileNumber} (${notification.applicant})`,
parentType: PARENT_TYPE.NOTIFICATION,
});
}
}
}
return result;
}
}
Loading