mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-04-04 22:39:46 +00:00
rework Embassy tab, fix error type in patch-db, fix response type for embassy updates
This commit is contained in:
committed by
Aiden McClelland
parent
2f865a1953
commit
933481cd7d
@@ -42,7 +42,7 @@ export class AppShowPage {
|
|||||||
} = { } as any
|
} = { } as any
|
||||||
connectionFailure: boolean
|
connectionFailure: boolean
|
||||||
loading = true
|
loading = true
|
||||||
healthChecks: { [id: string]: HealthCheckResult }
|
healthChecks: { [id: string]: HealthCheckResult } = { }
|
||||||
installProgress: ProgressData
|
installProgress: ProgressData
|
||||||
|
|
||||||
@ViewChild(IonContent) content: IonContent
|
@ViewChild(IonContent) content: IonContent
|
||||||
@@ -80,18 +80,17 @@ export class AppShowPage {
|
|||||||
this.installProgress = !isEmptyObject(pkg['install-progress']) ? this.packageLoadingService.transform(pkg['install-progress']) : undefined
|
this.installProgress = !isEmptyObject(pkg['install-progress']) ? this.packageLoadingService.transform(pkg['install-progress']) : undefined
|
||||||
this.statuses = renderPkgStatus(pkg)
|
this.statuses = renderPkgStatus(pkg)
|
||||||
|
|
||||||
// health
|
const installed = pkg.installed
|
||||||
if (this.pkg.installed?.status.main.status === PackageMainStatus.Running) {
|
|
||||||
this.healthChecks = { ...this.pkg.installed.status.main.health }
|
|
||||||
} else {
|
|
||||||
this.healthChecks = { }
|
|
||||||
}
|
|
||||||
|
|
||||||
// dependencies
|
if (!!installed) {
|
||||||
if (!pkg.installed) {
|
// health
|
||||||
this.dependencies = { }
|
if (installed.status.main.status === PackageMainStatus.Running) {
|
||||||
} else {
|
this.healthChecks = { ...installed.status.main.health }
|
||||||
const currentDeps = pkg.installed['current-dependencies']
|
} else {
|
||||||
|
this.healthChecks = { }
|
||||||
|
}
|
||||||
|
// dependencies
|
||||||
|
const currentDeps = installed['current-dependencies']
|
||||||
Object.keys(currentDeps).forEach(key => {
|
Object.keys(currentDeps).forEach(key => {
|
||||||
const manifestDep = pkg.manifest.dependencies[key]
|
const manifestDep = pkg.manifest.dependencies[key]
|
||||||
if (!this.dependencies[key] && manifestDep) {
|
if (!this.dependencies[key] && manifestDep) {
|
||||||
@@ -243,7 +242,7 @@ export class AppShowPage {
|
|||||||
// config unsatisfied
|
// config unsatisfied
|
||||||
} else if (error.type === DependencyErrorType.ConfigUnsatisfied) {
|
} else if (error.type === DependencyErrorType.ConfigUnsatisfied) {
|
||||||
errorText = 'Config not satisfied'
|
errorText = 'Config not satisfied'
|
||||||
actionText = 'Auto Config'
|
actionText = 'Auto config'
|
||||||
action = () => this.fixDep('configure', id)
|
action = () => this.fixDep('configure', id)
|
||||||
} else if (error.type === DependencyErrorType.Transitive) {
|
} else if (error.type === DependencyErrorType.Transitive) {
|
||||||
errorText = 'Dependency has a dependency issue'
|
errorText = 'Dependency has a dependency issue'
|
||||||
@@ -254,8 +253,6 @@ export class AppShowPage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.dependencies[id]) this.dependencies[id] = { } as any
|
|
||||||
|
|
||||||
const depInfo = this.pkg.installed['dependency-info'][id]
|
const depInfo = this.pkg.installed['dependency-info'][id]
|
||||||
|
|
||||||
this.dependencies[id].title = depInfo.manifest.title
|
this.dependencies[id].title = depInfo.manifest.title
|
||||||
@@ -287,16 +284,11 @@ export class AppShowPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async configureDep (depId: string): Promise<void> {
|
private async configureDep (depId: string): Promise<void> {
|
||||||
const configErrors = (this.pkg.installed.status['dependency-errors'][depId] as DependencyErrorConfigUnsatisfied).errors
|
|
||||||
|
|
||||||
const description = `<ul>${configErrors.map(d => `<li>${d}</li>`).join('\n')}</ul>`
|
|
||||||
const dependentTitle = this.pkg.manifest.title
|
|
||||||
|
|
||||||
const configRecommendation: Recommendation = {
|
const configRecommendation: Recommendation = {
|
||||||
dependentId: this.pkgId,
|
dependentId: this.pkgId,
|
||||||
dependentTitle,
|
dependentTitle: this.pkg.manifest.title,
|
||||||
dependentIcon: this.pkg['static-files'].icon,
|
dependentIcon: this.pkg['static-files'].icon,
|
||||||
description,
|
description: (this.pkg.installed.status['dependency-errors'][depId] as DependencyErrorConfigUnsatisfied).error,
|
||||||
}
|
}
|
||||||
const params = {
|
const params = {
|
||||||
pkgId: depId,
|
pkgId: depId,
|
||||||
@@ -352,7 +344,7 @@ export class AppShowPage {
|
|||||||
{
|
{
|
||||||
action: () => this.navCtrl.navigateForward(['instructions'], { relativeTo: this.route }),
|
action: () => this.navCtrl.navigateForward(['instructions'], { relativeTo: this.route }),
|
||||||
title: 'Instructions',
|
title: 'Instructions',
|
||||||
description: '',
|
description: `Understand how to use ${pkgTitle}`,
|
||||||
icon: 'list-outline',
|
icon: 'list-outline',
|
||||||
color: 'danger',
|
color: 'danger',
|
||||||
},
|
},
|
||||||
@@ -400,7 +392,7 @@ export class AppShowPage {
|
|||||||
{
|
{
|
||||||
action: () => this.navCtrl.navigateForward(['logs'], { relativeTo: this.route }),
|
action: () => this.navCtrl.navigateForward(['logs'], { relativeTo: this.route }),
|
||||||
title: 'Logs',
|
title: 'Logs',
|
||||||
description: '',
|
description: 'Raw, unfiltered service logs',
|
||||||
icon: 'receipt-outline',
|
icon: 'receipt-outline',
|
||||||
color: 'danger',
|
color: 'danger',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -9,11 +9,33 @@
|
|||||||
|
|
||||||
<ion-content class="ion-padding-top">
|
<ion-content class="ion-padding-top">
|
||||||
|
|
||||||
<ion-item-group>
|
<ion-item-group *ngIf="patch.data['server-info'] as server">
|
||||||
|
<ion-item-divider>General</ion-item-divider>
|
||||||
<ion-item button (click)="presentModalName()">
|
<ion-item button (click)="presentModalName()">
|
||||||
<ion-label>{{ fields['name'].name }}</ion-label>
|
<ion-label>{{ fields['name'].name }}</ion-label>
|
||||||
<ion-note slot="end">{{ patch.data.ui.name || defaultName }}</ion-note>
|
<ion-note slot="end">{{ patch.data.ui.name || defaultName }}</ion-note>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
|
<ion-item button (click)="serverConfig.presentAlert('share-stats', server['share-stats'])">
|
||||||
|
<ion-label>Auto Report Bugs</ion-label>
|
||||||
|
<ion-note slot="end">{{ server['share-stats'] ? 'Enabled' : 'Disabled' }}</ion-note>
|
||||||
|
</ion-item>
|
||||||
|
|
||||||
|
<!-- <ion-item button (click)="presentModalValueEdit('password')">
|
||||||
|
<ion-label>Change Password</ion-label>
|
||||||
|
<ion-note slot="end">********</ion-note>
|
||||||
|
</ion-item> -->
|
||||||
|
|
||||||
|
<ion-item-divider>Marketplace</ion-item-divider>
|
||||||
|
<ion-item button (click)="serverConfig.presentAlert('auto-check-updates', patch.data.ui['auto-check-updates'])">
|
||||||
|
<ion-label>Auto Check for Updates</ion-label>
|
||||||
|
<ion-note slot="end">{{ patch.data.ui['auto-check-updates'] ? 'Enabled' : 'Disabled' }}</ion-note>
|
||||||
|
</ion-item>
|
||||||
|
|
||||||
|
<!-- <ion-item button (click)="presentModalValueEdit('packageMarketplace', server['package-marketplace'])">
|
||||||
|
<ion-label>Package Marketplace</ion-label>
|
||||||
|
<ion-note slot="end">{{ server['package-marketplace'] }}</ion-note>
|
||||||
|
</ion-item> -->
|
||||||
</ion-item-group>
|
</ion-item-group>
|
||||||
|
|
||||||
</ion-content>
|
</ion-content>
|
||||||
@@ -4,7 +4,7 @@ import { IonContent, ModalController } from '@ionic/angular'
|
|||||||
import { GenericInputComponent } from 'src/app/modals/generic-input/generic-input.component'
|
import { GenericInputComponent } from 'src/app/modals/generic-input/generic-input.component'
|
||||||
import { ConfigSpec } from 'src/app/pkg-config/config-types'
|
import { ConfigSpec } from 'src/app/pkg-config/config-types'
|
||||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||||
import { ErrorToastService } from 'src/app/services/error-toast.service'
|
import { ServerConfigService } from 'src/app/services/server-config.service'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'preferences',
|
selector: 'preferences',
|
||||||
@@ -19,6 +19,7 @@ export class PreferencesPage {
|
|||||||
constructor (
|
constructor (
|
||||||
private readonly modalCtrl: ModalController,
|
private readonly modalCtrl: ModalController,
|
||||||
private readonly api: ApiService,
|
private readonly api: ApiService,
|
||||||
|
public readonly serverConfig: ServerConfigService,
|
||||||
public readonly patch: PatchDbService,
|
public readonly patch: PatchDbService,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
import { NgModule } from '@angular/core'
|
|
||||||
import { CommonModule } from '@angular/common'
|
|
||||||
import { IonicModule } from '@ionic/angular'
|
|
||||||
import { SecurityOptionsPage } from './security-options.page'
|
|
||||||
import { Routes, RouterModule } from '@angular/router'
|
|
||||||
import { SharingModule } from 'src/app/modules/sharing.module'
|
|
||||||
|
|
||||||
const routes: Routes = [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
component: SecurityOptionsPage,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [
|
|
||||||
CommonModule,
|
|
||||||
IonicModule,
|
|
||||||
RouterModule.forChild(routes),
|
|
||||||
SharingModule,
|
|
||||||
],
|
|
||||||
declarations: [
|
|
||||||
SecurityOptionsPage,
|
|
||||||
],
|
|
||||||
})
|
|
||||||
export class SecurityOptionsPageModule { }
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
<ion-header>
|
|
||||||
<ion-toolbar>
|
|
||||||
<ion-buttons slot="start">
|
|
||||||
<pwa-back-button></pwa-back-button>
|
|
||||||
</ion-buttons>
|
|
||||||
<ion-title>Privacy and Security</ion-title>
|
|
||||||
</ion-toolbar>
|
|
||||||
</ion-header>
|
|
||||||
|
|
||||||
<ion-content class="ion-padding-top" *ngIf="patch.data['server-info'] as server">
|
|
||||||
|
|
||||||
<ion-item-group>
|
|
||||||
<ion-item-divider>General</ion-item-divider>
|
|
||||||
<ion-item button (click)="serverConfig.presentAlert('share-stats', server['share-stats'])">
|
|
||||||
<ion-label>Report Bugs</ion-label>
|
|
||||||
<ion-note slot="end">{{ server['share-stats'] ? 'Enabled' : 'Disabled' }}</ion-note>
|
|
||||||
</ion-item>
|
|
||||||
|
|
||||||
<ion-item-divider>Marketplace</ion-item-divider>
|
|
||||||
<ion-item button (click)="serverConfig.presentAlert('auto-check-updates', patch.data.ui['auto-check-updates'])">
|
|
||||||
<ion-label>Auto Check for Updates</ion-label>
|
|
||||||
<ion-note slot="end">{{ patch.data.ui['auto-check-updates'] ? 'Enabled' : 'Disabled' }}</ion-note>
|
|
||||||
</ion-item>
|
|
||||||
<!-- <ion-item button (click)="presentModalValueEdit('packageMarketplace', server['package-marketplace'])">
|
|
||||||
<ion-label>Package Marketplace</ion-label>
|
|
||||||
<ion-note slot="end">{{ server['package-marketplace'] }}</ion-note>
|
|
||||||
</ion-item> -->
|
|
||||||
|
|
||||||
<ion-item-divider>Security</ion-item-divider>
|
|
||||||
<!-- <ion-item button (click)="presentModalValueEdit('password')">
|
|
||||||
<ion-label>Change Password</ion-label>
|
|
||||||
<ion-note slot="end">********</ion-note>
|
|
||||||
</ion-item> -->
|
|
||||||
<ion-item detail="true" button [routerLink]="['ssh-keys']">
|
|
||||||
<ion-label>SSH Keys</ion-label>
|
|
||||||
</ion-item>
|
|
||||||
<ion-item detail="true" button [routerLink]="['sessions']">
|
|
||||||
<ion-label>Active Sessions</ion-label>
|
|
||||||
</ion-item>
|
|
||||||
</ion-item-group>
|
|
||||||
|
|
||||||
</ion-content>
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
import { Component, ViewChild } from '@angular/core'
|
|
||||||
import { ServerConfigService } from 'src/app/services/server-config.service'
|
|
||||||
import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
|
|
||||||
import { ConfigService } from 'src/app/services/config.service'
|
|
||||||
import { IonContent } from '@ionic/angular'
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'security-options',
|
|
||||||
templateUrl: './security-options.page.html',
|
|
||||||
styleUrls: ['./security-options.page.scss'],
|
|
||||||
})
|
|
||||||
export class SecurityOptionsPage {
|
|
||||||
@ViewChild(IonContent) content: IonContent
|
|
||||||
|
|
||||||
constructor (
|
|
||||||
public readonly serverConfig: ServerConfigService,
|
|
||||||
public readonly config: ConfigService,
|
|
||||||
public readonly patch: PatchDbService,
|
|
||||||
) { }
|
|
||||||
|
|
||||||
ngAfterViewInit () {
|
|
||||||
this.content.scrollToPoint(undefined, 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
import { NgModule } from '@angular/core'
|
|
||||||
import { Routes, RouterModule } from '@angular/router'
|
|
||||||
|
|
||||||
const routes: Routes = [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
loadChildren: () => import('./security-options/security-options.module').then(m => m.SecurityOptionsPageModule),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'sessions',
|
|
||||||
loadChildren: () => import('./sessions/sessions.module').then(m => m.SessionsPageModule),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'ssh-keys',
|
|
||||||
loadChildren: () => import('./ssh-keys/ssh-keys.module').then(m => m.SSHKeysPageModule),
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [RouterModule.forChild(routes)],
|
|
||||||
exports: [RouterModule],
|
|
||||||
})
|
|
||||||
export class SecurityRoutingModule { }
|
|
||||||
@@ -11,33 +11,37 @@ const routes: Routes = [
|
|||||||
loadChildren: () => import('./server-backup/server-backup.module').then(m => m.ServerBackupPageModule),
|
loadChildren: () => import('./server-backup/server-backup.module').then(m => m.ServerBackupPageModule),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'specs',
|
path: 'lan',
|
||||||
loadChildren: () => import('./server-specs/server-specs.module').then(m => m.ServerSpecsPageModule),
|
loadChildren: () => import('./lan/lan.module').then(m => m.LANPageModule),
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'metrics',
|
|
||||||
loadChildren: () => import('./server-metrics/server-metrics.module').then(m => m.ServerMetricsPageModule),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'logs',
|
path: 'logs',
|
||||||
loadChildren: () => import('./server-logs/server-logs.module').then(m => m.ServerLogsPageModule),
|
loadChildren: () => import('./server-logs/server-logs.module').then(m => m.ServerLogsPageModule),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'wifi',
|
path: 'metrics',
|
||||||
loadChildren: () => import('./wifi/wifi.module').then(m => m.WifiPageModule),
|
loadChildren: () => import('./server-metrics/server-metrics.module').then(m => m.ServerMetricsPageModule),
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'lan',
|
|
||||||
loadChildren: () => import('./lan/lan.module').then(m => m.LANPageModule),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'security',
|
|
||||||
loadChildren: () => import('./security-routes/security-routing.module').then( m => m.SecurityRoutingModule),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'preferences',
|
path: 'preferences',
|
||||||
loadChildren: () => import('./preferences/preferences.module').then( m => m.PreferencesPageModule),
|
loadChildren: () => import('./preferences/preferences.module').then( m => m.PreferencesPageModule),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'sessions',
|
||||||
|
loadChildren: () => import('./sessions/sessions.module').then( m => m.SessionsPageModule),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'specs',
|
||||||
|
loadChildren: () => import('./server-specs/server-specs.module').then(m => m.ServerSpecsPageModule),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'ssh',
|
||||||
|
loadChildren: () => import('./ssh-keys/ssh-keys.module').then( m => m.SSHKeysPageModule),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'wifi',
|
||||||
|
loadChildren: () => import('./wifi/wifi.module').then(m => m.WifiPageModule),
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
|||||||
@@ -13,7 +13,10 @@
|
|||||||
<ion-item-divider><ion-text color="dark">{{ cat.key }}</ion-text></ion-item-divider>
|
<ion-item-divider><ion-text color="dark">{{ cat.key }}</ion-text></ion-item-divider>
|
||||||
<ion-item [detail]="button.detail" button *ngFor="let button of cat.value" (click)="button.action()">
|
<ion-item [detail]="button.detail" button *ngFor="let button of cat.value" (click)="button.action()">
|
||||||
<ion-icon slot="start" [name]="button.icon"></ion-icon>
|
<ion-icon slot="start" [name]="button.icon"></ion-icon>
|
||||||
<ion-label>{{ button.title }}</ion-label>
|
<ion-label>
|
||||||
|
<h2>{{ button.title }}</h2>
|
||||||
|
<p *ngIf="button.description">{{ button.description }}</p>
|
||||||
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</div>
|
</div>
|
||||||
</ion-item-group>
|
</ion-item-group>
|
||||||
|
|||||||
@@ -108,66 +108,83 @@ export class ServerShowPage {
|
|||||||
'Backups': [
|
'Backups': [
|
||||||
{
|
{
|
||||||
title: 'Create Backup',
|
title: 'Create Backup',
|
||||||
|
description: 'Back up your Embassy and all its services',
|
||||||
icon: 'save-outline',
|
icon: 'save-outline',
|
||||||
action: () => this.navCtrl.navigateForward(['backup'], { relativeTo: this.route }),
|
action: () => this.navCtrl.navigateForward(['backup'], { relativeTo: this.route }),
|
||||||
detail: true,
|
detail: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'Settings': [
|
|
||||||
{
|
|
||||||
title: 'Preferences',
|
|
||||||
icon: 'options-outline',
|
|
||||||
action: () => this.navCtrl.navigateForward(['preferences'], { relativeTo: this.route }),
|
|
||||||
detail: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Privacy and Security',
|
|
||||||
icon: 'shield-checkmark-outline',
|
|
||||||
action: () => this.navCtrl.navigateForward(['security'], { relativeTo: this.route }),
|
|
||||||
detail: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'LAN',
|
|
||||||
icon: 'home-outline',
|
|
||||||
action: () => this.navCtrl.navigateForward(['lan'], { relativeTo: this.route }),
|
|
||||||
detail: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'WiFi',
|
|
||||||
icon: 'wifi',
|
|
||||||
action: () => this.navCtrl.navigateForward(['wifi'], { relativeTo: this.route }),
|
|
||||||
detail: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'Insights': [
|
'Insights': [
|
||||||
{
|
{
|
||||||
title: 'About',
|
title: 'About',
|
||||||
|
description: 'Basic information about your Embassy',
|
||||||
icon: 'information-circle-outline',
|
icon: 'information-circle-outline',
|
||||||
action: () => this.navCtrl.navigateForward(['specs'], { relativeTo: this.route }),
|
action: () => this.navCtrl.navigateForward(['specs'], { relativeTo: this.route }),
|
||||||
detail: true,
|
detail: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Monitor',
|
title: 'Monitor',
|
||||||
|
description: 'CPU, disk, memory, and other useful metrics',
|
||||||
icon: 'pulse',
|
icon: 'pulse',
|
||||||
action: () => this.navCtrl.navigateForward(['metrics'], { relativeTo: this.route }),
|
action: () => this.navCtrl.navigateForward(['metrics'], { relativeTo: this.route }),
|
||||||
detail: true,
|
detail: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Logs',
|
title: 'Logs',
|
||||||
|
description: 'Raw, unfiltered device logs',
|
||||||
icon: 'newspaper-outline',
|
icon: 'newspaper-outline',
|
||||||
action: () => this.navCtrl.navigateForward(['logs'], { relativeTo: this.route }),
|
action: () => this.navCtrl.navigateForward(['logs'], { relativeTo: this.route }),
|
||||||
detail: true,
|
detail: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
'Settings': [
|
||||||
|
{
|
||||||
|
title: 'Preferences',
|
||||||
|
description: 'Device name, background tasks',
|
||||||
|
icon: 'options-outline',
|
||||||
|
action: () => this.navCtrl.navigateForward(['preferences'], { relativeTo: this.route }),
|
||||||
|
detail: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'LAN',
|
||||||
|
description: 'Access your Embassy on the Local Area Network',
|
||||||
|
icon: 'home-outline',
|
||||||
|
action: () => this.navCtrl.navigateForward(['lan'], { relativeTo: this.route }),
|
||||||
|
detail: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'SSH',
|
||||||
|
description: 'Access your Embassy from the command line',
|
||||||
|
icon: 'terminal-outline',
|
||||||
|
action: () => this.navCtrl.navigateForward(['ssh'], { relativeTo: this.route }),
|
||||||
|
detail: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'WiFi',
|
||||||
|
description: 'Add or remove WiFi networks',
|
||||||
|
icon: 'wifi',
|
||||||
|
action: () => this.navCtrl.navigateForward(['wifi'], { relativeTo: this.route }),
|
||||||
|
detail: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Active Sessions',
|
||||||
|
description: 'View and manage device access',
|
||||||
|
icon: 'desktop-outline',
|
||||||
|
action: () => this.navCtrl.navigateForward(['sessions'], { relativeTo: this.route }),
|
||||||
|
detail: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
'Power': [
|
'Power': [
|
||||||
{
|
{
|
||||||
title: 'Restart',
|
title: 'Restart',
|
||||||
|
description: '',
|
||||||
icon: 'reload',
|
icon: 'reload',
|
||||||
action: () => this.presentAlertRestart(),
|
action: () => this.presentAlertRestart(),
|
||||||
detail: false,
|
detail: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Shutdown',
|
title: 'Shutdown',
|
||||||
|
description: '',
|
||||||
icon: 'power',
|
icon: 'power',
|
||||||
action: () => this.presentAlertShutdown(),
|
action: () => this.presentAlertShutdown(),
|
||||||
detail: false,
|
detail: false,
|
||||||
@@ -184,6 +201,7 @@ export class ServerShowPage {
|
|||||||
interface ServerSettings {
|
interface ServerSettings {
|
||||||
[key: string]: {
|
[key: string]: {
|
||||||
title: string
|
title: string
|
||||||
|
description: string
|
||||||
icon: string
|
icon: string
|
||||||
action: Function
|
action: Function
|
||||||
detail: boolean
|
detail: boolean
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export module RR {
|
|||||||
export type GetServerMetricsRes = Metrics
|
export type GetServerMetricsRes = Metrics
|
||||||
|
|
||||||
export type UpdateServerReq = WithExpire<{ }> // server.update
|
export type UpdateServerReq = WithExpire<{ }> // server.update
|
||||||
export type UpdateServerRes = WithRevision<null>
|
export type UpdateServerRes = WithRevision<'updating' | 'no-updates'>
|
||||||
|
|
||||||
export type RestartServerReq = { } // server.restart
|
export type RestartServerReq = { } // server.restart
|
||||||
export type RestartServerRes = null
|
export type RestartServerRes = null
|
||||||
|
|||||||
@@ -54,8 +54,15 @@ export abstract class ApiService implements Source<DataModel>, Http<DataModel> {
|
|||||||
|
|
||||||
protected abstract updateServerRaw (params: RR.UpdateServerReq): Promise<RR.UpdateServerRes>
|
protected abstract updateServerRaw (params: RR.UpdateServerReq): Promise<RR.UpdateServerRes>
|
||||||
updateServer = (params: RR.UpdateServerReq) => this.syncResponse(
|
updateServer = (params: RR.UpdateServerReq) => this.syncResponse(
|
||||||
() => this.updateServerRaw(params),
|
() => this.updateServerWrapper(params),
|
||||||
)()
|
)()
|
||||||
|
async updateServerWrapper (params: RR.UpdateServerReq) {
|
||||||
|
const res = await this.updateServerRaw(params)
|
||||||
|
if (res.response === 'no-updates') {
|
||||||
|
throw new Error('Could ont find a newer version of EmbassyOS')
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
abstract restartServer (params: RR.UpdateServerReq): Promise<RR.RestartServerRes>
|
abstract restartServer (params: RR.UpdateServerReq): Promise<RR.RestartServerRes>
|
||||||
|
|
||||||
|
|||||||
@@ -118,9 +118,11 @@ export class MockApiService extends ApiService {
|
|||||||
value: initialProgress,
|
value: initialProgress,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
const res = await this.http.rpcRequest<WithRevision<null>>({ method: 'db.patch', params: { patch } })
|
const res = await this.http.rpcRequest<RR.UpdateServerRes>({ method: 'db.patch', params: { patch } })
|
||||||
|
res.response = 'updating'
|
||||||
|
|
||||||
this.updateOSProgress(initialProgress.size)
|
this.updateOSProgress(initialProgress.size)
|
||||||
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ import { ErrorHandler, Injectable } from '@angular/core'
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class GlobalErrorHandler implements ErrorHandler {
|
export class GlobalErrorHandler implements ErrorHandler {
|
||||||
|
|
||||||
handleError (error: any): void {
|
handleError (e: any): void {
|
||||||
const chunkFailedMessage = /Loading chunk [\d]+ failed/
|
console.error(e)
|
||||||
|
const chunkFailedMessage = /Loading chunk [\d]+ failed/
|
||||||
|
|
||||||
if (chunkFailedMessage.test(error.message)) {
|
if (chunkFailedMessage.test(e.message)) {
|
||||||
window.location.reload()
|
window.location.reload()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -334,7 +334,7 @@ export interface DependencyErrorIncorrectVersion {
|
|||||||
|
|
||||||
export interface DependencyErrorConfigUnsatisfied {
|
export interface DependencyErrorConfigUnsatisfied {
|
||||||
type: DependencyErrorType.ConfigUnsatisfied
|
type: DependencyErrorType.ConfigUnsatisfied
|
||||||
errors: string[]
|
error: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DependencyErrorHealthChecksFailed {
|
export interface DependencyErrorHealthChecksFailed {
|
||||||
|
|||||||
Reference in New Issue
Block a user