mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 20:14:49 +00:00
chore: fix issues from dev channel (#2968)
This commit is contained in:
@@ -521,4 +521,5 @@ export default {
|
|||||||
520: 'Update verfügbar',
|
520: 'Update verfügbar',
|
||||||
521: 'Um das Problem zu beheben, siehe',
|
521: 'Um das Problem zu beheben, siehe',
|
||||||
522: 'SDK Version',
|
522: 'SDK Version',
|
||||||
|
523: 'Sicherungsbericht',
|
||||||
} satisfies i18n
|
} satisfies i18n
|
||||||
|
|||||||
@@ -520,4 +520,5 @@ export const ENGLISH = {
|
|||||||
'Update available': 520,
|
'Update available': 520,
|
||||||
'To resolve the issue, refer to': 521,
|
'To resolve the issue, refer to': 521,
|
||||||
'SDK Version': 522,
|
'SDK Version': 522,
|
||||||
|
'Backup Report': 523,
|
||||||
} as const
|
} as const
|
||||||
|
|||||||
@@ -521,4 +521,5 @@ export default {
|
|||||||
520: 'Actualización disponible',
|
520: 'Actualización disponible',
|
||||||
521: 'Para resolver el problema, consulta',
|
521: 'Para resolver el problema, consulta',
|
||||||
522: 'Versión de SDK',
|
522: 'Versión de SDK',
|
||||||
|
523: 'Informe de respaldo',
|
||||||
} satisfies i18n
|
} satisfies i18n
|
||||||
|
|||||||
@@ -521,4 +521,5 @@ export default {
|
|||||||
520: 'Mise à jour disponible',
|
520: 'Mise à jour disponible',
|
||||||
521: 'Pour résoudre le problème, consultez',
|
521: 'Pour résoudre le problème, consultez',
|
||||||
522: 'Version de SDK',
|
522: 'Version de SDK',
|
||||||
|
523: 'Rapport de sauvegarde',
|
||||||
} satisfies i18n
|
} satisfies i18n
|
||||||
|
|||||||
@@ -521,4 +521,5 @@ export default {
|
|||||||
520: 'Aktualizacja dostępna',
|
520: 'Aktualizacja dostępna',
|
||||||
521: 'Aby rozwiązać problem, zapoznaj się z',
|
521: 'Aby rozwiązać problem, zapoznaj się z',
|
||||||
522: 'Wersja SDK',
|
522: 'Wersja SDK',
|
||||||
|
523: 'Raport kopii zapasowej',
|
||||||
} satisfies i18n
|
} satisfies i18n
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
import { inject, Injectable, TemplateRef } from '@angular/core'
|
import { inject, Injectable } from '@angular/core'
|
||||||
import {
|
import {
|
||||||
TuiResponsiveDialogOptions,
|
TuiResponsiveDialogOptions,
|
||||||
TuiResponsiveDialogService,
|
TuiResponsiveDialogService,
|
||||||
} from '@taiga-ui/addon-mobile'
|
} from '@taiga-ui/addon-mobile'
|
||||||
import { TUI_CONFIRM, TuiConfirmData } from '@taiga-ui/kit'
|
import { TUI_CONFIRM, TuiConfirmData } from '@taiga-ui/kit'
|
||||||
import { PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
import {
|
||||||
|
PolymorpheusComponent,
|
||||||
|
PolymorpheusContent,
|
||||||
|
} from '@taiga-ui/polymorpheus'
|
||||||
import { PROMPT, PromptOptions } from '../components/prompt.component'
|
import { PROMPT, PromptOptions } from '../components/prompt.component'
|
||||||
import { i18nPipe } from '../i18n/i18n.pipe'
|
import { i18nPipe } from '../i18n/i18n.pipe'
|
||||||
import { i18nKey } from '../i18n/i18n.providers'
|
import { i18nKey } from '../i18n/i18n.providers'
|
||||||
@@ -73,7 +76,7 @@ export class DialogService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
openComponent<T = void>(
|
openComponent<T = void>(
|
||||||
component: PolymorpheusComponent<any> | TemplateRef<any>,
|
component: PolymorpheusContent,
|
||||||
options: Partial<TuiResponsiveDialogOptions<any>> & {
|
options: Partial<TuiResponsiveDialogOptions<any>> & {
|
||||||
label?: i18nKey
|
label?: i18nKey
|
||||||
} = {},
|
} = {},
|
||||||
|
|||||||
@@ -18,8 +18,16 @@ export abstract class Control<
|
|||||||
}
|
}
|
||||||
|
|
||||||
get readOnly(): boolean {
|
get readOnly(): boolean {
|
||||||
|
const def =
|
||||||
|
'default' in this.spec &&
|
||||||
|
this.spec.default != null &&
|
||||||
|
this.spec.default !== this.value
|
||||||
|
|
||||||
return (
|
return (
|
||||||
!!this.value && !!this.control.control?.pristine && this.control.immutable
|
!!this.value &&
|
||||||
|
!def &&
|
||||||
|
!!this.control.control?.pristine &&
|
||||||
|
this.control.immutable
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { TuiButton } from '@taiga-ui/core'
|
|
||||||
import { CommonModule, TitleCasePipe } from '@angular/common'
|
import { CommonModule, TitleCasePipe } from '@angular/common'
|
||||||
import {
|
import {
|
||||||
ChangeDetectionStrategy,
|
ChangeDetectionStrategy,
|
||||||
@@ -6,37 +5,41 @@ import {
|
|||||||
inject,
|
inject,
|
||||||
Input,
|
Input,
|
||||||
} from '@angular/core'
|
} from '@angular/core'
|
||||||
|
import { toSignal } from '@angular/core/rxjs-interop'
|
||||||
import { Router } from '@angular/router'
|
import { Router } from '@angular/router'
|
||||||
import { MarketplacePkgBase } from '@start9labs/marketplace'
|
import { MarketplacePkgBase } from '@start9labs/marketplace'
|
||||||
import {
|
import {
|
||||||
Exver,
|
|
||||||
ErrorService,
|
ErrorService,
|
||||||
|
Exver,
|
||||||
|
ExverPipesModule,
|
||||||
|
i18nPipe,
|
||||||
isEmptyObject,
|
isEmptyObject,
|
||||||
LoadingService,
|
LoadingService,
|
||||||
sameUrl,
|
sameUrl,
|
||||||
ExverPipesModule,
|
|
||||||
i18nPipe,
|
|
||||||
} from '@start9labs/shared'
|
} from '@start9labs/shared'
|
||||||
|
import { TuiButton } from '@taiga-ui/core'
|
||||||
import { PatchDB } from 'patch-db-client'
|
import { PatchDB } from 'patch-db-client'
|
||||||
import { firstValueFrom } from 'rxjs'
|
import { firstValueFrom } from 'rxjs'
|
||||||
|
import { ToManifestPipe } from 'src/app/routes/portal/pipes/to-manifest'
|
||||||
|
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||||
|
import { MarketplaceService } from 'src/app/services/marketplace.service'
|
||||||
import {
|
import {
|
||||||
DataModel,
|
DataModel,
|
||||||
PackageDataEntry,
|
PackageDataEntry,
|
||||||
} from 'src/app/services/patch-db/data-model'
|
} from 'src/app/services/patch-db/data-model'
|
||||||
import { MarketplaceService } from 'src/app/services/marketplace.service'
|
|
||||||
import { hasCurrentDeps } from 'src/app/utils/has-deps'
|
|
||||||
import { getAllPackages, getManifest } from 'src/app/utils/get-package-data'
|
|
||||||
import { dryUpdate } from 'src/app/utils/dry-update'
|
import { dryUpdate } from 'src/app/utils/dry-update'
|
||||||
|
import { getAllPackages, getManifest } from 'src/app/utils/get-package-data'
|
||||||
|
import { hasCurrentDeps } from 'src/app/utils/has-deps'
|
||||||
|
|
||||||
|
import { MarketplacePreviewComponent } from '../modals/preview.component'
|
||||||
import { MarketplaceAlertsService } from '../services/alerts.service'
|
import { MarketplaceAlertsService } from '../services/alerts.service'
|
||||||
import { ToManifestPipe } from 'src/app/routes/portal/pipes/to-manifest'
|
|
||||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'marketplace-controls',
|
selector: 'marketplace-controls',
|
||||||
template: `
|
template: `
|
||||||
@if (localPkg) {
|
@if (localPkg) {
|
||||||
@if (localPkg | toManifest; as localManifest) {
|
@if (localPkg | toManifest; as localManifest) {
|
||||||
@switch (localManifest.version | compareExver: pkg.version) {
|
@switch (localManifest.version | compareExver: version() || '') {
|
||||||
@case (1) {
|
@case (1) {
|
||||||
<button
|
<button
|
||||||
tuiButton
|
tuiButton
|
||||||
@@ -111,6 +114,9 @@ export class MarketplaceControlsComponent {
|
|||||||
private readonly router = inject(Router)
|
private readonly router = inject(Router)
|
||||||
private readonly marketplaceService = inject(MarketplaceService)
|
private readonly marketplaceService = inject(MarketplaceService)
|
||||||
private readonly api = inject(ApiService)
|
private readonly api = inject(ApiService)
|
||||||
|
private readonly preview = inject(MarketplacePreviewComponent)
|
||||||
|
|
||||||
|
protected readonly version = toSignal(this.preview.version$)
|
||||||
|
|
||||||
@Input({ required: true })
|
@Input({ required: true })
|
||||||
pkg!: MarketplacePkgBase
|
pkg!: MarketplacePkgBase
|
||||||
@@ -147,10 +153,11 @@ export class MarketplaceControlsComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const localManifest = getManifest(this.localPkg)
|
const localManifest = getManifest(this.localPkg)
|
||||||
|
const version = this.version() || ''
|
||||||
|
|
||||||
if (
|
if (
|
||||||
hasCurrentDeps(localManifest.id, await getAllPackages(this.patch)) &&
|
hasCurrentDeps(localManifest.id, await getAllPackages(this.patch)) &&
|
||||||
this.exver.compareExver(localManifest.version, this.pkg.version) !== 0
|
this.exver.compareExver(localManifest.version, version) !== 0
|
||||||
) {
|
) {
|
||||||
this.dryInstall(currentUrl)
|
this.dryInstall(currentUrl)
|
||||||
} else {
|
} else {
|
||||||
@@ -159,12 +166,14 @@ export class MarketplaceControlsComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async showService() {
|
async showService() {
|
||||||
this.router.navigate(['/portal/services', this.pkg.id])
|
this.router.navigate(['/portal/services', this.preview.pkgId])
|
||||||
}
|
}
|
||||||
|
|
||||||
private async dryInstall(url: string | null) {
|
private async dryInstall(url: string | null) {
|
||||||
|
const id = this.preview.pkgId
|
||||||
|
const version = this.version() || ''
|
||||||
const breakages = dryUpdate(
|
const breakages = dryUpdate(
|
||||||
this.pkg,
|
{ id, version },
|
||||||
await getAllPackages(this.patch),
|
await getAllPackages(this.patch),
|
||||||
this.exver,
|
this.exver,
|
||||||
)
|
)
|
||||||
@@ -188,7 +197,8 @@ export class MarketplaceControlsComponent {
|
|||||||
|
|
||||||
private async install(url: string) {
|
private async install(url: string) {
|
||||||
const loader = this.loader.open('Beginning install').subscribe()
|
const loader = this.loader.open('Beginning install').subscribe()
|
||||||
const { id, version } = this.pkg
|
const version = this.version() || ''
|
||||||
|
const id = this.preview.pkgId
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.marketplaceService.installPackage(id, version, url)
|
await this.marketplaceService.installPackage(id, version, url)
|
||||||
|
|||||||
@@ -167,11 +167,11 @@ export class MarketplacePreviewComponent {
|
|||||||
private readonly exver = inject(Exver)
|
private readonly exver = inject(Exver)
|
||||||
private readonly router = inject(Router)
|
private readonly router = inject(Router)
|
||||||
private readonly marketplaceService = inject(MarketplaceService)
|
private readonly marketplaceService = inject(MarketplaceService)
|
||||||
private readonly version$ = new BehaviorSubject<string | null>(null)
|
|
||||||
private readonly flavor$ = this.router.routerState.root.queryParamMap.pipe(
|
private readonly flavor$ = this.router.routerState.root.queryParamMap.pipe(
|
||||||
map(paramMap => paramMap.get('flavor')),
|
map(paramMap => paramMap.get('flavor')),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
readonly version$ = new BehaviorSubject<string | null>(null)
|
||||||
readonly pkg$ = combineLatest([this.version$, this.flavor$]).pipe(
|
readonly pkg$ = combineLatest([this.version$, this.flavor$]).pipe(
|
||||||
switchMap(([version, flavor]) =>
|
switchMap(([version, flavor]) =>
|
||||||
this.marketplaceService
|
this.marketplaceService
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ import { SystemWipeComponent } from './wipe.component'
|
|||||||
<tui-icon icon="@tui.languages" />
|
<tui-icon icon="@tui.languages" />
|
||||||
<span tuiTitle>
|
<span tuiTitle>
|
||||||
<strong>{{ 'Language' | i18n }}</strong>
|
<strong>{{ 'Language' | i18n }}</strong>
|
||||||
<span tuiSubtitle>
|
<span tuiSubtitle [style.text-transform]="'capitalize'">
|
||||||
@if (language; as lang) {
|
@if (language; as lang) {
|
||||||
{{ lang | i18n }}
|
{{ lang | i18n }}
|
||||||
} @else {
|
} @else {
|
||||||
@@ -197,7 +197,7 @@ import { SystemWipeComponent } from './wipe.component'
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<img
|
<img
|
||||||
[snek]="score()"
|
[snek]="score() || 0"
|
||||||
class="snek"
|
class="snek"
|
||||||
alt="Play Snake"
|
alt="Play Snake"
|
||||||
src="assets/img/icons/snek.png"
|
src="assets/img/icons/snek.png"
|
||||||
@@ -271,15 +271,17 @@ export default class SystemGeneralComponent {
|
|||||||
|
|
||||||
readonly server = toSignal(this.patch.watch$('serverInfo'))
|
readonly server = toSignal(this.patch.watch$('serverInfo'))
|
||||||
readonly name = toSignal(this.patch.watch$('ui', 'name'))
|
readonly name = toSignal(this.patch.watch$('ui', 'name'))
|
||||||
|
readonly score = toSignal(this.patch.watch$('ui', 'snakeHighScore'))
|
||||||
readonly os = inject(OSService)
|
readonly os = inject(OSService)
|
||||||
readonly i18nService = inject(i18nService)
|
readonly i18nService = inject(i18nService)
|
||||||
readonly languages = languages
|
readonly languages = languages
|
||||||
readonly translation: TuiStringHandler<TuiContext<Languages>> = ({
|
readonly translation: TuiStringHandler<TuiContext<Languages>> = ({
|
||||||
$implicit,
|
$implicit,
|
||||||
}) => this.i18n.transform($implicit)!
|
}) => {
|
||||||
readonly score = toSignal(this.patch.watch$('ui', 'snakeHighScore'), {
|
const [head = '', ...result] = this.i18n.transform($implicit) || ''
|
||||||
initialValue: 0,
|
|
||||||
})
|
return [head.toUpperCase(), ...result].join('')
|
||||||
|
}
|
||||||
|
|
||||||
get language(): Languages | undefined {
|
get language(): Languages | undefined {
|
||||||
return this.languages.find(lang => lang === this.i18nService.language)
|
return this.languages.find(lang => lang === this.i18nService.language)
|
||||||
|
|||||||
@@ -9,18 +9,6 @@ export class FormDialogService {
|
|||||||
private readonly dialog = inject(DialogService)
|
private readonly dialog = inject(DialogService)
|
||||||
private readonly i18n = inject(i18nPipe)
|
private readonly i18n = inject(i18nPipe)
|
||||||
private readonly formService = new TuiConfirmService()
|
private readonly formService = new TuiConfirmService()
|
||||||
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({
|
private readonly injector = Injector.create({
|
||||||
parent: inject(Injector),
|
parent: inject(Injector),
|
||||||
providers: [
|
providers: [
|
||||||
@@ -37,10 +25,23 @@ export class FormDialogService {
|
|||||||
label?: i18nKey
|
label?: i18nKey
|
||||||
} = {},
|
} = {},
|
||||||
) {
|
) {
|
||||||
|
const 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'),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const closeable = this.formService.withConfirm(PROMPT)
|
||||||
|
|
||||||
this.dialog
|
this.dialog
|
||||||
.openComponent(new PolymorpheusComponent(component, this.injector), {
|
.openComponent(new PolymorpheusComponent(component, this.injector), {
|
||||||
closeable: this.prompt,
|
dismissible: closeable,
|
||||||
dismissible: this.prompt,
|
closeable,
|
||||||
...options,
|
...options,
|
||||||
})
|
})
|
||||||
.subscribe({
|
.subscribe({
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
import { inject, Injectable } from '@angular/core'
|
import { inject, Injectable } from '@angular/core'
|
||||||
import { ErrorService, MARKDOWN } from '@start9labs/shared'
|
import {
|
||||||
import { TuiResponsiveDialogService } from '@taiga-ui/addon-mobile'
|
DialogService,
|
||||||
|
ErrorService,
|
||||||
|
i18nKey,
|
||||||
|
MARKDOWN,
|
||||||
|
} from '@start9labs/shared'
|
||||||
import { PatchDB } from 'patch-db-client'
|
import { PatchDB } from 'patch-db-client'
|
||||||
import { firstValueFrom, merge, of, shareReplay, Subject } from 'rxjs'
|
import { firstValueFrom, merge, of, shareReplay, Subject } from 'rxjs'
|
||||||
import { REPORT } from 'src/app/components/backup-report.component'
|
import { REPORT } from 'src/app/components/backup-report.component'
|
||||||
@@ -16,7 +20,7 @@ export class NotificationService {
|
|||||||
private readonly patch = inject<PatchDB<DataModel>>(PatchDB)
|
private readonly patch = inject<PatchDB<DataModel>>(PatchDB)
|
||||||
private readonly errorService = inject(ErrorService)
|
private readonly errorService = inject(ErrorService)
|
||||||
private readonly api = inject(ApiService)
|
private readonly api = inject(ApiService)
|
||||||
private readonly dialogs = inject(TuiResponsiveDialogService)
|
private readonly dialogs = inject(DialogService)
|
||||||
private readonly localUnreadCount$ = new Subject<number>()
|
private readonly localUnreadCount$ = new Subject<number>()
|
||||||
|
|
||||||
readonly unreadCount$ = merge(
|
readonly unreadCount$ = merge(
|
||||||
@@ -93,12 +97,12 @@ export class NotificationService {
|
|||||||
{ data, createdAt, code, title, message }: ServerNotification<number>,
|
{ data, createdAt, code, title, message }: ServerNotification<number>,
|
||||||
full = false,
|
full = false,
|
||||||
) {
|
) {
|
||||||
const label = code === 1 ? 'Backup Report' : title
|
const label = code === 1 ? 'Backup Report' : (title as i18nKey)
|
||||||
const component = code === 1 ? REPORT : MARKDOWN
|
const component = code === 1 ? REPORT : MARKDOWN
|
||||||
const content = code === 1 ? data : of(data)
|
const content = code === 1 ? data : of(data)
|
||||||
|
|
||||||
this.dialogs
|
this.dialogs
|
||||||
.open(full ? message : component, {
|
.openComponent(full ? message : component, {
|
||||||
label,
|
label,
|
||||||
data: {
|
data: {
|
||||||
content,
|
content,
|
||||||
|
|||||||
Reference in New Issue
Block a user