mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 12:11:56 +00:00
Refactor i18n approach (#2875)
* Refactor i18n approach * chore: move to shared * chore: add default * create DialogService and update LoadingService (#2876) * complete translation infra for ui project, currently broken * cleanup and more dictionaries * chore: fix --------- Co-authored-by: Matt Hill <MattDHill@users.noreply.github.com> Co-authored-by: Matt Hill <mattnine@protonmail.com>
This commit is contained in:
@@ -1,7 +1,11 @@
|
||||
import { inject, Injectable } from '@angular/core'
|
||||
import { ErrorService, LoadingService } from '@start9labs/shared'
|
||||
import { TuiDialogService } from '@taiga-ui/core'
|
||||
import { TUI_CONFIRM } from '@taiga-ui/kit'
|
||||
import {
|
||||
DialogService,
|
||||
ErrorService,
|
||||
i18nKey,
|
||||
i18nPipe,
|
||||
LoadingService,
|
||||
} from '@start9labs/shared'
|
||||
import { PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
import { filter } from 'rxjs'
|
||||
import {
|
||||
@@ -31,10 +35,11 @@ const allowedStatuses = {
|
||||
})
|
||||
export class ActionService {
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly dialogs = inject(TuiDialogService)
|
||||
private readonly dialog = inject(DialogService)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
private readonly loader = inject(LoadingService)
|
||||
private readonly formDialog = inject(FormDialogService)
|
||||
private readonly i18n = inject(i18nPipe)
|
||||
|
||||
async present(data: PackageActionData) {
|
||||
const { pkgInfo, actionInfo } = data
|
||||
@@ -46,19 +51,19 @@ export class ActionService {
|
||||
) {
|
||||
if (actionInfo.metadata.hasInput) {
|
||||
this.formDialog.open<PackageActionData>(ActionInputModal, {
|
||||
label: actionInfo.metadata.name,
|
||||
label: actionInfo.metadata.name as i18nKey,
|
||||
data,
|
||||
})
|
||||
} else {
|
||||
if (actionInfo.metadata.warning) {
|
||||
this.dialogs
|
||||
.open(TUI_CONFIRM, {
|
||||
this.dialog
|
||||
.openConfirm({
|
||||
label: 'Warning',
|
||||
size: 's',
|
||||
data: {
|
||||
no: 'Cancel',
|
||||
yes: 'Run',
|
||||
content: actionInfo.metadata.warning,
|
||||
content: actionInfo.metadata.warning as i18nKey,
|
||||
},
|
||||
})
|
||||
.pipe(filter(Boolean))
|
||||
@@ -71,7 +76,6 @@ export class ActionService {
|
||||
const statuses = [...allowedStatuses[actionInfo.metadata.allowedStatuses]]
|
||||
const last = statuses.pop()
|
||||
let statusesStr = statuses.join(', ')
|
||||
let error = ''
|
||||
if (statuses.length) {
|
||||
if (statuses.length > 1) {
|
||||
// oxford comma
|
||||
@@ -79,18 +83,14 @@ export class ActionService {
|
||||
}
|
||||
statusesStr += ` or ${last}`
|
||||
} else if (last) {
|
||||
statusesStr = `${last}`
|
||||
} else {
|
||||
error = `There is no status for which this action may be run. This is a bug. Please file an issue with the service maintainer.`
|
||||
statusesStr = last
|
||||
}
|
||||
|
||||
this.dialogs
|
||||
.open(
|
||||
error ||
|
||||
`Action "${actionInfo.metadata.name}" can only be executed when service is ${statusesStr}`,
|
||||
this.dialog
|
||||
.openAlert(
|
||||
`${this.i18n.transform('Action can only be executed when service is')} ${statusesStr}` as i18nKey,
|
||||
{
|
||||
label: 'Forbidden',
|
||||
size: 's',
|
||||
},
|
||||
)
|
||||
.pipe(filter(Boolean))
|
||||
@@ -99,7 +99,7 @@ export class ActionService {
|
||||
}
|
||||
|
||||
async execute(packageId: string, actionId: string, input?: object) {
|
||||
const loader = this.loader.open('Loading...').subscribe()
|
||||
const loader = this.loader.open('Loading').subscribe()
|
||||
|
||||
try {
|
||||
const res = await this.api.runAction({
|
||||
@@ -111,14 +111,16 @@ export class ActionService {
|
||||
if (!res) return
|
||||
|
||||
if (res.result) {
|
||||
this.dialogs
|
||||
.open(new PolymorpheusComponent(ActionSuccessPage), {
|
||||
label: res.title,
|
||||
this.dialog
|
||||
.openComponent(new PolymorpheusComponent(ActionSuccessPage), {
|
||||
label: res.title as i18nKey,
|
||||
data: res,
|
||||
})
|
||||
.subscribe()
|
||||
} else if (res.message) {
|
||||
this.dialogs.open(res.message, { label: res.title }).subscribe()
|
||||
this.dialog
|
||||
.openAlert(res.message as i18nKey, { label: res.title as i18nKey })
|
||||
.subscribe()
|
||||
}
|
||||
} catch (e: any) {
|
||||
this.errorService.handleError(e)
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
import { inject, Injectable } from '@angular/core'
|
||||
import { ErrorService, LoadingService } from '@start9labs/shared'
|
||||
import { T } from '@start9labs/start-sdk'
|
||||
import { TuiDialogOptions, TuiDialogService } from '@taiga-ui/core'
|
||||
import { TUI_CONFIRM, TuiConfirmData } from '@taiga-ui/kit'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import {
|
||||
defaultIfEmpty,
|
||||
defer,
|
||||
filter,
|
||||
firstValueFrom,
|
||||
of,
|
||||
switchMap,
|
||||
} from 'rxjs'
|
||||
DialogService,
|
||||
ErrorService,
|
||||
i18nKey,
|
||||
i18nPipe,
|
||||
LoadingService,
|
||||
} from '@start9labs/shared'
|
||||
import { T } from '@start9labs/start-sdk'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import { defaultIfEmpty, defer, filter, firstValueFrom, of } from 'rxjs'
|
||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||
import { DataModel } from 'src/app/services/patch-db/data-model'
|
||||
import { getAllPackages } from 'src/app/utils/get-package-data'
|
||||
@@ -21,23 +18,25 @@ import { hasCurrentDeps } from 'src/app/utils/has-deps'
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class ControlsService {
|
||||
private readonly dialogs = inject(TuiDialogService)
|
||||
private readonly dialog = inject(DialogService)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
private readonly loader = inject(LoadingService)
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly patch = inject<PatchDB<DataModel>>(PatchDB)
|
||||
private readonly i18n = inject(i18nPipe)
|
||||
|
||||
async start({ title, alerts, id }: T.Manifest, unmet: boolean) {
|
||||
const deps = `${title} has unmet dependencies. It will not work as expected.`
|
||||
const deps =
|
||||
`${title} ${this.i18n.transform('has unmet dependencies. It will not work as expected.')}` as i18nKey
|
||||
|
||||
if (
|
||||
(unmet && !(await this.alert(deps))) ||
|
||||
(alerts.start && !(await this.alert(alerts.start)))
|
||||
(alerts.start && !(await this.alert(alerts.start as i18nKey)))
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
const loader = this.loader.open(`Starting...`).subscribe()
|
||||
const loader = this.loader.open('Starting').subscribe()
|
||||
|
||||
try {
|
||||
await this.api.startPackage({ id })
|
||||
@@ -49,7 +48,7 @@ export class ControlsService {
|
||||
}
|
||||
|
||||
async stop({ id, title, alerts }: T.Manifest) {
|
||||
const depMessage = `Services that depend on ${title} will no longer work properly and may crash`
|
||||
const depMessage = `${this.i18n.transform('Services that depend on')} ${title} ${this.i18n.transform('will no longer work properly and may crash.')}`
|
||||
let content = alerts.stop || ''
|
||||
|
||||
if (hasCurrentDeps(id, await getAllPackages(this.patch))) {
|
||||
@@ -58,12 +57,20 @@ export class ControlsService {
|
||||
|
||||
defer(() =>
|
||||
content
|
||||
? this.dialogs
|
||||
.open(TUI_CONFIRM, getOptions(content, 'Stop'))
|
||||
? this.dialog
|
||||
.openConfirm({
|
||||
label: 'Warning',
|
||||
size: 's',
|
||||
data: {
|
||||
content: content as i18nKey,
|
||||
yes: 'Stop',
|
||||
no: 'Cancel',
|
||||
},
|
||||
})
|
||||
.pipe(filter(Boolean))
|
||||
: of(null),
|
||||
).subscribe(async () => {
|
||||
const loader = this.loader.open(`Stopping...`).subscribe()
|
||||
const loader = this.loader.open('Stopping').subscribe()
|
||||
|
||||
try {
|
||||
await this.api.stopPackage({ id })
|
||||
@@ -77,17 +84,24 @@ export class ControlsService {
|
||||
|
||||
async restart({ id, title }: T.Manifest) {
|
||||
const packages = await getAllPackages(this.patch)
|
||||
const options = getOptions(
|
||||
`Services that depend on ${title} may temporarily experiences issues`,
|
||||
'Restart',
|
||||
)
|
||||
|
||||
defer(() =>
|
||||
hasCurrentDeps(id, packages)
|
||||
? this.dialogs.open(TUI_CONFIRM, options).pipe(filter(Boolean))
|
||||
? this.dialog
|
||||
.openConfirm({
|
||||
label: 'Warning',
|
||||
size: 's',
|
||||
data: {
|
||||
content:
|
||||
`${this.i18n.transform('Services that depend on')} ${title} ${this.i18n.transform('may temporarily experiences issues')}` as i18nKey,
|
||||
yes: 'Restart',
|
||||
no: 'Cancel',
|
||||
},
|
||||
})
|
||||
.pipe(filter(Boolean))
|
||||
: of(null),
|
||||
).subscribe(async () => {
|
||||
const loader = this.loader.open(`Restarting...`).subscribe()
|
||||
const loader = this.loader.open('Restarting').subscribe()
|
||||
|
||||
try {
|
||||
await this.api.restartPackage({ id })
|
||||
@@ -99,26 +113,19 @@ export class ControlsService {
|
||||
})
|
||||
}
|
||||
|
||||
private alert(content: string): Promise<boolean> {
|
||||
private alert(content: i18nKey): Promise<boolean> {
|
||||
return firstValueFrom(
|
||||
this.dialogs
|
||||
.open<boolean>(TUI_CONFIRM, getOptions(content))
|
||||
this.dialog
|
||||
.openConfirm<boolean>({
|
||||
label: 'Warning',
|
||||
size: 's',
|
||||
data: {
|
||||
content,
|
||||
yes: 'Continue',
|
||||
no: 'Cancel',
|
||||
},
|
||||
})
|
||||
.pipe(defaultIfEmpty(false)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function getOptions(
|
||||
content: string,
|
||||
yes = 'Continue',
|
||||
): Partial<TuiDialogOptions<TuiConfirmData>> {
|
||||
return {
|
||||
label: 'Warning',
|
||||
size: 's',
|
||||
data: {
|
||||
content,
|
||||
yes,
|
||||
no: 'Cancel',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,26 @@
|
||||
import { inject, Injectable, Injector, Type } from '@angular/core'
|
||||
import { TuiDialogOptions, TuiDialogService } from '@taiga-ui/core'
|
||||
import { DialogService, i18nKey, i18nPipe } from '@start9labs/shared'
|
||||
import { TuiDialogOptions } from '@taiga-ui/core'
|
||||
import { TuiConfirmData, TuiConfirmService } from '@taiga-ui/kit'
|
||||
import { PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
|
||||
const PROMPT: Partial<TuiDialogOptions<TuiConfirmData>> = {
|
||||
label: 'Unsaved Changes',
|
||||
data: {
|
||||
content: 'You have unsaved changes. Are you sure you want to leave?',
|
||||
yes: 'Leave',
|
||||
no: 'Cancel',
|
||||
},
|
||||
}
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class FormDialogService {
|
||||
private readonly dialogs = inject(TuiDialogService)
|
||||
private readonly dialog = inject(DialogService)
|
||||
private readonly i18n = inject(i18nPipe)
|
||||
private readonly formService = new TuiConfirmService()
|
||||
private readonly prompt = this.formService.withConfirm(PROMPT)
|
||||
private readonly PROMPT: Partial<TuiDialogOptions<TuiConfirmData>> = {
|
||||
label: this.i18n.transform('Unsaved changes'),
|
||||
data: {
|
||||
content: this.i18n.transform(
|
||||
'You have unsaved changes. Are you sure you want to leave?',
|
||||
),
|
||||
yes: this.i18n.transform('Leave'),
|
||||
no: this.i18n.transform('Cancel'),
|
||||
},
|
||||
}
|
||||
|
||||
private readonly prompt = this.formService.withConfirm(this.PROMPT)
|
||||
private readonly injector = Injector.create({
|
||||
parent: inject(Injector),
|
||||
providers: [
|
||||
@@ -27,9 +31,14 @@ export class FormDialogService {
|
||||
],
|
||||
})
|
||||
|
||||
open<T>(component: Type<any>, options: Partial<TuiDialogOptions<T>> = {}) {
|
||||
this.dialogs
|
||||
.open(new PolymorpheusComponent(component, this.injector), {
|
||||
open<T>(
|
||||
component: Type<any>,
|
||||
options: Partial<TuiDialogOptions<T>> & {
|
||||
label?: i18nKey
|
||||
} = {},
|
||||
) {
|
||||
this.dialog
|
||||
.openComponent(new PolymorpheusComponent(component, this.injector), {
|
||||
closeable: this.prompt,
|
||||
dismissible: this.prompt,
|
||||
...options,
|
||||
|
||||
@@ -243,15 +243,15 @@ function listValidators(spec: IST.ValueSpecList): ValidatorFn[] {
|
||||
return validators
|
||||
}
|
||||
|
||||
function fileValidators(spec: IST.ValueSpecFile): ValidatorFn[] {
|
||||
const validators: ValidatorFn[] = []
|
||||
// function fileValidators(spec: IST.ValueSpecFile): ValidatorFn[] {
|
||||
// const validators: ValidatorFn[] = []
|
||||
|
||||
if (spec.required) {
|
||||
validators.push(Validators.required)
|
||||
}
|
||||
// if (spec.required) {
|
||||
// validators.push(Validators.required)
|
||||
// }
|
||||
|
||||
return validators
|
||||
}
|
||||
// return validators
|
||||
// }
|
||||
|
||||
export function numberInRange(
|
||||
min: number | null,
|
||||
|
||||
@@ -49,6 +49,7 @@ export class MarketplaceService {
|
||||
switchMap(url => this.fetchRegistry$(url)),
|
||||
filter(Boolean),
|
||||
map(registry => {
|
||||
// @TODO Aiden let's drop description. We do not use it. categories should just be Record<string, string>
|
||||
registry.info.categories = {
|
||||
all: {
|
||||
name: 'All',
|
||||
@@ -178,12 +179,13 @@ export class MarketplaceService {
|
||||
return from(this.api.getRegistryInfo(url)).pipe(
|
||||
map(info => ({
|
||||
...info,
|
||||
// @TODO Aiden let's drop description. We do not use it. categories should just be Record<string, string>
|
||||
categories: {
|
||||
all: {
|
||||
name: 'All',
|
||||
description: {
|
||||
short: 'All services',
|
||||
long: 'An unfiltered list of all services available on this registry.',
|
||||
short: '',
|
||||
long: '',
|
||||
},
|
||||
},
|
||||
...info.categories,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { inject, Injectable } from '@angular/core'
|
||||
import { ErrorService, MARKDOWN } from '@start9labs/shared'
|
||||
import { TuiDialogService } from '@taiga-ui/core'
|
||||
import { TuiResponsiveDialogService } from '@taiga-ui/addon-mobile'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import { firstValueFrom, merge, of, shareReplay, Subject } from 'rxjs'
|
||||
import { REPORT } from 'src/app/components/report.component'
|
||||
import { REPORT } from 'src/app/components/backup-report.component'
|
||||
import {
|
||||
ServerNotification,
|
||||
ServerNotifications,
|
||||
@@ -16,7 +16,7 @@ export class NotificationService {
|
||||
private readonly patch = inject<PatchDB<DataModel>>(PatchDB)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly dialogs = inject(TuiDialogService)
|
||||
private readonly dialogs = inject(TuiResponsiveDialogService)
|
||||
private readonly localUnreadCount$ = new Subject<number>()
|
||||
|
||||
readonly unreadCount$ = merge(
|
||||
|
||||
@@ -7,7 +7,7 @@ import { EOSService } from 'src/app/services/eos.service'
|
||||
import { ConnectionService } from 'src/app/services/connection.service'
|
||||
import { LocalStorageBootstrap } from './patch-db/local-storage-bootstrap'
|
||||
|
||||
// Get data from PatchDb after is starts and act upon it
|
||||
// @TODO Alex this file has just become checking for StartOS updates. Maybe it can be removed/simplified. I'm not sure why getMarketplace$() line is commented out, I assume we are checking for service updates somewhere else?
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
@@ -19,7 +19,6 @@ export class PatchDataService extends Observable<void> {
|
||||
this.bootstrapper.update(cache)
|
||||
|
||||
if (index === 0) {
|
||||
// check for updates to StartOS and services
|
||||
this.checkForUpdates()
|
||||
}
|
||||
}),
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Languages } from '@start9labs/shared'
|
||||
import { T } from '@start9labs/start-sdk'
|
||||
|
||||
export type DataModel = T.Public & { ui: UIData; packageData: AllPackageData }
|
||||
@@ -12,7 +13,7 @@ export type UIData = {
|
||||
}
|
||||
ackInstructions: Record<string, boolean>
|
||||
theme: string
|
||||
language: 'english' | 'spanish'
|
||||
language: Languages
|
||||
}
|
||||
|
||||
export type UIMarketplaceData = {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { PackageDataEntry } from 'src/app/services/patch-db/data-model'
|
||||
import { PkgDependencyErrors } from './dep-error.service'
|
||||
import { T } from '@start9labs/start-sdk'
|
||||
import { i18nKey } from '@start9labs/shared'
|
||||
|
||||
export interface PackageStatus {
|
||||
primary: PrimaryStatus
|
||||
@@ -65,7 +66,7 @@ function getHealthStatus(status: T.MainStatus): T.HealthStatus | null {
|
||||
}
|
||||
|
||||
export interface StatusRendering {
|
||||
display: string
|
||||
display: i18nKey
|
||||
color: string
|
||||
showDots?: boolean
|
||||
}
|
||||
@@ -138,7 +139,7 @@ export const PrimaryRendering: Record<PrimaryStatus, StatusRendering> = {
|
||||
showDots: false,
|
||||
},
|
||||
actionRequired: {
|
||||
display: 'Action Required',
|
||||
display: 'Task Required',
|
||||
color: 'warning',
|
||||
showDots: false,
|
||||
},
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
import { inject, Injectable } from '@angular/core'
|
||||
import { Router } from '@angular/router'
|
||||
import { ErrorService, LoadingService } from '@start9labs/shared'
|
||||
import {
|
||||
DialogService,
|
||||
ErrorService,
|
||||
i18nKey,
|
||||
i18nPipe,
|
||||
LoadingService,
|
||||
} from '@start9labs/shared'
|
||||
import { T } from '@start9labs/start-sdk'
|
||||
import { TuiDialogService } from '@taiga-ui/core'
|
||||
import { TUI_CONFIRM } from '@taiga-ui/kit'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import { filter } from 'rxjs'
|
||||
import { getAllPackages } from '../utils/get-package-data'
|
||||
@@ -17,13 +21,14 @@ import { DataModel } from './patch-db/data-model'
|
||||
export class StandardActionsService {
|
||||
private readonly patch = inject<PatchDB<DataModel>>(PatchDB)
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly dialogs = inject(TuiDialogService)
|
||||
private readonly dialog = inject(DialogService)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
private readonly loader = inject(LoadingService)
|
||||
private readonly router = inject(Router)
|
||||
private readonly i18n = inject(i18nPipe)
|
||||
|
||||
async rebuild(id: string) {
|
||||
const loader = this.loader.open(`Rebuilding Container...`).subscribe()
|
||||
const loader = this.loader.open('Rebuilding container').subscribe()
|
||||
|
||||
try {
|
||||
await this.api.rebuildPackage({ id })
|
||||
@@ -38,18 +43,18 @@ export class StandardActionsService {
|
||||
async uninstall({ id, title, alerts }: T.Manifest): Promise<void> {
|
||||
let content =
|
||||
alerts.uninstall ||
|
||||
`Uninstalling ${title} will permanently delete its data`
|
||||
`${this.i18n.transform('Uninstalling')} ${title} ${this.i18n.transform('will permanently delete its data.')}`
|
||||
|
||||
if (hasCurrentDeps(id, await getAllPackages(this.patch))) {
|
||||
content = `${content}. Services that depend on ${title} will no longer work properly and may crash`
|
||||
content = `${content}. ${this.i18n.transform('Services that depend on')} ${title} ${this.i18n.transform('will no longer work properly and may crash.')}`
|
||||
}
|
||||
|
||||
this.dialogs
|
||||
.open(TUI_CONFIRM, {
|
||||
this.dialog
|
||||
.openConfirm({
|
||||
label: 'Warning',
|
||||
size: 's',
|
||||
data: {
|
||||
content,
|
||||
content: content as i18nKey,
|
||||
yes: 'Uninstall',
|
||||
no: 'Cancel',
|
||||
},
|
||||
@@ -59,7 +64,7 @@ export class StandardActionsService {
|
||||
}
|
||||
|
||||
private async doUninstall(id: string) {
|
||||
const loader = this.loader.open(`Beginning uninstall...`).subscribe()
|
||||
const loader = this.loader.open('Beginning uninstall').subscribe()
|
||||
|
||||
try {
|
||||
await this.api.uninstallPackage({ id })
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { inject, Injectable } from '@angular/core'
|
||||
import { CanActivateFn, IsActiveMatchOptions, Router } from '@angular/router'
|
||||
import { DialogService } from '@start9labs/shared'
|
||||
import { TUI_TRUE_HANDLER } from '@taiga-ui/cdk'
|
||||
import { TuiAlertService } from '@taiga-ui/core'
|
||||
import {
|
||||
BehaviorSubject,
|
||||
combineLatest,
|
||||
@@ -41,7 +41,7 @@ const OPTIONS: IsActiveMatchOptions = {
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class StateService extends Observable<RR.ServerState | null> {
|
||||
private readonly alerts = inject(TuiAlertService)
|
||||
private readonly dialog = inject(DialogService)
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly router = inject(Router)
|
||||
private readonly network$ = inject(NetworkService)
|
||||
@@ -91,8 +91,8 @@ export class StateService extends Observable<RR.ServerState | null> {
|
||||
.pipe(
|
||||
exhaustMap(() =>
|
||||
concat(
|
||||
this.alerts
|
||||
.open('Trying to reach server', {
|
||||
this.dialog
|
||||
.openAlert('Trying to reach server', {
|
||||
label: 'State unknown',
|
||||
autoClose: 0,
|
||||
appearance: 'negative',
|
||||
@@ -104,8 +104,8 @@ export class StateService extends Observable<RR.ServerState | null> {
|
||||
),
|
||||
),
|
||||
),
|
||||
this.alerts.open('Connection restored', {
|
||||
label: 'Server reached',
|
||||
this.dialog.openAlert('Connection restored', {
|
||||
label: 'Server connected',
|
||||
appearance: 'positive',
|
||||
}),
|
||||
),
|
||||
|
||||
@@ -5,6 +5,7 @@ import { combineLatest, map, startWith } from 'rxjs'
|
||||
import { ConnectionService } from './connection.service'
|
||||
import { NetworkService } from './network.service'
|
||||
import { DataModel } from './patch-db/data-model'
|
||||
import { i18nKey } from '@start9labs/shared'
|
||||
|
||||
export const STATUS = new InjectionToken('', {
|
||||
factory: () =>
|
||||
@@ -29,33 +30,40 @@ export const STATUS = new InjectionToken('', {
|
||||
),
|
||||
})
|
||||
|
||||
const OFFLINE = {
|
||||
const OFFLINE: ServerStatus = {
|
||||
message: 'No Internet',
|
||||
color: 'var(--tui-status-negative)',
|
||||
icon: '@tui.cloud-off',
|
||||
status: 'error',
|
||||
}
|
||||
const CONNECTING = {
|
||||
const CONNECTING: ServerStatus = {
|
||||
message: 'Connecting',
|
||||
color: 'var(--tui-status-warning)',
|
||||
icon: '@tui.cloud-off',
|
||||
status: 'warning',
|
||||
}
|
||||
const SHUTTING_DOWN = {
|
||||
message: 'Shutting Down',
|
||||
const SHUTTING_DOWN: ServerStatus = {
|
||||
message: 'Shutting down',
|
||||
color: 'var(--tui-status-neutral)',
|
||||
icon: '@tui.power',
|
||||
status: 'neutral',
|
||||
}
|
||||
const RESTARTING = {
|
||||
const RESTARTING: ServerStatus = {
|
||||
message: 'Restarting',
|
||||
color: 'var(--tui-status-neutral)',
|
||||
icon: '@tui.power',
|
||||
status: 'neutral',
|
||||
}
|
||||
const CONNECTED = {
|
||||
const CONNECTED: ServerStatus = {
|
||||
message: 'Connected',
|
||||
color: 'var(--tui-status-positive)',
|
||||
icon: '@tui.cloud',
|
||||
status: 'success',
|
||||
}
|
||||
|
||||
type ServerStatus = {
|
||||
message: i18nKey
|
||||
color: string
|
||||
icon: string
|
||||
status: 'error' | 'warning' | 'neutral' | 'success'
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user