mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 02:11:53 +00:00
refresh LAN and more
This commit is contained in:
committed by
Aiden McClelland
parent
3e3097945f
commit
6585d91816
@@ -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>
|
||||
|
||||
@@ -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,
|
||||
],
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 = ''
|
||||
|
||||
@@ -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],
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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],
|
||||
})
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,
|
||||
],
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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],
|
||||
})
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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],
|
||||
})
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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],
|
||||
})
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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],
|
||||
|
||||
@@ -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 -->
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
.tiny-icon {
|
||||
font-size: 12px;
|
||||
}
|
||||
@@ -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({
|
||||
|
||||
@@ -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],
|
||||
})
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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],
|
||||
})
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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],
|
||||
})
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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],
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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],
|
||||
})
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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],
|
||||
})
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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 } {
|
||||
|
||||
@@ -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?`)
|
||||
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -302,7 +302,6 @@ ion-avatar {
|
||||
}
|
||||
|
||||
ion-item-divider {
|
||||
margin-top: 15px;
|
||||
color: var(--ion-color-medium);
|
||||
font-size: medium;
|
||||
padding-left: 10px;
|
||||
|
||||
Reference in New Issue
Block a user