0.2.5 initial commit

Makefile incomplete
This commit is contained in:
Aiden McClelland
2020-11-23 13:44:28 -07:00
commit 95d3845906
503 changed files with 53448 additions and 0 deletions

View File

@@ -0,0 +1,32 @@
import { NgModule } from '@angular/core'
import { CommonModule } from '@angular/common'
import { IonicModule } from '@ionic/angular'
import { RouterModule, Routes } from '@angular/router'
import { ServerShowPage } from './server-show.page'
import { StatusComponentModule } from 'src/app/components/status/status.component.module'
import { FormsModule } from '@angular/forms'
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'
const routes: Routes = [
{
path: '',
component: ServerShowPage,
},
]
@NgModule({
imports: [
CommonModule,
FormsModule,
StatusComponentModule,
IonicModule,
RouterModule.forChild(routes),
SharingModule,
PwaBackComponentModule,
BadgeMenuComponentModule,
],
declarations: [ServerShowPage],
})
export class ServerShowPageModule { }

View File

@@ -0,0 +1,86 @@
<ion-header>
<ion-toolbar>
<ion-title>{{ server.name | async }}</ion-title>
<ion-buttons slot="end">
<badge-menu-button></badge-menu-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding-bottom">
<ng-container *ngIf="updating">
<ion-item class="ion-text-center">
<div style="display: flex; justify-content: center; width: 100%;">
<ion-text class="ion-text-wrap" style="margin-right: 5px; margin-top: 5px" color="primary">Server Updating</ion-text>
<ion-spinner style="margin-left: 5px" name="lines"></ion-spinner>
</div>
</ion-item>
</ng-container>
<ng-container *ngIf="!updating">
<ion-refresher slot="fixed" (ionRefresh)="doRefresh($event)">
<ion-refresher-content pullingIcon="lines" refreshingSpinner="lines"></ion-refresher-content>
</ion-refresher>
<ion-item *ngIf="error">
<ion-text class="ion-text-wrap" color="danger">{{ error }}</ion-text>
</ion-item>
<ion-item-group>
<ion-item-divider></ion-item-divider>
<ion-item [routerLink]="['specs']">
<ion-icon slot="start" name="information-circle-outline" color="primary"></ion-icon>
<ion-label><ion-text color="primary">About</ion-text></ion-label>
</ion-item>
<ion-item [routerLink]="['metrics']">
<ion-icon slot="start" name="pulse" color="primary"></ion-icon>
<ion-label><ion-text color="primary">Monitor</ion-text></ion-label>
</ion-item>
<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>
</ion-item>
<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]="['lan']">
<ion-icon slot="start" name="home-outline" color="primary"></ion-icon>
<ion-label><ion-text color="primary">Secure LAN Setup</ion-text></ion-label>
</ion-item>
<ion-item [routerLink]="['wifi']">
<ion-icon slot="start" name="wifi" color="primary"></ion-icon>
<ion-label><ion-text color="primary">WiFi</ion-text></ion-label>
</ion-item>
<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>
</ion-item>
<ion-item-divider></ion-item-divider>
<ion-item button (click)="presentAlertRestart()">
<ion-icon slot="start" name="reload-outline" color="primary"></ion-icon>
<ion-label><ion-text color="primary">Restart</ion-text></ion-label>
</ion-item>
<ion-item button lines="none" (click)="presentAlertShutdown()">
<ion-icon slot="start" name="power" color="primary"></ion-icon>
<ion-label><ion-text color="primary">Shutdown</ion-text></ion-label>
</ion-item>
</ion-item-group>
</ng-container>
</ion-content>

View File

@@ -0,0 +1,12 @@
.notification-button {
ion-badge {
position: absolute;
font-size: 8px;
bottom: .7rem;
left: .8rem;
}
}
ion-item-divider {
margin-top: 0px;
}

View File

@@ -0,0 +1,222 @@
import { Component } from '@angular/core'
import { LoadingOptions } from '@ionic/core'
import { ServerModel, ServerStatus } from 'src/app/models/server-model'
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'
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'
@Component({
selector: 'server-show',
templateUrl: 'server-show.page.html',
styleUrls: ['server-show.page.scss'],
})
export class ServerShowPage {
error = ''
s9Host$: Observable<string>
server: PropertySubject<S9Server>
currentServer: S9Server
subsToTearDown: Subscription[] = []
updatingFreeze = false
updating = false
constructor (
private readonly serverModel: ServerModel,
private readonly alertCtrl: AlertController,
private readonly loader: LoaderService,
private readonly apiService: ApiService,
private readonly syncDaemon: SyncDaemon,
private readonly emver: Emver,
) { }
async ngOnInit () {
this.server = this.serverModel.watch()
this.subsToTearDown.push(
// serverUpdateSubscription
this.server.status.subscribe(status => {
if (status === ServerStatus.UPDATING) {
this.updating = true
} else {
if (!this.updatingFreeze) { this.updating = false }
}
}),
// currentServerSubscription
toObservable(this.server).subscribe(currentServerProperties => {
this.currentServer = currentServerProperties
}),
)
}
ionViewDidEnter () {
this.error = ''
}
ngOnDestroy () {
this.subsToTearDown.forEach(s => s.unsubscribe())
}
async doRefresh (event: any) {
await doForAtLeast([this.getServerAndApps()], 600)
event.target.complete()
}
async getServerAndApps (): Promise<void> {
try {
this.syncDaemon.sync()
this.error = ''
} catch (e) {
console.error(e)
this.error = e.message
}
}
async checkForUpdates (): Promise<void> {
const loader = await this.loader.ctrl.create(LoadingSpinner('Checking for updates...'))
await loader.present()
try {
const { versionLatest } = await this.apiService.getVersionLatest()
if (this.emver.compare(this.server.versionInstalled.getValue(), versionLatest) === -1) {
this.presentAlertUpdate(versionLatest)
} 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) {
const alert = await this.alertCtrl.create({
backdropDismiss: false,
header: 'Confirm',
message: `Update EmbassyOS to ${versionLatest}?`,
buttons: [
{
text: 'Cancel',
role: 'cancel',
},
{
text: 'Update',
handler: () => {
this.updateEmbassyOS(versionLatest)
},
},
],
})
await alert.present()
}
async presentAlertRestart () {
const alert = await this.alertCtrl.create({
backdropDismiss: false,
header: 'Confirm',
message: `Are you sure you want to restart your Embassy?`,
buttons: [
{
text: 'Cancel',
role: 'cancel',
},
{
text: 'Restart',
cssClass: 'alert-danger',
handler: () => {
this.restart()
},
},
]},
)
await alert.present()
}
async presentAlertShutdown () {
const alert = await this.alertCtrl.create({
backdropDismiss: false,
header: 'Confirm',
message: `Are you sure you shut down your Embassy? To turn it back on, you will need to physically unplug the device and plug it back in.`,
buttons: [
{
text: 'Cancel',
role: 'cancel',
},
{
text: 'Shutdown',
cssClass: 'alert-danger',
handler: () => {
this.shutdown()
},
},
],
})
await alert.present()
}
private async updateEmbassyOS (versionLatest: string) {
this.loader
.displayDuringAsync(async () => {
await this.apiService.updateAgent(versionLatest)
this.serverModel.update({ status: ServerStatus.UPDATING })
// hides the "Update Embassy to..." button for this intance of the component
this.updatingFreeze = true
this.updating = true
setTimeout(() => this.updatingFreeze = false, 8000)
})
.catch(e => this.setError(e))
}
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))
}
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))
}
setError (e: Error) {
console.error(e)
this.error = e.message
}
}
const LoadingSpinner: (m?: string) => LoadingOptions = (m) => {
const toMergeIn = m ? { message: m } : { }
return {
spinner: 'lines',
cssClass: 'loader',
...toMergeIn,
} as LoadingOptions
}