mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 10:21:52 +00:00
styling etc
This commit is contained in:
committed by
Aiden McClelland
parent
517251d672
commit
a2103d4307
@@ -27,6 +27,12 @@ const routes: Routes = [
|
||||
canActivate: [AuthGuard, UnmaintenanceGuard],
|
||||
loadChildren: () => import('./pages/maintenance/maintenance.module').then(m => m.MaintenancePageModule),
|
||||
},
|
||||
{
|
||||
path: 'marketplace',
|
||||
canActivate: [AuthGuard, MaintenanceGuard],
|
||||
canActivateChild: [AuthGuard, MaintenanceGuard],
|
||||
loadChildren: () => import('./pages/marketplace-routes/marketplace-routing.module').then(m => m.MarketplaceRoutingModule),
|
||||
},
|
||||
{
|
||||
path: 'notifications',
|
||||
canActivate: [AuthGuard, MaintenanceGuard],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.selected {
|
||||
--background: linear-gradient(120deg, #1e1e1e -1%, var(--ion-color-start9) 96%);
|
||||
--background: linear-gradient(120deg, #1e1e1e -1%, var(--ion-color-start9) 100%);
|
||||
}
|
||||
|
||||
.menu-style {
|
||||
@@ -10,4 +10,8 @@
|
||||
|
||||
.selected-badge {
|
||||
background-color: #1e1e1e;
|
||||
}
|
||||
|
||||
ion-split-pane {
|
||||
--side-max-width: 280px;
|
||||
}
|
||||
@@ -28,7 +28,7 @@ export class AppComponent {
|
||||
appPages = [
|
||||
{
|
||||
title: 'Services',
|
||||
url: '/services/installed',
|
||||
url: '/services',
|
||||
icon: 'grid-outline',
|
||||
},
|
||||
{
|
||||
@@ -38,7 +38,7 @@ export class AppComponent {
|
||||
},
|
||||
{
|
||||
title: 'Marketplace',
|
||||
url: '/services/marketplace',
|
||||
url: '/marketplace',
|
||||
icon: 'storefront-outline',
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,24 +1,9 @@
|
||||
<p *ngIf="size === 'small'" style="margin: 0 0 4px 0;">
|
||||
<ion-text [color]="color">{{ display }}</ion-text>
|
||||
<p
|
||||
[style.color]="'var(--ion-color-' + color + ')'"
|
||||
[style.font-size]="size"
|
||||
[style.font-style]="style"
|
||||
[style.font-weight]="weight"
|
||||
>
|
||||
{{ display }}
|
||||
<ion-spinner *ngIf="showDots" class="dots dots-small" name="dots" [color]="color"></ion-spinner>
|
||||
</p>
|
||||
|
||||
<p *ngIf="size === 'italics-small'" style="margin: 0 0 4px 0; font-style: italic;">
|
||||
<ion-text [color]="color">{{ display }}</ion-text>
|
||||
<ion-spinner *ngIf="showDots" class="dots dots-small" name="dots" [color]="color"></ion-spinner>
|
||||
</p>
|
||||
|
||||
<h3 *ngIf="size === 'medium'">
|
||||
<ion-text [color]="color">{{ display }}</ion-text>
|
||||
<ion-spinner *ngIf="showDots" class="dots dots-medium" name="dots" [color]="color"></ion-spinner>
|
||||
</h3>
|
||||
|
||||
<h1 *ngIf="size === 'large'">
|
||||
<ion-text [color]="color">{{ display }}</ion-text>
|
||||
<ion-spinner *ngIf="showDots" class="dots" name="dots" [color]="color"></ion-spinner>
|
||||
</h1>
|
||||
|
||||
<h1 *ngIf="size === 'bold-large'" style="font-size: 18px; font-weight: 500">
|
||||
<ion-text [color]="color">{{ display }}</ion-text>
|
||||
<ion-spinner *ngIf="showDots" class="dots" name="dots" [color]="color"></ion-spinner>
|
||||
</h1>
|
||||
|
||||
@@ -1,17 +1,5 @@
|
||||
.icon-small {
|
||||
width: auto;
|
||||
height: 14px;
|
||||
padding-left: 6px;
|
||||
}
|
||||
|
||||
.icon-medium {
|
||||
width: auto;
|
||||
height: 18px;
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
.icon-large {
|
||||
width: auto;
|
||||
height: 24px;
|
||||
padding-left: 12px;
|
||||
p {
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,9 @@ import { renderPkgStatus } from 'src/app/services/pkg-status-rendering.service'
|
||||
export class StatusComponent {
|
||||
@Input() pkg: PackageDataEntry
|
||||
@Input() connection: ConnectionState
|
||||
@Input() size: 'small' | 'medium' | 'large' | 'italics-small' | 'bold-large' = 'large'
|
||||
@Input() size?: 'small' | 'medium' | 'large' = 'large'
|
||||
@Input() style?: string = 'regular'
|
||||
@Input() weight?: string = 'normal'
|
||||
display = ''
|
||||
color = ''
|
||||
showDots = false
|
||||
|
||||
@@ -89,7 +89,7 @@ export class AppActionsPage {
|
||||
)
|
||||
|
||||
if (data.cancelled) return
|
||||
return this.navCtrl.navigateRoot('/services/installed')
|
||||
return this.navCtrl.navigateRoot('/services')
|
||||
}
|
||||
|
||||
private async executeAction (pkgId: string, actionId: string) {
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<pwa-back-button></pwa-back-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Listing</ion-title>
|
||||
<ion-buttons slot="end">
|
||||
<badge-menu-button></badge-menu-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content class="ion-padding-bottom">
|
||||
|
||||
<ion-spinner *ngIf="!aaService.pkgs[pkgId]" class="center" name="lines" color="warning"></ion-spinner>
|
||||
|
||||
<ng-container *ngIf="aaService.pkgs[pkgId] as pkg">
|
||||
<ion-item *ngIf="error" style="margin-bottom: 16px;">
|
||||
<ion-text class="ion-text-wrap" color="danger">{{ error }}</ion-text>
|
||||
</ion-item>
|
||||
|
||||
<ng-container *ngrxLet="patch.watch$('package-data', pkgId) as localPkg">
|
||||
<ion-item-group>
|
||||
<ion-item lines="none">
|
||||
<ion-avatar slot="start">
|
||||
<img [src]="pkg.icon" />
|
||||
</ion-avatar>
|
||||
<ion-label class="ion-text-wrap">
|
||||
<h1 style="font-family: 'Montserrat'">{{ pkg.manifest.title }}</h1>
|
||||
<h3>{{ pkg.manifest.version | displayEmver }}</h3>
|
||||
<!-- no localPkg -->
|
||||
<h3 *ngIf="!localPkg; else local">
|
||||
<ion-text color="medium">Not Installed</ion-text>
|
||||
</h3>
|
||||
<!-- localPkg -->
|
||||
<ng-template #local>
|
||||
<h3 *ngIf="localPkg.state !== PackageState.Installed; else installed">
|
||||
<!-- installing, updating, removing -->
|
||||
<ion-text [color]="localPkg.state === PackageState.Removing ? 'danger' : 'primary'">{{ localPkg.state }}</ion-text>
|
||||
<ion-spinner class="dots dots-medium" name="dots" [color]="localPkg.state === PackageState.Removing ? 'danger' : 'primary'"></ion-spinner>
|
||||
</h3>
|
||||
<!-- installed -->
|
||||
<ng-template #installed>
|
||||
<h3>
|
||||
<ion-text color="medium">Installed at {{ localPkg.installed.manifest.version | displayEmver }}</ion-text>
|
||||
</h3>
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ion-item-group>
|
||||
|
||||
<!-- no localPkg -->
|
||||
<ion-button *ngIf="!localPkg; else localPkg2" class="main-action-button" expand="block" fill="outline" color="success" (click)="install()">
|
||||
Install
|
||||
</ion-button>
|
||||
|
||||
<!-- localPkg -->
|
||||
<ng-template #localPkg2>
|
||||
<!-- not removing -->
|
||||
<ng-container *ngIf="localPkg.state !== PackageState.Removing">
|
||||
<ion-button class="main-action-button" expand="block" fill="outline" [routerLink]="['/services', 'installed', pkgId]">
|
||||
Go to Service
|
||||
</ion-button>
|
||||
<!-- not installing or updating -->
|
||||
<ng-container *ngIf="localPkg.state === PackageState.Installed">
|
||||
<ion-button *ngIf="(localPkg.installed.manifest.version | compareEmver : pkg.manifest.version) === -1" class="main-action-button" expand="block" fill="outline" color="success" (click)="update('update')">
|
||||
Update to {{ pkg.manifest.version | displayEmver }}
|
||||
</ion-button>
|
||||
<ion-button *ngIf="(localPkg.installed.manifest.version | compareEmver : pkg.manifest.version) === 1" class="main-action-button" expand="block" fill="outline" color="warning" (click)="update('downgrade')">
|
||||
Downgrade to {{ pkg.manifest.version | displayEmver }}
|
||||
</ion-button>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
|
||||
<!-- recommendation -->
|
||||
<ion-item *ngIf="rec && showRec" class="rec-item">
|
||||
<ion-label class="ion-text-wrap">
|
||||
<h2 style="display: flex; align-items: center;">
|
||||
<ion-avatar style="height: 3vh; width: 3vh; margin: 5px" slot="start">
|
||||
<img [src]="rec.dependentIcon" [alt]="rec.dependentTitle"/>
|
||||
</ion-avatar>
|
||||
<ion-text style="margin: 5px; font-family: 'Montserrat'; font-size: smaller;">{{ rec.dependentTitle }}</ion-text>
|
||||
</h2>
|
||||
<div style="margin: 7px 5px;">
|
||||
<p style="color: var(--ion-color-dark); font-size: small">{{ rec.description }}</p>
|
||||
<p *ngIf="pkg.manifest.version | satisfiesEmver: rec.version" class="recommendation-text">{{ pkg.manifest.title }} version {{ pkg.manifest.version | displayEmver }} is compatible.</p>
|
||||
<p *ngIf="!(pkg.manifest.version | satisfiesEmver: rec.version)" class="recommendation-text recommendation-error">{{ pkg.manifest.title }} version {{ pkg.manifest.version | displayEmver }} is NOT compatible.</p>
|
||||
<ion-button style="position: absolute; right: 0; top: 0" color="primary" fill="clear" (click)="dismissRec()">
|
||||
<ion-icon name="close-outline"></ion-icon>
|
||||
</ion-button>
|
||||
</div>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item-group>
|
||||
<!-- release notes -->
|
||||
<ion-item-divider style="color: var(--ion-color-dark); font-weight: bold;">
|
||||
New in {{ pkg.manifest.version | displayEmver }}
|
||||
<ion-button [routerLink]="['notes']" style="position: absolute; right: 10px;" fill="clear" color="primary" >
|
||||
Version History
|
||||
<ion-icon slot="end" name="arrow-forward-outline"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-item-divider>
|
||||
<ion-item lines="none">
|
||||
<ion-label style="display: flex; align-items: center; justify-content: space-between;" class="ion-text-wrap" >
|
||||
<div id='release-notes' [innerHTML]="pkg.manifest['release-notes'] | markdown"></div>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<!-- description -->
|
||||
<ion-item-divider class="divider">
|
||||
<ion-text color="dark">Description</ion-text>
|
||||
</ion-item-divider>
|
||||
<ion-item lines="none">
|
||||
<ion-label class="ion-text-wrap">
|
||||
<ion-text color="dark">
|
||||
<h5>{{ pkg.manifest.description.long }}</h5>
|
||||
</ion-text>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<!-- dependencies -->
|
||||
<ng-container *ngIf="!(pkg.manifest.dependencies | empty)">
|
||||
<ion-item-divider class="divider">
|
||||
<ion-text color="dark">Service Dependencies</ion-text>
|
||||
<ion-button style="position: relative; right: 10px;" size="small" fill="clear" color="dark" (click)="presentPopover(depDefintion, $event)">
|
||||
<ion-icon name="help-circle-outline"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-item-divider>
|
||||
|
||||
<div *ngFor="let dep of pkg.manifest.dependencies | keyvalue">
|
||||
<ion-item *ngIf="!dep.value.optional" class="dependency-item">
|
||||
<ion-avatar slot="start">
|
||||
<img [src]="pkg['dependency-metadata'][dep.key].icon" />
|
||||
</ion-avatar>
|
||||
<ion-label class="ion-text-wrap" style="padding: 1vh; padding-left: 2vh">
|
||||
<h4 style="font-family: 'Montserrat'">
|
||||
{{ pkg['dependency-metadata'][dep.key].title }}
|
||||
<span *ngIf="dep.value.recommended" style="font-family: 'Open Sans'; font-size: small; color: var(--ion-color-dark)"> (recommended)</span>
|
||||
</h4>
|
||||
<p style="font-size: small">{{ dep.value.version | displayEmver }}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item style="margin-bottom: 10px" *ngIf="dep.value.description" lines="none">
|
||||
<div style="font-size: small; color: var(--ion-color-dark)" [innerHtml]="dep.value.description"></div>
|
||||
</ion-item>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<!-- versions -->
|
||||
<ion-item-divider></ion-item-divider>
|
||||
<ion-item lines="none" button (click)="presentAlertVersions()">
|
||||
<ion-icon color="dark" slot="start" name="file-tray-stacked-outline"></ion-icon>
|
||||
<ion-label color="dark">Other versions</ion-label>
|
||||
</ion-item>
|
||||
</ion-item-group>
|
||||
|
||||
</ng-container>
|
||||
</ion-content>
|
||||
@@ -1,24 +0,0 @@
|
||||
.recommendation-text {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.recommendation-error {
|
||||
color: var(--ion-color-danger);
|
||||
}
|
||||
|
||||
.main-action-button {
|
||||
margin: 20px 5px 20px 5px;
|
||||
}
|
||||
|
||||
.divider {
|
||||
margin-top: 15px;
|
||||
color: var(--ion-color-medium);
|
||||
font-size: medium;
|
||||
padding-left: 10px;
|
||||
font-weight: unset;
|
||||
}
|
||||
|
||||
#release-notes {
|
||||
overflow: auto;
|
||||
max-height: 160px;
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import { NgModule } from '@angular/core'
|
||||
import { CommonModule } from '@angular/common'
|
||||
import { Routes, RouterModule } from '@angular/router'
|
||||
import { IonicModule } from '@ionic/angular'
|
||||
import { AppInstalledListPage } from './app-installed-list.page'
|
||||
import { AppListPage } from './app-list.page'
|
||||
import { StatusComponentModule } from 'src/app/components/status/status.component.module'
|
||||
import { SharingModule } from 'src/app/modules/sharing.module'
|
||||
import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.module'
|
||||
@@ -10,7 +10,7 @@ import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/b
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: AppInstalledListPage,
|
||||
component: AppListPage,
|
||||
},
|
||||
]
|
||||
|
||||
@@ -24,7 +24,7 @@ const routes: Routes = [
|
||||
BadgeMenuComponentModule,
|
||||
],
|
||||
declarations: [
|
||||
AppInstalledListPage,
|
||||
AppListPage,
|
||||
],
|
||||
})
|
||||
export class AppInstalledListPageModule { }
|
||||
export class AppListPageModule { }
|
||||
@@ -15,7 +15,7 @@
|
||||
<h2>Welcome to your <span style="font-style: italic; color: var(--ion-color-start9)">Embassy</span></h2>
|
||||
<p class="ion-text-wrap">Get started by installing your first service.</p>
|
||||
</div>
|
||||
<ion-button [routerLink]="['/services','marketplace']" style="width: 50%;" fill="outline">
|
||||
<ion-button [routerLink]="['/marketplace']" style="width: 50%;" fill="outline">
|
||||
<ion-icon slot="start" name="storefront-outline"></ion-icon>
|
||||
Marketplace
|
||||
</ion-button>
|
||||
@@ -24,10 +24,10 @@
|
||||
<ng-template #list>
|
||||
<ion-grid>
|
||||
<ion-row *ngIf="connectionService.monitor$() | ngrxPush as connection">
|
||||
<ion-col *ngFor="let pkg of pkgs | keyvalue : asIsOrder" sizeXs="4" sizeSm="3" sizeMd="2" sizeLg="2">
|
||||
<ion-card class="installed-card" style="position:relative" [routerLink]="['/services', 'installed', (pkg.value | manifest).id]">
|
||||
<ion-col *ngFor="let pkg of pkgs | keyvalue : asIsOrder" sizeXs="4" sizeSm="3" sizeLg="3" sizeXl="2">
|
||||
<ion-card class="installed-card" style="position:relative" [routerLink]="['/services', (pkg.value | manifest).id]">
|
||||
<div class="launch-container" *ngIf="pkg.value | hasUi">
|
||||
<div class="launch-button-triangle" (click)="launchUi(pkg.value, $event)" [class.disabled]="!(pkg.value | isLaunchable)">
|
||||
<div class="launch-button-triangle" (click)="launchUi(pkg.value, $event)" [class.launch-disabled]="!(pkg.value | isLaunchable)">
|
||||
<ion-icon name="rocket-outline"></ion-icon>
|
||||
</div>
|
||||
</div>
|
||||
@@ -40,8 +40,8 @@
|
||||
<img class="bulb-off" *ngIf="pkg.value | displayBulb: 'off' : connection" src="assets/img/off-bulb.png"/>
|
||||
|
||||
<ion-card-header>
|
||||
<status [pkg]="pkg.value" [connection]="connection" size="small"></status>
|
||||
<p>{{ (pkg.value | manifest).title }}</p>
|
||||
<status [pkg]="pkg.value" [connection]="connection" size="calc(4px + .7vw)" weight="bold"></status>
|
||||
<ion-card-title>{{ (pkg.value | manifest).title }}</ion-card-title>
|
||||
</ion-card-header>
|
||||
</ion-card>
|
||||
</ion-col>
|
||||
@@ -5,21 +5,16 @@
|
||||
text-align: center;
|
||||
|
||||
ion-card-header {
|
||||
padding: 0;
|
||||
padding: 0 10px;
|
||||
|
||||
status {
|
||||
font-size: 9px;
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
p {
|
||||
font-family: 'Montserrat';
|
||||
font-size: 11px;
|
||||
ion-card-title {
|
||||
font-size: calc(8px + .7vw);
|
||||
color: white;
|
||||
margin: 0px 12px 8px 12px;
|
||||
margin: 10px 0;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
@@ -72,7 +67,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.disabled {
|
||||
.launch-disabled {
|
||||
pointer-events: none;
|
||||
border-color: transparent;
|
||||
&:hover {
|
||||
@@ -5,11 +5,11 @@ import { PatchDbModel } from 'src/app/models/patch-db/patch-db-model'
|
||||
import { PackageDataEntry } from 'src/app/models/patch-db/data-model'
|
||||
|
||||
@Component({
|
||||
selector: 'app-installed-list',
|
||||
templateUrl: './app-installed-list.page.html',
|
||||
styleUrls: ['./app-installed-list.page.scss'],
|
||||
selector: 'app-list',
|
||||
templateUrl: './app-list.page.html',
|
||||
styleUrls: ['./app-list.page.scss'],
|
||||
})
|
||||
export class AppInstalledListPage {
|
||||
export class AppListPage {
|
||||
pkgs: PackageDataEntry[] = []
|
||||
|
||||
constructor (
|
||||
@@ -6,7 +6,6 @@ import { copyToClipboard } from 'src/app/util/web.util'
|
||||
import { AlertController, NavController, PopoverController, ToastController } from '@ionic/angular'
|
||||
import { PackageProperties } from 'src/app/util/properties.util'
|
||||
import { QRComponent } from 'src/app/components/qr/qr.component'
|
||||
import { PropertyStore } from './property-store'
|
||||
import { PatchDbModel } from 'src/app/models/patch-db/patch-db-model'
|
||||
import * as JsonPointer from 'json-pointer'
|
||||
import { FEStatus } from 'src/app/services/pkg-status-rendering.service'
|
||||
@@ -34,7 +33,6 @@ export class AppPropertiesPage {
|
||||
private readonly alertCtrl: AlertController,
|
||||
private readonly toastCtrl: ToastController,
|
||||
private readonly popoverCtrl: PopoverController,
|
||||
private readonly propertyStore: PropertyStore,
|
||||
private readonly navCtrl: NavController,
|
||||
public readonly patch: PatchDbModel,
|
||||
) { }
|
||||
@@ -75,7 +73,7 @@ export class AppPropertiesPage {
|
||||
}
|
||||
|
||||
async goToNested (key: string): Promise<any> {
|
||||
this.navCtrl.navigateForward(`/services/installed/${this.pkgId}/properties`, {
|
||||
this.navCtrl.navigateForward(`/services/${this.pkgId}/properties`, {
|
||||
queryParams: {
|
||||
pointer: `${this.pointer || ''}/${key}/value`,
|
||||
},
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { BehaviorSubject } from 'rxjs'
|
||||
import { PackageProperties } from '../../../util/properties.util'
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class PropertyStore {
|
||||
properties$: BehaviorSubject<PackageProperties> = new BehaviorSubject({ })
|
||||
watch$ () { return this.properties$.asObservable() }
|
||||
|
||||
update (properties: PackageProperties): void {
|
||||
this.properties$.next(properties)
|
||||
}
|
||||
}
|
||||
@@ -2,18 +2,17 @@ import { NgModule } from '@angular/core'
|
||||
import { CommonModule } from '@angular/common'
|
||||
import { Routes, RouterModule } from '@angular/router'
|
||||
import { IonicModule } from '@ionic/angular'
|
||||
import { AppInstalledShowPage } from './app-installed-show.page'
|
||||
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'
|
||||
import { InformationPopoverComponentModule } from 'src/app/components/information-popover/information-popover.component.module'
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: AppInstalledShowPage,
|
||||
component: AppShowPage,
|
||||
},
|
||||
]
|
||||
|
||||
@@ -27,9 +26,8 @@ const routes: Routes = [
|
||||
PwaBackComponentModule,
|
||||
BadgeMenuComponentModule,
|
||||
InstallWizardComponentModule,
|
||||
InformationPopoverComponentModule,
|
||||
],
|
||||
declarations: [AppInstalledShowPage],
|
||||
declarations: [AppShowPage],
|
||||
})
|
||||
export class AppInstalledShowPageModule { }
|
||||
export class AppShowPageModule { }
|
||||
|
||||
@@ -41,23 +41,21 @@
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item class="no-cushion-item" lines="none" style="margin-bottom: 10px;">
|
||||
<ion-label class="status-readout">
|
||||
<status size="bold-large" [pkg]="pkg" [connection]="connection"></status>
|
||||
<ion-button *ngIf="status === FeStatus.NeedsConfig" expand="block" fill="outline" [routerLink]="['config']">
|
||||
Configure
|
||||
</ion-button>
|
||||
<ion-button *ngIf="[FeStatus.Running, FeStatus.StartingUp, FeStatus.NeedsAttention] | includes : status" expand="block" fill="outline" color="danger" (click)="stop()">
|
||||
Stop
|
||||
</ion-button>
|
||||
<ion-button *ngIf="status === FeStatus.DependencyIssue" expand="block" fill="outline" (click)="scrollToRequirements()">
|
||||
Fix
|
||||
</ion-button>
|
||||
<ion-button *ngIf="status === FeStatus.Stopped" expand="block" fill="outline" color="success" (click)="tryStart()">
|
||||
Start
|
||||
</ion-button>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<div class="status-readout">
|
||||
<status size="large" weight="bold" [pkg]="pkg" [connection]="connection"></status>
|
||||
<ion-button *ngIf="status === FeStatus.NeedsConfig" expand="block" fill="outline" [routerLink]="['config']">
|
||||
Configure
|
||||
</ion-button>
|
||||
<ion-button *ngIf="[FeStatus.Running, FeStatus.StartingUp, FeStatus.NeedsAttention] | includes : status" expand="block" fill="outline" color="danger" (click)="stop()">
|
||||
Stop
|
||||
</ion-button>
|
||||
<ion-button *ngIf="status === FeStatus.DependencyIssue" expand="block" fill="outline" (click)="scrollToRequirements()">
|
||||
Fix
|
||||
</ion-button>
|
||||
<ion-button *ngIf="status === FeStatus.Stopped" expand="block" fill="outline" color="success" (click)="tryStart()">
|
||||
Start
|
||||
</ion-button>
|
||||
</div>
|
||||
|
||||
<ion-button size="small" *ngIf="pkg | hasUi" [disabled]="!(pkg | isLaunchable)" class="launch-button" expand="block" (click)="launchUiTab()">
|
||||
Launch Web Interface
|
||||
@@ -69,11 +67,11 @@
|
||||
<ion-grid class="ion-text-center" style="margin: 0 6px;">
|
||||
<ion-row>
|
||||
<ion-col *ngFor="let button of buttons" sizeMd="4" sizeSm="6" sizeXs="6">
|
||||
<ion-button style="width: 100% !important; min-height: 120px; --background: #2f4858;" [disabled]="button.disabled | includes : status" (click)="button.action()">
|
||||
<ion-button style="width: 100%; min-height: 120px;" color="light" [disabled]="button.disabled | includes : status" (click)="button.action()">
|
||||
<div>
|
||||
<ion-icon size="large" [name]="button.icon" style="color: #fbe6ea"></ion-icon>
|
||||
<ion-icon size="large" [name]="button.icon"></ion-icon>
|
||||
<br/><br/>
|
||||
<ion-text style="color: #fbe6ea">{{ button.title }}</ion-text>
|
||||
{{ button.title }}
|
||||
</div>
|
||||
</ion-button>
|
||||
</ion-col>
|
||||
@@ -101,7 +99,7 @@
|
||||
<p style="padding-top: 2px; position: relative; font-style: italic; font-size: smaller"><ion-text [color]="pkg.installed.status['dependency-errors'][dep.key] ? 'warning' : 'success'">{{ pkg.installed.status['dependency-errors'][dep.key] ? pkg.installed.status['dependency-errors'][dep.key].type : 'satisfied' }}</ion-text></p>
|
||||
</ion-label>
|
||||
|
||||
<ion-button *ngIf="!pkg.installed.status['dependency-errors'][dep.key] || (pkg.installed.status['dependency-errors'][dep.key] && [DependencyErrorType.InterfaceHealthChecksFailed, DependencyErrorType.HealthChecksFailed] | includes : pkg.installed.status['dependency-errors'][dep.key].type)" slot="end" size="small" [routerLink]="['/services', 'installed', dep.key]" color="primary" fill="outline" style="font-size: x-small">
|
||||
<ion-button *ngIf="!pkg.installed.status['dependency-errors'][dep.key] || (pkg.installed.status['dependency-errors'][dep.key] && [DependencyErrorType.InterfaceHealthChecksFailed, DependencyErrorType.HealthChecksFailed] | includes : pkg.installed.status['dependency-errors'][dep.key].type)" slot="end" size="small" [routerLink]="['/services', dep.key]" color="primary" fill="outline" style="font-size: x-small">
|
||||
View
|
||||
</ion-button>
|
||||
|
||||
@@ -111,7 +109,7 @@
|
||||
</ion-button>
|
||||
|
||||
<ng-container *ngIf="localDep && localDep.state === PackageState.Installed">
|
||||
<ion-button *ngIf="pkg.installed.status['dependency-errors'][dep.key].type === DependencyErrorType.NotRunning" slot="end" size="small" [routerLink]="['/services', 'installed', dep.key]" color="primary" fill="outline" style="font-size: x-small">
|
||||
<ion-button *ngIf="pkg.installed.status['dependency-errors'][dep.key].type === DependencyErrorType.NotRunning" slot="end" size="small" [routerLink]="['/services', dep.key]" color="primary" fill="outline" style="font-size: x-small">
|
||||
Start
|
||||
</ion-button>
|
||||
<ion-button *ngIf="pkg.installed.status['dependency-errors'][dep.key].type === DependencyErrorType.IncorrectVersion" slot="end" size="small" (click)="fixDep('update', dep.key)" color="primary" fill="outline" style="font-size: x-small">
|
||||
@@ -1,15 +1,3 @@
|
||||
.full-width {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.about-attribute {
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
.about-attribute-value {
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
.less-large {
|
||||
font-size: 20px !important;
|
||||
}
|
||||
@@ -23,9 +11,10 @@
|
||||
}
|
||||
|
||||
.status-readout {
|
||||
--background: transparent;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 4px 10px;
|
||||
padding: 0 10px;
|
||||
border-radius: 10px;
|
||||
align-items: center;
|
||||
background: var(--ion-background-color);
|
||||
@@ -35,10 +24,6 @@
|
||||
border-color: #404040;
|
||||
}
|
||||
|
||||
.no-cushion-item {
|
||||
--background: transparent; --padding-start: 0px; --inner-padding-end: 0px; --padding-end: 0px;
|
||||
}
|
||||
|
||||
.launch-button {
|
||||
--background: rgb(70 193 255 / 75%);
|
||||
--background-hover: rgb(70 193 255);
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Component, ViewChild } from '@angular/core'
|
||||
import { AlertController, NavController, ModalController, IonContent, PopoverController } from '@ionic/angular'
|
||||
import { AlertController, NavController, ModalController, IonContent } from '@ionic/angular'
|
||||
import { ApiService } from 'src/app/services/api/api.service'
|
||||
import { ActivatedRoute, NavigationExtras } from '@angular/router'
|
||||
import { chill, isEmptyObject } from 'src/app/util/misc.util'
|
||||
@@ -7,7 +7,6 @@ import { LoaderService } from 'src/app/services/loader.service'
|
||||
import { Observable, of, Subscription } from 'rxjs'
|
||||
import { wizardModal } from 'src/app/components/install-wizard/install-wizard.component'
|
||||
import { WizardBaker } from 'src/app/components/install-wizard/prebaked-wizards'
|
||||
import { InformationPopoverComponent } from 'src/app/components/information-popover/information-popover.component'
|
||||
import { ConfigService, getManifest } from 'src/app/services/config.service'
|
||||
import { PatchDbModel } from 'src/app/models/patch-db/patch-db-model'
|
||||
import { DependencyErrorConfigUnsatisfied, DependencyErrorNotInstalled, DependencyErrorType, Manifest, PackageDataEntry, PackageState } from 'src/app/models/patch-db/data-model'
|
||||
@@ -16,11 +15,11 @@ import { ConnectionService } from 'src/app/services/connection.service'
|
||||
import { Recommendation } from 'src/app/components/recommendation-button/recommendation-button.component'
|
||||
|
||||
@Component({
|
||||
selector: 'app-installed-show',
|
||||
templateUrl: './app-installed-show.page.html',
|
||||
styleUrls: ['./app-installed-show.page.scss'],
|
||||
selector: 'app-show',
|
||||
templateUrl: './app-show.page.html',
|
||||
styleUrls: ['./app-show.page.scss'],
|
||||
})
|
||||
export class AppInstalledShowPage {
|
||||
export class AppShowPage {
|
||||
error: string
|
||||
pkgId: string
|
||||
pkg: PackageDataEntry
|
||||
@@ -43,7 +42,6 @@ export class AppInstalledShowPage {
|
||||
private readonly modalCtrl: ModalController,
|
||||
private readonly apiService: ApiService,
|
||||
private readonly wizardBaker: WizardBaker,
|
||||
private readonly popoverController: PopoverController,
|
||||
private readonly config: ConfigService,
|
||||
public readonly patch: PatchDbModel,
|
||||
public readonly connectionService: ConnectionService,
|
||||
@@ -120,20 +118,6 @@ export class AppInstalledShowPage {
|
||||
}
|
||||
}
|
||||
|
||||
async presentPopover (information: string, ev: any) {
|
||||
const popover = await this.popoverController.create({
|
||||
component: InformationPopoverComponent,
|
||||
event: ev,
|
||||
translucent: false,
|
||||
showBackdrop: true,
|
||||
backdropDismiss: true,
|
||||
componentProps: {
|
||||
information,
|
||||
},
|
||||
})
|
||||
return await popover.present()
|
||||
}
|
||||
|
||||
scrollToRequirements () {
|
||||
const el = document.getElementById('dependencies')
|
||||
if (!el) return
|
||||
@@ -170,7 +154,7 @@ export class AppInstalledShowPage {
|
||||
state: { installRec },
|
||||
}
|
||||
|
||||
await this.navCtrl.navigateForward(`/services/marketplace/${depId}`, navigationExtras)
|
||||
await this.navCtrl.navigateForward(`/marketplace/${depId}`, navigationExtras)
|
||||
}
|
||||
|
||||
private async configureDep (depId: string): Promise<void> {
|
||||
@@ -189,7 +173,7 @@ export class AppInstalledShowPage {
|
||||
state: { configRecommendation },
|
||||
}
|
||||
|
||||
await this.navCtrl.navigateForward(`/services/installed/${depId}/config`, navigationExtras)
|
||||
await this.navCtrl.navigateForward(`/services/${depId}/config`, navigationExtras)
|
||||
}
|
||||
|
||||
private async presentAlertStart (message: string): Promise<void> {
|
||||
@@ -300,7 +284,7 @@ export class AppInstalledShowPage {
|
||||
disabled: [],
|
||||
},
|
||||
{
|
||||
action: () => this.navCtrl.navigateForward(['/services', 'marketplace', this.pkgId], { relativeTo: this.route }),
|
||||
action: () => this.navCtrl.navigateForward(['/marketplace', this.pkgId], { relativeTo: this.route }),
|
||||
title: 'Marketplace Listing',
|
||||
icon: 'storefront-outline',
|
||||
color: 'danger',
|
||||
@@ -4,69 +4,57 @@ import { Routes, RouterModule } from '@angular/router'
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
redirectTo: 'installed',
|
||||
redirectTo: 'list',
|
||||
pathMatch: 'full',
|
||||
},
|
||||
{
|
||||
path: 'installed',
|
||||
loadChildren: () => import('./app-installed-list/app-installed-list.module').then(m => m.AppInstalledListPageModule),
|
||||
path: 'list',
|
||||
loadChildren: () => import('./app-list/app-list.module').then(m => m.AppListPageModule),
|
||||
},
|
||||
{
|
||||
path: 'installed/:pkgId',
|
||||
loadChildren: () => import('./app-installed-show/app-installed-show.module').then(m => m.AppInstalledShowPageModule),
|
||||
path: ':pkgId',
|
||||
loadChildren: () => import('./app-show/app-show.module').then(m => m.AppShowPageModule),
|
||||
},
|
||||
{
|
||||
path: 'installed/:pkgId/actions',
|
||||
path: ':pkgId/actions',
|
||||
loadChildren: () => import('./app-actions/app-actions.module').then(m => m.AppActionsPageModule),
|
||||
},
|
||||
{
|
||||
path: 'installed/:pkgId/config',
|
||||
path: ':pkgId/config',
|
||||
loadChildren: () => import('./app-config/app-config.module').then(m => m.AppConfigPageModule),
|
||||
},
|
||||
{
|
||||
path: 'installed/:pkgId/config/:edit',
|
||||
path: ':pkgId/config/:edit',
|
||||
loadChildren: () => import('./app-config/app-config.module').then(m => m.AppConfigPageModule),
|
||||
},
|
||||
{
|
||||
path: 'installed/:pkgId/instructions',
|
||||
path: ':pkgId/instructions',
|
||||
loadChildren: () => import('./app-instructions/app-instructions.module').then(m => m.AppInstructionsPageModule),
|
||||
},
|
||||
{
|
||||
path: 'installed/:pkgId/interfaces',
|
||||
path: ':pkgId/interfaces',
|
||||
loadChildren: () => import('./app-interfaces/app-interfaces.module').then(m => m.AppInterfacesPageModule),
|
||||
},
|
||||
{
|
||||
path: 'installed/:pkgId/logs',
|
||||
path: ':pkgId/logs',
|
||||
loadChildren: () => import('./app-logs/app-logs.module').then(m => m.AppLogsPageModule),
|
||||
},
|
||||
{
|
||||
path: 'installed/:pkgId/manifest',
|
||||
path: ':pkgId/manifest',
|
||||
loadChildren: () => import('./app-manifest/app-manifest.module').then(m => m.AppManifestPageModule),
|
||||
},
|
||||
{
|
||||
path: 'installed/:pkgId/metrics',
|
||||
path: ':pkgId/metrics',
|
||||
loadChildren: () => import('./app-metrics/app-metrics.module').then(m => m.AppMetricsPageModule),
|
||||
},
|
||||
{
|
||||
path: 'installed/:pkgId/properties',
|
||||
path: ':pkgId/properties',
|
||||
loadChildren: () => import('./app-properties/app-properties.module').then(m => m.AppPropertiesPageModule),
|
||||
},
|
||||
{
|
||||
path: 'installed/:pkgId/restore',
|
||||
path: ':pkgId/restore',
|
||||
loadChildren: () => import('./app-restore/app-restore.module').then(m => m.AppRestorePageModule),
|
||||
},
|
||||
{
|
||||
path: 'marketplace',
|
||||
loadChildren: () => import('./app-available-list/app-available-list.module').then(m => m.AppAvailableListPageModule),
|
||||
},
|
||||
{
|
||||
path: 'marketplace/:pkgId',
|
||||
loadChildren: () => import('./app-available-show/app-available-show.module').then(m => m.AppAvailableShowPageModule),
|
||||
},
|
||||
{
|
||||
path: 'marketplace/:pkgId/notes',
|
||||
loadChildren: () => import('./app-release-notes/app-release-notes.module').then(m => m.ReleaseNotesModule),
|
||||
},
|
||||
]
|
||||
|
||||
@NgModule({
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
</ion-header>
|
||||
|
||||
<ion-content>
|
||||
<ion-spinner *ngIf="!aaService.pkgs[pkgId]; else loaded" class="center" name="lines" color="warning"></ion-spinner>
|
||||
<ion-spinner *ngIf="!marketplaceService.pkgs[pkgId]; else loaded" class="center" name="lines" color="warning"></ion-spinner>
|
||||
|
||||
<ng-template #loaded>
|
||||
<div *ngFor="let note of aaService.pkgs[pkgId]['release-notes'] | keyvalue : asIsOrder">
|
||||
<div *ngFor="let note of marketplaceService.pkgs[pkgId]['release-notes'] | keyvalue : asIsOrder">
|
||||
<ion-button (click)="setSelected(note.key)" expand="full" color="light" style="height: 50px;" >
|
||||
<p style="position: absolute; left: 10px;">{{ note.key | displayEmver }}</p>
|
||||
</ion-button>
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component } from '@angular/core'
|
||||
import { ActivatedRoute } from '@angular/router'
|
||||
import { AppAvailableService } from '../app-available.service'
|
||||
import { MarketplaceService } from '../marketplace.service'
|
||||
|
||||
@Component({
|
||||
selector: 'app-release-notes',
|
||||
@@ -14,7 +14,7 @@ export class AppReleaseNotes {
|
||||
|
||||
constructor (
|
||||
private readonly route: ActivatedRoute,
|
||||
public aaService: AppAvailableService,
|
||||
public aaService: MarketplaceService,
|
||||
) { }
|
||||
|
||||
ngOnInit () {
|
||||
@@ -2,7 +2,7 @@ import { NgModule } from '@angular/core'
|
||||
import { CommonModule } from '@angular/common'
|
||||
import { Routes, RouterModule } from '@angular/router'
|
||||
import { IonicModule } from '@ionic/angular'
|
||||
import { AppAvailableListPage } from './app-available-list.page'
|
||||
import { MarketplaceListPage } from './marketplace-list.page'
|
||||
import { SharingModule } from '../../../modules/sharing.module'
|
||||
import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.module'
|
||||
import { StatusComponentModule } from 'src/app/components/status/status.component.module'
|
||||
@@ -11,7 +11,7 @@ import { StatusComponentModule } from 'src/app/components/status/status.componen
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: AppAvailableListPage,
|
||||
component: MarketplaceListPage,
|
||||
},
|
||||
]
|
||||
|
||||
@@ -24,6 +24,6 @@ const routes: Routes = [
|
||||
SharingModule,
|
||||
BadgeMenuComponentModule,
|
||||
],
|
||||
declarations: [AppAvailableListPage],
|
||||
declarations: [MarketplaceListPage],
|
||||
})
|
||||
export class AppAvailableListPageModule { }
|
||||
export class MarketplaceListPageModule { }
|
||||
@@ -19,19 +19,7 @@
|
||||
<ion-text class="ion-text-wrap" color="danger">{{ error }}</ion-text>
|
||||
</ion-item>
|
||||
|
||||
<div class="scrollable">
|
||||
<ion-button
|
||||
*ngFor="let cat of data.categories"
|
||||
size="small"
|
||||
fill="clear"
|
||||
[color]="cat === category ? 'success' : 'dark'"
|
||||
(click)="switchCategory(cat)"
|
||||
>
|
||||
{{ cat }}
|
||||
</ion-button>
|
||||
</div>
|
||||
|
||||
<ion-card *ngIf="eos && category === 'featured'" class="eos-card" (click)="updateEos()">
|
||||
<ion-card *ngIf="eos" class="eos-card" (click)="updateEos()">
|
||||
<ion-card-header>
|
||||
<ion-card-subtitle>Now Available...</ion-card-subtitle>
|
||||
<ion-card-title>EmbassyOS Version {{ eos.version }}</ion-card-title>
|
||||
@@ -41,10 +29,42 @@
|
||||
</ion-card-content>
|
||||
</ion-card>
|
||||
|
||||
<ion-spinner *ngIf="pkgsLoading; else pkgsLoaded" style="padding-top: 200px;" name="lines" color="warning"></ion-spinner>
|
||||
<h2 class="ion-margin-start">Categories</h2>
|
||||
|
||||
<div class="scrollable">
|
||||
<ion-button
|
||||
*ngFor="let cat of data.categories"
|
||||
fill="clear"
|
||||
[color]="cat === category ? 'primary' : 'dark'"
|
||||
[class.cat-selected]="cat === category"
|
||||
(click)="switchCategory(cat)"
|
||||
>
|
||||
{{ cat }}
|
||||
</ion-button>
|
||||
</div>
|
||||
|
||||
<div *ngIf="pkgsLoading; else pkgsLoaded" style="margin-top: 64px;" class="ion-text-center">
|
||||
<ion-spinner name="lines" color="warning"></ion-spinner>
|
||||
</div>
|
||||
|
||||
<ng-template #pkgsLoaded>
|
||||
<ion-card *ngFor="let pkg of pkgs" style="margin: 10px 10px;" [routerLink]="[pkg.id]">
|
||||
<ion-grid style="margin: 0 6px;">
|
||||
<ion-row>
|
||||
<ion-col *ngFor="let pkg of pkgs" sizeXl="2" sizeLg="3" sizeMd="3" sizeSm="4" sizeXs="4">
|
||||
<ion-card class="ion-text-center" style="margin: 0;" [routerLink]="['/marketplace', pkg.id]">
|
||||
<img [src]="pkg.icon" style="width: 90%; margin-top: 8px;" />
|
||||
<ion-card-header style="min-height: 70px; text-align: left;">
|
||||
<ion-card-title>{{ pkg.title }}</ion-card-title>
|
||||
</ion-card-header>
|
||||
<ion-card-content style="text-align: left;">
|
||||
{{ pkg.descriptionShort }}
|
||||
</ion-card-content>
|
||||
</ion-card>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
|
||||
<!-- <ion-card *ngFor="let pkg of pkgs" style="margin: 10px 10px;" [routerLink]="['/marketplace', pkg.id]">
|
||||
<ion-item style="--inner-border-width: 0 0 .4px 0; --border-color: #525252;">
|
||||
<ion-avatar style="margin-top: 8px;" slot="start">
|
||||
<img [src]="pkg.icon" />
|
||||
@@ -81,7 +101,7 @@
|
||||
">
|
||||
{{ pkg.descriptionShort }}
|
||||
</ion-card-content>
|
||||
</ion-card>
|
||||
</ion-card> -->
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
</ion-content>
|
||||
@@ -8,8 +8,8 @@
|
||||
.scrollable {
|
||||
overflow: auto;
|
||||
white-space: nowrap;
|
||||
background-color: var(--ion-color-light);
|
||||
margin-bottom: 16px;
|
||||
// background-color: var(--ion-color-light);
|
||||
height: 80px;
|
||||
|
||||
/* Hide scrollbar for Chrome, Safari and Opera */
|
||||
::-webkit-scrollbar {
|
||||
@@ -23,6 +23,11 @@
|
||||
|
||||
.eos-card {
|
||||
--background: linear-gradient(45deg, #101010 16%, var(--ion-color-danger) 150%);
|
||||
margin: 16px 10px;
|
||||
margin: 0 10px 16px 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.cat-selected {
|
||||
border-width: 0 0 1px 0;
|
||||
border-style: solid;
|
||||
}
|
||||
@@ -8,11 +8,11 @@ import { PatchDbModel } from 'src/app/models/patch-db/patch-db-model'
|
||||
import { PackageState } from 'src/app/models/patch-db/data-model'
|
||||
|
||||
@Component({
|
||||
selector: 'app-available-list',
|
||||
templateUrl: './app-available-list.page.html',
|
||||
styleUrls: ['./app-available-list.page.scss'],
|
||||
selector: 'marketplace-list',
|
||||
templateUrl: './marketplace-list.page.html',
|
||||
styleUrls: ['./marketplace-list.page.scss'],
|
||||
})
|
||||
export class AppAvailableListPage {
|
||||
export class MarketplaceListPage {
|
||||
pageLoading = true
|
||||
pkgsLoading = true
|
||||
error = ''
|
||||
@@ -0,0 +1,28 @@
|
||||
import { NgModule } from '@angular/core'
|
||||
import { Routes, RouterModule } from '@angular/router'
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
redirectTo: 'browse',
|
||||
pathMatch: 'full',
|
||||
},
|
||||
{
|
||||
path: 'browse',
|
||||
loadChildren: () => import('./marketplace-list/marketplace-list.module').then(m => m.MarketplaceListPageModule),
|
||||
},
|
||||
{
|
||||
path: ':pkgId',
|
||||
loadChildren: () => import('./marketplace-show/marketplace-show.module').then(m => m.MarketplaceShowPageModule),
|
||||
},
|
||||
{
|
||||
path: ':pkgId/notes',
|
||||
loadChildren: () => import('./app-release-notes/app-release-notes.module').then(m => m.ReleaseNotesModule),
|
||||
},
|
||||
]
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class MarketplaceRoutingModule { }
|
||||
@@ -2,19 +2,18 @@ import { NgModule } from '@angular/core'
|
||||
import { CommonModule } from '@angular/common'
|
||||
import { Routes, RouterModule } from '@angular/router'
|
||||
import { IonicModule } from '@ionic/angular'
|
||||
import { AppAvailableShowPage } from './app-available-show.page'
|
||||
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 { RecommendationButtonComponentModule } from 'src/app/components/recommendation-button/recommendation-button.component.module'
|
||||
import { InstallWizardComponentModule } from 'src/app/components/install-wizard/install-wizard.component.module'
|
||||
import { InformationPopoverComponentModule } from 'src/app/components/information-popover/information-popover.component.module'
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: AppAvailableShowPage,
|
||||
component: MarketplaceShowPage,
|
||||
},
|
||||
]
|
||||
|
||||
@@ -29,8 +28,7 @@ const routes: Routes = [
|
||||
RecommendationButtonComponentModule,
|
||||
BadgeMenuComponentModule,
|
||||
InstallWizardComponentModule,
|
||||
InformationPopoverComponentModule,
|
||||
],
|
||||
declarations: [AppAvailableShowPage],
|
||||
declarations: [MarketplaceShowPage],
|
||||
})
|
||||
export class AppAvailableShowPageModule { }
|
||||
export class MarketplaceShowPageModule { }
|
||||
@@ -0,0 +1,156 @@
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<pwa-back-button></pwa-back-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Listing</ion-title>
|
||||
<ion-buttons slot="end">
|
||||
<badge-menu-button></badge-menu-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content class="ion-padding">
|
||||
|
||||
<ion-spinner *ngIf="!marketplaceService.pkgs[pkgId]" class="center" name="lines" color="warning"></ion-spinner>
|
||||
|
||||
<ng-container *ngIf="marketplaceService.pkgs[pkgId] as pkg">
|
||||
<ion-item *ngIf="error" style="margin-bottom: 16px;">
|
||||
<ion-text class="ion-text-wrap" color="danger">{{ error }}</ion-text>
|
||||
</ion-item>
|
||||
|
||||
<ng-container *ngrxLet="patch.watch$('package-data', pkgId) as localPkg">
|
||||
<ion-grid>
|
||||
<ion-row>
|
||||
<ion-col sizeXl="9" sizeLg="9" sizeMd="9" sizeSm="12" sizeXs="12">
|
||||
<div class="header">
|
||||
<img [src]="pkg.icon" />
|
||||
<div class="header-text">
|
||||
<h1 class="header-title">{{ pkg.manifest.title }}</h1>
|
||||
<p class="header-version">{{ pkg.manifest.version | displayEmver }}</p>
|
||||
<div class="header-status">
|
||||
<!-- no localPkg -->
|
||||
<p *ngIf="!localPkg; else local">
|
||||
<ion-text color="medium">Not Installed</ion-text>
|
||||
</p>
|
||||
<!-- localPkg -->
|
||||
<ng-template #local>
|
||||
<p *ngIf="localPkg.state !== PackageState.Installed; else installed">
|
||||
<!-- installing, updating, removing -->
|
||||
<ion-text [color]="localPkg.state === PackageState.Removing ? 'danger' : 'primary'">{{ localPkg.state }}</ion-text>
|
||||
<ion-spinner class="dots dots-medium" name="dots" [color]="localPkg.state === PackageState.Removing ? 'danger' : 'primary'"></ion-spinner>
|
||||
</p>
|
||||
<!-- installed -->
|
||||
<ng-template #installed>
|
||||
<p>
|
||||
<ion-text color="medium">Installed at {{ localPkg.installed.manifest.version | displayEmver }}</ion-text>
|
||||
</p>
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ion-col>
|
||||
<ion-col sizeXl="3" sizeLg="3" sizeMd="3" sizeSm="12" sizeXs="12" class="ion-align-self-center">
|
||||
<!-- no localPkg -->
|
||||
<ion-button *ngIf="!localPkg; else localPkg2" class="main-action-button" expand="block" (click)="install()">
|
||||
Install
|
||||
</ion-button>
|
||||
<!-- localPkg -->
|
||||
<ng-template #localPkg2>
|
||||
<!-- not installing, updating, or removing -->
|
||||
<ng-container *ngIf="localPkg.state === PackageState.Installed">
|
||||
<ion-button *ngIf="(localPkg.installed.manifest.version | compareEmver : pkg.manifest.version) === -1" class="main-action-button" expand="block" (click)="update('update')">
|
||||
Update
|
||||
</ion-button>
|
||||
<ion-button *ngIf="(localPkg.installed.manifest.version | compareEmver : pkg.manifest.version) === 1" class="main-action-button" expand="block" color="warning" (click)="update('downgrade')">
|
||||
Downgrade
|
||||
</ion-button>
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
</ng-container>
|
||||
|
||||
<!-- recommendation -->
|
||||
<ion-item *ngIf="rec && showRec" class="rec-item">
|
||||
<ion-label class="ion-text-wrap">
|
||||
<h2 style="display: flex; align-items: center;">
|
||||
<ion-avatar style="height: 3vh; width: 3vh; margin: 5px" slot="start">
|
||||
<img [src]="rec.dependentIcon" [alt]="rec.dependentTitle"/>
|
||||
</ion-avatar>
|
||||
<ion-text style="margin: 5px; font-family: 'Montserrat'; font-size: smaller;">{{ rec.dependentTitle }}</ion-text>
|
||||
</h2>
|
||||
<div style="margin: 7px 5px;">
|
||||
<p style="color: var(--ion-color-dark); font-size: small">{{ rec.description }}</p>
|
||||
<p *ngIf="pkg.manifest.version | satisfiesEmver: rec.version" class="recommendation-text">{{ pkg.manifest.title }} version {{ pkg.manifest.version | displayEmver }} is compatible.</p>
|
||||
<p *ngIf="!(pkg.manifest.version | satisfiesEmver: rec.version)" class="recommendation-text recommendation-error">{{ pkg.manifest.title }} version {{ pkg.manifest.version | displayEmver }} is NOT compatible.</p>
|
||||
<ion-button style="position: absolute; right: 0; top: 0" color="primary" fill="clear" (click)="dismissRec()">
|
||||
<ion-icon name="close-outline"></ion-icon>
|
||||
</ion-button>
|
||||
</div>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item-group>
|
||||
<!-- release notes -->
|
||||
<ion-item-divider>
|
||||
New in {{ pkg.manifest.version | displayEmver }}
|
||||
<ion-button [routerLink]="['notes']" style="position: absolute; right: 10px;" fill="clear" color="dark">
|
||||
Release History
|
||||
<ion-icon slot="end" name="arrow-forward-outline"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-item-divider>
|
||||
<ion-item lines="none" color="transparent">
|
||||
<ion-label class="ion-text-wrap" >
|
||||
<div id='release-notes' [innerHTML]="pkg.manifest['release-notes'] | markdown"></div>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<!-- description -->
|
||||
<ion-item-divider>Description</ion-item-divider>
|
||||
<ion-item lines="none" color="transparent">
|
||||
<ion-label class="ion-text-wrap">
|
||||
<ion-text>
|
||||
<h5>{{ pkg.manifest.description.long }}</h5>
|
||||
</ion-text>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<!-- dependencies -->
|
||||
<ng-container *ngIf="!(pkg.manifest.dependencies | empty)">
|
||||
<ion-item-divider>Dependencies</ion-item-divider>
|
||||
<ion-grid>
|
||||
<ion-row>
|
||||
<ion-col *ngFor="let dep of pkg.manifest.dependencies | keyvalue" sizeMd="6" sizeSm="12" sizeXs="12">
|
||||
<ion-card *ngIf="!dep.value.optional" style="--background: #171717" [routerLink]="['/marketplace', dep.key]">
|
||||
<ion-item color="transparent" lines="none">
|
||||
<ion-avatar slot="start">
|
||||
<img [src]="pkg['dependency-metadata'][dep.key].icon" />
|
||||
</ion-avatar>
|
||||
<ion-label class="ion-text-wrap">
|
||||
<h2>
|
||||
{{ pkg['dependency-metadata'][dep.key].title }}
|
||||
<span *ngIf="dep.value.recommended"> (recommended)</span>
|
||||
</h2>
|
||||
<p style="font-size: small">{{ dep.value.version | displayEmver }}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-card-content>
|
||||
{{ dep.value.description }}
|
||||
</ion-card-content>
|
||||
</ion-card>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
</ng-container>
|
||||
|
||||
<!-- versions -->
|
||||
<ion-item-divider>Additional Information</ion-item-divider>
|
||||
<ion-item lines="none" button (click)="presentAlertVersions()" color="transparent">
|
||||
<ion-icon color="dark" slot="start" name="file-tray-stacked-outline"></ion-icon>
|
||||
<ion-label color="dark">Other versions</ion-label>
|
||||
</ion-item>
|
||||
</ion-item-group>
|
||||
|
||||
</ng-container>
|
||||
</ion-content>
|
||||
@@ -0,0 +1,48 @@
|
||||
.header {
|
||||
font-family: 'Montserrat';
|
||||
padding: 2%;
|
||||
img {
|
||||
min-width: 16%;
|
||||
max-width: 18%;
|
||||
}
|
||||
.header-text {
|
||||
margin-left: 5%;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
.header-title {
|
||||
line-height: .65;
|
||||
margin: 0 0 0 -2px;
|
||||
font-size: calc(20px + 3vw)
|
||||
}
|
||||
.header-version {
|
||||
padding: 12px 0;
|
||||
margin: 0;
|
||||
font-size: calc(10px + 1vw)
|
||||
}
|
||||
.header-status {
|
||||
p {
|
||||
margin: 0;
|
||||
font-size: calc(6px + 1vw)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.recommendation-text {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.recommendation-error {
|
||||
color: var(--ion-color-danger);
|
||||
}
|
||||
|
||||
ion-item-divider {
|
||||
text-transform: uppercase;
|
||||
margin-top: 22px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
#release-notes {
|
||||
overflow: auto;
|
||||
max-height: 160px;
|
||||
}
|
||||
@@ -1,23 +1,22 @@
|
||||
import { Component } from '@angular/core'
|
||||
import { ActivatedRoute } from '@angular/router'
|
||||
import { AlertController, ModalController, NavController, PopoverController } from '@ionic/angular'
|
||||
import { AlertController, ModalController, NavController } from '@ionic/angular'
|
||||
import { Recommendation } from 'src/app/components/recommendation-button/recommendation-button.component'
|
||||
import { wizardModal } from 'src/app/components/install-wizard/install-wizard.component'
|
||||
import { WizardBaker } from 'src/app/components/install-wizard/prebaked-wizards'
|
||||
import { InformationPopoverComponent } from 'src/app/components/information-popover/information-popover.component'
|
||||
import { Emver } from 'src/app/services/emver.service'
|
||||
import { displayEmver } from 'src/app/pipes/emver.pipe'
|
||||
import { pauseFor } from 'src/app/util/misc.util'
|
||||
import { PatchDbModel } from 'src/app/models/patch-db/patch-db-model'
|
||||
import { PackageState } from 'src/app/models/patch-db/data-model'
|
||||
import { AppAvailableService } from '../app-available.service'
|
||||
import { MarketplaceService } from '../marketplace.service'
|
||||
|
||||
@Component({
|
||||
selector: 'app-available-show',
|
||||
templateUrl: './app-available-show.page.html',
|
||||
styleUrls: ['./app-available-show.page.scss'],
|
||||
selector: 'marketplace-show',
|
||||
templateUrl: './marketplace-show.page.html',
|
||||
styleUrls: ['./marketplace-show.page.scss'],
|
||||
})
|
||||
export class AppAvailableShowPage {
|
||||
export class MarketplaceShowPage {
|
||||
error = ''
|
||||
pkgId: string
|
||||
|
||||
@@ -26,18 +25,15 @@ export class AppAvailableShowPage {
|
||||
rec: Recommendation | null = null
|
||||
showRec = true
|
||||
|
||||
depDefinition = '<span style="font-style: italic">Service Dependencies</span> are other services that this service recommends or requires in order to run.'
|
||||
|
||||
constructor (
|
||||
private readonly route: ActivatedRoute,
|
||||
private readonly alertCtrl: AlertController,
|
||||
private readonly modalCtrl: ModalController,
|
||||
private readonly wizardBaker: WizardBaker,
|
||||
private readonly navCtrl: NavController,
|
||||
private readonly popoverController: PopoverController,
|
||||
private readonly emver: Emver,
|
||||
public readonly patch: PatchDbModel,
|
||||
public aaService: AppAvailableService,
|
||||
public marketplaceService: MarketplaceService,
|
||||
) { }
|
||||
|
||||
async ngOnInit () {
|
||||
@@ -48,38 +44,24 @@ export class AppAvailableShowPage {
|
||||
async getPkg (version?: string): Promise<void> {
|
||||
this.pkgId = this.route.snapshot.paramMap.get('pkgId')
|
||||
try {
|
||||
await this.aaService.setPkg(this.pkgId, version)
|
||||
await this.marketplaceService.setPkg(this.pkgId, version)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
this.error = e.message
|
||||
}
|
||||
}
|
||||
|
||||
async presentPopover (information: string, ev: any) {
|
||||
const popover = await this.popoverController.create({
|
||||
component: InformationPopoverComponent,
|
||||
event: ev,
|
||||
translucent: false,
|
||||
showBackdrop: true,
|
||||
backdropDismiss: true,
|
||||
componentProps: {
|
||||
information,
|
||||
},
|
||||
})
|
||||
return await popover.present()
|
||||
}
|
||||
|
||||
async presentAlertVersions () {
|
||||
const alert = await this.alertCtrl.create({
|
||||
header: 'Versions',
|
||||
backdropDismiss: false,
|
||||
inputs: this.aaService.pkgs[this.pkgId].versions.sort((a, b) => -1 * this.emver.compare(a, b)).map(v => {
|
||||
inputs: this.marketplaceService.pkgs[this.pkgId].versions.sort((a, b) => -1 * this.emver.compare(a, b)).map(v => {
|
||||
return {
|
||||
name: v, // for CSS
|
||||
type: 'radio',
|
||||
label: displayEmver(v), // appearance on screen
|
||||
value: v, // literal SEM version value
|
||||
checked: this.aaService.pkgs[this.pkgId].manifest.version === v,
|
||||
checked: this.marketplaceService.pkgs[this.pkgId].manifest.version === v,
|
||||
}
|
||||
}),
|
||||
buttons: [
|
||||
@@ -99,7 +81,7 @@ export class AppAvailableShowPage {
|
||||
}
|
||||
|
||||
async install () {
|
||||
const { id, title, version, dependencies, alerts } = this.aaService.pkgs[this.pkgId].manifest
|
||||
const { id, title, version, dependencies, alerts } = this.marketplaceService.pkgs[this.pkgId].manifest
|
||||
const { cancelled } = await wizardModal(
|
||||
this.modalCtrl,
|
||||
this.wizardBaker.install({
|
||||
@@ -115,7 +97,7 @@ export class AppAvailableShowPage {
|
||||
}
|
||||
|
||||
async update (action: 'update' | 'downgrade') {
|
||||
const { id, title, version, dependencies, alerts } = this.aaService.pkgs[this.pkgId].manifest
|
||||
const { id, title, version, dependencies, alerts } = this.marketplaceService.pkgs[this.pkgId].manifest
|
||||
const value = {
|
||||
id,
|
||||
title,
|
||||
@@ -5,7 +5,7 @@ import { ApiService } from 'src/app/services/api/api.service'
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class AppAvailableService {
|
||||
export class MarketplaceService {
|
||||
pkgs: { [id: string]: AvailableShow } = { }
|
||||
|
||||
constructor (
|
||||
@@ -46,7 +46,7 @@
|
||||
</h2>
|
||||
<p>
|
||||
{{ not['created-at'] | date: 'short' }}
|
||||
<a *ngIf="not['package-id'] as pkgId" style="text-decoration: none;" [routerLink]="['/services', 'installed', not['package-id']]">
|
||||
<a *ngIf="not['package-id'] as pkgId" style="text-decoration: none;" [routerLink]="['/services', not['package-id']]">
|
||||
- {{ not['package-id'] }}
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -69,7 +69,6 @@
|
||||
<ion-icon slot="icon-only" name="copy-outline"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-item>
|
||||
<ion-item-divider></ion-item-divider>
|
||||
</ng-container>
|
||||
</ion-item-group>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { NgModule } from '@angular/core'
|
||||
import { CommonModule } from '@angular/common'
|
||||
import { IonicModule } from '@ionic/angular'
|
||||
import { GeneralSettingsPage } from './general-settings.page'
|
||||
import { PreferencesPage } from './preferences.page'
|
||||
import { Routes, RouterModule } from '@angular/router'
|
||||
import { SharingModule } from 'src/app/modules/sharing.module'
|
||||
import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-back.component.module'
|
||||
@@ -9,7 +9,7 @@ import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-b
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: GeneralSettingsPage,
|
||||
component: PreferencesPage,
|
||||
},
|
||||
]
|
||||
|
||||
@@ -22,7 +22,7 @@ const routes: Routes = [
|
||||
PwaBackComponentModule,
|
||||
],
|
||||
declarations: [
|
||||
GeneralSettingsPage,
|
||||
PreferencesPage,
|
||||
],
|
||||
})
|
||||
export class GeneralSettingsPageModule { }
|
||||
export class PreferencesPageModule { }
|
||||
@@ -3,7 +3,7 @@
|
||||
<ion-buttons slot="start">
|
||||
<pwa-back-button></pwa-back-button>
|
||||
</ion-buttons>
|
||||
<ion-title>General Settings</ion-title>
|
||||
<ion-title>Preferences</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
@@ -3,11 +3,11 @@ import { ServerConfigService } from 'src/app/services/server-config.service'
|
||||
import { PatchDbModel } from 'src/app/models/patch-db/patch-db-model'
|
||||
|
||||
@Component({
|
||||
selector: 'general-settings',
|
||||
templateUrl: './general-settings.page.html',
|
||||
styleUrls: ['./general-settings.page.scss'],
|
||||
selector: 'preferences',
|
||||
templateUrl: './preferences.page.html',
|
||||
styleUrls: ['./preferences.page.scss'],
|
||||
})
|
||||
export class GeneralSettingsPage {
|
||||
export class PreferencesPage {
|
||||
constructor (
|
||||
private readonly serverConfigService: ServerConfigService,
|
||||
public readonly patch: PatchDbModel,
|
||||
@@ -23,8 +23,8 @@ const routes: Routes = [
|
||||
loadChildren: () => import('./server-logs/server-logs.module').then(m => m.ServerLogsPageModule),
|
||||
},
|
||||
{
|
||||
path: 'settings',
|
||||
loadChildren: () => import('./general-settings/general-settings.module').then(m => m.GeneralSettingsPageModule),
|
||||
path: 'preferences',
|
||||
loadChildren: () => import('./preferences/preferences.module').then(m => m.PreferencesPageModule),
|
||||
},
|
||||
{
|
||||
path: 'wifi',
|
||||
|
||||
@@ -7,65 +7,17 @@
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content class="ion-padding-top ion-padding-bottom">
|
||||
<ion-content>
|
||||
|
||||
<ion-item-divider>Backups</ion-item-divider>
|
||||
|
||||
<ion-item [routerLink]="['backup']">
|
||||
<ion-icon slot="start" name="save-outline"></ion-icon>
|
||||
<ion-label>Create Backup</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item-divider>Insights</ion-item-divider>
|
||||
|
||||
<ion-item-group>
|
||||
<ion-item [routerLink]="['specs']">
|
||||
<ion-icon slot="start" name="information-circle-outline"></ion-icon>
|
||||
<ion-label>About</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item [routerLink]="['metrics']">
|
||||
<ion-icon slot="start" name="pulse"></ion-icon>
|
||||
<ion-label>Monitor</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item [routerLink]="['logs']">
|
||||
<ion-icon slot="start" name="newspaper-outline"></ion-icon>
|
||||
<ion-label>Logs</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item-divider>Settings</ion-item-divider>
|
||||
|
||||
<ion-item lines="none" [routerLink]="['settings']">
|
||||
<ion-icon slot="start" name="cog-outline"></ion-icon>
|
||||
<ion-label>General</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item [routerLink]="['lan']">
|
||||
<ion-icon slot="start" name="home-outline"></ion-icon>
|
||||
<ion-label>LAN</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item [routerLink]="['wifi']">
|
||||
<ion-icon slot="start" name="wifi"></ion-icon>
|
||||
<ion-label>WiFi</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item lines="none" [routerLink]="['developer']">
|
||||
<ion-icon slot="start" name="terminal-outline"></ion-icon>
|
||||
<ion-label>Developer Options</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item-divider>Power</ion-item-divider>
|
||||
|
||||
<ion-item button (click)="presentAlertRestart()">
|
||||
<ion-icon slot="start" name="reload-outline"></ion-icon>
|
||||
<ion-label>Restart</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item button lines="none" (click)="presentAlertShutdown()">
|
||||
<ion-icon slot="start" name="power"></ion-icon>
|
||||
<ion-label>Shutdown</ion-label>
|
||||
</ion-item>
|
||||
</ion-item-group>
|
||||
<ion-grid>
|
||||
<ion-row>
|
||||
<ion-col *ngFor="let cat of settings | keyvalue : asIsOrder" sizeXs="12" sizeMd="6">
|
||||
<ion-item-divider>{{ cat.key }}</ion-item-divider>
|
||||
<ion-item style="cursor: pointer;" button *ngFor="let button of cat.value" (click)="button.action()">
|
||||
<ion-icon slot="start" [name]="button.icon"></ion-icon>
|
||||
<ion-label>{{ button.title }}</ion-label>
|
||||
</ion-item>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
</ion-content>
|
||||
@@ -1,12 +0,0 @@
|
||||
.notification-button {
|
||||
ion-badge {
|
||||
position: absolute;
|
||||
font-size: 8px;
|
||||
bottom: .7rem;
|
||||
left: .8rem;
|
||||
}
|
||||
}
|
||||
|
||||
ion-item-divider {
|
||||
margin-top: 0px;
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
import { Component } from '@angular/core'
|
||||
import { LoadingOptions } from '@ionic/core'
|
||||
import { AlertController, ModalController } from '@ionic/angular'
|
||||
import { AlertController, NavController } from '@ionic/angular'
|
||||
import { ApiService } from 'src/app/services/api/api.service'
|
||||
import { LoaderService } from 'src/app/services/loader.service'
|
||||
import { PatchDbModel } from 'src/app/models/patch-db/patch-db-model'
|
||||
import { ServerStatus } from 'src/app/models/patch-db/data-model'
|
||||
import { ActivatedRoute } from '@angular/router'
|
||||
|
||||
@Component({
|
||||
selector: 'server-show',
|
||||
@@ -13,15 +14,21 @@ import { ServerStatus } from 'src/app/models/patch-db/data-model'
|
||||
})
|
||||
export class ServerShowPage {
|
||||
ServerStatus = ServerStatus
|
||||
settings: ServerSettings = { }
|
||||
|
||||
constructor (
|
||||
private readonly alertCtrl: AlertController,
|
||||
private readonly loader: LoaderService,
|
||||
private readonly apiService: ApiService,
|
||||
private readonly modalCtrl: ModalController,
|
||||
private readonly navCtrl: NavController,
|
||||
private readonly route: ActivatedRoute,
|
||||
public readonly patch: PatchDbModel,
|
||||
) { }
|
||||
|
||||
ngOnInit () {
|
||||
this.setButtons()
|
||||
}
|
||||
|
||||
async presentAlertRestart () {
|
||||
const alert = await this.alertCtrl.create({
|
||||
backdropDismiss: false,
|
||||
@@ -73,7 +80,7 @@ export class ServerShowPage {
|
||||
// this.serverModel.markUnreachable()
|
||||
await this.apiService.restartServer({ })
|
||||
})
|
||||
.catch(e => this.setError(e))
|
||||
.catch(console.error)
|
||||
}
|
||||
|
||||
private async shutdown () {
|
||||
@@ -83,11 +90,74 @@ export class ServerShowPage {
|
||||
// this.serverModel.markUnreachable()
|
||||
await this.apiService.shutdownServer({ })
|
||||
})
|
||||
.catch(e => this.setError(e))
|
||||
.catch(console.error)
|
||||
}
|
||||
|
||||
setError (e: Error) {
|
||||
console.error(e)
|
||||
private setButtons (): void {
|
||||
this.settings = {
|
||||
'Settings': [
|
||||
{
|
||||
title: 'Preferences',
|
||||
icon: 'cog-outline',
|
||||
action: () => this.navCtrl.navigateForward(['preferences'], { relativeTo: this.route }),
|
||||
},
|
||||
{
|
||||
title: 'LAN',
|
||||
icon: 'home-outline',
|
||||
action: () => this.navCtrl.navigateForward(['lan'], { relativeTo: this.route }),
|
||||
},
|
||||
{
|
||||
title: 'WiFi',
|
||||
icon: 'wifi',
|
||||
action: () => this.navCtrl.navigateForward(['wifi'], { relativeTo: this.route }),
|
||||
},
|
||||
{
|
||||
title: 'Developer Options',
|
||||
icon: 'terminal-outline',
|
||||
action: () => this.navCtrl.navigateForward(['developer'], { relativeTo: this.route }),
|
||||
},
|
||||
],
|
||||
'Insights': [
|
||||
{
|
||||
title: 'About',
|
||||
icon: 'information-circle-outline',
|
||||
action: () => this.navCtrl.navigateForward(['specs'], { relativeTo: this.route }),
|
||||
},
|
||||
{
|
||||
title: 'Monitor',
|
||||
icon: 'pulse',
|
||||
action: () => this.navCtrl.navigateForward(['metrics'], { relativeTo: this.route }),
|
||||
},
|
||||
{
|
||||
title: 'Logs',
|
||||
icon: 'newspaper-outline',
|
||||
action: () => this.navCtrl.navigateForward(['logs'], { relativeTo: this.route }),
|
||||
},
|
||||
],
|
||||
'Backups': [
|
||||
{
|
||||
title: 'Create Backup',
|
||||
icon: 'save-outline',
|
||||
action: () => this.navCtrl.navigateForward(['backup'], { relativeTo: this.route }),
|
||||
},
|
||||
],
|
||||
'Power': [
|
||||
{
|
||||
title: 'Restart',
|
||||
icon: 'reload-outline',
|
||||
action: () => this.presentAlertRestart(),
|
||||
},
|
||||
{
|
||||
title: 'Shutdown',
|
||||
icon: 'power',
|
||||
action: () => this.presentAlertShutdown(),
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
asIsOrder () {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,4 +170,10 @@ const LoadingSpinner: (m?: string) => LoadingOptions = (m) => {
|
||||
} as LoadingOptions
|
||||
}
|
||||
|
||||
|
||||
interface ServerSettings {
|
||||
[key: string]: {
|
||||
title: string
|
||||
icon: string
|
||||
action: Function
|
||||
}[]
|
||||
}
|
||||
|
||||
@@ -469,7 +469,7 @@ export class MockApiService extends ApiService {
|
||||
async getMarketplaceData (params: RR.GetMarketplaceDataReq): Promise<RR.GetMarketplaceDataRes> {
|
||||
await pauseFor(2000)
|
||||
return {
|
||||
categories: ['featured', 'bitcoin', 'lightning', 'data', 'messaging'],
|
||||
categories: ['featured', 'bitcoin', 'lightning', 'data', 'messaging', 'social', 'alt coin'],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ export module Mock {
|
||||
},
|
||||
{
|
||||
id: 'lnd',
|
||||
title: 'Lightning Network Daemon',
|
||||
title: 'LND',
|
||||
version: '0.11.1',
|
||||
descriptionShort: 'A BOLT-compliant, lightning network node.',
|
||||
icon: 'assets/img/service-icons/lnd.png',
|
||||
@@ -157,7 +157,7 @@ export module Mock {
|
||||
|
||||
export const MockManifestLnd: Manifest = {
|
||||
id: 'lnd',
|
||||
title: 'Lightning Network Daemon',
|
||||
title: 'LND',
|
||||
version: '0.11.1',
|
||||
description: {
|
||||
short: 'A bolt spec compliant client.',
|
||||
|
||||
@@ -20,7 +20,7 @@ function handleInstalledState (status: Status): PkgStatusRendering {
|
||||
}
|
||||
|
||||
if (Object.keys(status['dependency-errors']).length) {
|
||||
return { display: 'Dependency Issue', color: 'warning', showDots: false, feStatus: FEStatus.DependencyIssue }
|
||||
return { display: 'Needs Attention', color: 'warning', showDots: false, feStatus: FEStatus.DependencyIssue }
|
||||
}
|
||||
|
||||
switch (status.main.status) {
|
||||
@@ -36,7 +36,7 @@ function handleRunningState (status: MainStatusRunning): PkgStatusRendering {
|
||||
if (Object.values(status.health).some(h => h.result === 'failure')) {
|
||||
return { display: 'Needs Attention', color: 'danger', showDots: false, feStatus: FEStatus.NeedsAttention }
|
||||
} else if (Object.values(status.health).some(h => h.result === 'starting')) {
|
||||
return { display: 'Starting Up', color: 'warning', showDots: true, feStatus: FEStatus.Starting }
|
||||
return { display: 'Starting', color: 'warning', showDots: true, feStatus: FEStatus.Starting }
|
||||
} else if (Object.values(status.health).some(h => h.result === 'loading')) {
|
||||
const firstLoading = Object.values(status.health).find(h => h.result === 'loading') as HealthCheckResultLoading
|
||||
return { display: firstLoading.message, color: 'warning', showDots: true, feStatus: FEStatus.Loading }
|
||||
|
||||
@@ -183,7 +183,7 @@ export class StartupAlertsNotifier {
|
||||
{
|
||||
text: 'View in Marketplace',
|
||||
handler: () => {
|
||||
return this.navCtrl.navigateForward('/services/marketplace').then(() => resolve(false))
|
||||
return this.navCtrl.navigateForward('/marketplace').then(() => resolve(false))
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -117,9 +117,12 @@
|
||||
white-space: normal !important;
|
||||
}
|
||||
|
||||
ion-card-title {
|
||||
font-family: 'Montserrat';
|
||||
}
|
||||
|
||||
ion-title {
|
||||
font-family: 'Montserrat';
|
||||
font-weight: unset;
|
||||
}
|
||||
|
||||
ion-textarea {
|
||||
@@ -272,11 +275,6 @@ ion-avatar {
|
||||
--border-radius: var(--icon-border-radius);
|
||||
}
|
||||
|
||||
.no-white-space {
|
||||
--white-space: 0;
|
||||
--box-shadow: 3px 3px 10px var(--ion-color-primary);
|
||||
}
|
||||
|
||||
.notifier-item {
|
||||
margin: 12px;
|
||||
margin-top: 0px;
|
||||
@@ -301,7 +299,6 @@ ion-item-divider {
|
||||
color: var(--ion-color-medium);
|
||||
font-size: medium;
|
||||
padding-left: 10px;
|
||||
font-weight: unset;
|
||||
}
|
||||
|
||||
.dots {
|
||||
|
||||
Reference in New Issue
Block a user