refresh LAN and more

This commit is contained in:
Matt Hill
2021-02-26 14:32:58 -07:00
committed by Aiden McClelland
parent 3e3097945f
commit 6585d91816
42 changed files with 119 additions and 284 deletions

View File

@@ -92,11 +92,11 @@
<ion-icon name="information-circle-outline"></ion-icon>
<ion-icon name="list-outline"></ion-icon>
<ion-icon name="newspaper-outline"></ion-icon>
<ion-icon name="notifications-outline"></ion-icon>
<ion-icon name="notifications-outline"></ion-icon>
<ion-icon name="open-outline"></ion-icon>
<ion-icon name="power"></ion-icon>
<ion-icon name="pulse"></ion-icon>
<ion-icon name="qr-code-outline"></ion-icon>
<ion-icon name="globe-outline"></ion-icon>
<ion-icon name="reload-outline"></ion-icon>
<ion-icon name="refresh-outline"></ion-icon>
<ion-icon name="save-outline"></ion-icon>

View File

@@ -1,12 +1,9 @@
import { NgModule } from '@angular/core'
import { CommonModule } from '@angular/common'
import { Routes, RouterModule } from '@angular/router'
import { IonicModule } from '@ionic/angular'
import { AppActionsPage } from './app-actions.page'
import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-back.component.module'
import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.module'
import { QRComponentModule } from 'src/app/components/qr/qr.component.module'
import { SharingModule } from 'src/app/modules/sharing.module'
@@ -23,7 +20,6 @@ const routes: Routes = [
IonicModule,
RouterModule.forChild(routes),
PwaBackComponentModule,
BadgeMenuComponentModule,
QRComponentModule,
SharingModule,
],

View File

@@ -4,9 +4,6 @@
<pwa-back-button></pwa-back-button>
</ion-buttons>
<ion-title>Actions</ion-title>
<ion-buttons slot="end">
<badge-menu-button></badge-menu-button>
</ion-buttons>
</ion-toolbar>
</ion-header>

View File

@@ -27,7 +27,7 @@
<ion-card class="installed-card" [class.installed-card-on]="vars.status === 'RUNNING'" style="position:relative" [routerLink]="['/services', 'installed', app.id]">
<div class="launch-container" *ngIf="vars.ui && !isConsulate">
<div class="launch-button-triangle" (click)="launchUiTab(app.id, $event)" [class.disabled]="vars.status !== AppStatus.RUNNING">
<ion-icon class="launch-button-triangle-icon" name="globe-outline"></ion-icon>
<ion-icon name="open-outline"></ion-icon>
</div>
</div>

View File

@@ -77,9 +77,8 @@
</ion-label>
</ion-item>
<ion-button *ngIf="vars.status === AppStatus.RUNNING && vars.ui && !isConsulate" class="launch-button" expand="block" fill="outline" (click)="launchUiTab()">
<!-- <ion-icon slot="start" name="globe-outline"></ion-icon> -->
Launch Web
<ion-button size="small" *ngIf="vars.status === AppStatus.RUNNING && vars.ui && !isConsulate" class="launch-button" expand="block" fill="outline" (click)="launchUiTab()">
Launch Web Interface
<ion-icon slot="end" name="open-outline"></ion-icon>
</ion-button>
@@ -87,7 +86,7 @@
<ng-container *ngIf="app && app.id && vars.status !== 'INSTALLING'">
<ion-item-group class="ion-padding-bottom">
<ion-item-divider>Addresses</ion-item-divider>
<!-- addresses -->
<ion-item>
<ion-label class="ion-text-wrap">
<h2>Tor Address</h2>
@@ -107,7 +106,8 @@
</ion-button>
</ion-item>
<ion-item-divider>Backups</ion-item-divider>
<!-- backups -->
<ion-item-divider></ion-item-divider>
<!-- create backup -->
<ion-item button [disabled]="[AppStatus.RESTORING_BACKUP, AppStatus.CREATING_BACKUP, AppStatus.INSTALLING, AppStatus.RESTARTING, AppStatus.STOPPING] | includes: vars.status" (click)="presentModalBackup('create')">
<ion-icon slot="start" name="save-outline" color="primary"></ion-icon>
@@ -124,12 +124,7 @@
<ion-label><ion-text color="primary">Restore from Backup</ion-text></ion-label>
</ion-item>
<ion-item-divider>General</ion-item-divider>
<!-- instructions -->
<ion-item button details="true" (click)="checkForUpdates()">
<ion-icon slot="start" name="refresh-outline" color="primary"></ion-icon>
<ion-label><ion-text style="font-weight: 500;" color="primary">Check for Updates</ion-text></ion-label>
</ion-item>
<ion-item-divider></ion-item-divider>
<!-- instructions -->
<ion-item [routerLink]="['instructions']">
<ion-icon slot="start" name="list-outline" color="primary"></ion-icon>

View File

@@ -40,7 +40,11 @@
}
.launch-button {
--border-width: 1px;
--background: rgb(70 193 255 / 75%);
--background-hover: rgb(70 193 255);
--background-hover-opacity: 100%;
--border-style: none;
--color: white;
--border-radius: 10px;
margin: 10px;
margin: 12px 10px;
}

View File

@@ -16,8 +16,6 @@ import { WizardBaker } from 'src/app/components/install-wizard/prebaked-wizards'
import { catchError, concatMap, filter, switchMap, tap } from 'rxjs/operators'
import { Cleanup } from 'src/app/util/cleanup'
import { InformationPopoverComponent } from 'src/app/components/information-popover/information-popover.component'
import { Emver } from 'src/app/services/emver.service'
import { displayEmver } from 'src/app/pipes/emver.pipe'
import { ConfigService } from 'src/app/services/config.service'
@Component({
@@ -53,7 +51,6 @@ export class AppInstalledShowPage extends Cleanup {
private readonly wizardBaker: WizardBaker,
private readonly appModel: AppModel,
private readonly popoverController: PopoverController,
private readonly emver: Emver,
config: ConfigService,
) {
super()
@@ -109,56 +106,6 @@ export class AppInstalledShowPage extends Cleanup {
return window.open(uiAddress, '_blank')
}
async checkForUpdates () {
const app = peekProperties(this.app)
this.loader.of({
message: `Checking for updates...`,
spinner: 'lines',
cssClass: 'loader',
}).displayDuringAsync(
async () => {
const { versionLatest } = await this.apiService.getAvailableApp(this.appId)
if (this.emver.compare(versionLatest, app.versionInstalled) === 1) {
this.presentAlertUpdate(app, versionLatest)
} else {
this.presentAlertUpToDate()
}
},
).catch(e => this.setError(e))
}
async presentAlertUpdate (app: AppInstalledFull, versionLatest: string) {
const alert = await this.alertCtrl.create({
backdropDismiss: false,
header: 'Update Available',
message: `New version ${displayEmver(versionLatest)} found for ${app.title}.`,
buttons: [
{
text: 'Cancel',
role: 'cancel',
},
{
text: 'View in Store',
cssClass: 'alert-success',
handler: () => {
this.navCtrl.navigateForward(['/services', 'marketplace', this.appId])
},
},
],
})
await alert.present()
}
async presentAlertUpToDate () {
const alert = await this.alertCtrl.create({
header: 'Up To Date',
message: `You are running the latest version of ${this.app.title.getValue()}!`,
buttons: ['OK'],
})
await alert.present()
}
async copyTor () {
const app = peekProperties(this.app)
let message = ''

View File

@@ -2,10 +2,8 @@ import { NgModule } from '@angular/core'
import { CommonModule } from '@angular/common'
import { Routes, RouterModule } from '@angular/router'
import { IonicModule } from '@ionic/angular'
import { AppInstructionsPage } from './app-instructions.page'
import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-back.component.module'
import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.module'
import { SharingModule } from 'src/app/modules/sharing.module'
const routes: Routes = [
@@ -21,7 +19,6 @@ const routes: Routes = [
IonicModule,
RouterModule.forChild(routes),
PwaBackComponentModule,
BadgeMenuComponentModule,
SharingModule,
],
declarations: [AppInstructionsPage],

View File

@@ -4,9 +4,6 @@
<pwa-back-button></pwa-back-button>
</ion-buttons>
<ion-title>Instructions</ion-title>
<ion-buttons slot="end">
<badge-menu-button></badge-menu-button>
</ion-buttons>
</ion-toolbar>
</ion-header>

View File

@@ -1,12 +1,9 @@
import { NgModule } from '@angular/core'
import { CommonModule } from '@angular/common'
import { Routes, RouterModule } from '@angular/router'
import { IonicModule } from '@ionic/angular'
import { AppLogsPage } from './app-logs.page'
import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-back.component.module'
import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.module'
const routes: Routes = [
{
@@ -21,7 +18,6 @@ const routes: Routes = [
IonicModule,
RouterModule.forChild(routes),
PwaBackComponentModule,
BadgeMenuComponentModule,
],
declarations: [AppLogsPage],
})

View File

@@ -8,7 +8,6 @@
<ion-button (click)="getLogs()" color="primary">
<ion-icon name="refresh-outline"></ion-icon>
</ion-button>
<badge-menu-button></badge-menu-button>
</ion-buttons>
</ion-toolbar>
</ion-header>

View File

@@ -1,12 +1,9 @@
import { NgModule } from '@angular/core'
import { CommonModule } from '@angular/common'
import { Routes, RouterModule } from '@angular/router'
import { IonicModule } from '@ionic/angular'
import { AppMetricsPage } from './app-metrics.page'
import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-back.component.module'
import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.module'
import { QRComponentModule } from 'src/app/components/qr/qr.component.module'
import { SharingModule } from 'src/app/modules/sharing.module'
@@ -23,7 +20,6 @@ const routes: Routes = [
IonicModule,
RouterModule.forChild(routes),
PwaBackComponentModule,
BadgeMenuComponentModule,
QRComponentModule,
SharingModule,
],

View File

@@ -4,9 +4,6 @@
<pwa-back-button></pwa-back-button>
</ion-buttons>
<ion-title>Properties</ion-title>
<ion-buttons slot="end">
<badge-menu-button></badge-menu-button>
</ion-buttons>
</ion-toolbar>
</ion-header>

View File

@@ -4,7 +4,6 @@ import { IonicModule } from '@ionic/angular'
import { DevOptionsPage } from './dev-options.page'
import { Routes, RouterModule } from '@angular/router'
import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-back.component.module'
import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.module'
import { ObjectConfigComponentModule } from 'src/app/components/object-config/object-config.component.module'
const routes: Routes = [
@@ -21,7 +20,6 @@ const routes: Routes = [
ObjectConfigComponentModule,
RouterModule.forChild(routes),
PwaBackComponentModule,
BadgeMenuComponentModule,
],
declarations: [DevOptionsPage],
})

View File

@@ -4,9 +4,6 @@
<pwa-back-button></pwa-back-button>
</ion-buttons>
<ion-title>Developer Options</ion-title>
<ion-buttons slot="end">
<badge-menu-button></badge-menu-button>
</ion-buttons>
</ion-toolbar>
</ion-header>

View File

@@ -4,7 +4,6 @@ import { IonicModule } from '@ionic/angular'
import { RouterModule, Routes } from '@angular/router'
import { DevSSHKeysPage } from './dev-ssh-keys.page'
import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-back.component.module'
import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.module'
const routes: Routes = [
{
@@ -19,7 +18,6 @@ const routes: Routes = [
IonicModule,
RouterModule.forChild(routes),
PwaBackComponentModule,
BadgeMenuComponentModule,
],
declarations: [DevSSHKeysPage],
})

View File

@@ -4,9 +4,6 @@
<pwa-back-button></pwa-back-button>
</ion-buttons>
<ion-title>SSH Keys</ion-title>
<ion-buttons slot="end">
<badge-menu-button></badge-menu-button>
</ion-buttons>
</ion-toolbar>
</ion-header>

View File

@@ -5,7 +5,6 @@ import { ExternalDrivesPage } from './external-drives.page'
import { Routes, RouterModule } from '@angular/router'
import { SharingModule } from 'src/app/modules/sharing.module'
import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-back.component.module'
import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.module'
import { ObjectConfigComponentModule } from 'src/app/components/object-config/object-config.component.module'
// TODO: EJECT-DISKS
@@ -24,7 +23,6 @@ const routes: Routes = [
ObjectConfigComponentModule,
RouterModule.forChild(routes),
PwaBackComponentModule,
BadgeMenuComponentModule,
],
declarations: [ExternalDrivesPage],
})

View File

@@ -5,9 +5,6 @@
<pwa-back-button></pwa-back-button>
</ion-buttons>
<ion-title>Backup drives</ion-title>
<ion-buttons slot="end">
<badge-menu-button></badge-menu-button>
</ion-buttons>
</ion-toolbar>
</ion-header>

View File

@@ -4,7 +4,6 @@ import { Routes, RouterModule } from '@angular/router'
import { IonicModule } from '@ionic/angular'
import { LANPage } from './lan.page'
import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-back.component.module'
import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.module'
import { SharingModule } from 'src/app/modules/sharing.module'
const routes: Routes = [
@@ -20,7 +19,6 @@ const routes: Routes = [
IonicModule,
RouterModule.forChild(routes),
PwaBackComponentModule,
BadgeMenuComponentModule,
SharingModule,
],
declarations: [LANPage],

View File

@@ -1,8 +1,5 @@
<ion-header>
<ion-toolbar>
<ion-buttons slot="end">
<badge-menu-button></badge-menu-button>
</ion-buttons>
<ion-title>LAN Setup</ion-title>
<ion-buttons slot="start">
<pwa-back-button></pwa-back-button>
@@ -11,54 +8,60 @@
</ion-header>
<ion-content class="ion-padding-top">
<ion-item-group>
<ion-item lines="none" style="font-size: small; --background: var(--ion-background-color);">
<ion-label size="small" class="ion-text-wrap">
<ion-text color="medium">For a <ion-text style="font-style: italic;">faster</ion-text> experience, you can also securely communicate with your Embassy by visiting its Local Area Network (LAN) address.</ion-text>
<ion-item>
<ion-label class="ion-text-wrap">
If you are having issues connecting to your Embassy or services over LAN, you can try refreshing the network by clicking the button below.
</ion-label>
</ion-item>
<!-- info -->
<ion-item>
<ion-button slot="start" fill="clear" (click)="refreshLAN()">
<ion-icon slot="start" name="refresh-outline"></ion-icon>
Refresh Network
</ion-button>
</ion-item>
<ion-item-divider>About</ion-item-divider>
<ion-item lines="none">
<ion-label class="ion-text-wrap">
<h2><ion-text color="warning">Instructions</ion-text></h2>
<ng-container *ngIf="!lanDisabled">
<ul style="font-size: smaller">
<li>Download your Embassy's SSL Certificate Authority by clicking the download button below.</li>
<li>Install and trust the CA.</li>
<li>Connect this device to the same network as the Embassy. This should be your private home network.</li>
<li>Navigate to your Embassy LAN address, indicated below.</li>
</ul>
</ng-container>
<div *ngIf="lanDisabled" class="ion-padding-top ion-padding-bottom">
<p [innerHtml]="lanDisabledExplanation[lanDisabled]"></p>
</div>
<a *ngIf="!isConsulate" [href]="fullDocumentationLink" target="_blank">full documentation</a>
<ion-button *ngIf="isConsulate" fill="outline" (click)="copyDocumentation()">full documentation</ion-button>
You can connect to your Embassy over your Local Area Network (LAN). This can be useful for achieving a faster experience, as well as a fallback in case the Tor network is experiencing issues.
</ion-label>
</ion-item>
<ion-item-divider style="margin-top: 0px"></ion-item-divider>
<!-- Certificate -->
<ion-item [disabled]="!!lanDisabled">
<ion-item *ngIf="lanDisabled">
<ion-label class="ion-text-wrap">
<h2>SSL Certificate</h2>
<p>Embassy Local CA</p>
<ion-text color="warning" [innerHtml]="lanDisabledExplanation[lanDisabled]"></ion-text>
</ion-label>
<ion-button [disabled]="!!lanDisabled" slot="end" fill="clear" (click)="installCert()">
<ion-icon slot="icon-only" name="download-outline"></ion-icon>
</ion-button>
</ion-item>
<!-- URL -->
<ion-item [disabled]="!!lanDisabled" >
<ion-label class="ion-text-wrap">
<h2>LAN Address</h2>
<a [href]="lanAddress" target="_blank">{{ lanAddress }}</a>
</ion-label>
<ion-button [disabled]="!!lanDisabled" slot="end" fill="clear" (click)="copyLAN()">
<ion-icon slot="icon-only" name="copy-outline"></ion-icon>
</ion-button>
<ion-item>
<ion-button slot="start" fill="clear" color="primary">View Instructions</ion-button>
</ion-item>
<ng-container *ngIf="!lanDisabled">
<ion-item-divider>Certificate and Address</ion-item-divider>
<!-- Certificate -->
<ion-item>
<ion-label class="ion-text-wrap">
<h2>Root Certificate Authority</h2>
<p>Embassy Local CA</p>
</ion-label>
<ion-button slot="end" fill="clear" (click)="installCert()">
<ion-icon slot="icon-only" name="download-outline"></ion-icon>
</ion-button>
</ion-item>
<!-- URL -->
<ion-item>
<ion-label class="ion-text-wrap">
<h2>LAN Address</h2>
<p>{{ lanAddress }}</p>
</ion-label>
<ion-button slot="end" fill="clear" (click)="copyLAN()">
<ion-icon slot="icon-only" name="copy-outline"></ion-icon>
</ion-button>
</ion-item>
</ng-container>
</ion-item-group>
<!-- hidden element for downloading cert -->

View File

@@ -0,0 +1,3 @@
.tiny-icon {
font-size: 12px;
}

View File

@@ -3,6 +3,8 @@ import { isPlatform, ToastController } from '@ionic/angular'
import { ServerModel } from 'src/app/models/server-model'
import { copyToClipboard } from 'src/app/util/web.util'
import { ConfigService } from 'src/app/services/config.service'
import { LoaderService } from 'src/app/services/loader.service'
import { ApiService } from 'src/app/services/api/api.service'
@Component({
selector: 'lan',
@@ -20,13 +22,15 @@ export class LANPage {
lanDisabled: LanSetupIssue = undefined
readonly lanDisabledExplanation: { [k in LanSetupIssue]: string } = {
NotDesktop: `We have detected you are on a mobile device. To setup LAN on a mobile device, use the Start9 Setup App.`,
NotTor: `We have detected you are not using a Tor connection. For security reasons, you must setup LAN over a Tor connection.<br /><br/>Navigate to your Embassy Tor Address and try again.`,
NotTor: `We have detected you are not using a Tor connection. For security reasons, you must setup LAN over a Tor connection. Please navigate to your Embassy Tor Address and try again.`,
}
constructor (
private readonly serverModel: ServerModel,
private readonly toastCtrl: ToastController,
private readonly config: ConfigService,
private readonly loader: LoaderService,
private readonly apiService: ApiService,
) { }
ngOnInit () {
@@ -48,7 +52,19 @@ export class LANPage {
this.lanAddress = `https://${server.serverId}.local`
}
async copyLAN (): Promise < void > {
async refreshLAN (): Promise<void> {
this.loader.of({
message: 'Refreshing Network',
spinner: 'lines',
cssClass: 'loader',
}).displayDuringAsync( async () => {
await this.apiService.refreshLAN()
}).catch(e => {
console.error(e)
})
}
async copyLAN (): Promise <void> {
const message = await copyToClipboard(this.lanAddress).then(success => success ? 'copied to clipboard!' : 'failed to copy')
const toast = await this.toastCtrl.create({

View File

@@ -5,7 +5,6 @@ import { ServerConfigPage } from './server-config.page'
import { Routes, RouterModule } from '@angular/router'
import { SharingModule } from 'src/app/modules/sharing.module'
import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-back.component.module'
import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.module'
import { ObjectConfigComponentModule } from 'src/app/components/object-config/object-config.component.module'
const routes: Routes = [
@@ -23,7 +22,6 @@ const routes: Routes = [
ObjectConfigComponentModule,
RouterModule.forChild(routes),
PwaBackComponentModule,
BadgeMenuComponentModule,
],
declarations: [ServerConfigPage],
})

View File

@@ -4,9 +4,6 @@
<pwa-back-button></pwa-back-button>
</ion-buttons>
<ion-title>Config</ion-title>
<ion-buttons slot="end">
<badge-menu-button></badge-menu-button>
</ion-buttons>
</ion-toolbar>
</ion-header>

View File

@@ -1,12 +1,9 @@
import { NgModule } from '@angular/core'
import { CommonModule } from '@angular/common'
import { Routes, RouterModule } from '@angular/router'
import { IonicModule } from '@ionic/angular'
import { ServerLogsPage } from './server-logs.page'
import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-back.component.module'
import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.module'
const routes: Routes = [
{
@@ -21,7 +18,6 @@ const routes: Routes = [
IonicModule,
RouterModule.forChild(routes),
PwaBackComponentModule,
BadgeMenuComponentModule,
],
declarations: [ServerLogsPage],
})

View File

@@ -8,7 +8,6 @@
<ion-button (click)="getLogs()" color="primary">
<ion-icon name="refresh-outline"></ion-icon>
</ion-button>
<badge-menu-button></badge-menu-button>
</ion-buttons>
</ion-toolbar>
</ion-header>

View File

@@ -1,12 +1,9 @@
import { NgModule } from '@angular/core'
import { CommonModule } from '@angular/common'
import { Routes, RouterModule } from '@angular/router'
import { IonicModule } from '@ionic/angular'
import { ServerMetricsPage } from './server-metrics.page'
import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-back.component.module'
import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.module'
const routes: Routes = [
{
@@ -21,7 +18,6 @@ const routes: Routes = [
IonicModule,
RouterModule.forChild(routes),
PwaBackComponentModule,
BadgeMenuComponentModule,
],
declarations: [ServerMetricsPage],
})

View File

@@ -4,9 +4,6 @@
<pwa-back-button></pwa-back-button>
</ion-buttons>
<ion-title>Metrics</ion-title>
<ion-buttons slot="end">
<badge-menu-button></badge-menu-button>
</ion-buttons>
</ion-toolbar>
</ion-header>

View File

@@ -7,7 +7,7 @@
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding-bottom">
<ion-content class="ion-padding-top ion-padding-bottom">
<ng-container *ngIf="updating">
<ion-item class="ion-text-center">
<div style="display: flex; justify-content: center; width: 100%;">
@@ -28,14 +28,6 @@
</ion-item>
<ion-item-group>
<ion-item-divider></ion-item-divider>
<ion-item lines="none" button (click)="checkForUpdates()">
<ion-icon slot="start" name="refresh-outline" color="primary"></ion-icon>
<ion-label><ion-text style="font-weight: bold;" color="primary">Check for Updates</ion-text></ion-label>
</ion-item>
<ion-item-divider></ion-item-divider>
<ion-item [routerLink]="['specs']">
<ion-icon slot="start" name="information-circle-outline" color="primary"></ion-icon>
@@ -52,6 +44,8 @@
<ion-label><ion-text color="primary">Logs</ion-text></ion-label>
</ion-item>
<ion-item-divider></ion-item-divider>
<ion-item lines="none" [routerLink]="['config']">
<ion-icon slot="start" name="cog-outline" color="primary"></ion-icon>
<ion-label><ion-text color="primary">Config</ion-text></ion-label>
@@ -59,7 +53,7 @@
<ion-item [routerLink]="['lan']">
<ion-icon slot="start" name="home-outline" color="primary"></ion-icon>
<ion-label><ion-text color="primary">LAN Setup</ion-text></ion-label>
<ion-label><ion-text color="primary">Connect over LAN</ion-text></ion-label>
</ion-item>
<ion-item [routerLink]="['wifi']">
@@ -67,6 +61,8 @@
<ion-label><ion-text color="primary">WiFi Setup</ion-text></ion-label>
</ion-item>
<ion-item-divider></ion-item-divider>
<ion-item lines="none" [routerLink]="['developer']">
<ion-icon slot="start" name="terminal-outline" color="primary"></ion-icon>
<ion-label><ion-text color="primary">Developer Options</ion-text></ion-label>

View File

@@ -1,7 +1,7 @@
import { Component } from '@angular/core'
import { LoadingOptions } from '@ionic/core'
import { ServerModel, ServerStatus } from 'src/app/models/server-model'
import { AlertController, ModalController } from '@ionic/angular'
import { AlertController } from '@ionic/angular'
import { S9Server } from 'src/app/models/server-model'
import { ApiService } from 'src/app/services/api/api.service'
import { SyncDaemon } from 'src/app/services/sync.service'
@@ -9,9 +9,6 @@ import { Subscription, Observable } from 'rxjs'
import { PropertySubject, toObservable } from 'src/app/util/property-subject.util'
import { doForAtLeast } from 'src/app/util/misc.util'
import { LoaderService } from 'src/app/services/loader.service'
import { Emver } from 'src/app/services/emver.service'
import { wizardModal } from 'src/app/components/install-wizard/install-wizard.component'
import { WizardBaker } from 'src/app/components/install-wizard/prebaked-wizards'
@Component({
selector: 'server-show',
@@ -36,9 +33,6 @@ export class ServerShowPage {
private readonly loader: LoaderService,
private readonly apiService: ApiService,
private readonly syncDaemon: SyncDaemon,
private readonly emver: Emver,
private readonly modalCtrl: ModalController,
private readonly wizardBaker: WizardBaker,
) { }
async ngOnInit () {
@@ -82,55 +76,6 @@ export class ServerShowPage {
}
}
async checkForUpdates (): Promise<void> {
const loader = await this.loader.ctrl.create(LoadingSpinner('Checking for updates...'))
await loader.present()
try {
const { versionLatest, releaseNotes } = await this.apiService.getVersionLatest()
if (this.emver.compare(this.server.versionInstalled.getValue(), versionLatest) === -1) {
this.presentAlertUpdate(versionLatest, releaseNotes)
} else {
this.presentAlertUpToDate()
}
} catch (e) {
console.error(e)
this.error = e.message
} finally {
await loader.dismiss()
}
}
async presentAlertUpToDate () {
const alert = await this.alertCtrl.create({
header: 'Up To Date',
message: `You are running the latest version of EmbassyOS!`,
buttons: ['OK'],
})
await alert.present()
}
async presentAlertUpdate (versionLatest: string, releaseNotes: string) {
const alert = await this.alertCtrl.create({
backdropDismiss: false,
header: 'Confirm',
message: `Update EmbassyOS to version ${versionLatest}?`,
buttons: [
{
text: 'Cancel',
role: 'cancel',
},
{
text: 'Update',
handler: () => {
this.updateEmbassyOS(versionLatest, releaseNotes)
},
},
],
})
await alert.present()
}
async presentAlertRestart () {
const alert = await this.alertCtrl.create({
backdropDismiss: false,
@@ -175,38 +120,24 @@ export class ServerShowPage {
await alert.present()
}
private async updateEmbassyOS (versionLatest: string, releaseNotes: string) {
const { cancelled } = await wizardModal(
this.modalCtrl,
this.wizardBaker.updateOS({
version: versionLatest,
releaseNotes: releaseNotes,
}),
)
if (cancelled) return
this.updatingFreeze = true
this.updating = true
setTimeout(() => this.updatingFreeze = false, 8000)
}
private async restart () {
this.loader
.of(LoadingSpinner(`Restarting ${this.currentServer.name}...`))
.displayDuringAsync( async () => {
this.serverModel.markUnreachable()
await this.apiService.restartServer()
})
.catch(e => this.setError(e))
.of(LoadingSpinner(`Restarting ${this.currentServer.name}...`))
.displayDuringAsync( async () => {
this.serverModel.markUnreachable()
await this.apiService.restartServer()
})
.catch(e => this.setError(e))
}
private async shutdown () {
this.loader
.of(LoadingSpinner(`Shutting down ${this.currentServer.name}...`))
.displayDuringAsync( async () => {
this.serverModel.markUnreachable()
await this.apiService.shutdownServer()
})
.catch(e => this.setError(e))
.of(LoadingSpinner(`Shutting down ${this.currentServer.name}...`))
.displayDuringAsync( async () => {
this.serverModel.markUnreachable()
await this.apiService.shutdownServer()
})
.catch(e => this.setError(e))
}
setError (e: Error) {

View File

@@ -1,12 +1,9 @@
import { NgModule } from '@angular/core'
import { CommonModule } from '@angular/common'
import { Routes, RouterModule } from '@angular/router'
import { IonicModule } from '@ionic/angular'
import { ServerSpecsPage } from './server-specs.page'
import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-back.component.module'
import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.module'
import { SharingModule } from 'src/app/modules/sharing.module'
const routes: Routes = [
@@ -22,7 +19,6 @@ const routes: Routes = [
IonicModule,
RouterModule.forChild(routes),
PwaBackComponentModule,
BadgeMenuComponentModule,
SharingModule,
],
declarations: [ServerSpecsPage],

View File

@@ -4,9 +4,6 @@
<pwa-back-button></pwa-back-button>
</ion-buttons>
<ion-title>About</ion-title>
<ion-buttons slot="end">
<badge-menu-button></badge-menu-button>
</ion-buttons>
</ion-toolbar>
</ion-header>

View File

@@ -1,6 +1,5 @@
import { Component } from '@angular/core'
import { S9Server } from 'src/app/models/server-model'
import { ToastController } from '@ionic/angular'
import { copyToClipboard } from 'src/app/util/web.util'
import { PropertySubject } from 'src/app/util/property-subject.util'

View File

@@ -5,7 +5,6 @@ import { IonicModule } from '@ionic/angular'
import { RouterModule, Routes } from '@angular/router'
import { WifiAddPage } from './wifi-add.page'
import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-back.component.module'
import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.module'
const routes: Routes = [
{
@@ -21,7 +20,6 @@ const routes: Routes = [
IonicModule,
RouterModule.forChild(routes),
PwaBackComponentModule,
BadgeMenuComponentModule,
],
declarations: [WifiAddPage],
})

View File

@@ -4,9 +4,6 @@
<pwa-back-button></pwa-back-button>
</ion-buttons>
<ion-title>Add Network</ion-title>
<ion-buttons slot="end">
<badge-menu-button></badge-menu-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
@@ -38,12 +35,12 @@
<ion-row>
<ion-col size="6">
<ion-button [disabled]="!ssid" expand="block" fill="outline" color="primary" (click)="add()">
Add
Save for Later
</ion-button>
</ion-col>
<ion-col size="6">
<ion-button [disabled]="!ssid" expand="block" fill="outline" color="success" (click)="addAndConnect()">
Add and Connect
<ion-button [disabled]="!ssid" expand="block" fill="outline" color="primary" (click)="addAndConnect()">
Save and Connect Now
</ion-button>
</ion-col>
</ion-row>

View File

@@ -4,7 +4,6 @@ import { IonicModule } from '@ionic/angular'
import { RouterModule, Routes } from '@angular/router'
import { WifiListPage } from './wifi.page'
import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-back.component.module'
import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.module'
const routes: Routes = [
{
@@ -23,7 +22,6 @@ const routes: Routes = [
IonicModule,
RouterModule.forChild(routes),
PwaBackComponentModule,
BadgeMenuComponentModule,
],
declarations: [WifiListPage],
})

View File

@@ -4,9 +4,6 @@
<pwa-back-button></pwa-back-button>
</ion-buttons>
<ion-title>WiFi Setup</ion-title>
<ion-buttons slot="end">
<badge-menu-button></badge-menu-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
@@ -23,10 +20,13 @@
<ion-item-group>
<ion-item>
<ion-label class="ion-text-wrap">
<ion-text color="dark">By providing your Embassy with WiFi credentials for one or more networks, you can remove the Ethernet cable and place your Embassy anywhere.</ion-text>
<br />
<br />
<ion-text color="warning">Warning!</ion-text>
<br />
<br />
<ion-text color="dark">Making changes to WiFi can cause your Embassy and its Services to become unreachable for a few minutes to an hour. Please be patient.</ion-text>
<ion-text color="dark">Connecting, disconnecting, or changing WiFi networks can cause your Embassy and its services to become unreachable for up to an hour. Please be patient.</ion-text>
</ion-label>
</ion-item>

View File

@@ -63,6 +63,7 @@ export abstract class ApiService {
abstract shutdownServer (): Promise<Unit>
abstract ejectExternalDisk (logicalName: string): Promise<Unit>
abstract serviceAction (appId: string, serviceAction: ServiceAction): Promise<ReqRes.ServiceActionResponse>
abstract refreshLAN (): Promise<Unit>
}
export function isRpcFailure<Error, Result> (arg: { error: Error } | { result: Result}): arg is { error: Error } {

View File

@@ -13,6 +13,7 @@ import { modulateTime } from 'src/app/util/misc.util'
import { Observable, of, throwError } from 'rxjs'
import { catchError, mapTo } from 'rxjs/operators'
import * as uuid from 'uuid'
import { METHODS } from 'http'
@Injectable()
export class LiveApiService extends ApiService {
@@ -276,6 +277,10 @@ export class LiveApiService extends ApiService {
return this.authRequest({ method: Method.POST, url: `apps/${appId}/actions`, data })
}
async refreshLAN (): Promise<Unit> {
return this.authRequest({ method: Method.POST, url: '/network/lan/reset' })
}
private async authRequest<T> (opts: HttpOptions, overrides: Partial<{ version: string }> = { }): Promise<T> {
if (!this.authenticatedRequestsEnabled) throw new Error(`Authenticated requests are not enabled. Do you need to login?`)

View File

@@ -242,6 +242,10 @@ export class MockApiService extends ApiService {
},
}
}
refreshLAN (): Promise<Unit> {
return mockRefreshLAN()
}
}
async function mockGetServer (): Promise<ReqRes.GetServerRes> {
@@ -406,6 +410,11 @@ async function mockShutdownServer (): Promise<Unit> {
return { }
}
async function mockRefreshLAN (): Promise<Unit> {
await pauseFor(1000)
return { }
}
const mockApiNotifications: ReqRes.GetNotificationsRes = [
{
id: '123e4567-e89b-12d3-a456-426655440000',

View File

@@ -302,7 +302,6 @@ ion-avatar {
}
ion-item-divider {
margin-top: 15px;
color: var(--ion-color-medium);
font-size: medium;
padding-left: 10px;