mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 12:11:56 +00:00
Fix/UI misc (#1606)
* stop expansion when description icon clicked * add test for ensuring string sanitization * rename log out to terminate in sessions component and remove sanitization bypass as unneeded * remove unecessary instances of safe string
This commit is contained in:
@@ -1,9 +1,5 @@
|
|||||||
import { Component } from '@angular/core'
|
import { Component } from '@angular/core'
|
||||||
import {
|
import { AlertController, LoadingController } from '@ionic/angular'
|
||||||
AlertController,
|
|
||||||
IonicSafeString,
|
|
||||||
LoadingController,
|
|
||||||
} from '@ionic/angular'
|
|
||||||
import { ApiService } from 'src/app/services/api/api.service'
|
import { ApiService } from 'src/app/services/api/api.service'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ export class RecoverPage {
|
|||||||
private readonly loadingCtrl: LoadingController,
|
private readonly loadingCtrl: LoadingController,
|
||||||
private readonly errorToastService: ErrorToastService,
|
private readonly errorToastService: ErrorToastService,
|
||||||
public readonly stateService: StateService,
|
public readonly stateService: StateService,
|
||||||
) { }
|
) {}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
await this.getDrives()
|
await this.getDrives()
|
||||||
@@ -99,8 +99,12 @@ export class RecoverPage {
|
|||||||
const alert = await this.alertCtrl.create({
|
const alert = await this.alertCtrl.create({
|
||||||
header: 'Embassy Data Drive Detected',
|
header: 'Embassy Data Drive Detected',
|
||||||
message: new IonicSafeString(
|
message: new IonicSafeString(
|
||||||
`${importableDrive.vendor || 'Unknown Vendor'} - ${importableDrive.model || 'Unknown Model'
|
`<strong>${importableDrive.vendor || 'Unknown Vendor'} - ${
|
||||||
} contains Embassy data. To use this drive and its data <i>as-is</i>, click "Use Drive". This will complete the setup process.<br /><br /><b>Important</b>. If you are trying to restore from backup or update from 0.2.x, DO NOT click "Use Drive". Instead, click "Cancel" and follow instructions.`,
|
importableDrive.model || 'Unknown Model'
|
||||||
|
}</strong> contains Embassy data.
|
||||||
|
<p>To use this drive and its data, select <strong>"USE DRIVE"</strong>. This will complete the setup process.
|
||||||
|
<p><strong style="color:red">Important!</strong><br><br>
|
||||||
|
If you are trying to restore from a backup or update from 0.2.x, <strong>DO NOT</strong> select "USE DRIVE". Instead, select <strong>"CANCEL"</strong> and follow instructions.`,
|
||||||
),
|
),
|
||||||
buttons: [
|
buttons: [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { IonicSafeString, ToastController, ToastOptions } from '@ionic/angular'
|
import { ToastController, ToastOptions } from '@ionic/angular'
|
||||||
import { ToastButton } from '@ionic/core'
|
import { ToastButton } from '@ionic/core'
|
||||||
import { EMPTY, from, Observable } from 'rxjs'
|
import { EMPTY, from, Observable } from 'rxjs'
|
||||||
import {
|
import {
|
||||||
@@ -112,6 +112,6 @@ function getButtons(link?: string): ToastButton[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface OfflineMessage {
|
interface OfflineMessage {
|
||||||
readonly message: string | IonicSafeString
|
readonly message: string
|
||||||
readonly link?: string
|
readonly link?: string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
*ngIf="data.spec.description"
|
*ngIf="data.spec.description"
|
||||||
class="slot-start"
|
class="slot-start"
|
||||||
fill="clear"
|
fill="clear"
|
||||||
(click)="presentAlertDescription()"
|
(click)="presentAlertDescription($event)"
|
||||||
>
|
>
|
||||||
<ion-icon name="help-circle-outline" slot="icon-only" size="small"></ion-icon>
|
<ion-icon name="help-circle-outline" slot="icon-only" size="small"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
size="small"
|
size="small"
|
||||||
(click)="
|
(click)="
|
||||||
presentUnionTagDescription(
|
presentUnionTagDescription(
|
||||||
|
$event,
|
||||||
unionSpec.tag.name,
|
unionSpec.tag.name,
|
||||||
unionSpec.tag.description
|
unionSpec.tag.description
|
||||||
)
|
)
|
||||||
@@ -121,7 +122,7 @@
|
|||||||
<ion-button
|
<ion-button
|
||||||
*ngIf="spec.description"
|
*ngIf="spec.description"
|
||||||
fill="clear"
|
fill="clear"
|
||||||
(click)="presentAlertDescription(spec)"
|
(click)="presentAlertDescription($event, spec)"
|
||||||
style="--padding-start: 0"
|
style="--padding-start: 0"
|
||||||
>
|
>
|
||||||
<ion-icon
|
<ion-icon
|
||||||
|
|||||||
@@ -300,7 +300,8 @@ export class FormObjectComponent {
|
|||||||
await alert.present()
|
await alert.present()
|
||||||
}
|
}
|
||||||
|
|
||||||
async presentAlertDescription(spec: ValueSpec) {
|
async presentAlertDescription(event: Event, spec: ValueSpec) {
|
||||||
|
event.stopPropagation()
|
||||||
const { name, description } = spec
|
const { name, description } = spec
|
||||||
|
|
||||||
const alert = await this.alertCtrl.create({
|
const alert = await this.alertCtrl.create({
|
||||||
@@ -353,7 +354,12 @@ export class FormObjectComponent {
|
|||||||
return `${key}-${index}-${this.objectId}`
|
return `${key}-${index}-${this.objectId}`
|
||||||
}
|
}
|
||||||
|
|
||||||
async presentUnionTagDescription(name: string, description: string) {
|
async presentUnionTagDescription(
|
||||||
|
event: Event,
|
||||||
|
name: string,
|
||||||
|
description: string,
|
||||||
|
) {
|
||||||
|
event.stopPropagation()
|
||||||
const alert = await this.alertCtrl.create({
|
const alert = await this.alertCtrl.create({
|
||||||
header: name,
|
header: name,
|
||||||
message: description,
|
message: description,
|
||||||
@@ -384,7 +390,8 @@ export class FormLabelComponent {
|
|||||||
|
|
||||||
constructor(private readonly alertCtrl: AlertController) {}
|
constructor(private readonly alertCtrl: AlertController) {}
|
||||||
|
|
||||||
async presentAlertDescription() {
|
async presentAlertDescription(event: Event) {
|
||||||
|
event.stopPropagation()
|
||||||
const { name, description } = this.data.spec
|
const { name, description } = this.data.spec
|
||||||
|
|
||||||
const alert = await this.alertCtrl.create({
|
const alert = await this.alertCtrl.create({
|
||||||
|
|||||||
@@ -200,14 +200,14 @@ export class AppConfigPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async presentAlertBreakages(breakages: Breakages): Promise<boolean> {
|
private async presentAlertBreakages(breakages: Breakages): Promise<boolean> {
|
||||||
let message: string | IonicSafeString =
|
let message: string =
|
||||||
'As a result of this change, the following services will no longer work properly and may crash:<ul>'
|
'As a result of this change, the following services will no longer work properly and may crash:<ul>'
|
||||||
const localPkgs = this.patch.getData()['package-data']
|
const localPkgs = this.patch.getData()['package-data']
|
||||||
const bullets = Object.keys(breakages).map(id => {
|
const bullets = Object.keys(breakages).map(id => {
|
||||||
const title = localPkgs[id].manifest.title
|
const title = localPkgs[id].manifest.title
|
||||||
return `<li><b>${title}</b></li>`
|
return `<li><b>${title}</b></li>`
|
||||||
})
|
})
|
||||||
message = new IonicSafeString(`${message}${bullets}</ul>`)
|
message = `${message}${bullets}</ul>`
|
||||||
|
|
||||||
return new Promise(async resolve => {
|
return new Promise(async resolve => {
|
||||||
const alert = await this.alertCtrl.create({
|
const alert = await this.alertCtrl.create({
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Component } from '@angular/core'
|
import { Component } from '@angular/core'
|
||||||
import { ModalController, IonicSafeString } from '@ionic/angular'
|
import { ModalController } from '@ionic/angular'
|
||||||
import { map, take } from 'rxjs/operators'
|
import { map, take } from 'rxjs/operators'
|
||||||
import { PackageState } from 'src/app/services/patch-db/data-model'
|
import { PackageState } from 'src/app/services/patch-db/data-model'
|
||||||
import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
|
import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
|
||||||
@@ -11,7 +11,6 @@ import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
|
|||||||
})
|
})
|
||||||
export class BackupSelectPage {
|
export class BackupSelectPage {
|
||||||
hasSelection = false
|
hasSelection = false
|
||||||
error: string | IonicSafeString = ''
|
|
||||||
selectAll = true
|
selectAll = true
|
||||||
pkgs: {
|
pkgs: {
|
||||||
id: string
|
id: string
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { ApiService } from 'src/app/services/api/embassy-api.service'
|
|||||||
import {
|
import {
|
||||||
AlertController,
|
AlertController,
|
||||||
IonContent,
|
IonContent,
|
||||||
IonicSafeString,
|
|
||||||
LoadingController,
|
LoadingController,
|
||||||
ModalController,
|
ModalController,
|
||||||
NavController,
|
NavController,
|
||||||
|
|||||||
@@ -4,11 +4,7 @@ import {
|
|||||||
Inject,
|
Inject,
|
||||||
Input,
|
Input,
|
||||||
} from '@angular/core'
|
} from '@angular/core'
|
||||||
import {
|
import { AlertController, LoadingController } from '@ionic/angular'
|
||||||
AlertController,
|
|
||||||
IonicSafeString,
|
|
||||||
LoadingController,
|
|
||||||
} from '@ionic/angular'
|
|
||||||
import {
|
import {
|
||||||
AbstractMarketplaceService,
|
AbstractMarketplaceService,
|
||||||
MarketplacePkg,
|
MarketplacePkg,
|
||||||
@@ -153,14 +149,14 @@ export class MarketplaceShowControlsComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async presentAlertBreakages(breakages: Breakages): Promise<boolean> {
|
private async presentAlertBreakages(breakages: Breakages): Promise<boolean> {
|
||||||
let message: string | IonicSafeString =
|
let message: string =
|
||||||
'As a result of this update, the following services will no longer work properly and may crash:<ul>'
|
'As a result of this update, the following services will no longer work properly and may crash:<ul>'
|
||||||
const localPkgs = this.patch.getData()['package-data']
|
const localPkgs = this.patch.getData()['package-data']
|
||||||
const bullets = Object.keys(breakages).map(id => {
|
const bullets = Object.keys(breakages).map(id => {
|
||||||
const title = localPkgs[id].manifest.title
|
const title = localPkgs[id].manifest.title
|
||||||
return `<li><b>${title}</b></li>`
|
return `<li><b>${title}</b></li>`
|
||||||
})
|
})
|
||||||
message = new IonicSafeString(`${message}${bullets}</ul>`)
|
message = `${message}${bullets}</ul>`
|
||||||
|
|
||||||
return new Promise(async resolve => {
|
return new Promise(async resolve => {
|
||||||
const alert = await this.alertCtrl.create({
|
const alert = await this.alertCtrl.create({
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import {
|
|||||||
AlertController,
|
AlertController,
|
||||||
LoadingController,
|
LoadingController,
|
||||||
NavController,
|
NavController,
|
||||||
IonicSafeString,
|
|
||||||
ModalController,
|
ModalController,
|
||||||
} from '@ionic/angular'
|
} from '@ionic/angular'
|
||||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||||
@@ -121,9 +120,7 @@ export class ServerShowPage {
|
|||||||
const minutes = Object.keys(this.patch.getData()['package-data']).length * 2
|
const minutes = Object.keys(this.patch.getData()['package-data']).length * 2
|
||||||
const alert = await this.alertCtrl.create({
|
const alert = await this.alertCtrl.create({
|
||||||
header: 'Warning',
|
header: 'Warning',
|
||||||
message: new IonicSafeString(
|
message: `This action will tear down all service containers and rebuild them from scratch. No data will be deleted. This action is useful if your system gets into a bad state, and it should only be performed if you are experiencing general performance or reliability issues. It may take up to ${minutes} minutes to complete. During this time, you will lose all connectivity to your Embassy.`,
|
||||||
`This action will tear down all service containers and rebuild them from scratch. No data will be deleted. This action is useful if your system gets into a bad state, and it should only be performed if you are experiencing general performance or reliability issues. It may take up to ${minutes} minutes to complete. During this time, you will lose all connectivity to your Embassy.`,
|
|
||||||
),
|
|
||||||
buttons: [
|
buttons: [
|
||||||
{
|
{
|
||||||
text: 'Cancel',
|
text: 'Cancel',
|
||||||
@@ -145,9 +142,7 @@ export class ServerShowPage {
|
|||||||
async presentAlertRepairDisk() {
|
async presentAlertRepairDisk() {
|
||||||
const alert = await this.alertCtrl.create({
|
const alert = await this.alertCtrl.create({
|
||||||
header: 'Warning',
|
header: 'Warning',
|
||||||
message: new IonicSafeString(
|
message: `<p>This action will attempt to preform a disk repair operation and system reboot. No data will be deleted. This action should only be executed if directed by a Start9 support specialist. We recommend backing up your device before preforming this action.</p><p>If anything happens to the device during the reboot (between the bep and chime), such as loosing power, a power surge, unplugging the drive, or unplugging the Embassy, the filesystem <i>will</i> be in an unrecoverable state. Please proceed with caution.</p>`,
|
||||||
`<p>This action will attempt to preform a disk repair operation and system reboot. No data will be deleted. This action should only be executed if directed by a Start9 support specialist. We recommend backing up your device before preforming this action.</p><p>If anything happens to the device during the reboot (between the bep and chime), such as loosing power, a power surge, unplugging the drive, or unplugging the Embassy, the filesystem <i>will</i> be in an unrecoverable state. Please proceed with caution.</p>`,
|
|
||||||
),
|
|
||||||
buttons: [
|
buttons: [
|
||||||
{
|
{
|
||||||
text: 'Cancel',
|
text: 'Cancel',
|
||||||
|
|||||||
@@ -67,7 +67,7 @@
|
|||||||
strong
|
strong
|
||||||
(click)="presentAlertKillAll()"
|
(click)="presentAlertKillAll()"
|
||||||
>
|
>
|
||||||
Log out all
|
Terminate all
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-item-divider>
|
</ion-item-divider>
|
||||||
<div *ngFor="let session of otherSessions">
|
<div *ngFor="let session of otherSessions">
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
import { Component } from '@angular/core'
|
import { Component } from '@angular/core'
|
||||||
import {
|
import { AlertController, LoadingController } from '@ionic/angular'
|
||||||
AlertController,
|
|
||||||
IonicSafeString,
|
|
||||||
LoadingController,
|
|
||||||
} from '@ionic/angular'
|
|
||||||
import { ErrorToastService } from '@start9labs/shared'
|
import { ErrorToastService } from '@start9labs/shared'
|
||||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||||
import { PlatformType, Session } from 'src/app/services/api/api.types'
|
import { PlatformType, Session } from 'src/app/services/api/api.types'
|
||||||
@@ -53,16 +49,14 @@ export class SessionsPage {
|
|||||||
async presentAlertKillAll() {
|
async presentAlertKillAll() {
|
||||||
const alert = await this.alertCtrl.create({
|
const alert = await this.alertCtrl.create({
|
||||||
header: 'Confirm',
|
header: 'Confirm',
|
||||||
message: new IonicSafeString(
|
message: `Terminate <b>all</b> other web sessions?<br /><br />Note: you will <b>not</b> be logged out of your current session on this device.`,
|
||||||
`Log out <b>all</b> other web sessions?<br /><br />Note: you will <b>not</b> be logged out of your current session on this device.`,
|
|
||||||
),
|
|
||||||
buttons: [
|
buttons: [
|
||||||
{
|
{
|
||||||
text: 'Cancel',
|
text: 'Cancel',
|
||||||
role: 'cancel',
|
role: 'cancel',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: 'Log out all',
|
text: 'Terminate all',
|
||||||
handler: () => {
|
handler: () => {
|
||||||
this.kill(this.otherSessions.map(s => s.id))
|
this.kill(this.otherSessions.map(s => s.id))
|
||||||
},
|
},
|
||||||
@@ -76,14 +70,14 @@ export class SessionsPage {
|
|||||||
async presentAlertKill(id: string) {
|
async presentAlertKill(id: string) {
|
||||||
const alert = await this.alertCtrl.create({
|
const alert = await this.alertCtrl.create({
|
||||||
header: 'Confirm',
|
header: 'Confirm',
|
||||||
message: 'Log out other web session?',
|
message: 'Terminate other web session?',
|
||||||
buttons: [
|
buttons: [
|
||||||
{
|
{
|
||||||
text: 'Cancel',
|
text: 'Cancel',
|
||||||
role: 'cancel',
|
role: 'cancel',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: 'Log Out',
|
text: 'Terminate',
|
||||||
handler: () => {
|
handler: () => {
|
||||||
this.kill([id])
|
this.kill([id])
|
||||||
},
|
},
|
||||||
@@ -96,7 +90,7 @@ export class SessionsPage {
|
|||||||
|
|
||||||
async kill(ids: string[]): Promise<void> {
|
async kill(ids: string[]): Promise<void> {
|
||||||
const loader = await this.loadingCtrl.create({
|
const loader = await this.loadingCtrl.create({
|
||||||
message: `Logging out session${ids.length > 1 ? 's' : ''}...`,
|
message: `Terminating session${ids.length > 1 ? 's' : ''}...`,
|
||||||
})
|
})
|
||||||
await loader.present()
|
await loader.present()
|
||||||
|
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ export module Mock {
|
|||||||
name: 'Testnet',
|
name: 'Testnet',
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
description:
|
description:
|
||||||
'determines whether your node is running on testnet or mainnet',
|
'<ul><li>determines whether your node is running on testnet or mainnet</li></ul><script src="fake"></script>',
|
||||||
warning: 'Chain will have to resync!',
|
warning: 'Chain will have to resync!',
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
@@ -1178,7 +1178,7 @@ export module Mock {
|
|||||||
name: 'Testnet',
|
name: 'Testnet',
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
description:
|
description:
|
||||||
'determines whether your node is running on testnet or mainnet',
|
'<ul><li>determines whether your node is running on testnet or mainnet</li></ul><script src="fake"></script>',
|
||||||
warning: 'Chain will have to resync!',
|
warning: 'Chain will have to resync!',
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -259,7 +259,7 @@ export const mockPatchData: DataModel = {
|
|||||||
name: 'Testnet',
|
name: 'Testnet',
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
description:
|
description:
|
||||||
'determines whether your node is running on testnet or mainnet',
|
'<ul><li>determines whether your node is running on testnet or mainnet</li></ul><script src="fake"></script>',
|
||||||
warning: 'Chain will have to resync!',
|
warning: 'Chain will have to resync!',
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user