diff --git a/apps/red-ui/src/app/app-routing.module.ts b/apps/red-ui/src/app/app-routing.module.ts index 23e8b18d8..0033f3247 100644 --- a/apps/red-ui/src/app/app-routing.module.ts +++ b/apps/red-ui/src/app/app-routing.module.ts @@ -48,6 +48,7 @@ const dossierTemplateIdRoutes: IqserRoutes = [ allow: [ROLES.dossierAttributes.read, ROLES.dossierAttributes.readConfig], redirectTo: '/auth-error', }, + skeleton: 'dossier', }, loadChildren: () => import('./modules/dossier-overview/dossier-overview.module').then(m => m.DossierOverviewModule), }, @@ -119,9 +120,9 @@ const routes: IqserRoutes = [ { path: 'dashboard', loadChildren: () => import('./modules/dashboard/dashboard.module').then(m => m.DashboardModule), - canActivate: [CompositeRouteGuard, IqserPermissionsGuard], + canActivate: [CompositeRouteGuard], data: { - routeGuards: [IqserAuthGuard, RedRoleGuard, DossierTemplatesGuard, DashboardGuard], + routeGuards: [IqserAuthGuard, RedRoleGuard, IqserPermissionsGuard, DossierTemplatesGuard, DashboardGuard], permissions: { allow: [ ROLES.any, @@ -140,6 +141,7 @@ const routes: IqserRoutes = [ [DEFAULT_REDIRECT_KEY]: '/auth-error', }, }, + skeleton: 'dashboard', }, }, { diff --git a/apps/red-ui/src/app/app.component.html b/apps/red-ui/src/app/app.component.html index 6f2b09693..a5f32ccc0 100644 --- a/apps/red-ui/src/app/app.component.html +++ b/apps/red-ui/src/app/app.component.html @@ -5,3 +5,13 @@ + + + + + + + + + + diff --git a/apps/red-ui/src/app/app.module.ts b/apps/red-ui/src/app/app.module.ts index 3c25bae90..b08fc3adb 100644 --- a/apps/red-ui/src/app/app.module.ts +++ b/apps/red-ui/src/app/app.module.ts @@ -14,6 +14,7 @@ import { IqserLoadingModule, IqserPermissionsModule, IqserPermissionsService, + IqserSharedModule, IqserTranslateModule, IqserUsersModule, LanguageService, @@ -27,6 +28,7 @@ import { ServiceWorkerModule } from '@angular/service-worker'; import { environment } from '@environments/environment'; import { AuthErrorComponent } from '@components/auth-error/auth-error.component'; import { NotificationsComponent } from '@components/notifications/notifications.component'; +import { DashboardSkeletonComponent } from '@components/skeleton/dashboard-skeleton/dashboard-skeleton.component'; import { DownloadsListScreenComponent } from '@components/downloads-list-screen/downloads-list-screen.component'; import { AppRoutingModule } from './app-routing.module'; import { SharedModule } from '@shared/shared.module'; @@ -59,10 +61,25 @@ import { LicenseService } from '@services/license.service'; import { TenantIdInterceptor } from '@utils/tenant-id-interceptor'; import { UI_CACHES } from '@utils/constants'; import { RedRoleGuard } from '@users/red-role.guard'; +import { SkeletonTopBarComponent } from '@components/skeleton/skeleton-top-bar/skeleton-top-bar.component'; +import { DossierSkeletonComponent } from '@components/skeleton/dossier-skeleton/dossier-skeleton.component'; +import { SkeletonStatsComponent } from '@components/skeleton/skeleton-stats/skeleton-stats.component'; const screens = [BaseScreenComponent, DownloadsListScreenComponent]; -const components = [AppComponent, AuthErrorComponent, NotificationsComponent, SpotlightSearchComponent, BreadcrumbsComponent, ...screens]; +const components = [ + AppComponent, + AuthErrorComponent, + NotificationsComponent, + SpotlightSearchComponent, + BreadcrumbsComponent, + DashboardSkeletonComponent, + DossierSkeletonComponent, + SkeletonTopBarComponent, + SkeletonStatsComponent, + + ...screens, +]; export const appModuleFactory = (config: AppConfig) => { @NgModule({ @@ -83,6 +100,7 @@ export const appModuleFactory = (config: AppConfig) => { existingUserService: UserService, existingRoleGuard: RedRoleGuard, }), + IqserSharedModule, CachingModule.forRoot(UI_CACHES), IqserHelpModeModule.forRoot(links), PdfViewerModule, diff --git a/apps/red-ui/src/app/components/skeleton/dashboard-skeleton/dashboard-skeleton.component.html b/apps/red-ui/src/app/components/skeleton/dashboard-skeleton/dashboard-skeleton.component.html new file mode 100644 index 000000000..92bf9dabb --- /dev/null +++ b/apps/red-ui/src/app/components/skeleton/dashboard-skeleton/dashboard-skeleton.component.html @@ -0,0 +1,16 @@ + + +
+ +
+
+
+ +
+
+
+
+
+ +
+
diff --git a/apps/red-ui/src/app/components/skeleton/dashboard-skeleton/dashboard-skeleton.component.scss b/apps/red-ui/src/app/components/skeleton/dashboard-skeleton/dashboard-skeleton.component.scss new file mode 100644 index 000000000..535465137 --- /dev/null +++ b/apps/red-ui/src/app/components/skeleton/dashboard-skeleton/dashboard-skeleton.component.scss @@ -0,0 +1,33 @@ +@use 'common-mixins'; + +:host { + min-height: 100vh; + background-color: var(--iqser-alt-background); + display: flex; + flex-direction: column; + align-items: center; + + .container { + padding: 32px; + width: 900px; + max-width: 100%; + box-sizing: border-box; + } +} + +.dialog { + flex-direction: row; + max-width: unset; + min-height: unset; + margin: 0 0 16px 0; + + > div { + display: flex; + flex-direction: column; + overflow: hidden; + } + + redaction-skeleton-stats { + border-left: 1px solid var(--iqser-separator); + } +} diff --git a/apps/red-ui/src/app/components/skeleton/dashboard-skeleton/dashboard-skeleton.component.ts b/apps/red-ui/src/app/components/skeleton/dashboard-skeleton/dashboard-skeleton.component.ts new file mode 100644 index 000000000..67c47d282 --- /dev/null +++ b/apps/red-ui/src/app/components/skeleton/dashboard-skeleton/dashboard-skeleton.component.ts @@ -0,0 +1,9 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; + +@Component({ + selector: 'redaction-dashboard-skeleton', + templateUrl: './dashboard-skeleton.component.html', + styleUrls: ['./dashboard-skeleton.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class DashboardSkeletonComponent {} diff --git a/apps/red-ui/src/app/components/skeleton/dossier-skeleton/dossier-skeleton.component.html b/apps/red-ui/src/app/components/skeleton/dossier-skeleton/dossier-skeleton.component.html new file mode 100644 index 000000000..fcaa9e487 --- /dev/null +++ b/apps/red-ui/src/app/components/skeleton/dossier-skeleton/dossier-skeleton.component.html @@ -0,0 +1,134 @@ + + +
+ + +
+ +
+
+
+
+ +
+
+
+ +
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+ + +
+
+
+
+ + +
+
+ + + + +
+
+
+ + +
+
+ + +
+
+
diff --git a/apps/red-ui/src/app/components/skeleton/dossier-skeleton/dossier-skeleton.component.scss b/apps/red-ui/src/app/components/skeleton/dossier-skeleton/dossier-skeleton.component.scss new file mode 100644 index 000000000..3f2bcbc90 --- /dev/null +++ b/apps/red-ui/src/app/components/skeleton/dossier-skeleton/dossier-skeleton.component.scss @@ -0,0 +1,87 @@ +@use 'common-mixins'; + +:host { + background-color: var(--iqser-background); + display: block; +} + +.w-100p { + width: 100%; +} + +.right-container { + display: flex; + flex-direction: column; + width: 375px; + min-width: 375px; + padding: 16px 24px; + overflow: hidden; + + .header { + display: flex; + align-items: center; + justify-content: space-between; + } +} + +.sk-table { + display: flex; + + .sk-table-header, + .sk-table-cell { + padding: 0 10px; + border-bottom: 1px solid var(--iqser-separator); + box-sizing: border-box; + } + + .sk-table-column { + display: flex; + flex-direction: column; + flex: 1; + + &:first-child { + flex: 3; + + .sk-table-header, + .sk-table-cell { + padding-left: 56px; + } + } + + .sk-line { + margin: auto 0; + } + + &:last-child { + flex: 2; + + .sk-table-header, + .sk-table-cell { + padding-right: 21px; + } + + .sk-line { + margin-left: auto; + } + } + + &:nth-child(4), + &:nth-child(5) { + .sk-line, + .sk-circle { + margin: auto; + } + } + } + + .sk-table-header { + height: 30px; + padding-top: 11px; + } + + .sk-table-cell { + height: 80px; + display: flex; + align-items: center; + } +} diff --git a/apps/red-ui/src/app/components/skeleton/dossier-skeleton/dossier-skeleton.component.ts b/apps/red-ui/src/app/components/skeleton/dossier-skeleton/dossier-skeleton.component.ts new file mode 100644 index 000000000..4b5724e8e --- /dev/null +++ b/apps/red-ui/src/app/components/skeleton/dossier-skeleton/dossier-skeleton.component.ts @@ -0,0 +1,35 @@ +import { ChangeDetectionStrategy, Component, OnInit, TemplateRef, ViewChild } from '@angular/core'; + +@Component({ + selector: 'redaction-dossier-skeleton', + templateUrl: './dossier-skeleton.component.html', + styleUrls: ['./dossier-skeleton.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class DossierSkeletonComponent implements OnInit { + @ViewChild('workload1', { static: true }) workload1: TemplateRef; + @ViewChild('workload2', { static: true }) workload2: TemplateRef; + @ViewChild('workload3', { static: true }) workload3: TemplateRef; + @ViewChild('workload4', { static: true }) workload4: TemplateRef; + @ViewChild('workload5', { static: true }) workload5: TemplateRef; + @ViewChild('workload6', { static: true }) workload6: TemplateRef; + + workloadTemplates: TemplateRef[]; + + ngOnInit(): void { + this.workloadTemplates = [ + this.workload1, + this.workload3, + this.workload2, + this.workload3, + this.workload4, + this.workload5, + this.workload1, + this.workload5, + this.workload6, + this.workload6, + this.workload2, + this.workload5, + ]; + } +} diff --git a/apps/red-ui/src/app/components/skeleton/skeleton-stats/skeleton-stats.component.html b/apps/red-ui/src/app/components/skeleton/skeleton-stats/skeleton-stats.component.html new file mode 100644 index 000000000..6d01a6bd8 --- /dev/null +++ b/apps/red-ui/src/app/components/skeleton/skeleton-stats/skeleton-stats.component.html @@ -0,0 +1,10 @@ +
+ +
+ +
+
+
+
+
+
diff --git a/apps/red-ui/src/app/components/skeleton/skeleton-stats/skeleton-stats.component.scss b/apps/red-ui/src/app/components/skeleton/skeleton-stats/skeleton-stats.component.scss new file mode 100644 index 000000000..01079ba9d --- /dev/null +++ b/apps/red-ui/src/app/components/skeleton/skeleton-stats/skeleton-stats.component.scss @@ -0,0 +1,10 @@ +:host { + display: flex; + align-items: center; +} + +mat-icon { + width: unset; + height: unset; + color: var(--iqser-skeleton-color); +} diff --git a/apps/red-ui/src/app/components/skeleton/skeleton-stats/skeleton-stats.component.ts b/apps/red-ui/src/app/components/skeleton/skeleton-stats/skeleton-stats.component.ts new file mode 100644 index 000000000..ba2b3f882 --- /dev/null +++ b/apps/red-ui/src/app/components/skeleton/skeleton-stats/skeleton-stats.component.ts @@ -0,0 +1,9 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; + +@Component({ + selector: 'redaction-skeleton-stats', + templateUrl: './skeleton-stats.component.html', + styleUrls: ['./skeleton-stats.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class SkeletonStatsComponent {} diff --git a/apps/red-ui/src/app/components/skeleton/skeleton-top-bar/skeleton-top-bar.component.html b/apps/red-ui/src/app/components/skeleton/skeleton-top-bar/skeleton-top-bar.component.html new file mode 100644 index 000000000..e83646bf0 --- /dev/null +++ b/apps/red-ui/src/app/components/skeleton/skeleton-top-bar/skeleton-top-bar.component.html @@ -0,0 +1,15 @@ + diff --git a/apps/red-ui/src/app/components/skeleton/skeleton-top-bar/skeleton-top-bar.component.scss b/apps/red-ui/src/app/components/skeleton/skeleton-top-bar/skeleton-top-bar.component.scss new file mode 100644 index 000000000..02e36c560 --- /dev/null +++ b/apps/red-ui/src/app/components/skeleton/skeleton-top-bar/skeleton-top-bar.component.scss @@ -0,0 +1,9 @@ +:host { + display: contents; +} + +.top-bar .actions { + display: flex; + align-items: center; + justify-content: flex-end; +} diff --git a/apps/red-ui/src/app/components/skeleton/skeleton-top-bar/skeleton-top-bar.component.ts b/apps/red-ui/src/app/components/skeleton/skeleton-top-bar/skeleton-top-bar.component.ts new file mode 100644 index 000000000..1ac32cbd5 --- /dev/null +++ b/apps/red-ui/src/app/components/skeleton/skeleton-top-bar/skeleton-top-bar.component.ts @@ -0,0 +1,12 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { Title } from '@angular/platform-browser'; + +@Component({ + selector: 'redaction-skeleton-top-bar', + templateUrl: './skeleton-top-bar.component.html', + styleUrls: ['./skeleton-top-bar.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class SkeletonTopBarComponent { + constructor(readonly titleService: Title) {} +} diff --git a/apps/red-ui/src/app/modules/archive/archive-routing.module.ts b/apps/red-ui/src/app/modules/archive/archive-routing.module.ts index 905d3924a..69315fb0d 100644 --- a/apps/red-ui/src/app/modules/archive/archive-routing.module.ts +++ b/apps/red-ui/src/app/modules/archive/archive-routing.module.ts @@ -20,6 +20,7 @@ const routes: Routes = [ routeGuards: [DossierFilesGuard], breadcrumbs: [BreadcrumbTypes.dossierTemplate, BreadcrumbTypes.dossier], dossiersService: ARCHIVED_DOSSIERS_SERVICE, + skeleton: 'dossier', }, loadChildren: () => import('../dossier-overview/dossier-overview.module').then(m => m.DossierOverviewModule), }, diff --git a/apps/red-ui/src/app/modules/icons/icons.module.ts b/apps/red-ui/src/app/modules/icons/icons.module.ts index 9b1eeb327..71e2161bc 100644 --- a/apps/red-ui/src/app/modules/icons/icons.module.ts +++ b/apps/red-ui/src/app/modules/icons/icons.module.ts @@ -68,6 +68,7 @@ export class IconsModule { 'rss', 'rule', 'secret', + 'skeleton-stats', 'status', 'status-info', 'template', diff --git a/apps/red-ui/src/assets/config/config.json b/apps/red-ui/src/assets/config/config.json index f4b69417a..c2b4d2dfb 100644 --- a/apps/red-ui/src/assets/config/config.json +++ b/apps/red-ui/src/assets/config/config.json @@ -1,7 +1,7 @@ { "ADMIN_CONTACT_NAME": null, "ADMIN_CONTACT_URL": null, - "API_URL": "https://dev-08.iqser.cloud/redaction-gateway-v1", + "API_URL": "https://dev-04.iqser.cloud/redaction-gateway-v1", "APP_NAME": "RedactManager", "AUTO_READ_TIME": 3, "BACKEND_APP_VERSION": "4.4.40", @@ -11,7 +11,7 @@ "MAX_RETRIES_ON_SERVER_ERROR": 3, "OAUTH_CLIENT_ID": "redaction", "OAUTH_IDP_HINT": null, - "OAUTH_URL": "https://dev-08.iqser.cloud/auth/realms/redaction", + "OAUTH_URL": "https://dev-04.iqser.cloud/auth/realms/redaction", "RECENT_PERIOD_IN_HOURS": 24, "SELECTION_MODE": "structural", "MANUAL_BASE_URL": "https://docs.redactmanager.com/preview", diff --git a/apps/red-ui/src/assets/icons/general/skeleton-stats.svg b/apps/red-ui/src/assets/icons/general/skeleton-stats.svg new file mode 100644 index 000000000..66933075a --- /dev/null +++ b/apps/red-ui/src/assets/icons/general/skeleton-stats.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/red-ui/src/styles.scss b/apps/red-ui/src/styles.scss index 0e445cf4b..fd6f16587 100644 --- a/apps/red-ui/src/styles.scss +++ b/apps/red-ui/src/styles.scss @@ -80,6 +80,7 @@ $iqser-tab-hover: vars.$grey-6, $iqser-loading-progress: vars.$grey-7, $iqser-highlight-color: #fffcc4, + $iqser-skeleton-color: vars.$grey-4, $iqser-font-family: 'Inter, sans-serif', $iqser-app-name-font-family: 'OpenSans Extrabold, sans-serif' ); @@ -132,6 +133,7 @@ $dark-accent-10: darken(vars.$accent, 10%); $iqser-tab-hover: vars.$accent, $iqser-loading-progress: $light-accent-10, $iqser-highlight-color: #905854, + $iqser-skeleton-color: vars.$grey-10, $iqser-font-family: 'Inter, sans-serif', $iqser-app-name-font-family: 'OpenSans Extrabold, sans-serif' ); diff --git a/libs/common-ui b/libs/common-ui index cb3f1e3ee..9340cda21 160000 --- a/libs/common-ui +++ b/libs/common-ui @@ -1 +1 @@ -Subproject commit cb3f1e3eea6353711d2e5bdfe8664b1b4b8e70e2 +Subproject commit 9340cda21abe78b653c876b7d0fd045ecda28a57