mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 10:21:52 +00:00
Merge branch 'next/major' of github.com:Start9Labs/start-os into feat/preferred-port-design
This commit is contained in:
@@ -5,7 +5,7 @@ export default {
|
||||
2: 'Aktualisieren',
|
||||
4: 'System',
|
||||
5: 'Allgemein',
|
||||
6: 'E-Mail',
|
||||
6: 'SMTP',
|
||||
7: 'Sicherung erstellen',
|
||||
8: 'Sicherung wiederherstellen',
|
||||
9: 'Zum Login gehen',
|
||||
@@ -385,8 +385,8 @@ export default {
|
||||
405: 'Verbunden',
|
||||
406: 'Vergessen',
|
||||
407: 'WiFi-Zugangsdaten',
|
||||
408: 'Veraltet',
|
||||
409: 'Die WLAN-Unterstützung wird in StartOS v0.4.1 entfernt. Wenn Sie keinen Zugriff auf Ethernet haben, können Sie einen WLAN-Extender verwenden, um sich mit dem lokalen Netzwerk zu verbinden und dann Ihren Server über Ethernet an den Extender anschließen. Bitte wenden Sie sich bei Fragen an den Start9-Support.',
|
||||
408: 'Mit verstecktem Netzwerk verbinden',
|
||||
409: 'Verbinden mit',
|
||||
410: 'Bekannte Netzwerke',
|
||||
411: 'Weitere Netzwerke',
|
||||
412: 'WiFi ist deaktiviert',
|
||||
|
||||
@@ -4,7 +4,7 @@ export const ENGLISH: Record<string, number> = {
|
||||
'Update': 2, // verb
|
||||
'System': 4, // as in, system preferences
|
||||
'General': 5, // as in, general settings
|
||||
'Email': 6,
|
||||
'SMTP': 6,
|
||||
'Create Backup': 7, // create a backup
|
||||
'Restore Backup': 8, // restore from backup
|
||||
'Go to login': 9,
|
||||
@@ -384,8 +384,8 @@ export const ENGLISH: Record<string, number> = {
|
||||
'Connected': 405,
|
||||
'Forget': 406, // as in, delete or remove
|
||||
'WiFi Credentials': 407,
|
||||
'Deprecated': 408,
|
||||
'WiFi support will be removed in StartOS v0.4.1. If you do not have access to Ethernet, you can use a WiFi extender to connect to the local network, then connect your server to the extender via Ethernet. Please contact Start9 support with any questions or concerns.': 409,
|
||||
'Connect to hidden network': 408,
|
||||
'Connect to': 409, // followed by a network name, e.g. "Connect to MyWiFi?"
|
||||
'Known Networks': 410,
|
||||
'Other Networks': 411,
|
||||
'WiFi is disabled': 412,
|
||||
|
||||
@@ -5,7 +5,7 @@ export default {
|
||||
2: 'Actualizar',
|
||||
4: 'Sistema',
|
||||
5: 'General',
|
||||
6: 'Correo electrónico',
|
||||
6: 'SMTP',
|
||||
7: 'Crear copia de seguridad',
|
||||
8: 'Restaurar copia de seguridad',
|
||||
9: 'Ir a inicio de sesión',
|
||||
@@ -385,8 +385,8 @@ export default {
|
||||
405: 'Conectado',
|
||||
406: 'Olvidar',
|
||||
407: 'Credenciales WiFi',
|
||||
408: 'Obsoleto',
|
||||
409: 'El soporte para WiFi será eliminado en StartOS v0.4.1. Si no tienes acceso a Ethernet, puedes usar un extensor WiFi para conectarte a la red local y luego conectar tu servidor al extensor por Ethernet. Por favor, contacta al soporte de Start9 si tienes dudas o inquietudes.',
|
||||
408: 'Conectar a red oculta',
|
||||
409: 'Conectar a',
|
||||
410: 'Redes conocidas',
|
||||
411: 'Otras redes',
|
||||
412: 'WiFi está deshabilitado',
|
||||
|
||||
@@ -5,7 +5,7 @@ export default {
|
||||
2: 'Mettre à jour',
|
||||
4: 'Système',
|
||||
5: 'Général',
|
||||
6: 'Email',
|
||||
6: 'SMTP',
|
||||
7: 'Créer une sauvegarde',
|
||||
8: 'Restaurer une sauvegarde',
|
||||
9: 'Se connecter',
|
||||
@@ -385,8 +385,8 @@ export default {
|
||||
405: 'Connecté',
|
||||
406: 'Oublier',
|
||||
407: 'Identifiants WiFi',
|
||||
408: 'Obsolète',
|
||||
409: 'Le support WiFi sera supprimé dans StartOS v0.4.1. Si vous n’avez pas accès à internet via Ethernet, vous pouvez utiliser un répéteur WiFi pour vous connecter au réseau local, puis brancher votre serveur sur le répéteur en Ethernet. Contactez le support Start9 pour toute question.',
|
||||
408: 'Se connecter à un réseau masqué',
|
||||
409: 'Se connecter à',
|
||||
410: 'Réseaux connus',
|
||||
411: 'Autres réseaux',
|
||||
412: 'Le WiFi est désactivé',
|
||||
|
||||
@@ -5,7 +5,7 @@ export default {
|
||||
2: 'Aktualizuj',
|
||||
4: 'Ustawienia',
|
||||
5: 'Ogólne',
|
||||
6: 'E-mail',
|
||||
6: 'SMTP',
|
||||
7: 'Utwórz kopię zapasową',
|
||||
8: 'Przywróć z kopii zapasowej',
|
||||
9: 'Przejdź do logowania',
|
||||
@@ -385,8 +385,8 @@ export default {
|
||||
405: 'Połączono',
|
||||
406: 'Zapomnij',
|
||||
407: 'Dane logowania WiFi',
|
||||
408: 'Przestarzałe',
|
||||
409: 'Obsługa WiFi zostanie usunięta w StartOS v0.4.1. Jeśli nie masz dostępu do sieci Ethernet, możesz użyć wzmacniacza WiFi do połączenia z siecią lokalną, a następnie podłączyć serwer do wzmacniacza przez Ethernet. W razie pytań lub wątpliwości skontaktuj się z pomocą techniczną Start9.',
|
||||
408: 'Połącz z ukrytą siecią',
|
||||
409: 'Połącz z',
|
||||
410: 'Znane sieci',
|
||||
411: 'Inne sieci',
|
||||
412: 'WiFi jest wyłączone',
|
||||
|
||||
@@ -28,7 +28,7 @@ import { configBuilderToSpec } from 'src/app/utils/configBuilderToSpec'
|
||||
<a routerLink=".." tuiIconButton iconStart="@tui.arrow-left">
|
||||
{{ 'Back' | i18n }}
|
||||
</a>
|
||||
{{ 'Email' | i18n }}
|
||||
{{ 'SMTP' | i18n }}
|
||||
</ng-container>
|
||||
@if (form$ | async; as form) {
|
||||
<form [formGroup]="form">
|
||||
|
||||
@@ -160,7 +160,11 @@ export default class SystemSSHComponent {
|
||||
const loader = this.loader.open('Deleting').subscribe()
|
||||
|
||||
try {
|
||||
await this.api.deleteSshKey({ fingerprint: '' })
|
||||
await Promise.all(
|
||||
fingerprints.map(fingerprint =>
|
||||
this.api.deleteSshKey({ fingerprint }),
|
||||
),
|
||||
)
|
||||
this.local$.next(
|
||||
all.filter(s => !fingerprints.includes(s.fingerprint)),
|
||||
)
|
||||
|
||||
@@ -5,8 +5,23 @@ import {
|
||||
inject,
|
||||
Input,
|
||||
} from '@angular/core'
|
||||
import { ErrorService, i18nPipe, LoadingService } from '@start9labs/shared'
|
||||
import { TuiButton, TuiIcon, TuiTitle } from '@taiga-ui/core'
|
||||
import { NgTemplateOutlet } from '@angular/common'
|
||||
import {
|
||||
DialogService,
|
||||
ErrorService,
|
||||
i18nPipe,
|
||||
LoadingService,
|
||||
} from '@start9labs/shared'
|
||||
import { filter } from 'rxjs'
|
||||
import { IST } from '@start9labs/start-sdk'
|
||||
import {
|
||||
TuiButton,
|
||||
TuiDataList,
|
||||
TuiDropdown,
|
||||
TuiIcon,
|
||||
TuiTextfield,
|
||||
TuiTitle,
|
||||
} from '@taiga-ui/core'
|
||||
import { TuiBadge, TuiFade } from '@taiga-ui/kit'
|
||||
import { TuiCell } from '@taiga-ui/layout'
|
||||
import {
|
||||
@@ -22,50 +37,78 @@ import { wifiSpec } from './wifi.const'
|
||||
@Component({
|
||||
selector: '[wifi]',
|
||||
template: `
|
||||
@for (network of wifi; track $index) {
|
||||
@if (network.ssid) {
|
||||
<ng-template #row let-network>
|
||||
@if (getSignal(network.strength); as signal) {
|
||||
<tui-icon
|
||||
background="@tui.wifi"
|
||||
[icon]="signal.icon"
|
||||
[style.background]="'var(--tui-background-neutral-2)'"
|
||||
[style.color]="signal.color"
|
||||
/>
|
||||
} @else {
|
||||
<tui-icon icon="@tui.wifi-off" />
|
||||
}
|
||||
<tui-icon
|
||||
[icon]="network.security.length ? '@tui.lock' : '@tui.lock-open'"
|
||||
/>
|
||||
<div tuiTitle>
|
||||
<strong tuiFade>
|
||||
{{ network.ssid }}
|
||||
</strong>
|
||||
</div>
|
||||
@if (network.connected) {
|
||||
<tui-badge appearance="positive">
|
||||
{{ 'Connected' | i18n }}
|
||||
</tui-badge>
|
||||
}
|
||||
@if (network.connected === false) {
|
||||
<button
|
||||
tuiCell
|
||||
[disabled]="network.connected"
|
||||
(click)="prompt(network)"
|
||||
tuiIconButton
|
||||
tuiDropdown
|
||||
size="s"
|
||||
appearance="flat-grayscale"
|
||||
iconStart="@tui.ellipsis-vertical"
|
||||
[(tuiDropdownOpen)]="open"
|
||||
>
|
||||
<div tuiTitle>
|
||||
<strong tuiFade>
|
||||
{{ network.ssid }}
|
||||
@if (network.connected) {
|
||||
<tui-badge appearance="positive">
|
||||
{{ 'Connected' | i18n }}
|
||||
</tui-badge>
|
||||
}
|
||||
</strong>
|
||||
</div>
|
||||
@if (network.connected !== undefined) {
|
||||
{{ 'More' | i18n }}
|
||||
<tui-data-list *tuiTextfieldDropdown>
|
||||
<button
|
||||
tuiIconButton
|
||||
size="s"
|
||||
appearance="icon"
|
||||
iconStart="@tui.trash-2"
|
||||
(click.stop)="forget(network)"
|
||||
tuiOption
|
||||
new
|
||||
iconStart="@tui.wifi"
|
||||
(click)="prompt(network)"
|
||||
>
|
||||
{{ 'Connect' | i18n }}
|
||||
</button>
|
||||
<button
|
||||
tuiOption
|
||||
new
|
||||
iconStart="@tui.trash"
|
||||
class="g-negative"
|
||||
(click)="forget(network)"
|
||||
>
|
||||
{{ 'Forget' | i18n }}
|
||||
</button>
|
||||
} @else {
|
||||
<tui-icon
|
||||
[icon]="network.security.length ? '@tui.lock' : '@tui.lock-open'"
|
||||
/>
|
||||
}
|
||||
@if (getSignal(network.strength); as signal) {
|
||||
<tui-icon
|
||||
background="@tui.wifi"
|
||||
[icon]="signal.icon"
|
||||
[style.background]="'var(--tui-background-neutral-2)'"
|
||||
[style.color]="signal.color"
|
||||
/>
|
||||
} @else {
|
||||
<tui-icon icon="@tui.wifi-off" />
|
||||
}
|
||||
</tui-data-list>
|
||||
</button>
|
||||
}
|
||||
</ng-template>
|
||||
@for (network of wifi; track $index) {
|
||||
@if (network.ssid) {
|
||||
@if (network.connected === undefined) {
|
||||
<button tuiCell (click)="prompt(network)">
|
||||
<ng-container
|
||||
*ngTemplateOutlet="row; context: { $implicit: network }"
|
||||
/>
|
||||
</button>
|
||||
} @else {
|
||||
<div tuiCell>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="row; context: { $implicit: network }"
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
styles: `
|
||||
@@ -75,8 +118,6 @@ import { wifiSpec } from './wifi.const'
|
||||
}
|
||||
|
||||
[tuiCell] {
|
||||
padding-inline: 1rem !important;
|
||||
|
||||
&:disabled > * {
|
||||
opacity: 1;
|
||||
}
|
||||
@@ -88,11 +129,24 @@ import { wifiSpec } from './wifi.const'
|
||||
}
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [TuiCell, TuiTitle, TuiBadge, TuiButton, TuiIcon, TuiFade, i18nPipe],
|
||||
imports: [
|
||||
NgTemplateOutlet,
|
||||
TuiCell,
|
||||
TuiTitle,
|
||||
TuiBadge,
|
||||
TuiButton,
|
||||
TuiIcon,
|
||||
TuiFade,
|
||||
TuiDropdown,
|
||||
TuiDataList,
|
||||
TuiTextfield,
|
||||
i18nPipe,
|
||||
],
|
||||
})
|
||||
export class WifiTableComponent {
|
||||
private readonly loader = inject(LoadingService)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
private readonly dialogs = inject(DialogService)
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly formDialog = inject(FormDialogService)
|
||||
private readonly component = inject(SystemWifiComponent)
|
||||
@@ -102,6 +156,8 @@ export class WifiTableComponent {
|
||||
@Input()
|
||||
wifi: readonly Wifi[] = []
|
||||
|
||||
open = false
|
||||
|
||||
getSignal(signal: number) {
|
||||
if (signal < 5) {
|
||||
return null
|
||||
@@ -141,17 +197,30 @@ export class WifiTableComponent {
|
||||
|
||||
async prompt(network: Wifi): Promise<void> {
|
||||
if (!network.security.length) {
|
||||
await this.component.saveAndConnect(network.ssid)
|
||||
this.dialogs
|
||||
.openConfirm({
|
||||
label: `${this.i18n.transform('Connect to')} ${network.ssid}?`,
|
||||
size: 's',
|
||||
})
|
||||
.pipe(filter(Boolean))
|
||||
.subscribe(() => this.component.saveAndConnect(network.ssid))
|
||||
} else {
|
||||
const ssid = wifiSpec.spec['ssid'] as IST.ValueSpecText
|
||||
const spec: IST.InputSpec = {
|
||||
...wifiSpec.spec,
|
||||
ssid: { ...ssid, disabled: 'ssid', default: network.ssid },
|
||||
}
|
||||
|
||||
this.formDialog.open<FormContext<WiFiForm>>(FormComponent, {
|
||||
label: 'Password needed',
|
||||
data: {
|
||||
spec: wifiSpec.spec,
|
||||
spec,
|
||||
value: { ssid: network.ssid, password: '' },
|
||||
buttons: [
|
||||
{
|
||||
text: this.i18n.transform('Connect')!,
|
||||
handler: async ({ ssid, password }) =>
|
||||
this.component.saveAndConnect(ssid, password),
|
||||
handler: async ({ password }) =>
|
||||
this.component.saveAndConnect(network.ssid, password),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -8,6 +8,7 @@ import { toSignal } from '@angular/core/rxjs-interop'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { RouterLink } from '@angular/router'
|
||||
import {
|
||||
DocsLinkDirective,
|
||||
ErrorService,
|
||||
i18nKey,
|
||||
i18nPipe,
|
||||
@@ -19,11 +20,9 @@ import {
|
||||
TuiAppearance,
|
||||
TuiButton,
|
||||
TuiLoader,
|
||||
TuiNotification,
|
||||
TuiTitle,
|
||||
} from '@taiga-ui/core'
|
||||
import { TuiSwitch } from '@taiga-ui/kit'
|
||||
import { TuiCardLarge, TuiHeader } from '@taiga-ui/layout'
|
||||
import { TuiCardLarge } from '@taiga-ui/layout'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import { catchError, defer, map, merge, Observable, of, Subject } from 'rxjs'
|
||||
import {
|
||||
@@ -47,23 +46,20 @@ import { wifiSpec } from './wifi.const'
|
||||
</a>
|
||||
WiFi
|
||||
</ng-container>
|
||||
<header tuiHeader>
|
||||
<tui-notification appearance="negative">
|
||||
<div tuiTitle>
|
||||
{{ 'Deprecated' | i18n }}
|
||||
<div tuiSubtitle>
|
||||
{{
|
||||
'WiFi support will be removed in StartOS v0.4.1. If you do not have access to Ethernet, you can use a WiFi extender to connect to the local network, then connect your server to the extender via Ethernet. Please contact Start9 support with any questions or concerns.'
|
||||
| i18n
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</tui-notification>
|
||||
</header>
|
||||
@if (status()?.interface) {
|
||||
<section class="g-card">
|
||||
<header>
|
||||
Wi-Fi
|
||||
<a
|
||||
tuiIconButton
|
||||
size="xs"
|
||||
docsLink
|
||||
path="/user-manual/wifi.html"
|
||||
appearance="icon"
|
||||
iconStart="@tui.external-link"
|
||||
>
|
||||
{{ 'Documentation' | i18n }}
|
||||
</a>
|
||||
<input
|
||||
type="checkbox"
|
||||
tuiSwitch
|
||||
@@ -92,8 +88,8 @@ import { wifiSpec } from './wifi.const'
|
||||
></div>
|
||||
}
|
||||
<p>
|
||||
<button tuiButton (click)="other(data)">
|
||||
{{ 'Add' | i18n }}
|
||||
<button tuiButton (click)="other(data)" appearance="flat">
|
||||
+ {{ 'Connect to hidden network' | i18n }}
|
||||
</button>
|
||||
</p>
|
||||
} @else {
|
||||
@@ -128,10 +124,8 @@ import { wifiSpec } from './wifi.const'
|
||||
TitleDirective,
|
||||
RouterLink,
|
||||
PlaceholderComponent,
|
||||
TuiHeader,
|
||||
TuiTitle,
|
||||
TuiNotification,
|
||||
i18nPipe,
|
||||
DocsLinkDirective,
|
||||
],
|
||||
})
|
||||
export default class SystemWifiComponent {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { AsyncPipe } from '@angular/common'
|
||||
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
|
||||
import { toSignal } from '@angular/core/rxjs-interop'
|
||||
import { RouterModule } from '@angular/router'
|
||||
@@ -6,12 +5,9 @@ import { i18nPipe } from '@start9labs/shared'
|
||||
import { TuiIcon, TuiTitle } from '@taiga-ui/core'
|
||||
import { TuiBadgeNotification } from '@taiga-ui/kit'
|
||||
import { TuiCell } from '@taiga-ui/layout'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import { BadgeService } from 'src/app/services/badge.service'
|
||||
import { DataModel } from 'src/app/services/patch-db/data-model'
|
||||
import { TitleDirective } from 'src/app/services/title.service'
|
||||
import { SYSTEM_MENU } from './system.const'
|
||||
import { map } from 'rxjs'
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
@@ -26,9 +22,6 @@ import { map } from 'rxjs'
|
||||
tuiCell="s"
|
||||
routerLinkActive="active"
|
||||
[routerLink]="page.link"
|
||||
[style.display]="
|
||||
!(wifiEnabled$ | async) && page.item === 'WiFi' ? 'none' : null
|
||||
"
|
||||
>
|
||||
<tui-icon [icon]="page.icon" />
|
||||
<span tuiTitle>
|
||||
@@ -116,13 +109,9 @@ import { map } from 'rxjs'
|
||||
TitleDirective,
|
||||
TuiBadgeNotification,
|
||||
i18nPipe,
|
||||
AsyncPipe,
|
||||
],
|
||||
})
|
||||
export class SystemComponent {
|
||||
readonly menu = SYSTEM_MENU
|
||||
readonly badge = toSignal(inject(BadgeService).getCount('system'))
|
||||
readonly wifiEnabled$ = inject<PatchDB<DataModel>>(PatchDB)
|
||||
.watch$('serverInfo', 'network', 'wifi')
|
||||
.pipe(map(wifi => !!wifi.interface && wifi.enabled))
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ export const SYSTEM_MENU = [
|
||||
},
|
||||
{
|
||||
icon: '@tui.mail',
|
||||
item: 'Email',
|
||||
item: 'SMTP',
|
||||
link: 'email',
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user