fix: refactor legacy components (#3010)

* fix: comments

* fix: refactor legacy components

* remove default again

---------

Co-authored-by: Matt Hill <mattnine@protonmail.com>
This commit is contained in:
Alex Inkin
2025-08-19 21:13:36 +07:00
committed by GitHub
parent 0709ea65d7
commit 931505ff08
9 changed files with 160 additions and 160 deletions

View File

@@ -14,9 +14,13 @@ import {
TuiDialogContext, TuiDialogContext,
TuiDialogService, TuiDialogService,
TuiError, TuiError,
TuiTextfield,
} from '@taiga-ui/core' } from '@taiga-ui/core'
import { TUI_VALIDATION_ERRORS, TuiFieldErrorPipe } from '@taiga-ui/kit' import {
import { TuiInputModule, TuiInputPasswordModule } from '@taiga-ui/legacy' TUI_VALIDATION_ERRORS,
TuiFieldErrorPipe,
TuiPassword,
} from '@taiga-ui/kit'
import { injectContext, PolymorpheusComponent } from '@taiga-ui/polymorpheus' import { injectContext, PolymorpheusComponent } from '@taiga-ui/polymorpheus'
import { SERVERS, ServersResponse } from 'src/app/components/servers.component' import { SERVERS, ServersResponse } from 'src/app/components/servers.component'
import { ApiService } from 'src/app/services/api.service' import { ApiService } from 'src/app/services/api.service'
@@ -30,39 +34,47 @@ export interface CifsResponse {
@Component({ @Component({
template: ` template: `
<form [formGroup]="form" (ngSubmit)="submit()"> <form [formGroup]="form" (ngSubmit)="submit()">
<tui-input formControlName="hostname"> <tui-textfield>
Hostname * <label tuiLabel>Hostname *</label>
<input <input
tuiTextfieldLegacy tuiTextfield
formControlName="hostname"
placeholder="e.g. 'My Computer' OR 'my-computer.local'" placeholder="e.g. 'My Computer' OR 'my-computer.local'"
/> />
</tui-input> </tui-textfield>
<tui-error <tui-error
formControlName="hostname" formControlName="hostname"
[error]="['required'] | tuiFieldError | async" [error]="['required'] | tuiFieldError | async"
></tui-error> />
<tui-input formControlName="path" class="input"> <tui-textfield class="input">
Path * <label tuiLabel>Path *</label>
<input tuiTextfieldLegacy placeholder="/Desktop/my-folder'" /> <input
</tui-input> tuiTextfield
<tui-error formControlName="path"
formControlName="path" placeholder="/Desktop/my-folder'"
[error]="[] | tuiFieldError | async" />
></tui-error> </tui-textfield>
<tui-error formControlName="path" [error]="[] | tuiFieldError | async" />
<tui-input formControlName="username" class="input"> <tui-textfield class="input">
Username * <label tuiLabel>Username *</label>
<input tuiTextfieldLegacy placeholder="Enter username" /> <input
</tui-input> tuiTextfield
formControlName="username"
placeholder="Enter username"
/>
</tui-textfield>
<tui-error <tui-error
formControlName="username" formControlName="username"
[error]="[] | tuiFieldError | async" [error]="[] | tuiFieldError | async"
></tui-error> />
<tui-input-password formControlName="password" class="input"> <tui-textfield class="input">
Password <label tuiLabel>Password</label>
</tui-input-password> <input tuiTextfield type="password" formControlName="password" />
<tui-icon tuiPassword />
</tui-textfield>
<footer> <footer>
<button <button
@@ -93,8 +105,8 @@ export interface CifsResponse {
FormsModule, FormsModule,
ReactiveFormsModule, ReactiveFormsModule,
TuiButton, TuiButton,
TuiInputModule, TuiTextfield,
TuiInputPasswordModule, TuiPassword,
TuiError, TuiError,
TuiFieldErrorPipe, TuiFieldErrorPipe,
], ],

View File

@@ -1,12 +1,8 @@
import { ChangeDetectionStrategy, Component, Inject } from '@angular/core' import { ChangeDetectionStrategy, Component } from '@angular/core'
import { FormsModule } from '@angular/forms' import { FormsModule } from '@angular/forms'
import { TuiAutoFocus } from '@taiga-ui/cdk' import { TuiAutoFocus } from '@taiga-ui/cdk'
import { TuiButton, TuiDialogContext } from '@taiga-ui/core' import { TuiButton, TuiDialogContext, TuiTextfield } from '@taiga-ui/core'
import { TuiInputModule, TuiTextfieldControllerModule } from '@taiga-ui/legacy' import { injectContext, PolymorpheusComponent } from '@taiga-ui/polymorpheus'
import {
POLYMORPHEUS_CONTEXT,
PolymorpheusComponent,
} from '@taiga-ui/polymorpheus'
import { i18nPipe } from '../i18n/i18n.pipe' import { i18nPipe } from '../i18n/i18n.pipe'
import { i18nKey } from '../i18n/i18n.providers' import { i18nKey } from '../i18n/i18n.providers'
@@ -17,23 +13,36 @@ import { i18nKey } from '../i18n/i18n.providers'
<p class="warning">{{ options.warning }}</p> <p class="warning">{{ options.warning }}</p>
} }
<form (ngSubmit)="submit(value.trim())"> <form (ngSubmit)="submit(value.trim())">
<tui-input <tui-textfield>
tuiAutoFocus @if (options.label) {
[tuiTextfieldLabelOutside]="!options.label" <label tuiLabel>
[tuiTextfieldCustomContent]="options.useMask ? toggle : ''" {{ options.label }}
[ngModelOptions]="{ standalone: true }" @if (options.required !== false && options.label) {
[(ngModel)]="value" <span>*</span>
> }
{{ options.label }} </label>
@if (options.required !== false && options.label) {
<span>*</span>
} }
<input <input
tuiTextfieldLegacy tuiTextfield
tuiAutoFocus
[ngModelOptions]="{ standalone: true }"
[(ngModel)]="value"
[class.masked]="options.useMask && masked && value" [class.masked]="options.useMask && masked && value"
[placeholder]="options.placeholder || ''" [placeholder]="options.placeholder || ''"
/> />
</tui-input> @if (options.useMask) {
<button
tuiIconButton
type="button"
appearance="icon"
title="Toggle masking"
size="xs"
class="button"
[iconStart]="masked ? '@tui.eye' : '@tui.eye-off'"
(click)="masked = !masked"
></button>
}
</tui-textfield>
<footer class="g-buttons"> <footer class="g-buttons">
<button <button
tuiButton tuiButton
@@ -48,19 +57,6 @@ import { i18nKey } from '../i18n/i18n.providers'
</button> </button>
</footer> </footer>
</form> </form>
<ng-template #toggle>
<button
tuiIconButton
type="button"
appearance="icon"
title="Toggle masking"
size="xs"
class="button"
[iconStart]="masked ? '@tui.eye' : '@tui.eye-off'"
(click)="masked = !masked"
></button>
</ng-template>
`, `,
styles: ` styles: `
.warning { .warning {
@@ -76,25 +72,16 @@ import { i18nKey } from '../i18n/i18n.providers'
-webkit-text-security: disc; -webkit-text-security: disc;
} }
`, `,
imports: [ imports: [FormsModule, TuiButton, TuiTextfield, TuiAutoFocus, i18nPipe],
FormsModule,
TuiInputModule,
TuiButton,
TuiTextfieldControllerModule,
TuiAutoFocus,
i18nPipe,
],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
}) })
export class PromptModal { export class PromptModal {
private readonly context =
injectContext<TuiDialogContext<string, PromptOptions>>()
masked = this.options.useMask masked = this.options.useMask
value = this.options.initialValue || '' value = this.options.initialValue || ''
constructor(
@Inject(POLYMORPHEUS_CONTEXT)
private readonly context: TuiDialogContext<string, PromptOptions>,
) {}
get options(): PromptOptions { get options(): PromptOptions {
return this.context.data return this.context.data
} }

View File

@@ -7,14 +7,18 @@
<img alt="StartOS Icon" class="logo" src="assets/img/icon.png" /> <img alt="StartOS Icon" class="logo" src="assets/img/icon.png" />
<h1 class="header">{{ 'Login to StartOS' | i18n }}</h1> <h1 class="header">{{ 'Login to StartOS' | i18n }}</h1>
<form (submit)="submit()"> <form (submit)="submit()">
<tui-input-password <tui-textfield iconStart="@tui.key">
tuiTextfieldIconLeft="@tui.key" <label tuiLabel>{{ 'Password' | i18n }}</label>
[ngModelOptions]="{ standalone: true }" <input
[(ngModel)]="password" tuiAutoFocus
(ngModelChange)="error = null" tuiTextfield
> type="password"
{{ 'Password' | i18n }} [ngModelOptions]="{ standalone: true }"
</tui-input-password> [(ngModel)]="password"
(ngModelChange)="error = null"
/>
<tui-icon tuiPassword />
</tui-textfield>
<tui-error class="error" [error]="error || null" /> <tui-error class="error" [error]="error || null" />
<button tuiButton class="button">{{ 'Login' | i18n }}</button> <button tuiButton class="button">{{ 'Login' | i18n }}</button>
</form> </form>

View File

@@ -2,15 +2,13 @@ import { CommonModule } from '@angular/common'
import { NgModule } from '@angular/core' import { NgModule } from '@angular/core'
import { FormsModule } from '@angular/forms' import { FormsModule } from '@angular/forms'
import { RouterModule, Routes } from '@angular/router' import { RouterModule, Routes } from '@angular/router'
import { TuiButton, TuiError } from '@taiga-ui/core' import { i18nPipe } from '@start9labs/shared'
import { TuiAutoFocus } from '@taiga-ui/cdk'
import { TuiButton, TuiError, TuiIcon, TuiTextfield } from '@taiga-ui/core'
import { TuiPassword } from '@taiga-ui/kit'
import { TuiCardLarge } from '@taiga-ui/layout' import { TuiCardLarge } from '@taiga-ui/layout'
import {
TuiInputPasswordModule,
TuiTextfieldControllerModule,
} from '@taiga-ui/legacy'
import { CAWizardComponent } from './ca-wizard/ca-wizard.component' import { CAWizardComponent } from './ca-wizard/ca-wizard.component'
import { LoginPage } from './login.page' import { LoginPage } from './login.page'
import { i18nPipe } from '@start9labs/shared'
const routes: Routes = [ const routes: Routes = [
{ {
@@ -26,8 +24,10 @@ const routes: Routes = [
CAWizardComponent, CAWizardComponent,
TuiButton, TuiButton,
TuiCardLarge, TuiCardLarge,
TuiInputPasswordModule, ...TuiTextfield,
TuiTextfieldControllerModule, TuiIcon,
TuiPassword,
TuiAutoFocus,
TuiError, TuiError,
RouterModule.forChild(routes), RouterModule.forChild(routes),
i18nPipe, i18nPipe,

View File

@@ -31,3 +31,7 @@
border-radius: 10rem; border-radius: 10rem;
margin-bottom: 1rem; margin-bottom: 1rem;
} }
[tuiLabel] {
text-align: start;
}

View File

@@ -2,13 +2,13 @@ import { Component, inject } from '@angular/core'
import { toSignal } from '@angular/core/rxjs-interop' import { toSignal } from '@angular/core/rxjs-interop'
import { FormsModule } from '@angular/forms' import { FormsModule } from '@angular/forms'
import { ErrorService, LoadingService } from '@start9labs/shared' import { ErrorService, LoadingService } from '@start9labs/shared'
import { TuiButton, TuiDialogContext, TuiDialogService } from '@taiga-ui/core'
import { TuiBadge, TuiSwitch } from '@taiga-ui/kit'
import { import {
TuiInputModule, TuiButton,
TuiInputNumberModule, TuiDialogContext,
TuiWrapperModule, TuiDialogService,
} from '@taiga-ui/legacy' TuiTextfield,
} from '@taiga-ui/core'
import { TuiBadge, TuiSwitch } from '@taiga-ui/kit'
import { injectContext, PolymorpheusComponent } from '@taiga-ui/polymorpheus' import { injectContext, PolymorpheusComponent } from '@taiga-ui/polymorpheus'
import { from, map } from 'rxjs' import { from, map } from 'rxjs'
import { BackupJob, BackupTarget } from 'src/app/services/api/api.types' import { BackupJob, BackupTarget } from 'src/app/services/api/api.types'
@@ -21,10 +21,15 @@ import { TARGET, TARGET_CREATE } from './target.component'
@Component({ @Component({
template: ` template: `
<form class="form"> <form class="form">
<tui-input name="name" [(ngModel)]="job.name"> <tui-textfield>
Job Name <label tuiLabel>Job Name</label>
<input tuiTextfieldLegacy placeholder="My Backup Job" /> <input
</tui-input> tuiTextfield
name="name"
[(ngModel)]="job.name"
placeholder="My Backup Job"
/>
</tui-textfield>
<button <button
tuiButton tuiButton
appearance="secondary" appearance="secondary"
@@ -53,10 +58,15 @@ import { TARGET, TARGET_CREATE } from './target.component'
{{ job.packageIds.length + ' selected' }} {{ job.packageIds.length + ' selected' }}
</tui-badge> </tui-badge>
</button> </button>
<tui-input name="cron" [(ngModel)]="job.cron"> <tui-textfield>
Schedule <label tuiLabel>Schedule</label>
<input tuiTextfieldLegacy placeholder="* * * * *" /> <input
</tui-input> tuiTextfield
name="cron"
[(ngModel)]="job.cron"
placeholder="* * * * *"
/>
</tui-textfield>
@if (job.cron | toHumanCron; as human) { @if (job.cron | toHumanCron; as human) {
<div [style.color]="human.color">{{ human.message }}</div> <div [style.color]="human.color">{{ human.message }}</div>
} }
@@ -98,10 +108,8 @@ import { TARGET, TARGET_CREATE } from './target.component'
`, `,
imports: [ imports: [
FormsModule, FormsModule,
TuiInputModule, TuiTextfield,
TuiInputNumberModule,
TuiSwitch, TuiSwitch,
TuiWrapperModule,
TuiButton, TuiButton,
TuiBadge, TuiBadge,
ToHumanCronPipe, ToHumanCronPipe,

View File

@@ -10,35 +10,26 @@ import {
import { FormsModule } from '@angular/forms' import { FormsModule } from '@angular/forms'
import { DialogService, i18nPipe } from '@start9labs/shared' import { DialogService, i18nPipe } from '@start9labs/shared'
import { T } from '@start9labs/start-sdk' import { T } from '@start9labs/start-sdk'
import { TuiButton, TuiTitle } from '@taiga-ui/core'
import { import {
TuiInputModule, TuiButton,
TuiTextfieldComponent, TuiTextfield,
TuiTextfieldControllerModule, TuiTextfieldDirective,
} from '@taiga-ui/legacy' TuiTitle,
import { QrCodeModule } from 'ng-qrcode' } from '@taiga-ui/core'
import { QrCodeComponent } from 'ng-qrcode'
@Component({ @Component({
selector: 'app-action-success-member', selector: 'app-action-success-member',
template: ` template: `
<tui-input <tui-textfield>
[readOnly]="true" <label tuiLabel>{{ member.name }}</label>
[ngModel]="member.value"
[tuiTextfieldCustomContent]="actions"
>
{{ member.name }}
<input <input
tuiTextfieldLegacy tuiTextfield
[readOnly]="true"
[ngModel]="member.value"
[style.border-inline-end-width.rem]="border" [style.border-inline-end-width.rem]="border"
[type]="member.masked && masked ? 'password' : 'text'" [type]="member.masked && masked ? 'password' : 'text'"
/> />
</tui-input>
@if (member.description) {
<label [style.padding-top.rem]="0.25" tuiTitle>
<span tuiSubtitle [style.opacity]="0.8">{{ member.description }}</span>
</label>
}
<ng-template #actions>
@if (member.masked) { @if (member.masked) {
<button <button
tuiIconButton tuiIconButton
@@ -81,7 +72,12 @@ import { QrCodeModule } from 'ng-qrcode'
{{ 'Show QR' | i18n }} {{ 'Show QR' | i18n }}
</button> </button>
} }
</ng-template> </tui-textfield>
@if (member.description) {
<label [style.padding-top.rem]="0.25" tuiTitle>
<span tuiSubtitle [style.opacity]="0.8">{{ member.description }}</span>
</label>
}
<ng-template #qr> <ng-template #qr>
<qr-code <qr-code
[value]="member.value" [value]="member.value"
@@ -116,16 +112,15 @@ import { QrCodeModule } from 'ng-qrcode'
`, `,
imports: [ imports: [
FormsModule, FormsModule,
TuiInputModule, TuiTextfield,
TuiTextfieldControllerModule,
TuiButton, TuiButton,
QrCodeModule, QrCodeComponent,
TuiTitle, TuiTitle,
i18nPipe, i18nPipe,
], ],
}) })
export class ActionSuccessMemberComponent { export class ActionSuccessMemberComponent {
@ViewChild(TuiTextfieldComponent, { read: ElementRef }) @ViewChild(TuiTextfieldDirective, { read: ElementRef })
private readonly input!: ElementRef<HTMLInputElement> private readonly input!: ElementRef<HTMLInputElement>
private readonly dialog = inject(DialogService) private readonly dialog = inject(DialogService)

View File

@@ -7,15 +7,10 @@ import {
ViewChild, ViewChild,
} from '@angular/core' } from '@angular/core'
import { FormsModule } from '@angular/forms' import { FormsModule } from '@angular/forms'
import { TuiButton } from '@taiga-ui/core'
import {
TuiInputModule,
TuiTextfieldComponent,
TuiTextfieldControllerModule,
} from '@taiga-ui/legacy'
import { QrCodeModule } from 'ng-qrcode'
import { SingleResult } from './types'
import { i18nPipe } from '@start9labs/shared' import { i18nPipe } from '@start9labs/shared'
import { TuiButton, TuiTextfield, TuiTextfieldDirective } from '@taiga-ui/core'
import { QrCodeComponent } from 'ng-qrcode'
import { SingleResult } from './types'
@Component({ @Component({
selector: 'app-action-success-single', selector: 'app-action-success-single',
@@ -23,19 +18,14 @@ import { i18nPipe } from '@start9labs/shared'
@if (single.qr) { @if (single.qr) {
<p class="qr"><ng-container *ngTemplateOutlet="qr" /></p> <p class="qr"><ng-container *ngTemplateOutlet="qr" /></p>
} }
<tui-input <tui-textfield>
[readOnly]="true"
[ngModel]="single.value"
[tuiTextfieldLabelOutside]="true"
[tuiTextfieldCustomContent]="actions"
>
<input <input
tuiTextfieldLegacy tuiTextfield
[readOnly]="true"
[ngModel]="single.value"
[style.border-inline-end-width.rem]="border" [style.border-inline-end-width.rem]="border"
[type]="single.masked && masked ? 'password' : 'text'" [type]="single.masked && masked ? 'password' : 'text'"
/> />
</tui-input>
<ng-template #actions>
@if (single.masked) { @if (single.masked) {
<button <button
tuiIconButton tuiIconButton
@@ -64,7 +54,7 @@ import { i18nPipe } from '@start9labs/shared'
{{ 'Copy' | i18n }} {{ 'Copy' | i18n }}
</button> </button>
} }
</ng-template> </tui-textfield>
<ng-template #qr> <ng-template #qr>
<qr-code <qr-code
[value]="single.value" [value]="single.value"
@@ -100,15 +90,14 @@ import { i18nPipe } from '@start9labs/shared'
imports: [ imports: [
CommonModule, CommonModule,
FormsModule, FormsModule,
TuiInputModule, TuiTextfield,
TuiTextfieldControllerModule,
TuiButton, TuiButton,
QrCodeModule, QrCodeComponent,
i18nPipe, i18nPipe,
], ],
}) })
export class ActionSuccessSingleComponent { export class ActionSuccessSingleComponent {
@ViewChild(TuiTextfieldComponent, { read: ElementRef }) @ViewChild(TuiTextfieldDirective, { read: ElementRef })
private readonly input!: ElementRef<HTMLInputElement> private readonly input!: ElementRef<HTMLInputElement>
@Input() @Input()

View File

@@ -11,9 +11,8 @@ import {
LoadingService, LoadingService,
} from '@start9labs/shared' } from '@start9labs/shared'
import { inputSpec, IST } from '@start9labs/start-sdk' import { inputSpec, IST } from '@start9labs/start-sdk'
import { TuiButton, TuiTitle } from '@taiga-ui/core' import { TuiButton, TuiTextfield, TuiTitle } from '@taiga-ui/core'
import { TuiHeader } from '@taiga-ui/layout' import { TuiHeader } from '@taiga-ui/layout'
import { TuiInputModule } from '@taiga-ui/legacy'
import { PatchDB } from 'patch-db-client' import { PatchDB } from 'patch-db-client'
import { switchMap, tap } from 'rxjs' import { switchMap, tap } from 'rxjs'
import { FormModule } from 'src/app/routes/portal/components/form/form.module' import { FormModule } from 'src/app/routes/portal/components/form/form.module'
@@ -80,13 +79,15 @@ import { configBuilderToSpec } from 'src/app/utils/configBuilderToSpec'
<b>{{ 'Send test email' | i18n }}</b> <b>{{ 'Send test email' | i18n }}</b>
</h3> </h3>
</header> </header>
<tui-input <tui-textfield>
[(ngModel)]="testAddress" <label tuiLabel>Name Lastname &lt;email&#64;example.com&gt;</label>
[ngModelOptions]="{ standalone: true }" <input
> tuiTextfield
Name Lastname &lt;email&#64;example.com&gt; inputmode="email"
<input tuiTextfieldLegacy inputmode="email" /> [(ngModel)]="testAddress"
</tui-input> [ngModelOptions]="{ standalone: true }"
/>
</tui-textfield>
<footer> <footer>
<button <button
tuiButton tuiButton
@@ -123,7 +124,7 @@ import { configBuilderToSpec } from 'src/app/utils/configBuilderToSpec'
ReactiveFormsModule, ReactiveFormsModule,
FormModule, FormModule,
TuiButton, TuiButton,
TuiInputModule, TuiTextfield,
TuiHeader, TuiHeader,
TuiTitle, TuiTitle,
RouterLink, RouterLink,