feat: update Taiga UI to 4 release candidate

This commit is contained in:
waterplea
2024-07-15 11:16:19 +05:00
parent a2b1968d6e
commit c7a2e7ada1
219 changed files with 1977 additions and 2176 deletions

View File

@@ -1,18 +1,6 @@
<svg-definitions />
<!--TODO: Theme-->
<tui-root tuiTheme="night" tuiMode="onDark" [class.offline]="offline$ | async">
<tui-root tuiTheme="dark" [class.offline]="offline$ | async">
<router-outlet />
<toast-container />
<sidebar-host ngProjectAs="tuiOverContent" />
</tui-root>
<!--TODO: Theme-->
@if (auth.isVerified$ | async) {
@switch (theme$ | async) {
@case ('Dark') {
<tui-theme-night />
}
}
} @else {
<tui-theme-night />
}

Before

Width:  |  Height:  |  Size: 394 B

After

Width:  |  Height:  |  Size: 184 B

View File

@@ -2,15 +2,7 @@ import { HttpClientModule } from '@angular/common/http'
import { NgModule } from '@angular/core'
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'
import { ServiceWorkerModule } from '@angular/service-worker'
import { LoadingModule } from '@start9labs/shared'
import { TuiSheetDialogModule } from '@taiga-ui/addon-mobile'
import {
TuiAlertModule,
TuiDialogModule,
TuiModeModule,
TuiRootModule,
TuiThemeNightModule,
} from '@taiga-ui/core'
import { TuiRoot } from '@taiga-ui/core'
import { SidebarHostComponent } from 'src/app/components/sidebar-host.component'
import { SvgDefinitionsComponent } from 'src/app/components/svg-definitions.component'
import { ToastContainerComponent } from 'src/app/components/toast-container.component'
@@ -26,19 +18,13 @@ import { RoutingModule } from './routing.module'
BrowserAnimationsModule,
RoutingModule,
ToastContainerComponent,
TuiRootModule,
TuiDialogModule,
TuiSheetDialogModule,
TuiAlertModule,
TuiModeModule,
TuiThemeNightModule,
TuiRoot,
ServiceWorkerModule.register('ngsw-worker.js', {
enabled: environment.useServiceWorker,
// Register the ServiceWorker as soon as the application is stable
// or after 30 seconds (whichever comes first).
registrationStrategy: 'registerWhenStable:30000',
}),
LoadingModule,
SidebarHostComponent,
SvgDefinitionsComponent,
],

View File

@@ -7,17 +7,18 @@ import {
FilterPackagesPipe,
} from '@start9labs/marketplace'
import { RELATIVE_URL, THEME, WorkspaceConfig } from '@start9labs/shared'
import { TUI_DATE_FORMAT, TUI_DATE_SEPARATOR } from '@taiga-ui/cdk'
import {
TUI_DATE_FORMAT,
tuiButtonOptionsProvider,
tuiDropdownOptionsProvider,
tuiNumberFormatProvider,
tuiTextfieldOptionsProvider,
} from '@taiga-ui/core'
import { tuiButtonOptionsProvider } from '@taiga-ui/experimental'
import { NG_EVENT_PLUGINS } from '@taiga-ui/event-plugins'
import {
TUI_DATE_TIME_VALUE_TRANSFORMER,
TUI_DATE_VALUE_TRANSFORMER,
} from '@taiga-ui/kit'
import { tuiTextfieldOptionsProvider } from '@taiga-ui/legacy'
import { PATCH_DB_PROVIDERS } from 'src/app/services/patch-db/patch-db.providers'
import { ApiService } from './services/api/embassy-api.service'
import { LiveApiService } from './services/api/embassy-live-api.service'
@@ -37,6 +38,7 @@ const {
export const APP_PROVIDERS: Provider[] = [
PATCH_DB_PROVIDERS,
NG_EVENT_PLUGINS,
FilterPackagesPipe,
UntypedFormBuilder,
tuiNumberFormatProvider({ decimalSeparator: '.', thousandSeparator: '' }),
@@ -45,11 +47,10 @@ export const APP_PROVIDERS: Provider[] = [
tuiDropdownOptionsProvider({ appearance: 'start-os' }),
{
provide: TUI_DATE_FORMAT,
useValue: 'MDY',
},
{
provide: TUI_DATE_SEPARATOR,
useValue: '/',
useValue: {
mode: 'MDY',
separator: '/',
},
},
{
provide: TUI_DATE_VALUE_TRANSFORMER,

View File

@@ -1,9 +1,9 @@
import { AsyncPipe } from '@angular/common'
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
import { RouterLink } from '@angular/router'
import { TuiAlertModule } from '@taiga-ui/core'
import { TuiAlert } from '@taiga-ui/core'
import { PatchDB } from 'patch-db-client'
import { Observable, Subject, merge, pairwise, map, endWith } from 'rxjs'
import { endWith, map, merge, Observable, pairwise, Subject } from 'rxjs'
import { DataModel } from 'src/app/services/patch-db/data-model'
@Component({
@@ -20,7 +20,7 @@ import { DataModel } from 'src/app/services/patch-db/data-model'
</ng-template>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [TuiAlertModule, RouterLink, AsyncPipe],
imports: [TuiAlert, RouterLink, AsyncPipe],
})
export class NotificationsToastComponent {
private readonly dismiss$ = new Subject<boolean>()

View File

@@ -2,9 +2,8 @@ import { AsyncPipe } from '@angular/common'
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
import { SwUpdate } from '@angular/service-worker'
import { Emver, LoadingService } from '@start9labs/shared'
import { TuiAutoFocusModule } from '@taiga-ui/cdk'
import { TuiDialogModule } from '@taiga-ui/core'
import { TuiButtonModule } from '@taiga-ui/experimental'
import { TuiAutoFocus } from '@taiga-ui/cdk'
import { TuiButton, TuiDialog } from '@taiga-ui/core'
import { PatchDB } from 'patch-db-client'
import { debounceTime, endWith, map, merge, Subject } from 'rxjs'
import { ConfigService } from 'src/app/services/config.service'
@@ -43,7 +42,7 @@ import { DataModel } from 'src/app/services/patch-db/data-model'
<!-- </ng-template>-->
`,
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [TuiDialogModule, AsyncPipe, TuiButtonModule, TuiAutoFocusModule],
imports: [TuiDialog, AsyncPipe, TuiButton, TuiAutoFocus],
})
export class RefreshAlertComponent {
private readonly updates = inject(SwUpdate)

View File

@@ -1,10 +1,10 @@
import { CommonModule } from '@angular/common'
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
import { TuiDialogContext, TuiSvgModule } from '@taiga-ui/core'
import { TuiDialogContext, TuiIcon } from '@taiga-ui/core'
import {
POLYMORPHEUS_CONTEXT,
PolymorpheusComponent,
} from '@tinkoff/ng-polymorpheus'
} from '@taiga-ui/polymorpheus'
import { BackupReport } from 'src/app/services/api/api.types'
@Component({
@@ -15,7 +15,7 @@ import { BackupReport } from 'src/app/services/api/api.types'
<strong>System data</strong>
<div [style.color]="system.color">{{ system.result }}</div>
</div>
<tui-svg [src]="system.icon" [style.color]="system.color"></tui-svg>
<tui-icon [icon]="system.icon" [style.color]="system.color" />
</div>
<div *ngFor="let pkg of report?.packages | keyvalue" class="g-action">
<div [style.flex]="1">
@@ -24,15 +24,15 @@ import { BackupReport } from 'src/app/services/api/api.types'
{{ pkg.value.error ? 'Failed: ' + pkg.value.error : 'Succeeded' }}
</div>
</div>
<tui-svg
[src]="getIcon(pkg.value.error)"
<tui-icon
[icon]="getIcon(pkg.value.error)"
[style.color]="getColor(pkg.value.error)"
></tui-svg>
/>
</div>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [CommonModule, TuiSvgModule],
imports: [CommonModule, TuiIcon],
})
export class BackupsReportModal {
private readonly context =
@@ -51,34 +51,34 @@ export class BackupsReportModal {
}
getColor(error: unknown) {
return error ? 'var(--tui-negative)' : 'var(--tui-positive)'
return error ? 'var(--tui-text-negative)' : 'var(--tui-text-positive)'
}
getIcon(error: unknown) {
return error ? 'tuiIconMinusCircleLarge' : 'tuiIconCheckLarge'
return error ? '@tui.circle-minus' : '@tui.check'
}
private getSystem() {
if (!this.report.server.attempted) {
return {
result: 'Not Attempted',
icon: 'tuiIconMinusLarge',
color: 'var(--tui-text-02)',
icon: '@tui.minus',
color: 'var(--tui-text-secondary)',
}
}
if (this.report.server.error) {
return {
result: `Failed: ${this.report.server.error}`,
icon: 'tuiIconMinusCircleLarge',
color: 'var(--tui-negative)',
icon: '@tui.circle-minus',
color: 'var(--tui-text-negative)',
}
}
return {
result: 'Succeeded',
icon: 'tuiIconCheckLarge',
color: 'var(--tui-positive)',
icon: '@tui.check',
color: 'var(--tui-text-positive)',
}
}
}

View File

@@ -1,24 +1,19 @@
import { TuiDropdownService } from '@taiga-ui/core'
import {
ChangeDetectionStrategy,
Component,
Directive,
Injectable,
} from '@angular/core'
import {
AbstractTuiPortalHostComponent,
AbstractTuiPortalService,
TuiDropdownPortalService,
} from '@taiga-ui/cdk'
import { TuiPortals, TuiPortalService } from '@taiga-ui/cdk'
@Injectable({ providedIn: `root` })
export class SidebarService extends AbstractTuiPortalService {}
export class SidebarService extends TuiPortalService {}
@Directive({
selector: '[tuiSidebar]',
standalone: true,
providers: [
{ provide: TuiDropdownPortalService, useExisting: SidebarService },
],
providers: [{ provide: TuiDropdownService, useExisting: SidebarService }],
})
export class SidebarDirective {}
@@ -28,8 +23,6 @@ export class SidebarDirective {}
styles: [':host { position: fixed; top: 0; }'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
providers: [
{ provide: AbstractTuiPortalService, useExisting: SidebarService },
],
providers: [{ provide: TuiPortalService, useExisting: SidebarService }],
})
export class SidebarHostComponent extends AbstractTuiPortalHostComponent {}
export class SidebarHostComponent extends TuiPortals {}

View File

@@ -1,8 +1,7 @@
import { AsyncPipe } from '@angular/common'
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
import { ErrorService, LoadingService } from '@start9labs/shared'
import { TuiAlertModule } from '@taiga-ui/core'
import { TuiButtonModule } from '@taiga-ui/experimental'
import { TuiAlert, TuiButton } from '@taiga-ui/core'
import { PatchDB } from 'patch-db-client'
import {
distinctUntilChanged,
@@ -24,7 +23,7 @@ import { DataModel } from 'src/app/services/patch-db/data-model'
[tuiAlertOptions]="{
label: 'StartOS download complete!',
status: 'success',
autoClose: false
autoClose: 0
}"
(tuiAlertChange)="onDismiss()"
>
@@ -44,7 +43,7 @@ import { DataModel } from 'src/app/services/patch-db/data-model'
</ng-template>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [TuiButtonModule, TuiAlertModule, AsyncPipe],
imports: [TuiButton, TuiAlert, AsyncPipe],
})
export class UpdateToastComponent {
private readonly api = inject(ApiService)

View File

@@ -1,7 +1,6 @@
import { Component, inject, Inject } from '@angular/core'
import { TuiDialogContext } from '@taiga-ui/core'
import { TuiButtonModule } from '@taiga-ui/experimental'
import { POLYMORPHEUS_CONTEXT } from '@tinkoff/ng-polymorpheus'
import { TuiDialogContext, TuiButton } from '@taiga-ui/core'
import { POLYMORPHEUS_CONTEXT } from '@taiga-ui/polymorpheus'
@Component({
standalone: true,
@@ -42,7 +41,7 @@ import { POLYMORPHEUS_CONTEXT } from '@tinkoff/ng-polymorpheus'
</p>
`,
styles: 'li { margin-bottom: 0.5rem }',
imports: [TuiButtonModule],
imports: [TuiButton],
})
export class WelcomeComponent {
readonly context = inject<TuiDialogContext>(POLYMORPHEUS_CONTEXT)

View File

@@ -1,7 +1,7 @@
import { TuiButton } from '@taiga-ui/core'
import { NgModule } from '@angular/core'
import { CommonModule } from '@angular/common'
import { RouterModule, Routes } from '@angular/router'
import { TuiButtonModule } from '@taiga-ui/experimental'
import { HomePage } from './home.page'
const ROUTES: Routes = [
@@ -12,7 +12,7 @@ const ROUTES: Routes = [
]
@NgModule({
imports: [CommonModule, TuiButtonModule, RouterModule.forChild(ROUTES)],
imports: [CommonModule, TuiButton, RouterModule.forChild(ROUTES)],
declarations: [HomePage],
})
export class HomePageModule {}

View File

@@ -2,7 +2,7 @@
display: block;
padding: 2rem;
overflow: auto;
background: var(--tui-base-01);
background: var(--tui-background-base);
}
.title {
@@ -20,14 +20,14 @@
.code {
display: block;
color: var(--tui-success-fill);
color: var(--tui-status-positive);
background: rgb(69, 69, 69);
padding: 1px 1rem;
margin-bottom: 2rem;
}
.warning {
color: var(--tui-warning-fill);
color: var(--tui-status-warning);
}
.buttons {

View File

@@ -1,8 +1,8 @@
import { TUI_CONFIRM } from '@taiga-ui/kit'
import { Component, Inject } from '@angular/core'
import { WINDOW } from '@ng-web-apis/common'
import { LoadingService } from '@start9labs/shared'
import { TuiDialogService } from '@taiga-ui/core'
import { TUI_PROMPT } from '@taiga-ui/kit'
import { filter } from 'rxjs'
import { DiagnosticService } from '../services/diagnostic.service'
@@ -118,7 +118,7 @@ export class HomePage {
async presentAlertSystemRebuild() {
this.dialogs
.open(TUI_PROMPT, {
.open(TUI_CONFIRM, {
label: 'Warning',
size: 's',
data: {
@@ -140,7 +140,7 @@ export class HomePage {
async presentAlertRepairDisk() {
this.dialogs
.open(TUI_PROMPT, {
.open(TUI_CONFIRM, {
label: 'Warning',
size: 's',
data: {

View File

@@ -1,10 +1,10 @@
import { NgModule } from '@angular/core'
import { CommonModule } from '@angular/common'
import { Routes, RouterModule } from '@angular/router'
import { IntersectionObserverModule } from '@ng-web-apis/intersection-observer'
import { MutationObserverModule } from '@ng-web-apis/mutation-observer'
import { TuiLoaderModule, TuiScrollbarModule } from '@taiga-ui/core'
import { TuiBadgeModule, TuiButtonModule } from '@taiga-ui/experimental'
import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'
import { WaIntersectionObserver } from '@ng-web-apis/intersection-observer'
import { WaMutationObserver } from '@ng-web-apis/mutation-observer'
import { TuiButton, TuiLoader, TuiScrollbar } from '@taiga-ui/core'
import { TuiBadge } from '@taiga-ui/kit'
import { NgDompurifyModule } from '@tinkoff/ng-dompurify'
import { LogsPage } from './logs.page'
@@ -19,13 +19,13 @@ const ROUTES: Routes = [
imports: [
CommonModule,
RouterModule.forChild(ROUTES),
IntersectionObserverModule,
MutationObserverModule,
...WaIntersectionObserver,
WaMutationObserver,
NgDompurifyModule,
TuiBadgeModule,
TuiButtonModule,
TuiLoaderModule,
TuiScrollbarModule,
TuiBadge,
TuiButton,
TuiLoader,
TuiScrollbar,
],
declarations: [LogsPage],
})

View File

@@ -1,7 +1,7 @@
<a
routerLink="../"
tuiButton
iconLeft="tuiIconChevronLeft"
iconStart="@tui.chevron-left"
appearance="icon"
[style.align-self]="'flex-start'"
>

View File

@@ -1,7 +1,7 @@
import { Component, ElementRef, inject, OnInit, ViewChild } from '@angular/core'
import { INTERSECTION_ROOT } from '@ng-web-apis/intersection-observer'
import { convertAnsi, ErrorService } from '@start9labs/shared'
import { TuiScrollbarComponent } from '@taiga-ui/core'
import { TuiScrollbar } from '@taiga-ui/core'
import { DiagnosticService } from 'src/app/routes/diagnostic/services/diagnostic.service'
@Component({
@@ -15,7 +15,7 @@ import { DiagnosticService } from 'src/app/routes/diagnostic/services/diagnostic
justify-content: flex-start;
padding: 1rem;
gap: 1rem;
background: var(--tui-base-01);
background: var(--tui-background-base);
}
`,
providers: [
@@ -26,7 +26,7 @@ import { DiagnosticService } from 'src/app/routes/diagnostic/services/diagnostic
],
})
export class LogsPage implements OnInit {
@ViewChild(TuiScrollbarComponent, { read: ElementRef })
@ViewChild(TuiScrollbar, { read: ElementRef })
private readonly scrollbar?: ElementRef<HTMLElement>
private readonly api = inject(DiagnosticService)
private readonly errorService = inject(ErrorService)

View File

@@ -4,7 +4,7 @@
tuiSurface="elevated"
class="card"
>
<tui-icon icon="tuiIconLock" [style.font-size.rem]="4" />
<tui-icon icon="@tui.lock" [style.font-size.rem]="4" />
<h1>Trust Your Root CA</h1>
<p>
Download and trust your server's Root Certificate Authority to establish a
@@ -29,7 +29,7 @@
tuiButton
size="s"
appearance="tertiary-solid"
iconRight="tuiIconDownload"
iconEnd="@tui.download"
href="/eos/local.crt"
>
Download
@@ -47,7 +47,7 @@
href="https://docs.start9.com/0.3.5.x/user-manual/trust-ca"
target="_blank"
rel="noreferrer"
iconRight="tuiIconExternalLink"
iconEnd="@tui.external-link"
>
View Instructions
</a>
@@ -62,7 +62,7 @@
size="s"
class="refresh"
appearance="success-solid"
iconRight="tuiIconRefreshCw"
iconEnd="@tui.refresh-cw"
(click)="refresh()"
>
Refresh
@@ -73,7 +73,7 @@
tuiButton
size="s"
appearance="flat"
iconRight="tuiIconExternalLink"
iconEnd="@tui.external-link"
(click)="launchHttps()"
[disabled]="caTrusted"
>
@@ -85,7 +85,7 @@
<ng-template #trusted>
<div tuiCardLarge tuiSurface="elevated" class="card">
<tui-icon
icon="tuiIconShield"
icon="@tui.shield"
tuiAppearance="icon-success"
[style.font-size.rem]="4"
/>
@@ -97,7 +97,7 @@
<button
tuiButton
appearance="tertiary-solid"
iconRight="tuiIconExternalLink"
iconEnd="@tui.external-link"
(click)="launchHttps()"
>
Go to login

View File

@@ -1,13 +1,8 @@
import { CommonModule, DOCUMENT } from '@angular/common'
import { Component, inject } from '@angular/core'
import { RELATIVE_URL } from '@start9labs/shared'
import {
TuiAppearanceModule,
TuiButtonModule,
TuiCardModule,
TuiIconModule,
TuiSurfaceModule,
} from '@taiga-ui/experimental'
import { TuiAppearance, TuiButton, TuiIcon, TuiSurface } from '@taiga-ui/core'
import { TuiCardLarge } from '@taiga-ui/layout'
import { ApiService } from 'src/app/services/api/embassy-api.service'
import { ConfigService } from 'src/app/services/config.service'
@@ -18,11 +13,11 @@ import { ConfigService } from 'src/app/services/config.service'
styleUrls: ['./ca-wizard.component.scss'],
imports: [
CommonModule,
TuiIconModule,
TuiButtonModule,
TuiAppearanceModule,
TuiCardModule,
TuiSurfaceModule,
TuiIcon,
TuiButton,
TuiAppearance,
TuiCardLarge,
TuiSurface,
],
})
export class CAWizardComponent {

View File

@@ -2,13 +2,12 @@ import { CommonModule } from '@angular/common'
import { NgModule } from '@angular/core'
import { FormsModule } from '@angular/forms'
import { RouterModule, Routes } from '@angular/router'
import { TuiErrorModule, TuiTextfieldControllerModule } from '@taiga-ui/core'
import { TuiButton, TuiError } from '@taiga-ui/core'
import { TuiCardLarge } from '@taiga-ui/layout'
import {
TuiButtonModule,
TuiCardModule,
TuiSurfaceModule,
} from '@taiga-ui/experimental'
import { TuiInputPasswordModule } from '@taiga-ui/kit'
TuiInputPasswordModule,
TuiTextfieldControllerModule,
} from '@taiga-ui/legacy'
import { CAWizardComponent } from './ca-wizard/ca-wizard.component'
import { LoginPage } from './login.page'
@@ -24,12 +23,11 @@ const routes: Routes = [
CommonModule,
FormsModule,
CAWizardComponent,
TuiButtonModule,
TuiCardModule,
TuiSurfaceModule,
TuiButton,
TuiCardLarge,
TuiInputPasswordModule,
TuiTextfieldControllerModule,
TuiErrorModule,
TuiError,
RouterModule.forChild(routes),
],
declarations: [LoginPage],

View File

@@ -3,12 +3,12 @@
<!-- not Local HTTP -->
<ng-template #notLanHttp>
<div tuiCardLarge tuiSurface="elevated" class="card">
<div tuiCardLarge class="card">
<img alt="StartOS Icon" class="logo" src="assets/img/icon.png" />
<h1 class="header">Login to StartOS</h1>
<form (submit)="submit()">
<tui-input-password
tuiTextfieldIconLeft="tuiIconKeyLarge"
tuiTextfieldIconLeft="@tui.key"
[ngModelOptions]="{ standalone: true }"
[(ngModel)]="password"
(ngModelChange)="error = ''"

View File

@@ -1,15 +1,13 @@
@import '@taiga-ui/core/styles/taiga-ui-local';
:host {
background: var(--tui-base-02);
}
.card {
@include center-all();
overflow: visible;
align-items: center;
text-align: center;
width: max(33%, 20rem);
background: var(--tui-background-base-alt);
box-shadow: var(--tui-shadow-small);
}
.logo {

View File

@@ -1,10 +1,10 @@
import { Component, Inject } from '@angular/core'
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'
import { Component, Inject, DestroyRef, inject } from '@angular/core'
import { ApiService } from 'src/app/services/api/embassy-api.service'
import { AuthService } from 'src/app/services/auth.service'
import { Router } from '@angular/router'
import { ConfigService } from 'src/app/services/config.service'
import { LoadingService } from '@start9labs/shared'
import { TuiDestroyService } from '@taiga-ui/cdk'
import { takeUntil } from 'rxjs'
import { DOCUMENT } from '@angular/common'
@@ -12,14 +12,13 @@ import { DOCUMENT } from '@angular/common'
selector: 'login',
templateUrl: './login.page.html',
styleUrls: ['./login.page.scss'],
providers: [TuiDestroyService],
providers: [],
})
export class LoginPage {
password = ''
error = ''
constructor(
private readonly destroy$: TuiDestroyService,
private readonly router: Router,
private readonly authService: AuthService,
private readonly loader: LoadingService,
@@ -33,7 +32,7 @@ export class LoginPage {
const loader = this.loader
.open('Logging in...')
.pipe(takeUntil(this.destroy$))
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe()
try {
@@ -58,4 +57,6 @@ export class LoginPage {
loader.unsubscribe()
}
}
readonly destroyRef = inject(DestroyRef)
}

View File

@@ -1,7 +1,6 @@
import { TuiDataList, TuiIcon } from '@taiga-ui/core'
import { CommonModule } from '@angular/common'
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
import { TuiDataListModule } from '@taiga-ui/core'
import { TuiIconModule } from '@taiga-ui/experimental'
export interface Action {
icon: string
@@ -52,7 +51,7 @@ export interface Action {
],
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [TuiDataListModule, CommonModule, TuiIconModule],
imports: [TuiDataList, CommonModule, TuiIcon],
})
export class ActionsComponent {
@Input()

View File

@@ -1,3 +1,4 @@
import { TuiConfirmService } from '@taiga-ui/kit'
import { CommonModule } from '@angular/common'
import {
ChangeDetectionStrategy,
@@ -12,12 +13,10 @@ import { CT } from '@start9labs/start-sdk'
import {
tuiMarkControlAsTouchedAndValidate,
TuiValueChangesModule,
TuiValueChanges,
} from '@taiga-ui/cdk'
import { TuiDialogContext, TuiModeModule } from '@taiga-ui/core'
import { TuiButtonModule } from '@taiga-ui/experimental'
import { TuiDialogFormService } from '@taiga-ui/kit'
import { POLYMORPHEUS_CONTEXT } from '@tinkoff/ng-polymorpheus'
import { TuiDialogContext, TuiButton } from '@taiga-ui/core'
import { POLYMORPHEUS_CONTEXT } from '@taiga-ui/polymorpheus'
import { compare, Operation } from 'fast-json-patch'
import { FormModule } from 'src/app/routes/portal/components/form/form.module'
import { InvalidService } from 'src/app/routes/portal/components/form/invalid.service'
@@ -47,7 +46,7 @@ export interface FormContext<T> {
(tuiValueChanges)="markAsDirty()"
>
<form-group [spec]="spec" />
<footer tuiMode="onDark">
<footer>
<ng-content />
<ng-container *ngFor="let button of buttons; let last = last">
<button
@@ -84,8 +83,8 @@ export interface FormContext<T> {
padding: 1rem 0;
margin: 1rem 0 -1rem;
gap: 1rem;
background: var(--tui-elevation-01);
border-top: 1px solid var(--tui-base-02);
background: var(--tui-background-elevation-1);
border-top: 1px solid var(--tui-background-base-alt);
}
`,
],
@@ -93,16 +92,15 @@ export interface FormContext<T> {
CommonModule,
ReactiveFormsModule,
RouterModule,
TuiValueChangesModule,
TuiButtonModule,
TuiModeModule,
TuiValueChanges,
TuiButton,
FormModule,
],
providers: [InvalidService],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FormComponent<T extends Record<string, any>> implements OnInit {
private readonly dialogFormService = inject(TuiDialogFormService)
private readonly dialogFormService = inject(TuiConfirmService)
private readonly formService = inject(FormService)
private readonly invalidService = inject(InvalidService)
private readonly context = inject<TuiDialogContext<void, FormContext<T>>>(

View File

@@ -1,9 +1,9 @@
<div class="label">
{{ spec.name }}
<tui-tooltip
<tui-icon
*ngIf="spec.description || spec.disabled"
[content]="spec | hint"
></tui-tooltip>
[tuiTooltip]="spec | hint"
/>
<button
tuiLink
type="button"
@@ -48,7 +48,7 @@
tuiIconButton
type="button"
class="remove"
iconLeft="tuiIconTrash"
iconStart="@tui.trash"
appearance="icon"
size="m"
title="Remove"

View File

@@ -35,7 +35,7 @@
height: 1px;
left: 3rem;
right: 1rem;
background: var(--tui-clear);
background: var(--tui-background-neutral-1);
}
}

View File

@@ -1,15 +1,23 @@
import { Component, HostBinding, inject, Input } from '@angular/core'
import { AbstractControl, FormArrayName } from '@angular/forms'
import { TUI_PARENT_STOP, TuiDestroyService } from '@taiga-ui/cdk'
import {
TUI_ANIMATION_OPTIONS,
Component,
DestroyRef,
HostBinding,
inject,
Input,
} from '@angular/core'
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'
import { AbstractControl, FormArrayName } from '@angular/forms'
import { CT } from '@start9labs/start-sdk'
import {
TUI_ANIMATIONS_SPEED,
TuiDialogService,
tuiFadeIn,
tuiHeightCollapse,
tuiParentStop,
tuiToAnimationOptions,
} from '@taiga-ui/core'
import { TUI_PROMPT } from '@taiga-ui/kit'
import { CT } from '@start9labs/start-sdk'
import { filter, takeUntil } from 'rxjs'
import { TUI_CONFIRM } from '@taiga-ui/kit'
import { filter } from 'rxjs'
import { FormService } from 'src/app/services/form.service'
import { ERRORS } from '../form-group/form-group.component'
@@ -17,15 +25,15 @@ import { ERRORS } from '../form-group/form-group.component'
selector: 'form-array',
templateUrl: './form-array.component.html',
styleUrls: ['./form-array.component.scss'],
animations: [tuiFadeIn, tuiHeightCollapse, TUI_PARENT_STOP],
providers: [TuiDestroyService],
animations: [tuiFadeIn, tuiHeightCollapse, tuiParentStop],
providers: [],
})
export class FormArrayComponent {
@Input({ required: true })
spec!: CT.ValueSpecList
@HostBinding('@tuiParentStop')
readonly animation = { value: '', ...inject(TUI_ANIMATION_OPTIONS) }
readonly animation = tuiToAnimationOptions(inject(TUI_ANIMATIONS_SPEED))
readonly order = ERRORS
readonly array = inject(FormArrayName)
readonly open = new Map<AbstractControl, boolean>()
@@ -33,7 +41,6 @@ export class FormArrayComponent {
private warned = false
private readonly formService = inject(FormService)
private readonly dialogs = inject(TuiDialogService)
private readonly destroy$ = inject(TuiDestroyService)
get canAdd(): boolean {
return (
@@ -46,12 +53,12 @@ export class FormArrayComponent {
add() {
if (!this.warned && this.spec.warning) {
this.dialogs
.open<boolean>(TUI_PROMPT, {
.open<boolean>(TUI_CONFIRM, {
label: 'Warning',
size: 's',
data: { content: this.spec.warning, yes: 'Ok', no: 'Cancel' },
})
.pipe(filter(Boolean), takeUntil(this.destroy$))
.pipe(filter(Boolean), takeUntilDestroyed(this.destroyRef))
.subscribe(() => {
this.addItem()
})
@@ -64,7 +71,7 @@ export class FormArrayComponent {
removeAt(index: number) {
this.dialogs
.open<boolean>(TUI_PROMPT, {
.open<boolean>(TUI_CONFIRM, {
label: 'Confirm',
size: 's',
data: {
@@ -73,7 +80,7 @@ export class FormArrayComponent {
no: 'Cancel',
},
})
.pipe(filter(Boolean), takeUntil(this.destroy$))
.pipe(filter(Boolean), takeUntilDestroyed(this.destroyRef))
.subscribe(() => {
this.removeItem(index)
})
@@ -88,4 +95,6 @@ export class FormArrayComponent {
this.array.control.insert(0, this.formService.getListItem(this.spec))
this.open.set(this.array.control.at(0), true)
}
readonly destroyRef = inject(DestroyRef)
}

View File

@@ -22,11 +22,6 @@
[(ngModel)]="value"
(click.stop)="(0)"
/>
<tui-svg
src="tuiIconPaintLarge"
tuiWrapper
appearance="icon"
class="icon"
></tui-svg>
<tui-icon icon="@tui.paint" tuiAppearance="icon" class="icon" />
</div>
</ng-template>

View File

@@ -6,14 +6,11 @@ import {
TemplateRef,
ViewChild,
} from '@angular/core'
import { AbstractTuiNullableControl } from '@taiga-ui/cdk'
import {
TuiAlertService,
TuiDialogContext,
TuiNotification,
} from '@taiga-ui/core'
import { filter, takeUntil } from 'rxjs'
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'
import { CT } from '@start9labs/start-sdk'
import { TuiAlertService, TuiDialogContext } from '@taiga-ui/core'
import { AbstractTuiNullableControl } from '@taiga-ui/legacy'
import { filter } from 'rxjs'
import { ERRORS } from '../form-group/form-group.component'
import { FORM_CONTROL_PROVIDERS } from './form-control.providers'
@@ -55,11 +52,11 @@ export class FormControlComponent<
this.alerts
.open<boolean>(this.warning, {
label: 'Warning',
status: TuiNotification.Warning,
hasCloseButton: false,
autoClose: false,
status: 'warning',
closeable: false,
autoClose: 0,
})
.pipe(filter(Boolean), takeUntil(this.destroy$))
.pipe(filter(Boolean), takeUntilDestroyed(this.destroyRef))
.subscribe(() => {
this.value = previous
})

View File

@@ -1,31 +1,33 @@
<tui-input-files
[pseudoInvalid]="invalid"
[(ngModel)]="value"
(focusedChange)="onFocus($event)"
>
<input tuiInputFiles [accept]="spec.extensions.join(',')" />
<label tuiInputFiles [(ngModel)]="value">
<input
tuiInputFiles
[invalid]="invalid"
[accept]="spec.extensions.join(',')"
(blur)="onFocus(false)"
/>
<ng-template let-drop>
<div class="template" [class.template_hidden]="drop">
<div class="label">
{{ spec.name }}
<span *ngIf="spec.required">*</span>
<tui-tooltip
*ngIf="spec.description"
[content]="spec.description"
></tui-tooltip>
@if (spec.required) {
<span>*</span>
}
@if (spec.description) {
<tui-icon [tuiTooltip]="spec.description" />
}
</div>
<tui-tag
*ngIf="value; else label"
class="file"
size="l"
[value]="value.name"
[removable]="true"
(edited)="value = null"
></tui-tag>
<ng-template #label>
@if (value) {
<tui-tag
class="file"
size="l"
[value]="value.name"
[removable]="true"
(edited)="value = null"
/>
} @else {
<small>Click or drop file here</small>
</ng-template>
}
</div>
<div class="drop" [class.drop_hidden]="!drop">Drop file here</div>
</ng-template>
</tui-input-files>
</label>

View File

@@ -36,7 +36,7 @@
small {
max-width: 50%;
font-weight: normal;
color: var(--tui-text-02);
color: var(--tui-text-secondary);
margin-left: auto;
}

View File

@@ -1,6 +1,5 @@
<ng-container
*ngFor="let entry of spec | keyvalue: asIsOrder"
tuiMode="onDark"
[ngSwitch]="entry.value.type"
[tuiTextfieldCleaner]="true"
>

View File

@@ -10,7 +10,7 @@ form-group .g-form-group {
&::after {
content: '';
position: absolute;
background: var(--tui-clear);
background: var(--tui-background-neutral-1);
}
&::before {

View File

@@ -1,11 +1,8 @@
import { Provider, SkipSelf } from '@angular/core'
import {
TUI_ARROW_MODE,
tuiInputDateOptionsProvider,
tuiInputTimeOptionsProvider,
} from '@taiga-ui/kit'
import { TUI_DEFAULT_ERROR_MESSAGE } from '@taiga-ui/core'
import { ControlContainer } from '@angular/forms'
import { TUI_DEFAULT_ERROR_MESSAGE } from '@taiga-ui/core'
import { tuiInputDateOptionsProvider } from '@taiga-ui/kit'
import { TUI_ARROW_MODE, tuiInputTimeOptionsProvider } from '@taiga-ui/legacy'
import { identity, of } from 'rxjs'
export const FORM_GROUP_PROVIDERS: Provider[] = [

View File

@@ -4,8 +4,10 @@
[readOnly]="readOnly"
[tuiTextfieldPostfix]="spec.units || ''"
[pseudoInvalid]="invalid"
[precision]="Infinity"
[decimal]="spec.integer ? 'never' : 'not-zero'"
[tuiNumberFormat]="{
precision: spec.integer ? 0 : Infinity,
decimalMode: 'not-zero'
}"
[min]="spec.min ?? -Infinity"
[max]="spec.max ?? Infinity"
[step]="spec.step || 0"
@@ -14,5 +16,5 @@
>
{{ spec.name }}
<span *ngIf="spec.required">*</span>
<input tuiTextfield [placeholder]="spec.placeholder || ''" />
<input tuiTextfieldLegacy [placeholder]="spec.placeholder || ''" />
</tui-input-number>

View File

@@ -2,24 +2,22 @@
<button
tuiIconButton
size="s"
iconLeft="tuiIconChevronDown"
iconStart="@tui.chevron-down"
type="button"
class="button"
[class.button_open]="open"
[style.border-radius.%]="100"
[appearance]="invalid ? 'danger-solid' : 'secondary'"
></button>
<ng-content></ng-content>
<ng-content />
{{ spec.name }}
<tui-tooltip
*ngIf="spec.description"
[content]="spec.description"
(click.stop)="(0)"
></tui-tooltip>
@if (spec.description) {
<tui-icon [tuiTooltip]="spec.description" (click.stop)="(0)" />
}
</h3>
<tui-expand class="expand" [expanded]="open">
<div class="g-form-group" [class.g-form-group_invalid]="invalid">
<form-group [spec]="spec.spec"></form-group>
<form-group [spec]="spec.spec" />
</div>
</tui-expand>

View File

@@ -36,6 +36,6 @@
&_invalid::before,
&_invalid::after {
background: var(--tui-error-bg);
background: var(--tui-status-negative-pale);
}
}

View File

@@ -10,7 +10,7 @@
{{ spec.name }}
<span *ngIf="spec.required">*</span>
<input
tuiTextfield
tuiTextfieldLegacy
[class.masked]="spec.masked && masked"
[placeholder]="spec.placeholder || ''"
[attr.minLength]="spec.minLength"
@@ -27,7 +27,7 @@
title="Generate"
size="xs"
class="button"
iconLeft="tuiIconRefreshCcw"
iconStart="@tui.refresh-ccw"
(click)="generate()"
></button>
<button
@@ -38,7 +38,7 @@
title="Toggle masking"
size="xs"
class="button"
[iconLeft]="masked ? 'tuiIconEye' : 'tuiIconEyeOff'"
[iconStart]="masked ? '@tui.eye' : '@tui.eye-off'"
(click)="masked = !masked"
></button>
</ng-template>

View File

@@ -1,4 +1,4 @@
<tui-text-area
<tui-textarea
[tuiHintContent]="spec | hint"
[disabled]="!!spec.disabled"
[readOnly]="readOnly"
@@ -11,5 +11,8 @@
>
{{ spec.name }}
<span *ngIf="spec.required">*</span>
<textarea tuiTextfield [placeholder]="spec.placeholder || ''"></textarea>
</tui-text-area>
<textarea
tuiTextfieldLegacy
[placeholder]="spec.placeholder || ''"
></textarea>
</tui-textarea>

View File

@@ -1,11 +1,12 @@
{{ spec.name }}
<tui-tooltip
*ngIf="spec.description || spec.disabled"
[tuiHintContent]="spec | hint"
></tui-tooltip>
<tui-toggle
size="l"
@if (spec.description || spec.disabled) {
<tui-icon [tuiTooltip]="spec | hint" />
}
<input
tuiSwitch
type="checkbox"
size="m"
[disabled]="!!spec.disabled || readOnly"
[(ngModel)]="value"
(focusedChange)="onFocus($event)"
></tui-toggle>
(blur)="onFocus(false)"
/>

View File

@@ -1,54 +1,55 @@
import { NgModule } from '@angular/core'
import { CommonModule } from '@angular/common'
import { NgModule } from '@angular/core'
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { MaskitoModule } from '@maskito/angular'
import { TuiMapperPipeModule, TuiValueChangesModule } from '@taiga-ui/cdk'
import { TuiMapperPipe, TuiValueChanges } from '@taiga-ui/cdk'
import {
TuiErrorModule,
TuiExpandModule,
TuiHintModule,
TuiLinkModule,
TuiModeModule,
TuiSvgModule,
TuiTextfieldControllerModule,
TuiTooltipModule,
TuiWrapperModule,
TuiAppearance,
TuiButton,
TuiError,
TuiExpand,
TuiHint,
TuiIcon,
TuiLink,
TuiNumberFormat,
} from '@taiga-ui/core'
import { TuiButtonModule } from '@taiga-ui/experimental'
import {
TuiElasticContainerModule,
TuiFieldErrorPipeModule,
TuiElasticContainer,
TuiFieldErrorPipe,
TuiFiles,
TuiSwitch,
TuiTooltip,
} from '@taiga-ui/kit'
import {
TuiInputDateModule,
TuiInputDateTimeModule,
TuiInputFilesModule,
TuiInputModule,
TuiInputNumberModule,
TuiInputTimeModule,
TuiMultiSelectModule,
TuiPromptModule,
TuiSelectModule,
TuiTagModule,
TuiTextAreaModule,
TuiToggleModule,
} from '@taiga-ui/kit'
TuiTextareaModule,
TuiTextfieldControllerModule,
} from '@taiga-ui/legacy'
import { ControlDirective } from './control.directive'
import { FormArrayComponent } from './form-array/form-array.component'
import { FormColorComponent } from './form-color/form-color.component'
import { FormControlComponent } from './form-control/form-control.component'
import { FormDatetimeComponent } from './form-datetime/form-datetime.component'
import { FormFileComponent } from './form-file/form-file.component'
import { FormGroupComponent } from './form-group/form-group.component'
import { FormTextComponent } from './form-text/form-text.component'
import { FormToggleComponent } from './form-toggle/form-toggle.component'
import { FormTextareaComponent } from './form-textarea/form-textarea.component'
import { FormNumberComponent } from './form-number/form-number.component'
import { FormSelectComponent } from './form-select/form-select.component'
import { FormFileComponent } from './form-file/form-file.component'
import { FormMultiselectComponent } from './form-multiselect/form-multiselect.component'
import { FormUnionComponent } from './form-union/form-union.component'
import { FormNumberComponent } from './form-number/form-number.component'
import { FormObjectComponent } from './form-object/form-object.component'
import { FormArrayComponent } from './form-array/form-array.component'
import { FormControlComponent } from './form-control/form-control.component'
import { MustachePipe } from './mustache.pipe'
import { ControlDirective } from './control.directive'
import { FormColorComponent } from './form-color/form-color.component'
import { FormDatetimeComponent } from './form-datetime/form-datetime.component'
import { FormSelectComponent } from './form-select/form-select.component'
import { FormTextComponent } from './form-text/form-text.component'
import { FormTextareaComponent } from './form-textarea/form-textarea.component'
import { FormToggleComponent } from './form-toggle/form-toggle.component'
import { FormUnionComponent } from './form-union/form-union.component'
import { HintPipe } from './hint.pipe'
import { MustachePipe } from './mustache.pipe'
@NgModule({
imports: [
@@ -57,31 +58,30 @@ import { HintPipe } from './hint.pipe'
ReactiveFormsModule,
TuiInputModule,
TuiInputNumberModule,
TuiInputFilesModule,
TuiTextAreaModule,
...TuiFiles,
TuiTextareaModule,
TuiSelectModule,
TuiMultiSelectModule,
TuiToggleModule,
TuiTooltipModule,
TuiHintModule,
TuiModeModule,
TuiSwitch,
TuiTooltip,
...TuiHint,
TuiTagModule,
TuiButtonModule,
TuiExpandModule,
TuiButton,
...TuiExpand,
TuiTextfieldControllerModule,
TuiLinkModule,
TuiPromptModule,
TuiErrorModule,
TuiFieldErrorPipeModule,
TuiValueChangesModule,
TuiElasticContainerModule,
TuiLink,
TuiError,
TuiFieldErrorPipe,
TuiValueChanges,
TuiElasticContainer,
MaskitoModule,
TuiSvgModule,
TuiWrapperModule,
TuiInputDateModule,
TuiInputTimeModule,
TuiInputDateTimeModule,
TuiMapperPipeModule,
TuiMapperPipe,
TuiAppearance,
TuiIcon,
TuiNumberFormat,
],
declarations: [
FormGroupComponent,

View File

@@ -1,12 +1,9 @@
import { TuiCell } from '@taiga-ui/layout'
import { TuiTitle, TuiButton } from '@taiga-ui/core'
import { CommonModule } from '@angular/common'
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
import { CopyService, EmverPipesModule } from '@start9labs/shared'
import {
TuiButtonModule,
TuiCellModule,
TuiTitleModule,
} from '@taiga-ui/experimental'
import { PolymorpheusComponent } from '@tinkoff/ng-polymorpheus'
import { PolymorpheusComponent } from '@taiga-ui/polymorpheus'
import { PatchDB } from 'patch-db-client'
import { DataModel } from 'src/app/services/patch-db/data-model'
import { ConfigService } from 'src/app/services/config.service'
@@ -28,7 +25,7 @@ import { ConfigService } from 'src/app/services/config.service'
<button
tuiIconButton
appearance="icon"
iconLeft="tuiIconCopy"
iconStart="@tui.copy"
(click)="copyService.copy(gitHash)"
>
Copy
@@ -42,7 +39,7 @@ import { ConfigService } from 'src/app/services/config.service'
<button
tuiIconButton
appearance="icon"
iconLeft="tuiIconCopy"
iconStart="@tui.copy"
(click)="copyService.copy(server.caFingerprint)"
>
Copy
@@ -53,13 +50,7 @@ import { ConfigService } from 'src/app/services/config.service'
styles: ['[tuiCell] { padding-inline: 0 }'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [
CommonModule,
EmverPipesModule,
TuiTitleModule,
TuiButtonModule,
TuiCellModule,
],
imports: [CommonModule, EmverPipesModule, TuiTitle, TuiButton, TuiCell],
})
export class AboutComponent {
readonly server$ = inject(PatchDB<DataModel>).watch$('serverInfo')

View File

@@ -5,19 +5,21 @@ import {
inject,
Input,
} from '@angular/core'
import { Breadcrumb } from 'src/app/services/breadcrumbs.service'
import { TuiIconModule, TuiTitleModule } from '@taiga-ui/experimental'
import {
TUI_ANIMATION_OPTIONS,
TUI_ANIMATIONS_SPEED,
tuiFadeIn,
TuiIcon,
TuiTitle,
tuiToAnimationOptions,
tuiWidthCollapse,
} from '@taiga-ui/core'
import { Breadcrumb } from 'src/app/services/breadcrumbs.service'
@Component({
standalone: true,
selector: 'a[headerBreadcrumb]',
template: `
@if (item.icon?.startsWith('tuiIcon')) {
@if (item.icon?.startsWith('@tui.')) {
<tui-icon [icon]="item.icon || ''" />
} @else if (item.icon) {
<img [style.width.rem]="2" [src]="item.icon" [alt]="item.title" />
@@ -78,7 +80,7 @@ import {
`,
],
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [TuiIconModule, TuiTitleModule],
imports: [TuiIcon, TuiTitle],
animations: [tuiWidthCollapse, tuiFadeIn],
})
export class HeaderBreadcrumbComponent {
@@ -87,5 +89,5 @@ export class HeaderBreadcrumbComponent {
@HostBinding('@tuiFadeIn')
@HostBinding('@tuiWidthCollapse')
readonly animation = inject(TUI_ANIMATION_OPTIONS)
readonly animation = tuiToAnimationOptions(inject(TUI_ANIMATIONS_SPEED))
}

View File

@@ -1,6 +1,6 @@
import { TuiIcon } from '@taiga-ui/core'
import { AsyncPipe } from '@angular/common'
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
import { TuiIconModule } from '@taiga-ui/experimental'
import { PatchDB } from 'patch-db-client'
import { combineLatest, map, Observable, startWith } from 'rxjs'
import { ConnectionService } from 'src/app/services/connection.service'
@@ -38,7 +38,7 @@ import { DataModel } from 'src/app/services/patch-db/data-model'
`,
],
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [TuiIconModule, AsyncPipe],
imports: [TuiIcon, AsyncPipe],
})
export class HeaderConnectionComponent {
readonly connection$: Observable<{
@@ -57,36 +57,36 @@ export class HeaderConnectionComponent {
if (!network)
return {
message: 'No Internet',
color: 'var(--tui-error-fill)',
icon: 'tuiIconCloudOff',
color: 'var(--tui-status-negative)',
icon: '@tui.cloud-off',
status: 'error',
}
if (!websocket)
return {
message: 'Connecting',
color: 'var(--tui-warning-fill)',
icon: 'tuiIconCloudOff',
color: 'var(--tui-status-warning)',
icon: '@tui.cloud-off',
status: 'warning',
}
if (status.shuttingDown)
return {
message: 'Shutting Down',
color: 'var(--tui-neutral-fill)',
icon: 'tuiIconPower',
color: 'var(--tui-status-neutral)',
icon: '@tui.power',
status: 'neutral',
}
if (status.restarting)
return {
message: 'Restarting',
color: 'var(--tui-neutral-fill)',
icon: 'tuiIconPower',
color: 'var(--tui-status-neutral)',
icon: '@tui.power',
status: 'neutral',
}
return {
message: 'Connected',
color: 'var(--tui-success-fill)',
icon: 'tuiIconCloud',
color: 'var(--tui-status-positive)',
icon: '@tui.cloud',
status: 'success',
}
}),

View File

@@ -1,18 +1,16 @@
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
import { RouterLink } from '@angular/router'
import { TuiSidebarModule } from '@taiga-ui/addon-mobile'
import { TuiLetModule } from '@taiga-ui/cdk'
import { TuiSidebar } from '@taiga-ui/addon-mobile'
import { TuiLet } from '@taiga-ui/cdk'
import {
TUI_ANIMATION_OPTIONS,
TUI_ANIMATIONS_SPEED,
TuiButton,
tuiFadeIn,
tuiScaleIn,
tuiToAnimationOptions,
tuiWidthCollapse,
} from '@taiga-ui/core'
import {
TuiBadgedContentModule,
TuiBadgeNotificationModule,
TuiButtonModule,
} from '@taiga-ui/experimental'
import { TuiBadgedContent, TuiBadgeNotification } from '@taiga-ui/kit'
import { SidebarDirective } from 'src/app/components/sidebar-host.component'
import { getMenu } from 'src/app/utils/system-utilities'
import { HeaderMenuComponent } from './menu.component'
@@ -37,9 +35,9 @@ import { HeaderMenuComponent } from './menu.component'
tuiIconButton
appearance="icon"
size="s"
[iconLeft]="item.icon"
[iconStart]="item.icon"
[routerLink]="item.routerLink"
[style.color]="'var(--tui-text-01)'"
[style.color]="'var(--tui-text-primary)'"
>
{{ item.name }}
</a>
@@ -68,15 +66,15 @@ import { HeaderMenuComponent } from './menu.component'
imports: [
HeaderMenuComponent,
SidebarDirective,
TuiBadgeNotificationModule,
TuiBadgedContentModule,
TuiButtonModule,
TuiLetModule,
TuiSidebarModule,
TuiBadgeNotification,
TuiBadgedContent,
TuiButton,
TuiLet,
TuiSidebar,
RouterLink,
],
})
export class HeaderCornerComponent {
readonly animation = inject(TUI_ANIMATION_OPTIONS)
readonly animation = tuiToAnimationOptions(inject(TUI_ANIMATIONS_SPEED))
readonly utils = getMenu()
}

View File

@@ -72,26 +72,26 @@ import { BreadcrumbsService } from 'src/app/services/breadcrumbs.service'
}
&:has([data-connection='error']) {
--status: var(--tui-error-fill);
--status: var(--tui-status-negative);
}
&:has([data-connection='warning']) {
--status: var(--tui-warning-fill);
--status: var(--tui-status-warning);
}
&:has([data-connection='neutral']) {
--status: var(--tui-neutral-fill);
--status: var(--tui-status-neutral);
}
&:has([data-connection='success']) {
--status: var(--tui-success-fill);
--status: var(--tui-status-positive);
}
}
header-connection .plaque::before {
box-shadow:
inset 0 1px rgba(255, 255, 255, 0.25),
inset 0 -0.25rem var(--tui-success-fill);
inset 0 -0.25rem var(--tui-status-positive);
}
:host-context(tui-root._mobile) {

View File

@@ -1,5 +1,5 @@
import { TuiIcon } from '@taiga-ui/core'
import { ChangeDetectionStrategy, Component } from '@angular/core'
import { TuiIconModule } from '@taiga-ui/experimental'
@Component({
standalone: true,
@@ -41,6 +41,6 @@ import { TuiIconModule } from '@taiga-ui/experimental'
`,
],
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [TuiIconModule],
imports: [TuiIcon],
})
export class HeaderHomeComponent {}

View File

@@ -1,19 +1,13 @@
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
import { RouterLink } from '@angular/router'
import { TuiActiveZoneModule } from '@taiga-ui/cdk'
import {
TuiDataListModule,
TuiButton,
TuiDataList,
TuiDialogService,
TuiDropdownModule,
TuiHostedDropdownModule,
TuiSvgModule,
TuiDropdown,
TuiIcon,
} from '@taiga-ui/core'
import {
TuiBadgeNotificationModule,
TuiButtonModule,
TuiIconModule,
} from '@taiga-ui/experimental'
import { TuiDataListDropdownManagerModule } from '@taiga-ui/kit'
import { TuiBadgeNotification, TuiDataListDropdownManager } from '@taiga-ui/kit'
import { RESOURCES } from 'src/app/utils/resources'
import { getMenu } from 'src/app/utils/system-utilities'
import { ABOUT } from './about.component'
@@ -21,74 +15,75 @@ import { ABOUT } from './about.component'
@Component({
selector: 'header-menu',
template: `
<tui-hosted-dropdown
[content]="content"
[(open)]="open"
<button
tuiIconButton
appearance=""
[tuiDropdown]="content"
[(tuiDropdownOpen)]="open"
[tuiDropdownMaxHeight]="9999"
>
<button tuiIconButton appearance="">
<img [style.max-width.%]="50" src="assets/img/icon.png" alt="StartOS" />
</button>
<ng-template #content let-zone>
<tui-data-list
tuiDataListDropdownManager
[tuiActiveZoneParent]="zone"
[style.width.rem]="13"
>
@for (link of utils; track $index) {
<a
tuiOption
class="item"
[routerLink]="link.routerLink"
(click)="open = false"
>
<tui-icon [icon]="link.icon" />
{{ link.name }}
@if (link.badge(); as badge) {
<tui-badge-notification>{{ badge }}</tui-badge-notification>
}
</a>
@if (!$index || $index === 3 || $index === 5) {
<hr />
}
}
<hr />
<button
<img [style.max-width.%]="50" src="assets/img/icon.png" alt="StartOS" />
</button>
<ng-template #content>
<tui-data-list tuiDataListDropdownManager [style.width.rem]="13">
@for (link of utils; track $index) {
<a
tuiOption
class="item"
tuiDropdownSided
[tuiDropdown]="dropdown"
[tuiDropdownOffset]="12"
[tuiDropdownManual]="false"
[iconStart]="link.icon"
[routerLink]="link.routerLink"
(click)="open = false"
>
<tui-icon icon="tuiIconHelpCircle" />
Resources
<ng-template #dropdown>
<tui-data-list [tuiActiveZoneParent]="zone">
<button tuiOption class="item" (click)="about()">
<tui-icon icon="tuiIconInfo" />
About this server
</button>
<hr />
@for (link of links; track $index) {
<a
tuiOption
class="item"
target="_blank"
rel="noreferrer"
[href]="link.href"
>
<tui-icon [icon]="link.icon" />
{{ link.name }}
<tui-icon class="external" icon="tuiIconExternalLink" />
</a>
}
</tui-data-list>
</ng-template>
</button>
</tui-data-list>
</ng-template>
</tui-hosted-dropdown>
{{ link.name }}
@if (link.badge(); as badge) {
<tui-badge-notification>{{ badge }}</tui-badge-notification>
}
</a>
@if (!$index || $index === 3 || $index === 5) {
<hr />
}
}
<hr />
<button
tuiOption
class="item"
tuiDropdownSided
iconStart="@tui.circle-help"
iconEnd="@tui.chevron-right"
[tuiDropdown]="dropdown"
[tuiDropdownOffset]="12"
[tuiDropdownManual]="false"
>
Resources
<ng-template #dropdown>
<tui-data-list>
<button
tuiOption
iconStart="@tui.info"
class="item"
(click)="about()"
>
About this server
</button>
<hr />
@for (link of links; track $index) {
<a
tuiOption
class="item"
target="_blank"
rel="noreferrer"
iconEnd="@tui.external-link"
[iconStart]="link.icon"
[href]="link.href"
>
{{ link.name }}
</a>
}
</tui-data-list>
</ng-template>
</button>
</tui-data-list>
</ng-template>
`,
styles: [
`
@@ -108,31 +103,20 @@ import { ABOUT } from './about.component'
.item {
justify-content: flex-start;
gap: 0.75rem;
::ng-deep tui-svg {
margin-left: auto;
}
}
.external {
margin-left: auto;
padding-left: 0.5rem;
}
`,
],
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [
TuiHostedDropdownModule,
TuiDataListModule,
TuiSvgModule,
TuiButtonModule,
TuiIconModule,
TuiDropdown,
TuiDataList,
TuiButton,
TuiIcon,
RouterLink,
TuiBadgeNotificationModule,
TuiDropdownModule,
TuiDataListDropdownManagerModule,
TuiActiveZoneModule,
TuiBadgeNotification,
TuiDropdown,
TuiDataListDropdownManager,
],
})
export class HeaderMenuComponent {

View File

@@ -1,3 +1,4 @@
import { TuiIcon } from '@taiga-ui/core'
import {
ChangeDetectionStrategy,
Component,
@@ -6,7 +7,6 @@ import {
} from '@angular/core'
import { RouterLink } from '@angular/router'
import { WINDOW } from '@ng-web-apis/common'
import { TuiIconModule } from '@taiga-ui/experimental'
import { Breadcrumb } from 'src/app/services/breadcrumbs.service'
@Component({
@@ -19,7 +19,7 @@ import { Breadcrumb } from 'src/app/services/breadcrumbs.service'
[style.padding.rem]="0.75"
[queryParams]="queryParams"
>
<tui-icon icon="tuiIconArrowLeft" />
<tui-icon icon="@tui.arrow-left" />
</a>
}
<span class="title">{{ title }}</span>
@@ -65,7 +65,7 @@ import { Breadcrumb } from 'src/app/services/breadcrumbs.service'
`,
],
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [TuiIconModule, RouterLink],
imports: [TuiIcon, RouterLink],
})
export class HeaderMobileComponent {
private readonly win = inject(WINDOW)

View File

@@ -7,9 +7,8 @@ import {
OnDestroy,
} from '@angular/core'
import { pauseFor } from '@start9labs/shared'
import { TuiButtonModule } from '@taiga-ui/experimental'
import { POLYMORPHEUS_CONTEXT } from '@tinkoff/ng-polymorpheus'
import { TuiDialogContext } from '@taiga-ui/core'
import { POLYMORPHEUS_CONTEXT } from '@taiga-ui/polymorpheus'
import { TuiDialogContext, TuiButton } from '@taiga-ui/core'
@Component({
standalone: true,
@@ -41,7 +40,7 @@ import { TuiDialogContext } from '@taiga-ui/core'
}
`,
],
imports: [TuiButtonModule],
imports: [TuiButton],
})
export class HeaderSnekComponent implements AfterViewInit, OnDestroy {
private readonly document = inject(DOCUMENT)

View File

@@ -1,7 +1,7 @@
import { Directive, HostListener, inject, Input } from '@angular/core'
import { ErrorService, LoadingService } from '@start9labs/shared'
import { TuiDialogService } from '@taiga-ui/core'
import { PolymorpheusComponent } from '@tinkoff/ng-polymorpheus'
import { PolymorpheusComponent } from '@taiga-ui/polymorpheus'
import { filter } from 'rxjs'
import { ApiService } from 'src/app/services/api/embassy-api.service'
import { HeaderSnekComponent } from './snek.component'

View File

@@ -1,3 +1,4 @@
import { TuiButton } from '@taiga-ui/core'
import {
ChangeDetectionStrategy,
Component,
@@ -5,7 +6,6 @@ import {
inject,
} from '@angular/core'
import { AddressItemComponent } from './address-item.component'
import { TuiButtonModule } from '@taiga-ui/experimental'
import { AddressDetails, AddressesService } from './interface.utils'
@Component({
@@ -18,20 +18,20 @@ import { AddressDetails, AddressesService } from './interface.utils'
class="icon-add-btn"
tuiIconButton
appearance="secondary"
iconLeft="tuiIconPlus"
iconStart="@tui.plus"
(click)="service.add()"
>
Add
</button>
}
<ng-content></ng-content>
<ng-content />
</div>
@for (address of addresses; track $index) {
<app-address-item [label]="address.label" [address]="address.url" />
} @empty {
<button
tuiButton
iconLeft="tuiIconPlus"
iconStart="@tui.plus"
[style.align-self]="'flex-start'"
(click)="service.add()"
>
@@ -39,7 +39,7 @@ import { AddressDetails, AddressesService } from './interface.utils'
</button>
}
`,
imports: [AddressItemComponent, TuiButtonModule],
imports: [AddressItemComponent, TuiButton],
changeDetection: ChangeDetectionStrategy.OnPush,
styles: `
.icon-add-btn {

View File

@@ -1,3 +1,5 @@
import { TuiCell } from '@taiga-ui/layout'
import { TuiBadge } from '@taiga-ui/kit'
import { NgIf } from '@angular/common'
import {
ChangeDetectionStrategy,
@@ -7,14 +9,8 @@ import {
} from '@angular/core'
import { WINDOW } from '@ng-web-apis/common'
import { CopyService } from '@start9labs/shared'
import { TuiDialogService } from '@taiga-ui/core'
import {
TuiBadgeModule,
TuiButtonModule,
TuiCellModule,
TuiTitleModule,
} from '@taiga-ui/experimental'
import { PolymorpheusComponent } from '@tinkoff/ng-polymorpheus'
import { TuiDialogService, TuiTitle, TuiButton } from '@taiga-ui/core'
import { PolymorpheusComponent } from '@taiga-ui/polymorpheus'
import { QRModal } from 'src/app/routes/portal/modals/qr.component'
import { mask } from 'src/app/utils/mask'
import { InterfaceComponent } from './interface.component'
@@ -36,7 +32,7 @@ import { AddressesService } from './interface.utils'
<button
*ngIf="interface.serviceInterface.type === 'ui'"
tuiIconButton
iconLeft="tuiIconExternalLink"
iconStart="@tui.external-link"
appearance="icon"
(click)="launch(address)"
>
@@ -44,7 +40,7 @@ import { AddressesService } from './interface.utils'
</button>
<button
tuiIconButton
iconLeft="tuiIconGrid"
iconStart="@tui.qr-code"
appearance="icon"
(click)="showQR(address)"
>
@@ -52,7 +48,7 @@ import { AddressesService } from './interface.utils'
</button>
<button
tuiIconButton
iconLeft="tuiIconCopy"
iconStart="@tui.copy"
appearance="icon"
(click)="copyService.copy(address)"
>
@@ -60,7 +56,7 @@ import { AddressesService } from './interface.utils'
</button>
<button
tuiIconButton
iconLeft="tuiIconTrash"
iconStart="@tui.trash"
appearance="icon"
(click)="service.remove()"
>
@@ -68,13 +64,7 @@ import { AddressesService } from './interface.utils'
</button>
</div>
`,
imports: [
NgIf,
TuiCellModule,
TuiTitleModule,
TuiButtonModule,
TuiBadgeModule,
],
imports: [NgIf, TuiCell, TuiTitle, TuiButton, TuiBadge],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AddressItemComponent {

View File

@@ -6,14 +6,15 @@ import {
Input,
} from '@angular/core'
import { T } from '@start9labs/start-sdk'
import { TuiCardModule, TuiSurfaceModule } from '@taiga-ui/experimental'
import { TuiSurface } from '@taiga-ui/core'
import { TuiCardLarge } from '@taiga-ui/layout'
import { PatchDB } from 'patch-db-client'
import { AddressGroupComponent } from 'src/app/routes/portal/components/interfaces/address-group.component'
import { DataModel } from 'src/app/services/patch-db/data-model'
import { AddressDetails } from './interface.utils'
import { ClearnetAddressesDirective } from './directives/clearnet.directive'
import { LocalAddressesDirective } from './directives/local.directive'
import { TorAddressesDirective } from './directives/tor.directive'
import { AddressDetails } from './interface.utils'
@Component({
standalone: true,
@@ -86,8 +87,8 @@ import { TorAddressesDirective } from './directives/tor.directive'
imports: [
CommonModule,
AddressGroupComponent,
TuiCardModule,
TuiSurfaceModule,
TuiCardLarge,
TuiSurface,
ClearnetAddressesDirective,
TorAddressesDirective,
LocalAddressesDirective,

View File

@@ -1,6 +1,6 @@
import { CB, CT, T } from '@start9labs/start-sdk'
import { TuiDialogOptions } from '@taiga-ui/core'
import { TuiPromptData } from '@taiga-ui/kit'
import { TuiConfirmData } from '@taiga-ui/kit'
import { NetworkInfo } from 'src/app/services/patch-db/data-model'
import { configBuilderToSpec } from 'src/app/utils/configBuilderToSpec'
@@ -9,7 +9,7 @@ export abstract class AddressesService {
abstract remove(): Promise<void>
}
export const REMOVE: Partial<TuiDialogOptions<TuiPromptData>> = {
export const REMOVE: Partial<TuiDialogOptions<TuiConfirmData>> = {
label: 'Confirm',
size: 's',
data: {

View File

@@ -50,7 +50,7 @@
<button
tuiButton
appearance="flat"
iconLeft="tuiIconArrowDownCircle"
iconStart="@tui.circle-arrow-down"
(click)="setScroll(true); scrollToBottom()"
>
Scroll to bottom
@@ -58,7 +58,7 @@
<button
tuiButton
appearance="flat"
iconLeft="tuiIconDownload"
iconStart="@tui.download"
[logsDownload]="fetchLogs"
>
Download

View File

@@ -27,15 +27,15 @@
align-items: center;
justify-content: space-between;
padding-top: 1rem;
border-top: 1px solid var(--tui-clear);
border-top: 1px solid var(--tui-background-neutral-1);
}
[data-status='reconnecting'] {
color: var(--tui-success-fill);
color: var(--tui-status-positive);
}
[data-status='disconnected'] {
color: var(--tui-warning-fill);
color: var(--tui-status-warning);
}
pre {

View File

@@ -2,16 +2,11 @@ import { CommonModule } from '@angular/common'
import { Component, ElementRef, Input, ViewChild } from '@angular/core'
import {
INTERSECTION_ROOT,
IntersectionObserverModule,
WaIntersectionObserver,
} from '@ng-web-apis/intersection-observer'
import { MutationObserverModule } from '@ng-web-apis/mutation-observer'
import { WaMutationObserver } from '@ng-web-apis/mutation-observer'
import { FetchLogsReq, FetchLogsRes } from '@start9labs/shared'
import {
TuiLoaderModule,
TuiScrollbarComponent,
TuiScrollbarModule,
} from '@taiga-ui/core'
import { TuiButtonModule } from '@taiga-ui/experimental'
import { TuiLoader, TuiScrollbar, TuiButton } from '@taiga-ui/core'
import { NgDompurifyModule } from '@tinkoff/ng-dompurify'
import { RR } from 'src/app/services/api/api.types'
import { LogsDownloadDirective } from './logs-download.directive'
@@ -26,12 +21,12 @@ import { BehaviorSubject } from 'rxjs'
styleUrls: ['./logs.component.scss'],
imports: [
CommonModule,
IntersectionObserverModule,
MutationObserverModule,
WaIntersectionObserver,
WaMutationObserver,
NgDompurifyModule,
TuiButtonModule,
TuiLoaderModule,
TuiScrollbarModule,
TuiButton,
TuiLoader,
TuiScrollbar,
LogsDownloadDirective,
LogsFetchDirective,
LogsPipe,
@@ -47,7 +42,7 @@ export class LogsComponent {
@ViewChild('bottom')
private readonly bottom?: ElementRef<HTMLElement>
@ViewChild(TuiScrollbarComponent, { read: ElementRef })
@ViewChild(TuiScrollbar, { read: ElementRef })
private readonly scrollbar?: ElementRef<HTMLElement>
@Input({ required: true }) followLogs!: (

View File

@@ -80,7 +80,7 @@ export class LogsPipe implements PipeTransform {
function getMessage(success: boolean): string {
return `<p style="color: ${
success ? 'var(--tui-success-fill)' : 'var(--tui-error-fill)'
success ? 'var(--tui-status-positive)' : 'var(--tui-status-negative)'
}; text-align: center;">${
success ? 'Reconnected' : 'Disconnected'
} at ${toLocalIsoString(new Date())}</p>`

View File

@@ -7,12 +7,9 @@ import {
} from '@angular/core'
import { toSignal } from '@angular/core/rxjs-interop'
import { RouterLink, RouterLinkActive } from '@angular/router'
import { TuiSheetDialogService, TuiTabBarModule } from '@taiga-ui/addon-mobile'
import { TuiDialogService } from '@taiga-ui/core'
import {
TuiBadgeNotificationModule,
TuiIconModule,
} from '@taiga-ui/experimental'
import { TuiSheetDialogService, TuiTabBar } from '@taiga-ui/addon-mobile'
import { TuiDialogService, TuiIcon } from '@taiga-ui/core'
import { TuiBadgeNotification } from '@taiga-ui/kit'
import { ABOUT } from 'src/app/routes/portal/components/header/about.component'
import { BadgeService } from 'src/app/services/badge.service'
import { RESOURCES } from 'src/app/utils/resources'
@@ -27,7 +24,7 @@ const FILTER = ['/portal/system/settings', '/portal/system/marketplace']
<nav tuiTabBar [(activeItemIndex)]="index">
<a
tuiTabBarItem
icon="tuiIconGrid"
icon="@tui.layout-grid"
routerLink="/portal/dashboard"
routerLinkActive
(isActiveChange)="update()"
@@ -36,7 +33,7 @@ const FILTER = ['/portal/system/settings', '/portal/system/marketplace']
</a>
<a
tuiTabBarItem
icon="tuiIconShoppingCart"
icon="@tui.shopping-cart"
routerLink="/portal/system/marketplace"
routerLinkActive
(isActiveChange)="update()"
@@ -45,7 +42,7 @@ const FILTER = ['/portal/system/settings', '/portal/system/marketplace']
</a>
<a
tuiTabBarItem
icon="tuiIconSettings"
icon="@tui.settings"
routerLink="/portal/system/settings"
routerLinkActive
[badge]="badge()"
@@ -55,7 +52,7 @@ const FILTER = ['/portal/system/settings', '/portal/system/marketplace']
</a>
<button
tuiTabBarItem
icon="tuiIconMoreHorizontal"
icon="@tui.ellipsis"
(click)="more(content)"
[badge]="all()"
>
@@ -76,7 +73,7 @@ const FILTER = ['/portal/system/settings', '/portal/system/marketplace']
</a>
}
<button class="item" (click)="about()">
<tui-icon icon="tuiIconInfo" />
<tui-icon icon="@tui.info" />
About this server
</button>
@for (link of resources; track $index) {
@@ -84,7 +81,7 @@ const FILTER = ['/portal/system/settings', '/portal/system/marketplace']
<tui-icon [icon]="link.icon" />
{{ link.name }}
<tui-icon
icon="tuiIconExternalLink"
icon="@tui.external-link"
[style.margin-inline-start]="'auto'"
/>
</a>
@@ -100,10 +97,10 @@ const FILTER = ['/portal/system/settings', '/portal/system/marketplace']
display: none;
backdrop-filter: blur(1rem);
// TODO: Theme
--tui-elevation-01: #333;
--tui-base-01: #fff;
--tui-base-04: var(--tui-clear);
--tui-error-fill: #f52222;
--tui-background-elevation-1: #333;
--tui-background-base: #fff;
--tui-border-normal: var(--tui-background-neutral-1);
--tui-status-negative: #f52222;
}
[tuiTabBar]::before {
@@ -111,7 +108,7 @@ const FILTER = ['/portal/system/settings', '/portal/system/marketplace']
}
.item {
@include clearbtn();
@include button-clear();
display: flex;
padding: 0.75rem 0.25rem;
@@ -119,7 +116,7 @@ const FILTER = ['/portal/system/settings', '/portal/system/marketplace']
align-items: center;
&_active {
color: var(--tui-link);
color: var(--tui-text-action);
}
}
@@ -130,9 +127,9 @@ const FILTER = ['/portal/system/settings', '/portal/system/marketplace']
imports: [
RouterLink,
RouterLinkActive,
TuiTabBarModule,
TuiBadgeNotificationModule,
TuiIconModule,
TuiTabBar,
TuiBadgeNotification,
TuiIcon,
],
})
export class TabsComponent {

View File

@@ -4,11 +4,11 @@ import {
Input,
OnChanges,
} from '@angular/core'
import { TuiNotification } from '@taiga-ui/core'
import { compare, getValueByPointer, Operation } from 'fast-json-patch'
import { isObject } from '@start9labs/shared'
import { tuiIsNumber } from '@taiga-ui/cdk'
import { CommonModule } from '@angular/common'
import { TuiNotificationModule } from '@taiga-ui/core'
@Component({
selector: 'config-dep',
@@ -26,7 +26,7 @@ import { TuiNotificationModule } from '@taiga-ui/core'
</tui-notification>
`,
standalone: true,
imports: [CommonModule, TuiNotificationModule],
imports: [CommonModule, TuiNotification],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ConfigDepComponent implements OnChanges {

View File

@@ -7,16 +7,15 @@ import {
LoadingService,
} from '@start9labs/shared'
import { CT } from '@start9labs/start-sdk'
import { TuiButtonModule } from '@taiga-ui/experimental'
import {
TuiDialogContext,
TuiDialogService,
TuiLoaderModule,
TuiModeModule,
TuiNotificationModule,
TuiLoader,
TuiButton,
TuiNotification,
} from '@taiga-ui/core'
import { TUI_PROMPT, TuiPromptData } from '@taiga-ui/kit'
import { POLYMORPHEUS_CONTEXT } from '@tinkoff/ng-polymorpheus'
import { TuiConfirmData, TUI_CONFIRM } from '@taiga-ui/kit'
import { POLYMORPHEUS_CONTEXT } from '@taiga-ui/polymorpheus'
import { compare, Operation } from 'fast-json-patch'
import { PatchDB } from 'patch-db-client'
import { endWith, firstValueFrom, Subscription } from 'rxjs'
@@ -80,7 +79,6 @@ export interface PackageConfigData {
</tui-notification>
<app-form
tuiMode="onDark"
[spec]="spec"
[value]="value || {}"
[buttons]="buttons"
@@ -109,10 +107,9 @@ export interface PackageConfigData {
imports: [
CommonModule,
FormComponent,
TuiLoaderModule,
TuiNotificationModule,
TuiButtonModule,
TuiModeModule,
TuiLoader,
TuiNotification,
TuiButton,
ConfigDepComponent,
ToManifestPipe,
],
@@ -271,10 +268,10 @@ export class ConfigModal {
const content = `${message}${Object.keys(breakages).map(
id => `<li><b>${getManifest(packages[id]).title}</b></li>`,
)}</ul>`
const data: TuiPromptData = { content, yes: 'Continue', no: 'Cancel' }
const data: TuiConfirmData = { content, yes: 'Continue', no: 'Cancel' }
return firstValueFrom(
this.dialogs.open<boolean>(TUI_PROMPT, { data }).pipe(endWith(false)),
this.dialogs.open<boolean>(TUI_CONFIRM, { data }).pipe(endWith(false)),
)
}
}

View File

@@ -1,14 +1,13 @@
import { TuiTextfieldControllerModule, TuiInputModule } from '@taiga-ui/legacy'
import { TuiAutoFocus } from '@taiga-ui/cdk'
import { CommonModule } from '@angular/common'
import { ChangeDetectionStrategy, Component, Inject } from '@angular/core'
import { FormsModule } from '@angular/forms'
import { TuiAutoFocusModule } from '@taiga-ui/cdk'
import { TuiDialogContext, TuiTextfieldControllerModule } from '@taiga-ui/core'
import { TuiButtonModule } from '@taiga-ui/experimental'
import { TuiInputModule } from '@taiga-ui/kit'
import { TuiDialogContext, TuiButton } from '@taiga-ui/core'
import {
POLYMORPHEUS_CONTEXT,
PolymorpheusComponent,
} from '@tinkoff/ng-polymorpheus'
} from '@taiga-ui/polymorpheus'
@Component({
standalone: true,
@@ -26,7 +25,7 @@ import {
{{ options.label }}
<span *ngIf="options.required !== false && options.label">*</span>
<input
tuiTextfield
tuiTextfieldLegacy
[class.masked]="options.useMask && masked && value"
[placeholder]="options.placeholder || ''"
/>
@@ -54,7 +53,7 @@ import {
title="Toggle masking"
size="xs"
class="button"
[iconLeft]="masked ? 'tuiIconEye' : 'tuiIconEyeOff'"
[iconStart]="masked ? '@tui.eye' : '@tui.eye-off'"
(click)="masked = !masked"
></button>
</ng-template>
@@ -62,7 +61,7 @@ import {
styles: [
`
.warning {
color: var(--tui-warning-fill);
color: var(--tui-status-warning);
}
.button {
@@ -79,9 +78,9 @@ import {
CommonModule,
FormsModule,
TuiInputModule,
TuiButtonModule,
TuiButton,
TuiTextfieldControllerModule,
TuiAutoFocusModule,
TuiAutoFocus,
],
changeDetection: ChangeDetectionStrategy.OnPush,
})

View File

@@ -1,6 +1,6 @@
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
import { TuiDialogContext } from '@taiga-ui/core'
import { POLYMORPHEUS_CONTEXT } from '@tinkoff/ng-polymorpheus'
import { POLYMORPHEUS_CONTEXT } from '@taiga-ui/polymorpheus'
import { QrCodeModule } from 'ng-qrcode'
@Component({

View File

@@ -1,8 +1,8 @@
import { TuiScrollbar } from '@taiga-ui/core'
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 { TuiScrollbarModule } from '@taiga-ui/core'
import { PatchDB } from 'patch-db-client'
import { filter } from 'rxjs'
import { TabsComponent } from 'src/app/routes/portal/components/tabs.component'
@@ -44,7 +44,7 @@ import { HeaderComponent } from './components/header/header.component'
RouterOutlet,
HeaderComponent,
TabsComponent,
TuiScrollbarModule,
TuiScrollbar,
],
})
export class PortalComponent {

View File

@@ -6,11 +6,8 @@ import {
inject,
input,
} from '@angular/core'
import { TuiLetModule } from '@taiga-ui/cdk'
import {
TuiButtonModule,
tuiButtonOptionsProvider,
} from '@taiga-ui/experimental'
import { TuiLet } from '@taiga-ui/cdk'
import { TuiButton, tuiButtonOptionsProvider } from '@taiga-ui/core'
import { map } from 'rxjs'
import { UILaunchComponent } from 'src/app/routes/portal/routes/dashboard/ui.component'
import { ActionsService } from 'src/app/services/actions.service'
@@ -25,7 +22,7 @@ import { getManifest } from 'src/app/utils/get-package-data'
@if (pkg().status.main.status === 'running') {
<button
tuiIconButton
iconLeft="tuiIconSquare"
iconStart="@tui.square"
(click)="actions.stop(manifest())"
>
Stop
@@ -33,7 +30,7 @@ import { getManifest } from 'src/app/utils/get-package-data'
<button
tuiIconButton
iconLeft="tuiIconRotateCw"
iconStart="@tui.rotate-cw"
(click)="actions.restart(manifest())"
>
Restart
@@ -42,7 +39,7 @@ import { getManifest } from 'src/app/utils/get-package-data'
<button
*tuiLet="hasUnmet() | async as hasUnmet"
tuiIconButton
iconLeft="tuiIconPlay"
iconStart="@tui.play"
[disabled]="!pkg().status.configured"
(click)="actions.start(manifest(), !!hasUnmet)"
>
@@ -51,7 +48,7 @@ import { getManifest } from 'src/app/utils/get-package-data'
<button
tuiIconButton
iconLeft="tuiIconTool"
iconStart="@tui.wrench"
(click)="actions.configure(manifest())"
>
Configure
@@ -61,7 +58,7 @@ import { getManifest } from 'src/app/utils/get-package-data'
<app-ui-launch [pkg]="pkg()" />
`,
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [TuiButtonModule, UILaunchComponent, TuiLetModule, AsyncPipe],
imports: [TuiButton, UILaunchComponent, TuiLet, AsyncPipe],
providers: [tuiButtonOptionsProvider({ size: 's', appearance: 'none' })],
styles: `
:host {

View File

@@ -1,6 +1,6 @@
import { TuiIcon } from '@taiga-ui/core'
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
import { toSignal } from '@angular/core/rxjs-interop'
import { TuiIconModule } from '@taiga-ui/experimental'
import { ToManifestPipe } from 'src/app/routes/portal/pipes/to-manifest'
import { ServiceComponent } from 'src/app/routes/portal/routes/dashboard/service.component'
import { ServicesService } from 'src/app/routes/portal/routes/dashboard/services.service'
@@ -10,7 +10,7 @@ import { DepErrorService } from 'src/app/services/dep-error.service'
standalone: true,
template: `
<h2>
<tui-icon icon="tuiIconGrid" />
<tui-icon icon="@tui.layout-grid" />
Services
</h2>
<div class="g-plaque"></div>
@@ -86,12 +86,12 @@ import { DepErrorService } from 'src/app/services/dep-error.service'
}
tr:not(:last-child) {
box-shadow: inset 0 -1px var(--tui-clear);
box-shadow: inset 0 -1px var(--tui-background-neutral-1);
}
th {
text-transform: uppercase;
color: var(--tui-text-02);
color: var(--tui-text-secondary);
font: var(--tui-font-text-s);
font-weight: bold;
text-align: left;
@@ -118,7 +118,7 @@ import { DepErrorService } from 'src/app/services/dep-error.service'
}
}
`,
imports: [TuiIconModule, ServiceComponent, ToManifestPipe],
imports: [TuiIcon, ServiceComponent, ToManifestPipe],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DashboardComponent {

View File

@@ -50,7 +50,7 @@ import { getManifest } from 'src/app/utils/get-package-data'
cursor: pointer;
&:hover {
background: var(--tui-clear);
background: var(--tui-background-neutral-1);
}
}
@@ -66,7 +66,7 @@ import { getManifest } from 'src/app/utils/get-package-data'
}
a {
color: var(--tui-text-01);
color: var(--tui-text-primary);
font-weight: bold;
}

View File

@@ -1,3 +1,4 @@
import { TuiLoader, TuiIcon } from '@taiga-ui/core'
import {
ChangeDetectionStrategy,
Component,
@@ -5,8 +6,6 @@ import {
Input,
} from '@angular/core'
import { tuiPure } from '@taiga-ui/cdk'
import { TuiLoaderModule } from '@taiga-ui/core'
import { TuiIconModule } from '@taiga-ui/experimental'
import { PackageDataEntry } from 'src/app/services/patch-db/data-model'
import { renderPkgStatus } from 'src/app/services/pkg-status-rendering.service'
import { InstallingProgressDisplayPipe } from '../service/pipes/install-progress.pipe'
@@ -19,9 +18,9 @@ import { InstallingProgressDisplayPipe } from '../service/pipes/install-progress
<tui-loader size="s" />
} @else {
@if (healthy) {
<tui-icon icon="tuiIconCheck" class="g-success" />
<tui-icon icon="@tui.check" class="g-success" />
} @else {
<tui-icon icon="tuiIconAlertTriangle" class="g-warning" />
<tui-icon icon="@tui.triangle-alert" class="g-warning" />
}
}
<b [style.color]="color">{{ status }}</b>
@@ -46,7 +45,7 @@ import { InstallingProgressDisplayPipe } from '../service/pipes/install-progress
}
`,
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [TuiIconModule, TuiLoaderModule],
imports: [TuiIcon, TuiLoader],
providers: [InstallingProgressDisplayPipe],
})
export class StatusComponent {
@@ -69,7 +68,7 @@ export class StatusComponent {
}
get loading(): boolean {
return this.color === 'var(--tui-info-fill)'
return this.color === 'var(--tui-status-info)'
}
@tuiPure
@@ -111,9 +110,9 @@ export class StatusComponent {
get color(): string {
switch (this.getStatus(this.pkg).primary) {
case 'running':
return 'var(--tui-success-fill)'
return 'var(--tui-status-positive)'
case 'needsConfig':
return 'var(--tui-warning-fill)'
return 'var(--tui-status-warning)'
case 'installing':
case 'updating':
case 'stopping':
@@ -122,10 +121,10 @@ export class StatusComponent {
case 'restarting':
case 'removing':
case 'restoring':
return 'var(--tui-info-fill)'
return 'var(--tui-status-info)'
// stopped
default:
return 'var(--tui-text-02)'
return 'var(--tui-text-secondary)'
}
}
}

View File

@@ -6,8 +6,7 @@ import {
} from '@angular/core'
import { T } from '@start9labs/start-sdk'
import { tuiPure } from '@taiga-ui/cdk'
import { TuiDataListModule, TuiHostedDropdownModule } from '@taiga-ui/core'
import { TuiButtonModule } from '@taiga-ui/experimental'
import { TuiDataList, TuiDropdown, TuiButton } from '@taiga-ui/core'
import { ConfigService } from 'src/app/services/config.service'
import { PackageDataEntry } from 'src/app/services/patch-db/data-model'
@@ -16,38 +15,38 @@ import { PackageDataEntry } from 'src/app/services/patch-db/data-model'
selector: 'app-ui-launch',
template: `
@if (interfaces.length > 1) {
<tui-hosted-dropdown [content]="content">
<button
tuiIconButton
iconLeft="tuiIconExternalLink"
[disabled]="!isRunning"
>
Launch UI
</button>
<ng-template #content>
<tui-data-list>
@for (interface of interfaces; track $index) {
<a
tuiOption
target="_blank"
rel="noreferrer"
[attr.href]="getHref(interface)"
>
{{ interface.name }}
</a>
}
</tui-data-list>
</ng-template>
</tui-hosted-dropdown>
<button
tuiIconButton
iconStart="@tui.external-link"
tuiDropdownOpen
[disabled]="!isRunning"
[tuiDropdown]="content"
>
Launch UI
</button>
<ng-template #content>
<tui-data-list>
@for (interface of interfaces; track $index) {
<a
tuiOption
target="_blank"
rel="noreferrer"
[attr.href]="getHref(interface)"
>
{{ interface.name }}
</a>
}
</tui-data-list>
</ng-template>
} @else {
<a
tuiIconButton
iconLeft="tuiIconExternalLink"
iconStart="@tui.external-link"
target="_blank"
rel="noreferrer"
[attr.href]="getHref(interfaces[0])"
[attr.href]="getHref(first)"
>
{{ interfaces[0]?.name }}
{{ first?.name }}
</a>
}
`,
@@ -57,7 +56,7 @@ import { PackageDataEntry } from 'src/app/services/patch-db/data-model'
}
`,
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [TuiButtonModule, TuiHostedDropdownModule, TuiDataListModule],
imports: [TuiButton, TuiDropdown, TuiDataList],
})
export class UILaunchComponent {
private readonly config = inject(ConfigService)
@@ -73,6 +72,10 @@ export class UILaunchComponent {
return this.pkg.status.main.status === 'running'
}
get first(): T.ServiceInterfaceWithHostInfo | undefined {
return this.interfaces[0]
}
@tuiPure
getInterfaces(pkg?: PackageDataEntry): T.ServiceInterfaceWithHostInfo[] {
return pkg

View File

@@ -1,9 +1,8 @@
import { CommonModule } from '@angular/common'
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
import { CopyService } from '@start9labs/shared'
import { TuiDialogContext } from '@taiga-ui/core'
import { TuiButtonModule } from '@taiga-ui/experimental'
import { POLYMORPHEUS_CONTEXT } from '@tinkoff/ng-polymorpheus'
import { TuiDialogContext, TuiButton } from '@taiga-ui/core'
import { POLYMORPHEUS_CONTEXT } from '@taiga-ui/polymorpheus'
import { QrCodeModule } from 'ng-qrcode'
import { ActionResponse } from 'src/app/services/api/api.types'
@@ -22,7 +21,7 @@ import { ActionResponse } from 'src/app/services/api/api.types'
*ngIf="context.data.copyable"
tuiIconButton
appearance="flat"
iconLeft="tuiIconCopyLarge"
iconStart="@tui.copy"
(click)="copyService.copy(context.data.value)"
>
Copy
@@ -48,7 +47,7 @@ import { ActionResponse } from 'src/app/services/api/api.types'
],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [CommonModule, QrCodeModule, TuiButtonModule],
imports: [CommonModule, QrCodeModule, TuiButton],
})
export class ServiceActionSuccessComponent {
readonly copyService = inject(CopyService)

View File

@@ -1,6 +1,5 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
import { TuiSvgModule } from '@taiga-ui/core'
import { TuiIconModule } from '@taiga-ui/experimental'
import { TuiIcon } from '@taiga-ui/core'
interface ActionItem {
readonly icon: string
@@ -19,7 +18,7 @@ interface ActionItem {
`,
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [TuiIconModule],
imports: [TuiIcon],
})
export class ServiceActionComponent {
@Input({ required: true })

View File

@@ -1,3 +1,4 @@
import { TuiButton } from '@taiga-ui/core'
import {
ChangeDetectionStrategy,
Component,
@@ -6,10 +7,7 @@ import {
} from '@angular/core'
import { T } from '@start9labs/start-sdk'
import { tuiPure } from '@taiga-ui/cdk'
import {
TuiButtonModule,
tuiButtonOptionsProvider,
} from '@taiga-ui/experimental'
import { tuiButtonOptionsProvider } from '@taiga-ui/core'
import { DependencyInfo } from 'src/app/routes/portal/routes/service/types/dependency-info'
import { ActionsService } from 'src/app/services/actions.service'
import { PackageDataEntry } from 'src/app/services/patch-db/data-model'
@@ -22,7 +20,7 @@ import { getManifest } from 'src/app/utils/get-package-data'
<button
tuiButton
appearance="danger-solid"
iconLeft="tuiIconSquare"
iconStart="@tui.square"
(click)="actions.stop(manifest)"
>
Stop
@@ -30,7 +28,7 @@ import { getManifest } from 'src/app/utils/get-package-data'
<button
tuiButton
iconLeft="tuiIconRotateCw"
iconStart="@tui.rotate-cw"
(click)="actions.restart(manifest)"
>
Restart
@@ -40,7 +38,7 @@ import { getManifest } from 'src/app/utils/get-package-data'
@if (pkg.status.main.status === 'stopped' && isConfigured) {
<button
tuiButton
iconLeft="tuiIconPlay"
iconStart="@tui.play"
(click)="actions.start(manifest, hasUnmet(dependencies))"
>
Start
@@ -51,7 +49,7 @@ import { getManifest } from 'src/app/utils/get-package-data'
<button
tuiButton
appearance="secondary-warning"
iconLeft="tuiIconTool"
iconStart="@tui.wrench"
(click)="actions.configure(manifest)"
>
Configure
@@ -70,7 +68,7 @@ import { getManifest } from 'src/app/utils/get-package-data'
],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [TuiButtonModule],
imports: [TuiButton],
providers: [tuiButtonOptionsProvider({ size: 's' })],
})
export class ServiceActionsComponent {

View File

@@ -1,3 +1,4 @@
import { TuiButton } from '@taiga-ui/core'
import { I18nPluralPipe } from '@angular/common'
import {
ChangeDetectionStrategy,
@@ -7,7 +8,6 @@ import {
} from '@angular/core'
import { RouterLink } from '@angular/router'
import { T } from '@start9labs/start-sdk'
import { TuiButtonModule } from '@taiga-ui/experimental'
@Component({
selector: 'service-backups',
@@ -23,7 +23,7 @@ import { TuiButtonModule } from '@taiga-ui/experimental'
<div [style.min-width.%]="100">
<a
tuiButton
iconLeft="tuiIconPlusSquare"
iconStart="@tui.square-plus"
routerLink="/portal/system/backups"
size="s"
appearance="secondary-warning"
@@ -43,13 +43,13 @@ import { TuiButtonModule } from '@taiga-ui/experimental'
small {
display: block;
text-transform: uppercase;
color: var(--tui-text-02);
color: var(--tui-text-secondary);
}
}
`,
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [TuiButtonModule, RouterLink, I18nPluralPipe],
imports: [TuiButton, RouterLink, I18nPluralPipe],
})
export class ServiceBackupsComponent {
pkg = input.required<T.PackageDataEntry>()

View File

@@ -1,7 +1,6 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
import { EmverPipesModule } from '@start9labs/shared'
import { CommonModule } from '@angular/common'
import { TuiSvgModule } from '@taiga-ui/core'
import { TuiIcon } from '@taiga-ui/core'
import { DependencyInfo } from '../types/dependency-info'
@Component({
@@ -10,11 +9,9 @@ import { DependencyInfo } from '../types/dependency-info'
<img [src]="dep.icon" alt="" />
<span [style.flex]="1">
<strong>
<tui-svg
*ngIf="dep.errorText"
src="tuiIconAlertTriangle"
[style.color]="color"
></tui-svg>
@if (dep.errorText) {
<tui-icon icon="@tui.triangle-alert" [style.color]="color" />
}
{{ dep.title }}
</strong>
<div>{{ dep.version | displayEmver }}</div>
@@ -22,10 +19,12 @@ import { DependencyInfo } from '../types/dependency-info'
{{ dep.errorText || 'Satisfied' }}
</div>
</span>
<div *ngIf="dep.actionText">
{{ dep.actionText }}
<tui-svg src="tuiIconArrowRight"></tui-svg>
</div>
@if (dep.actionText) {
<div>
{{ dep.actionText }}
<tui-icon icon="@tui.arrow-right" />
</div>
}
`,
styles: [
`
@@ -35,15 +34,14 @@ import { DependencyInfo } from '../types/dependency-info'
border-radius: 100%;
}
tui-svg {
width: 1rem;
height: 1rem;
tui-icon {
font-size: 1rem;
}
`,
],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [EmverPipesModule, CommonModule, TuiSvgModule],
imports: [EmverPipesModule, TuiIcon],
})
export class ServiceDependencyComponent {
@Input({ required: true, alias: 'serviceDependency' })
@@ -51,7 +49,7 @@ export class ServiceDependencyComponent {
get color(): string {
return this.dep.errorText
? 'var(--tui-warning-fill)'
: 'var(--tui-success-fill)'
? 'var(--tui-status-warning)'
: 'var(--tui-status-positive)'
}
}

View File

@@ -1,23 +1,22 @@
import { CommonModule } from '@angular/common'
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
import { T } from '@start9labs/start-sdk'
import { TuiLoaderModule, TuiSvgModule } from '@taiga-ui/core'
import { TuiIcon, TuiLoader } from '@taiga-ui/core'
@Component({
selector: 'service-health-check',
template: `
<tui-loader
*ngIf="loading; else svg"
[class.tui-skeleton]="!connected"
[inheritColor]="!check.result"
></tui-loader>
<ng-template #svg>
<tui-svg
[src]="icon"
@if (loading) {
<tui-loader
[class.tui-skeleton]="!connected"
[inheritColor]="!check.result"
/>
} @else {
<tui-icon
[icon]="icon"
[class.tui-skeleton]="!connected"
[style.color]="color"
></tui-svg>
</ng-template>
/>
}
<div>
<strong [class.tui-skeleton]="!connected">{{ check.name }}</strong>
<div [class.tui-skeleton]="!connected" [style.color]="color">
@@ -39,7 +38,7 @@ import { TuiLoaderModule, TuiSvgModule } from '@taiga-ui/core'
],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [CommonModule, TuiLoaderModule, TuiSvgModule],
imports: [TuiLoader, TuiIcon],
})
export class ServiceHealthCheckComponent {
@Input({ required: true })
@@ -57,26 +56,26 @@ export class ServiceHealthCheckComponent {
get icon(): string {
switch (this.check.result) {
case 'success':
return 'tuiIconCheckLarge'
return '@tui.check'
case 'failure':
return 'tuiIconAlertTriangleLarge'
return '@tui.triangle-alert'
default:
return 'tuiIconMinusLarge'
return '@tui.minus'
}
}
get color(): string {
switch (this.check.result) {
case 'success':
return 'var(--tui-success-fill)'
return 'var(--tui-status-positive)'
case 'failure':
return 'var(--tui-warning-fill)'
return 'var(--tui-status-warning)'
case 'starting':
case 'loading':
return 'var(--tui-primary)'
return 'var(--tui-background-accent-1)'
// disabled
default:
return 'var(--tui-text-02)'
return 'var(--tui-text-secondary)'
}
}

View File

@@ -1,3 +1,5 @@
import { TuiLet } from '@taiga-ui/cdk'
import { TuiLoader, TuiIcon, TuiButton } from '@taiga-ui/core'
import { CommonModule } from '@angular/common'
import {
ChangeDetectionStrategy,
@@ -5,9 +7,6 @@ import {
inject,
Input,
} from '@angular/core'
import { TuiLetModule } from '@taiga-ui/cdk'
import { TuiLoaderModule } from '@taiga-ui/core'
import { TuiButtonModule, TuiIconModule } from '@taiga-ui/experimental'
import { map, timer } from 'rxjs'
import { ConfigService } from 'src/app/services/config.service'
import { ExtendedInterfaceInfo } from '../pipes/interface-info.pipe'
@@ -21,7 +20,7 @@ import { ExtendedInterfaceInfo } from '../pipes/interface-info.pipe'
} @else if (check === '') {
<tui-icon [icon]="info.icon" [style.color]="info.color" />
} @else {
<tui-icon icon="tuiIconXCircle" class="g-error" />
<tui-icon icon="@tui.circle-x" class="g-error" />
}
<div [style.flex]="1">
<strong>{{ info.name }}</strong>
@@ -39,7 +38,7 @@ import { ExtendedInterfaceInfo } from '../pipes/interface-info.pipe'
<a
tuiIconButton
appearance="flat"
iconLeft="tuiIconExternalLinkLarge"
iconStart="@tui.external-link"
target="_blank"
rel="noreferrer"
title="Open"
@@ -52,13 +51,7 @@ import { ExtendedInterfaceInfo } from '../pipes/interface-info.pipe'
`,
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [
CommonModule,
TuiButtonModule,
TuiLetModule,
TuiLoaderModule,
TuiIconModule,
],
imports: [CommonModule, TuiButton, TuiLet, TuiLoader, TuiIcon],
})
export class ServiceInterfaceListItemComponent {
private readonly config = inject(ConfigService)

View File

@@ -1,5 +1,5 @@
import { TuiIcon } from '@taiga-ui/core'
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
import { TuiIconModule } from '@taiga-ui/experimental'
import { ServiceMenu } from '../pipes/to-menu.pipe'
@Component({
@@ -13,11 +13,11 @@ import { ServiceMenu } from '../pipes/to-menu.pipe'
<ng-content />
</div>
</div>
<tui-icon icon="tuiIconChevronRight" />
<tui-icon icon="@tui.chevron-right" />
`,
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [TuiIconModule],
imports: [TuiIcon],
})
export class ServiceMenuItemComponent {
@Input({ required: true, alias: 'serviceMenuItem' })

View File

@@ -38,7 +38,7 @@ export class ServiceMenuComponent {
get color(): string {
return this.pkg.outboundProxy
? 'var(--tui-success-fill)'
: 'var(--tui-warning-fill)'
? 'var(--tui-status-positive)'
: 'var(--tui-status-warning)'
}
}

View File

@@ -1,20 +1,21 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
import { T } from '@start9labs/start-sdk'
import { TuiProgressModule } from '@taiga-ui/kit'
import { TuiProgress } from '@taiga-ui/kit'
import { InstallingProgressPipe } from 'src/app/routes/portal/routes/service/pipes/install-progress.pipe'
@Component({
selector: '[progress]',
template: `
<ng-content></ng-content>
<ng-content />
@if (progress | installingProgress; as decimal) {
: {{ decimal * 100 }}%
<progress
tuiProgressBar
new
size="xs"
[style.color]="
progress === true ? 'var(--tui-positive)' : 'var(--tui-link)'
progress === true
? 'var(--tui-text-positive)'
: 'var(--tui-text-action)'
"
[value]="decimal * 100"
></progress>
@@ -23,7 +24,7 @@ import { InstallingProgressPipe } from 'src/app/routes/portal/routes/service/pip
styles: [':host { line-height: 2rem }'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [TuiProgressModule, InstallingProgressPipe],
imports: [TuiProgress, InstallingProgressPipe],
})
export class ServiceProgressComponent {
@Input({ required: true }) progress!: T.Progress

View File

@@ -5,20 +5,20 @@ import {
Input,
} from '@angular/core'
import { CopyService } from '@start9labs/shared'
import { TuiButton, TuiLabel, TuiTitle } from '@taiga-ui/core'
import { mask } from 'src/app/utils/mask'
import { TuiLabelModule } from '@taiga-ui/core'
import { TuiButtonModule } from '@taiga-ui/experimental'
@Component({
selector: 'service-property',
template: `
<label [style.flex]="1" [tuiLabel]="label">
<label [style.flex]="1" tuiTitle>
<span tuiSubtitle>{{ label }}</span>
{{ masked ? mask : value }}
</label>
<button
tuiIconButton
appearance="flat"
[iconLeft]="masked ? 'tuiIconEyeLarge' : 'tuiIconEyeOffLarge'"
[iconStart]="masked ? '@tui.eye' : '@tui.eye-off'"
(click)="masked = !masked"
>
Toggle
@@ -26,7 +26,7 @@ import { TuiButtonModule } from '@taiga-ui/experimental'
<button
tuiIconButton
appearance="flat"
iconLeft="tuiIconCopyLarge"
iconStart="@tui.copy"
(click)="copyService.copy(value)"
>
Copy
@@ -39,14 +39,14 @@ import { TuiButtonModule } from '@taiga-ui/experimental'
padding: 0.5rem 0;
&:not(:last-of-type) {
box-shadow: 0 1px var(--tui-clear);
box-shadow: 0 1px var(--tui-background-neutral-1);
}
}
`,
],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [TuiButtonModule, TuiLabelModule],
imports: [TuiButton, TuiLabel, TuiTitle],
})
export class ServicePropertyComponent {
@Input()

View File

@@ -1,3 +1,4 @@
import { TuiLoader, TuiIcon } from '@taiga-ui/core'
import { CommonModule } from '@angular/common'
import {
ChangeDetectionStrategy,
@@ -5,8 +6,6 @@ import {
HostBinding,
Input,
} from '@angular/core'
import { TuiLoaderModule } from '@taiga-ui/core'
import { TuiIconModule } from '@taiga-ui/experimental'
import { StatusRendering } from 'src/app/services/pkg-status-rendering.service'
import { InstallingProgressDisplayPipe } from '../pipes/install-progress.pipe'
import { InstallingInfo } from 'src/app/services/patch-db/data-model'
@@ -41,7 +40,7 @@ import { UnitConversionPipesModule } from '@start9labs/shared'
white-space: nowrap;
margin: auto 0;
min-height: 2.75rem;
color: var(--tui-text-02);
color: var(--tui-text-secondary);
}
tui-loader {
@@ -52,7 +51,7 @@ import { UnitConversionPipesModule } from '@start9labs/shared'
div {
font-size: 1rem;
color: var(--tui-text-02);
color: var(--tui-text-secondary);
margin: 1rem 0;
}
`,
@@ -63,8 +62,8 @@ import { UnitConversionPipesModule } from '@start9labs/shared'
CommonModule,
InstallingProgressDisplayPipe,
UnitConversionPipesModule,
TuiIconModule,
TuiLoaderModule,
TuiIcon,
TuiLoader,
],
})
export class ServiceStatusComponent {
@@ -98,19 +97,19 @@ export class ServiceStatusComponent {
}
get icon(): string {
if (!this.connected) return 'tuiIconCircle'
if (!this.connected) return '@tui.circle'
switch (this.rendering.color) {
case 'danger':
return 'tuiIconXCircle'
return '@tui.circle-x'
case 'warning':
return 'tuiIconAlertCircle'
return '@tui.circle-alert'
case 'success':
return 'tuiIconCheckCircle'
return '@tui.circle-check'
case 'primary':
return 'tuiIconMinusCircle'
return '@tui.circle-minus'
default:
return 'tuiIconCircle'
return '@tui.circle'
}
}
}

View File

@@ -1,6 +1,5 @@
import { CommonModule } from '@angular/common'
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
import { TuiSvgModule } from '@taiga-ui/core'
import { TuiIcon } from '@taiga-ui/core'
import {
AdditionalItem,
FALLBACK_URL,
@@ -13,7 +12,9 @@ import {
<strong>{{ additionalItem.name }}</strong>
<div>{{ additionalItem.description }}</div>
</div>
<tui-svg *ngIf="icon" [src]="icon"></tui-svg>
@if (icon) {
<tui-icon [icon]="icon" />
}
`,
styles: [
`
@@ -32,7 +33,7 @@ import {
},
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [CommonModule, TuiSvgModule],
imports: [TuiIcon],
})
export class ServiceAdditionalItemComponent {
@Input({ required: true })
@@ -44,7 +45,7 @@ export class ServiceAdditionalItemComponent {
get icon(): string | undefined {
return this.additionalItem.description.startsWith('http')
? 'tuiIconExternalLinkLarge'
? '@tui.external-link'
: this.additionalItem.icon
}
}

View File

@@ -5,7 +5,7 @@ import {
Input,
} from '@angular/core'
import { TuiDialogOptions } from '@taiga-ui/core'
import { POLYMORPHEUS_CONTEXT } from '@tinkoff/ng-polymorpheus'
import { POLYMORPHEUS_CONTEXT } from '@taiga-ui/polymorpheus'
import { PackageDataEntry } from 'src/app/services/patch-db/data-model'
import { ToAdditionalPipe } from 'src/app/routes/portal/routes/service/pipes/to-additional.pipe'
import { ServiceAdditionalItemComponent } from './additional-item.component'

View File

@@ -1,9 +1,8 @@
import { TuiLoader, TuiButton } from '@taiga-ui/core'
import { CommonModule } from '@angular/common'
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
import { ErrorService } from '@start9labs/shared'
import { TuiLoaderModule } from '@taiga-ui/core'
import { TuiButtonModule } from '@taiga-ui/experimental'
import { POLYMORPHEUS_CONTEXT } from '@tinkoff/ng-polymorpheus'
import { POLYMORPHEUS_CONTEXT } from '@taiga-ui/polymorpheus'
import { BehaviorSubject } from 'rxjs'
import { ApiService } from 'src/app/services/api/embassy-api.service'
import { ServicePropertyComponent } from '../components/property.component'
@@ -19,7 +18,7 @@ import { ServicePropertyComponent } from '../components/property.component'
No properties
}
}
<button tuiButton iconLeft="tuiIconRefreshCwLarge" (click)="refresh()">
<button tuiButton iconStart="@tui.refresh-cw" (click)="refresh()">
Refresh
</button>
`,
@@ -33,12 +32,7 @@ import { ServicePropertyComponent } from '../components/property.component'
],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [
CommonModule,
TuiButtonModule,
ServicePropertyComponent,
TuiLoaderModule,
],
imports: [CommonModule, TuiButton, ServicePropertyComponent, TuiLoader],
})
export class ServicePropertiesModal {
private readonly api = inject(ApiService)

View File

@@ -23,18 +23,18 @@ export class InterfaceInfoPipe implements PipeTransform {
switch (val.type) {
case 'ui':
color = 'var(--tui-primary)'
icon = 'tuiIconMonitor'
color = 'var(--tui-background-accent-1)'
icon = '@tui.monitor'
typeDetail = 'User Interface (UI)'
break
case 'p2p':
color = 'var(--tui-info-fill)'
icon = 'tuiIconUsers'
color = 'var(--tui-status-info)'
icon = '@tui.users'
typeDetail = 'Peer-To-Peer Interface (P2P)'
break
case 'api':
color = 'var(--tui-support-09)'
icon = 'tuiIconTerminal'
color = 'var(--tui-chart-categorical-09)'
icon = '@tui.terminal'
typeDetail = 'Application Program Interface (API)'
break
}

View File

@@ -2,7 +2,7 @@ import { inject, Pipe, PipeTransform } from '@angular/core'
import { CopyService, MarkdownComponent } from '@start9labs/shared'
import { T } from '@start9labs/start-sdk'
import { TuiDialogService } from '@taiga-ui/core'
import { PolymorpheusComponent } from '@tinkoff/ng-polymorpheus'
import { PolymorpheusComponent } from '@taiga-ui/polymorpheus'
import { from } from 'rxjs'
import { ApiService } from 'src/app/services/api/embassy-api.service'
import { PackageDataEntry } from 'src/app/services/patch-db/data-model'
@@ -39,14 +39,14 @@ export class ToAdditionalPipe implements PipeTransform {
{
name: 'Git Hash',
description: manifest.gitHash || 'Unknown',
icon: manifest.gitHash ? 'tuiIconCopyLarge' : '',
icon: manifest.gitHash ? '@tui.copy' : '',
action: () =>
manifest.gitHash && this.copyService.copy(manifest.gitHash),
},
{
name: 'License',
description: manifest.license,
icon: 'tuiIconChevronRightLarge',
icon: '@tui.chevron-right',
action: () => this.showLicense(manifest),
},
{

View File

@@ -3,7 +3,7 @@ import { Params } from '@angular/router'
import { MarkdownComponent } from '@start9labs/shared'
import { T } from '@start9labs/start-sdk'
import { TuiDialogService } from '@taiga-ui/core'
import { PolymorpheusComponent } from '@tinkoff/ng-polymorpheus'
import { PolymorpheusComponent } from '@taiga-ui/polymorpheus'
import { from } from 'rxjs'
import {
ConfigModal,
@@ -41,19 +41,19 @@ export class ToMenuPipe implements PipeTransform {
return [
{
icon: 'tuiIconList',
icon: '@tui.list',
name: 'Instructions',
description: `Understand how to use ${manifest.title}`,
action: () => this.showInstructions(manifest),
},
{
icon: 'tuiIconSliders',
icon: '@tui.sliders-vertical',
name: 'Config',
description: `Customize ${manifest.title}`,
action: () => this.openConfig(manifest),
},
{
icon: 'tuiIconKey',
icon: '@tui.key',
name: 'Properties',
description: `Runtime information, credentials, and other values of interest`,
action: () =>
@@ -65,13 +65,13 @@ export class ToMenuPipe implements PipeTransform {
.subscribe(),
},
{
icon: 'tuiIconZap',
icon: '@tui.zap',
name: 'Actions',
description: `Uninstall and other commands specific to ${manifest.title}`,
routerLink: `actions`,
},
{
icon: 'tuiIconShield',
icon: '@tui.shield',
name: 'Outbound Proxy',
description: `Proxy all outbound traffic from ${manifest.title}`,
action: () =>
@@ -81,13 +81,13 @@ export class ToMenuPipe implements PipeTransform {
),
},
{
icon: 'tuiIconFileText',
icon: '@tui.file-text',
name: 'Logs',
description: `Raw, unfiltered logs`,
routerLink: 'logs',
},
{
icon: 'tuiIconInfo',
icon: '@tui.info',
name: 'Additional Info',
description: `View package details`,
action: () =>
@@ -100,14 +100,14 @@ export class ToMenuPipe implements PipeTransform {
},
pkg.marketplaceUrl
? {
icon: 'tuiIconShoppingBag',
icon: '@tui.shopping-bag',
name: 'Marketplace Listing',
description: `View ${manifest.title} on the Marketplace`,
routerLink: `/portal/system/marketplace`,
params: { url: pkg.marketplaceUrl, id: manifest.id },
}
: {
icon: 'tuiIconShoppingBag',
icon: '@tui.shopping-bag',
name: 'Marketplace Listing',
description: `This package was not installed from the marketplace`,
},

View File

@@ -1,3 +1,4 @@
import { TUI_CONFIRM } from '@taiga-ui/kit'
import { CommonModule } from '@angular/common'
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
import { ActivatedRoute, Router } from '@angular/router'
@@ -9,8 +10,7 @@ import {
getPkgId,
} from '@start9labs/shared'
import { TuiDialogService } from '@taiga-ui/core'
import { TUI_PROMPT } from '@taiga-ui/kit'
import { PolymorpheusComponent } from '@tinkoff/ng-polymorpheus'
import { PolymorpheusComponent } from '@taiga-ui/polymorpheus'
import { PatchDB } from 'patch-db-client'
import { filter, switchMap, timer } from 'rxjs'
import { FormComponent } from 'src/app/routes/portal/components/form.component'
@@ -50,7 +50,7 @@ import { getAllPackages, getManifest } from 'src/app/utils/get-package-data'
[action]="{
name: action.name,
description: action.description,
icon: 'tuiIconPlayCircle'
icon: '@tui.circle-play'
}"
(click)="handleAction(action)"
></button>
@@ -75,7 +75,7 @@ export class ServiceActionsRoute {
.pipe(filter(pkg => pkg.stateInfo.state === 'installed'))
readonly action = {
icon: 'tuiIconTrash2',
icon: '@tui.trash-2',
name: 'Uninstall',
description:
'This will uninstall the service from StartOS and delete all data permanently.',
@@ -116,7 +116,7 @@ export class ServiceActionsRoute {
})
} else {
this.dialogs
.open(TUI_PROMPT, {
.open(TUI_CONFIRM, {
label: 'Confirm',
size: 's',
data: {
@@ -145,7 +145,7 @@ export class ServiceActionsRoute {
}
this.dialogs
.open(TUI_PROMPT, {
.open(TUI_CONFIRM, {
label: 'Warning',
size: 's',
data: {

View File

@@ -128,8 +128,8 @@ import { DependencyInfo } from '../types/dependency-info'
width: 100%;
padding: 1rem 1.5rem 0.5rem;
border-radius: 0.5rem;
background: var(--tui-clear);
box-shadow: inset 0 7rem 0 -4rem var(--tui-clear);
background: var(--tui-background-neutral-1);
box-shadow: inset 0 7rem 0 -4rem var(--tui-background-neutral-1);
clip-path: polygon(0 1.5rem, 1.5rem 0, 100% 0, 100% 100%, 0 100%);
}

View File

@@ -1,6 +1,5 @@
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
import { TuiDialogService } from '@taiga-ui/core'
import { TuiIconModule } from '@taiga-ui/experimental'
import { TuiDialogService, TuiIcon } from '@taiga-ui/core'
import { BackupsUpcomingComponent } from './components/upcoming.component'
import { HISTORY } from './modals/history.component'
import { JOBS } from './modals/jobs.component'
@@ -28,7 +27,7 @@ import { BackupsRestoreService } from './services/restore.service'
host: { class: 'g-page' },
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [BackupsUpcomingComponent, TuiIconModule],
imports: [BackupsUpcomingComponent, TuiIcon],
})
export default class BackupsComponent {
private readonly dialogs = inject(TuiDialogService)
@@ -36,19 +35,19 @@ export default class BackupsComponent {
readonly options = [
{
name: 'Create a Backup',
icon: 'tuiIconPlusLarge',
icon: '@tui.plus',
description: 'Create a one-time backup',
action: inject(BackupsCreateService).handle,
},
{
name: 'Restore from Backup',
icon: 'tuiIconShareLarge',
icon: '@tui.share',
description: 'Restore services from a backup',
action: inject(BackupsRestoreService).handle,
},
{
name: 'Jobs',
icon: 'tuiIconToolLarge',
icon: '@tui.wrench',
description: 'Manage backup jobs',
action: () =>
this.dialogs
@@ -57,7 +56,7 @@ export default class BackupsComponent {
},
{
name: 'Targets',
icon: 'tuiIconDatabaseLarge',
icon: '@tui.database',
description: 'Manage backup targets',
action: () =>
this.dialogs
@@ -66,7 +65,7 @@ export default class BackupsComponent {
},
{
name: 'History',
icon: 'tuiIconArchiveLarge',
icon: '@tui.archive',
description: 'View your entire backup history',
action: () =>
this.dialogs

View File

@@ -1,4 +1,3 @@
import { CommonModule } from '@angular/common'
import {
ChangeDetectionStrategy,
Component,
@@ -6,10 +5,8 @@ import {
Input,
Output,
} from '@angular/core'
import { TuiForModule } from '@taiga-ui/cdk'
import { TuiSvgModule } from '@taiga-ui/core'
import { TuiButtonModule } from '@taiga-ui/experimental'
import { UnitConversionPipesModule } from '@start9labs/shared'
import { TuiButton } from '@taiga-ui/core'
import { UnknownDisk } from 'src/app/services/api/api.types'
@Component({
@@ -40,7 +37,7 @@ import { UnknownDisk } from 'src/app/services/api/api.types'
<button
tuiButton
size="xs"
iconLeft="tuiIconPlus"
iconStart="@tui.plus"
(click)="add.emit(disk)"
>
Save
@@ -76,7 +73,7 @@ import { UnknownDisk } from 'src/app/services/api/api.types'
.model {
order: 1;
white-space: nowrap;
color: var(--tui-text-02);
color: var(--tui-text-secondary);
}
.actions {
@@ -112,7 +109,7 @@ import { UnknownDisk } from 'src/app/services/api/api.types'
`,
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [TuiButtonModule, UnitConversionPipesModule],
imports: [TuiButton, UnitConversionPipesModule],
})
export class BackupsPhysicalComponent {
@Input()

View File

@@ -5,20 +5,20 @@ import {
Input,
} from '@angular/core'
import { Emver } from '@start9labs/shared'
import { TuiSvgModule } from '@taiga-ui/core'
import { TuiIcon } from '@taiga-ui/core'
import { BackupTarget } from 'src/app/services/api/api.types'
import { BackupType } from '../types/backup-type'
@Component({
selector: 'backups-status',
template: `
<tui-svg [src]="status.icon" [style.color]="status.color"></tui-svg>
<tui-icon [icon]="status.icon" [style.color]="status.color" />
{{ status.text }}
`,
styles: [':host { display: flex; gap: 0.5rem; align-items: center }'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [TuiSvgModule],
imports: [TuiIcon],
})
export class BackupsStatusComponent {
private readonly emver = inject(Emver)
@@ -29,16 +29,16 @@ export class BackupsStatusComponent {
get status() {
if (!this.target.mountable) {
return {
icon: 'tuiIconBarChartLarge',
color: 'var(--tui-negative)',
icon: '@tui.bar-chart',
color: 'var(--tui-text-negative)',
text: 'Unable to connect',
}
}
if (this.type === 'create') {
return {
icon: 'tuiIconCloudLarge',
color: 'var(--tui-positive)',
icon: '@tui.cloud',
color: 'var(--tui-text-positive)',
text: this.hasBackup
? 'Available, contains existing backup'
: 'Available for fresh backup',
@@ -47,15 +47,15 @@ export class BackupsStatusComponent {
if (this.hasBackup) {
return {
icon: 'tuiIconCloudLarge',
color: 'var(--tui-positive)',
icon: '@tui.cloud',
color: 'var(--tui-text-positive)',
text: 'Embassy backup detected',
}
}
return {
icon: 'tuiIconCloudOffLarge',
color: 'var(--tui-negative)',
icon: '@tui.cloud-off',
color: 'var(--tui-text-negative)',
text: 'No Embassy backup',
}
}

View File

@@ -6,9 +6,13 @@ import {
Input,
Output,
} from '@angular/core'
import { TuiDialogOptions, TuiDialogService } from '@taiga-ui/core'
import { TuiButtonModule, TuiIconModule } from '@taiga-ui/experimental'
import { TUI_PROMPT, TuiPromptData } from '@taiga-ui/kit'
import {
TuiDialogOptions,
TuiDialogService,
TuiIcon,
TuiButton,
} from '@taiga-ui/core'
import { TuiConfirmData, TUI_CONFIRM } from '@taiga-ui/kit'
import { filter, map, Subject, switchMap } from 'rxjs'
import { BackupTarget } from 'src/app/services/api/api.types'
import { GetBackupIconPipe } from '../pipes/get-backup-icon.pipe'
@@ -35,7 +39,7 @@ import { GetBackupIconPipe } from '../pipes/get-backup-icon.pipe'
</td>
<td class="available">
<tui-icon
[icon]="target.mountable ? 'tuiIconCheck' : 'tuiIconClose'"
[icon]="target.mountable ? '@tui.check' : '@tui.x'"
[class]="target.mountable ? 'g-success' : 'g-error'"
/>
</td>
@@ -45,7 +49,7 @@ import { GetBackupIconPipe } from '../pipes/get-backup-icon.pipe'
tuiIconButton
size="xs"
appearance="icon"
iconLeft="tuiIconEdit2"
iconStart="@tui.pencil"
(click)="update.emit(target)"
>
Update
@@ -54,7 +58,7 @@ import { GetBackupIconPipe } from '../pipes/get-backup-icon.pipe'
tuiIconButton
size="xs"
appearance="icon"
iconLeft="tuiIconTrash2"
iconStart="@tui.trash-2"
(click)="delete$.next(target.id)"
>
Delete
@@ -93,7 +97,7 @@ import { GetBackupIconPipe } from '../pipes/get-backup-icon.pipe'
.type {
order: 1;
text-transform: capitalize;
color: var(--tui-text-02);
color: var(--tui-text-secondary);
grid-column: span 3;
tui-icon {
@@ -119,7 +123,7 @@ import { GetBackupIconPipe } from '../pipes/get-backup-icon.pipe'
.path {
order: 5;
color: var(--tui-text-03);
color: var(--tui-text-tertiary);
grid-column: span 2;
overflow: hidden;
text-overflow: ellipsis;
@@ -128,7 +132,7 @@ import { GetBackupIconPipe } from '../pipes/get-backup-icon.pipe'
`,
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [TuiButtonModule, GetBackupIconPipe, TuiIconModule],
imports: [TuiButton, GetBackupIconPipe, TuiIcon],
})
export class BackupsTargetsComponent {
private readonly dialogs = inject(TuiDialogService)
@@ -144,7 +148,7 @@ export class BackupsTargetsComponent {
@Output()
readonly delete = this.delete$.pipe(
switchMap(id =>
this.dialogs.open(TUI_PROMPT, OPTIONS).pipe(
this.dialogs.open(TUI_CONFIRM, OPTIONS).pipe(
filter(Boolean),
map(() => id),
),
@@ -152,7 +156,7 @@ export class BackupsTargetsComponent {
)
}
const OPTIONS: Partial<TuiDialogOptions<TuiPromptData>> = {
const OPTIONS: Partial<TuiDialogOptions<TuiConfirmData>> = {
label: 'Confirm',
size: 's',
data: {

View File

@@ -1,7 +1,7 @@
import { TuiIcon } from '@taiga-ui/core'
import { DatePipe } from '@angular/common'
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
import { toSignal } from '@angular/core/rxjs-interop'
import { TuiIconModule } from '@taiga-ui/experimental'
import { CronJob } from 'cron'
import { PatchDB } from 'patch-db-client'
import { from, map } from 'rxjs'
@@ -26,7 +26,7 @@ import { GetBackupIconPipe } from '../pipes/get-backup-icon.pipe'
<tr>
<td class="date">
@if (current.id === job.id) {
<span [style.color]="'var(--tui-positive)'">Running</span>
<span [style.color]="'var(--tui-text-positive)'">Running</span>
} @else {
{{ job.next | date: 'medium' }}
}
@@ -76,7 +76,7 @@ import { GetBackupIconPipe } from '../pipes/get-backup-icon.pipe'
:host-context(tui-root._mobile) {
.date {
color: var(--tui-text-02);
color: var(--tui-text-secondary);
}
.name {
@@ -91,7 +91,7 @@ import { GetBackupIconPipe } from '../pipes/get-backup-icon.pipe'
`,
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [GetBackupIconPipe, DatePipe, TuiIconModule],
imports: [GetBackupIconPipe, DatePipe, TuiIcon],
})
export class BackupsUpcomingComponent {
readonly current = toSignal(

View File

@@ -1,19 +1,17 @@
import { CommonModule } from '@angular/common'
import { Component, inject } from '@angular/core'
import { FormsModule } from '@angular/forms'
import { TuiForModule } from '@taiga-ui/cdk'
import {
TuiButton,
TuiDialogContext,
TuiDialogOptions,
TuiGroupModule,
TuiLoaderModule,
TuiGroup,
TuiLoader,
} from '@taiga-ui/core'
import { TuiButtonModule } from '@taiga-ui/experimental'
import { TuiCheckboxBlockModule } from '@taiga-ui/kit'
import { TuiBlock, TuiCheckbox } from '@taiga-ui/kit'
import {
POLYMORPHEUS_CONTEXT,
PolymorpheusComponent,
} from '@tinkoff/ng-polymorpheus'
} from '@taiga-ui/polymorpheus'
import { PatchDB } from 'patch-db-client'
import { firstValueFrom, map } from 'rxjs'
import { DataModel } from 'src/app/services/patch-db/data-model'
@@ -29,27 +27,35 @@ interface Package {
@Component({
template: `
<div tuiGroup orientation="vertical">
<tui-checkbox-block
*ngFor="let pkg of pkgs; else: loading; empty: blank"
[disabled]="pkg.disabled"
[(ngModel)]="pkg.checked"
(ngModelChange)="handleChange()"
>
<div class="g-action">
<img class="icon" alt="" [src]="pkg.icon" />
{{ pkg.title }}
</div>
</tui-checkbox-block>
<ng-template #loading><tui-loader></tui-loader></ng-template>
<ng-template #blank>No services installed!</ng-template>
<div tuiGroup orientation="vertical" [collapsed]="true">
@if (pkgs) {
@for (pkg of pkgs; track $index) {
<label tuiBlock>
<div class="g-action">
<img class="icon" alt="" [src]="pkg.icon" />
{{ pkg.title }}
</div>
<input
type="checkbox"
tuiCheckbox
[disabled]="pkg.disabled"
[(ngModel)]="pkg.checked"
(ngModelChange)="handleChange()"
/>
</label>
} @empty {
No services installed!
}
} @else {
<tui-loader />
}
</div>
<footer class="g-buttons">
<button tuiButton appearance="flat" (click)="toggleSelectAll()">
Toggle all
</button>
<button tuiButton [disabled]="!hasSelection" (click)="done()">
{{ context.data.btnText || 'Done' }}
{{ context.data?.btnText || 'Done' }}
</button>
</footer>
`,
@@ -68,20 +74,12 @@ interface Package {
`,
],
standalone: true,
imports: [
CommonModule,
FormsModule,
TuiForModule,
TuiButtonModule,
TuiGroupModule,
TuiCheckboxBlockModule,
TuiLoaderModule,
],
imports: [FormsModule, TuiButton, TuiGroup, TuiLoader, TuiBlock, TuiCheckbox],
})
export class BackupsBackupModal {
private readonly patch = inject(PatchDB<DataModel>)
readonly context =
inject<TuiDialogContext<string[], { btnText: string }>>(
inject<TuiDialogContext<string[], { btnText: string } | undefined>>(
POLYMORPHEUS_CONTEXT,
)

View File

@@ -1,22 +1,18 @@
import {
TuiWrapperModule,
TuiInputModule,
TuiInputNumberModule,
} from '@taiga-ui/legacy'
import { CommonModule } from '@angular/common'
import { Component, inject } from '@angular/core'
import { FormsModule } from '@angular/forms'
import { ErrorService, LoadingService } from '@start9labs/shared'
import {
TuiDialogContext,
TuiDialogService,
TuiWrapperModule,
} from '@taiga-ui/core'
import { TuiBadgeModule, TuiButtonModule } from '@taiga-ui/experimental'
import {
TuiInputModule,
TuiInputNumberModule,
TuiToggleModule,
} from '@taiga-ui/kit'
import { TuiDialogContext, TuiDialogService, TuiButton } from '@taiga-ui/core'
import { TuiBadge, TuiSwitch } from '@taiga-ui/kit'
import {
POLYMORPHEUS_CONTEXT,
PolymorpheusComponent,
} from '@tinkoff/ng-polymorpheus'
} from '@taiga-ui/polymorpheus'
import { ApiService } from 'src/app/services/api/embassy-api.service'
import { BackupJob, BackupTarget } from 'src/app/services/api/api.types'
import { TARGET, TARGET_CREATE } from './target.component'
@@ -29,7 +25,7 @@ import { ToHumanCronPipe } from '../pipes/to-human-cron.pipe'
<form class="form">
<tui-input name="name" [(ngModel)]="job.name">
Job Name
<input tuiTextfield placeholder="My Backup Job" />
<input tuiTextfieldLegacy placeholder="My Backup Job" />
</tui-input>
<button
tuiButton
@@ -59,14 +55,14 @@ import { ToHumanCronPipe } from '../pipes/to-human-cron.pipe'
</button>
<tui-input name="cron" [(ngModel)]="job.cron">
Schedule
<input tuiTextfield placeholder="* * * * *" />
<input tuiTextfieldLegacy placeholder="* * * * *" />
</tui-input>
<div *ngIf="job.cron | toHumanCron as human" [style.color]="human.color">
{{ human.message }}
</div>
<div *ngIf="!job.job.id" class="g-toggle">
Also Execute Now
<tui-toggle size="l" name="now" [(ngModel)]="job.now"></tui-toggle>
<input tuiSwitch type="checkbox" name="now" [(ngModel)]="job.now" />
</div>
<button
tuiButton
@@ -100,10 +96,10 @@ import { ToHumanCronPipe } from '../pipes/to-human-cron.pipe'
FormsModule,
TuiInputModule,
TuiInputNumberModule,
TuiToggleModule,
TuiSwitch,
TuiWrapperModule,
TuiButtonModule,
TuiBadgeModule,
TuiButton,
TuiBadge,
ToHumanCronPipe,
],
})

View File

@@ -1,3 +1,4 @@
import { TuiCheckbox } from '@taiga-ui/kit'
import { CommonModule } from '@angular/common'
import {
ChangeDetectionStrategy,
@@ -7,14 +8,9 @@ import {
} from '@angular/core'
import { FormsModule } from '@angular/forms'
import { ErrorService, LoadingService } from '@start9labs/shared'
import { ALWAYS_FALSE_HANDLER, ALWAYS_TRUE_HANDLER } from '@taiga-ui/cdk'
import { TuiDialogService, TuiLinkModule } from '@taiga-ui/core'
import {
TuiButtonModule,
TuiCheckboxModule,
TuiIconModule,
} from '@taiga-ui/experimental'
import { PolymorpheusComponent } from '@tinkoff/ng-polymorpheus'
import { TUI_TRUE_HANDLER, TUI_FALSE_HANDLER } from '@taiga-ui/cdk'
import { TuiDialogService, TuiIcon, TuiLink, TuiButton } from '@taiga-ui/core'
import { PolymorpheusComponent } from '@taiga-ui/polymorpheus'
import { REPORT } from 'src/app/components/report.component'
import { BackupRun } from 'src/app/services/api/api.types'
import { ApiService } from 'src/app/services/api/embassy-api.service'
@@ -73,9 +69,9 @@ import { HasErrorPipe } from '../pipes/has-error.pipe'
<td class="title">{{ run.job.name || 'No job' }}</td>
<td class="result">
@if (run.report | hasError) {
<tui-icon icon="tuiIconClose" class="g-error" />
<tui-icon icon="@tui.x" class="g-error" />
} @else {
<tui-icon icon="tuiIconCheck" class="g-success" />
<tui-icon icon="@tui.check" class="g-success" />
}
<button tuiLink (click)="showReport(run)">Report</button>
</td>
@@ -141,7 +137,7 @@ import { HasErrorPipe } from '../pipes/has-error.pipe'
.date,
.duration {
order: 1;
color: var(--tui-text-02);
color: var(--tui-text-secondary);
}
.duration,
@@ -155,13 +151,13 @@ import { HasErrorPipe } from '../pipes/has-error.pipe'
imports: [
CommonModule,
FormsModule,
TuiButtonModule,
TuiIconModule,
TuiLinkModule,
TuiButton,
TuiIcon,
TuiLink,
DurationPipe,
HasErrorPipe,
GetBackupIconPipe,
TuiCheckboxModule,
TuiCheckbox,
],
})
export class BackupsHistoryModal {
@@ -194,7 +190,7 @@ export class BackupsHistoryModal {
async ngOnInit() {
try {
this.runs.set(await this.api.getBackupRuns({}))
this.selected = this.runs()?.map(ALWAYS_FALSE_HANDLER) || []
this.selected = this.runs()?.map(TUI_FALSE_HANDLER) || []
} catch (e: any) {
this.runs.set([])
this.errorService.handleError(e)
@@ -210,7 +206,7 @@ export class BackupsHistoryModal {
try {
await this.api.deleteBackupRuns({ ids })
this.runs.set(this.runs()?.filter(r => !ids.includes(r.id)) || [])
this.selected = this.runs()?.map(ALWAYS_FALSE_HANDLER) || []
this.selected = this.runs()?.map(TUI_FALSE_HANDLER) || []
} catch (e: any) {
this.errorService.handleError(e)
} finally {
@@ -232,9 +228,9 @@ export class BackupsHistoryModal {
toggle() {
if (this.all) {
this.selected = this.selected.map(ALWAYS_FALSE_HANDLER)
this.selected = this.selected.map(TUI_FALSE_HANDLER)
} else {
this.selected = this.selected.map(ALWAYS_TRUE_HANDLER)
this.selected = this.selected.map(TUI_TRUE_HANDLER)
}
}
}

View File

@@ -3,11 +3,12 @@ import { ErrorService, LoadingService } from '@start9labs/shared'
import {
TuiDialogOptions,
TuiDialogService,
TuiNotificationModule,
TuiIcon,
TuiButton,
TuiNotification,
} from '@taiga-ui/core'
import { TuiButtonModule, TuiIconModule } from '@taiga-ui/experimental'
import { TUI_PROMPT, TuiPromptData } from '@taiga-ui/kit'
import { PolymorpheusComponent } from '@tinkoff/ng-polymorpheus'
import { TuiConfirmData, TUI_CONFIRM } from '@taiga-ui/kit'
import { PolymorpheusComponent } from '@taiga-ui/polymorpheus'
import { BehaviorSubject, filter } from 'rxjs'
import { BackupJob } from 'src/app/services/api/api.types'
import { ApiService } from 'src/app/services/api/embassy-api.service'
@@ -32,7 +33,7 @@ import { EDIT } from './edit.component'
</tui-notification>
<h3 class="g-title">
Saved Jobs
<button tuiButton size="s" iconLeft="tuiIconPlus" (click)="create()">
<button tuiButton size="s" iconStart="@tui.plus" (click)="create()">
Create New Job
</button>
</h3>
@@ -61,14 +62,14 @@ import { EDIT } from './edit.component'
tuiIconButton
appearance="icon"
size="xs"
iconLeft="tuiIconEdit2"
iconStart="@tui.pencil"
(click)="update(job)"
></button>
<button
tuiIconButton
appearance="icon"
size="xs"
iconLeft="tuiIconTrash2"
iconStart="@tui.trash-2"
(click)="delete(job.id)"
></button>
</td>
@@ -126,15 +127,15 @@ import { EDIT } from './edit.component'
.schedule {
order: 5;
color: var(--tui-text-02);
color: var(--tui-text-secondary);
}
}
`,
standalone: true,
imports: [
TuiNotificationModule,
TuiButtonModule,
TuiIconModule,
TuiNotification,
TuiButton,
TuiIcon,
ToHumanCronPipe,
GetBackupIconPipe,
],
@@ -188,7 +189,7 @@ export class BackupsJobsModal implements OnInit {
delete(id: string) {
this.dialogs
.open(TUI_PROMPT, PROMPT_OPTIONS)
.open(TUI_CONFIRM, PROMPT_OPTIONS)
.pipe(filter(Boolean))
.subscribe(async () => {
const loader = this.loader.open('Deleting...').subscribe()
@@ -205,7 +206,7 @@ export class BackupsJobsModal implements OnInit {
}
}
const PROMPT_OPTIONS: Partial<TuiDialogOptions<TuiPromptData>> = {
const PROMPT_OPTIONS: Partial<TuiDialogOptions<TuiConfirmData>> = {
label: 'Confirm',
size: 's',
data: {

View File

@@ -2,44 +2,52 @@ import { CommonModule } from '@angular/common'
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
import { FormsModule } from '@angular/forms'
import { ErrorService, LoadingService } from '@start9labs/shared'
import { TuiDialogContext, TuiGroupModule } from '@taiga-ui/core'
import { TuiButtonModule } from '@taiga-ui/experimental'
import { TuiCheckboxBlockModule } from '@taiga-ui/kit'
import { TuiMapperPipe } from '@taiga-ui/cdk'
import { TuiButton, TuiDialogContext, TuiGroup } from '@taiga-ui/core'
import { TuiBlock, TuiCheckbox } from '@taiga-ui/kit'
import {
POLYMORPHEUS_CONTEXT,
PolymorpheusComponent,
} from '@tinkoff/ng-polymorpheus'
} from '@taiga-ui/polymorpheus'
import { PatchDB } from 'patch-db-client'
import { take } from 'rxjs'
import { PackageBackupInfo } from 'src/app/services/api/api.types'
import { ApiService } from 'src/app/services/api/embassy-api.service'
import { DataModel } from 'src/app/services/patch-db/data-model'
import { PackageBackupInfo } from 'src/app/services/api/api.types'
import { ToOptionsPipe } from '../pipes/to-options.pipe'
import { RecoverOption } from '../types/recover-option'
import { RecoverData } from '../types/recover-data'
import { TuiMapperPipeModule } from '@taiga-ui/cdk'
import { RecoverOption } from '../types/recover-option'
@Component({
template: `
<ng-container *ngIf="packageData$ | toOptions: backups | async as options">
<div tuiGroup orientation="vertical" [style.width.%]="100">
<tui-checkbox-block
*ngFor="let option of options"
[disabled]="option.installed || option.newerStartOs"
[(ngModel)]="option.checked"
>
<div [style.margin]="'0.75rem 0'">
<strong>{{ option.title }}</strong>
<div>Version {{ option.version }}</div>
<div>Backup made: {{ option.timestamp | date: 'medium' }}</div>
<div
*ngIf="option | tuiMapper: toMessage as message"
[style.color]="message.color"
>
{{ message.text }}
<div
tuiGroup
orientation="vertical"
[collapsed]="true"
[style.width.%]="100"
>
@for (option of options; track $index) {
<label tuiBlock>
<div [style.flex]="1" [style.margin]="'0.75rem 0'">
<strong>{{ option.title }}</strong>
<div>Version {{ option.version }}</div>
<div>Backup made: {{ option.timestamp | date: 'medium' }}</div>
<div
*ngIf="option | tuiMapper: toMessage as message"
[style.color]="message.color"
>
{{ message.text }}
</div>
</div>
</div>
</tui-checkbox-block>
<input
type="checkbox"
tuiCheckbox
[disabled]="option.installed || option.newerStartOs"
[(ngModel)]="option.checked"
/>
</label>
}
</div>
<footer class="g-buttons">
@@ -59,10 +67,11 @@ import { TuiMapperPipeModule } from '@taiga-ui/cdk'
CommonModule,
FormsModule,
ToOptionsPipe,
TuiButtonModule,
TuiCheckboxBlockModule,
TuiGroupModule,
TuiMapperPipeModule,
TuiButton,
TuiGroup,
TuiMapperPipe,
TuiCheckbox,
TuiBlock,
],
})
export class BackupsRecoverModal {
@@ -80,20 +89,20 @@ export class BackupsRecoverModal {
if (option.newerStartOs) {
return {
text: `Unavailable. Backup was made on a newer version of StartOS.`,
color: 'var(--tui-error-fill)',
color: 'var(--tui-status-negative)',
}
}
if (option.installed) {
return {
text: `Unavailable. ${option.title} is already installed.`,
color: 'var(--tui-warning-fill)',
color: 'var(--tui-status-warning)',
}
}
return {
text: 'Ready to restore',
color: 'var(--tui-success-fill)',
color: 'var(--tui-status-positive)',
}
}

View File

@@ -1,72 +1,66 @@
import { CommonModule } from '@angular/common'
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
import { ErrorService } from '@start9labs/shared'
import { TuiForModule } from '@taiga-ui/cdk'
import { TuiButtonModule } from '@taiga-ui/experimental'
import {
ChangeDetectionStrategy,
Component,
inject,
signal,
} from '@angular/core'
import { ErrorService } from '@start9labs/shared'
import {
TuiButton,
TuiDialogContext,
TuiDialogOptions,
TuiDialogService,
TuiLoaderModule,
TuiSvgModule,
TuiIcon,
TuiLoader,
} from '@taiga-ui/core'
import {
POLYMORPHEUS_CONTEXT,
PolymorpheusComponent,
} from '@tinkoff/ng-polymorpheus'
import { BehaviorSubject } from 'rxjs'
} from '@taiga-ui/polymorpheus'
import { BackupTarget } from 'src/app/services/api/api.types'
import { ApiService } from 'src/app/services/api/embassy-api.service'
import { BackupType } from '../types/backup-type'
import { BackupsStatusComponent } from '../components/status.component'
import { GetDisplayInfoPipe } from '../pipes/get-display-info.pipe'
import { BackupType } from '../types/backup-type'
import { TARGETS } from './targets.component'
@Component({
template: `
<tui-loader
*ngIf="loading$ | async; else loaded"
size="l"
[textContent]="loading"
></tui-loader>
<ng-template #loaded>
@if (loading()) {
<tui-loader size="l" [textContent]="text" />
} @else {
<h3 class="g-title">Saved Targets</h3>
<button
*ngFor="let target of targets; empty: blank"
class="g-action"
[disabled]="isDisabled(target)"
(click)="context.completeWith(target)"
>
<ng-container *ngIf="target | getDisplayInfo as displayInfo">
<tui-svg [src]="displayInfo.icon"></tui-svg>
<div>
<strong>{{ displayInfo.name }}</strong>
<backups-status
[type]="context.data.type"
[target]="target"
></backups-status>
<div [style.color]="'var(--tui-text-02'">
{{ displayInfo.description }}
<br />
{{ displayInfo.path }}
@for (target of targets; track $index) {
<button
class="g-action"
[disabled]="isDisabled(target)"
(click)="context.completeWith(target)"
>
@if (target | getDisplayInfo; as displayInfo) {
<tui-icon [icon]="displayInfo.icon" />
<div>
<strong>{{ displayInfo.name }}</strong>
<backups-status [type]="context.data.type" [target]="target" />
<div [style.color]="'var(--tui-text-secondary'">
{{ displayInfo.description }}
<br />
{{ displayInfo.path }}
</div>
</div>
</div>
</ng-container>
</button>
<ng-template #blank>
}
</button>
} @empty {
<p>No saved targets</p>
<button tuiButton (click)="goToTargets()">Go to Targets</button>
</ng-template>
</ng-template>
}
}
`,
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [
CommonModule,
TuiLoaderModule,
TuiForModule,
TuiButtonModule,
TuiSvgModule,
TuiLoader,
TuiButton,
TuiIcon,
BackupsStatusComponent,
GetDisplayInfoPipe,
],
@@ -81,8 +75,8 @@ export class BackupsTargetModal {
POLYMORPHEUS_CONTEXT,
)
readonly loading$ = new BehaviorSubject(true)
readonly loading =
readonly loading = signal(true)
readonly text =
this.context.data.type === 'create'
? 'Loading Backup Targets'
: 'Loading Backup Sources'
@@ -95,7 +89,7 @@ export class BackupsTargetModal {
} catch (e: any) {
this.errorService.handleError(e)
} finally {
this.loading$.next(false)
this.loading.set(false)
}
}

Some files were not shown because too many files have changed in this diff Show More