From 7f28fc17ca4eae802a632cb9f6549f3f3076c171 Mon Sep 17 00:00:00 2001 From: Alex Inkin Date: Sat, 30 Mar 2024 22:48:36 +0800 Subject: [PATCH] feat: add mobile view for dashboard (#2581) --- .../components/header/corner.component.ts | 4 + .../apps/portal/components/tabs.component.ts | 84 +++++++++++++++++++ .../src/app/apps/portal/portal.component.ts | 18 +++- .../routes/dashboard/controls.component.ts | 13 ++- .../routes/dashboard/dashboard.component.ts | 38 +++++++++ .../routes/dashboard/metrics.component.ts | 5 ++ .../routes/dashboard/service.component.ts | 51 +++++++++-- .../routes/dashboard/services.component.ts | 14 ++++ .../routes/dashboard/status.component.ts | 11 +++ .../portal/routes/dashboard/ui.component.ts | 5 ++ .../routes/dashboard/utilities.component.ts | 15 ++++ .../routes/system/logs/logs.component.ts | 9 ++ 12 files changed, 254 insertions(+), 13 deletions(-) create mode 100644 web/projects/ui/src/app/apps/portal/components/tabs.component.ts diff --git a/web/projects/ui/src/app/apps/portal/components/header/corner.component.ts b/web/projects/ui/src/app/apps/portal/components/header/corner.component.ts index 1a49954a2..dc28b2eba 100644 --- a/web/projects/ui/src/app/apps/portal/components/header/corner.component.ts +++ b/web/projects/ui/src/app/apps/portal/components/header/corner.component.ts @@ -59,6 +59,10 @@ import { NotificationService } from '../../services/notification.service' padding: 0 0.5rem 0 1.75rem; --clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 1.75rem 100%); } + + :host-context(tui-root._mobile) tui-badged-content { + display: none; + } `, ], changeDetection: ChangeDetectionStrategy.OnPush, diff --git a/web/projects/ui/src/app/apps/portal/components/tabs.component.ts b/web/projects/ui/src/app/apps/portal/components/tabs.component.ts new file mode 100644 index 000000000..3238a4c94 --- /dev/null +++ b/web/projects/ui/src/app/apps/portal/components/tabs.component.ts @@ -0,0 +1,84 @@ +import { AsyncPipe } from '@angular/common' +import { Component, inject } from '@angular/core' +import { RouterLink, RouterLinkActive } from '@angular/router' +import { TuiTabBarModule } from '@taiga-ui/addon-mobile' +import { combineLatest, map, startWith } from 'rxjs' +import { SYSTEM_UTILITIES } from 'src/app/apps/portal/constants/system-utilities' +import { BadgeService } from 'src/app/apps/portal/services/badge.service' +import { NotificationService } from 'src/app/apps/portal/services/notification.service' + +@Component({ + standalone: true, + selector: 'app-tabs', + template: ` + + `, + styles: ` + :host { + display: none; + // TODO: Theme + --tui-elevation-01: #333; + --tui-base-04: var(--tui-clear); + backdrop-filter: blur(1rem); + } + + [tuiTabBar]::before { + opacity: 0.7; + } + + :host-context(tui-root._mobile) { + display: block; + } + `, + imports: [AsyncPipe, RouterLink, RouterLinkActive, TuiTabBarModule], +}) +export class TabsComponent { + private readonly badge = inject(BadgeService) + + readonly utils$ = combineLatest( + Object.keys(SYSTEM_UTILITIES) + .filter(key => key !== '/portal/system/notifications') + .map(key => this.badge.getCount(key).pipe(startWith(0))), + ).pipe(map(values => values.reduce((acc, value) => acc + value, 0))) + readonly notification$ = inject(NotificationService).unreadCount$ +} diff --git a/web/projects/ui/src/app/apps/portal/portal.component.ts b/web/projects/ui/src/app/apps/portal/portal.component.ts index 6592e2320..aa79ed8b7 100644 --- a/web/projects/ui/src/app/apps/portal/portal.component.ts +++ b/web/projects/ui/src/app/apps/portal/portal.component.ts @@ -1,10 +1,16 @@ import { CommonModule } from '@angular/common' import { ChangeDetectionStrategy, Component, inject } from '@angular/core' import { takeUntilDestroyed } from '@angular/core/rxjs-interop' -import { NavigationEnd, Router, RouterOutlet } from '@angular/router' +import { + ActivatedRoute, + NavigationEnd, + Router, + RouterOutlet, +} from '@angular/router' import { tuiDropdownOptionsProvider } from '@taiga-ui/core' import { PatchDB } from 'patch-db-client' -import { filter } from 'rxjs' +import { filter, map } from 'rxjs' +import { TabsComponent } from 'src/app/apps/portal/components/tabs.component' import { DataModel } from 'src/app/services/patch-db/data-model' import { HeaderComponent } from './components/header/header.component' import { BreadcrumbsService } from './services/breadcrumbs.service' @@ -13,7 +19,8 @@ import { BreadcrumbsService } from './services/breadcrumbs.service' standalone: true, template: `
{{ name$ | async }}
-
+
+ `, styles: [ ` @@ -30,7 +37,7 @@ import { BreadcrumbsService } from './services/breadcrumbs.service' `, ], changeDetection: ChangeDetectionStrategy.OnPush, - imports: [CommonModule, RouterOutlet, HeaderComponent], + imports: [CommonModule, RouterOutlet, HeaderComponent, TabsComponent], providers: [ // TODO: Move to global tuiDropdownOptionsProvider({ @@ -51,4 +58,7 @@ export class PortalComponent { }) readonly name$ = inject(PatchDB).watch$('ui', 'name') + readonly tab$ = inject(ActivatedRoute).queryParams.pipe( + map(params => params['tab']), + ) } diff --git a/web/projects/ui/src/app/apps/portal/routes/dashboard/controls.component.ts b/web/projects/ui/src/app/apps/portal/routes/dashboard/controls.component.ts index 4ca933b89..bb7f81f19 100644 --- a/web/projects/ui/src/app/apps/portal/routes/dashboard/controls.component.ts +++ b/web/projects/ui/src/app/apps/portal/routes/dashboard/controls.component.ts @@ -65,7 +65,18 @@ import { Manifest } from '@start9labs/marketplace' changeDetection: ChangeDetectionStrategy.OnPush, imports: [TuiButtonModule, UILaunchComponent, TuiLetModule, AsyncPipe], providers: [tuiButtonOptionsProvider({ size: 's', appearance: 'none' })], - styles: ':host { padding: 0; border: none }', + styles: ` + :host { + padding: 0; + border: none; + } + + :host-context(tui-root._mobile) { + button { + display: none; + } + } + `, }) export class ControlsComponent { private readonly errors = inject(DepErrorService) diff --git a/web/projects/ui/src/app/apps/portal/routes/dashboard/dashboard.component.ts b/web/projects/ui/src/app/apps/portal/routes/dashboard/dashboard.component.ts index 531112839..73aed8a91 100644 --- a/web/projects/ui/src/app/apps/portal/routes/dashboard/dashboard.component.ts +++ b/web/projects/ui/src/app/apps/portal/routes/dashboard/dashboard.component.ts @@ -74,6 +74,44 @@ import { UtilitiesComponent } from './utilities.component' font-size: 1rem; } } + + :host-context(tui-root._mobile) { + height: 100%; + display: block; + margin: 0; + border-top: 0; + + app-metrics, + app-utilities, + app-services { + display: none; + } + + time, + h2 { + display: none; + } + } + + :host-context(tui-root._mobile [data-dashboard='metrics']) { + app-metrics { + display: block; + } + } + + :host-context(tui-root._mobile [data-dashboard='utilities']) { + app-utilities { + display: flex; + align-items: center; + } + } + + :host-context(tui-root._mobile main:not([data-dashboard])) { + app-services { + display: block; + margin: 0; + } + } `, imports: [ ServicesComponent, diff --git a/web/projects/ui/src/app/apps/portal/routes/dashboard/metrics.component.ts b/web/projects/ui/src/app/apps/portal/routes/dashboard/metrics.component.ts index 017a6322c..ce38e16b1 100644 --- a/web/projects/ui/src/app/apps/portal/routes/dashboard/metrics.component.ts +++ b/web/projects/ui/src/app/apps/portal/routes/dashboard/metrics.component.ts @@ -36,6 +36,11 @@ import { ChangeDetectionStrategy, Component } from '@angular/core' justify-content: center; } } + + :host-context(tui-root._mobile) { + --clip-path: none !important; + height: 100%; + } `, changeDetection: ChangeDetectionStrategy.OnPush, }) diff --git a/web/projects/ui/src/app/apps/portal/routes/dashboard/service.component.ts b/web/projects/ui/src/app/apps/portal/routes/dashboard/service.component.ts index e2bba6bc1..e6be029d8 100644 --- a/web/projects/ui/src/app/apps/portal/routes/dashboard/service.component.ts +++ b/web/projects/ui/src/app/apps/portal/routes/dashboard/service.component.ts @@ -18,18 +18,23 @@ import { getManifest } from 'src/app/util/get-package-data' standalone: true, selector: 'tr[appService]', template: ` - logo - + + logo + + {{ manifest.title }} - {{ manifest.version }} - - + {{ manifest.version }} + +
@@ -47,6 +52,32 @@ import { getManifest } from 'src/app/util/get-package-data' a { color: var(--tui-text-01); + font-weight: bold; + } + + .text { + display: contents; + } + + :host-context(tui-root._mobile) { + position: relative; + display: grid; + grid-template: 2rem 2rem 2rem/6rem 1fr 2rem; + align-items: center; + padding: 1rem; + + img { + height: 4rem; + width: 4rem; + margin: 1rem; + } + + td { + padding: 0; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } } `, changeDetection: ChangeDetectionStrategy.OnPush, @@ -61,6 +92,10 @@ export class ServiceComponent { readonly connected$ = inject(ConnectionService).connected$ + get installed(): boolean { + return this.pkg.stateInfo.state !== 'installed' + } + get manifest() { return getManifest(this.pkg) } diff --git a/web/projects/ui/src/app/apps/portal/routes/dashboard/services.component.ts b/web/projects/ui/src/app/apps/portal/routes/dashboard/services.component.ts index 2d976c199..03fe26da6 100644 --- a/web/projects/ui/src/app/apps/portal/routes/dashboard/services.component.ts +++ b/web/projects/ui/src/app/apps/portal/routes/dashboard/services.component.ts @@ -78,6 +78,20 @@ import { ToManifestPipe } from '../../pipes/to-manifest' text-align: center; padding: 1rem; } + + :host-context(tui-root._mobile) { + --clip-path: none !important; + height: 100%; + + table { + width: 100%; + margin: 0; + } + + thead { + display: none; + } + } `, changeDetection: ChangeDetectionStrategy.OnPush, imports: [ServiceComponent, AsyncPipe, ToManifestPipe], diff --git a/web/projects/ui/src/app/apps/portal/routes/dashboard/status.component.ts b/web/projects/ui/src/app/apps/portal/routes/dashboard/status.component.ts index 3343df80a..0c076aef0 100644 --- a/web/projects/ui/src/app/apps/portal/routes/dashboard/status.component.ts +++ b/web/projects/ui/src/app/apps/portal/routes/dashboard/status.component.ts @@ -37,6 +37,17 @@ import { InstallingProgressDisplayPipe } from '../service/pipes/install-progress gap: 0.5rem; height: 3rem; } + + :host-context(tui-root._mobile) { + height: auto; + + tui-loader, + tui-icon { + position: absolute; + top: 1rem; + left: 1rem; + } + } `, changeDetection: ChangeDetectionStrategy.OnPush, imports: [TuiIconModule, TuiLoaderModule], diff --git a/web/projects/ui/src/app/apps/portal/routes/dashboard/ui.component.ts b/web/projects/ui/src/app/apps/portal/routes/dashboard/ui.component.ts index 8cb56f1cc..0d85273fa 100644 --- a/web/projects/ui/src/app/apps/portal/routes/dashboard/ui.component.ts +++ b/web/projects/ui/src/app/apps/portal/routes/dashboard/ui.component.ts @@ -54,6 +54,11 @@ import { } `, + styles: ` + :host-context(tui-root._mobile) *:before { + font-size: 1.5rem !important; + } + `, changeDetection: ChangeDetectionStrategy.OnPush, imports: [TuiButtonModule, TuiHostedDropdownModule, TuiDataListModule], }) diff --git a/web/projects/ui/src/app/apps/portal/routes/dashboard/utilities.component.ts b/web/projects/ui/src/app/apps/portal/routes/dashboard/utilities.component.ts index d2f7b4539..00d4483a0 100644 --- a/web/projects/ui/src/app/apps/portal/routes/dashboard/utilities.component.ts +++ b/web/projects/ui/src/app/apps/portal/routes/dashboard/utilities.component.ts @@ -44,6 +44,7 @@ import { BadgeService } from 'src/app/apps/portal/services/badge.service' } .links { + width: 100%; display: grid; grid-template: 1fr 1fr / 1fr 1fr 1fr; gap: 0.75rem; @@ -77,6 +78,20 @@ import { BadgeService } from 'src/app/apps/portal/services/badge.service' background: var(--tui-clear); } } + + :host-context(tui-root._mobile) { + --clip-path: none !important; + height: 100%; + + .links { + grid-template: 1fr 1fr/1fr 1fr; + } + + .link { + font-size: 1rem; + gap: 0.75rem; + } + } `, changeDetection: ChangeDetectionStrategy.OnPush, imports: [TuiIconModule, RouterLink, TuiBadgeNotificationModule, AsyncPipe], diff --git a/web/projects/ui/src/app/apps/portal/routes/system/logs/logs.component.ts b/web/projects/ui/src/app/apps/portal/routes/system/logs/logs.component.ts index 0ea32aa6f..a7e75f560 100644 --- a/web/projects/ui/src/app/apps/portal/routes/system/logs/logs.component.ts +++ b/web/projects/ui/src/app/apps/portal/routes/system/logs/logs.component.ts @@ -53,6 +53,15 @@ import { LogsComponent } from '../../../components/logs/logs.component' logs { height: calc(100% - 4rem); } + + :host-context(tui-root._mobile) { + --clip-path: none; + height: 100%; + margin: 0; + padding: 1rem 1rem 0; + border: 0.375rem solid transparent; + border-top: 0; + } `, ], imports: [