mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 20:14:49 +00:00
react to enter key for alerts and modals. Styling and logic
This commit is contained in:
committed by
Aiden McClelland
parent
5c2f724e0c
commit
37a6df0815
@@ -80,6 +80,7 @@ export class AppActionsPage {
|
||||
handler: () => {
|
||||
this.executeAction(pkg.manifest.id, action.key)
|
||||
},
|
||||
cssClass: 'enter-click',
|
||||
},
|
||||
],
|
||||
})
|
||||
@@ -104,7 +105,7 @@ export class AppActionsPage {
|
||||
header: 'Forbidden',
|
||||
message: error || `Action "${action.value.name}" can only be executed when service is ${statusesStr}`,
|
||||
buttons: ['OK'],
|
||||
cssClass: 'alert-error-message',
|
||||
cssClass: 'alert-error-message enter-click',
|
||||
})
|
||||
await alert.present()
|
||||
}
|
||||
@@ -159,7 +160,13 @@ export class AppActionsPage {
|
||||
const successAlert = await this.alertCtrl.create({
|
||||
header: 'Execution Complete',
|
||||
message: res.message.split('\n').join('</br ></br />'),
|
||||
buttons: ['OK'],
|
||||
buttons: [
|
||||
{
|
||||
text: 'Ok',
|
||||
role: 'cancel',
|
||||
cssClass: 'enter-click',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
setTimeout(() => successAlert.present(), 400)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<ion-title>Properties</ion-title>
|
||||
<ion-buttons slot="end">
|
||||
<ion-button (click)="refresh()">
|
||||
<ion-icon slot="start" name="refresh-outline"></ion-icon>
|
||||
<ion-icon slot="start" name="refresh"></ion-icon>
|
||||
Refresh
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
|
||||
@@ -130,7 +130,6 @@ export class AppShowPage {
|
||||
const alert = await this.alertCtrl.create({
|
||||
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.`,
|
||||
buttons: ['OK'],
|
||||
})
|
||||
await alert.present()
|
||||
}
|
||||
@@ -215,6 +214,7 @@ export class AppShowPage {
|
||||
handler: () => {
|
||||
this.start()
|
||||
},
|
||||
cssClass: 'enter-click',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
@@ -140,18 +140,6 @@
|
||||
<ion-row>
|
||||
<ion-col sizeSm="12" sizeMd="6">
|
||||
<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-label>
|
||||
<h2>Other Versions</h2>
|
||||
@@ -198,20 +186,6 @@
|
||||
</ion-label>
|
||||
<ion-icon slot="end" name="open-outline"></ion-icon>
|
||||
</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-col>
|
||||
</ion-row>
|
||||
|
||||
@@ -81,7 +81,6 @@ export class MarketplaceShowPage {
|
||||
async presentAlertVersions () {
|
||||
const alert = await this.alertCtrl.create({
|
||||
header: 'Versions',
|
||||
backdropDismiss: false,
|
||||
inputs: this.marketplaceService.pkgs[this.pkgId].versions.sort((a, b) => -1 * this.emver.compare(a, b)).map(v => {
|
||||
return {
|
||||
name: v, // for CSS
|
||||
@@ -100,6 +99,7 @@ export class MarketplaceShowPage {
|
||||
handler: (version: string) => {
|
||||
this.getPkg(version)
|
||||
},
|
||||
cssClass: 'enter-click',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
@@ -32,7 +32,6 @@ export class SessionsPage {
|
||||
|
||||
async presentAlertKill (id: string) {
|
||||
const alert = await this.alertCtrl.create({
|
||||
backdropDismiss: false,
|
||||
header: 'Caution',
|
||||
message: `Are you sure you want to kill this session?`,
|
||||
buttons: [
|
||||
@@ -45,6 +44,7 @@ export class SessionsPage {
|
||||
handler: () => {
|
||||
this.kill(id)
|
||||
},
|
||||
cssClass: 'enter-click',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
<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-label>Add new key</ion-label>
|
||||
</ion-item>
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { Component } from '@angular/core'
|
||||
import { ServerConfigService } from 'src/app/services/server-config.service'
|
||||
import { AlertController, LoadingController } from '@ionic/angular'
|
||||
import { SSHService } from './ssh.service'
|
||||
import { Subscription } from 'rxjs'
|
||||
import { AlertController, LoadingController, ModalController } from '@ionic/angular'
|
||||
import { SSHKeys } from 'src/app/services/api/api.types'
|
||||
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({
|
||||
selector: 'ssh-keys',
|
||||
@@ -14,37 +13,66 @@ import { ErrorToastService } from 'src/app/services/error-toast.service'
|
||||
export class SSHKeysPage {
|
||||
loading = true
|
||||
sshKeys: SSHKeys
|
||||
subs: Subscription[] = []
|
||||
readonly docsUrl = 'https://docs.start9.com/user-manual/general/developer-options/ssh-setup.html'
|
||||
|
||||
constructor (
|
||||
private readonly loadingCtrl: LoadingController,
|
||||
private readonly modalCtrl: ModalController,
|
||||
private readonly errToast: ErrorToastService,
|
||||
private readonly alertCtrl: AlertController,
|
||||
private readonly sshService: SSHService,
|
||||
public readonly serverConfig: ServerConfigService,
|
||||
private readonly embassyApi: ApiService,
|
||||
) { }
|
||||
|
||||
async ngOnInit () {
|
||||
this.subs = [
|
||||
this.sshService.watch$()
|
||||
.subscribe(keys => {
|
||||
this.sshKeys = keys
|
||||
}),
|
||||
]
|
||||
|
||||
await this.sshService.getKeys()
|
||||
|
||||
this.loading = false
|
||||
await this.getKeys()
|
||||
}
|
||||
|
||||
ngOnDestroy () {
|
||||
this.subs.forEach(sub => sub.unsubscribe())
|
||||
async getKeys (): Promise<void> {
|
||||
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) {
|
||||
const alert = await this.alertCtrl.create({
|
||||
backdropDismiss: false,
|
||||
header: 'Caution',
|
||||
message: `Are you sure you want to delete this key?`,
|
||||
buttons: [
|
||||
@@ -57,6 +85,7 @@ export class SSHKeysPage {
|
||||
handler: () => {
|
||||
this.delete(hash)
|
||||
},
|
||||
cssClass: 'enter-click',
|
||||
},
|
||||
],
|
||||
})
|
||||
@@ -72,7 +101,8 @@ export class SSHKeysPage {
|
||||
await loader.present()
|
||||
|
||||
try {
|
||||
await this.sshService.delete(hash)
|
||||
await this.embassyApi.deleteSshKey({ hash })
|
||||
delete this.sshKeys[hash]
|
||||
} catch (e) {
|
||||
this.errToast.present(e)
|
||||
} finally {
|
||||
@@ -84,3 +114,15 @@ export class SSHKeysPage {
|
||||
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()
|
||||
}
|
||||
|
||||
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 () {
|
||||
const alert = await this.alertCtrl.create({
|
||||
backdropDismiss: false,
|
||||
header: 'Confirm',
|
||||
message: `Are you sure you want to restart your Embassy?`,
|
||||
buttons: [
|
||||
@@ -40,15 +39,15 @@ export class ServerShowPage {
|
||||
handler: () => {
|
||||
this.restart()
|
||||
},
|
||||
cssClass: 'enter-click',
|
||||
},
|
||||
]},
|
||||
)
|
||||
],
|
||||
})
|
||||
await alert.present()
|
||||
}
|
||||
|
||||
async presentAlertShutdown () {
|
||||
const alert = await this.alertCtrl.create({
|
||||
backdropDismiss: false,
|
||||
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.`,
|
||||
buttons: [
|
||||
@@ -61,6 +60,7 @@ export class ServerShowPage {
|
||||
handler: () => {
|
||||
this.shutdown()
|
||||
},
|
||||
cssClass: 'enter-click',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
@@ -33,7 +33,7 @@ export class WifiPage {
|
||||
try {
|
||||
await this.getWifi()
|
||||
} catch (e) {
|
||||
this.errToast.present(e.message)
|
||||
this.errToast.present(e)
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
@@ -72,7 +72,7 @@ export class WifiPage {
|
||||
},
|
||||
},
|
||||
],
|
||||
cssClass: 'wide-alert',
|
||||
cssClass: 'wide-alert enter-click',
|
||||
})
|
||||
await alert.present()
|
||||
}
|
||||
@@ -206,7 +206,13 @@ export class WifiPage {
|
||||
const alert = await this.alertCtrl.create({
|
||||
header: `Connected to "${ssid}"`,
|
||||
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()
|
||||
|
||||
Reference in New Issue
Block a user