chore: refactor install and setup wizards (#2561)

* chore: refactor install and setup wizards

* chore: return tui-root
This commit is contained in:
Alex Inkin
2024-02-22 17:58:01 +04:00
committed by GitHub
parent 69d5f521a5
commit 7b41b295b7
109 changed files with 1863 additions and 3538 deletions

View File

@@ -0,0 +1,182 @@
import { Component, inject } from '@angular/core'
import { Router } from '@angular/router'
import {
DiskInfo,
DriveComponent,
ErrorService,
LoadingService,
toGuid,
} from '@start9labs/shared'
import { TuiDialogService, TuiLoaderModule } from '@taiga-ui/core'
import {
TuiButtonModule,
TuiCardModule,
TuiCellModule,
} from '@taiga-ui/experimental'
import { TUI_PROMPT } from '@taiga-ui/kit'
import { filter, of, switchMap } from 'rxjs'
import { PASSWORD } from 'src/app/components/password.component'
import {
ApiService,
BackupRecoverySource,
DiskMigrateSource,
DiskRecoverySource,
} from 'src/app/services/api.service'
import { StateService } from 'src/app/services/state.service'
@Component({
standalone: true,
template: `
<section tuiCardLarge>
@if (loading || drives.length) {
<header>Select storage drive</header>
This is the drive where your StartOS data will be stored.
} @else {
<header>No drives found</header>
Please connect a storage drive to your server. Then click "Refresh".
}
@if (loading) {
<tui-loader />
}
@for (d of drives; track d) {
<button tuiCell [drive]="d" [disabled]="isSmall(d)" (click)="select(d)">
@if (isSmall(d)) {
<span tuiSubtitle class="g-error">Drive capacity too small</span>
}
</button>
}
<button tuiButton iconLeft="tuiIconRotateCwLarge" (click)="getDrives()">
Refresh
</button>
</section>
`,
imports: [
TuiCardModule,
TuiLoaderModule,
TuiCellModule,
TuiButtonModule,
DriveComponent,
],
})
export default class StoragePage {
private readonly api = inject(ApiService)
private readonly router = inject(Router)
private readonly dialogs = inject(TuiDialogService)
private readonly stateService = inject(StateService)
private readonly loader = inject(LoadingService)
private readonly errorService = inject(ErrorService)
drives: DiskInfo[] = []
loading = true
async ngOnInit() {
await this.getDrives()
}
isSmall({ capacity }: DiskInfo) {
return capacity < 34359738368
}
async refresh() {
this.loading = true
await this.getDrives()
}
async getDrives() {
this.loading = true
try {
const disks = await this.api.getDrives()
if (this.stateService.setupType === 'fresh') {
this.drives = disks
} else if (this.stateService.setupType === 'restore') {
this.drives = disks.filter(
d =>
!d.partitions
.map(p => p.logicalname)
.includes(
(
(this.stateService.recoverySource as BackupRecoverySource)
?.target as DiskRecoverySource
)?.logicalname,
),
)
} else if (this.stateService.setupType === 'transfer') {
const guid = (this.stateService.recoverySource as DiskMigrateSource)
.guid
this.drives = disks.filter(d => {
return (
d.guid !== guid && !d.partitions.map(p => p.guid).includes(guid)
)
})
}
} catch (e: any) {
this.errorService.handleError(e)
} finally {
this.loading = false
}
}
select(drive: DiskInfo) {
of(!toGuid(drive) && !drive.partitions.some(p => p.used))
.pipe(
switchMap(unused =>
unused
? of(true)
: this.dialogs.open(TUI_PROMPT, {
label: 'Warning',
size: 's',
data: {
content:
'<strong>Drive contains data!</strong><p>All data stored on this drive will be permanently deleted.</p>',
yes: 'Continue',
no: 'Cancel',
},
}),
),
)
.pipe(filter(Boolean))
.subscribe(() => {
// for backup recoveries
if (this.stateService.recoveryPassword) {
this.setupEmbassy(
drive.logicalname,
this.stateService.recoveryPassword,
)
} else {
// for migrations and fresh setups
this.presentModalPassword(drive.logicalname)
}
})
}
private presentModalPassword(logicalname: string) {
this.dialogs
.open<string>(PASSWORD, {
label: 'Set Password',
size: 's',
data: { storageDrive: true },
})
.subscribe(password => {
this.setupEmbassy(logicalname, password)
})
}
private async setupEmbassy(
logicalname: string,
password: string,
): Promise<void> {
const loader = this.loader.open('Connecting to drive...').subscribe()
try {
await this.stateService.setupEmbassy(logicalname, password)
await this.router.navigate([`loading`])
} catch (e: any) {
this.errorService.handleError(e)
} finally {
loader.unsubscribe()
}
}
}