diff --git a/apps/red-ui/src/app/app-routing.module.ts b/apps/red-ui/src/app/app-routing.module.ts
index 92d9eae7a..b6ec3c6fd 100644
--- a/apps/red-ui/src/app/app-routing.module.ts
+++ b/apps/red-ui/src/app/app-routing.module.ts
@@ -7,7 +7,6 @@ import { RouteReuseStrategy, RouterModule } from '@angular/router';
import { NgModule } from '@angular/core';
import { DownloadsListScreenComponent } from '@components/downloads-list-screen/downloads-list-screen.component';
import { AppStateGuard } from '@state/app-state.guard';
-import { UserProfileScreenComponent } from '@components/user-profile/user-profile-screen.component';
const routes = [
{
@@ -21,18 +20,9 @@ const routes = [
canActivate: [AuthGuard],
},
{
- path: 'main/my-profile',
+ path: 'main/account',
component: BaseScreenComponent,
- children: [
- {
- path: '',
- component: UserProfileScreenComponent,
- },
- ],
- canActivate: [CompositeRouteGuard],
- data: {
- routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard],
- },
+ loadChildren: () => import('./modules/account/account.module').then(m => m.AccountModule),
},
{
path: 'main/admin',
diff --git a/apps/red-ui/src/app/app.module.ts b/apps/red-ui/src/app/app.module.ts
index 67dfac44c..32387e151 100644
--- a/apps/red-ui/src/app/app.module.ts
+++ b/apps/red-ui/src/app/app.module.ts
@@ -20,7 +20,6 @@ import { DownloadsListScreenComponent } from '@components/downloads-list-screen/
import { AppRoutingModule } from './app-routing.module';
import { SharedModule } from '@shared/shared.module';
import { FileUploadDownloadModule } from '@upload-download/file-upload-download.module';
-import { UserProfileScreenComponent } from '@components/user-profile/user-profile-screen.component';
import { PlatformLocation } from '@angular/common';
import { BASE_HREF } from './tokens';
import { MONACO_PATH, MonacoEditorModule } from '@materia-ui/ngx-monaco-editor';
@@ -51,7 +50,7 @@ function cleanupBaseUrl(baseUrl: string) {
}
}
-const screens = [BaseScreenComponent, DownloadsListScreenComponent, UserProfileScreenComponent];
+const screens = [BaseScreenComponent, DownloadsListScreenComponent];
const components = [AppComponent, AuthErrorComponent, NotificationsComponent, SpotlightSearchComponent, ...screens];
diff --git a/apps/red-ui/src/app/components/base-screen/base-screen.component.ts b/apps/red-ui/src/app/components/base-screen/base-screen.component.ts
index 80e31da53..20cd1506a 100644
--- a/apps/red-ui/src/app/components/base-screen/base-screen.component.ts
+++ b/apps/red-ui/src/app/components/base-screen/base-screen.component.ts
@@ -32,9 +32,10 @@ export class BaseScreenComponent {
readonly currentUser = this.userService.currentUser;
readonly userMenuItems: readonly MenuItem[] = [
{
- name: _('top-bar.navigation-items.my-account.children.my-profile'),
- routerLink: '/main/my-profile',
- show: true,
+ name: _('top-bar.navigation-items.my-account.children.account'),
+ routerLink: '/main/account',
+ show: this.currentUser.isUser,
+ action: this.appStateService.reset,
showDot: () => false,
},
{
diff --git a/apps/red-ui/src/app/components/user-profile/user-profile-screen.component.html b/apps/red-ui/src/app/components/user-profile/user-profile-screen.component.html
deleted file mode 100644
index c643dc6b2..000000000
--- a/apps/red-ui/src/app/components/user-profile/user-profile-screen.component.html
+++ /dev/null
@@ -1,50 +0,0 @@
-
diff --git a/apps/red-ui/src/app/modules/account/account-routing.module.ts b/apps/red-ui/src/app/modules/account/account-routing.module.ts
new file mode 100644
index 000000000..777b82c0c
--- /dev/null
+++ b/apps/red-ui/src/app/modules/account/account-routing.module.ts
@@ -0,0 +1,36 @@
+import { NgModule } from '@angular/core';
+import { RouterModule } from '@angular/router';
+import { CompositeRouteGuard } from '@iqser/common-ui';
+import { AuthGuard } from '../auth/auth.guard';
+import { RedRoleGuard } from '../auth/red-role.guard';
+import { AppStateGuard } from '../../state/app-state.guard';
+import { BaseAccountScreenComponent } from './base-account-screen/base-account-screen-component';
+
+const routes = [
+ { path: '', redirectTo: 'user-profile', pathMatch: 'full' },
+ {
+ path: 'user-profile',
+ component: BaseAccountScreenComponent,
+ canActivate: [CompositeRouteGuard],
+ data: {
+ routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard],
+ requiredRoles: ['RED_USER'],
+ },
+ loadChildren: () => import('./screens/user-profile/user-profile.module').then(m => m.UserProfileModule),
+ },
+ {
+ path: 'notifications',
+ component: BaseAccountScreenComponent,
+ canActivate: [CompositeRouteGuard],
+ data: {
+ routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard],
+ },
+ loadChildren: () => import('./screens/notifications/notifications.module').then(m => m.NotificationsModule),
+ },
+];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule],
+})
+export class AccountRoutingModule {}
diff --git a/apps/red-ui/src/app/modules/account/account-side-nav/account-side-nav.component.html b/apps/red-ui/src/app/modules/account/account-side-nav/account-side-nav.component.html
new file mode 100644
index 000000000..8ebc033dc
--- /dev/null
+++ b/apps/red-ui/src/app/modules/account/account-side-nav/account-side-nav.component.html
@@ -0,0 +1,7 @@
+
+
+
+ {{ item.label | translate }}
+
+
+
diff --git a/apps/red-ui/src/app/modules/account/account-side-nav/account-side-nav.component.scss b/apps/red-ui/src/app/modules/account/account-side-nav/account-side-nav.component.scss
new file mode 100644
index 000000000..15c54cccf
--- /dev/null
+++ b/apps/red-ui/src/app/modules/account/account-side-nav/account-side-nav.component.scss
@@ -0,0 +1,7 @@
+:host {
+ height: calc(100vh - 61px);
+
+ &.dossier-templates {
+ height: calc(100vh - 111px);
+ }
+}
diff --git a/apps/red-ui/src/app/modules/account/account-side-nav/account-side-nav.component.ts b/apps/red-ui/src/app/modules/account/account-side-nav/account-side-nav.component.ts
new file mode 100644
index 000000000..f4cf007ae
--- /dev/null
+++ b/apps/red-ui/src/app/modules/account/account-side-nav/account-side-nav.component.ts
@@ -0,0 +1,26 @@
+import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
+import { ChangeDetectionStrategy, Component } from '@angular/core';
+
+interface NavItem {
+ readonly label: string;
+ readonly screen: string;
+}
+
+@Component({
+ selector: 'redaction-account-side-nav',
+ templateUrl: './account-side-nav.component.html',
+ styleUrls: ['./account-side-nav.component.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class AccountSideNavComponent {
+ readonly items: NavItem[] = [
+ {
+ screen: 'user-profile',
+ label: _('user-profile'),
+ },
+ {
+ screen: 'notifications',
+ label: _('notifications'),
+ },
+ ];
+}
diff --git a/apps/red-ui/src/app/modules/account/account.module.ts b/apps/red-ui/src/app/modules/account/account.module.ts
new file mode 100644
index 000000000..28b2ee431
--- /dev/null
+++ b/apps/red-ui/src/app/modules/account/account.module.ts
@@ -0,0 +1,14 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { SharedModule } from '../shared/shared.module';
+import { AccountRoutingModule } from './account-routing.module';
+import { AccountSideNavComponent } from './account-side-nav/account-side-nav.component';
+import { BaseAccountScreenComponent } from './base-account-screen/base-account-screen-component';
+import { NotificationPreferencesService } from './services/notification-preferences.service';
+
+@NgModule({
+ declarations: [AccountSideNavComponent, BaseAccountScreenComponent],
+ imports: [CommonModule, SharedModule, AccountRoutingModule],
+ providers: [NotificationPreferencesService],
+})
+export class AccountModule {}
diff --git a/apps/red-ui/src/app/modules/account/base-account-screen/base-account-screen-component.html b/apps/red-ui/src/app/modules/account/base-account-screen/base-account-screen-component.html
new file mode 100644
index 000000000..1597a1874
--- /dev/null
+++ b/apps/red-ui/src/app/modules/account/base-account-screen/base-account-screen-component.html
@@ -0,0 +1,20 @@
+
diff --git a/apps/red-ui/src/app/components/user-profile/user-profile-screen.component.scss b/apps/red-ui/src/app/modules/account/base-account-screen/base-account-screen-component.scss
similarity index 64%
rename from apps/red-ui/src/app/components/user-profile/user-profile-screen.component.scss
rename to apps/red-ui/src/app/modules/account/base-account-screen/base-account-screen-component.scss
index 677b2c3d2..fd508d3c9 100644
--- a/apps/red-ui/src/app/components/user-profile/user-profile-screen.component.scss
+++ b/apps/red-ui/src/app/modules/account/base-account-screen/base-account-screen-component.scss
@@ -1,11 +1,16 @@
-@use 'variables';
-@use 'common-mixins';
+@use 'apps/red-ui/src/assets/styles/variables';
+@use 'libs/common-ui/src/assets/styles/common-mixins';
.content-container {
background-color: variables.$grey-2;
justify-content: center;
@include common-mixins.scroll-bar;
overflow: auto;
+
+ .dialog {
+ width: var(--width);
+ min-height: unset;
+ }
}
.full-height {
@@ -17,11 +22,3 @@
height: calc(100% + 50px);
z-index: 1;
}
-
-iframe {
- background: white;
- width: 500px;
- height: 500px;
- position: absolute;
- z-index: 100;
-}
diff --git a/apps/red-ui/src/app/modules/account/base-account-screen/base-account-screen-component.ts b/apps/red-ui/src/app/modules/account/base-account-screen/base-account-screen-component.ts
new file mode 100644
index 000000000..c87363a82
--- /dev/null
+++ b/apps/red-ui/src/app/modules/account/base-account-screen/base-account-screen-component.ts
@@ -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%');
+ }
+}
diff --git a/apps/red-ui/src/app/modules/account/screens/notifications/constants.ts b/apps/red-ui/src/app/modules/account/screens/notifications/constants.ts
new file mode 100644
index 000000000..3c98f33b1
--- /dev/null
+++ b/apps/red-ui/src/app/modules/account/screens/notifications/constants.ts
@@ -0,0 +1,38 @@
+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'] as const;
+export const NotificationGroupsValues = [
+ OwnDossiersNotificationsTypesValues,
+ ReviewerOnDossiersNotificationsTypesValues,
+ ApproverOnDossiersNotificationsTypesValues,
+] as const;
diff --git a/apps/red-ui/src/app/modules/account/screens/notifications/notifications-screen/notifications-screen.component.html b/apps/red-ui/src/app/modules/account/screens/notifications/notifications-screen/notifications-screen.component.html
new file mode 100644
index 000000000..8c76795dc
--- /dev/null
+++ b/apps/red-ui/src/app/modules/account/screens/notifications/notifications-screen/notifications-screen.component.html
@@ -0,0 +1,43 @@
+
diff --git a/apps/red-ui/src/app/modules/account/screens/notifications/notifications-screen/notifications-screen.component.scss b/apps/red-ui/src/app/modules/account/screens/notifications/notifications-screen/notifications-screen.component.scss
new file mode 100644
index 000000000..82f2afa68
--- /dev/null
+++ b/apps/red-ui/src/app/modules/account/screens/notifications/notifications-screen/notifications-screen.component.scss
@@ -0,0 +1,51 @@
+@use '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;
+ }
+ }
+ }
+}
diff --git a/apps/red-ui/src/app/modules/account/screens/notifications/notifications-screen/notifications-screen.component.ts b/apps/red-ui/src/app/modules/account/screens/notifications/notifications-screen/notifications-screen.component.ts
new file mode 100644
index 000000000..e6b8f4a2a
--- /dev/null
+++ b/apps/red-ui/src/app/modules/account/screens/notifications/notifications-screen/notifications-screen.component.ts
@@ -0,0 +1,89 @@
+import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
+import { FormBuilder, FormGroup } from '@angular/forms';
+import { notificationsTranslations } from '../../../translations/notifications-translations';
+import { NotificationPreferencesService } from '../../../services/notification-preferences.service';
+import { LoadingService, Toaster } from '@iqser/common-ui';
+import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
+import { NotificationCategoriesValues, NotificationGroupsKeys, NotificationGroupsValues } from '../constants';
+import { EmailNotificationScheduleTypesValues } from '@red/domain';
+
+@Component({
+ selector: 'redaction-notifications-screen',
+ templateUrl: './notifications-screen.component.html',
+ styleUrls: ['./notifications-screen.component.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class NotificationsScreenComponent implements OnInit {
+ readonly emailNotificationScheduleTypes = EmailNotificationScheduleTypesValues;
+ readonly notificationCategories = NotificationCategoriesValues;
+ readonly notificationGroupsKeys = NotificationGroupsKeys;
+ readonly notificationGroupsValues = NotificationGroupsValues;
+ readonly translations = notificationsTranslations;
+
+ formGroup: FormGroup;
+
+ constructor(
+ private readonly _toaster: Toaster,
+ private readonly _formBuilder: FormBuilder,
+ private readonly _loadingService: LoadingService,
+ private readonly _notificationPreferencesService: NotificationPreferencesService,
+ ) {
+ this.formGroup = this._formBuilder.group({
+ inAppNotificationsEnabled: [undefined],
+ emailNotificationsEnabled: [undefined],
+ emailNotificationType: [undefined],
+ emailNotifications: [undefined],
+ inAppNotifications: [undefined],
+ });
+ }
+
+ async ngOnInit(): Promise {
+ await this._initializeForm();
+ }
+
+ isCategoryActive(category: string) {
+ return this.formGroup.get(`${category}Enabled`).value;
+ }
+
+ setEmailNotificationType(type: string) {
+ this.formGroup.get('emailNotificationType').setValue(type);
+ }
+
+ getEmailNotificationType() {
+ return this.formGroup.get('emailNotificationType').value;
+ }
+
+ isPreferenceChecked(category: string, preference: string) {
+ return this.formGroup.get(category).value.includes(preference);
+ }
+
+ addRemovePreference(checked: boolean, category: string, preference: string) {
+ const preferences = this.formGroup.get(category).value;
+ if (checked) {
+ preferences.push(preference);
+ } else {
+ const indexOfPreference = preferences.indexOf(preference);
+ preferences.splice(indexOfPreference, 1);
+ }
+ this.formGroup.get(category).setValue(preferences);
+ }
+
+ async save() {
+ this._loadingService.start();
+ try {
+ await this._notificationPreferencesService.update(this.formGroup.value).toPromise();
+ } catch (e) {
+ this._toaster.error(_('notifications-screen.error.generic'));
+ }
+ this._loadingService.stop();
+ }
+
+ private async _initializeForm() {
+ this._loadingService.start();
+
+ const notificationPreferences = await this._notificationPreferencesService.get().toPromise();
+ this.formGroup.patchValue(notificationPreferences);
+
+ this._loadingService.stop();
+ }
+}
diff --git a/apps/red-ui/src/app/modules/account/screens/notifications/notifications.module.ts b/apps/red-ui/src/app/modules/account/screens/notifications/notifications.module.ts
new file mode 100644
index 000000000..bc6d3f30a
--- /dev/null
+++ b/apps/red-ui/src/app/modules/account/screens/notifications/notifications.module.ts
@@ -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 {}
diff --git a/apps/red-ui/src/app/modules/account/screens/user-profile/user-profile-screen/user-profile-screen.component.html b/apps/red-ui/src/app/modules/account/screens/user-profile/user-profile-screen/user-profile-screen.component.html
new file mode 100644
index 000000000..25d5a5a44
--- /dev/null
+++ b/apps/red-ui/src/app/modules/account/screens/user-profile/user-profile-screen/user-profile-screen.component.html
@@ -0,0 +1,37 @@
+
diff --git a/apps/red-ui/src/app/modules/account/screens/user-profile/user-profile-screen/user-profile-screen.component.scss b/apps/red-ui/src/app/modules/account/screens/user-profile/user-profile-screen/user-profile-screen.component.scss
new file mode 100644
index 000000000..e1573c569
--- /dev/null
+++ b/apps/red-ui/src/app/modules/account/screens/user-profile/user-profile-screen/user-profile-screen.component.scss
@@ -0,0 +1,3 @@
+a {
+ color: black;
+}
diff --git a/apps/red-ui/src/app/components/user-profile/user-profile-screen.component.ts b/apps/red-ui/src/app/modules/account/screens/user-profile/user-profile-screen/user-profile-screen.component.ts
similarity index 87%
rename from apps/red-ui/src/app/components/user-profile/user-profile-screen.component.ts
rename to apps/red-ui/src/app/modules/account/screens/user-profile/user-profile-screen/user-profile-screen.component.ts
index 1601afc46..f1a23936a 100644
--- a/apps/red-ui/src/app/components/user-profile/user-profile-screen.component.ts
+++ b/apps/red-ui/src/app/modules/account/screens/user-profile/user-profile-screen/user-profile-screen.component.ts
@@ -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 { UserService } from '@services/user.service';
-import { PermissionsService } from '@services/permissions.service';
-import { LanguageService } from '@i18n/language.service';
-import { TranslateService } from '@ngx-translate/core';
-import { ConfigService } from '@services/config.service';
import { DomSanitizer } from '@angular/platform-browser';
-import { languagesTranslations } from '../../translations/languages-translations';
+import { TranslateService } from '@ngx-translate/core';
import { LoadingService } from '@iqser/common-ui';
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({
selector: 'redaction-user-profile-screen',
templateUrl: './user-profile-screen.component.html',
styleUrls: ['./user-profile-screen.component.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
})
export class UserProfileScreenComponent implements OnInit {
formGroup: FormGroup;
diff --git a/apps/red-ui/src/app/modules/account/screens/user-profile/user-profile.module.ts b/apps/red-ui/src/app/modules/account/screens/user-profile/user-profile.module.ts
new file mode 100644
index 000000000..928581695
--- /dev/null
+++ b/apps/red-ui/src/app/modules/account/screens/user-profile/user-profile.module.ts
@@ -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 {}
diff --git a/apps/red-ui/src/app/modules/account/services/notification-preferences.service.ts b/apps/red-ui/src/app/modules/account/services/notification-preferences.service.ts
new file mode 100644
index 000000000..acd23a718
--- /dev/null
+++ b/apps/red-ui/src/app/modules/account/services/notification-preferences.service.ts
@@ -0,0 +1,31 @@
+import { Injectable, Injector } from '@angular/core';
+import { GenericService } from '@iqser/common-ui';
+import { Observable, of } from 'rxjs';
+import { UserService } from '../../../services/user.service';
+import { EmailNotificationScheduleTypes, INotificationPreferences } from '@red/domain';
+import { catchError } from 'rxjs/operators';
+
+@Injectable()
+export class NotificationPreferencesService extends GenericService {
+ constructor(protected readonly _injector: Injector, private readonly _userService: UserService) {
+ super(_injector, 'notification-preferences');
+ }
+
+ get(): Observable {
+ return super.get().pipe(catchError(() => of(this._defaultPreferences)));
+ }
+
+ update(notificationPreferences: INotificationPreferences): Observable {
+ return super._post(notificationPreferences);
+ }
+
+ private get _defaultPreferences(): INotificationPreferences {
+ return {
+ emailNotificationType: EmailNotificationScheduleTypes.INSTANT,
+ emailNotifications: [],
+ emailNotificationsEnabled: false,
+ inAppNotifications: [],
+ inAppNotificationsEnabled: true,
+ };
+ }
+}
diff --git a/apps/red-ui/src/app/translations/languages-translations.ts b/apps/red-ui/src/app/modules/account/translations/languages-translations.ts
similarity index 100%
rename from apps/red-ui/src/app/translations/languages-translations.ts
rename to apps/red-ui/src/app/modules/account/translations/languages-translations.ts
diff --git a/apps/red-ui/src/app/modules/account/translations/notifications-translations.ts b/apps/red-ui/src/app/modules/account/translations/notifications-translations.ts
new file mode 100644
index 000000000..c85d03104
--- /dev/null
+++ b/apps/red-ui/src/app/modules/account/translations/notifications-translations.ts
@@ -0,0 +1,24 @@
+import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
+
+export const notificationsTranslations: { [key: string]: string } = {
+ daily: _('notifications-screen.schedule.instant'),
+ daily_summary: _('notifications-screen.schedule.daily'),
+ weekly_summary: _('notifications-screen.schedule.weekly'),
+ inAppNotifications: _('notifications-screen.category.in-app-notifications'),
+ emailNotifications: _('notifications-screen.category.email-notifications'),
+ documentIsSentForApproval: _('notifications-screen.options.document-is-sent-for-approval'),
+ documentStatusChanges: _('notifications-screen.options.document-status-changes'),
+ dossierStatusChanges: _('notifications-screen.options.dossier-status-changes'),
+ requestToJoinTheDossier: _('notifications-screen.options.request-to-join-the-dossier'),
+ whenADocumentIsApproved: _('notifications-screen.options.when-a-document-is-approved'),
+ whenADocumentIsAssignedToAReviewer: _('notifications-screen.options.when-a-document-is-assigned-to-a-reviewer'),
+ whenADocumentIsSentForApproval: _('notifications-screen.options.when-a-document-is-sent-for-approval'),
+ whenAReviewerIsUnassignedFromADocument: _('notifications-screen.options.when-a-reviewer-is-unassigned-from-a-document'),
+ whenIAmAssignedOnADocument: _('notifications-screen.options.when-i-am-assigned-on-a-document'),
+ whenIAmUnassignedFromADocument: _('notifications-screen.options.when-i-am-unassigned-from-a-document'),
+ approver: _('notifications-screen.groups.approver'),
+ own: _('notifications-screen.groups.own'),
+ reviewer: _('notifications-screen.groups.reviewer'),
+ notifications: _('notifications-screen.title'),
+ 'user-profile': _('user-profile-screen.title'),
+} as const;
diff --git a/apps/red-ui/src/app/modules/admin/screens/justifications/justifications-dialog.service.ts b/apps/red-ui/src/app/modules/admin/screens/justifications/justifications-dialog.service.ts
index 5a226efb9..a4ee07326 100644
--- a/apps/red-ui/src/app/modules/admin/screens/justifications/justifications-dialog.service.ts
+++ b/apps/red-ui/src/app/modules/admin/screens/justifications/justifications-dialog.service.ts
@@ -5,7 +5,6 @@ import {
ConfirmationDialogInput,
DialogConfig,
DialogService,
- ListingService,
LoadingService,
TitleColors,
} from '@iqser/common-ui';
diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json
index c82e4bd4d..fdd8aaea6 100644
--- a/apps/red-ui/src/assets/i18n/en.json
+++ b/apps/red-ui/src/assets/i18n/en.json
@@ -1,4 +1,5 @@
{
+ "account-settings": "Account Settings",
"actions": {
"all": "All",
"none": "None"
@@ -1298,9 +1299,39 @@
"user-promoted-to-approver": "{user} promoted to approver in dossier: {dossierName}!",
"user-removed-as-dossier-member": "{user} removed as a member of: {dossierName} !"
},
- "notifications": {
- "mark-as": "Mark as {type, select, read{read} unread{unread} other{}}",
- "no-data": "You have no notifications."
+ "notifications": "Notifications",
+ "notifications-screen": {
+ "category": {
+ "email-notifications": "Email Notifications",
+ "in-app-notifications": "In-App Notifications"
+ },
+ "error": {
+ "generic": "Something went wrong... Preferences update failed!"
+ },
+ "groups": {
+ "approver": "Dossiers you are approver on",
+ "own": "Dossiers you own",
+ "reviewer": "Dossiers you are reviewer on"
+ },
+ "options-title": "Choose on which category you want to be notified",
+ "options": {
+ "document-is-sent-for-approval": "Document is sent for approval",
+ "document-status-changes": "Document status changes",
+ "dossier-status-changes": "Dossier status changes",
+ "request-to-join-the-dossier": "Request to join the dossier",
+ "when-a-document-is-approved": "When a document is approved",
+ "when-a-document-is-assigned-to-a-reviewer": "When a document is assigned to a reviewer",
+ "when-a-document-is-sent-for-approval": "When a document is sent for approval",
+ "when-a-reviewer-is-unassigned-from-a-document": "When a reviewer is unassigned from a document",
+ "when-i-am-assigned-on-a-document": "When I am assigned on a document",
+ "when-i-am-unassigned-from-a-document": "When I am unassigned from a document"
+ },
+ "schedule": {
+ "daily": "Daily Summary",
+ "instant": "Instant",
+ "weekly": "Weekly Summary"
+ },
+ "title": "Notifications Preferences"
},
"overwrite-files-dialog": {
"options": {
@@ -1477,6 +1508,7 @@
"dossiers": "Active Dossiers",
"my-account": {
"children": {
+ "account": "Account",
"admin": "Settings",
"downloads": "My Downloads",
"language": {
@@ -1485,7 +1517,6 @@
"label": "Language"
},
"logout": "Logout",
- "my-profile": "My Profile",
"trash": "Trash"
}
}
@@ -1557,17 +1588,18 @@
}
},
"user-management": "User Management",
- "user-profile": {
+ "user-profile": "My Profile",
+ "user-profile-screen": {
"actions": {
"change-password": "Change Password",
- "save": "Save profile"
+ "save": "Save Changes"
},
"form": {
"email": "Email",
"first-name": "First name",
"last-name": "Last name"
},
- "title": "My profile"
+ "title": "Edit Profile"
},
"user-stats": {
"chart": {
diff --git a/libs/red-domain/.eslintrc.json b/libs/red-domain/.eslintrc.json
index c3a38e5bf..a4e2637cd 100644
--- a/libs/red-domain/.eslintrc.json
+++ b/libs/red-domain/.eslintrc.json
@@ -1,15 +1,9 @@
{
- "extends": [
- "../../.eslintrc.json"
- ],
- "ignorePatterns": [
- "!**/*"
- ],
+ "extends": ["../../.eslintrc.json"],
+ "ignorePatterns": ["!**/*"],
"overrides": [
{
- "files": [
- "*.ts"
- ],
+ "files": ["*.ts"],
"extends": [
"plugin:@nrwl/nx/angular",
"plugin:@angular-eslint/template/process-inline-templates",
@@ -20,9 +14,7 @@
"plugin:@angular-eslint/recommended--extra"
],
"parserOptions": {
- "project": [
- "libs/red-domain/tsconfig.*?.json"
- ]
+ "project": ["libs/red-domain/tsconfig.*?.json"]
},
"rules": {
"@angular-eslint/directive-selector": [
@@ -55,33 +47,20 @@
"error",
{
"selector": "memberLike",
- "modifiers": [
- "private"
- ],
- "format": [
- "camelCase"
- ],
+ "modifiers": ["private"],
+ "format": ["camelCase"],
"leadingUnderscore": "require"
},
{
"selector": "memberLike",
- "modifiers": [
- "protected"
- ],
- "format": [
- "camelCase"
- ],
+ "modifiers": ["protected"],
+ "format": ["camelCase"],
"leadingUnderscore": "require"
},
{
"selector": "memberLike",
- "modifiers": [
- "private"
- ],
- "format": [
- "UPPER_CASE",
- "camelCase"
- ],
+ "modifiers": ["private"],
+ "format": ["UPPER_CASE", "camelCase"],
"leadingUnderscore": "require"
}
],
@@ -94,22 +73,12 @@
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/restrict-template-expressions": "off"
},
- "plugins": [
- "@angular-eslint/eslint-plugin",
- "@typescript-eslint"
- ]
+ "plugins": ["@angular-eslint/eslint-plugin", "@typescript-eslint"]
},
{
- "files": [
- "*.html"
- ],
- "extends": [
- "plugin:@nrwl/nx/angular-template",
- "plugin:@angular-eslint/template/recommended"
- ],
- "plugins": [
- "prettier"
- ],
+ "files": ["*.html"],
+ "extends": ["plugin:@nrwl/nx/angular-template", "plugin:@angular-eslint/template/recommended"],
+ "plugins": ["prettier"],
"rules": {}
}
]
diff --git a/libs/red-domain/src/index.ts b/libs/red-domain/src/index.ts
index 5365dabd6..3cd713b40 100644
--- a/libs/red-domain/src/index.ts
+++ b/libs/red-domain/src/index.ts
@@ -6,6 +6,7 @@ export * from './lib/users';
export * from './lib/pages';
export * from './lib/audit';
export * from './lib/notifications';
+export * from './lib/notifications-preferences';
export * from './lib/dossier-templates';
export * from './lib/dictionaries';
export * from './lib/redaction-log';
diff --git a/libs/red-domain/src/lib/notifications-preferences/index.ts b/libs/red-domain/src/lib/notifications-preferences/index.ts
new file mode 100644
index 000000000..f2fedd47f
--- /dev/null
+++ b/libs/red-domain/src/lib/notifications-preferences/index.ts
@@ -0,0 +1,2 @@
+export * from './notification-preferences';
+export * from './types';
diff --git a/libs/red-domain/src/lib/notifications-preferences/notification-preferences.ts b/libs/red-domain/src/lib/notifications-preferences/notification-preferences.ts
new file mode 100644
index 000000000..394af0193
--- /dev/null
+++ b/libs/red-domain/src/lib/notifications-preferences/notification-preferences.ts
@@ -0,0 +1,9 @@
+import { EmailNotificationScheduleType } from './types';
+
+export interface INotificationPreferences {
+ emailNotificationType: EmailNotificationScheduleType;
+ emailNotifications: string[];
+ emailNotificationsEnabled: boolean;
+ inAppNotifications: string[];
+ inAppNotificationsEnabled: boolean;
+}
diff --git a/libs/red-domain/src/lib/notifications-preferences/types.ts b/libs/red-domain/src/lib/notifications-preferences/types.ts
new file mode 100644
index 000000000..31c6061e1
--- /dev/null
+++ b/libs/red-domain/src/lib/notifications-preferences/types.ts
@@ -0,0 +1,8 @@
+export const EmailNotificationScheduleTypes = {
+ INSTANT: 'DAILY',
+ DAILY: 'DAILY_SUMMARY',
+ WEEKLY: 'WEEKLY_SUMMARY',
+} as const;
+
+export type EmailNotificationScheduleType = keyof typeof EmailNotificationScheduleTypes;
+export const EmailNotificationScheduleTypesValues = Object.values(EmailNotificationScheduleTypes);
diff --git a/paligo-theme/paligo-styles/redacto-theme.css b/paligo-theme/paligo-styles/redacto-theme.css
index a6388498e..0c1b353c2 100644
--- a/paligo-theme/paligo-styles/redacto-theme.css
+++ b/paligo-theme/paligo-styles/redacto-theme.css
@@ -1,507 +1,507 @@
@charset "UTF-8";
@font-face {
- font-family: "OpenSans";
- font-weight: 300;
- src: url("../fonts/OpenSans-VariableFont.ttf") format("truetype");
+ font-family: 'OpenSans';
+ font-weight: 300;
+ src: url('../fonts/OpenSans-VariableFont.ttf') format('truetype');
}
@font-face {
- font-family: "OpenSans";
- font-weight: 400;
- src: url("../fonts/OpenSans-VariableFont.ttf") format("truetype");
+ font-family: 'OpenSans';
+ font-weight: 400;
+ src: url('../fonts/OpenSans-VariableFont.ttf') format('truetype');
}
@font-face {
- font-family: "OpenSans";
- font-weight: 500;
- src: url("../fonts/OpenSans-VariableFont.ttf") format("truetype");
+ font-family: 'OpenSans';
+ font-weight: 500;
+ src: url('../fonts/OpenSans-VariableFont.ttf') format('truetype');
}
@font-face {
- font-family: "OpenSans";
- font-weight: 600;
- src: url("../fonts/OpenSans-VariableFont.ttf") format("truetype");
+ font-family: 'OpenSans';
+ font-weight: 600;
+ src: url('../fonts/OpenSans-VariableFont.ttf') format('truetype');
}
@font-face {
- font-family: "OpenSans";
- font-weight: 700;
- src: url("../font/OpenSans-VariableFont.ttf") format("truetype");
+ font-family: 'OpenSans';
+ font-weight: 700;
+ src: url('../font/OpenSans-VariableFont.ttf') format('truetype');
}
.portal-header {
- z-index: 1;
- height: 450px;
+ z-index: 1;
+ height: 450px;
}
.portal-header::before {
- background-color: #283241;
+ background-color: #283241;
}
.portal-header h1 {
- font-size: 64px;
- font-weight: 300;
- line-height: 87px;
- margin-top: 68px;
- margin-bottom: 40px;
+ font-size: 64px;
+ font-weight: 300;
+ line-height: 87px;
+ margin-top: 68px;
+ margin-bottom: 40px;
}
.portal-header .portal-search {
- max-width: 600px;
- margin: auto;
- position: relative;
+ max-width: 600px;
+ margin: auto;
+ position: relative;
}
.portal-header .portal-search .search-field {
- width: 100%;
- border: 1px solid #d3d5da;
- border-radius: 8px;
- background-color: #fff;
+ width: 100%;
+ border: 1px solid #d3d5da;
+ border-radius: 8px;
+ background-color: #fff;
}
.portal-header .portal-search .search-field::placeholder {
- opacity: 0.7;
+ opacity: 0.7;
}
.portal-header .portal-search .search-field,
.portal-header .portal-search .search-field::placeholder {
- color: #283241;
- font-size: 14px;
- line-height: 18px;
+ color: #283241;
+ font-size: 14px;
+ line-height: 18px;
}
.portal-header .portal-search .search-field {
- padding: 12px 17px;
+ padding: 12px 17px;
}
.portal-header .portal-search .btn {
- position: absolute;
- right: 0;
- padding: 11px 18px;
- background-color: transparent;
- color: #283241;
- cursor: pointer;
- border-radius: 0 8px 8px 0;
+ position: absolute;
+ right: 0;
+ padding: 11px 18px;
+ background-color: transparent;
+ color: #283241;
+ cursor: pointer;
+ border-radius: 0 8px 8px 0;
}
.portal-header .portal-search .btn:hover {
- background-color: #dd4d50;
+ background-color: #dd4d50;
}
@media only screen and (max-width: 768px) {
- .portal-header h1 {
- font-size: 42px;
- font-weight: 300;
- line-height: 57px;
- }
+ .portal-header h1 {
+ font-size: 42px;
+ font-weight: 300;
+ line-height: 57px;
+ }
}
.featured-content-label {
- display: none;
+ display: none;
}
.featured-content {
- display: none;
+ display: none;
}
.portal-single-publication .publication-icon {
- background-color: #dd4d50;
+ background-color: #dd4d50;
}
.portal-contents {
- margin-top: 100px;
- margin-bottom: 0;
+ margin-top: 100px;
+ margin-bottom: 0;
}
.portal-contents .inner {
- margin: 0;
- display: grid;
- grid-template-columns: 1fr 1fr;
- grid-gap: 24px;
+ margin: 0;
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ grid-gap: 24px;
}
.portal-contents .inner::before {
- content: none;
+ content: none;
}
.publication-contents {
- padding: 24px 40px;
- border: 1px solid #e2e4e9;
- width: 100%;
- margin: 0;
- background-color: #fff;
- border-radius: 4px;
+ padding: 24px 40px;
+ border: 1px solid #e2e4e9;
+ width: 100%;
+ margin: 0;
+ background-color: #fff;
+ border-radius: 4px;
}
.publication-contents:first-child {
- grid-column: 1/span 2;
+ grid-column: 1 / span 2;
}
.publication-contents h4.featured-title,
.publication-contents .section-toc-title {
- font-size: 26px;
- font-weight: 300;
- line-height: 36px;
- margin: 0;
+ font-size: 26px;
+ font-weight: 300;
+ line-height: 36px;
+ margin: 0;
}
.publication-contents h4.featured-title a,
.publication-contents .section-toc-title a {
- color: #283241;
+ color: #283241;
}
.publication-contents h4.featured-title a:hover,
.publication-contents .section-toc-title a:hover {
- color: #283241;
- text-decoration: underline;
+ color: #283241;
+ text-decoration: underline;
}
.publication-contents ul {
- margin: 0;
- padding: 0;
+ margin: 0;
+ padding: 0;
}
.publication-contents li {
- margin: 4px 0;
+ margin: 4px 0;
}
.publication-contents li:first-child {
- margin-top: 20px;
+ margin-top: 20px;
}
.publication-contents li:last-child {
- margin-bottom: 40px;
+ margin-bottom: 40px;
}
.publication-contents li a {
- color: #dd4d50;
- font-size: 16px;
- line-height: 24px;
+ color: #dd4d50;
+ font-size: 16px;
+ line-height: 24px;
}
.publication-contents li a:hover {
- color: #dd4d50;
- text-decoration: underline;
+ color: #dd4d50;
+ text-decoration: underline;
}
.publication-contents h4 span,
.publication-contents li::before {
- display: none;
+ display: none;
}
@media only screen and (max-width: 768px) {
- .portal-contents .inner {
- grid-template-columns: 1fr;
- }
+ .portal-contents .inner {
+ grid-template-columns: 1fr;
+ }
- .publication-contents:first-child {
- grid-column: auto;
- }
+ .publication-contents:first-child {
+ grid-column: auto;
+ }
}
/* Einleitung */
.cat-panel-1:before {
- content: "\f277";
+ content: '\f277';
}
/* Workflow */
.cat-panel-2:before {
- content: "\f0c1";
+ content: '\f0c1';
}
/* Voraussetzungen */
.cat-panel-3:before {
- content: "\f109";
+ content: '\f109';
}
/* Benutzermenü und -profil */
.cat-panel-4:before {
- content: "\f007";
+ content: '\f007';
}
/* Benachrichtigungen */
.cat-panel-5:before {
- content: "\f0f3";
+ content: '\f0f3';
}
/* Suchfunktion */
.cat-panel-6:before {
- content: "\f002";
+ content: '\f002';
}
/* Ebenen in der Benutzeroberfläche des RedactManagers */
.cat-panel-7:before {
- content: "\f248";
+ content: '\f248';
}
/* Rollen und Berechtigungen */
.cat-panel-8:before {
- content: "\f084";
+ content: '\f084';
}
/* Dossier erstellen und verwalten */
.cat-panel-9:before {
- content: "\f07c";
+ content: '\f07c';
}
/* Dokumente bearbeiten im Editor */
.cat-panel-10:before {
- content: "\f15c";
+ content: '\f15c';
}
/* Dossier abschließen und herunterladen */
.cat-panel-11:before {
- content: "\f019";
+ content: '\f019';
}
/* Funktionsübersicht */
.cat-panel-12:before {
- content: "\f03a";
+ content: '\f03a';
}
/* Glossar */
.cat-panel-13:before {
- content: "\f02d";
+ content: '\f02d';
}
/* FAQ’s (häufige Fragen) */
.cat-panel-14:before {
- content: "\f059";
+ content: '\f059';
}
.portal-search-result {
- background-color: #f5f5f7;
+ background-color: #f5f5f7;
}
.search-container {
- padding-bottom: 100px;
+ padding-bottom: 100px;
}
.search-container h2 {
- font-size: 42px;
- font-weight: 300;
- line-height: 57px;
+ font-size: 42px;
+ font-weight: 300;
+ line-height: 57px;
}
.portal-search-result {
- padding: 80px 0 0 0;
+ padding: 80px 0 0 0;
}
ul.searchresults {
- border: 1px solid #e2e4e9;
- background-color: #fff;
- border-radius: 4px;
- margin-top: 32px;
+ border: 1px solid #e2e4e9;
+ background-color: #fff;
+ border-radius: 4px;
+ margin-top: 32px;
}
ul.searchresults .search-highlight {
- font-style: normal;
+ font-style: normal;
}
li.searchresultitem {
- margin: 0 32px;
- border-bottom: 1px solid #e2e4e9;
- padding: 32px 8px;
+ margin: 0 32px;
+ border-bottom: 1px solid #e2e4e9;
+ padding: 32px 8px;
}
.searchresultitem.selected-searchresultitem {
- background-color: transparent;
- border-radius: 0;
+ background-color: transparent;
+ border-radius: 0;
}
.searchresulttitle {
- font-size: 26px;
- font-weight: 300;
- line-height: 36px;
- color: #283241;
+ font-size: 26px;
+ font-weight: 300;
+ line-height: 36px;
+ color: #283241;
}
.searchresultsnippet {
- margin: 16px 0;
- color: #283241;
+ margin: 16px 0;
+ color: #283241;
}
.search-result-breadcrumbs {
- color: #dd4d50;
+ color: #dd4d50;
}
.portal-footer,
.site-footer {
- border-top: 1px solid #e2e4e9;
- padding: 0;
+ border-top: 1px solid #e2e4e9;
+ padding: 0;
}
.portal-footer.portal-footer,
.site-footer.portal-footer {
- margin-top: 100px;
+ margin-top: 100px;
}
.portal-footer .inner,
.site-footer .inner {
- margin: 0;
- padding: 8px 0 64px 0;
- font-size: 16px;
- line-height: 24px;
+ margin: 0;
+ padding: 8px 0 64px 0;
+ font-size: 16px;
+ line-height: 24px;
}
.portal-footer .inner > *,
.site-footer .inner > * {
- padding: 0;
+ padding: 0;
}
.portal-footer .inner .copyright,
.site-footer .inner .copyright {
- width: 50%;
+ width: 50%;
}
:root {
- --iqser-primary: lightblue;
- --iqser-primary-rgb: 220, 230, 234;
- --iqser-primary-2: orange;
- --iqser-accent: blue;
- --iqser-accent-rgb: 123, 234, 111;
- --iqser-disabled: #9398a0;
- --iqser-not-disabled-table-item: #f9fafb;
- --iqser-btn-bg-hover: #e2e4e9;
- --iqser-btn-bg: #f0f1f4;
- --iqser-warn: #fdbd00;
- --iqser-white: white;
- --iqser-black: black;
- --iqser-light: white;
- --iqser-separator: rgba(226, 228, 233, 0.9);
- --iqser-quick-filter-border: #d3d5da;
- --iqser-grey-1: #283241;
- --iqser-grey-2: #f4f5f7;
- --iqser-grey-3: #aaacb3;
- --iqser-grey-4: #e2e4e9;
- --iqser-grey-5: #d3d5da;
- --iqser-grey-6: #f0f1f4;
- --iqser-grey-7: #9398a0;
- --iqser-green-1: #00ff00;
- --iqser-green-2: #5ce594;
- --iqser-yellow-1: #ffb83b;
- --iqser-yellow-2: #fdbd00;
- --iqser-red-1: #dd4d50;
- --iqser-blue-5: #c5d3eb;
- --iqser-helpmode-primary: green;
+ --iqser-primary: lightblue;
+ --iqser-primary-rgb: 220, 230, 234;
+ --iqser-primary-2: orange;
+ --iqser-accent: blue;
+ --iqser-accent-rgb: 123, 234, 111;
+ --iqser-disabled: #9398a0;
+ --iqser-not-disabled-table-item: #f9fafb;
+ --iqser-btn-bg-hover: #e2e4e9;
+ --iqser-btn-bg: #f0f1f4;
+ --iqser-warn: #fdbd00;
+ --iqser-white: white;
+ --iqser-black: black;
+ --iqser-light: white;
+ --iqser-separator: rgba(226, 228, 233, 0.9);
+ --iqser-quick-filter-border: #d3d5da;
+ --iqser-grey-1: #283241;
+ --iqser-grey-2: #f4f5f7;
+ --iqser-grey-3: #aaacb3;
+ --iqser-grey-4: #e2e4e9;
+ --iqser-grey-5: #d3d5da;
+ --iqser-grey-6: #f0f1f4;
+ --iqser-grey-7: #9398a0;
+ --iqser-green-1: #00ff00;
+ --iqser-green-2: #5ce594;
+ --iqser-yellow-1: #ffb83b;
+ --iqser-yellow-2: #fdbd00;
+ --iqser-red-1: #dd4d50;
+ --iqser-blue-5: #c5d3eb;
+ --iqser-helpmode-primary: green;
}
.site-sidebar {
- background-color: #283241;
- scrollbar-color: var(--iqser-quick-filter-border) var(--iqser-grey-2);
- scrollbar-width: thin;
- /* Track */
- /* Handle */
+ background-color: #283241;
+ scrollbar-color: var(--iqser-quick-filter-border) var(--iqser-grey-2);
+ scrollbar-width: thin;
+ /* Track */
+ /* Handle */
}
.site-sidebar .logo {
- padding: 24px 0 30px 0 !important;
+ padding: 24px 0 30px 0 !important;
}
.site-sidebar::-webkit-scrollbar {
- width: 11px;
+ width: 11px;
}
.site-sidebar::-webkit-scrollbar-track {
- background: var(--iqser-grey-2);
+ background: var(--iqser-grey-2);
}
.site-sidebar::-webkit-scrollbar-thumb {
- background: var(--iqser-quick-filter-border);
+ background: var(--iqser-quick-filter-border);
}
.site-sidebar-search {
- padding: 0 24px;
+ padding: 0 24px;
}
.site-sidebar-search .search-field {
- width: 100%;
- border: 1px solid #d3d5da;
- border-radius: 8px;
- background-color: #fff;
+ width: 100%;
+ border: 1px solid #d3d5da;
+ border-radius: 8px;
+ background-color: #fff;
}
.site-sidebar-search .search-field::placeholder {
- opacity: 0.7;
+ opacity: 0.7;
}
.site-sidebar-search .search-field,
.site-sidebar-search .search-field::placeholder {
- color: #283241;
- font-size: 14px;
- line-height: 18px;
+ color: #283241;
+ font-size: 14px;
+ line-height: 18px;
}
.site-sidebar-search .search-field {
- padding: 7px 13px;
+ padding: 7px 13px;
}
.nav-site-sidebar {
- margin-top: 16px;
+ margin-top: 16px;
}
.nav-site-sidebar .topic-link {
- padding-top: 11px;
- padding-bottom: 11px;
- font-size: 14px;
- line-height: 18px;
- color: #d3d5da;
+ padding-top: 11px;
+ padding-bottom: 11px;
+ font-size: 14px;
+ line-height: 18px;
+ color: #d3d5da;
}
.nav-site-sidebar .topic-link:hover {
- background-color: #313d4e;
+ background-color: #313d4e;
}
.nav-site-sidebar .active > .topic-link {
- background-color: #313d4e;
+ background-color: #313d4e;
}
.nav-site-sidebar .active > a {
- color: #fff;
- font-weight: 600;
+ color: #fff;
+ font-weight: 600;
}
.nav-site-sidebar > li > a {
- padding-left: 24px;
+ padding-left: 24px;
}
.nav-site-sidebar > li > ul > li > a {
- padding-left: 32px;
+ padding-left: 32px;
}
.nav-site-sidebar > li > ul > li > ul > li > a {
- padding-left: 40px;
+ padding-left: 40px;
}
.toc .glyphicon {
- top: 5px;
+ top: 5px;
}
.toc > li > .topic-link > .glyphicon {
- margin-top: 4px;
+ margin-top: 4px;
}
.toolbar {
- box-shadow: none;
- padding: 21px 24px;
- margin-bottom: 50px;
+ box-shadow: none;
+ padding: 21px 24px;
+ margin-bottom: 50px;
}
.topic-content .breadcrumb-container {
- margin-top: 40px;
+ margin-top: 40px;
}
.topic-content .breadcrumb {
- font-size: 14px;
- line-height: 18px;
- font-weight: 600;
+ font-size: 14px;
+ line-height: 18px;
+ font-weight: 600;
}
.topic-content .breadcrumb a {
- color: #283241;
+ color: #283241;
}
.topic-content .breadcrumb a:hover {
- color: #dd4d50;
- text-decoration: underline;
+ color: #dd4d50;
+ text-decoration: underline;
}
.topic-content .breadcrumb .breadcrumb-node {
- color: #dd4d50;
+ color: #dd4d50;
}
main article {
- margin-bottom: 0;
- padding: 0;
+ margin-bottom: 0;
+ padding: 0;
}
section > .titlepage .title {
- margin: 24px 0 16px 0;
+ margin: 24px 0 16px 0;
}
#topic-content > section > .titlepage h2.title {
- margin: 0 0 24px;
- font-size: 32px;
- font-weight: 300;
- line-height: 43px;
+ margin: 0 0 24px;
+ font-size: 32px;
+ font-weight: 300;
+ line-height: 43px;
}
.image-viewport {
- margin: auto;
+ margin: auto;
}
.image-viewport img {
- margin: 16px auto;
- box-shadow: 0 3px 12px 5px rgba(40, 50, 65, 0.14);
+ margin: 16px auto;
+ box-shadow: 0 3px 12px 5px rgba(40, 50, 65, 0.14);
}
.pager {
- margin-top: 30px;
- margin-bottom: 30px;
- padding: 0;
+ margin-top: 30px;
+ margin-bottom: 30px;
+ padding: 0;
}
.pager li > a,
.pager li > span {
- color: #dd4d50;
- font-size: 14px;
- font-weight: 600;
- line-height: 19px;
- text-transform: uppercase;
- padding: 0;
- background-color: transparent;
- border: none;
- border-radius: 0;
+ color: #dd4d50;
+ font-size: 14px;
+ font-weight: 600;
+ line-height: 19px;
+ text-transform: uppercase;
+ padding: 0;
+ background-color: transparent;
+ border: none;
+ border-radius: 0;
}
.pager li > a:hover,
.pager li > span:hover {
- text-decoration: underline;
- background-color: transparent;
- color: #dd4d50;
+ text-decoration: underline;
+ background-color: transparent;
+ color: #dd4d50;
}
.warning,
@@ -509,152 +509,152 @@ section > .titlepage .title {
.important,
.caution,
.tip {
- margin-top: 32px;
- margin-bottom: 32px;
- padding: 16px 24px 16px 68px;
- background-color: #fff;
- border-left: 4px solid #dd4d50;
+ margin-top: 32px;
+ margin-bottom: 32px;
+ padding: 16px 24px 16px 68px;
+ background-color: #fff;
+ border-left: 4px solid #dd4d50;
}
.warning:before,
.note:before,
.important:before,
.caution:before,
.tip:before {
- color: #dd4d50;
- width: 20px;
- height: 20px;
- text-align: center;
- left: 24px;
- top: calc(50% - 15px);
+ color: #dd4d50;
+ width: 20px;
+ height: 20px;
+ text-align: center;
+ left: 24px;
+ top: calc(50% - 15px);
}
.warning h3,
.note h3,
.important h3,
.caution h3,
.tip h3 {
- padding: 0;
- font-size: 18px;
- font-weight: 600;
- line-height: 24px;
- margin-bottom: 8px;
+ padding: 0;
+ font-size: 18px;
+ font-weight: 600;
+ line-height: 24px;
+ margin-bottom: 8px;
}
.warning p,
.note p,
.important p,
.caution p,
.tip p {
- line-height: 20px;
+ line-height: 20px;
}
.topic-content > section > p {
- margin: 24px 0;
+ margin: 24px 0;
}
.mediaobject {
- margin-top: 20px;
+ margin-top: 20px;
}
.mediaobject img {
- border-radius: 4px;
- margin: 0;
+ border-radius: 4px;
+ margin: 0;
}
.mediaobject .caption > p {
- font-size: 14px;
- text-align: center;
- font-style: italic;
- margin: 0;
+ font-size: 14px;
+ text-align: center;
+ font-style: italic;
+ margin: 0;
}
.inlinemediaobject {
- vertical-align: unset;
+ vertical-align: unset;
}
main ol,
main ul {
- margin: 0 0 24px;
+ margin: 0 0 24px;
}
.section-toc {
- padding: 24px 40px;
- border: 1px solid #e2e4e9;
- width: 100%;
- margin: 0;
- background-color: #fff;
- border-radius: 4px;
+ padding: 24px 40px;
+ border: 1px solid #e2e4e9;
+ width: 100%;
+ margin: 0;
+ background-color: #fff;
+ border-radius: 4px;
}
.section-toc:first-child {
- grid-column: 1/span 2;
+ grid-column: 1 / span 2;
}
.section-toc h4.featured-title,
.section-toc .section-toc-title {
- font-size: 26px;
- font-weight: 300;
- line-height: 36px;
- margin: 0;
+ font-size: 26px;
+ font-weight: 300;
+ line-height: 36px;
+ margin: 0;
}
.section-toc h4.featured-title a,
.section-toc .section-toc-title a {
- color: #283241;
+ color: #283241;
}
.section-toc h4.featured-title a:hover,
.section-toc .section-toc-title a:hover {
- color: #283241;
- text-decoration: underline;
+ color: #283241;
+ text-decoration: underline;
}
.section-toc ul {
- margin: 0;
- padding: 0;
+ margin: 0;
+ padding: 0;
}
.section-toc li {
- margin: 4px 0;
+ margin: 4px 0;
}
.section-toc li:first-child {
- margin-top: 20px;
+ margin-top: 20px;
}
.section-toc li:last-child {
- margin-bottom: 40px;
+ margin-bottom: 40px;
}
.section-toc li a {
- color: #dd4d50;
- font-size: 16px;
- line-height: 24px;
+ color: #dd4d50;
+ font-size: 16px;
+ line-height: 24px;
}
.section-toc li a:hover {
- color: #dd4d50;
- text-decoration: underline;
+ color: #dd4d50;
+ text-decoration: underline;
}
.section-toc h4 span,
.section-toc li::before {
- display: none;
+ display: none;
}
.section-toc li:first-child {
- margin-top: 16px;
+ margin-top: 16px;
}
.section-toc li:last-child {
- margin-bottom: 8px;
+ margin-bottom: 8px;
}
.question {
- font-weight: 600;
+ font-weight: 600;
}
.question > td > p {
- margin: 32px 0 18px 0;
+ margin: 32px 0 18px 0;
}
.question > td:first-child {
- padding-right: 4px;
+ padding-right: 4px;
}
.fixed-toolbar article.topic :target.question:before {
- content: none;
+ content: none;
}
body {
- color: #283241;
- background-color: #f5f5f7;
- font-family: "OpenSans", sans-serif;
- scrollbar-color: var(--iqser-quick-filter-border) var(--iqser-grey-2);
- scrollbar-width: thin;
- /* Track */
- /* Handle */
+ color: #283241;
+ background-color: #f5f5f7;
+ font-family: 'OpenSans', sans-serif;
+ scrollbar-color: var(--iqser-quick-filter-border) var(--iqser-grey-2);
+ scrollbar-width: thin;
+ /* Track */
+ /* Handle */
}
body h1,
body h2,
@@ -664,31 +664,31 @@ body h5,
body h6,
body p,
body pre {
- margin: 0;
- font-family: "OpenSans", sans-serif;
+ margin: 0;
+ font-family: 'OpenSans', sans-serif;
}
body::-webkit-scrollbar {
- width: 11px;
+ width: 11px;
}
body::-webkit-scrollbar-track {
- background: var(--iqser-grey-2);
+ background: var(--iqser-grey-2);
}
body::-webkit-scrollbar-thumb {
- background: var(--iqser-quick-filter-border);
+ background: var(--iqser-quick-filter-border);
}
body h3 {
- font-size: 32px;
- font-weight: 300;
- line-height: 43px;
+ font-size: 32px;
+ font-weight: 300;
+ line-height: 43px;
}
body p {
- font-size: 16px;
- line-height: 24px;
+ font-size: 16px;
+ line-height: 24px;
}
body a {
- color: #dd4d50;
+ color: #dd4d50;
}
body a:hover {
- text-decoration: underline;
- color: #dd4d50;
+ text-decoration: underline;
+ color: #dd4d50;
}