diff --git a/ui/src/app/app.component.html b/ui/src/app/app.component.html index 4f57d664c..e70261339 100644 --- a/ui/src/app/app.component.html +++ b/ui/src/app/app.component.html @@ -1,34 +1,48 @@ - - + +
+ +
+
+ - - {{ page.title }} + + + {{ page.title }} + {{ unreadCount }} -
+ +
+
+ + + + Log Out + + + +
- - - - - Logout - - - -
@@ -80,6 +94,8 @@ + + @@ -89,10 +105,8 @@ - - @@ -100,7 +114,6 @@ - @@ -137,11 +150,9 @@ - load bold - diff --git a/ui/src/app/app.component.scss b/ui/src/app/app.component.scss index aee63ce2d..1f58d0b37 100644 --- a/ui/src/app/app.component.scss +++ b/ui/src/app/app.component.scss @@ -1,18 +1,9 @@ -.selected { - --background: linear-gradient(120deg, #1e1e1e -1%, var(--ion-color-danger) 100%); +.bold { + font-weight: bold; } -.menu-style { - border-style: solid; - border-width: 0px 1px 0px 0px; - border-color: var(--ion-color-danger); - ion-item::part(native) { - height: 56px; - } -} - -.selected-badge { - background-color: #1e1e1e; +.dim { + color: var(--ion-color-dark-shade); } ion-split-pane { diff --git a/ui/src/app/app.component.ts b/ui/src/app/app.component.ts index 5ede9b38c..3b00243d5 100644 --- a/ui/src/app/app.component.ts +++ b/ui/src/app/app.component.ts @@ -71,9 +71,7 @@ export class AppComponent { private readonly config: ConfigService, readonly splitPane: SplitPaneTracker, ) { - // set dark theme - document.body.classList.toggle('dark', true) - this.init() + this.init() } async init () { @@ -266,7 +264,6 @@ export class AppComponent { }, { text: 'Logout', - cssClass: 'alert-danger', handler: () => { this.logout() }, diff --git a/ui/src/app/components/install-wizard/dependents/dependents.component.html b/ui/src/app/components/install-wizard/dependents/dependents.component.html index 94a04c346..6ca972529 100644 --- a/ui/src/app/components/install-wizard/dependents/dependents.component.html +++ b/ui/src/app/components/install-wizard/dependents/dependents.component.html @@ -26,12 +26,12 @@ Will Stop - + - +
{{ dep.value.title }}
diff --git a/ui/src/app/components/install-wizard/install-wizard.component.html b/ui/src/app/components/install-wizard/install-wizard.component.html index 277767d9b..48d5ddcd0 100644 --- a/ui/src/app/components/install-wizard/install-wizard.component.html +++ b/ui/src/app/components/install-wizard/install-wizard.component.html @@ -2,7 +2,7 @@

{{ params.toolbar.title }}

-

{{ params.toolbar.action }} {{ params.toolbar.version | displayEmver }}

+

{{ params.toolbar.action }} {{ params.toolbar.version | displayEmver }}

@@ -37,11 +37,11 @@ - + {{ cancel.text }} - + {{ cancel.text }} diff --git a/ui/src/app/components/object-config/object-config-item.component.html b/ui/src/app/components/object-config/object-config-item.component.html index 7ed4bd2c7..7092aa6b9 100644 --- a/ui/src/app/components/object-config/object-config-item.component.html +++ b/ui/src/app/components/object-config/object-config-item.component.html @@ -6,7 +6,7 @@
- {{ spec.name }} + {{ spec.name }} (new)
diff --git a/ui/src/app/components/skeleton-list/skeleton-list.component.scss b/ui/src/app/components/skeleton-list/skeleton-list.component.scss index 79ca6ab3f..730c11ca5 100644 --- a/ui/src/app/components/skeleton-list/skeleton-list.component.scss +++ b/ui/src/app/components/skeleton-list/skeleton-list.component.scss @@ -1,3 +1,3 @@ ion-note { width: 50%; -} \ No newline at end of file +} diff --git a/ui/src/app/components/status/status.component.ts b/ui/src/app/components/status/status.component.ts index bf326035d..405b0bb43 100644 --- a/ui/src/app/components/status/status.component.ts +++ b/ui/src/app/components/status/status.component.ts @@ -8,7 +8,7 @@ import { PkgStatusRendering } from 'src/app/services/pkg-status-rendering.servic }) export class StatusComponent { @Input() rendering: PkgStatusRendering - @Input() size?: 'small' | 'medium' | 'large' = 'large' + @Input() size?: 'small' | 'medium' | 'large' | 'x-large' = 'large' @Input() style?: string = 'regular' @Input() weight?: string = 'normal' } diff --git a/ui/src/app/modals/app-action-input/app-action-input.page.html b/ui/src/app/modals/app-action-input/app-action-input.page.html index bc17ab980..1626472db 100644 --- a/ui/src/app/modals/app-action-input/app-action-input.page.html +++ b/ui/src/app/modals/app-action-input/app-action-input.page.html @@ -1,8 +1,8 @@ - - + + {{ action.name }} diff --git a/ui/src/app/modals/app-config-list/app-config-list.page.html b/ui/src/app/modals/app-config-list/app-config-list.page.html index 2d1270b25..a9e23fb2c 100644 --- a/ui/src/app/modals/app-config-list/app-config-list.page.html +++ b/ui/src/app/modals/app-config-list/app-config-list.page.html @@ -55,7 +55,7 @@ {{ valueString[i] }} - +
diff --git a/ui/src/app/modals/app-config-list/app-config-list.page.ts b/ui/src/app/modals/app-config-list/app-config-list.page.ts index c35b48482..0a16fb4e1 100644 --- a/ui/src/app/modals/app-config-list/app-config-list.page.ts +++ b/ui/src/app/modals/app-config-list/app-config-list.page.ts @@ -118,7 +118,6 @@ export class AppConfigListPage extends ModalPresentable { }, { text: 'Delete', - cssClass: 'alert-danger', handler: () => { if (typeof key === 'number') { (this.value as any[]).splice(key, 1) diff --git a/ui/src/app/modals/app-config-object/app-config-object.page.ts b/ui/src/app/modals/app-config-object/app-config-object.page.ts index 8f6fde306..d5bac463c 100644 --- a/ui/src/app/modals/app-config-object/app-config-object.page.ts +++ b/ui/src/app/modals/app-config-object/app-config-object.page.ts @@ -41,7 +41,6 @@ export class AppConfigObjectPage { }, { text: 'Delete', - cssClass: 'alert-danger', handler: () => { this.dismiss(true) }, diff --git a/ui/src/app/modals/app-config-value/app-config-value.page.html b/ui/src/app/modals/app-config-value/app-config-value.page.html index 8c2d95fb4..ed74f6133 100644 --- a/ui/src/app/modals/app-config-value/app-config-value.page.html +++ b/ui/src/app/modals/app-config-value/app-config-value.page.html @@ -33,7 +33,7 @@ - + @@ -41,8 +41,8 @@ - {{ spec.units }} - + {{ spec.units }} + @@ -63,20 +63,18 @@

- {{ spec.patternDescription }} + {{ spec.patternDescription }}

- {{ integralDescription }} + {{ integralDescription }}

- {{ rangeDescription }} -

-

- -

Default: {{ defaultDescription }}

-

Units: {{ spec.units }}

- + {{ rangeDescription }}

+ +

Default: {{ defaultDescription }}

+

Units: {{ spec.units }}

+
diff --git a/ui/src/app/modals/app-config-value/app-config-value.page.ts b/ui/src/app/modals/app-config-value/app-config-value.page.ts index b4d124824..60f8407a9 100644 --- a/ui/src/app/modals/app-config-value/app-config-value.page.ts +++ b/ui/src/app/modals/app-config-value/app-config-value.page.ts @@ -176,7 +176,6 @@ export class AppConfigValuePage { }, { text: `Leave`, - cssClass: 'alert-danger', handler: () => { this.modalCtrl.dismiss() }, diff --git a/ui/src/app/pages/apps-routes/app-restore/app-restore.page.html b/ui/src/app/modals/app-restore/app-restore.component.html similarity index 83% rename from ui/src/app/pages/apps-routes/app-restore/app-restore.page.html rename to ui/src/app/modals/app-restore/app-restore.component.html index 02efcf81b..8c84baeef 100644 --- a/ui/src/app/pages/apps-routes/app-restore/app-restore.page.html +++ b/ui/src/app/modals/app-restore/app-restore.component.html @@ -1,22 +1,21 @@ - - - Restore From Backup - - - + + + + Restore From Backup + - - + + - +

Warning

@@ -56,5 +55,5 @@ -
+
diff --git a/ui/src/app/modals/app-restore/app-restore.component.module.ts b/ui/src/app/modals/app-restore/app-restore.component.module.ts new file mode 100644 index 000000000..bb729830f --- /dev/null +++ b/ui/src/app/modals/app-restore/app-restore.component.module.ts @@ -0,0 +1,25 @@ +import { NgModule } from '@angular/core' +import { CommonModule } from '@angular/common' +import { IonicModule } from '@ionic/angular' +import { AppRestoreComponent } from './app-restore.component' +import { PwaBackComponentModule } from '../../components/pwa-back-button/pwa-back.component.module' +import { BackupConfirmationComponentModule } from '../backup-confirmation/backup-confirmation.component.module' +import { SharingModule } from '../../modules/sharing.module' +import { TextSpinnerComponentModule } from '../../components/text-spinner/text-spinner.component.module' + +@NgModule({ + imports: [ + CommonModule, + IonicModule, + SharingModule, + BackupConfirmationComponentModule, + PwaBackComponentModule, + TextSpinnerComponentModule, + ], + declarations: [ + AppRestoreComponent, + ], + exports: [AppRestoreComponent], + +}) +export class AppRestoreComponentModule { } \ No newline at end of file diff --git a/ui/src/app/pages/apps-routes/app-restore/app-restore.page.scss b/ui/src/app/modals/app-restore/app-restore.component.scss similarity index 100% rename from ui/src/app/pages/apps-routes/app-restore/app-restore.page.scss rename to ui/src/app/modals/app-restore/app-restore.component.scss diff --git a/ui/src/app/pages/apps-routes/app-restore/app-restore.page.ts b/ui/src/app/modals/app-restore/app-restore.component.ts similarity index 73% rename from ui/src/app/pages/apps-routes/app-restore/app-restore.page.ts rename to ui/src/app/modals/app-restore/app-restore.component.ts index b694e1db6..ff3213ef4 100644 --- a/ui/src/app/pages/apps-routes/app-restore/app-restore.page.ts +++ b/ui/src/app/modals/app-restore/app-restore.component.ts @@ -1,31 +1,28 @@ -import { Component, ViewChild } from '@angular/core' -import { IonContent, LoadingController, ModalController } from '@ionic/angular' +import { Component, Input } from '@angular/core' +import { LoadingController, ModalController } from '@ionic/angular' import { ApiService } from 'src/app/services/api/embassy/embassy-api.service' import { BackupConfirmationComponent } from 'src/app/modals/backup-confirmation/backup-confirmation.component' import { DiskInfo } from 'src/app/services/api/api.types' -import { ActivatedRoute } from '@angular/router' import { PatchDbService } from 'src/app/services/patch-db/patch-db.service' import { Subscription } from 'rxjs' -import { take } from 'rxjs/operators' import { ErrorToastService } from 'src/app/services/error-toast.service' @Component({ selector: 'app-restore', - templateUrl: './app-restore.page.html', - styleUrls: ['./app-restore.page.scss'], + templateUrl: './app-restore.component.html', + styleUrls: ['./app-restore.component.scss'], }) -export class AppRestorePage { +export class AppRestoreComponent { + @Input() pkgId: string disks: DiskInfo - pkgId: string title: string loading = true + submitting = false allPartitionsMounted: boolean - @ViewChild(IonContent) content: IonContent subs: Subscription[] = [] constructor ( - private readonly route: ActivatedRoute, private readonly modalCtrl: ModalController, private readonly embassyApi: ApiService, private readonly loadingCtrl: LoadingController, @@ -34,13 +31,13 @@ export class AppRestorePage { ) { } ngOnInit () { - this.pkgId = this.route.snapshot.paramMap.get('pkgId') + console.log('initing') this.getExternalDisks() } - ngAfterViewInit () { - this.content.scrollToPoint(undefined, 1) - } + // ngAfterViewInit () { + // this.content.scrollToPoint(undefined, 1) + // } async refresh () { this.loading = true @@ -54,6 +51,7 @@ export class AppRestorePage { } catch (e) { this.errToast.present(e) } finally { + console.log('loading false') this.loading = false } } @@ -77,11 +75,14 @@ export class AppRestorePage { await m.present() } + dismiss () { + this.modalCtrl.dismiss({ }) + } + private async restore (logicalname: string, password: string): Promise { - const loader = await this.loadingCtrl.create({ - spinner: 'lines', - }) - await loader.present() + console.log('here here here') + this.submitting = true + // await loader.present() try { await this.embassyApi.restorePackage({ @@ -90,9 +91,9 @@ export class AppRestorePage { password, }) } catch (e) { - this.errToast.present(e) + this.modalCtrl.dismiss({ error: e }) } finally { - loader.dismiss() + this.modalCtrl.dismiss({ }) } } } diff --git a/ui/src/app/modals/backup-confirmation/backup-confirmation.component.html b/ui/src/app/modals/backup-confirmation/backup-confirmation.component.html index 4b115f653..33322e8e5 100644 --- a/ui/src/app/modals/backup-confirmation/backup-confirmation.component.html +++ b/ui/src/app/modals/backup-confirmation/backup-confirmation.component.html @@ -2,11 +2,11 @@

Encrypt Backup

-

Enter your master password to create an encrypted backup.

+

Enter your master password to create an encrypted backup.

Decrypt Backup

-

Enter the password that was originally used to encrypt this backup.

+

Enter the password that was originally used to encrypt this backup.

diff --git a/ui/src/app/pages/apps-routes/app-actions/app-actions.module.ts b/ui/src/app/pages/apps-routes/app-actions/app-actions.module.ts index a769ef9b9..8d5cb6e52 100644 --- a/ui/src/app/pages/apps-routes/app-actions/app-actions.module.ts +++ b/ui/src/app/pages/apps-routes/app-actions/app-actions.module.ts @@ -7,6 +7,7 @@ import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-b import { QRComponentModule } from 'src/app/components/qr/qr.component.module' import { SharingModule } from 'src/app/modules/sharing.module' import { AppActionInputPageModule } from 'src/app/modals/app-action-input/app-action-input.module' +import { AppRestoreComponentModule } from 'src/app/modals/app-restore/app-restore.component.module' const routes: Routes = [ { @@ -24,6 +25,7 @@ const routes: Routes = [ QRComponentModule, SharingModule, AppActionInputPageModule, + AppRestoreComponentModule, ], declarations: [AppActionsPage], }) diff --git a/ui/src/app/pages/apps-routes/app-actions/app-actions.page.html b/ui/src/app/pages/apps-routes/app-actions/app-actions.page.html index 0567483dd..db49895c2 100644 --- a/ui/src/app/pages/apps-routes/app-actions/app-actions.page.html +++ b/ui/src/app/pages/apps-routes/app-actions/app-actions.page.html @@ -7,9 +7,57 @@ + + - + + + + + + + + + + + {{ action.value.name }} + + + {{ action.value.description }} + + + + + + + + + + Restore From Backup + + + All changes since backup will be lost. + + + + + + + + + + Uninstall + + + This will uninstall the service from your Embassy and delete all data permanently. + + + + + + + \ No newline at end of file diff --git a/ui/src/app/pages/apps-routes/app-actions/app-actions.page.ts b/ui/src/app/pages/apps-routes/app-actions/app-actions.page.ts index 09bfe0f5f..7ac13751c 100644 --- a/ui/src/app/pages/apps-routes/app-actions/app-actions.page.ts +++ b/ui/src/app/pages/apps-routes/app-actions/app-actions.page.ts @@ -10,6 +10,7 @@ import { Subscription } from 'rxjs' import { ConfigCursor } from 'src/app/pkg-config/config-cursor' import { AppActionInputPage } from 'src/app/modals/app-action-input/app-action-input.page' import { ErrorToastService } from 'src/app/services/error-toast.service' +import { AppRestoreComponent } from 'src/app/modals/app-restore/app-restore.component' @Component({ selector: 'app-actions', @@ -79,7 +80,7 @@ export class AppActionsPage { await alert.present() } } else { - const statuses = [...action.value['allowedStatuses']] + const statuses = [...action.value['allowed-statuses']] const last = statuses.pop() let statusesStr = statuses.join(', ') let error = null @@ -103,6 +104,23 @@ export class AppActionsPage { } } + async restore (): Promise { + const m = await this.modalCtrl.create({ + componentProps: { + pkgId: this.pkgId, + }, + component: AppRestoreComponent, + backdropDismiss: false, + }) + + m.onWillDismiss().then(res => { + const data = res.data + if (data.error) this.errToast.present(data.error) + }) + + return await m.present() + } + async uninstall (manifest: Manifest) { const { id, title, version, alerts } = manifest const data = await wizardModal( @@ -134,7 +152,6 @@ export class AppActionsPage { header: 'Execution Complete', message: res.message.split('\n').join('

'), buttons: ['OK'], - cssClass: 'alert-success-message', }) await successAlert.present() } catch (e) { diff --git a/ui/src/app/pages/apps-routes/app-config/app-config.page.html b/ui/src/app/pages/apps-routes/app-config/app-config.page.html index 0674cb66e..97c9d0636 100644 --- a/ui/src/app/pages/apps-routes/app-config/app-config.page.html +++ b/ui/src/app/pages/apps-routes/app-config/app-config.page.html @@ -52,9 +52,9 @@

- + - + {{ rec.dependentTitle }}

diff --git a/ui/src/app/pages/apps-routes/app-config/app-config.page.ts b/ui/src/app/pages/apps-routes/app-config/app-config.page.ts index 1bfeae07d..f47146bd8 100644 --- a/ui/src/app/pages/apps-routes/app-config/app-config.page.ts +++ b/ui/src/app/pages/apps-routes/app-config/app-config.page.ts @@ -206,7 +206,6 @@ export class AppConfigPage { }, { text: `Leave`, - cssClass: 'alert-danger', handler: () => { this.navCtrl.back() }, diff --git a/ui/src/app/pages/apps-routes/app-interfaces/app-interfaces.page.html b/ui/src/app/pages/apps-routes/app-interfaces/app-interfaces.page.html index 57fc03920..1d82350a7 100644 --- a/ui/src/app/pages/apps-routes/app-interfaces/app-interfaces.page.html +++ b/ui/src/app/pages/apps-routes/app-interfaces/app-interfaces.page.html @@ -7,43 +7,37 @@ - - - - - - - {{ interface.value.name }} - {{ interface.value.description }} - - Launch - - - - - - - -

Tor Address

-

{{ 'http://' + int['tor-address'] }}

-
- - - -
- - -

LAN Address

-

{{ 'https://' + int['lan-address'] }}

-
- - - -
-
-
-
-
-
-
+ + + + {{ interface.value.name }} + {{ interface.value.description }} + + Launch + + + + + + + +

Tor Address

+

{{ 'http://' + int['tor-address'] }}

+
+ + + +
+ + +

LAN Address

+

{{ 'https://' + int['lan-address'] }}

+
+ + + +
+
+
+
\ No newline at end of file diff --git a/ui/src/app/pages/apps-routes/app-list/app-list.page.html b/ui/src/app/pages/apps-routes/app-list/app-list.page.html index baf87a241..abde30d58 100644 --- a/ui/src/app/pages/apps-routes/app-list/app-list.page.html +++ b/ui/src/app/pages/apps-routes/app-list/app-list.page.html @@ -10,10 +10,10 @@
-

Welcome to your Embassy

+

Welcome to Embassy

Get started by installing your first service.

- + Marketplace diff --git a/ui/src/app/pages/apps-routes/app-list/app-list.page.scss b/ui/src/app/pages/apps-routes/app-list/app-list.page.scss index 0678b11ce..a821184cb 100644 --- a/ui/src/app/pages/apps-routes/app-list/app-list.page.scss +++ b/ui/src/app/pages/apps-routes/app-list/app-list.page.scss @@ -25,7 +25,6 @@ .main-img { width: 50%; margin: 12px; - border-radius: var(--icon-border-radius); } .bulb-on { @@ -70,7 +69,7 @@ border-color: transparent; } ion-icon { - color: var(--ion-color-medium); + color: var(--ion-color-dark-shade); } } diff --git a/ui/src/app/pages/apps-routes/app-logs/app-logs.page.html b/ui/src/app/pages/apps-routes/app-logs/app-logs.page.html index 23a61df63..b6ca9e725 100644 --- a/ui/src/app/pages/apps-routes/app-logs/app-logs.page.html +++ b/ui/src/app/pages/apps-routes/app-logs/app-logs.page.html @@ -12,7 +12,7 @@ - + diff --git a/ui/src/app/pages/apps-routes/app-metrics/app-metrics.page.html b/ui/src/app/pages/apps-routes/app-metrics/app-metrics.page.html index a85baed77..5aee68a73 100644 --- a/ui/src/app/pages/apps-routes/app-metrics/app-metrics.page.html +++ b/ui/src/app/pages/apps-routes/app-metrics/app-metrics.page.html @@ -3,62 +3,19 @@ - Health + Monitor - + - - - - - Health Checks - - - - - - No health checks - - - - - -
- - - - - -

{{ health.key }}

-

{{ health.value.error }}

-
-
-
-
-
-
- - - - - - Metrics - - - - - - - - {{ metric.key }} - - - {{ metric.value.value }} {{ metric.value.unit }} - - - - - + + + + {{ metric.key }} + + {{ metric.value.value }} {{ metric.value.unit }} + + +
diff --git a/ui/src/app/pages/apps-routes/app-show/app-show.module.ts b/ui/src/app/pages/apps-routes/app-show/app-show.module.ts index 565484e3b..fdc51942e 100644 --- a/ui/src/app/pages/apps-routes/app-show/app-show.module.ts +++ b/ui/src/app/pages/apps-routes/app-show/app-show.module.ts @@ -6,7 +6,6 @@ import { AppShowPage } from './app-show.page' import { StatusComponentModule } from 'src/app/components/status/status.component.module' import { SharingModule } from 'src/app/modules/sharing.module' import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-back.component.module' -import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.module' import { InstallWizardComponentModule } from 'src/app/components/install-wizard/install-wizard.component.module' const routes: Routes = [ @@ -24,7 +23,6 @@ const routes: Routes = [ IonicModule, RouterModule.forChild(routes), PwaBackComponentModule, - BadgeMenuComponentModule, InstallWizardComponentModule, ], declarations: [AppShowPage], diff --git a/ui/src/app/pages/apps-routes/app-show/app-show.page.html b/ui/src/app/pages/apps-routes/app-show/app-show.page.html index c847f5e01..43a6b06a5 100644 --- a/ui/src/app/pages/apps-routes/app-show/app-show.page.html +++ b/ui/src/app/pages/apps-routes/app-show/app-show.page.html @@ -3,53 +3,118 @@ - Service Details - - - + + + + + +

+ {{ pkg.manifest.title }} +

+

{{ pkg.manifest.version | displayEmver }}

+
+
- + - -
- - - - - -

- {{ pkg.manifest.title }} -

-
{{ pkg.manifest.version | displayEmver }}
+ + + Status + + + - - -
- - - Configure - - - Stop - - - Fix - - - Start - -
- - - - Launch Web Interface + + Web - -
+ + Configure + + + Stop + + + Fix + + + Start + + + + + + + + Health Checks + + + + + + +

{{ health.key }}

+

{{ health.value.result }}

+

{{ health.value.error }}

+
+
+
+ + + Menu + + + {{ button.title }} + + + + + Dependencies + + + + + + +

{{ patch.data['package-data'][dep.key] ? patch.data['package-data'][dep.key].manifest.title : pkg.installed.status['dependency-errors'][dep.key]?.title }}

+

{{ pkg.manifest.dependencies[dep.key].version | displayEmver }}

+

{{ pkg.installed.status['dependency-errors'][dep.key] ? pkg.installed.status['dependency-errors'][dep.key].type : 'satisfied' }}

+
+ + + View + + + + + Install + + + + + Start + + + Update + + + Configure + + + +
+ +
+
+
+
+
+ + +

Downloading: {{ (pkg['install-progress'] | installState).downloadProgress }}%

- - - - - - - -
- -

- {{ button.title }} -
-
-
-
-
- - - - - Dependencies - - - - - - - - - -

{{ patch.data['package-data'][dep.key] ? patch.data['package-data'][dep.key].manifest.title : pkg.installed.status['dependency-errors'][dep.key]?.title }}

-

{{ pkg.manifest.dependencies[dep.key].version | displayEmver }}

-

{{ pkg.installed.status['dependency-errors'][dep.key] ? pkg.installed.status['dependency-errors'][dep.key].type : 'satisfied' }}

-
- - - View - - - - - Install - - - - - Start - - - Update - - - Configure - - - -
- -
-
-
-
-
-
-
-
-
diff --git a/ui/src/app/pages/apps-routes/app-show/app-show.page.scss b/ui/src/app/pages/apps-routes/app-show/app-show.page.scss index 4eaf15be4..504da9ea1 100644 --- a/ui/src/app/pages/apps-routes/app-show/app-show.page.scss +++ b/ui/src/app/pages/apps-routes/app-show/app-show.page.scss @@ -1,45 +1,14 @@ .less-large { - font-size: 20px !important; + font-size: 18px !important; } -.top-plate { - background: var(--ion-item-background); - margin: 0 16px; - padding: 12px; - border-radius: 10px; - border-style: solid; - border-color: #373737; - ion-item { - border-radius: 10px; - } -} - -.status-readout { - --background: transparent; - display: flex; - justify-content: space-between; - padding: 8px 16px; - border-radius: 10px; - align-items: center; - background: var(--ion-background-color); +.action-button { margin: 10px; - border-style: solid; - border-width: 1px; - border-color: #404040; + min-height: 36px; + min-width: 72px; } -.launch-button { - --background: rgb(70 193 255 / 75%); - --background-hover: rgb(70 193 255); - --background-hover-opacity: 100%; - --border-style: none; - --color: white; - --border-radius: 10px; - margin: 12px 10px; -} - -.dep-card { - border-radius: 10px; - border-style: solid; - border-color: #404040; -} +.icon-spinner { + height: 20px; + width: 20px; +} \ No newline at end of file diff --git a/ui/src/app/pages/apps-routes/app-show/app-show.page.ts b/ui/src/app/pages/apps-routes/app-show/app-show.page.ts index 65f234782..0b1c6e51b 100644 --- a/ui/src/app/pages/apps-routes/app-show/app-show.page.ts +++ b/ui/src/app/pages/apps-routes/app-show/app-show.page.ts @@ -8,7 +8,7 @@ import { wizardModal } from 'src/app/components/install-wizard/install-wizard.co import { WizardBaker } from 'src/app/components/install-wizard/prebaked-wizards' import { ConfigService } from 'src/app/services/config.service' import { PatchDbService } from 'src/app/services/patch-db/patch-db.service' -import { DependencyErrorConfigUnsatisfied, DependencyErrorNotInstalled, DependencyErrorType, PackageDataEntry, PackageState } from 'src/app/services/patch-db/data-model' +import { DependencyErrorConfigUnsatisfied, DependencyErrorNotInstalled, DependencyErrorType, MainStatus, PackageDataEntry, PackageState } from 'src/app/services/patch-db/data-model' import { FEStatus, PkgStatusRendering, renderPkgStatus } from 'src/app/services/pkg-status-rendering.service' import { ConnectionService } from 'src/app/services/connection.service' import { ErrorToastService } from 'src/app/services/error-toast.service' @@ -29,6 +29,8 @@ export class AppShowPage { DependencyErrorType = DependencyErrorType rendering: PkgStatusRendering Math = Math + mainStatus: MainStatus + @ViewChild(IonContent) content: IonContent subs: Subscription[] = [] @@ -59,6 +61,11 @@ export class AppShowPage { this.connected = connected this.rendering = renderPkgStatus(pkg.state, pkg.installed.status) }), + this.patch.watch$('package-data', this.pkgId, 'installed', 'status', 'main') + .subscribe(main => { + this.mainStatus = main + console.log(this.mainStatus) + }), ] this.setButtons() } @@ -236,17 +243,9 @@ export class AppShowPage { color: 'danger', disabled: [], }, - { - action: () => this.navCtrl.navigateForward(['metrics'], { relativeTo: this.route }), - title: 'Monitor', - icon: 'medkit-outline', - color: 'danger', - // @TODO make the disabled check better. Don't want to list every status here. Monitor should be disabled except is pkg is running. - disabled: [FEStatus.Installing, FEStatus.Updating, FEStatus.Removing, FEStatus.BackingUp, FEStatus.Restoring], - }, { action: () => this.navCtrl.navigateForward(['config'], { relativeTo: this.route }), - title: 'Configure', + title: 'Settings', icon: 'construct-outline', color: 'danger', disabled: [FEStatus.Installing, FEStatus.Updating, FEStatus.Removing, FEStatus.BackingUp, FEStatus.Restoring], @@ -272,6 +271,14 @@ export class AppShowPage { color: 'danger', disabled: [], }, + { + action: () => this.navCtrl.navigateForward(['metrics'], { relativeTo: this.route }), + title: 'Monitor', + icon: 'pulse-outline', + color: 'danger', + // @TODO make the disabled check better. Don't want to list every status here. Monitor should be disabled except is pkg is running. + disabled: [FEStatus.Installing, FEStatus.Updating, FEStatus.Removing, FEStatus.BackingUp, FEStatus.Restoring], + }, { action: () => this.navCtrl.navigateForward(['logs'], { relativeTo: this.route }), title: 'Logs', @@ -279,13 +286,6 @@ export class AppShowPage { color: 'danger', disabled: [], }, - { - action: () => this.navCtrl.navigateForward(['restore'], { relativeTo: this.route }), - title: 'Restore From Backup', - icon: 'color-wand-outline', - color: 'danger', - disabled: [FEStatus.Connecting, FEStatus.Installing, FEStatus.Updating, FEStatus.Stopping, FEStatus.Removing, FEStatus.BackingUp, FEStatus.Restoring], - }, { action: () => this.navCtrl.navigateForward(['manifest'], { relativeTo: this.route }), title: 'Package Details', @@ -295,18 +295,11 @@ export class AppShowPage { }, { action: () => this.donate(), - title: 'Support Project', + title: 'Donate', icon: 'logo-bitcoin', color: 'danger', disabled: [], }, - { - action: () => this.navCtrl.navigateForward(['/marketplace', this.pkgId], { relativeTo: this.route }), - title: 'Marketplace Listing', - icon: 'storefront-outline', - color: 'danger', - disabled: [], - }, ] } } diff --git a/ui/src/app/pages/apps-routes/apps-routing.module.ts b/ui/src/app/pages/apps-routes/apps-routing.module.ts index 05ae01bc0..7816170c1 100644 --- a/ui/src/app/pages/apps-routes/apps-routing.module.ts +++ b/ui/src/app/pages/apps-routes/apps-routing.module.ts @@ -51,10 +51,6 @@ const routes: Routes = [ path: ':pkgId/properties', loadChildren: () => import('./app-properties/app-properties.module').then(m => m.AppPropertiesPageModule), }, - { - path: ':pkgId/restore', - loadChildren: () => import('./app-restore/app-restore.module').then(m => m.AppRestorePageModule), - }, ] @NgModule({ diff --git a/ui/src/app/pages/login/login.page.html b/ui/src/app/pages/login/login.page.html index c90bc5177..ef6a33ed2 100644 --- a/ui/src/app/pages/login/login.page.html +++ b/ui/src/app/pages/login/login.page.html @@ -1,31 +1,35 @@ - - + + - - -
- - - - -
- - - - - - - - - {{ error }} - - - - Next - -
-
-
+ + +
+ +
+ + + + Log in to Embassy + + + +
+ +

Password

+ + + + + + + +

{{ error }}

+
+ +
+
diff --git a/ui/src/app/pages/login/login.page.scss b/ui/src/app/pages/login/login.page.scss index 3f4f0de05..eca54b7a1 100644 --- a/ui/src/app/pages/login/login.page.scss +++ b/ui/src/app/pages/login/login.page.scss @@ -1,3 +1,28 @@ -.sharp-button { - --border-radius: 1px; +ion-card-title { + margin: 24px 0; + font-family: 'Montserrat'; + font-size: x-large; + --color: var(--ion-color-light); +} + +ion-item { + --border-radius: 4px; + --border-style: solid; + --border-width: 1px; + --border-color: var(--ion-color-light); +} + +.input-label { + text-align: left; + padding-bottom: 2px; + font-size: small; + font-weight: bold; +} + +.login-button { + margin-inline-start: 0; + margin-inline-end: 0; + margin-top: 24px; + height: 48px; + --background: linear-gradient(45deg, var(--ion-color-light) 16%, var(--ion-color-dark) 150%); } \ No newline at end of file diff --git a/ui/src/app/pages/login/login.page.ts b/ui/src/app/pages/login/login.page.ts index f0efb80d1..dd40cbd80 100644 --- a/ui/src/app/pages/login/login.page.ts +++ b/ui/src/app/pages/login/login.page.ts @@ -33,7 +33,7 @@ export class LoginPage { this.error = '' this.loader = await this.loadingCtrl.create({ - message: 'Authenticating', + message: 'Logging in', spinner: 'lines', }) await this.loader.present() diff --git a/ui/src/app/pages/marketplace-routes/app-release-notes/app-release-notes.page.html b/ui/src/app/pages/marketplace-routes/app-release-notes/app-release-notes.page.html index e6fd347b6..a42d165e9 100644 --- a/ui/src/app/pages/marketplace-routes/app-release-notes/app-release-notes.page.html +++ b/ui/src/app/pages/marketplace-routes/app-release-notes/app-release-notes.page.html @@ -11,11 +11,23 @@ -
- +
+

{{ note.key | displayEmver }}

- +
diff --git a/ui/src/app/pages/marketplace-routes/app-release-notes/app-release-notes.page.scss b/ui/src/app/pages/marketplace-routes/app-release-notes/app-release-notes.page.scss index 7a499cb08..e122c8b4b 100644 --- a/ui/src/app/pages/marketplace-routes/app-release-notes/app-release-notes.page.scss +++ b/ui/src/app/pages/marketplace-routes/app-release-notes/app-release-notes.page.scss @@ -1,8 +1,8 @@ -.metric-note { - font-size: 16px; +.panel { + margin: 0px; + padding: 0px 24px; } -.acc-text { - margin: 0px 0px 10px 0px; - padding: 15px; +.active { + border: 5px solid #4d4d4d; } \ No newline at end of file diff --git a/ui/src/app/pages/marketplace-routes/app-release-notes/app-release-notes.page.ts b/ui/src/app/pages/marketplace-routes/app-release-notes/app-release-notes.page.ts index aaa52d4b4..7621c8494 100644 --- a/ui/src/app/pages/marketplace-routes/app-release-notes/app-release-notes.page.ts +++ b/ui/src/app/pages/marketplace-routes/app-release-notes/app-release-notes.page.ts @@ -37,6 +37,11 @@ export class AppReleaseNotes { } } + getDocSize (selected: string) { + const element = document.getElementById(selected) + return `${element.scrollHeight}px` + } + asIsOrder (a: any, b: any) { return 0 } diff --git a/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.page.html b/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.page.html index 17e93fbe4..0113c999f 100644 --- a/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.page.html +++ b/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.page.html @@ -1,59 +1,59 @@ - - Service Marketplace + + - - - - + - - - Now Available... - EmbassyOS Version {{ eos.version }} - - - {{ eos.headline }} - - +

Embassy Marketplace

-

Categories

- -
+
{{ cat }}
+
+
- +
+ + + + + + +

Now Available...

+

Embassy OS {{ eos.version }}

+

{{ eos.headline }}

+
+
+
-

{{ pkg.manifest.title }}

-

{{ pkg.manifest.description.short }}

- +

{{ pkg.manifest.title }}

+

{{ pkg.manifest.description.short }}

+

Installed Update Available @@ -66,6 +66,9 @@

+ +

Not Installed

+
diff --git a/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.page.scss b/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.page.scss index 595a7579d..d1ba64ed8 100644 --- a/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.page.scss +++ b/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.page.scss @@ -2,7 +2,7 @@ overflow: auto; white-space: nowrap; // background-color: var(--ion-color-light); - height: 80px; + height: 60px; /* Hide scrollbar for Chrome, Safari and Opera */ ::-webkit-scrollbar { @@ -14,14 +14,16 @@ scrollbar-width: none; /* Firefox */ } -.eos-card { - --background: linear-gradient(45deg, #101010 16%, var(--ion-color-danger) 150%); - margin: 0 10px 16px 10px; - cursor: pointer; +.eos-item { + --border-style: none; + --background: linear-gradient(45deg, var(--ion-color-dark) -380%, var(--ion-color-medium) 100%) } -.cat-selected { - border-width: 0 0 1px 0; - border-style: solid; - border-color: var(--ion-color-primary); +.selected { + font-weight: bold; +} + +.dim { + font-weight: 300; + color: var(--ion-color-dark-shade); } diff --git a/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show.module.ts b/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show.module.ts index 54c0ec21c..7023a22e8 100644 --- a/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show.module.ts +++ b/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show.module.ts @@ -5,7 +5,6 @@ import { IonicModule } from '@ionic/angular' import { MarketplaceShowPage } from './marketplace-show.page' import { SharingModule } from 'src/app/modules/sharing.module' import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-back.component.module' -import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.module' import { StatusComponentModule } from 'src/app/components/status/status.component.module' import { InstallWizardComponentModule } from 'src/app/components/install-wizard/install-wizard.component.module' import { TextSpinnerComponentModule } from 'src/app/components/text-spinner/text-spinner.component.module' @@ -26,7 +25,6 @@ const routes: Routes = [ RouterModule.forChild(routes), SharingModule, PwaBackComponentModule, - BadgeMenuComponentModule, InstallWizardComponentModule, ], declarations: [MarketplaceShowPage], diff --git a/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show.page.html b/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show.page.html index 2ff0e04e2..bdd67a882 100644 --- a/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show.page.html +++ b/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show.page.html @@ -4,9 +4,6 @@ Listing - - - @@ -27,13 +24,14 @@

- Not Installed + Not Installed

- Installed at {{ localPkg.manifest.version | displayEmver }} + Installed + Update Available

@@ -51,17 +49,17 @@ - + Install - + Update - + Downgrade @@ -74,9 +72,9 @@

- + - + {{ rec.dependentTitle }}

diff --git a/ui/src/app/pages/notifications/notifications.module.ts b/ui/src/app/pages/notifications/notifications.module.ts index 7cbcf5c40..0aaf655cf 100644 --- a/ui/src/app/pages/notifications/notifications.module.ts +++ b/ui/src/app/pages/notifications/notifications.module.ts @@ -6,6 +6,7 @@ import { NotificationsPage } from './notifications.page' import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-back.component.module' import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.module' import { SharingModule } from 'src/app/modules/sharing.module' +import { TextSpinnerComponentModule } from 'src/app/components/text-spinner/text-spinner.component.module' const routes: Routes = [ { @@ -22,6 +23,7 @@ const routes: Routes = [ PwaBackComponentModule, BadgeMenuComponentModule, SharingModule, + TextSpinnerComponentModule, ], declarations: [NotificationsPage], }) diff --git a/ui/src/app/pages/notifications/notifications.page.html b/ui/src/app/pages/notifications/notifications.page.html index db6deade7..ae6351eed 100644 --- a/ui/src/app/pages/notifications/notifications.page.html +++ b/ui/src/app/pages/notifications/notifications.page.html @@ -15,14 +15,12 @@ - + -

- Notifications about Embassy and services will appear here. -

+ Notifications about Embassy and services will appear here.
@@ -47,7 +45,7 @@

- + diff --git a/ui/src/app/pages/server-routes/security-routes/security-options/security-options.page.html b/ui/src/app/pages/server-routes/security-routes/security-options/security-options.page.html index 1bc181e2b..287159381 100644 --- a/ui/src/app/pages/server-routes/security-routes/security-options/security-options.page.html +++ b/ui/src/app/pages/server-routes/security-routes/security-options/security-options.page.html @@ -38,6 +38,9 @@ SSH Keys + + Active Sessions + \ No newline at end of file diff --git a/ui/src/app/pages/server-routes/security-routes/security-routing.module.ts b/ui/src/app/pages/server-routes/security-routes/security-routing.module.ts index 92ccf1dbd..8bcccafd8 100644 --- a/ui/src/app/pages/server-routes/security-routes/security-routing.module.ts +++ b/ui/src/app/pages/server-routes/security-routes/security-routing.module.ts @@ -6,6 +6,10 @@ const routes: Routes = [ path: '', loadChildren: () => import('./security-options/security-options.module').then(m => m.SecurityOptionsPageModule), }, + { + path: 'sessions', + loadChildren: () => import('./sessions/sessions.module').then(m => m.SessionsPageModule), + }, { path: 'ssh-keys', loadChildren: () => import('./ssh-keys/ssh-keys.module').then(m => m.SSHKeysPageModule), diff --git a/ui/src/app/pages/apps-routes/app-restore/app-restore.module.ts b/ui/src/app/pages/server-routes/security-routes/sessions/sessions.module.ts similarity index 68% rename from ui/src/app/pages/apps-routes/app-restore/app-restore.module.ts rename to ui/src/app/pages/server-routes/security-routes/sessions/sessions.module.ts index 965ddf52b..a8006122d 100644 --- a/ui/src/app/pages/apps-routes/app-restore/app-restore.module.ts +++ b/ui/src/app/pages/server-routes/security-routes/sessions/sessions.module.ts @@ -1,17 +1,16 @@ import { NgModule } from '@angular/core' import { CommonModule } from '@angular/common' import { IonicModule } from '@ionic/angular' -import { AppRestorePage } from './app-restore.page' import { RouterModule, Routes } from '@angular/router' +import { SessionsPage } from './sessions.page' import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-back.component.module' -import { BackupConfirmationComponentModule } from 'src/app/modals/backup-confirmation/backup-confirmation.component.module' import { SharingModule } from 'src/app/modules/sharing.module' import { TextSpinnerComponentModule } from 'src/app/components/text-spinner/text-spinner.component.module' const routes: Routes = [ { path: '', - component: AppRestorePage, + component: SessionsPage, }, ] @@ -19,14 +18,11 @@ const routes: Routes = [ imports: [ CommonModule, IonicModule, - SharingModule, RouterModule.forChild(routes), - BackupConfirmationComponentModule, PwaBackComponentModule, + SharingModule, TextSpinnerComponentModule, ], - declarations: [ - AppRestorePage, - ], + declarations: [SessionsPage], }) -export class AppRestorePageModule { } \ No newline at end of file +export class SessionsPageModule { } diff --git a/ui/src/app/pages/server-routes/security-routes/sessions/sessions.page.html b/ui/src/app/pages/server-routes/security-routes/sessions/sessions.page.html new file mode 100644 index 000000000..331171c7a --- /dev/null +++ b/ui/src/app/pages/server-routes/security-routes/sessions/sessions.page.html @@ -0,0 +1,41 @@ + + + + + + Active Sessions + + + + + + + + + Current Session + + + +

{{ getPlatformName(current.metadata.platforms) }}

+

Last Active: {{ current['last-active'] | date : 'medium' }}

+

{{ current['user-agent'] }}

+
+
+ + Other Sessions +
+ + + +

{{ getPlatformName(session.value.metadata.platforms) }}

+

Last Active: {{ session.value['last-active'] | date : 'medium' }}

+

{{ session.value['user-agent'] }}

+
+ + + +
+
+
+ +
\ No newline at end of file diff --git a/ui/src/app/pages/server-routes/security-routes/sessions/sessions.page.scss b/ui/src/app/pages/server-routes/security-routes/sessions/sessions.page.scss new file mode 100644 index 000000000..e69de29bb diff --git a/ui/src/app/pages/server-routes/security-routes/sessions/sessions.page.ts b/ui/src/app/pages/server-routes/security-routes/sessions/sessions.page.ts new file mode 100644 index 000000000..bfba3f89b --- /dev/null +++ b/ui/src/app/pages/server-routes/security-routes/sessions/sessions.page.ts @@ -0,0 +1,99 @@ +import { Component } from '@angular/core' +import { AlertController, getPlatforms, LoadingController } from '@ionic/angular' +import { ErrorToastService } from 'src/app/services/error-toast.service' +import { ApiService } from 'src/app/services/api/embassy/embassy-api.service' +import { PlatformType, RR, SessionMetadata } from 'src/app/services/api/api.types' + +@Component({ + selector: 'sessions', + templateUrl: 'sessions.page.html', + styleUrls: ['sessions.page.scss'], +}) +export class SessionsPage { + loading = true + sessionInfo: RR.GetSessionsRes + + constructor ( + private readonly loadingCtrl: LoadingController, + private readonly errToast: ErrorToastService, + private readonly alertCtrl: AlertController, + private readonly embassyApi: ApiService, + ) { } + + async ngOnInit () { + getPlatforms() + this.sessionInfo = await this.embassyApi.getSessions({ }) + this.loading = false + } + + async presentAlertKill (hash: string) { + const alert = await this.alertCtrl.create({ + backdropDismiss: false, + header: 'Caution', + message: `Are you sure you want to kill this session?`, + buttons: [ + { + text: 'Cancel', + role: 'cancel', + }, + { + text: 'Kill', + handler: () => { + this.kill(hash) + }, + }, + ], + }) + await alert.present() + } + + async kill (hash: string): Promise { + const loader = await this.loadingCtrl.create({ + spinner: 'lines', + message: 'Killing session...', + cssClass: 'loader', + }) + await loader.present() + + try { + await this.embassyApi.killSessions({ hashes: [hash] }) + delete this.sessionInfo.sessions[hash] + } catch (e) { + this.errToast.present(e) + } finally { + loader.dismiss() + } + } + + getPlatformIcon (platforms: PlatformType[]): string { + if (platforms.includes('cli')) { + return 'terminal-outline' + } else if (platforms.includes('desktop')) { + return 'desktop-outline' + } else { + return 'phone-portrait-outline' + } + } + + getPlatformName (platforms: PlatformType[]): string { + if (platforms.includes('cli')) { + return 'CLI' + } else if (platforms.includes('desktop')) { + return 'Desktop/Laptop' + } else if (platforms.includes('android')) { + return 'Android Device' + } else if (platforms.includes('iphone')) { + return 'iPhone' + } else if (platforms.includes('ipad')) { + return 'iPad' + } else if (platforms.includes('ios')) { + return 'iOS Device' + } else { + return 'Unknown Device' + } + } + + asIsOrder (a: any, b: any) { + return 0 + } +} diff --git a/ui/src/app/pages/server-routes/security-routes/ssh-keys/ssh-keys.page.html b/ui/src/app/pages/server-routes/security-routes/ssh-keys/ssh-keys.page.html index b851aa581..0572593d8 100644 --- a/ui/src/app/pages/server-routes/security-routes/ssh-keys/ssh-keys.page.html +++ b/ui/src/app/pages/server-routes/security-routes/ssh-keys/ssh-keys.page.html @@ -22,7 +22,7 @@ {{ ssh.value.alg }} {{ ssh.key }} {{ ssh.value.hostname }} - + diff --git a/ui/src/app/pages/server-routes/security-routes/ssh-keys/ssh-keys.page.ts b/ui/src/app/pages/server-routes/security-routes/ssh-keys/ssh-keys.page.ts index 662c16f81..7e2beeb3f 100644 --- a/ui/src/app/pages/server-routes/security-routes/ssh-keys/ssh-keys.page.ts +++ b/ui/src/app/pages/server-routes/security-routes/ssh-keys/ssh-keys.page.ts @@ -57,7 +57,6 @@ export class SSHKeysPage { }, { text: 'Delete', - cssClass: 'alert-danger', handler: () => { this.delete(hash) }, diff --git a/ui/src/app/pages/server-routes/server-logs/server-logs.page.html b/ui/src/app/pages/server-routes/server-logs/server-logs.page.html index 6747d77a8..dd90d13d2 100644 --- a/ui/src/app/pages/server-routes/server-logs/server-logs.page.html +++ b/ui/src/app/pages/server-routes/server-logs/server-logs.page.html @@ -12,7 +12,7 @@ - + diff --git a/ui/src/app/pages/server-routes/server-metrics/server-metrics.page.html b/ui/src/app/pages/server-routes/server-metrics/server-metrics.page.html index 895b2bb6c..082c4e4cf 100644 --- a/ui/src/app/pages/server-routes/server-metrics/server-metrics.page.html +++ b/ui/src/app/pages/server-routes/server-metrics/server-metrics.page.html @@ -7,16 +7,14 @@ - + - {{ metricGroup.key }} + {{ metricGroup.key }} - - {{ metric.key }} - + {{ metric.key }} {{ metric.value.value }} {{ metric.value.unit }} diff --git a/ui/src/app/pages/server-routes/server-metrics/server-metrics.page.scss b/ui/src/app/pages/server-routes/server-metrics/server-metrics.page.scss index eea898305..bee398a1b 100644 --- a/ui/src/app/pages/server-routes/server-metrics/server-metrics.page.scss +++ b/ui/src/app/pages/server-routes/server-metrics/server-metrics.page.scss @@ -1,3 +1,3 @@ .metric-note { font-size: 16px; -} \ No newline at end of file +} diff --git a/ui/src/app/pages/server-routes/server-show/server-show.page.html b/ui/src/app/pages/server-routes/server-show/server-show.page.html index 872b39284..b33060521 100644 --- a/ui/src/app/pages/server-routes/server-show/server-show.page.html +++ b/ui/src/app/pages/server-routes/server-show/server-show.page.html @@ -7,12 +7,11 @@ - - +
- {{ cat.key }} - + {{ cat.key }} + {{ button.title }} diff --git a/ui/src/app/pages/server-routes/server-show/server-show.page.ts b/ui/src/app/pages/server-routes/server-show/server-show.page.ts index b0d33d0a8..c2abedb70 100644 --- a/ui/src/app/pages/server-routes/server-show/server-show.page.ts +++ b/ui/src/app/pages/server-routes/server-show/server-show.page.ts @@ -37,7 +37,6 @@ export class ServerShowPage { }, { text: 'Restart', - cssClass: 'alert-danger', handler: () => { this.restart() }, @@ -59,7 +58,6 @@ export class ServerShowPage { }, { text: 'Shutdown', - cssClass: 'alert-danger', handler: () => { this.shutdown() }, @@ -110,16 +108,19 @@ export class ServerShowPage { title: 'Privacy and Security', icon: 'shield-checkmark-outline', action: () => this.navCtrl.navigateForward(['security'], { relativeTo: this.route }), + detail: true, }, { title: 'LAN', icon: 'home-outline', action: () => this.navCtrl.navigateForward(['lan'], { relativeTo: this.route }), + detail: true, }, { title: 'WiFi', icon: 'wifi', action: () => this.navCtrl.navigateForward(['wifi'], { relativeTo: this.route }), + detail: true, }, ], 'Insights': [ @@ -127,16 +128,19 @@ export class ServerShowPage { title: 'About', icon: 'information-circle-outline', action: () => this.navCtrl.navigateForward(['specs'], { relativeTo: this.route }), + detail: true, }, { title: 'Monitor', icon: 'pulse', action: () => this.navCtrl.navigateForward(['metrics'], { relativeTo: this.route }), + detail: true, }, { title: 'Logs', icon: 'newspaper-outline', action: () => this.navCtrl.navigateForward(['logs'], { relativeTo: this.route }), + detail: true, }, ], 'Backups': [ @@ -144,6 +148,7 @@ export class ServerShowPage { title: 'Create Backup', icon: 'save-outline', action: () => this.navCtrl.navigateForward(['backup'], { relativeTo: this.route }), + detail: true, }, ], 'Power': [ @@ -151,11 +156,13 @@ export class ServerShowPage { title: 'Restart', icon: 'reload-outline', action: () => this.presentAlertRestart(), + detail: false, }, { title: 'Shutdown', icon: 'power', action: () => this.presentAlertShutdown(), + detail: false, }, ], } @@ -171,5 +178,6 @@ interface ServerSettings { title: string icon: string action: Function + detail: boolean }[] } diff --git a/ui/src/app/pages/server-routes/server-specs/server-specs.page.html b/ui/src/app/pages/server-routes/server-specs/server-specs.page.html index 7246ce56b..110a56c29 100644 --- a/ui/src/app/pages/server-routes/server-specs/server-specs.page.html +++ b/ui/src/app/pages/server-routes/server-specs/server-specs.page.html @@ -14,7 +14,7 @@ -

Version

+

EmbassyOS Version

{{ server.version | displayEmver }}

diff --git a/ui/src/app/pages/server-routes/wifi/wifi.page.ts b/ui/src/app/pages/server-routes/wifi/wifi.page.ts index 14a82d7db..c4614c2a9 100644 --- a/ui/src/app/pages/server-routes/wifi/wifi.page.ts +++ b/ui/src/app/pages/server-routes/wifi/wifi.page.ts @@ -29,7 +29,6 @@ export class WifiListPage { const buttons: ActionSheetButton[] = [ { text: 'Forget', - cssClass: 'alert-danger', handler: () => { this.delete(ssid) }, diff --git a/ui/src/app/services/api/api.fixures.ts b/ui/src/app/services/api/api.fixures.ts index 70c9d03a8..ff8987501 100644 --- a/ui/src/app/services/api/api.fixures.ts +++ b/ui/src/app/services/api/api.fixures.ts @@ -739,6 +739,26 @@ export module Mock { }, ] + export const Sessions: RR.GetSessionsRes = { + current: 'b7b1a9cef4284f00af9e9dda6e676177', + sessions: { + '9513226517c54ddd8107d6d7b9d8aed7': { + 'last-active': '2021-07-14T20:49:17.774Z', + 'user-agent': 'AppleWebKit/{WebKit Rev} (KHTML, like Gecko)', + metadata: { + platforms: ['iphone', 'mobileweb', 'mobile', 'ios'], + }, + }, + 'b7b1a9cef4284f00af9e9dda6e676177': { + 'last-active': '2021-06-14T20:49:17.774Z', + 'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0', + metadata: { + platforms: ['desktop'], + }, + }, + }, + } + export const SshKeys: RR.GetSSHKeysRes = { '28:d2:7e:78:61:b4:bf:g2:de:24:15:96:4e:d4:15:53': { alg: 'ed25519', diff --git a/ui/src/app/services/api/api.types.ts b/ui/src/app/services/api/api.types.ts index f452fae9e..6e25cd8d5 100644 --- a/ui/src/app/services/api/api.types.ts +++ b/ui/src/app/services/api/api.types.ts @@ -16,7 +16,7 @@ export module RR { // auth - export type LoginReq = { password: string } // auth.login - unauthed + export type LoginReq = { password: string, metadata: SessionMetadata } // auth.login - unauthed export type loginRes = null export type LogoutReq = { } // auth.logout @@ -47,6 +47,17 @@ export module RR { export type RefreshLanReq = { } // network.lan.refresh export type RefreshLanRes = null + // sessions + + export type GetSessionsReq = { } // sessions.list + export type GetSessionsRes = { + current: string, + sessions: { [hash: string]: Session } + } + + export type KillSessionsReq = WithExpire<{ hashes: string[] }> // sessions.kill + export type KillSessionsRes = WithRevision + // marketplace URLs export type SetEosMarketplaceReq = WithExpire<{ url: string }> // marketplace.eos.set @@ -253,6 +264,18 @@ export interface Metric { } } +export interface Session { + 'last-active': string + 'user-agent': string + metadata: SessionMetadata +} + +export interface SessionMetadata { + platforms: PlatformType[] +} + +export type PlatformType = 'cli' | 'ios' | 'ipad' | 'iphone' | 'android' | 'phablet' | 'tablet' | 'cordova' | 'capacitor' | 'electron' | 'pwa' | 'mobile' | 'mobileweb' | 'desktop' | 'hybrid' + export interface DiskInfo { [id: string]: DiskInfoEntry } diff --git a/ui/src/app/services/api/embassy/embassy-api.service.ts b/ui/src/app/services/api/embassy/embassy-api.service.ts index eadbe58a7..fcb27b42a 100644 --- a/ui/src/app/services/api/embassy/embassy-api.service.ts +++ b/ui/src/app/services/api/embassy/embassy-api.service.ts @@ -32,6 +32,10 @@ export abstract class ApiService implements Source, Http { abstract logout (params: RR.LogoutReq): Promise + abstract getSessions (params: RR.GetSessionsReq): Promise + + abstract killSessions (params: RR.KillSessionsReq): Promise + // server protected abstract setShareStatsRaw (params: RR.SetShareStatsReq): Promise diff --git a/ui/src/app/services/api/embassy/embassy-live-api.service.ts b/ui/src/app/services/api/embassy/embassy-live-api.service.ts index fa942e58b..1c395798e 100644 --- a/ui/src/app/services/api/embassy/embassy-live-api.service.ts +++ b/ui/src/app/services/api/embassy/embassy-live-api.service.ts @@ -41,6 +41,14 @@ export class LiveApiService extends ApiService { return this.http.rpcRequest({ method: 'auth.logout', params }) } + async getSessions (params: RR.GetSessionsReq): Promise { + return this.http.rpcRequest({ method: 'auth.session.list', params }) + } + + async killSessions (params: RR.KillSessionsReq): Promise { + return this.http.rpcRequest({ method: 'auth.session.kill', params }) + } + // server async setShareStatsRaw (params: RR.SetShareStatsReq): Promise { diff --git a/ui/src/app/services/api/embassy/embassy-mock-api.service.ts b/ui/src/app/services/api/embassy/embassy-mock-api.service.ts index 6e29b7ddc..97aebdc9d 100644 --- a/ui/src/app/services/api/embassy/embassy-mock-api.service.ts +++ b/ui/src/app/services/api/embassy/embassy-mock-api.service.ts @@ -50,6 +50,16 @@ export class MockApiService extends ApiService { return null } + async getSessions (params: RR.GetSessionsReq): Promise { + await pauseFor(2000) + return Mock.Sessions + } + + async killSessions (params: RR.KillSessionsReq): Promise { + await pauseFor(2000) + return null + } + // server async setShareStatsRaw (params: RR.SetShareStatsReq): Promise { diff --git a/ui/src/app/services/auth.service.ts b/ui/src/app/services/auth.service.ts index 12136c207..248886f3f 100644 --- a/ui/src/app/services/auth.service.ts +++ b/ui/src/app/services/auth.service.ts @@ -3,6 +3,7 @@ import { BehaviorSubject, Observable } from 'rxjs' import { distinctUntilChanged } from 'rxjs/operators' import { ApiService } from './api/embassy/embassy-api.service' import { Storage } from '@ionic/storage' +import { getPlatforms, isPlatform } from '@ionic/angular' export enum AuthState { UNVERIFIED, @@ -31,7 +32,10 @@ export class AuthService { } async login (password: string): Promise { - await this.embassyApi.login({ password }) + await this.embassyApi.login({ + password, + metadata: { platforms: getPlatforms() }, + }) await this.storage.set(this.LOGGED_IN_KEY, true) this.authState$.next(AuthState.VERIFIED) } diff --git a/ui/src/app/services/config.service.ts b/ui/src/app/services/config.service.ts index 1f2727448..adb429747 100644 --- a/ui/src/app/services/config.service.ts +++ b/ui/src/app/services/config.service.ts @@ -67,6 +67,7 @@ export class ConfigService { } launchableURL (pkg: PackageDataEntry): string { + console.log('PKGPKGPKG', pkg) return this.isTor() ? `http://${torUiAddress(pkg)}` : `https://${lanUiAddress(pkg)}` } } @@ -85,7 +86,7 @@ export function torUiAddress (pkg: PackageDataEntry): string { const val = interfaces[key] return val.ui && val['tor-config'] }) - return pkg['interface-info'].addresses[id]['tor-address'] + return pkg.installed['interface-info'].addresses[id]['tor-address'] } export function lanUiAddress (pkg: PackageDataEntry): string { @@ -94,7 +95,7 @@ export function lanUiAddress (pkg: PackageDataEntry): string { const val = interfaces[key] return val.ui && val['lan-config'] }) - return pkg['interface-info'].addresses[id]['lan-address'] + return pkg.installed['interface-info'].addresses[id]['lan-address'] } export function hasUi (interfaces: { [id: string]: InterfaceDef }): boolean { diff --git a/ui/src/assets/img/icon.png b/ui/src/assets/img/icon.png new file mode 100644 index 000000000..928a04921 Binary files /dev/null and b/ui/src/assets/img/icon.png differ diff --git a/ui/src/global.scss b/ui/src/global.scss index edc108896..4225ea8d5 100644 --- a/ui/src/global.scss +++ b/ui/src/global.scss @@ -25,10 +25,6 @@ @import "~@ionic/angular/css/text-transformation.css"; @import "~@ionic/angular/css/flex-utils.css"; -.ios ion-title { - padding-inline-start: 60px; - padding-inline-end: 60px; -} .select-change-warning .alert-sub-title { color: var(--ion-color-warning) @@ -100,8 +96,11 @@ ion-toast { white-space: normal !important; } +img { + border-radius: 100%; +} + ion-card-title { - color: var(--ion-color-dark); font-family: 'Montserrat'; } @@ -109,11 +108,6 @@ ion-title { font-family: 'Montserrat'; } -ion-textarea { - margin-top: 0; - padding-left: 12px; -} - ion-note { max-width: 140px; overflow: hidden; @@ -125,23 +119,16 @@ ion-badge { font-weight: bold; } -ion-item-divider { - --background: transparent; - text-transform: uppercase; - margin-top: 12px; - font-weight: 400; +ion-toolbar { + --min-height: 72px; + --ion-background-color: var(--ion-color-light); } ion-infinite-scroll ion-infinite-scroll-content { --color: var(--ion-color-warning) !important; } -ion-action-sheet { - --backdrop-opacity: 0.75 !important; -} - ion-alert { - --backdrop-opacity: 0.75 !important; .alert-button { color: var(--ion-color-dark) !important; } @@ -151,10 +138,6 @@ ion-button { --color: var(--ion-color-dark) !important; } -ion-loading { - --backdrop-opacity: 0.75 !important; -} - * { -webkit-user-select: text; -moz-user-select: text; @@ -162,14 +145,6 @@ ion-loading { user-select: text; } -ion-popover { - --background: var(--ion-color-warning) !important; - - ion-backdrop { - --backdrop-opacity: 0.45 !important; - } -} - .text-ellipses { overflow: hidden; text-overflow: ellipsis; @@ -185,13 +160,19 @@ ion-popover { display: block; } +.modal-wrapper.sc-ion-modal-md { + border-radius: 6px; + border: 2px solid rgba(255,255,255,.03); + box-shadow: 0 0 70px 70px black; +} + @media (min-width:1000px) { .modal-wrapper { position: absolute; - height: 60% !important; - top: 20%; - width: 50% !important; - left: 25%; + height: 70% !important; + top: 15%; + width: 60% !important; + left: 20%; display: block; } } @@ -227,6 +208,10 @@ ion-popover { } } +.custom-modal { + border-radius: 8px; +} + ion-slides { .slider-wrapper { height: 100%; @@ -239,12 +224,21 @@ ion-slides { --background: transparent !important; } -ion-loading { - z-index: 100 !important; +ion-item-divider { + text-transform: uppercase; + margin-top: 24px; + font-weight: 600; + --color: var(--ion-color-dark); + border: none; + font-size: medium; } -ion-modal { - --backdrop-opacity: 0.75 !important; +ion-item { + border-radius: 4px; +} + +ion-loading { + z-index: 100 !important; } .swiper-pagination { @@ -253,10 +247,6 @@ ion-modal { padding-bottom: 3px; } -ion-avatar { - --border-radius: var(--icon-border-radius); -} - .notifier-item { margin: 12px; margin-top: 0px; @@ -277,10 +267,9 @@ ion-avatar { --padding-start: 10px; } -ion-item-divider { - color: var(--ion-color-medium); - font-size: medium; - padding-left: 10px; +.divider { + background: linear-gradient(90deg,var(--ion-color-light) 0,var(--ion-color-dark) 50%,var(--ion-color-light) 100%); + height: 1px; } .dots { diff --git a/ui/src/theme/variables.scss b/ui/src/theme/variables.scss index 10dedbcf3..63e3e3ef1 100644 --- a/ui/src/theme/variables.scss +++ b/ui/src/theme/variables.scss @@ -4,83 +4,13 @@ /** Ionic CSS Variables **/ :root { --ion-font-family: 'Open Sans'; - /** primary **/ - --ion-color-primary: #3880ff; - --ion-color-primary-rgb: 56, 128, 255; - --ion-color-primary-contrast: #ffffff; - --ion-color-primary-contrast-rgb: 255, 255, 255; - --ion-color-primary-shade: #3171e0; - --ion-color-primary-tint: #4c8dff; + --ion-background-color: var(--ion-color-medium); + --ion-background-color-rgb: var(--ion-color-medium-rgb); + --ion-text-color: var(--ion-color-dark); + --ion-text-color-rgb: var(--ion-color-dark-rgb); + // --ion-backdrop-opacity: .75; - /** secondary **/ - --ion-color-secondary: #3dc2ff; - --ion-color-secondary-rgb: 61, 194, 255; - --ion-color-secondary-contrast: #ffffff; - --ion-color-secondary-contrast-rgb: 255, 255, 255; - --ion-color-secondary-shade: #36abe0; - --ion-color-secondary-tint: #50c8ff; - - /** tertiary **/ - --ion-color-tertiary: #5260ff; - --ion-color-tertiary-rgb: 82, 96, 255; - --ion-color-tertiary-contrast: #ffffff; - --ion-color-tertiary-contrast-rgb: 255, 255, 255; - --ion-color-tertiary-shade: #4854e0; - --ion-color-tertiary-tint: #6370ff; - - /** success **/ - --ion-color-success: #2dd36f; - --ion-color-success-rgb: 45, 211, 111; - --ion-color-success-contrast: #ffffff; - --ion-color-success-contrast-rgb: 255, 255, 255; - --ion-color-success-shade: #28ba62; - --ion-color-success-tint: #42d77d; - - /** warning **/ - --ion-color-warning: #ffc409; - --ion-color-warning-rgb: 255, 196, 9; - --ion-color-warning-contrast: #000000; - --ion-color-warning-contrast-rgb: 0, 0, 0; - --ion-color-warning-shade: #e0ac08; - --ion-color-warning-tint: #ffca22; - - /** danger **/ - --ion-color-danger: #eb445a; - --ion-color-danger-rgb: 235, 68, 90; - --ion-color-danger-contrast: #ffffff; - --ion-color-danger-contrast-rgb: 255, 255, 255; - --ion-color-danger-shade: #cf3c4f; - --ion-color-danger-tint: #ed576b; - - /** dark **/ - --ion-color-dark: #222428; - --ion-color-dark-rgb: 34, 36, 40; - --ion-color-dark-contrast: #ffffff; - --ion-color-dark-contrast-rgb: 255, 255, 255; - --ion-color-dark-shade: #1e2023; - --ion-color-dark-tint: #383a3e; - - /** medium **/ - --ion-color-medium: #92949c; - --ion-color-medium-rgb: 146, 148, 156; - --ion-color-medium-contrast: #ffffff; - --ion-color-medium-contrast-rgb: 255, 255, 255; - --ion-color-medium-shade: #808289; - --ion-color-medium-tint: #9d9fa6; - - /** light **/ - --ion-color-light: #f4f5f8; - --ion-color-light-rgb: 244, 245, 248; - --ion-color-light-contrast: #000000; - --ion-color-light-contrast-rgb: 0, 0, 0; - --ion-color-light-shade: #d7d8da; - --ion-color-light-tint: #f5f6f9; - - --icon-border-radius: 10px -} - -body.dark { - --ion-color-primary: #428cff; + --ion-color-primary: #0075e1; --ion-color-primary-rgb: 66,140,255; --ion-color-primary-contrast: #ffffff; --ion-color-primary-contrast-rgb: 255,255,255; @@ -122,79 +52,26 @@ body.dark { --ion-color-danger-shade: #e04055; --ion-color-danger-tint: #ff5b71; - --ion-color-dark: #f4f5f8; - --ion-color-dark-rgb: 244,245,248; + --ion-color-light: #181818; + --ion-color-light-rgb: 24,24,24; + --ion-color-light-contrast: #ffffff; + --ion-color-light-contrast-rgb: 0,0,0; + --ion-color-light-shade: #000000; + --ion-color-light-tint: #000000; + + --ion-color-medium: #222428; + --ion-color-medium-rgb: 34,36,40; + --ion-color-medium-contrast: #ffffff; + --ion-color-medium-contrast-rgb: 255,255,255; + --ion-color-medium-shade: #1e2023; + --ion-color-medium-tint: #383a3e; + + --ion-color-dark: #e0e0e0; + --ion-color-dark-rgb: 224,224,224; --ion-color-dark-contrast: #000000; --ion-color-dark-contrast-rgb: 0,0,0; - --ion-color-dark-shade: #d7d8da; - --ion-color-dark-tint: #f5f6f9; - - --ion-color-medium: #989aa2; - --ion-color-medium-rgb: 152,154,162; - --ion-color-medium-contrast: #000000; - --ion-color-medium-contrast-rgb: 0,0,0; - --ion-color-medium-shade: #86888f; - --ion-color-medium-tint: #a2a4ab; - - --ion-color-light: #222428; - --ion-color-light-rgb: 34,36,40; - --ion-color-light-contrast: #ffffff; - --ion-color-light-contrast-rgb: 255,255,255; - --ion-color-light-shade: #1e2023; - --ion-color-light-tint: #383a3e; -} - -/* - * iOS Dark Theme - * ------------------------------------------- - */ - -.ios body.dark { - --ion-background-color: #000000; - --ion-background-color-rgb: 0,0,0; - - --ion-text-color: #ffffff; - --ion-text-color-rgb: 255,255,255; - - --ion-color-step-50: #0d0d0d; - --ion-color-step-100: #1a1a1a; - --ion-color-step-150: #262626; - --ion-color-step-200: #333333; - --ion-color-step-250: #404040; - --ion-color-step-300: #4d4d4d; - --ion-color-step-350: #595959; - --ion-color-step-400: #666666; - --ion-color-step-450: #737373; - --ion-color-step-500: #808080; - --ion-color-step-550: #8c8c8c; - --ion-color-step-600: #999999; - --ion-color-step-650: #a6a6a6; - --ion-color-step-700: #b3b3b3; - --ion-color-step-750: #bfbfbf; - --ion-color-step-800: #cccccc; - --ion-color-step-850: #d9d9d9; - --ion-color-step-900: #e6e6e6; - --ion-color-step-950: #f2f2f2; - - --ion-item-background: #1e1e1e; - - --ion-toolbar-background: #1f1f1f; -} - - -/* - * Material Design Dark Theme - * ------------------------------------------- - */ - -.md body.dark { - --ion-background-color: #121212; - --ion-background-color-rgb: 18,18,18; - - --ion-text-color: #ffffff; - --ion-text-color-rgb: 255,255,255; - - --ion-border-color: #222222; + --ion-color-dark-shade: #bfbfbf; + --ion-color-dark-tint: #d8d8d8; --ion-color-step-50: #1e1e1e; --ion-color-step-100: #2a2a2a; @@ -215,10 +92,6 @@ body.dark { --ion-color-step-850: #dbdbdb; --ion-color-step-900: #e7e7e7; --ion-color-step-950: #f3f3f3; - - --ion-item-background: #1e1e1e; - - --ion-toolbar-background: #1f1f1f; } @font-face {