solved pr comments
This commit is contained in:
parent
379dccf394
commit
1158846091
@ -4,27 +4,28 @@ import { CompositeRouteGuard } from '@iqser/common-ui';
|
|||||||
import { AuthGuard } from '../auth/auth.guard';
|
import { AuthGuard } from '../auth/auth.guard';
|
||||||
import { RedRoleGuard } from '../auth/red-role.guard';
|
import { RedRoleGuard } from '../auth/red-role.guard';
|
||||||
import { AppStateGuard } from '../../state/app-state.guard';
|
import { AppStateGuard } from '../../state/app-state.guard';
|
||||||
import { NotificationsScreenComponent } from './screens/notifications/notifications-screen.component';
|
import { BaseAccountScreenComponent } from './base-account-screen/base-account-screen-component';
|
||||||
import { UserProfileScreenComponent } from './screens/user-profile/user-profile-screen.component';
|
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{ path: '', redirectTo: 'user-profile', pathMatch: 'full' },
|
{ path: '', redirectTo: 'user-profile', pathMatch: 'full' },
|
||||||
{
|
{
|
||||||
path: 'user-profile',
|
path: 'user-profile',
|
||||||
component: UserProfileScreenComponent,
|
component: BaseAccountScreenComponent,
|
||||||
canActivate: [CompositeRouteGuard],
|
canActivate: [CompositeRouteGuard],
|
||||||
data: {
|
data: {
|
||||||
routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard],
|
routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard],
|
||||||
requiredRoles: ['RED_USER'],
|
requiredRoles: ['RED_USER'],
|
||||||
},
|
},
|
||||||
|
loadChildren: () => import('./screens/user-profile/user-profile.module').then(m => m.UserProfileModule),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'notifications',
|
path: 'notifications',
|
||||||
component: NotificationsScreenComponent,
|
component: BaseAccountScreenComponent,
|
||||||
canActivate: [CompositeRouteGuard],
|
canActivate: [CompositeRouteGuard],
|
||||||
data: {
|
data: {
|
||||||
routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard],
|
routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard],
|
||||||
},
|
},
|
||||||
|
loadChildren: () => import('./screens/notifications/notifications.module').then(m => m.NotificationsModule),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||||
import { Component } from '@angular/core';
|
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||||
|
|
||||||
interface NavItem {
|
interface NavItem {
|
||||||
readonly label: string;
|
readonly label: string;
|
||||||
@ -10,6 +10,7 @@ interface NavItem {
|
|||||||
selector: 'redaction-account-side-nav',
|
selector: 'redaction-account-side-nav',
|
||||||
templateUrl: './account-side-nav.component.html',
|
templateUrl: './account-side-nav.component.html',
|
||||||
styleUrls: ['./account-side-nav.component.scss'],
|
styleUrls: ['./account-side-nav.component.scss'],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class AccountSideNavComponent {
|
export class AccountSideNavComponent {
|
||||||
readonly items: NavItem[] = [
|
readonly items: NavItem[] = [
|
||||||
|
|||||||
@ -3,16 +3,12 @@ import { CommonModule } from '@angular/common';
|
|||||||
import { SharedModule } from '../shared/shared.module';
|
import { SharedModule } from '../shared/shared.module';
|
||||||
import { AccountRoutingModule } from './account-routing.module';
|
import { AccountRoutingModule } from './account-routing.module';
|
||||||
import { AccountSideNavComponent } from './account-side-nav/account-side-nav.component';
|
import { AccountSideNavComponent } from './account-side-nav/account-side-nav.component';
|
||||||
import { NotificationsScreenComponent } from './screens/notifications/notifications-screen.component';
|
import { BaseAccountScreenComponent } from './base-account-screen/base-account-screen-component';
|
||||||
import { UserProfileScreenComponent } from './screens/user-profile/user-profile-screen.component';
|
import { NotificationPreferencesService } from './services/notification-preferences.service';
|
||||||
|
|
||||||
const screens = [NotificationsScreenComponent, UserProfileScreenComponent];
|
|
||||||
|
|
||||||
const components = [AccountSideNavComponent, ...screens];
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [components],
|
declarations: [AccountSideNavComponent, BaseAccountScreenComponent],
|
||||||
providers: [],
|
|
||||||
imports: [CommonModule, SharedModule, AccountRoutingModule],
|
imports: [CommonModule, SharedModule, AccountRoutingModule],
|
||||||
|
providers: [NotificationPreferencesService],
|
||||||
})
|
})
|
||||||
export class AccountModule {}
|
export class AccountModule {}
|
||||||
|
|||||||
@ -0,0 +1,20 @@
|
|||||||
|
<section class="settings">
|
||||||
|
<div class="overlay-shadow"></div>
|
||||||
|
|
||||||
|
<redaction-account-side-nav></redaction-account-side-nav>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div class="content-inner">
|
||||||
|
<div class="content-container full-height">
|
||||||
|
<div class="overlay-shadow"></div>
|
||||||
|
<div class="dialog">
|
||||||
|
<div class="dialog-header">
|
||||||
|
<div class="heading-l" [translate]="translations[path]"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<router-outlet></router-outlet>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
@ -1,15 +1,16 @@
|
|||||||
@use 'variables';
|
@use 'apps/red-ui/src/assets/styles/variables';
|
||||||
@use 'common-mixins';
|
@use 'libs/common-ui/src/assets/styles/common-mixins';
|
||||||
|
|
||||||
.dialog {
|
|
||||||
min-height: unset;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-container {
|
.content-container {
|
||||||
background-color: variables.$grey-2;
|
background-color: variables.$grey-2;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@include common-mixins.scroll-bar;
|
@include common-mixins.scroll-bar;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
|
||||||
|
.dialog {
|
||||||
|
width: var(--width);
|
||||||
|
min-height: unset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.full-height {
|
.full-height {
|
||||||
@ -21,7 +22,3 @@
|
|||||||
height: calc(100% + 50px);
|
height: calc(100% + 50px);
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
import { ChangeDetectionStrategy, Component, OnInit, ViewContainerRef } from '@angular/core';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { notificationsTranslations } from '../translations/notifications-translations';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'redaction-base-account-screen',
|
||||||
|
templateUrl: './base-account-screen-component.html',
|
||||||
|
styleUrls: ['./base-account-screen-component.scss'],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class BaseAccountScreenComponent implements OnInit {
|
||||||
|
readonly translations = notificationsTranslations;
|
||||||
|
path: string;
|
||||||
|
|
||||||
|
constructor(private readonly _router: Router, private readonly _hostRef: ViewContainerRef) {
|
||||||
|
this.path = this._router.url.split('/').pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this._setDialogWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _setDialogWidth() {
|
||||||
|
const element = this._hostRef.element.nativeElement as HTMLElement;
|
||||||
|
element.style.setProperty('--width', this.path === 'user-profile' ? 'unset' : '100%');
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
export const EmailNotificationScheduleTypes = {
|
||||||
|
INSTANT: 'INSTANT',
|
||||||
|
DAILY: 'DAILY',
|
||||||
|
WEEKLY: 'WEEKLY',
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type EmailNotificationScheduleType = keyof typeof EmailNotificationScheduleTypes;
|
||||||
|
export const EmailNotificationScheduleTypesValues = Object.values(EmailNotificationScheduleTypes);
|
||||||
|
|
||||||
|
export const NotificationCategories = {
|
||||||
|
inAppNotifications: 'inAppNotifications',
|
||||||
|
emailNotifications: 'emailNotifications',
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export const NotificationCategoriesValues = Object.values(NotificationCategories);
|
||||||
|
|
||||||
|
export const OwnDossiersNotificationsTypes = {
|
||||||
|
dossierStatusChanges: 'dossierStatusChanges',
|
||||||
|
requestToJoinTheDossier: 'requestToJoinTheDossier',
|
||||||
|
documentStatusChanges: 'documentStatusChanges',
|
||||||
|
documentIsSentForApproval: 'documentIsSentForApproval',
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export const OwnDossiersNotificationsTypesValues = Object.values(OwnDossiersNotificationsTypes);
|
||||||
|
|
||||||
|
export const ReviewerOnDossiersNotificationsTypes = {
|
||||||
|
whenIAmAssignedOnADocument: 'whenIAmAssignedOnADocument',
|
||||||
|
whenIAmUnassignedFromADocument: 'whenIAmUnassignedFromADocument',
|
||||||
|
whenADocumentIsApproved: 'whenADocumentIsApproved',
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export const ReviewerOnDossiersNotificationsTypesValues = Object.values(ReviewerOnDossiersNotificationsTypes);
|
||||||
|
|
||||||
|
export const ApproverOnDossiersNotificationsTypes = {
|
||||||
|
whenADocumentIsSentForApproval: 'whenADocumentIsSentForApproval',
|
||||||
|
whenADocumentIsAssignedToAReviewer: 'whenADocumentIsAssignedToAReviewer',
|
||||||
|
whenAReviewerIsUnassignedFromADocument: 'whenAReviewerIsUnassignedFromADocument',
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export const ApproverOnDossiersNotificationsTypesValues = Object.values(ApproverOnDossiersNotificationsTypes);
|
||||||
|
|
||||||
|
export const NotificationGroupsKeys = ['own', 'reviewer', 'approver'];
|
||||||
|
export const NotificationGroupsValues = [
|
||||||
|
OwnDossiersNotificationsTypesValues,
|
||||||
|
ReviewerOnDossiersNotificationsTypesValues,
|
||||||
|
ApproverOnDossiersNotificationsTypesValues,
|
||||||
|
];
|
||||||
@ -1,64 +0,0 @@
|
|||||||
<section class="settings">
|
|
||||||
<div class="overlay-shadow"></div>
|
|
||||||
|
|
||||||
<redaction-account-side-nav></redaction-account-side-nav>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div class="content-inner">
|
|
||||||
<div class="content-container full-height">
|
|
||||||
<div class="overlay-shadow"></div>
|
|
||||||
<div class="dialog">
|
|
||||||
<div class="dialog-header">
|
|
||||||
<div class="heading-l" translate="notifications-screen.title"></div>
|
|
||||||
</div>
|
|
||||||
<form (submit)="save()" [formGroup]="formGroup" *ngIf="formGroup">
|
|
||||||
<div class="dialog-content">
|
|
||||||
<div *ngFor="let category of notificationCategories">
|
|
||||||
<div class="iqser-input-group header w-full">
|
|
||||||
<mat-slide-toggle color="primary" formControlName="{{ category }}Enabled">{{
|
|
||||||
translations[category] | translate
|
|
||||||
}}</mat-slide-toggle>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="options-content" *ngIf="isCategoryActive(category)">
|
|
||||||
<div class="radio-container" *ngIf="category === 'emailNotifications'">
|
|
||||||
<div class="radio-button" *ngFor="let type of emailNotificationTypes">
|
|
||||||
<iqser-round-checkbox
|
|
||||||
[active]="getEmailNotificationType() === type"
|
|
||||||
(click)="setEmailNotificationType(type)"
|
|
||||||
>
|
|
||||||
</iqser-round-checkbox>
|
|
||||||
<span> {{ translations[type.toLocaleLowerCase()] | translate }} </span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="statement" translate="notifications-screen.options-title"></div>
|
|
||||||
|
|
||||||
<div class="group" *ngFor="let key of notificationGroupsKeys; let i = index">
|
|
||||||
<div class="group-title" [translate]="translations[key]"></div>
|
|
||||||
<div class="iqser-input-group">
|
|
||||||
<mat-checkbox
|
|
||||||
*ngFor="let preference of notificationGroupsValues[i]"
|
|
||||||
color="primary"
|
|
||||||
[checked]="isPreferenceChecked(category, preference)"
|
|
||||||
(change)="addRemovePreference($event.checked, category, preference)"
|
|
||||||
>
|
|
||||||
{{ translations[preference] | translate }}
|
|
||||||
</mat-checkbox>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="dialog-actions">
|
|
||||||
<button [disabled]="formGroup.invalid" color="primary" mat-flat-button type="submit">
|
|
||||||
{{ 'user-profile-screen.actions.save' | translate }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
@ -1,73 +0,0 @@
|
|||||||
@use 'variables';
|
|
||||||
@use 'common-mixins';
|
|
||||||
|
|
||||||
.content-container {
|
|
||||||
background-color: variables.$grey-2;
|
|
||||||
justify-content: center;
|
|
||||||
@include common-mixins.scroll-bar;
|
|
||||||
overflow: auto;
|
|
||||||
|
|
||||||
.dialog {
|
|
||||||
width: 100%;
|
|
||||||
min-height: unset;
|
|
||||||
|
|
||||||
.dialog-content {
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
.header {
|
|
||||||
grid-column: span 2;
|
|
||||||
padding: 10px 10px;
|
|
||||||
margin-bottom: -1px;
|
|
||||||
border-top: 1px solid variables.$separator;
|
|
||||||
border-bottom: 1px solid variables.$separator;
|
|
||||||
}
|
|
||||||
|
|
||||||
.options-content {
|
|
||||||
padding: 10px 48px;
|
|
||||||
|
|
||||||
.statement {
|
|
||||||
opacity: 0.7;
|
|
||||||
color: variables.$grey-1;
|
|
||||||
font-weight: 500;
|
|
||||||
padding: 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.radio-container {
|
|
||||||
display: flex;
|
|
||||||
padding: 10px 0 10px;
|
|
||||||
.radio-button {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding-right: 30px;
|
|
||||||
iqser-round-checkbox {
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.group {
|
|
||||||
padding: 10px 0;
|
|
||||||
|
|
||||||
.group-title {
|
|
||||||
color: variables.$grey-1;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.iqser-input-group {
|
|
||||||
margin-top: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.full-height {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: calc(100% + 50px);
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
<form (submit)="save()" [formGroup]="formGroup">
|
||||||
|
<div class="dialog-content">
|
||||||
|
<div *ngFor="let category of notificationCategories">
|
||||||
|
<div class="iqser-input-group header w-full">
|
||||||
|
<mat-slide-toggle color="primary" formControlName="{{ category }}Enabled">{{
|
||||||
|
translations[category] | translate
|
||||||
|
}}</mat-slide-toggle>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="options-content" *ngIf="isCategoryActive(category)">
|
||||||
|
<div class="radio-container" *ngIf="category === 'emailNotifications'">
|
||||||
|
<div class="radio-button" *ngFor="let type of emailNotificationScheduleTypes">
|
||||||
|
<iqser-round-checkbox [active]="getEmailNotificationType() === type" (click)="setEmailNotificationType(type)">
|
||||||
|
</iqser-round-checkbox>
|
||||||
|
<span> {{ translations[type.toLocaleLowerCase()] | translate }} </span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="statement" translate="notifications-screen.options-title"></div>
|
||||||
|
|
||||||
|
<div class="group" *ngFor="let key of notificationGroupsKeys; let i = index">
|
||||||
|
<div class="group-title" [translate]="translations[key]"></div>
|
||||||
|
<div class="iqser-input-group">
|
||||||
|
<mat-checkbox
|
||||||
|
*ngFor="let preference of notificationGroupsValues[i]"
|
||||||
|
color="primary"
|
||||||
|
[checked]="isPreferenceChecked(category, preference)"
|
||||||
|
(change)="addRemovePreference($event.checked, category, preference)"
|
||||||
|
>
|
||||||
|
{{ translations[preference] | translate }}
|
||||||
|
</mat-checkbox>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="dialog-actions">
|
||||||
|
<button [disabled]="formGroup.invalid" color="primary" mat-flat-button type="submit">
|
||||||
|
{{ 'user-profile-screen.actions.save' | translate }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
@use 'apps/red-ui/src/assets/styles/variables';
|
||||||
|
@use 'libs/common-ui/src/assets/styles/common-mixins';
|
||||||
|
|
||||||
|
.dialog-content {
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.header {
|
||||||
|
grid-column: span 2;
|
||||||
|
padding: 10px 10px;
|
||||||
|
margin-bottom: -1px;
|
||||||
|
border-top: 1px solid variables.$separator;
|
||||||
|
border-bottom: 1px solid variables.$separator;
|
||||||
|
}
|
||||||
|
|
||||||
|
.options-content {
|
||||||
|
padding: 10px 48px;
|
||||||
|
|
||||||
|
.statement {
|
||||||
|
opacity: 0.7;
|
||||||
|
color: variables.$grey-1;
|
||||||
|
font-weight: 500;
|
||||||
|
padding: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-container {
|
||||||
|
display: flex;
|
||||||
|
padding: 10px 0 10px;
|
||||||
|
.radio-button {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding-right: 30px;
|
||||||
|
iqser-round-checkbox {
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.group {
|
||||||
|
padding: 10px 0;
|
||||||
|
|
||||||
|
.group-title {
|
||||||
|
color: variables.$grey-1;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.iqser-input-group {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,24 +1,27 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
|
||||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||||
import { notificationsTranslations } from '../../translations/notifications-translations';
|
import { notificationsTranslations } from '../../../translations/notifications-translations';
|
||||||
import { NotificationPreferencesService } from '../../../../services/notification-preferences.service';
|
import { NotificationPreferencesService } from '../../../services/notification-preferences.service';
|
||||||
import { LoadingService, Toaster } from '@iqser/common-ui';
|
import { LoadingService, Toaster } from '@iqser/common-ui';
|
||||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||||
|
import {
|
||||||
|
EmailNotificationScheduleTypesValues,
|
||||||
|
NotificationCategoriesValues,
|
||||||
|
NotificationGroupsKeys,
|
||||||
|
NotificationGroupsValues,
|
||||||
|
} from '../constants';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-notifications-screen',
|
selector: 'redaction-notifications-screen',
|
||||||
templateUrl: './notifications-screen.component.html',
|
templateUrl: './notifications-screen.component.html',
|
||||||
styleUrls: ['./notifications-screen.component.scss'],
|
styleUrls: ['./notifications-screen.component.scss'],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class NotificationsScreenComponent implements OnInit {
|
export class NotificationsScreenComponent implements OnInit {
|
||||||
readonly emailNotificationTypes: string[] = ['INSTANT', 'DAILY', 'WEEKLY'];
|
readonly emailNotificationScheduleTypes = EmailNotificationScheduleTypesValues;
|
||||||
readonly notificationCategories: string[] = ['inAppNotifications', 'emailNotifications'];
|
readonly notificationCategories = NotificationCategoriesValues;
|
||||||
readonly notificationGroupsKeys: string[] = ['own', 'reviewer', 'approver'];
|
readonly notificationGroupsKeys = NotificationGroupsKeys;
|
||||||
readonly notificationGroupsValues: string[][] = [
|
readonly notificationGroupsValues = NotificationGroupsValues;
|
||||||
['dossierStatusChanges', 'requestToJoinTheDossier', 'documentStatusChanges', 'documentIsSentForApproval'],
|
|
||||||
['whenIAmAssignedOnADocument', 'whenIAmUnassignedFromADocument', 'whenADocumentIsApproved'],
|
|
||||||
['whenADocumentIsSentForApproval', 'whenADocumentIsAssignedToAReviewer', 'whenAReviewerIsUnassignedFromADocument'],
|
|
||||||
];
|
|
||||||
readonly translations = notificationsTranslations;
|
readonly translations = notificationsTranslations;
|
||||||
|
|
||||||
formGroup: FormGroup;
|
formGroup: FormGroup;
|
||||||
@ -28,7 +31,15 @@ export class NotificationsScreenComponent implements OnInit {
|
|||||||
private readonly _formBuilder: FormBuilder,
|
private readonly _formBuilder: FormBuilder,
|
||||||
private readonly _loadingService: LoadingService,
|
private readonly _loadingService: LoadingService,
|
||||||
private readonly _notificationPreferencesService: NotificationPreferencesService,
|
private readonly _notificationPreferencesService: NotificationPreferencesService,
|
||||||
) {}
|
) {
|
||||||
|
this.formGroup = this._formBuilder.group({
|
||||||
|
inAppNotificationsEnabled: [undefined],
|
||||||
|
emailNotificationsEnabled: [undefined],
|
||||||
|
emailNotificationType: [undefined],
|
||||||
|
emailNotifications: [undefined],
|
||||||
|
inAppNotifications: [undefined],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async ngOnInit(): Promise<void> {
|
async ngOnInit(): Promise<void> {
|
||||||
await this._initializeForm();
|
await this._initializeForm();
|
||||||
@ -75,13 +86,7 @@ export class NotificationsScreenComponent implements OnInit {
|
|||||||
this._loadingService.start();
|
this._loadingService.start();
|
||||||
|
|
||||||
const notificationPreferences = await this._notificationPreferencesService.getNotificationPreferences().toPromise();
|
const notificationPreferences = await this._notificationPreferencesService.getNotificationPreferences().toPromise();
|
||||||
this.formGroup = this._formBuilder.group({
|
this.formGroup.patchValue(notificationPreferences);
|
||||||
inAppNotificationsEnabled: [notificationPreferences.inAppNotificationsEnabled],
|
|
||||||
emailNotificationsEnabled: [notificationPreferences.emailNotificationsEnabled],
|
|
||||||
emailNotificationType: [notificationPreferences.emailNotificationType],
|
|
||||||
emailNotifications: [notificationPreferences.emailNotifications],
|
|
||||||
inAppNotifications: [notificationPreferences.inAppNotifications],
|
|
||||||
});
|
|
||||||
|
|
||||||
this._loadingService.stop();
|
this._loadingService.stop();
|
||||||
}
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { SharedModule } from '../../../shared/shared.module';
|
||||||
|
import { NotificationsScreenComponent } from './notifications-screen/notifications-screen.component';
|
||||||
|
|
||||||
|
const routes = [{ path: '', component: NotificationsScreenComponent }];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [NotificationsScreenComponent],
|
||||||
|
imports: [RouterModule.forChild(routes), CommonModule, SharedModule],
|
||||||
|
})
|
||||||
|
export class NotificationsModule {}
|
||||||
@ -1,62 +0,0 @@
|
|||||||
<section class="settings">
|
|
||||||
<div class="overlay-shadow"></div>
|
|
||||||
|
|
||||||
<redaction-account-side-nav></redaction-account-side-nav>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div class="content-inner">
|
|
||||||
<div class="content-container full-height">
|
|
||||||
<div class="overlay-shadow"></div>
|
|
||||||
<div class="dialog">
|
|
||||||
<div class="dialog-header">
|
|
||||||
<div class="heading-l" translate="user-profile-screen.title"></div>
|
|
||||||
</div>
|
|
||||||
<form (submit)="save()" [formGroup]="formGroup">
|
|
||||||
<div class="dialog-content">
|
|
||||||
<div class="dialog-content-left">
|
|
||||||
<div class="iqser-input-group required">
|
|
||||||
<label translate="user-profile-screen.form.email"></label>
|
|
||||||
<input formControlName="email" name="email" type="email" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="iqser-input-group">
|
|
||||||
<label translate="user-profile-screen.form.first-name"></label>
|
|
||||||
<input formControlName="firstName" name="firstName" type="text" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="iqser-input-group">
|
|
||||||
<label translate="user-profile-screen.form.last-name"></label>
|
|
||||||
<input formControlName="lastName" name="lastName" type="text" />
|
|
||||||
</div>
|
|
||||||
<div class="iqser-input-group">
|
|
||||||
<label translate="top-bar.navigation-items.my-account.children.language.label"></label>
|
|
||||||
<mat-select formControlName="language">
|
|
||||||
<mat-option *ngFor="let language of languages" [value]="language">
|
|
||||||
{{ translations[language] | translate }}
|
|
||||||
</mat-option>
|
|
||||||
</mat-select>
|
|
||||||
</div>
|
|
||||||
<div class="iqser-input-group">
|
|
||||||
<a [href]="changePasswordUrl" target="_blank">
|
|
||||||
{{ 'user-profile-screen.actions.change-password' | translate }}</a
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="dialog-actions">
|
|
||||||
<button
|
|
||||||
[disabled]="formGroup.invalid || !(profileChanged || languageChanged)"
|
|
||||||
color="primary"
|
|
||||||
mat-flat-button
|
|
||||||
type="submit"
|
|
||||||
>
|
|
||||||
{{ 'user-profile-screen.actions.save' | translate }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
<form (submit)="save()" [formGroup]="formGroup">
|
||||||
|
<div class="dialog-content">
|
||||||
|
<div class="dialog-content-left">
|
||||||
|
<div class="iqser-input-group required">
|
||||||
|
<label translate="user-profile-screen.form.email"></label>
|
||||||
|
<input formControlName="email" name="email" type="email" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="iqser-input-group">
|
||||||
|
<label translate="user-profile-screen.form.first-name"></label>
|
||||||
|
<input formControlName="firstName" name="firstName" type="text" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="iqser-input-group">
|
||||||
|
<label translate="user-profile-screen.form.last-name"></label>
|
||||||
|
<input formControlName="lastName" name="lastName" type="text" />
|
||||||
|
</div>
|
||||||
|
<div class="iqser-input-group">
|
||||||
|
<label translate="top-bar.navigation-items.my-account.children.language.label"></label>
|
||||||
|
<mat-select formControlName="language">
|
||||||
|
<mat-option *ngFor="let language of languages" [value]="language">
|
||||||
|
{{ translations[language] | translate }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</div>
|
||||||
|
<div class="iqser-input-group">
|
||||||
|
<a [href]="changePasswordUrl" target="_blank"> {{ 'user-profile-screen.actions.change-password' | translate }}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="dialog-actions">
|
||||||
|
<button [disabled]="formGroup.invalid || !(profileChanged || languageChanged)" color="primary" mat-flat-button type="submit">
|
||||||
|
{{ 'user-profile-screen.actions.save' | translate }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
a {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
@ -1,19 +1,20 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
|
||||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
import { languagesTranslations } from '../../translations/languages-translations';
|
|
||||||
import { UserService } from '../../../../services/user.service';
|
|
||||||
import { PermissionsService } from '../../../../services/permissions.service';
|
|
||||||
import { ConfigService } from '../../../../services/config.service';
|
|
||||||
import { LanguageService } from '../../../../i18n/language.service';
|
|
||||||
import { DomSanitizer } from '@angular/platform-browser';
|
import { DomSanitizer } from '@angular/platform-browser';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { LoadingService } from '@iqser/common-ui';
|
import { LoadingService } from '@iqser/common-ui';
|
||||||
import { IProfile } from '@red/domain';
|
import { IProfile } from '@red/domain';
|
||||||
|
import { languagesTranslations } from '../../../translations/languages-translations';
|
||||||
|
import { PermissionsService } from '../../../../../services/permissions.service';
|
||||||
|
import { UserService } from '../../../../../services/user.service';
|
||||||
|
import { ConfigService } from '../../../../../services/config.service';
|
||||||
|
import { LanguageService } from '../../../../../i18n/language.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-user-profile-screen',
|
selector: 'redaction-user-profile-screen',
|
||||||
templateUrl: './user-profile-screen.component.html',
|
templateUrl: './user-profile-screen.component.html',
|
||||||
styleUrls: ['./user-profile-screen.component.scss'],
|
styleUrls: ['./user-profile-screen.component.scss'],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class UserProfileScreenComponent implements OnInit {
|
export class UserProfileScreenComponent implements OnInit {
|
||||||
formGroup: FormGroup;
|
formGroup: FormGroup;
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { SharedModule } from '../../../shared/shared.module';
|
||||||
|
import { UserProfileScreenComponent } from './user-profile-screen/user-profile-screen.component';
|
||||||
|
|
||||||
|
const routes = [{ path: '', component: UserProfileScreenComponent }];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [UserProfileScreenComponent],
|
||||||
|
imports: [RouterModule.forChild(routes), CommonModule, SharedModule],
|
||||||
|
})
|
||||||
|
export class UserProfileModule {}
|
||||||
@ -1,9 +1,10 @@
|
|||||||
import { Injectable, Injector } from '@angular/core';
|
import { Injectable, Injector } from '@angular/core';
|
||||||
import { GenericService } from '@iqser/common-ui';
|
import { GenericService } from '@iqser/common-ui';
|
||||||
import { Observable, of } from 'rxjs';
|
import { Observable, of } from 'rxjs';
|
||||||
import { UserService } from './user.service';
|
import { UserService } from '../../../services/user.service';
|
||||||
import { INotificationPreferences } from '@red/domain';
|
import { INotificationPreferences } from '@red/domain';
|
||||||
import { catchError, map } from 'rxjs/operators';
|
import { catchError } from 'rxjs/operators';
|
||||||
|
import { EmailNotificationScheduleTypes } from '../screens/notifications/constants';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
@ -14,10 +15,7 @@ export class NotificationPreferencesService extends GenericService<INotification
|
|||||||
}
|
}
|
||||||
|
|
||||||
getNotificationPreferences(): Observable<INotificationPreferences> {
|
getNotificationPreferences(): Observable<INotificationPreferences> {
|
||||||
return super.get().pipe(
|
return super.get<INotificationPreferences>().pipe(catchError(() => of(this._defaultPreferences)));
|
||||||
map(notificationPreferences => (Array.isArray(notificationPreferences) ? notificationPreferences[0] : notificationPreferences)),
|
|
||||||
catchError(() => of(this._defaultPreferences)),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateNotificationPreferences(notificationPreferences: INotificationPreferences): Observable<void> {
|
updateNotificationPreferences(notificationPreferences: INotificationPreferences): Observable<void> {
|
||||||
@ -26,7 +24,7 @@ export class NotificationPreferencesService extends GenericService<INotification
|
|||||||
|
|
||||||
private get _defaultPreferences(): INotificationPreferences {
|
private get _defaultPreferences(): INotificationPreferences {
|
||||||
return {
|
return {
|
||||||
emailNotificationType: 'INSTANT',
|
emailNotificationType: EmailNotificationScheduleTypes.INSTANT,
|
||||||
emailNotifications: [],
|
emailNotifications: [],
|
||||||
emailNotificationsEnabled: false,
|
emailNotificationsEnabled: false,
|
||||||
inAppNotifications: [],
|
inAppNotifications: [],
|
||||||
@ -19,4 +19,6 @@ export const notificationsTranslations: { [key: string]: string } = {
|
|||||||
approver: _('notifications-screen.groups.approver'),
|
approver: _('notifications-screen.groups.approver'),
|
||||||
own: _('notifications-screen.groups.own'),
|
own: _('notifications-screen.groups.own'),
|
||||||
reviewer: _('notifications-screen.groups.reviewer'),
|
reviewer: _('notifications-screen.groups.reviewer'),
|
||||||
|
notifications: _('notifications-screen.title'),
|
||||||
|
'user-profile': _('user-profile-screen.title'),
|
||||||
} as const;
|
} as const;
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
Subproject commit 712178ea34c998098cd2c079a0be1dd863dd266e
|
Subproject commit 64bf1b270deb96f399b1ab603cf9cd00ff700f36
|
||||||
@ -1,5 +1,7 @@
|
|||||||
|
import { EmailNotificationScheduleType } from '../../../../../apps/red-ui/src/app/modules/account/screens/notifications/constants';
|
||||||
|
|
||||||
export interface INotificationPreferences {
|
export interface INotificationPreferences {
|
||||||
emailNotificationType: 'INSTANT' | 'DAILY' | 'WEEKLY';
|
emailNotificationType: EmailNotificationScheduleType;
|
||||||
emailNotifications: string[];
|
emailNotifications: string[];
|
||||||
emailNotificationsEnabled: boolean;
|
emailNotificationsEnabled: boolean;
|
||||||
inAppNotifications: string[];
|
inAppNotifications: string[];
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user