| Yazar | SHA1 | Mesaj | Tarih |
|---|---|---|---|
|
|
481c37b21a | Add other name registration endpoints | 3 yıl önce |
|
|
890271cd70 | Add a register name service | 3 yıl önce |
|
|
e1877048c1 | Make notifications responsive | 3 yıl önce |
| @@ -8,8 +8,11 @@ | |||
| "watch": "ng build --watch --configuration development", | |||
| "test": "ng test", | |||
| "docker-build": "docker build -t b2rs-multi-stage-image .", | |||
| "docker-create": "docker run --name b2rs-app-container -d -p 80:80 b2rs-multi-stage-image", | |||
| "docker-build": "docker build -t b2rs-front-end-image .", | |||
| "docker-tag": "docker tag b2rs-front-end-image:latest 834628752744.dkr.ecr.ap-southeast-1.amazonaws.com/b2rs-front-end-image:latest", | |||
| "docker-push": "docker push 834628752744.dkr.ecr.ap-southeast-1.amazonaws.com/b2rs-front-end-image:latest", | |||
| "docker-create": "docker run --name b2rs-app-container -d -p 80:80 b2rs-front-end-image", | |||
| "docker-destroy": "docker container rm b2rs-app-container", | |||
| "docker-start": "docker start b2rs-app-container", | |||
| @@ -34,6 +34,7 @@ import { DashboardComponent } from './pages/dashboard/dashboard.component'; | |||
| import { FilterViewCardComponent } from './pages/dashboard/filter-view-card/filter-view-card.component'; | |||
| import { NavbarComponent } from './layout/navbar/navbar.component'; | |||
| import { NotificationsListComponent } from './layout/notifications/notifications-list/notifications-list.component'; | |||
| import { HttpClientModule } from '@angular/common/http'; | |||
| @NgModule({ | |||
| declarations: [ | |||
| @@ -73,6 +74,7 @@ import { NotificationsListComponent } from './layout/notifications/notifications | |||
| AppRoutingModule, | |||
| FormsModule, | |||
| FileUploadModule, | |||
| HttpClientModule, | |||
| ], | |||
| providers: [], | |||
| bootstrap: [AppComponent] | |||
| @@ -13,12 +13,16 @@ export class NavbarComponent implements OnInit, OnDestroy { | |||
| showLogout: boolean = false; | |||
| isShowingNotificationsSubscription: Subscription; | |||
| loginRoleSubscription: Subscription; | |||
| loginName: string = ''; | |||
| notificationsCount: number = 0; | |||
| constructor(loginService: LoginService, private notificationService: NotificationService) { | |||
| this.loginName = loginService.getLoginName(); | |||
| this.loginRoleSubscription = loginService.getLoginRoleObservable().subscribe(loginRole => { | |||
| this.loginName = loginService.getLoginName(); | |||
| }); | |||
| this.notificationsCount = notificationService.getAllowedNotifications().length; | |||
| this.isShowingNotificationsSubscription = this.notificationService.getIsShowingNotificationsObservable().subscribe(isShowingNotifications => this.isShowingNotifications = isShowingNotifications); | |||
| @@ -35,6 +39,10 @@ export class NavbarComponent implements OnInit, OnDestroy { | |||
| if (this.isShowingNotificationsSubscription) { | |||
| this.isShowingNotificationsSubscription.unsubscribe(); | |||
| } | |||
| if (this.loginRoleSubscription) { | |||
| this.loginRoleSubscription.unsubscribe(); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,6 +1,6 @@ | |||
| <ul> | |||
| <li *ngFor="let notification of allowedNotifications"> | |||
| <a *ngIf="notification.redirectionUrl" [routerLink]="notification.redirectionUrl"> | |||
| <a *ngIf="notification.redirectionUrl" (click)="closeNotifications()" [routerLink]="notification.redirectionUrl"> | |||
| <h5> {{ notification.text }} </h5> | |||
| <p *ngIf="notification.description"> {{ notification.description }} </p> | |||
| <span class="time-stamp"> {{ notification.timeStamp }} </span> | |||
| @@ -9,11 +9,15 @@ import { Notification, NotificationService } from 'src/app/services/notification | |||
| export class NotificationsListComponent implements OnInit { | |||
| allowedNotifications: Array<Notification> = []; | |||
| constructor(notificationService: NotificationService) { | |||
| constructor(private notificationService: NotificationService) { | |||
| this.allowedNotifications = notificationService.getAllowedNotifications(); | |||
| } | |||
| ngOnInit(): void { | |||
| } | |||
| closeNotifications() { | |||
| this.notificationService.setIsShowingNotifications(false); | |||
| } | |||
| } | |||
| @@ -1,4 +1,5 @@ | |||
| import { Component, OnInit } from '@angular/core'; | |||
| import { Component, OnDestroy, OnInit } from '@angular/core'; | |||
| import { Subscription } from 'rxjs'; | |||
| import { LoginService } from 'src/app/services/login.service'; | |||
| import { NotificationService } from 'src/app/services/notification.service'; | |||
| @@ -7,19 +8,30 @@ import { NotificationService } from 'src/app/services/notification.service'; | |||
| templateUrl: './tabs.component.html', | |||
| styleUrls: ['./tabs.component.scss'] | |||
| }) | |||
| export class TabsComponent implements OnInit { | |||
| export class TabsComponent implements OnInit, OnDestroy { | |||
| showNotifications: boolean = false; | |||
| showLogout: boolean = false; | |||
| loginRoleSubscription: Subscription; | |||
| loginName: string = ''; | |||
| notificationsCount: number = 0; | |||
| constructor(loginService: LoginService, notificationService: NotificationService) { | |||
| this.loginName = loginService.getLoginName(); | |||
| this.loginRoleSubscription = loginService.getLoginRoleObservable().subscribe(loginRole => { | |||
| this.loginName = loginService.getLoginName(); | |||
| }); | |||
| this.notificationsCount = notificationService.getAllowedNotifications().length; | |||
| } | |||
| ngOnInit(): void { | |||
| } | |||
| ngOnDestroy(): void { | |||
| if (this.loginRoleSubscription) { | |||
| this.loginRoleSubscription.unsubscribe(); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,7 +1,7 @@ | |||
| import { Component, OnInit } from '@angular/core'; | |||
| type State = 'VIEW INITIAL DETAILS'|'ENTER MORE DETAILS'|'ASSIGN COMMITTEE'|'REVIEW NON COMPLIANCE'|'CONCUR COMPLIANCE REVIEW'|'CLOSING REMARKS'|'PREPARE PRELIMINARY LETTER'|'RESPOND TO PRELIMINARY LETTER'; | |||
| type Role = 'Investigator'|'Hod'|'Panel'|'Customer'; | |||
| type Role = 'Investigator'|'Hod'|'Panel'|'Customer'|'Officer'; | |||
| @Component({ | |||
| selector: 'app-investigate-business-entities-and-individuals', | |||
| @@ -41,6 +41,8 @@ export class InvestigateBusinessEntitiesAndIndividualsComponent implements OnIni | |||
| this.loginRole = 'Panel'; | |||
| } else if (loginEmail && loginEmail.toLocaleLowerCase().startsWith('customer')) { | |||
| this.loginRole = 'Customer'; | |||
| } else if (loginEmail && loginEmail.toLocaleLowerCase().startsWith('officer')) { | |||
| this.loginRole = 'Officer'; | |||
| } else { | |||
| this.loginRole = 'Investigator'; | |||
| } | |||
| @@ -1,4 +1,5 @@ | |||
| import { Component, OnInit } from '@angular/core'; | |||
| import { LoginService } from 'src/app/services/login.service'; | |||
| @Component({ | |||
| selector: 'app-login', | |||
| @@ -8,7 +9,7 @@ import { Component, OnInit } from '@angular/core'; | |||
| export class LoginComponent implements OnInit { | |||
| email = ''; | |||
| constructor() { } | |||
| constructor(private loginService: LoginService) { } | |||
| ngOnInit(): void { | |||
| } | |||
| @@ -17,6 +18,7 @@ export class LoginComponent implements OnInit { | |||
| this.email = email; | |||
| localStorage.setItem('loginEmail', email); | |||
| this.loginService.updateLoginRole(); | |||
| } | |||
| } | |||
| @@ -77,7 +77,7 @@ | |||
| <button class="common-button neutral" (click)="formState = 'INIT_REGISTER'"> | |||
| Back | |||
| </button> | |||
| <button class="common-button" (click)="formState = 'SELECT_PLAN'"> | |||
| <button class="common-button" (click)="registerName()"> | |||
| Proceed | |||
| </button> | |||
| </div> | |||
| @@ -150,7 +150,7 @@ | |||
| <button class="common-button outline" (click)="print()"> | |||
| </button> | |||
| <button class="common-button" (click)="formState = 'RECEIPT'"> | |||
| <button class="common-button" (click)="goToReceipt()"> | |||
| View Receipt | |||
| </button> | |||
| </div> | |||
| @@ -1,7 +1,17 @@ | |||
| import { Component, OnInit } from '@angular/core'; | |||
| import { DateInputProperties } from 'src/app/widgets/form/date-input/date-input.component'; | |||
| import { GenericInputProperties } from 'src/app/widgets/form/generic-input/generic-input.component'; | |||
| import { SelectInputProperties } from 'src/app/widgets/form/select-input/select-input.component'; | |||
| import { RegisterBusinessNameService } from 'src/app/services/register-business-name.service'; | |||
| export interface AcknowledgementRow { | |||
| name: string, | |||
| value: string | number, | |||
| amount?: number, | |||
| highlight?: boolean, | |||
| }; | |||
| export interface ReceiptRow { | |||
| name: string, | |||
| value: string | number, | |||
| }; | |||
| @Component({ | |||
| selector: 'app-register-business', | |||
| @@ -50,64 +60,11 @@ export class RegisterBusinessComponent implements OnInit { | |||
| dropSuffixOptions = ['YES', 'NO']; | |||
| acknowledgementDetails: Array<{ | |||
| name: string, | |||
| value: string | number, | |||
| amount?: number, | |||
| highlight?: boolean, | |||
| }> = [{ | |||
| name: 'UEM', | |||
| value: '---' | |||
| }, { | |||
| name: 'Entity Name', | |||
| value: this.nameToCheck | |||
| }, { | |||
| name: 'Transaction Number', | |||
| value: '39047729362923293', | |||
| highlight: true, | |||
| }, { | |||
| name: 'Receipt Number', | |||
| value: 'ACRA38293', | |||
| highlight: true | |||
| }, { | |||
| name: 'EP Reference No.', | |||
| value: '20910038829384470' | |||
| }, { | |||
| name: 'Payment Date', | |||
| value: '06/11/2021 11:28:01' | |||
| }, { | |||
| name: 'Description', | |||
| value: 'Application for Business Name', | |||
| amount: 15 | |||
| }]; | |||
| receiptDetails: Array<{ | |||
| name: string, | |||
| value: string | number, | |||
| }> = [{ | |||
| name: 'Receipt Number', | |||
| value: 'ACRA38293', | |||
| }, { | |||
| name: 'ARN', | |||
| value: 'ARN2021110294038', | |||
| }, { | |||
| name: 'EP Reference No.', | |||
| value: '20910038829384470' | |||
| }, { | |||
| name: 'Tax ID', | |||
| value: 'M9-0C038921', | |||
| }, { | |||
| name: 'Paid By', | |||
| value: 'KOH YA TING', | |||
| }, { | |||
| name: 'Payment Date', | |||
| value: '06/11/2021 11:28:01' | |||
| }, { | |||
| name: 'Paid Via', | |||
| value: 'Net Banking', | |||
| }]; | |||
| constructor() { } | |||
| acknowledgementDetails: Array<AcknowledgementRow> = []; | |||
| receiptDetails: Array<ReceiptRow> = []; | |||
| constructor(private registerBusinessNameService: RegisterBusinessNameService) { } | |||
| ngOnInit(): void { | |||
| } | |||
| @@ -151,33 +108,52 @@ export class RegisterBusinessComponent implements OnInit { | |||
| payForReservation() { | |||
| this.paymentChild = window.open('/mock', '_blank', 'toolbar=0,status=0,width=626,height=436'); | |||
| this.childCheck = window.setInterval(() => { | |||
| this.childCheck = window.setInterval(async () => { | |||
| if (this.paymentChild && this.paymentChild.closed) { | |||
| this.formState = 'ACKNOWLEDGEMENT'; | |||
| window.clearInterval(this.childCheck); | |||
| this.childCheck = undefined; | |||
| this.acknowledgementDetails = await this.registerBusinessNameService.getAcknowledgement(); | |||
| } | |||
| }, 1000); | |||
| } | |||
| checkName() { | |||
| async goToReceipt() { | |||
| this.formState = 'RECEIPT'; | |||
| this.receiptDetails = await this.registerBusinessNameService.getReceipt(); | |||
| } | |||
| async checkName() { | |||
| this.formState = 'INIT_REGISTER'; | |||
| if (this.nameToCheck === `A'DROIT MANAGEMENT SERVICES`) { | |||
| this.error = { | |||
| message: this.nameToCheck + ' is unavailable. Entity with identical name exists', | |||
| isUnique: false, | |||
| isInvalid: false, | |||
| }; | |||
| } else { | |||
| const nameCheckResponse = await this.registerBusinessNameService.checkName(this.nameToCheck); | |||
| if (nameCheckResponse.status === `success`) { | |||
| this.error = { | |||
| message: this.nameToCheck + ' is available', | |||
| isUnique: true, | |||
| isInvalid: false | |||
| }; | |||
| } else { | |||
| this.error = { | |||
| message: this.nameToCheck + ' is unavailable. ' + nameCheckResponse.status, | |||
| isUnique: false, | |||
| isInvalid: false, | |||
| }; | |||
| } | |||
| } | |||
| async registerName() { | |||
| await this.registerBusinessNameService.registerName( | |||
| this.nameToCheck, | |||
| this.selectedEntityType, | |||
| this.selectedCompanyCategory, | |||
| this.selectedCompanySuffix, | |||
| this.selectedDropSuffix, | |||
| ); | |||
| this.formState = 'SELECT_PLAN'; | |||
| } | |||
| print() { | |||
| window.print(); | |||
| } | |||
| @@ -1,4 +1,5 @@ | |||
| import { Injectable } from '@angular/core'; | |||
| import { BehaviorSubject } from 'rxjs'; | |||
| export type Role = 'Officer'|'Investigator'|'Hod'|'Panel'|'Customer'; | |||
| @@ -7,8 +8,15 @@ export type Role = 'Officer'|'Investigator'|'Hod'|'Panel'|'Customer'; | |||
| }) | |||
| export class LoginService { | |||
| private loginRole: Role; | |||
| private loginRoleSubject: BehaviorSubject<string>; | |||
| constructor() { | |||
| this.loginRole = 'Customer'; | |||
| this.loginRoleSubject = new BehaviorSubject(''); | |||
| this.updateLoginRole(); | |||
| } | |||
| updateLoginRole() { | |||
| const loginEmail = localStorage.getItem('loginEmail'); | |||
| if (loginEmail && loginEmail.toLocaleLowerCase().startsWith('hod')) { | |||
| @@ -22,6 +30,8 @@ export class LoginService { | |||
| } else { | |||
| this.loginRole = 'Officer'; | |||
| } | |||
| this.loginRoleSubject.next(this.loginRole); | |||
| } | |||
| getLoginName() { | |||
| @@ -34,6 +44,10 @@ export class LoginService { | |||
| } | |||
| } | |||
| getLoginRoleObservable() { | |||
| return this.loginRoleSubject.asObservable(); | |||
| } | |||
| getLoginRole() { | |||
| return this.loginRole; | |||
| } | |||
| @@ -71,8 +71,10 @@ export class NotificationService { | |||
| private allowedNotifications: Array<Notification> = []; | |||
| constructor(loginService: LoginService) { | |||
| const loginRole = loginService.getLoginRole(); | |||
| this.allowedNotifications = this.notifications.filter(notification => notification.roles.includes(loginRole)); | |||
| loginService.getLoginRoleObservable().subscribe(loginRoleObserved => { | |||
| const loginRole = loginService.getLoginRole(); | |||
| this.allowedNotifications = this.notifications.filter(notification => notification.roles.includes(loginRole)); | |||
| }); | |||
| } | |||
| getAllowedNotifications() { | |||
| @@ -0,0 +1,16 @@ | |||
| import { TestBed } from '@angular/core/testing'; | |||
| import { RegisterBusinessNameService } from './register-business-name.service'; | |||
| describe('RegisterBusinessNameService', () => { | |||
| let service: RegisterBusinessNameService; | |||
| beforeEach(() => { | |||
| TestBed.configureTestingModule({}); | |||
| service = TestBed.inject(RegisterBusinessNameService); | |||
| }); | |||
| it('should be created', () => { | |||
| expect(service).toBeTruthy(); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,73 @@ | |||
| import { Injectable } from '@angular/core'; | |||
| import { HttpClient, HttpHeaders } from '@angular/common/http'; | |||
| import { Observable, throwError } from 'rxjs'; | |||
| import { catchError, retry } from 'rxjs/operators'; | |||
| import { AcknowledgementRow, ReceiptRow } from '../pages/register-business/register-business.component'; | |||
| export interface NameCheckRequest { | |||
| name: string; | |||
| } | |||
| export interface NameCheckResponse { | |||
| status: string; | |||
| } | |||
| export interface NameRegisterRequest { | |||
| name: string; | |||
| entityType: string; | |||
| companyCategory: string; | |||
| companySuffix: string; | |||
| dropSuffix: string; | |||
| } | |||
| export interface NameRegisterResponse { | |||
| status: string; | |||
| } | |||
| @Injectable({ | |||
| providedIn: 'root' | |||
| }) | |||
| export class RegisterBusinessNameService { | |||
| constructor(private http: HttpClient) { | |||
| } | |||
| checkName(name: string) { | |||
| const nameCheckRequest: NameCheckRequest = { | |||
| name, | |||
| }; | |||
| return new Promise<NameCheckResponse>((resolve, reject) => resolve({status: 'success'})); | |||
| return this.http.post<NameCheckResponse>('http://localhost:10000/name-check/', nameCheckRequest).toPromise(); | |||
| } | |||
| registerName( | |||
| name: string, | |||
| entityType: string, | |||
| companyCategory: string, | |||
| companySuffix: string, | |||
| dropSuffix: string, | |||
| ) { | |||
| const nameRegisterRequest: NameRegisterRequest = { | |||
| name, | |||
| entityType, | |||
| companyCategory, | |||
| companySuffix, | |||
| dropSuffix, | |||
| }; | |||
| return new Promise<NameCheckResponse>((resolve, reject) => resolve({status: 'success'})); | |||
| return this.http.post<NameRegisterResponse>('http://localhost:8080/name-register/', nameRegisterRequest).toPromise(); | |||
| } | |||
| getAcknowledgement() { | |||
| return this.http.get<Array<AcknowledgementRow>>('http://localhost:8080/acknowledgement/').toPromise(); | |||
| } | |||
| getReceipt() { | |||
| return this.http.get<Array<ReceiptRow>>('http://localhost:8080/receipt/').toPromise(); | |||
| } | |||
| } | |||