mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 12:11:56 +00:00
react to enter key for alerts and modals. Styling and logic
This commit is contained in:
@@ -101,7 +101,7 @@
|
|||||||
<ion-icon name="pulse"></ion-icon>
|
<ion-icon name="pulse"></ion-icon>
|
||||||
<ion-icon name="qr-code-outline"></ion-icon>
|
<ion-icon name="qr-code-outline"></ion-icon>
|
||||||
<ion-icon name="receipt-outline"></ion-icon>
|
<ion-icon name="receipt-outline"></ion-icon>
|
||||||
<ion-icon name="refresh-outline"></ion-icon>
|
<ion-icon name="refresh"></ion-icon>
|
||||||
<ion-icon name="reload-outline"></ion-icon>
|
<ion-icon name="reload-outline"></ion-icon>
|
||||||
<ion-icon name="remove-outline"></ion-icon>
|
<ion-icon name="remove-outline"></ion-icon>
|
||||||
<ion-icon name="save-outline"></ion-icon>
|
<ion-icon name="save-outline"></ion-icon>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Component } from '@angular/core'
|
import { Component, HostListener } from '@angular/core'
|
||||||
import { Storage } from '@ionic/storage-angular'
|
import { Storage } from '@ionic/storage-angular'
|
||||||
import { AuthService, AuthState } from './services/auth.service'
|
import { AuthService, AuthState } from './services/auth.service'
|
||||||
import { ApiService } from './services/api/embassy-api.service'
|
import { ApiService } from './services/api/embassy-api.service'
|
||||||
@@ -24,6 +24,15 @@ import { Subscription } from 'rxjs'
|
|||||||
styleUrls: ['app.component.scss'],
|
styleUrls: ['app.component.scss'],
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
|
@HostListener('document:keypress', ['$event'])
|
||||||
|
handleKeyboardEvent (event: KeyboardEvent) {
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
const elems = document.getElementsByClassName('enter-click')
|
||||||
|
const elem = elems[elems.length - 1] as HTMLButtonElement
|
||||||
|
if (elem) elem.click()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ServerStatus = ServerStatus
|
ServerStatus = ServerStatus
|
||||||
showMenu = false
|
showMenu = false
|
||||||
selectedIndex = 0
|
selectedIndex = 0
|
||||||
@@ -143,6 +152,47 @@ export class AppComponent {
|
|||||||
window.open(url, '_blank')
|
window.open(url, '_blank')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async presentAlertLogout () {
|
||||||
|
// @TODO warn user no way to recover Embassy if logout and forget password. Maybe require password to logout?
|
||||||
|
const alert = await this.alertCtrl.create({
|
||||||
|
header: 'Caution',
|
||||||
|
message: 'Are you sure you want to logout?',
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
text: 'Cancel',
|
||||||
|
role: 'cancel',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Logout',
|
||||||
|
cssClass: 'enter-click',
|
||||||
|
handler: () => {
|
||||||
|
this.logout()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
await alert.present()
|
||||||
|
}
|
||||||
|
|
||||||
|
private async logout () {
|
||||||
|
const loader = await this.loadingCtrl.create({
|
||||||
|
spinner: 'lines',
|
||||||
|
message: 'Logging out...',
|
||||||
|
cssClass: 'loader',
|
||||||
|
})
|
||||||
|
await loader.present()
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.embassyApi.logout({ })
|
||||||
|
this.authService.setUnverified()
|
||||||
|
} catch (e) {
|
||||||
|
await this.errToast.present(e)
|
||||||
|
} finally {
|
||||||
|
loader.dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private watchConnection (): Subscription {
|
private watchConnection (): Subscription {
|
||||||
return this.connectionService.watchFailure$()
|
return this.connectionService.watchFailure$()
|
||||||
.pipe(
|
.pipe(
|
||||||
@@ -234,7 +284,7 @@ export class AppComponent {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async presentAlertRefreshNeeded () {
|
private async presentAlertRefreshNeeded () {
|
||||||
const alert = await this.alertCtrl.create({
|
const alert = await this.alertCtrl.create({
|
||||||
backdropDismiss: false,
|
backdropDismiss: false,
|
||||||
header: 'Refresh Needed',
|
header: 'Refresh Needed',
|
||||||
@@ -242,6 +292,7 @@ export class AppComponent {
|
|||||||
buttons: [
|
buttons: [
|
||||||
{
|
{
|
||||||
text: 'Refresh Page',
|
text: 'Refresh Page',
|
||||||
|
cssClass: 'enter-click',
|
||||||
handler: () => {
|
handler: () => {
|
||||||
location.reload()
|
location.reload()
|
||||||
},
|
},
|
||||||
@@ -251,46 +302,6 @@ export class AppComponent {
|
|||||||
await alert.present()
|
await alert.present()
|
||||||
}
|
}
|
||||||
|
|
||||||
async presentAlertLogout () {
|
|
||||||
// @TODO warn user no way to recover Embassy if logout and forget password. Maybe require password to logout?
|
|
||||||
const alert = await this.alertCtrl.create({
|
|
||||||
backdropDismiss: false,
|
|
||||||
header: 'Caution',
|
|
||||||
message: 'Are you sure you want to logout?',
|
|
||||||
buttons: [
|
|
||||||
{
|
|
||||||
text: 'Cancel',
|
|
||||||
role: 'cancel',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Logout',
|
|
||||||
handler: () => {
|
|
||||||
this.logout()
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
await alert.present()
|
|
||||||
}
|
|
||||||
|
|
||||||
private async logout () {
|
|
||||||
const loader = await this.loadingCtrl.create({
|
|
||||||
spinner: 'lines',
|
|
||||||
message: 'Logging out...',
|
|
||||||
cssClass: 'loader',
|
|
||||||
})
|
|
||||||
await loader.present()
|
|
||||||
|
|
||||||
try {
|
|
||||||
await this.embassyApi.logout({ })
|
|
||||||
this.authService.setUnverified()
|
|
||||||
} catch (e) {
|
|
||||||
await this.errToast.present(e)
|
|
||||||
} finally {
|
|
||||||
loader.dismiss()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async presentToastNotifications () {
|
private async presentToastNotifications () {
|
||||||
const toast = await this.toastCtrl.create({
|
const toast = await this.toastCtrl.create({
|
||||||
header: 'Embassy',
|
header: 'Embassy',
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
<ion-item-group [formGroup]="formGroup">
|
<ion-item-group [formGroup]="formGroup">
|
||||||
<div *ngFor="let entry of formGroup.controls | keyvalue : asIsOrder">
|
<div *ngFor="let entry of formGroup.controls | keyvalue : asIsOrder">
|
||||||
|
<!-- union enum -->
|
||||||
<ng-container *ngIf="unionSpec && entry.key === unionSpec.tag.id">
|
<ng-container *ngIf="unionSpec && entry.key === unionSpec.tag.id">
|
||||||
<p class="input-label">{{ unionSpec.tag.name }}</p>
|
<p class="input-label">{{ unionSpec.tag.name }}</p>
|
||||||
<ion-item>
|
<ion-item>
|
||||||
<ion-label>{{ unionSpec.tag.name }}</ion-label>
|
<ion-label>{{ unionSpec.tag.name }}</ion-label>
|
||||||
<ion-select slot="end" placeholder="Select" [formControlName]="unionSpec.tag.id" [selectedText]="unionSpec.tag['variant-names'][entry.value.value]" (ionChange)="presentAlertChangeWarning(entry.key, unionSpec); updateUnion($event)">
|
<ion-select [interfaceOptions]="{ message: getWarningText(unionSpec.warning) }" slot="end" placeholder="Select" [formControlName]="unionSpec.tag.id" [selectedText]="unionSpec.tag['variant-names'][entry.value.value]" (ionChange)="updateUnion($event)">
|
||||||
<ion-select-option *ngFor="let option of Object.keys(unionSpec.variants)" [value]="option">
|
<ion-select-option *ngFor="let option of Object.keys(unionSpec.variants)" [value]="option">
|
||||||
{{ unionSpec.tag['variant-names'][option] }}
|
{{ unionSpec.tag['variant-names'][option] }}
|
||||||
</ion-select-option>
|
</ion-select-option>
|
||||||
</ion-select>
|
</ion-select>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngIf="objectSpec[entry.key] as spec">
|
<ng-container *ngIf="objectSpec[entry.key] as spec">
|
||||||
<!-- primitive -->
|
<!-- primitive -->
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Component, Input, Output, SimpleChange, EventEmitter } from '@angular/core'
|
import { Component, Input, Output, SimpleChange, EventEmitter } from '@angular/core'
|
||||||
import { AbstractFormGroupDirective, FormArray, FormGroup } from '@angular/forms'
|
import { AbstractFormGroupDirective, FormArray, FormGroup } from '@angular/forms'
|
||||||
import { AlertController, IonicSafeString, ModalController } from '@ionic/angular'
|
import { AlertButton, AlertController, IonicSafeString, ModalController } from '@ionic/angular'
|
||||||
import { ConfigSpec, ListValueSpecOf, ValueSpec, ValueSpecBoolean, ValueSpecList, ValueSpecListOf, ValueSpecNumber, ValueSpecString, ValueSpecUnion } from 'src/app/pkg-config/config-types'
|
import { ConfigSpec, ListValueSpecOf, ValueSpec, ValueSpecBoolean, ValueSpecList, ValueSpecListOf, ValueSpecUnion } from 'src/app/pkg-config/config-types'
|
||||||
import { FormService } from 'src/app/services/form.service'
|
import { FormService } from 'src/app/services/form.service'
|
||||||
import { Range } from 'src/app/pkg-config/config-utilities'
|
import { Range } from 'src/app/pkg-config/config-utilities'
|
||||||
import { EnumListPage } from 'src/app/modals/enum-list/enum-list.page'
|
import { EnumListPage } from 'src/app/modals/enum-list/enum-list.page'
|
||||||
@@ -34,17 +34,6 @@ export class FormObjectComponent {
|
|||||||
) { }
|
) { }
|
||||||
|
|
||||||
ngOnChanges (changes: { [propName: string]: SimpleChange }) {
|
ngOnChanges (changes: { [propName: string]: SimpleChange }) {
|
||||||
// @TODO figure out why changes are being triggered so often. If too heavy, switch to ngOnInit and figure out another way to manually reset defaults is executed. Needed because otherwise ObjectListInfo won't be accurate.
|
|
||||||
|
|
||||||
// if ( changes['current'] && changes['current'].previousValue != changes['current'].currentValue ) {
|
|
||||||
// console.log('CURRENT')
|
|
||||||
// }
|
|
||||||
// if ( changes['formGroup'] && changes['formGroup'].previousValue != changes['formGroup'].currentValue ) {
|
|
||||||
// console.log('FORM GROUP')
|
|
||||||
// }
|
|
||||||
// if ( changes['objectSpec'] && changes['objectSpec'].previousValue != changes['objectSpec'].currentValue ) {
|
|
||||||
// console.log('OBJECT SPEC')
|
|
||||||
// }
|
|
||||||
// Lists are automatically expanded, but their members are not
|
// Lists are automatically expanded, but their members are not
|
||||||
Object.keys(this.objectSpec).forEach(key => {
|
Object.keys(this.objectSpec).forEach(key => {
|
||||||
const spec = this.objectSpec[key]
|
const spec = this.objectSpec[key]
|
||||||
@@ -157,12 +146,13 @@ export class FormObjectComponent {
|
|||||||
if (!spec.warning || this.warningAck[key]) return okFn ? okFn() : null
|
if (!spec.warning || this.warningAck[key]) return okFn ? okFn() : null
|
||||||
this.warningAck[key] = true
|
this.warningAck[key] = true
|
||||||
|
|
||||||
const buttons = [
|
const buttons: AlertButton[] = [
|
||||||
{
|
{
|
||||||
text: 'Ok',
|
text: 'Ok',
|
||||||
handler: () => {
|
handler: () => {
|
||||||
if (okFn) okFn()
|
if (okFn) okFn()
|
||||||
},
|
},
|
||||||
|
cssClass: 'enter-click',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -186,7 +176,6 @@ export class FormObjectComponent {
|
|||||||
|
|
||||||
async presentAlertDelete (key: string, index: number) {
|
async presentAlertDelete (key: string, index: number) {
|
||||||
const alert = await this.alertCtrl.create({
|
const alert = await this.alertCtrl.create({
|
||||||
backdropDismiss: false,
|
|
||||||
header: 'Confirm',
|
header: 'Confirm',
|
||||||
message: 'Are you sure you want to delete this entry?',
|
message: 'Are you sure you want to delete this entry?',
|
||||||
buttons: [
|
buttons: [
|
||||||
@@ -199,6 +188,7 @@ export class FormObjectComponent {
|
|||||||
handler: () => {
|
handler: () => {
|
||||||
this.deleteListItem(key, index)
|
this.deleteListItem(key, index)
|
||||||
},
|
},
|
||||||
|
cssClass: 'enter-click',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
@@ -260,7 +250,6 @@ export class FormLabelComponent {
|
|||||||
const alert = await this.alertCtrl.create({
|
const alert = await this.alertCtrl.create({
|
||||||
header: name,
|
header: name,
|
||||||
message: description,
|
message: description,
|
||||||
buttons: ['Ok'],
|
|
||||||
})
|
})
|
||||||
await alert.present()
|
await alert.present()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,12 +49,12 @@
|
|||||||
<!-- next/finish buttons -->
|
<!-- next/finish buttons -->
|
||||||
<ng-container *ngIf="!(currentSlide.loading$ | async)">
|
<ng-container *ngIf="!(currentSlide.loading$ | async)">
|
||||||
<!-- next -->
|
<!-- next -->
|
||||||
<ion-button slot="end" *ngIf="currentBottomBar.next as next" (click)="transitions.next()" fill="outline" class="toolbar-button" color="primary">
|
<ion-button slot="end" *ngIf="currentBottomBar.next as next" (click)="transitions.next()" fill="outline" class="toolbar-button enter-click">
|
||||||
<ion-text [class.smaller-text]="next.length > 16">{{ next }}</ion-text>
|
<ion-text [class.smaller-text]="next.length > 16">{{ next }}</ion-text>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
|
|
||||||
<!-- finish -->
|
<!-- finish -->
|
||||||
<ion-button slot="end" *ngIf="currentBottomBar.finish as finish" (click)="transitions.final()" fill="outline" class="toolbar-button" color="primary">
|
<ion-button slot="end" *ngIf="currentBottomBar.finish as finish" (click)="transitions.final()" fill="outline" class="toolbar-button enter-click">
|
||||||
<ion-text [class.smaller-text]="finish.length > 16">{{ finish }}</ion-text>
|
<ion-text [class.smaller-text]="finish.length > 16">{{ finish }}</ion-text>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
<ion-header style="min-height: unset;">
|
<ion-header>
|
||||||
<ion-toolbar *ngIf="patch.data['package-data'][pkgId] as pkg">
|
<ion-toolbar>
|
||||||
|
<ion-buttons slot="start">
|
||||||
|
<ion-button (click)="dismiss()">
|
||||||
|
<ion-icon slot="icon-only" name="close"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
|
</ion-buttons>
|
||||||
<ion-title>Config</ion-title>
|
<ion-title>Config</ion-title>
|
||||||
<ion-buttons slot="end" class="ion-padding-end">
|
<ion-buttons slot="end" class="ion-padding-end">
|
||||||
<ion-button fill="clear" [disabled]="loadingText" (click)="resetDefaults()">
|
<ion-button fill="clear" [disabled]="loadingText" (click)="resetDefaults()">
|
||||||
<ion-icon slot="start" name="refresh-outline"></ion-icon>
|
<ion-icon slot="start" name="refresh"></ion-icon>
|
||||||
Reset Defaults
|
Reset Defaults
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
@@ -19,17 +24,11 @@
|
|||||||
<ng-template #loaded>
|
<ng-template #loaded>
|
||||||
|
|
||||||
<ng-container *ngIf="patch.data['package-data'][pkgId] as pkg">
|
<ng-container *ngIf="patch.data['package-data'][pkgId] as pkg">
|
||||||
<ng-container *ngIf="pkg.manifest.config && !pkg.installed.status.configured && !edited">
|
<ion-item>
|
||||||
<ion-item class="notifier-item">
|
<ion-label>
|
||||||
<ion-label>
|
<ion-text color="success">To use the default config for {{ pkg.manifest.title }}, click "Save" below.</ion-text>
|
||||||
<h2 style="display: flex; align-items: center; margin-bottom: 3px;">
|
</ion-label>
|
||||||
<ion-icon size="small" style="margin-right: 5px" slot="start" color="dark" slot="start" name="alert-circle-outline"></ion-icon>
|
</ion-item>
|
||||||
<ion-text style="font-size: smaller;">Initial Config</ion-text>
|
|
||||||
</h2>
|
|
||||||
<p style="font-size: small">To use the default config for {{ pkg.manifest.title }}, click "Save" above.</p>
|
|
||||||
</ion-label>
|
|
||||||
</ion-item>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container *ngIf="rec && showRec">
|
<ng-container *ngIf="rec && showRec">
|
||||||
<ion-item class="rec-item">
|
<ion-item class="rec-item">
|
||||||
@@ -81,13 +80,8 @@
|
|||||||
|
|
||||||
<ion-footer>
|
<ion-footer>
|
||||||
<ion-toolbar *ngIf="patch.data['package-data'][pkgId] as pkg">
|
<ion-toolbar *ngIf="patch.data['package-data'][pkgId] as pkg">
|
||||||
<ion-buttons slot="start" class="ion-padding-start">
|
|
||||||
<ion-button fill="outline" (click)="dismiss()">
|
|
||||||
Cancel
|
|
||||||
</ion-button>
|
|
||||||
</ion-buttons>
|
|
||||||
<ion-buttons slot="end" class="ion-padding-end">
|
<ion-buttons slot="end" class="ion-padding-end">
|
||||||
<ion-button fill="outline" color="primary" [disabled]="loadingText" (click)="save(pkg)">
|
<ion-button fill="outline" [disabled]="loadingText" (click)="save(pkg)" class="enter-click">
|
||||||
Save
|
Save
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
|
|||||||
@@ -172,6 +172,7 @@ export class AppConfigPage {
|
|||||||
handler: () => {
|
handler: () => {
|
||||||
this.modalCtrl.dismiss()
|
this.modalCtrl.dismiss()
|
||||||
},
|
},
|
||||||
|
cssClass: 'enter-click',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,10 +1,15 @@
|
|||||||
<ion-header>
|
<ion-header>
|
||||||
<ion-toolbar>
|
<ion-toolbar>
|
||||||
|
<ion-buttons slot="start">
|
||||||
|
<ion-button (click)="dismiss()">
|
||||||
|
<ion-icon slot="icon-only" name="close"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
|
</ion-buttons>
|
||||||
<ion-title>
|
<ion-title>
|
||||||
{{ spec.name }}
|
{{ spec.name }}
|
||||||
</ion-title>
|
</ion-title>
|
||||||
<ion-buttons slot="end">
|
<ion-buttons slot="end">
|
||||||
<ion-button slot="end" fill="clear" color="primary" (click)="toggleSelectAll()">
|
<ion-button slot="end" fill="clear" (click)="toggleSelectAll()">
|
||||||
{{ selectAll ? 'All' : 'None' }}
|
{{ selectAll ? 'All' : 'None' }}
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
@@ -22,13 +27,8 @@
|
|||||||
|
|
||||||
<ion-footer>
|
<ion-footer>
|
||||||
<ion-toolbar>
|
<ion-toolbar>
|
||||||
<ion-buttons slot="start" class="ion-padding-start">
|
|
||||||
<ion-button fill="outline" (click)="dismiss()">
|
|
||||||
Cancel
|
|
||||||
</ion-button>
|
|
||||||
</ion-buttons>
|
|
||||||
<ion-buttons slot="end" class="ion-padding-end">
|
<ion-buttons slot="end" class="ion-padding-end">
|
||||||
<ion-button fill="outline" color="primary" (click)="save()">
|
<ion-button fill="outline" (click)="save()" class="enter-click">
|
||||||
Done
|
Done
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
<ion-header>
|
<ion-header>
|
||||||
<ion-toolbar>
|
<ion-toolbar>
|
||||||
|
<ion-buttons slot="start">
|
||||||
|
<ion-button (click)="dismiss()">
|
||||||
|
<ion-icon slot="icon-only" name="close"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
|
</ion-buttons>
|
||||||
<ion-title>{{ title }}</ion-title>
|
<ion-title>{{ title }}</ion-title>
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
@@ -15,13 +20,8 @@
|
|||||||
|
|
||||||
<ion-footer>
|
<ion-footer>
|
||||||
<ion-toolbar>
|
<ion-toolbar>
|
||||||
<ion-buttons slot="start" class="ion-padding-start">
|
|
||||||
<ion-button fill="clear" (click)="dismiss()">
|
|
||||||
Cancel
|
|
||||||
</ion-button>
|
|
||||||
</ion-buttons>
|
|
||||||
<ion-buttons slot="end" class="ion-padding-end">
|
<ion-buttons slot="end" class="ion-padding-end">
|
||||||
<ion-button *ngFor="let button of buttons" fill="clear" (click)="handleClick(button)">
|
<ion-button *ngFor="let button of buttons" fill="outline" (click)="handleClick(button)">
|
||||||
{{ button.text }}
|
{{ button.text }}
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
|
|||||||
@@ -8,5 +8,5 @@
|
|||||||
|
|
||||||
.main-content {
|
.main-content {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
color: var(--ion-color-medium);
|
color: var(--ion-color-dark);
|
||||||
}
|
}
|
||||||
@@ -80,6 +80,7 @@ export class AppActionsPage {
|
|||||||
handler: () => {
|
handler: () => {
|
||||||
this.executeAction(pkg.manifest.id, action.key)
|
this.executeAction(pkg.manifest.id, action.key)
|
||||||
},
|
},
|
||||||
|
cssClass: 'enter-click',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
@@ -104,7 +105,7 @@ export class AppActionsPage {
|
|||||||
header: 'Forbidden',
|
header: 'Forbidden',
|
||||||
message: error || `Action "${action.value.name}" can only be executed when service is ${statusesStr}`,
|
message: error || `Action "${action.value.name}" can only be executed when service is ${statusesStr}`,
|
||||||
buttons: ['OK'],
|
buttons: ['OK'],
|
||||||
cssClass: 'alert-error-message',
|
cssClass: 'alert-error-message enter-click',
|
||||||
})
|
})
|
||||||
await alert.present()
|
await alert.present()
|
||||||
}
|
}
|
||||||
@@ -159,7 +160,13 @@ export class AppActionsPage {
|
|||||||
const successAlert = await this.alertCtrl.create({
|
const successAlert = await this.alertCtrl.create({
|
||||||
header: 'Execution Complete',
|
header: 'Execution Complete',
|
||||||
message: res.message.split('\n').join('</br ></br />'),
|
message: res.message.split('\n').join('</br ></br />'),
|
||||||
buttons: ['OK'],
|
buttons: [
|
||||||
|
{
|
||||||
|
text: 'Ok',
|
||||||
|
role: 'cancel',
|
||||||
|
cssClass: 'enter-click',
|
||||||
|
},
|
||||||
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
setTimeout(() => successAlert.present(), 400)
|
setTimeout(() => successAlert.present(), 400)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<ion-title>Properties</ion-title>
|
<ion-title>Properties</ion-title>
|
||||||
<ion-buttons slot="end">
|
<ion-buttons slot="end">
|
||||||
<ion-button (click)="refresh()">
|
<ion-button (click)="refresh()">
|
||||||
<ion-icon slot="start" name="refresh-outline"></ion-icon>
|
<ion-icon slot="start" name="refresh"></ion-icon>
|
||||||
Refresh
|
Refresh
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
|
|||||||
@@ -130,7 +130,6 @@ export class AppShowPage {
|
|||||||
const alert = await this.alertCtrl.create({
|
const alert = await this.alertCtrl.create({
|
||||||
header: 'Not Accepting Donations',
|
header: 'Not Accepting Donations',
|
||||||
message: `The developers of ${this.pkg.manifest.title} have not provided a donation URL. Please contact them directly if you insist on giving them money.`,
|
message: `The developers of ${this.pkg.manifest.title} have not provided a donation URL. Please contact them directly if you insist on giving them money.`,
|
||||||
buttons: ['OK'],
|
|
||||||
})
|
})
|
||||||
await alert.present()
|
await alert.present()
|
||||||
}
|
}
|
||||||
@@ -215,6 +214,7 @@ export class AppShowPage {
|
|||||||
handler: () => {
|
handler: () => {
|
||||||
this.start()
|
this.start()
|
||||||
},
|
},
|
||||||
|
cssClass: 'enter-click',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -140,18 +140,6 @@
|
|||||||
<ion-row>
|
<ion-row>
|
||||||
<ion-col sizeSm="12" sizeMd="6">
|
<ion-col sizeSm="12" sizeMd="6">
|
||||||
<ion-item-group>
|
<ion-item-group>
|
||||||
<ion-item detail="false">
|
|
||||||
<ion-label>
|
|
||||||
<h2>Service ID</h2>
|
|
||||||
<p>{{ pkg.manifest.id }}</p>
|
|
||||||
</ion-label>
|
|
||||||
</ion-item>
|
|
||||||
<ion-item detail="false">
|
|
||||||
<ion-label>
|
|
||||||
<h2>Categories</h2>
|
|
||||||
<p>{{ pkg.categories.join(', ') }}</p>
|
|
||||||
</ion-label>
|
|
||||||
</ion-item>
|
|
||||||
<ion-item button detail="false" (click)="presentAlertVersions()">
|
<ion-item button detail="false" (click)="presentAlertVersions()">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>Other Versions</h2>
|
<h2>Other Versions</h2>
|
||||||
@@ -198,20 +186,6 @@
|
|||||||
</ion-label>
|
</ion-label>
|
||||||
<ion-icon slot="end" name="open-outline"></ion-icon>
|
<ion-icon slot="end" name="open-outline"></ion-icon>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item [href]="pkg.manifest['marketing-site']" target="_blank" detail="false">
|
|
||||||
<ion-label>
|
|
||||||
<h2>Marketing Site</h2>
|
|
||||||
<p>{{ pkg.manifest['marketing-site'] }}</p>
|
|
||||||
</ion-label>
|
|
||||||
<ion-icon slot="end" name="open-outline"></ion-icon>
|
|
||||||
</ion-item>
|
|
||||||
<ion-item *ngIf="pkg.manifest['donation-url'] as donationUrl" [href]="donationUrl" target="_blank" detail="false">
|
|
||||||
<ion-label>
|
|
||||||
<h2>Donation Site</h2>
|
|
||||||
<p>{{ donationUrl }}</p>
|
|
||||||
</ion-label>
|
|
||||||
<ion-icon slot="end" name="open-outline"></ion-icon>
|
|
||||||
</ion-item>
|
|
||||||
</ion-item-group>
|
</ion-item-group>
|
||||||
</ion-col>
|
</ion-col>
|
||||||
</ion-row>
|
</ion-row>
|
||||||
|
|||||||
@@ -81,7 +81,6 @@ export class MarketplaceShowPage {
|
|||||||
async presentAlertVersions () {
|
async presentAlertVersions () {
|
||||||
const alert = await this.alertCtrl.create({
|
const alert = await this.alertCtrl.create({
|
||||||
header: 'Versions',
|
header: 'Versions',
|
||||||
backdropDismiss: false,
|
|
||||||
inputs: this.marketplaceService.pkgs[this.pkgId].versions.sort((a, b) => -1 * this.emver.compare(a, b)).map(v => {
|
inputs: this.marketplaceService.pkgs[this.pkgId].versions.sort((a, b) => -1 * this.emver.compare(a, b)).map(v => {
|
||||||
return {
|
return {
|
||||||
name: v, // for CSS
|
name: v, // for CSS
|
||||||
@@ -100,6 +99,7 @@ export class MarketplaceShowPage {
|
|||||||
handler: (version: string) => {
|
handler: (version: string) => {
|
||||||
this.getPkg(version)
|
this.getPkg(version)
|
||||||
},
|
},
|
||||||
|
cssClass: 'enter-click',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ export class SessionsPage {
|
|||||||
|
|
||||||
async presentAlertKill (id: string) {
|
async presentAlertKill (id: string) {
|
||||||
const alert = await this.alertCtrl.create({
|
const alert = await this.alertCtrl.create({
|
||||||
backdropDismiss: false,
|
|
||||||
header: 'Caution',
|
header: 'Caution',
|
||||||
message: `Are you sure you want to kill this session?`,
|
message: `Are you sure you want to kill this session?`,
|
||||||
buttons: [
|
buttons: [
|
||||||
@@ -45,6 +44,7 @@ export class SessionsPage {
|
|||||||
handler: () => {
|
handler: () => {
|
||||||
this.kill(id)
|
this.kill(id)
|
||||||
},
|
},
|
||||||
|
cssClass: 'enter-click',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
<ion-item-divider>Saved Keys</ion-item-divider>
|
<ion-item-divider>Saved Keys</ion-item-divider>
|
||||||
|
|
||||||
<ion-item button detail="false" (click)="serverConfig.presentModalInput('ssh')">
|
<ion-item button detail="false" (click)="presentModalAdd()">
|
||||||
<ion-icon slot="start" name="add" size="large"></ion-icon>
|
<ion-icon slot="start" name="add" size="large"></ion-icon>
|
||||||
<ion-label>Add new key</ion-label>
|
<ion-label>Add new key</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import { Component } from '@angular/core'
|
import { Component } from '@angular/core'
|
||||||
import { ServerConfigService } from 'src/app/services/server-config.service'
|
import { AlertController, LoadingController, ModalController } from '@ionic/angular'
|
||||||
import { AlertController, LoadingController } from '@ionic/angular'
|
|
||||||
import { SSHService } from './ssh.service'
|
|
||||||
import { Subscription } from 'rxjs'
|
|
||||||
import { SSHKeys } from 'src/app/services/api/api.types'
|
import { SSHKeys } from 'src/app/services/api/api.types'
|
||||||
import { ErrorToastService } from 'src/app/services/error-toast.service'
|
import { ErrorToastService } from 'src/app/services/error-toast.service'
|
||||||
|
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||||
|
import { BackupConfirmationComponent } from 'src/app/modals/backup-confirmation/backup-confirmation.component'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ssh-keys',
|
selector: 'ssh-keys',
|
||||||
@@ -14,37 +13,66 @@ import { ErrorToastService } from 'src/app/services/error-toast.service'
|
|||||||
export class SSHKeysPage {
|
export class SSHKeysPage {
|
||||||
loading = true
|
loading = true
|
||||||
sshKeys: SSHKeys
|
sshKeys: SSHKeys
|
||||||
subs: Subscription[] = []
|
|
||||||
readonly docsUrl = 'https://docs.start9.com/user-manual/general/developer-options/ssh-setup.html'
|
readonly docsUrl = 'https://docs.start9.com/user-manual/general/developer-options/ssh-setup.html'
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private readonly loadingCtrl: LoadingController,
|
private readonly loadingCtrl: LoadingController,
|
||||||
|
private readonly modalCtrl: ModalController,
|
||||||
private readonly errToast: ErrorToastService,
|
private readonly errToast: ErrorToastService,
|
||||||
private readonly alertCtrl: AlertController,
|
private readonly alertCtrl: AlertController,
|
||||||
private readonly sshService: SSHService,
|
private readonly embassyApi: ApiService,
|
||||||
public readonly serverConfig: ServerConfigService,
|
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
async ngOnInit () {
|
async ngOnInit () {
|
||||||
this.subs = [
|
await this.getKeys()
|
||||||
this.sshService.watch$()
|
|
||||||
.subscribe(keys => {
|
|
||||||
this.sshKeys = keys
|
|
||||||
}),
|
|
||||||
]
|
|
||||||
|
|
||||||
await this.sshService.getKeys()
|
|
||||||
|
|
||||||
this.loading = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy () {
|
async getKeys (): Promise<void> {
|
||||||
this.subs.forEach(sub => sub.unsubscribe())
|
try {
|
||||||
|
this.sshKeys = await this.embassyApi.getSshKeys({ })
|
||||||
|
} catch (e) {
|
||||||
|
this.errToast.present(e)
|
||||||
|
} finally {
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async presentModalAdd () {
|
||||||
|
const { name, description } = sshSpec
|
||||||
|
|
||||||
|
const modal = await this.modalCtrl.create({
|
||||||
|
component: BackupConfirmationComponent,
|
||||||
|
componentProps: {
|
||||||
|
title: name,
|
||||||
|
message: description,
|
||||||
|
label: name,
|
||||||
|
submitFn: this.add,
|
||||||
|
},
|
||||||
|
cssClass: 'alertlike-modal',
|
||||||
|
})
|
||||||
|
await modal.present()
|
||||||
|
}
|
||||||
|
|
||||||
|
async add (pubkey: string): Promise<void> {
|
||||||
|
const loader = await this.loadingCtrl.create({
|
||||||
|
spinner: 'lines',
|
||||||
|
message: 'Saving...',
|
||||||
|
cssClass: 'loader',
|
||||||
|
})
|
||||||
|
await loader.present()
|
||||||
|
|
||||||
|
try {
|
||||||
|
const key = await this.embassyApi.addSshKey({ pubkey })
|
||||||
|
this.sshKeys = { ...this.sshKeys, ...key }
|
||||||
|
} catch (e) {
|
||||||
|
this.errToast.present(e)
|
||||||
|
} finally {
|
||||||
|
loader.dismiss()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async presentAlertDelete (hash: string) {
|
async presentAlertDelete (hash: string) {
|
||||||
const alert = await this.alertCtrl.create({
|
const alert = await this.alertCtrl.create({
|
||||||
backdropDismiss: false,
|
|
||||||
header: 'Caution',
|
header: 'Caution',
|
||||||
message: `Are you sure you want to delete this key?`,
|
message: `Are you sure you want to delete this key?`,
|
||||||
buttons: [
|
buttons: [
|
||||||
@@ -57,6 +85,7 @@ export class SSHKeysPage {
|
|||||||
handler: () => {
|
handler: () => {
|
||||||
this.delete(hash)
|
this.delete(hash)
|
||||||
},
|
},
|
||||||
|
cssClass: 'enter-click',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
@@ -72,7 +101,8 @@ export class SSHKeysPage {
|
|||||||
await loader.present()
|
await loader.present()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.sshService.delete(hash)
|
await this.embassyApi.deleteSshKey({ hash })
|
||||||
|
delete this.sshKeys[hash]
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.errToast.present(e)
|
this.errToast.present(e)
|
||||||
} finally {
|
} finally {
|
||||||
@@ -84,3 +114,15 @@ export class SSHKeysPage {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sshSpec = {
|
||||||
|
type: 'string',
|
||||||
|
name: 'SSH Key',
|
||||||
|
description: 'Enter the SSH public key of you would like to authorize for root access to your Embassy.',
|
||||||
|
nullable: false,
|
||||||
|
// @TODO regex for SSH Key
|
||||||
|
// pattern: '',
|
||||||
|
'pattern-description': 'Must be a valid SSH key',
|
||||||
|
masked: false,
|
||||||
|
copyable: false,
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,27 +17,5 @@ export class SSHService {
|
|||||||
return this.keys$.asObservable()
|
return this.keys$.asObservable()
|
||||||
}
|
}
|
||||||
|
|
||||||
async getKeys (): Promise<void> {
|
|
||||||
const keys = await this.embassyApi.getSshKeys({ })
|
|
||||||
this.keys$.next(keys)
|
|
||||||
}
|
|
||||||
|
|
||||||
async add (pubkey: string): Promise<void> {
|
|
||||||
const key = await this.embassyApi.addSshKey({ pubkey })
|
|
||||||
const keys = this.keys$.getValue()
|
|
||||||
this.keys$.next({ ...keys, ...key })
|
|
||||||
}
|
|
||||||
|
|
||||||
async delete (hash: string): Promise<void> {
|
|
||||||
await this.embassyApi.deleteSshKey({ hash })
|
|
||||||
const keys = this.keys$.getValue()
|
|
||||||
|
|
||||||
const filtered = Object.keys(keys)
|
|
||||||
.filter(h => h !== hash)
|
|
||||||
.reduce((res, h) => {
|
|
||||||
res[h] = keys[h]
|
|
||||||
return res
|
|
||||||
}, { })
|
|
||||||
this.keys$.next(filtered)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ export class ServerShowPage {
|
|||||||
|
|
||||||
async presentAlertRestart () {
|
async presentAlertRestart () {
|
||||||
const alert = await this.alertCtrl.create({
|
const alert = await this.alertCtrl.create({
|
||||||
backdropDismiss: false,
|
|
||||||
header: 'Confirm',
|
header: 'Confirm',
|
||||||
message: `Are you sure you want to restart your Embassy?`,
|
message: `Are you sure you want to restart your Embassy?`,
|
||||||
buttons: [
|
buttons: [
|
||||||
@@ -40,15 +39,15 @@ export class ServerShowPage {
|
|||||||
handler: () => {
|
handler: () => {
|
||||||
this.restart()
|
this.restart()
|
||||||
},
|
},
|
||||||
|
cssClass: 'enter-click',
|
||||||
},
|
},
|
||||||
]},
|
],
|
||||||
)
|
})
|
||||||
await alert.present()
|
await alert.present()
|
||||||
}
|
}
|
||||||
|
|
||||||
async presentAlertShutdown () {
|
async presentAlertShutdown () {
|
||||||
const alert = await this.alertCtrl.create({
|
const alert = await this.alertCtrl.create({
|
||||||
backdropDismiss: false,
|
|
||||||
header: 'Confirm',
|
header: 'Confirm',
|
||||||
message: `Are you sure you want to shut down your Embassy? To turn it back on, you will need to physically unplug the device and plug it back in.`,
|
message: `Are you sure you want to shut down your Embassy? To turn it back on, you will need to physically unplug the device and plug it back in.`,
|
||||||
buttons: [
|
buttons: [
|
||||||
@@ -61,6 +60,7 @@ export class ServerShowPage {
|
|||||||
handler: () => {
|
handler: () => {
|
||||||
this.shutdown()
|
this.shutdown()
|
||||||
},
|
},
|
||||||
|
cssClass: 'enter-click',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export class WifiPage {
|
|||||||
try {
|
try {
|
||||||
await this.getWifi()
|
await this.getWifi()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.errToast.present(e.message)
|
this.errToast.present(e)
|
||||||
} finally {
|
} finally {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
}
|
}
|
||||||
@@ -72,7 +72,7 @@ export class WifiPage {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
cssClass: 'wide-alert',
|
cssClass: 'wide-alert enter-click',
|
||||||
})
|
})
|
||||||
await alert.present()
|
await alert.present()
|
||||||
}
|
}
|
||||||
@@ -206,7 +206,13 @@ export class WifiPage {
|
|||||||
const alert = await this.alertCtrl.create({
|
const alert = await this.alertCtrl.create({
|
||||||
header: `Connected to "${ssid}"`,
|
header: `Connected to "${ssid}"`,
|
||||||
message: 'Note. It may take several minutes to an hour for your Embassy to reconnect over Tor.',
|
message: 'Note. It may take several minutes to an hour for your Embassy to reconnect over Tor.',
|
||||||
buttons: ['OK'],
|
buttons: [
|
||||||
|
{
|
||||||
|
text: 'Ok',
|
||||||
|
role: 'cancel',
|
||||||
|
cssClass: 'enter-click',
|
||||||
|
},
|
||||||
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
await alert.present()
|
await alert.present()
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { PatchConnection, PatchDbService } from './patch-db/patch-db.service'
|
|||||||
import { HttpService, Method } from './http.service'
|
import { HttpService, Method } from './http.service'
|
||||||
import { distinctUntilChanged } from 'rxjs/operators'
|
import { distinctUntilChanged } from 'rxjs/operators'
|
||||||
import { ConfigService } from './config.service'
|
import { ConfigService } from './config.service'
|
||||||
import { pauseFor } from '../util/misc.util'
|
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { AlertInput, AlertButton } from '@ionic/core'
|
import { AlertInput, AlertButton } from '@ionic/core'
|
||||||
import { ApiService } from './api/embassy-api.service'
|
import { ApiService } from './api/embassy-api.service'
|
||||||
import { ConfigSpec, ValueSpecString } from '../pkg-config/config-types'
|
import { ConfigSpec } from '../pkg-config/config-types'
|
||||||
import { SSHService } from '../pages/server-routes/security-routes/ssh-keys/ssh.service'
|
|
||||||
import { AlertController, LoadingController } from '@ionic/angular'
|
import { AlertController, LoadingController } from '@ionic/angular'
|
||||||
import { ErrorToastService } from './error-toast.service'
|
import { ErrorToastService } from './error-toast.service'
|
||||||
import { ModalController } from '@ionic/angular'
|
|
||||||
import { BackupConfirmationComponent } from '../modals/backup-confirmation/backup-confirmation.component'
|
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
@@ -14,12 +11,10 @@ import { BackupConfirmationComponent } from '../modals/backup-confirmation/backu
|
|||||||
export class ServerConfigService {
|
export class ServerConfigService {
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private readonly modalCtrl: ModalController,
|
|
||||||
private readonly loadingCtrl: LoadingController,
|
private readonly loadingCtrl: LoadingController,
|
||||||
private readonly errToast: ErrorToastService,
|
private readonly errToast: ErrorToastService,
|
||||||
private readonly alertCtrl: AlertController,
|
private readonly alertCtrl: AlertController,
|
||||||
private readonly embassyApi: ApiService,
|
private readonly embassyApi: ApiService,
|
||||||
private readonly sshService: SSHService,
|
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
async presentAlert (key: string, current?: any): Promise<void> {
|
async presentAlert (key: string, current?: any): Promise<void> {
|
||||||
@@ -49,6 +44,7 @@ export class ServerConfigService {
|
|||||||
loader.dismiss()
|
loader.dismiss()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
cssClass: 'enter-click',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -84,24 +80,6 @@ export class ServerConfigService {
|
|||||||
await alert.present()
|
await alert.present()
|
||||||
}
|
}
|
||||||
|
|
||||||
async presentModalInput (key: string, current?: string) {
|
|
||||||
const { name, description, masked } = serverConfig[key] as ValueSpecString
|
|
||||||
|
|
||||||
const modal = await this.modalCtrl.create({
|
|
||||||
component: BackupConfirmationComponent,
|
|
||||||
componentProps: {
|
|
||||||
title: name,
|
|
||||||
message: description,
|
|
||||||
label: name,
|
|
||||||
useMask: masked,
|
|
||||||
value: current,
|
|
||||||
submitFn: this.saveFns[key],
|
|
||||||
},
|
|
||||||
cssClass: 'alertlike-modal',
|
|
||||||
})
|
|
||||||
await modal.present()
|
|
||||||
}
|
|
||||||
|
|
||||||
// async presentModalForm (key: string) {
|
// async presentModalForm (key: string) {
|
||||||
// const modal = await this.modalCtrl.create({
|
// const modal = await this.modalCtrl.create({
|
||||||
// component: AppActionInputPage,
|
// component: AppActionInputPage,
|
||||||
@@ -123,9 +101,6 @@ export class ServerConfigService {
|
|||||||
'auto-check-updates': async (enabled: boolean) => {
|
'auto-check-updates': async (enabled: boolean) => {
|
||||||
return this.embassyApi.setDbValue({ pointer: '/auto-check-updates', value: enabled })
|
return this.embassyApi.setDbValue({ pointer: '/auto-check-updates', value: enabled })
|
||||||
},
|
},
|
||||||
ssh: async (pubkey: string) => {
|
|
||||||
return this.sshService.add(pubkey)
|
|
||||||
},
|
|
||||||
// 'eos-marketplace': async () => {
|
// 'eos-marketplace': async () => {
|
||||||
// return this.embassyApi.setEosMarketplace()
|
// return this.embassyApi.setEosMarketplace()
|
||||||
// },
|
// },
|
||||||
@@ -148,17 +123,6 @@ export const serverConfig: ConfigSpec = {
|
|||||||
description: 'On launch, EmbassyOS will automatically check for updates of itself and your installed services. Updating still requires user approval and action. No updates will ever be performed automatically.',
|
description: 'On launch, EmbassyOS will automatically check for updates of itself and your installed services. Updating still requires user approval and action. No updates will ever be performed automatically.',
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
ssh: {
|
|
||||||
type: 'string',
|
|
||||||
name: 'SSH Key',
|
|
||||||
description: 'Enter the SSH public key of you would like to authorize for root access to your Embassy.',
|
|
||||||
nullable: false,
|
|
||||||
// @TODO regex for SSH Key
|
|
||||||
// pattern: '',
|
|
||||||
'pattern-description': 'Must be a valid SSH key',
|
|
||||||
masked: false,
|
|
||||||
copyable: false,
|
|
||||||
},
|
|
||||||
// 'eos-marketplace': {
|
// 'eos-marketplace': {
|
||||||
// type: 'boolean',
|
// type: 'boolean',
|
||||||
// name: 'Tor Only Marketplace',
|
// name: 'Tor Only Marketplace',
|
||||||
|
|||||||
@@ -155,7 +155,6 @@ export class StartupAlertsService {
|
|||||||
private async displayAppsCheck (): Promise<boolean> {
|
private async displayAppsCheck (): Promise<boolean> {
|
||||||
return new Promise(async resolve => {
|
return new Promise(async resolve => {
|
||||||
const alert = await this.alertCtrl.create({
|
const alert = await this.alertCtrl.create({
|
||||||
backdropDismiss: true,
|
|
||||||
header: 'Updates Available!',
|
header: 'Updates Available!',
|
||||||
message: new IonicSafeString(
|
message: new IonicSafeString(
|
||||||
`<div style="display: flex; flex-direction: column; justify-content: space-around; min-height: 100px">
|
`<div style="display: flex; flex-direction: column; justify-content: space-around; min-height: 100px">
|
||||||
@@ -173,8 +172,9 @@ export class StartupAlertsService {
|
|||||||
{
|
{
|
||||||
text: 'View in Marketplace',
|
text: 'View in Marketplace',
|
||||||
handler: () => {
|
handler: () => {
|
||||||
return this.navCtrl.navigateForward('/marketplace').then(() => resolve(false))
|
this.navCtrl.navigateForward('/marketplace').then(() => resolve(false))
|
||||||
},
|
},
|
||||||
|
cssClass: 'enter-click',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
@@ -186,7 +186,6 @@ export class StartupAlertsService {
|
|||||||
private async presentAlertNewOS (versionLatest: string): Promise<{ cancel?: true, update?: true }> {
|
private async presentAlertNewOS (versionLatest: string): Promise<{ cancel?: true, update?: true }> {
|
||||||
return new Promise(async resolve => {
|
return new Promise(async resolve => {
|
||||||
const alert = await this.alertCtrl.create({
|
const alert = await this.alertCtrl.create({
|
||||||
backdropDismiss: true,
|
|
||||||
header: 'New EmbassyOS Version!',
|
header: 'New EmbassyOS Version!',
|
||||||
message: new IonicSafeString(
|
message: new IonicSafeString(
|
||||||
`<div style="display: flex; flex-direction: column; justify-content: space-around; min-height: 100px">
|
`<div style="display: flex; flex-direction: column; justify-content: space-around; min-height: 100px">
|
||||||
@@ -204,6 +203,7 @@ export class StartupAlertsService {
|
|||||||
{
|
{
|
||||||
text: 'Update',
|
text: 'Update',
|
||||||
handler: () => resolve({ update: true }),
|
handler: () => resolve({ update: true }),
|
||||||
|
cssClass: 'enter-click',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user