mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 02:11:53 +00:00
Various (#3051)
* tell user to restart server after kiosk chnage * remove unused import * dont show tor address on server setup * chore: address comments * revert mock * chore: remove uptime block on mobile * utiliser le futur proche --------- Co-authored-by: waterplea <alexander@inkin.ru> Co-authored-by: Aiden McClelland <3732071+dr-bonez@users.noreply.github.com>
This commit is contained in:
@@ -39,7 +39,9 @@ import { DocsLinkDirective } from '@start9labs/shared'
|
|||||||
"
|
"
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<h3 style="color: #f8546a; font-weight: bold">Important!</h3>
|
<h2 style="font-variant-caps: all-small-caps">
|
||||||
|
Root Certificate Authority
|
||||||
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
Download your server's Root CA and
|
Download your server's Root CA and
|
||||||
<a
|
<a
|
||||||
@@ -47,7 +49,7 @@ import { DocsLinkDirective } from '@start9labs/shared'
|
|||||||
path="/user-manual/trust-ca.html"
|
path="/user-manual/trust-ca.html"
|
||||||
style="color: #6866cc; font-weight: bold; text-decoration: none"
|
style="color: #6866cc; font-weight: bold; text-decoration: none"
|
||||||
>
|
>
|
||||||
follow the instructions
|
follow instructions
|
||||||
</a>
|
</a>
|
||||||
to establish a secure connection with your server.
|
to establish a secure connection with your server.
|
||||||
</p>
|
</p>
|
||||||
@@ -84,15 +86,15 @@ import { DocsLinkDirective } from '@start9labs/shared'
|
|||||||
"
|
"
|
||||||
>
|
>
|
||||||
<h2 style="font-variant-caps: all-small-caps">
|
<h2 style="font-variant-caps: all-small-caps">
|
||||||
Access from home (LAN)
|
Permanent Local Address
|
||||||
</h2>
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
Visit the address below when you are connected to the same WiFi or
|
You must be connected to the same Local Area Network (LAN) as your
|
||||||
Local Area Network (LAN) as your server.
|
server to access this address.
|
||||||
</p>
|
</p>
|
||||||
<p
|
<p
|
||||||
style="
|
style="
|
||||||
padding: 16px;
|
padding: 16px 0;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 1.1rem;
|
font-size: 1.1rem;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
@@ -100,33 +102,6 @@ import { DocsLinkDirective } from '@start9labs/shared'
|
|||||||
>
|
>
|
||||||
<code id="lan-addr"></code>
|
<code id="lan-addr"></code>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2 style="font-variant-caps: all-small-caps">
|
|
||||||
Access on the go (Tor)
|
|
||||||
</h2>
|
|
||||||
<p>Visit the address below when you are away from home.</p>
|
|
||||||
<p>
|
|
||||||
<span style="font-weight: bold">Note:</span>
|
|
||||||
This address will only work from a Tor-enabled browser.
|
|
||||||
<a
|
|
||||||
docsLink
|
|
||||||
path="/user-manual/connecting-remotely/tor.html"
|
|
||||||
style="color: #6866cc; font-weight: bold; text-decoration: none"
|
|
||||||
>
|
|
||||||
Follow the instructions
|
|
||||||
</a>
|
|
||||||
to get setup.
|
|
||||||
</p>
|
|
||||||
<p
|
|
||||||
style="
|
|
||||||
padding: 16px;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
overflow: auto;
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<code id="tor-addr"></code>
|
|
||||||
</p>
|
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
DOCUMENT,
|
DOCUMENT,
|
||||||
} from '@angular/core'
|
} from '@angular/core'
|
||||||
import { DownloadHTMLService, ErrorService } from '@start9labs/shared'
|
import { DownloadHTMLService, ErrorService } from '@start9labs/shared'
|
||||||
import { TuiButton, TuiIcon, TuiSurface } from '@taiga-ui/core'
|
import { TuiButton, TuiIcon, TuiLoader, TuiSurface } from '@taiga-ui/core'
|
||||||
import { TuiCardLarge } from '@taiga-ui/layout'
|
import { TuiCardLarge } from '@taiga-ui/layout'
|
||||||
import { DocumentationComponent } from 'src/app/components/documentation.component'
|
import { DocumentationComponent } from 'src/app/components/documentation.component'
|
||||||
import { MatrixComponent } from 'src/app/components/matrix.component'
|
import { MatrixComponent } from 'src/app/components/matrix.component'
|
||||||
@@ -31,10 +31,16 @@ import { StateService } from 'src/app/services/state.service'
|
|||||||
<h3>You can now safely unplug your old StartOS data drive</h3>
|
<h3>You can now safely unplug your old StartOS data drive</h3>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<h3>
|
||||||
|
http://start.local was for setup purposes only. It will no longer
|
||||||
|
work.
|
||||||
|
</h3>
|
||||||
|
|
||||||
<button tuiCardLarge tuiSurface="floating" (click)="download()">
|
<button tuiCardLarge tuiSurface="floating" (click)="download()">
|
||||||
<strong class="caps">Download address info</strong>
|
<strong class="caps">Download address info</strong>
|
||||||
<span>
|
<span>
|
||||||
start.local was for setup purposes only. It will no longer work.
|
For future reference, this file contains your server's permanent
|
||||||
|
local address, as well as its Root Certificate Authority (Root CA).
|
||||||
</span>
|
</span>
|
||||||
<strong class="caps">
|
<strong class="caps">
|
||||||
Download
|
Download
|
||||||
@@ -48,17 +54,18 @@ import { StateService } from 'src/app/services/state.service'
|
|||||||
target="_blank"
|
target="_blank"
|
||||||
[attr.href]="disableLogin ? null : lanAddress"
|
[attr.href]="disableLogin ? null : lanAddress"
|
||||||
>
|
>
|
||||||
<strong class="caps">Trust your Root CA</strong>
|
|
||||||
<span>
|
<span>
|
||||||
In the new tab, follow instructions to trust your server's Root CA
|
In the new tab, follow instructions to trust your server's Root CA
|
||||||
and log in.
|
and log in.
|
||||||
</span>
|
</span>
|
||||||
<strong class="caps">
|
<strong class="caps">
|
||||||
Open
|
Open Local Address
|
||||||
<tui-icon icon="@tui.external-link" />
|
<tui-icon icon="@tui.external-link" />
|
||||||
</strong>
|
</strong>
|
||||||
</a>
|
</a>
|
||||||
<app-documentation hidden [lanAddress]="lanAddress" />
|
<app-documentation hidden [lanAddress]="lanAddress" />
|
||||||
|
} @else {
|
||||||
|
<tui-loader />
|
||||||
}
|
}
|
||||||
</section>
|
</section>
|
||||||
`,
|
`,
|
||||||
@@ -97,6 +104,10 @@ import { StateService } from 'src/app/services/state.service'
|
|||||||
opacity: var(--tui-disabled-opacity);
|
opacity: var(--tui-disabled-opacity);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
imports: [
|
imports: [
|
||||||
TuiCardLarge,
|
TuiCardLarge,
|
||||||
@@ -105,6 +116,7 @@ import { StateService } from 'src/app/services/state.service'
|
|||||||
TuiSurface,
|
TuiSurface,
|
||||||
MatrixComponent,
|
MatrixComponent,
|
||||||
DocumentationComponent,
|
DocumentationComponent,
|
||||||
|
TuiLoader,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export default class SuccessPage implements AfterViewInit {
|
export default class SuccessPage implements AfterViewInit {
|
||||||
@@ -117,7 +129,6 @@ export default class SuccessPage implements AfterViewInit {
|
|||||||
|
|
||||||
readonly stateService = inject(StateService)
|
readonly stateService = inject(StateService)
|
||||||
|
|
||||||
torAddresses?: string[]
|
|
||||||
lanAddress?: string
|
lanAddress?: string
|
||||||
cert?: string
|
cert?: string
|
||||||
disableLogin = this.stateService.setupType === 'fresh'
|
disableLogin = this.stateService.setupType === 'fresh'
|
||||||
@@ -127,10 +138,8 @@ export default class SuccessPage implements AfterViewInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
download() {
|
download() {
|
||||||
const torElem = this.document.getElementById('tor-addr')
|
|
||||||
const lanElem = this.document.getElementById('lan-addr')
|
const lanElem = this.document.getElementById('lan-addr')
|
||||||
|
|
||||||
if (torElem) torElem.innerHTML = this.torAddresses?.join('\n') || ''
|
|
||||||
if (lanElem) lanElem.innerHTML = this.lanAddress || ''
|
if (lanElem) lanElem.innerHTML = this.lanAddress || ''
|
||||||
|
|
||||||
this.document
|
this.document
|
||||||
@@ -155,9 +164,6 @@ export default class SuccessPage implements AfterViewInit {
|
|||||||
try {
|
try {
|
||||||
const ret = await this.api.complete()
|
const ret = await this.api.complete()
|
||||||
if (!this.stateService.kiosk) {
|
if (!this.stateService.kiosk) {
|
||||||
this.torAddresses = ret.torAddresses.map(a =>
|
|
||||||
a.replace(/^https:/, 'http:'),
|
|
||||||
)
|
|
||||||
this.lanAddress = ret.lanAddress.replace(/^https:/, 'http:')
|
this.lanAddress = ret.lanAddress.replace(/^https:/, 'http:')
|
||||||
this.cert = ret.rootCa
|
this.cert = ret.rootCa
|
||||||
|
|
||||||
|
|||||||
@@ -484,7 +484,7 @@ export default {
|
|||||||
512: 'Der Kiosk-Modus ist auf diesem Gerät nicht verfügbar',
|
512: 'Der Kiosk-Modus ist auf diesem Gerät nicht verfügbar',
|
||||||
513: 'Aktivieren',
|
513: 'Aktivieren',
|
||||||
514: 'Deaktivieren',
|
514: 'Deaktivieren',
|
||||||
515: 'Du verwendest derzeit einen Kiosk. Wenn du den Kiosk-Modus deaktivierst, wird die Verbindung zum Kiosk getrennt.',
|
515: 'Diese Änderung wird nach dem nächsten Neustart wirksam',
|
||||||
516: 'Empfohlen',
|
516: 'Empfohlen',
|
||||||
517: 'Möchten Sie diese Aufgabe wirklich verwerfen?',
|
517: 'Möchten Sie diese Aufgabe wirklich verwerfen?',
|
||||||
518: 'Verwerfen',
|
518: 'Verwerfen',
|
||||||
|
|||||||
@@ -483,7 +483,7 @@ export const ENGLISH = {
|
|||||||
'Kiosk Mode is unavailable on this device': 512,
|
'Kiosk Mode is unavailable on this device': 512,
|
||||||
'Enable': 513,
|
'Enable': 513,
|
||||||
'Disable': 514,
|
'Disable': 514,
|
||||||
'You are currently using a kiosk. Disabling Kiosk Mode will result in the kiosk disconnecting.': 515,
|
'This change will take effect after the next boot': 515,
|
||||||
'Recommended': 516, // as in, we recommend this
|
'Recommended': 516, // as in, we recommend this
|
||||||
'Are you sure you want to dismiss this task?': 517,
|
'Are you sure you want to dismiss this task?': 517,
|
||||||
'Dismiss': 518, // as in, dismiss or delete a task
|
'Dismiss': 518, // as in, dismiss or delete a task
|
||||||
|
|||||||
@@ -484,7 +484,7 @@ export default {
|
|||||||
512: 'El modo quiosco no está disponible en este dispositivo',
|
512: 'El modo quiosco no está disponible en este dispositivo',
|
||||||
513: 'Activar',
|
513: 'Activar',
|
||||||
514: 'Desactivar',
|
514: 'Desactivar',
|
||||||
515: 'Actualmente estás utilizando un quiosco. Desactivar el modo quiosco provocará su desconexión.',
|
515: 'Este cambio tendrá efecto después del próximo inicio',
|
||||||
516: 'Recomendado',
|
516: 'Recomendado',
|
||||||
517: '¿Estás seguro de que deseas descartar esta tarea?',
|
517: '¿Estás seguro de que deseas descartar esta tarea?',
|
||||||
518: 'Descartar',
|
518: 'Descartar',
|
||||||
|
|||||||
@@ -484,7 +484,7 @@ export default {
|
|||||||
512: 'Le mode kiosque n’est pas disponible sur cet appareil',
|
512: 'Le mode kiosque n’est pas disponible sur cet appareil',
|
||||||
513: 'Activer',
|
513: 'Activer',
|
||||||
514: 'Désactiver',
|
514: 'Désactiver',
|
||||||
515: 'Vous utilisez actuellement un kiosque. Désactiver le mode kiosque entraînera sa déconnexion.',
|
515: 'Ce changement va prendre effet après le prochain démarrage',
|
||||||
516: 'Recommandé',
|
516: 'Recommandé',
|
||||||
517: 'Êtes-vous sûr de vouloir ignorer cette tâche ?',
|
517: 'Êtes-vous sûr de vouloir ignorer cette tâche ?',
|
||||||
518: 'Ignorer',
|
518: 'Ignorer',
|
||||||
|
|||||||
@@ -484,7 +484,7 @@ export default {
|
|||||||
512: 'Tryb kiosku jest niedostępny na tym urządzeniu',
|
512: 'Tryb kiosku jest niedostępny na tym urządzeniu',
|
||||||
513: 'Włącz',
|
513: 'Włącz',
|
||||||
514: 'Wyłącz',
|
514: 'Wyłącz',
|
||||||
515: 'Obecnie używasz kiosku. Wyłączenie trybu kiosku spowoduje jego rozłączenie.',
|
515: 'Ta zmiana zacznie obowiązywać po następnym uruchomieniu',
|
||||||
516: 'Zalecane',
|
516: 'Zalecane',
|
||||||
517: 'Czy na pewno chcesz odrzucić to zadanie?',
|
517: 'Czy na pewno chcesz odrzucić to zadanie?',
|
||||||
518: 'Odrzuć',
|
518: 'Odrzuć',
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { I18N, i18nKey } from './i18n.providers'
|
|||||||
export class i18nPipe implements PipeTransform {
|
export class i18nPipe implements PipeTransform {
|
||||||
private readonly i18n = inject(I18N)
|
private readonly i18n = inject(I18N)
|
||||||
|
|
||||||
transform(englishKey: i18nKey | null | undefined): string {
|
transform(englishKey: i18nKey | null | undefined | ''): string {
|
||||||
englishKey = englishKey || ('' as i18nKey)
|
englishKey = englishKey || ('' as i18nKey)
|
||||||
|
|
||||||
return this.i18n()?.[ENGLISH[englishKey]] || englishKey
|
return this.i18n()?.[ENGLISH[englishKey]] || englishKey
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
import {
|
import {
|
||||||
ChangeDetectionStrategy,
|
ChangeDetectionStrategy,
|
||||||
Component,
|
Component,
|
||||||
inject,
|
computed,
|
||||||
Input,
|
input,
|
||||||
} from '@angular/core'
|
} from '@angular/core'
|
||||||
import { i18nKey, i18nPipe } from '@start9labs/shared'
|
import { i18nPipe } from '@start9labs/shared'
|
||||||
import { T } from '@start9labs/start-sdk'
|
|
||||||
import { TuiLoader } from '@taiga-ui/core'
|
import { TuiLoader } from '@taiga-ui/core'
|
||||||
|
import { ServiceUptimeComponent } from 'src/app/routes/portal/routes/services/components/uptime.component'
|
||||||
import { getProgressText } from 'src/app/routes/portal/routes/services/pipes/install-progress.pipe'
|
import { getProgressText } from 'src/app/routes/portal/routes/services/pipes/install-progress.pipe'
|
||||||
import { InstallingInfo } from 'src/app/services/patch-db/data-model'
|
import { PackageDataEntry } from 'src/app/services/patch-db/data-model'
|
||||||
import {
|
import {
|
||||||
|
getInstalledPrimaryStatus,
|
||||||
PrimaryRendering,
|
PrimaryRendering,
|
||||||
PrimaryStatus,
|
|
||||||
} from 'src/app/services/pkg-status-rendering.service'
|
} from 'src/app/services/pkg-status-rendering.service'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -19,23 +19,27 @@ import {
|
|||||||
template: `
|
template: `
|
||||||
<header>{{ 'Status' | i18n }}</header>
|
<header>{{ 'Status' | i18n }}</header>
|
||||||
<div>
|
<div>
|
||||||
@if (installingInfo) {
|
@if (info()) {
|
||||||
<h3>
|
<h3>
|
||||||
<tui-loader size="s" [inheritColor]="true" />
|
<tui-loader size="s" [inheritColor]="true" />
|
||||||
{{ 'Installing' | i18n }}
|
{{ 'Installing' | i18n }}
|
||||||
<span class="loading-dots"></span>
|
<span class="loading-dots"></span>
|
||||||
{{ getText(installingInfo.progress.overall) | i18n }}
|
{{ info() | i18n }}
|
||||||
</h3>
|
</h3>
|
||||||
} @else {
|
} @else {
|
||||||
<h3 [class]="class">
|
<h3 [class]="class()">
|
||||||
{{ text | i18n }}
|
{{ text() || 'Unknown' | i18n }}
|
||||||
@if (text === 'Task Required') {
|
@if (text() === 'Task Required') {
|
||||||
<small>{{ 'See below' | i18n }}</small>
|
<small>{{ 'See below' | i18n }}</small>
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (rendering?.showDots) {
|
@if (rendering().showDots) {
|
||||||
<span class="loading-dots"></span>
|
<span class="loading-dots"></span>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@if ($any(pkg().status)?.started; as started) {
|
||||||
|
<service-uptime [started]="started" />
|
||||||
|
}
|
||||||
</h3>
|
</h3>
|
||||||
}
|
}
|
||||||
<ng-content />
|
<ng-content />
|
||||||
@@ -76,6 +80,12 @@ import {
|
|||||||
margin: 0 0.25rem -0.125rem 0;
|
margin: 0 0.25rem -0.125rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
service-uptime {
|
||||||
|
display: none;
|
||||||
|
width: fit-content;
|
||||||
|
margin: 0.5rem 0.125rem;
|
||||||
|
}
|
||||||
|
|
||||||
:host-context(tui-root._mobile) {
|
:host-context(tui-root._mobile) {
|
||||||
:host {
|
:host {
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
@@ -94,32 +104,33 @@ import {
|
|||||||
small {
|
small {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
service-uptime {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
host: { class: 'g-card' },
|
host: { class: 'g-card' },
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
imports: [TuiLoader, i18nPipe],
|
imports: [TuiLoader, i18nPipe, ServiceUptimeComponent],
|
||||||
})
|
})
|
||||||
export class ServiceStatusComponent {
|
export class ServiceStatusComponent {
|
||||||
@Input({ required: true })
|
readonly pkg = input.required<PackageDataEntry>()
|
||||||
status?: PrimaryStatus
|
readonly connected = input(false)
|
||||||
|
|
||||||
@Input()
|
protected readonly status = computed((pkg = this.pkg()) =>
|
||||||
installingInfo?: InstallingInfo
|
pkg?.stateInfo.state === 'installed'
|
||||||
|
? getInstalledPrimaryStatus(pkg)
|
||||||
|
: pkg?.stateInfo.state,
|
||||||
|
)
|
||||||
|
|
||||||
@Input()
|
protected readonly rendering = computed(() => PrimaryRendering[this.status()])
|
||||||
connected = false
|
protected readonly text = computed(
|
||||||
|
() => this.connected() && this.rendering().display,
|
||||||
|
)
|
||||||
|
|
||||||
private readonly i18n = inject(i18nPipe)
|
protected readonly class = computed(() => {
|
||||||
|
switch (this.connected() && this.rendering().color) {
|
||||||
get text(): i18nKey {
|
|
||||||
return this.connected ? this.rendering?.display || 'Unknown' : 'Unknown'
|
|
||||||
}
|
|
||||||
|
|
||||||
get class(): string | null {
|
|
||||||
if (!this.connected) return null
|
|
||||||
|
|
||||||
switch (this.rendering?.color) {
|
|
||||||
case 'danger':
|
case 'danger':
|
||||||
return 'g-negative'
|
return 'g-negative'
|
||||||
case 'warning':
|
case 'warning':
|
||||||
@@ -131,13 +142,10 @@ export class ServiceStatusComponent {
|
|||||||
default:
|
default:
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
get rendering() {
|
protected readonly info = computed(
|
||||||
return this.status && PrimaryRendering[this.status]
|
(progress = this.pkg().stateInfo.installingInfo?.progress.overall) =>
|
||||||
}
|
progress ? getProgressText(progress) : '',
|
||||||
|
)
|
||||||
getText(progress: T.Progress): i18nKey {
|
|
||||||
return getProgressText(progress)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,6 +79,10 @@ import { getManifest } from 'src/app/utils/get-package-data'
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
td:not(:last-child) {
|
||||||
|
padding-inline-end: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
td:last-child {
|
td:last-child {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
|||||||
@@ -66,7 +66,8 @@ import { distinctUntilChanged } from 'rxjs/operators'
|
|||||||
color: var(--tui-text-primary);
|
color: var(--tui-text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
:host-context(table) {
|
:host-context(table),
|
||||||
|
:host-context(service-status) {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
header {
|
header {
|
||||||
|
|||||||
@@ -39,11 +39,7 @@ import { ServiceUptimeComponent } from '../components/uptime.component'
|
|||||||
} @else if (installing()) {
|
} @else if (installing()) {
|
||||||
<service-install-progress [pkg]="pkg" />
|
<service-install-progress [pkg]="pkg" />
|
||||||
} @else if (installed()) {
|
} @else if (installed()) {
|
||||||
<service-status
|
<service-status [connected]="!!connected()" [pkg]="pkg">
|
||||||
[connected]="!!connected()"
|
|
||||||
[installingInfo]="pkg.stateInfo.installingInfo"
|
|
||||||
[status]="status()"
|
|
||||||
>
|
|
||||||
@if (connected()) {
|
@if (connected()) {
|
||||||
<service-controls [pkg]="pkg" [status]="status()" />
|
<service-controls [pkg]="pkg" [status]="status()" />
|
||||||
}
|
}
|
||||||
@@ -51,10 +47,8 @@ import { ServiceUptimeComponent } from '../components/uptime.component'
|
|||||||
|
|
||||||
@if (status() !== 'backingUp') {
|
@if (status() !== 'backingUp') {
|
||||||
<service-health-checks [checks]="health()" />
|
<service-health-checks [checks]="health()" />
|
||||||
<service-uptime
|
<service-uptime class="g-card" [started]="$any(pkg.status).started" />
|
||||||
class="g-card"
|
<service-interfaces [pkg]="pkg" [disabled]="status() !== 'running'" />
|
||||||
[started]="$any(pkg.status)?.started"
|
|
||||||
/>
|
|
||||||
|
|
||||||
@if (errors() | async; as errors) {
|
@if (errors() | async; as errors) {
|
||||||
<service-dependencies
|
<service-dependencies
|
||||||
@@ -63,7 +57,6 @@ import { ServiceUptimeComponent } from '../components/uptime.component'
|
|||||||
[errors]="errors"
|
[errors]="errors"
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
<service-interfaces [pkg]="pkg" [disabled]="status() !== 'running'" />
|
|
||||||
|
|
||||||
<service-tasks
|
<service-tasks
|
||||||
#tasks="elementRef"
|
#tasks="elementRef"
|
||||||
@@ -91,7 +84,7 @@ import { ServiceUptimeComponent } from '../components/uptime.component'
|
|||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
} @else if (removing()) {
|
} @else if (removing()) {
|
||||||
<service-status [connected]="!!connected()" [status]="status()" />
|
<service-status [connected]="!!connected()" [pkg]="pkg" />
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
@@ -139,6 +132,10 @@ import { ServiceUptimeComponent } from '../components/uptime.component'
|
|||||||
> * {
|
> * {
|
||||||
grid-column: span 1;
|
grid-column: span 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
service-uptime {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
host: { class: 'g-subpage' },
|
host: { class: 'g-subpage' },
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import {
|
|||||||
Component,
|
Component,
|
||||||
inject,
|
inject,
|
||||||
INJECTOR,
|
INJECTOR,
|
||||||
DOCUMENT,
|
|
||||||
} from '@angular/core'
|
} 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'
|
||||||
@@ -151,7 +150,7 @@ import { SystemWipeComponent } from './wipe.component'
|
|||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
@if (server.kiosk !== null) {
|
@if (server.kiosk !== null) {
|
||||||
<button tuiButton appearance="primary" (click)="tryToggleKiosk()">
|
<button tuiButton appearance="primary" (click)="toggleKiosk()">
|
||||||
{{ server.kiosk ? ('Disable' | i18n) : ('Enable' | i18n) }}
|
{{ server.kiosk ? ('Disable' | i18n) : ('Enable' | i18n) }}
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
@@ -242,7 +241,6 @@ export default class SystemGeneralComponent {
|
|||||||
private readonly patch = inject<PatchDB<DataModel>>(PatchDB)
|
private readonly patch = inject<PatchDB<DataModel>>(PatchDB)
|
||||||
private readonly api = inject(ApiService)
|
private readonly api = inject(ApiService)
|
||||||
private readonly isTor = inject(ConfigService).isTor()
|
private readonly isTor = inject(ConfigService).isTor()
|
||||||
private readonly document = inject(DOCUMENT)
|
|
||||||
private readonly dialog = inject(DialogService)
|
private readonly dialog = inject(DialogService)
|
||||||
private readonly i18n = inject(i18nPipe)
|
private readonly i18n = inject(i18nPipe)
|
||||||
private readonly injector = inject(INJECTOR)
|
private readonly injector = inject(INJECTOR)
|
||||||
@@ -326,28 +324,6 @@ export default class SystemGeneralComponent {
|
|||||||
.subscribe(() => this.resetTor(this.wipe))
|
.subscribe(() => this.resetTor(this.wipe))
|
||||||
}
|
}
|
||||||
|
|
||||||
async tryToggleKiosk() {
|
|
||||||
if (
|
|
||||||
this.server()?.kiosk &&
|
|
||||||
['localhost', '127.0.0.1'].includes(this.document.location.hostname)
|
|
||||||
) {
|
|
||||||
return this.dialog
|
|
||||||
.openConfirm({
|
|
||||||
label: 'Warning',
|
|
||||||
data: {
|
|
||||||
content:
|
|
||||||
'You are currently using a kiosk. Disabling Kiosk Mode will result in the kiosk disconnecting.',
|
|
||||||
yes: 'Disable',
|
|
||||||
no: 'Cancel',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.pipe(filter(Boolean))
|
|
||||||
.subscribe(async () => this.toggleKiosk())
|
|
||||||
}
|
|
||||||
|
|
||||||
this.toggleKiosk()
|
|
||||||
}
|
|
||||||
|
|
||||||
async onRepair() {
|
async onRepair() {
|
||||||
this.dialog
|
this.dialog
|
||||||
.openConfirm({
|
.openConfirm({
|
||||||
@@ -370,7 +346,7 @@ export default class SystemGeneralComponent {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private async toggleKiosk() {
|
async toggleKiosk() {
|
||||||
const kiosk = this.server()?.kiosk
|
const kiosk = this.server()?.kiosk
|
||||||
|
|
||||||
const loader = this.loader
|
const loader = this.loader
|
||||||
@@ -379,6 +355,11 @@ export default class SystemGeneralComponent {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await this.api.toggleKiosk(!kiosk)
|
await this.api.toggleKiosk(!kiosk)
|
||||||
|
this.dialog
|
||||||
|
.openAlert('This change will take effect after the next boot', {
|
||||||
|
label: 'Restart to apply',
|
||||||
|
})
|
||||||
|
.subscribe()
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
this.errorService.handleError(e)
|
this.errorService.handleError(e)
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -1,16 +1,20 @@
|
|||||||
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
|
import {
|
||||||
|
ChangeDetectionStrategy,
|
||||||
|
Component,
|
||||||
|
inject,
|
||||||
|
viewChild,
|
||||||
|
} from '@angular/core'
|
||||||
import { toSignal } from '@angular/core/rxjs-interop'
|
import { toSignal } from '@angular/core/rxjs-interop'
|
||||||
import { RouterLink } from '@angular/router'
|
import { RouterLink } from '@angular/router'
|
||||||
import { verify } from '@start9labs/argon2'
|
import { verify } from '@start9labs/argon2'
|
||||||
import {
|
import {
|
||||||
DialogService,
|
|
||||||
ErrorService,
|
ErrorService,
|
||||||
i18nKey,
|
i18nKey,
|
||||||
i18nPipe,
|
i18nPipe,
|
||||||
LoadingService,
|
LoadingService,
|
||||||
} from '@start9labs/shared'
|
} from '@start9labs/shared'
|
||||||
import { ISB } from '@start9labs/start-sdk'
|
import { ISB } from '@start9labs/start-sdk'
|
||||||
import { TuiButton, TuiTitle } from '@taiga-ui/core'
|
import { TuiAlertService, TuiButton, TuiTitle } from '@taiga-ui/core'
|
||||||
import { TuiHeader } from '@taiga-ui/layout'
|
import { TuiHeader } from '@taiga-ui/layout'
|
||||||
import { PatchDB } from 'patch-db-client'
|
import { PatchDB } from 'patch-db-client'
|
||||||
import { from } from 'rxjs'
|
import { from } from 'rxjs'
|
||||||
@@ -70,13 +74,14 @@ import { getServerInfo } from 'src/app/utils/get-server-info'
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
export default class SystemPasswordComponent {
|
export default class SystemPasswordComponent {
|
||||||
private readonly dialog = inject(DialogService)
|
private readonly alerts = inject(TuiAlertService)
|
||||||
private readonly loader = inject(LoadingService)
|
private readonly loader = inject(LoadingService)
|
||||||
private readonly errorService = inject(ErrorService)
|
private readonly errorService = inject(ErrorService)
|
||||||
private readonly patch = inject<PatchDB<DataModel>>(PatchDB)
|
private readonly patch = inject<PatchDB<DataModel>>(PatchDB)
|
||||||
private readonly api = inject(ApiService)
|
private readonly api = inject(ApiService)
|
||||||
private readonly i18n = inject(i18nPipe)
|
private readonly i18n = inject(i18nPipe)
|
||||||
|
|
||||||
|
readonly form = viewChild(FormComponent)
|
||||||
readonly spec = toSignal(from(configBuilderToSpec(this.passwordSpec())))
|
readonly spec = toSignal(from(configBuilderToSpec(this.passwordSpec())))
|
||||||
readonly buttons = [
|
readonly buttons = [
|
||||||
{
|
{
|
||||||
@@ -119,7 +124,12 @@ export default class SystemPasswordComponent {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await this.api.resetPassword({ oldPassword, newPassword })
|
await this.api.resetPassword({ oldPassword, newPassword })
|
||||||
this.dialog.openAlert('Password changed').subscribe()
|
this.form()?.form.reset()
|
||||||
|
this.alerts
|
||||||
|
.open(this.i18n.transform('Password changed'), {
|
||||||
|
appearance: 'positive',
|
||||||
|
})
|
||||||
|
.subscribe()
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
this.errorService.handleError(e)
|
this.errorService.handleError(e)
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
Reference in New Issue
Block a user