mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 20:14:49 +00:00
chore: cleanup and small misc fixes
display success alert if on latest EOS after check for update fix bug with loader dismiss after alert present fix restart button on update complete alert and fix mocks to account for this state fix make clean and adjust default registry names
This commit is contained in:
4
Makefile
4
Makefile
@@ -29,8 +29,8 @@ clean:
|
|||||||
rm -rf patch-db/client/node_modules
|
rm -rf patch-db/client/node_modules
|
||||||
rm -rf patch-db/client/dist
|
rm -rf patch-db/client/dist
|
||||||
|
|
||||||
rm libs/js_engine/src/artifacts/ARM_JS_SNAPSHOT.bin
|
rm -f libs/js_engine/src/artifacts/ARM_JS_SNAPSHOT.bin
|
||||||
rm libs/js_engine/src/artifacts/JS_SNAPSHOT.bin
|
rm -f libs/js_engine/src/artifacts/JS_SNAPSHOT.bin
|
||||||
touch libs/snapshot-creator/Cargo.toml
|
touch libs/snapshot-creator/Cargo.toml
|
||||||
|
|
||||||
eos.img: $(EMBASSY_SRC) system-images/compat/compat.tar system-images/utils/utils.tar $(EMBASSY_V8_SNAPSHOTS)
|
eos.img: $(EMBASSY_SRC) system-images/compat/compat.tar system-images/utils/utils.tar $(EMBASSY_V8_SNAPSHOTS)
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ npm run start:diagnostic-ui
|
|||||||
|
|
||||||
This section enables you to run a local frontend with a remote backend (eg. hosted on a live Embassy). It assumes you have completed Step 1 and Step 2 in the [section above](#running-locally-with-mocks)
|
This section enables you to run a local frontend with a remote backend (eg. hosted on a live Embassy). It assumes you have completed Step 1 and Step 2 in the [section above](#running-locally-with-mocks)
|
||||||
|
|
||||||
1. Set `useMocks: true` in `config.json`
|
1. Set `useMocks: false` in `config.json`
|
||||||
|
|
||||||
2. Create a proxy configuration file from the sample:
|
2. Create a proxy configuration file from the sample:
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,14 @@
|
|||||||
import { Component } from '@angular/core'
|
import { Component } from '@angular/core'
|
||||||
import { AlertController, LoadingController, ModalController } from '@ionic/angular'
|
import {
|
||||||
import { ApiService, CifsBackupTarget, EmbassyOSRecoveryInfo } from 'src/app/services/api/api.service'
|
AlertController,
|
||||||
|
LoadingController,
|
||||||
|
ModalController,
|
||||||
|
} from '@ionic/angular'
|
||||||
|
import {
|
||||||
|
ApiService,
|
||||||
|
CifsBackupTarget,
|
||||||
|
EmbassyOSRecoveryInfo,
|
||||||
|
} from 'src/app/services/api/api.service'
|
||||||
import { PasswordPage } from '../password/password.page'
|
import { PasswordPage } from '../password/password.page'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -17,18 +25,18 @@ export class CifsModal {
|
|||||||
password: '',
|
password: '',
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor (
|
constructor(
|
||||||
private readonly modalController: ModalController,
|
private readonly modalController: ModalController,
|
||||||
private readonly apiService: ApiService,
|
private readonly apiService: ApiService,
|
||||||
private readonly loadingCtrl: LoadingController,
|
private readonly loadingCtrl: LoadingController,
|
||||||
private readonly alertCtrl: AlertController,
|
private readonly alertCtrl: AlertController,
|
||||||
) { }
|
) {}
|
||||||
|
|
||||||
cancel () {
|
cancel() {
|
||||||
this.modalController.dismiss()
|
this.modalController.dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
async submit (): Promise<void> {
|
async submit(): Promise<void> {
|
||||||
const loader = await this.loadingCtrl.create({
|
const loader = await this.loadingCtrl.create({
|
||||||
spinner: 'lines',
|
spinner: 'lines',
|
||||||
message: 'Connecting to shared folder...',
|
message: 'Connecting to shared folder...',
|
||||||
@@ -38,23 +46,30 @@ export class CifsModal {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const embassyOS = await this.apiService.verifyCifs(this.cifs)
|
const embassyOS = await this.apiService.verifyCifs(this.cifs)
|
||||||
|
|
||||||
|
await loader.dismiss()
|
||||||
|
|
||||||
const is02x = embassyOS.version.startsWith('0.2')
|
const is02x = embassyOS.version.startsWith('0.2')
|
||||||
|
|
||||||
if (is02x) {
|
if (is02x) {
|
||||||
this.modalController.dismiss({
|
this.modalController.dismiss(
|
||||||
cifs: this.cifs,
|
{
|
||||||
}, 'success')
|
cifs: this.cifs,
|
||||||
|
},
|
||||||
|
'success',
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
this.presentModalPassword(embassyOS)
|
this.presentModalPassword(embassyOS)
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
await loader.dismiss()
|
||||||
this.presentAlertFailed()
|
this.presentAlertFailed()
|
||||||
} finally {
|
|
||||||
loader.dismiss()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async presentModalPassword (embassyOS: EmbassyOSRecoveryInfo): Promise<void> {
|
private async presentModalPassword(
|
||||||
|
embassyOS: EmbassyOSRecoveryInfo,
|
||||||
|
): Promise<void> {
|
||||||
const target: CifsBackupTarget = {
|
const target: CifsBackupTarget = {
|
||||||
...this.cifs,
|
...this.cifs,
|
||||||
mountable: true,
|
mountable: true,
|
||||||
@@ -68,19 +83,23 @@ export class CifsModal {
|
|||||||
})
|
})
|
||||||
modal.onDidDismiss().then(res => {
|
modal.onDidDismiss().then(res => {
|
||||||
if (res.role === 'success') {
|
if (res.role === 'success') {
|
||||||
this.modalController.dismiss({
|
this.modalController.dismiss(
|
||||||
cifs: this.cifs,
|
{
|
||||||
recoveryPassword: res.data.password,
|
cifs: this.cifs,
|
||||||
}, 'success')
|
recoveryPassword: res.data.password,
|
||||||
|
},
|
||||||
|
'success',
|
||||||
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
await modal.present()
|
await modal.present()
|
||||||
}
|
}
|
||||||
|
|
||||||
private async presentAlertFailed (): Promise<void> {
|
private async presentAlertFailed(): Promise<void> {
|
||||||
const alert = await this.alertCtrl.create({
|
const alert = await this.alertCtrl.create({
|
||||||
header: 'Connection Failed',
|
header: 'Connection Failed',
|
||||||
message: 'Unable to connect to shared folder. Ensure (1) target computer is connected to LAN, (2) target folder is being shared, and (3) hostname, path, and credentials are accurate.',
|
message:
|
||||||
|
'Unable to connect to shared folder. Ensure (1) target computer is connected to LAN, (2) target folder is being shared, and (3) hostname, path, and credentials are accurate.',
|
||||||
buttons: ['OK'],
|
buttons: ['OK'],
|
||||||
})
|
})
|
||||||
alert.present()
|
alert.present()
|
||||||
|
|||||||
@@ -45,23 +45,43 @@ export class UpdateToastService extends Observable<unknown> {
|
|||||||
super(subscriber => this.stream$.subscribe(subscriber))
|
super(subscriber => this.stream$.subscribe(subscriber))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOADER: LoadingOptions = {
|
||||||
|
spinner: 'lines',
|
||||||
|
message: 'Restarting...',
|
||||||
|
}
|
||||||
|
|
||||||
|
TOAST: ToastOptions = {
|
||||||
|
header: 'EOS download complete!',
|
||||||
|
message:
|
||||||
|
'Restart your Embassy for these updates to take effect. It can take several minutes to come back online.',
|
||||||
|
position: 'bottom',
|
||||||
|
duration: 0,
|
||||||
|
cssClass: 'success-toast',
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
side: 'start',
|
||||||
|
icon: 'close',
|
||||||
|
handler: () => true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
side: 'end',
|
||||||
|
text: 'Restart',
|
||||||
|
handler: () => {
|
||||||
|
this.restart()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
private async showToast() {
|
private async showToast() {
|
||||||
await this.updateToast?.dismiss()
|
await this.updateToast?.dismiss()
|
||||||
|
|
||||||
this.updateToast = await this.toastCtrl.create(TOAST)
|
this.updateToast = await this.toastCtrl.create(this.TOAST)
|
||||||
this.updateToast.buttons?.push({
|
|
||||||
side: 'end',
|
|
||||||
text: 'Restart',
|
|
||||||
handler: () => {
|
|
||||||
this.restart()
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
await this.updateToast.present()
|
await this.updateToast.present()
|
||||||
}
|
}
|
||||||
|
|
||||||
private async restart(): Promise<void> {
|
private async restart(): Promise<void> {
|
||||||
const loader = await this.loadingCtrl.create(LOADER)
|
const loader = await this.loadingCtrl.create(this.LOADER)
|
||||||
|
|
||||||
await loader.present()
|
await loader.present()
|
||||||
|
|
||||||
@@ -74,24 +94,3 @@ export class UpdateToastService extends Observable<unknown> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const LOADER: LoadingOptions = {
|
|
||||||
spinner: 'lines',
|
|
||||||
message: 'Restarting...',
|
|
||||||
}
|
|
||||||
|
|
||||||
const TOAST: ToastOptions = {
|
|
||||||
header: 'EOS download complete!',
|
|
||||||
message:
|
|
||||||
'Restart your Embassy for these updates to take effect. It can take several minutes to come back online.',
|
|
||||||
position: 'bottom',
|
|
||||||
duration: 0,
|
|
||||||
cssClass: 'success-toast',
|
|
||||||
buttons: [
|
|
||||||
{
|
|
||||||
side: 'start',
|
|
||||||
icon: 'close',
|
|
||||||
handler: () => true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ export class SnekDirective {
|
|||||||
|
|
||||||
if (data?.highScore > highScore) {
|
if (data?.highScore > highScore) {
|
||||||
const loader = await this.loadingCtrl.create({
|
const loader = await this.loadingCtrl.create({
|
||||||
spinner: 'lines',
|
message: 'Saving high score...',
|
||||||
message: 'Saving High Score...',
|
backdropDismiss: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
await loader.present()
|
await loader.present()
|
||||||
|
|||||||
@@ -66,22 +66,30 @@
|
|||||||
<ion-footer>
|
<ion-footer>
|
||||||
<ion-toolbar>
|
<ion-toolbar>
|
||||||
<ng-container *ngIf="!initializing && swiper">
|
<ng-container *ngIf="!initializing && swiper">
|
||||||
<ion-buttons slot="end" style="padding-right: 8px">
|
<ion-buttons slot="end" class="ion-padding-end">
|
||||||
<ion-button
|
<ion-button
|
||||||
*ngIf="error; else noError"
|
*ngIf="error; else noError"
|
||||||
|
fill="solid"
|
||||||
|
color="dark"
|
||||||
(click)="dismiss()"
|
(click)="dismiss()"
|
||||||
class="enter-click"
|
class="enter-click btn-128"
|
||||||
>
|
>
|
||||||
<b>Dismiss</b>
|
Dismiss
|
||||||
</ion-button>
|
</ion-button>
|
||||||
<ng-template #noError>
|
<ng-template #noError>
|
||||||
<ion-button
|
<ion-button
|
||||||
*ngIf="!currentSlide.loading && !swiper.isEnd"
|
*ngIf="!currentSlide.loading && !swiper.isEnd"
|
||||||
|
fill="solid"
|
||||||
|
color="primary"
|
||||||
(click)="next()"
|
(click)="next()"
|
||||||
class="enter-click"
|
class="enter-click btn-128"
|
||||||
[class.no-click]="currentSlide.loading"
|
[class.no-click]="currentSlide.loading"
|
||||||
>
|
>
|
||||||
<b>Continue</b>
|
{{
|
||||||
|
currentIndex < swiper.slides.length - 2
|
||||||
|
? 'Continue'
|
||||||
|
: params.submitBtn
|
||||||
|
}}
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ export class AppWizardComponent {
|
|||||||
action: WizardAction
|
action: WizardAction
|
||||||
title: string
|
title: string
|
||||||
slides: SlideDefinition[]
|
slides: SlideDefinition[]
|
||||||
|
submitBtn: string
|
||||||
version?: string
|
version?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +77,6 @@ export class AppWizardComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setError(e: any) {
|
setError(e: any) {
|
||||||
console.log(e)
|
|
||||||
this.error = e
|
this.error = e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
{{ v.version }}
|
{{ v.version }}
|
||||||
</b>
|
</b>
|
||||||
</h4>
|
</h4>
|
||||||
<hr style="height: 0; border-width: 1px" />
|
<div class="underline" style="margin: unset"></div>
|
||||||
<div [innerHTML]="v.notes | markdown"></div>
|
<div [innerHTML]="v.notes | markdown"></div>
|
||||||
<br />
|
<br />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ export class WizardDefs {
|
|||||||
title,
|
title,
|
||||||
version,
|
version,
|
||||||
slides: slides.filter(exists),
|
slides: slides.filter(exists),
|
||||||
|
submitBtn: 'Begin Update',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,6 +111,7 @@ export class WizardDefs {
|
|||||||
title,
|
title,
|
||||||
version,
|
version,
|
||||||
slides: slides.filter(exists),
|
slides: slides.filter(exists),
|
||||||
|
submitBtn: 'Begin Update',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,6 +162,7 @@ export class WizardDefs {
|
|||||||
title,
|
title,
|
||||||
version,
|
version,
|
||||||
slides: slides.filter(exists),
|
slides: slides.filter(exists),
|
||||||
|
submitBtn: 'Begin Downgrade',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,6 +202,7 @@ export class WizardDefs {
|
|||||||
action: 'uninstall',
|
action: 'uninstall',
|
||||||
title,
|
title,
|
||||||
slides: slides.filter(exists),
|
slides: slides.filter(exists),
|
||||||
|
submitBtn: 'Uninstall Anyway',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,6 +232,7 @@ export class WizardDefs {
|
|||||||
action: 'stop',
|
action: 'stop',
|
||||||
title,
|
title,
|
||||||
slides: slides.filter(exists),
|
slides: slides.filter(exists),
|
||||||
|
submitBtn: 'Stop Anyway',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,6 +266,7 @@ export class WizardDefs {
|
|||||||
action: 'configure',
|
action: 'configure',
|
||||||
title,
|
title,
|
||||||
slides: slides.filter(exists),
|
slides: slides.filter(exists),
|
||||||
|
submitBtn: 'Configure Anyway',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
rendering.display === PR[PS.Stopping].display &&
|
rendering.display === PR[PS.Stopping].display &&
|
||||||
(sigtermTimeout | durationToSeconds) > 30
|
(sigtermTimeout | durationToSeconds) > 30
|
||||||
"
|
"
|
||||||
>This may take a while.</span
|
>this may take a while</span
|
||||||
>
|
>
|
||||||
</span>
|
</span>
|
||||||
<span *ngIf="installProgress">
|
<span *ngIf="installProgress">
|
||||||
|
|||||||
@@ -107,19 +107,21 @@
|
|||||||
>
|
>
|
||||||
<ion-button
|
<ion-button
|
||||||
*ngIf="hasConfig"
|
*ngIf="hasConfig"
|
||||||
fill="outline"
|
fill="solid"
|
||||||
|
color="primary"
|
||||||
[disabled]="saving"
|
[disabled]="saving"
|
||||||
(click)="save()"
|
(click)="save()"
|
||||||
class="enter-click"
|
class="enter-click btn-128"
|
||||||
[class.no-click]="saving"
|
[class.no-click]="saving"
|
||||||
>
|
>
|
||||||
Save
|
Save
|
||||||
</ion-button>
|
</ion-button>
|
||||||
<ion-button
|
<ion-button
|
||||||
*ngIf="!hasConfig"
|
*ngIf="!hasConfig"
|
||||||
fill="outline"
|
fill="solid"
|
||||||
|
color="dark"
|
||||||
(click)="dismiss()"
|
(click)="dismiss()"
|
||||||
class="enter-click"
|
class="enter-click btn-128"
|
||||||
>
|
>
|
||||||
Close
|
Close
|
||||||
</ion-button>
|
</ion-button>
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ export class AppConfigPage {
|
|||||||
|
|
||||||
async dismiss() {
|
async dismiss() {
|
||||||
if (this.configForm?.dirty) {
|
if (this.configForm?.dirty) {
|
||||||
await this.presentAlertUnsaved()
|
this.presentAlertUnsaved()
|
||||||
} else {
|
} else {
|
||||||
this.modalCtrl.dismiss()
|
this.modalCtrl.dismiss()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,13 +20,23 @@
|
|||||||
<ion-text color="success">Ready to restore</ion-text>
|
<ion-text color="success">Ready to restore</ion-text>
|
||||||
</p>
|
</p>
|
||||||
<p *ngIf="option.installed">
|
<p *ngIf="option.installed">
|
||||||
<ion-text color="warning">Unavailable. {{ option.title }} is already installed.</ion-text>
|
<ion-text color="warning"
|
||||||
|
>Unavailable. {{ option.title }} is already installed.</ion-text
|
||||||
|
>
|
||||||
</p>
|
</p>
|
||||||
<p *ngIf="option['newer-eos']">
|
<p *ngIf="option['newer-eos']">
|
||||||
<ion-text color="danger">Unavailable. Backup was made on a newer version of EmbassyOS.</ion-text>
|
<ion-text color="danger"
|
||||||
|
>Unavailable. Backup was made on a newer version of
|
||||||
|
EmbassyOS.</ion-text
|
||||||
|
>
|
||||||
</p>
|
</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
<ion-checkbox slot="end" [(ngModel)]="option.checked" [disabled]="option.installed || option['newer-eos']" (ionChange)="handleChange()"></ion-checkbox>
|
<ion-checkbox
|
||||||
|
slot="end"
|
||||||
|
[(ngModel)]="option.checked"
|
||||||
|
[disabled]="option.installed || option['newer-eos']"
|
||||||
|
(ionChange)="handleChange()"
|
||||||
|
></ion-checkbox>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</ion-item-group>
|
</ion-item-group>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
@@ -34,7 +44,13 @@
|
|||||||
<ion-footer>
|
<ion-footer>
|
||||||
<ion-toolbar>
|
<ion-toolbar>
|
||||||
<ion-buttons slot="end" class="ion-padding-end">
|
<ion-buttons slot="end" class="ion-padding-end">
|
||||||
<ion-button [disabled]="!hasSelection" fill="outline" (click)="restore()" class="enter-click">
|
<ion-button
|
||||||
|
[disabled]="!hasSelection"
|
||||||
|
fill="solid"
|
||||||
|
color="primary"
|
||||||
|
(click)="restore()"
|
||||||
|
class="enter-click btn-128"
|
||||||
|
>
|
||||||
Restore Selected
|
Restore Selected
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
|
|||||||
@@ -1,26 +1,30 @@
|
|||||||
<ion-header>
|
<ion-header>
|
||||||
<ion-toolbar>
|
<ion-toolbar>
|
||||||
<ion-buttons slot="start">
|
<ion-title> {{ spec.name }} </ion-title>
|
||||||
|
<ion-buttons slot="end">
|
||||||
<ion-button (click)="dismiss()">
|
<ion-button (click)="dismiss()">
|
||||||
<ion-icon slot="icon-only" name="close"></ion-icon>
|
<ion-icon slot="icon-only" name="close"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
<ion-title>
|
|
||||||
{{ spec.name }}
|
|
||||||
</ion-title>
|
|
||||||
<ion-buttons slot="end">
|
|
||||||
<ion-button slot="end" fill="clear" (click)="toggleSelectAll()">
|
|
||||||
{{ selectAll ? 'All' : 'None' }}
|
|
||||||
</ion-button>
|
|
||||||
</ion-buttons>
|
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
|
|
||||||
<ion-content>
|
<ion-content>
|
||||||
<ion-item-group>
|
<ion-item-group>
|
||||||
|
<ion-item-divider style="padding-bottom: 4px">
|
||||||
|
<ion-buttons slot="end">
|
||||||
|
<ion-button fill="clear" (click)="toggleSelectAll()">
|
||||||
|
<b>{{ selectAll ? 'All' : 'None' }}</b>
|
||||||
|
</ion-button>
|
||||||
|
</ion-buttons>
|
||||||
|
</ion-item-divider>
|
||||||
<ion-item *ngFor="let option of options | keyvalue : asIsOrder">
|
<ion-item *ngFor="let option of options | keyvalue : asIsOrder">
|
||||||
<ion-label>{{ spec.spec['value-names'][option.key] }}</ion-label>
|
<ion-label>{{ spec.spec['value-names'][option.key] }}</ion-label>
|
||||||
<ion-checkbox slot="end" [(ngModel)]="option.value" (click)="toggleSelected(option.key)"></ion-checkbox>
|
<ion-checkbox
|
||||||
|
slot="end"
|
||||||
|
[(ngModel)]="option.value"
|
||||||
|
(click)="toggleSelected(option.key)"
|
||||||
|
></ion-checkbox>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</ion-item-group>
|
</ion-item-group>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
@@ -28,7 +32,12 @@
|
|||||||
<ion-footer>
|
<ion-footer>
|
||||||
<ion-toolbar>
|
<ion-toolbar>
|
||||||
<ion-buttons slot="end" class="ion-padding-end">
|
<ion-buttons slot="end" class="ion-padding-end">
|
||||||
<ion-button fill="outline" (click)="save()" class="enter-click">
|
<ion-button
|
||||||
|
fill="solid"
|
||||||
|
color="primary"
|
||||||
|
(click)="save()"
|
||||||
|
class="enter-click btn-128"
|
||||||
|
>
|
||||||
Done
|
Done
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
|
|||||||
@@ -90,7 +90,12 @@
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="ion-text-center ion-padding">
|
<div class="ion-text-center ion-padding">
|
||||||
<ion-button fill="outline" color="dark" (click)="dismiss()">
|
<ion-button
|
||||||
|
fill="solid"
|
||||||
|
color="primary"
|
||||||
|
(click)="dismiss()"
|
||||||
|
class="enter-click btn-128"
|
||||||
|
>
|
||||||
Begin
|
Begin
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -15,9 +15,14 @@
|
|||||||
<ion-toolbar>
|
<ion-toolbar>
|
||||||
<ion-title slot="start">High Score: {{ highScore }}</ion-title>
|
<ion-title slot="start">High Score: {{ highScore }}</ion-title>
|
||||||
<ion-buttons slot="end" class="ion-padding-end">
|
<ion-buttons slot="end" class="ion-padding-end">
|
||||||
<ion-button (click)="dismiss()" class="enter-click"
|
<ion-button
|
||||||
>Byeeeeeee!</ion-button
|
fill="solid"
|
||||||
|
color="primary"
|
||||||
|
(click)="dismiss()"
|
||||||
|
class="enter-click btn-128"
|
||||||
>
|
>
|
||||||
|
Save and Quit
|
||||||
|
</ion-button>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-footer>
|
</ion-footer>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
.bulb {
|
.bulb {
|
||||||
position: absolute !important;
|
position: absolute !important;
|
||||||
left: 9px !important;
|
top: 6px !important;
|
||||||
top: 8px !important;
|
|
||||||
height: 14px;
|
height: 14px;
|
||||||
width: 14px;
|
width: 14px;
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
@@ -10,7 +9,6 @@
|
|||||||
|
|
||||||
.warning-icon {
|
.warning-icon {
|
||||||
position: absolute !important;
|
position: absolute !important;
|
||||||
left: 6px !important;
|
|
||||||
top: 6px !important;
|
top: 6px !important;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
@@ -21,7 +19,6 @@
|
|||||||
|
|
||||||
.spinner {
|
.spinner {
|
||||||
position: absolute !important;
|
position: absolute !important;
|
||||||
left: 6px !important;
|
|
||||||
top: 6px !important;
|
top: 6px !important;
|
||||||
width: 18px;
|
width: 18px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,19 +12,10 @@ import { ValueSpecObject } from 'src/app/pkg-config/config-types'
|
|||||||
import { GenericFormPage } from 'src/app/modals/generic-form/generic-form.page'
|
import { GenericFormPage } from 'src/app/modals/generic-form/generic-form.page'
|
||||||
import { PatchDbService } from '../../../services/patch-db/patch-db.service'
|
import { PatchDbService } from '../../../services/patch-db/patch-db.service'
|
||||||
import { v4 } from 'uuid'
|
import { v4 } from 'uuid'
|
||||||
import {
|
import { UIMarketplaceData } from '../../../services/patch-db/data-model'
|
||||||
UIData,
|
|
||||||
UIMarketplaceData,
|
|
||||||
} from '../../../services/patch-db/data-model'
|
|
||||||
import { ConfigService } from '../../../services/config.service'
|
import { ConfigService } from '../../../services/config.service'
|
||||||
import { MarketplaceService } from 'src/app/services/marketplace.service'
|
import { MarketplaceService } from 'src/app/services/marketplace.service'
|
||||||
import {
|
import { distinctUntilChanged, finalize, first } from 'rxjs/operators'
|
||||||
distinctUntilChanged,
|
|
||||||
finalize,
|
|
||||||
first,
|
|
||||||
map,
|
|
||||||
startWith,
|
|
||||||
} from 'rxjs/operators'
|
|
||||||
|
|
||||||
type Marketplaces = {
|
type Marketplaces = {
|
||||||
id: string | undefined
|
id: string | undefined
|
||||||
@@ -55,11 +46,8 @@ export class MarketplacesPage {
|
|||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.patch
|
this.patch
|
||||||
.watch$('ui')
|
.watch$('ui', 'marketplace')
|
||||||
.pipe(
|
.pipe(distinctUntilChanged())
|
||||||
map((ui: UIData) => ui.marketplace),
|
|
||||||
distinctUntilChanged(),
|
|
||||||
)
|
|
||||||
.subscribe((mp: UIMarketplaceData | undefined) => {
|
.subscribe((mp: UIMarketplaceData | undefined) => {
|
||||||
let marketplaces: Marketplaces = [
|
let marketplaces: Marketplaces = [
|
||||||
{
|
{
|
||||||
@@ -114,8 +102,7 @@ export class MarketplacesPage {
|
|||||||
|
|
||||||
async presentAction(id: string = '') {
|
async presentAction(id: string = '') {
|
||||||
// no need to view actions if is selected marketplace
|
// no need to view actions if is selected marketplace
|
||||||
if (!id || id === this.patch.getData().ui.marketplace?.['selected-id'])
|
if (id === this.patch.getData().ui.marketplace?.['selected-id']) return
|
||||||
return
|
|
||||||
|
|
||||||
const buttons: ActionSheetButton[] = [
|
const buttons: ActionSheetButton[] = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { WizardDefs } from 'src/app/components/app-wizard/wizard-defs'
|
|||||||
import { exists, isEmptyObject, ErrorToastService } from '@start9labs/shared'
|
import { exists, isEmptyObject, ErrorToastService } from '@start9labs/shared'
|
||||||
import { EOSService } from 'src/app/services/eos.service'
|
import { EOSService } from 'src/app/services/eos.service'
|
||||||
import { LocalStorageService } from 'src/app/services/local-storage.service'
|
import { LocalStorageService } from 'src/app/services/local-storage.service'
|
||||||
|
import { RecoveredPackageDataEntry } from 'src/app/services/patch-db/data-model'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'server-show',
|
selector: 'server-show',
|
||||||
@@ -47,7 +48,7 @@ export class ServerShowPage {
|
|||||||
this.patch
|
this.patch
|
||||||
.watch$('recovered-packages')
|
.watch$('recovered-packages')
|
||||||
.pipe(filter(exists), take(1))
|
.pipe(filter(exists), take(1))
|
||||||
.subscribe(rps => {
|
.subscribe((rps: { [id: string]: RecoveredPackageDataEntry }) => {
|
||||||
this.hasRecoveredPackage = !isEmptyObject(rps)
|
this.hasRecoveredPackage = !isEmptyObject(rps)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -233,16 +234,36 @@ export class ServerShowPage {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const updateAvailable = await this.eosService.getEOS()
|
const updateAvailable = await this.eosService.getEOS()
|
||||||
|
|
||||||
|
await loader.dismiss()
|
||||||
|
|
||||||
if (updateAvailable) {
|
if (updateAvailable) {
|
||||||
this.updateEos()
|
this.updateEos()
|
||||||
|
} else {
|
||||||
|
this.presentAlertLatest()
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
|
await loader.dismiss()
|
||||||
this.errToast.present(e)
|
this.errToast.present(e)
|
||||||
} finally {
|
|
||||||
loader.dismiss()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async presentAlertLatest() {
|
||||||
|
const alert = await this.alertCtrl.create({
|
||||||
|
header: 'Up to date!',
|
||||||
|
message: 'You are on the latest version of EmbassyOS.',
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
text: 'OK',
|
||||||
|
role: 'cancel',
|
||||||
|
cssClass: 'enter-click',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
cssClass: 'alert-success-message',
|
||||||
|
})
|
||||||
|
alert.present()
|
||||||
|
}
|
||||||
|
|
||||||
settings: ServerSettings = {
|
settings: ServerSettings = {
|
||||||
Backups: [
|
Backups: [
|
||||||
{
|
{
|
||||||
@@ -332,8 +353,8 @@ export class ServerShowPage {
|
|||||||
disabled: of(false),
|
disabled: of(false),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Manually install a service',
|
title: 'Manually Install A Service',
|
||||||
description: `Install a service by drag n' drop`,
|
description: `Install a service by drag and drop`,
|
||||||
icon: 'push-outline',
|
icon: 'push-outline',
|
||||||
action: () =>
|
action: () =>
|
||||||
this.navCtrl.navigateForward(['sideload'], {
|
this.navCtrl.navigateForward(['sideload'], {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<ion-buttons slot="start">
|
<ion-buttons slot="start">
|
||||||
<ion-back-button defaultHref="embassy"></ion-back-button>
|
<ion-back-button defaultHref="embassy"></ion-back-button>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
<ion-title>Manually install a service</ion-title>
|
<ion-title>Manually Install A Service</ion-title>
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
PackageDataEntry,
|
PackageDataEntry,
|
||||||
PackageMainStatus,
|
PackageMainStatus,
|
||||||
PackageState,
|
PackageState,
|
||||||
|
ServerStatusInfo,
|
||||||
} from 'src/app/services/patch-db/data-model'
|
} from 'src/app/services/patch-db/data-model'
|
||||||
import {
|
import {
|
||||||
Log,
|
Log,
|
||||||
@@ -18,6 +19,11 @@ import { BTC_ICON, LND_ICON, PROXY_ICON } from './api-icons'
|
|||||||
import { MarketplacePkg } from '@start9labs/marketplace'
|
import { MarketplacePkg } from '@start9labs/marketplace'
|
||||||
|
|
||||||
export module Mock {
|
export module Mock {
|
||||||
|
export const ServerUpdated: ServerStatusInfo = {
|
||||||
|
'backing-up': false,
|
||||||
|
'update-progress': null,
|
||||||
|
updated: true,
|
||||||
|
}
|
||||||
export const MarketplaceEos: RR.GetMarketplaceEOSRes = {
|
export const MarketplaceEos: RR.GetMarketplaceEOSRes = {
|
||||||
version: '0.3.2',
|
version: '0.3.2',
|
||||||
headline: 'Our biggest release ever.',
|
headline: 'Our biggest release ever.',
|
||||||
|
|||||||
@@ -187,7 +187,6 @@ export class MockApiService extends ApiService {
|
|||||||
value: initialProgress,
|
value: initialProgress,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
return this.withRevision(patch, 'updating')
|
return this.withRevision(patch, 'updating')
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -860,6 +859,16 @@ export class MockApiService extends ApiService {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
this.updateMock(patch4)
|
this.updateMock(patch4)
|
||||||
|
// set patch indicating update is complete
|
||||||
|
await pauseFor(100)
|
||||||
|
const patch6 = [
|
||||||
|
{
|
||||||
|
op: PatchOp.REPLACE,
|
||||||
|
path: '/server-info/status-info',
|
||||||
|
value: Mock.ServerUpdated,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
this.updateMock(patch6)
|
||||||
}, 1000)
|
}, 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -444,7 +444,7 @@ export const mockPatchData: DataModel = {
|
|||||||
'donation-url': null,
|
'donation-url': null,
|
||||||
alerts: {
|
alerts: {
|
||||||
install: null,
|
install: null,
|
||||||
uninstall: undefined,
|
uninstall: null,
|
||||||
restore:
|
restore:
|
||||||
'If this is a duplicate instance of the same LND node, you may loose your funds.',
|
'If this is a duplicate instance of the same LND node, you may loose your funds.',
|
||||||
start: 'Starting LND is good for your health.',
|
start: 'Starting LND is good for your health.',
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { MarketplaceEOS } from 'src/app/services/api/api.types'
|
|||||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||||
import { Emver } from '@start9labs/shared'
|
import { Emver } from '@start9labs/shared'
|
||||||
import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
|
import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
|
||||||
|
import { switchMap, take } from 'rxjs/operators'
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
|
|||||||
@@ -12,13 +12,11 @@ import { ApiService } from 'src/app/services/api/embassy-api.service'
|
|||||||
import { ConfigService } from 'src/app/services/config.service'
|
import { ConfigService } from 'src/app/services/config.service'
|
||||||
import {
|
import {
|
||||||
ServerInfo,
|
ServerInfo,
|
||||||
UIData,
|
|
||||||
UIMarketplaceData,
|
UIMarketplaceData,
|
||||||
} from 'src/app/services/patch-db/data-model'
|
} 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'
|
||||||
import {
|
import {
|
||||||
catchError,
|
catchError,
|
||||||
distinctUntilChanged,
|
|
||||||
filter,
|
filter,
|
||||||
map,
|
map,
|
||||||
shareReplay,
|
shareReplay,
|
||||||
@@ -34,11 +32,7 @@ export class MarketplaceService extends AbstractMarketplaceService {
|
|||||||
|
|
||||||
private readonly altMarketplaceData$: Observable<
|
private readonly altMarketplaceData$: Observable<
|
||||||
UIMarketplaceData | undefined
|
UIMarketplaceData | undefined
|
||||||
> = this.patch.watch$('ui').pipe(
|
> = this.patch.watch$('ui', 'marketplace').pipe(shareReplay())
|
||||||
map((ui: UIData) => ui.marketplace),
|
|
||||||
distinctUntilChanged(),
|
|
||||||
shareReplay({ bufferSize: 1, refCount: true }),
|
|
||||||
)
|
|
||||||
|
|
||||||
private readonly marketplace$ = this.altMarketplaceData$.pipe(
|
private readonly marketplace$ = this.altMarketplaceData$.pipe(
|
||||||
map(data => this.toMarketplace(data)),
|
map(data => this.toMarketplace(data)),
|
||||||
@@ -46,7 +40,7 @@ export class MarketplaceService extends AbstractMarketplaceService {
|
|||||||
|
|
||||||
private readonly serverInfo$: Observable<ServerInfo> = this.patch
|
private readonly serverInfo$: Observable<ServerInfo> = this.patch
|
||||||
.watch$('server-info')
|
.watch$('server-info')
|
||||||
.pipe(take(1), shareReplay({ bufferSize: 1, refCount: true }))
|
.pipe(take(1), shareReplay())
|
||||||
|
|
||||||
private readonly categories$: Observable<string[]> = this.marketplace$.pipe(
|
private readonly categories$: Observable<string[]> = this.marketplace$.pipe(
|
||||||
switchMap(({ url }) =>
|
switchMap(({ url }) =>
|
||||||
@@ -57,6 +51,7 @@ export class MarketplaceService extends AbstractMarketplaceService {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
map(({ categories }) => categories),
|
map(({ categories }) => categories),
|
||||||
|
shareReplay(),
|
||||||
)
|
)
|
||||||
|
|
||||||
private readonly pkg$: Observable<MarketplacePkg[]> =
|
private readonly pkg$: Observable<MarketplacePkg[]> =
|
||||||
@@ -79,7 +74,7 @@ export class MarketplaceService extends AbstractMarketplaceService {
|
|||||||
|
|
||||||
return of([])
|
return of([])
|
||||||
}),
|
}),
|
||||||
shareReplay({ bufferSize: 1, refCount: true }),
|
shareReplay(),
|
||||||
)
|
)
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
|||||||
@@ -52,15 +52,17 @@ export interface ServerInfo {
|
|||||||
'lan-address': Url
|
'lan-address': Url
|
||||||
'tor-address': Url
|
'tor-address': Url
|
||||||
'unread-notification-count': number
|
'unread-notification-count': number
|
||||||
'status-info': {
|
'status-info': ServerStatusInfo
|
||||||
'backing-up': boolean
|
|
||||||
updated: boolean
|
|
||||||
'update-progress': { size: number | null; downloaded: number } | null
|
|
||||||
}
|
|
||||||
'eos-version-compat': string
|
'eos-version-compat': string
|
||||||
'password-hash': string
|
'password-hash': string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ServerStatusInfo {
|
||||||
|
'backing-up': boolean
|
||||||
|
updated: boolean
|
||||||
|
'update-progress': { size: number | null; downloaded: number } | null
|
||||||
|
}
|
||||||
|
|
||||||
export enum ServerStatus {
|
export enum ServerStatus {
|
||||||
Running = 'running',
|
Running = 'running',
|
||||||
Updated = 'updated',
|
Updated = 'updated',
|
||||||
|
|||||||
@@ -60,6 +60,10 @@ $subheader-height: 48px;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-128 {
|
||||||
|
min-width: 128px;
|
||||||
|
}
|
||||||
|
|
||||||
.subheader-padding {
|
.subheader-padding {
|
||||||
--padding-top: #{$subheader-height} + 10px;
|
--padding-top: #{$subheader-height} + 10px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,10 @@
|
|||||||
},
|
},
|
||||||
"beta": {
|
"beta": {
|
||||||
"url": "https://beta-registry-0-3.start9labs.com",
|
"url": "https://beta-registry-0-3.start9labs.com",
|
||||||
"name": "Embassy Marketplace (Beta)"
|
"name": "Beta Marketplace"
|
||||||
},
|
},
|
||||||
"alpha": {
|
"alpha": {
|
||||||
"url": "https://alpha-registry-0-3.start9labs.com",
|
"url": "https://alpha-registry-0-3.start9labs.com",
|
||||||
"name": "Embassy Marketplace (Alpha)"
|
"name": "Alpha Marketplace"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user