mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 20:14:49 +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],
|
canActivate: [AuthGuard, UnmaintenanceGuard],
|
||||||
loadChildren: () => import('./pages/maintenance/maintenance.module').then(m => m.MaintenancePageModule),
|
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',
|
path: 'notifications',
|
||||||
canActivate: [AuthGuard, MaintenanceGuard],
|
canActivate: [AuthGuard, MaintenanceGuard],
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
.selected {
|
.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 {
|
.menu-style {
|
||||||
@@ -11,3 +11,7 @@
|
|||||||
.selected-badge {
|
.selected-badge {
|
||||||
background-color: #1e1e1e;
|
background-color: #1e1e1e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ion-split-pane {
|
||||||
|
--side-max-width: 280px;
|
||||||
|
}
|
||||||
@@ -28,7 +28,7 @@ export class AppComponent {
|
|||||||
appPages = [
|
appPages = [
|
||||||
{
|
{
|
||||||
title: 'Services',
|
title: 'Services',
|
||||||
url: '/services/installed',
|
url: '/services',
|
||||||
icon: 'grid-outline',
|
icon: 'grid-outline',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -38,7 +38,7 @@ export class AppComponent {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Marketplace',
|
title: 'Marketplace',
|
||||||
url: '/services/marketplace',
|
url: '/marketplace',
|
||||||
icon: 'storefront-outline',
|
icon: 'storefront-outline',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,24 +1,9 @@
|
|||||||
<p *ngIf="size === 'small'" style="margin: 0 0 4px 0;">
|
<p
|
||||||
<ion-text [color]="color">{{ display }}</ion-text>
|
[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>
|
<ion-spinner *ngIf="showDots" class="dots dots-small" name="dots" [color]="color"></ion-spinner>
|
||||||
</p>
|
</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 {
|
p {
|
||||||
width: auto;
|
margin: 0;
|
||||||
height: 14px;
|
overflow: hidden;
|
||||||
padding-left: 6px;
|
text-overflow: ellipsis;
|
||||||
}
|
|
||||||
|
|
||||||
.icon-medium {
|
|
||||||
width: auto;
|
|
||||||
height: 18px;
|
|
||||||
padding-left: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-large {
|
|
||||||
width: auto;
|
|
||||||
height: 24px;
|
|
||||||
padding-left: 12px;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ import { renderPkgStatus } from 'src/app/services/pkg-status-rendering.service'
|
|||||||
export class StatusComponent {
|
export class StatusComponent {
|
||||||
@Input() pkg: PackageDataEntry
|
@Input() pkg: PackageDataEntry
|
||||||
@Input() connection: ConnectionState
|
@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 = ''
|
display = ''
|
||||||
color = ''
|
color = ''
|
||||||
showDots = false
|
showDots = false
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ export class AppActionsPage {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (data.cancelled) return
|
if (data.cancelled) return
|
||||||
return this.navCtrl.navigateRoot('/services/installed')
|
return this.navCtrl.navigateRoot('/services')
|
||||||
}
|
}
|
||||||
|
|
||||||
private async executeAction (pkgId: string, actionId: string) {
|
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 { CommonModule } from '@angular/common'
|
||||||
import { Routes, RouterModule } from '@angular/router'
|
import { Routes, RouterModule } from '@angular/router'
|
||||||
import { IonicModule } from '@ionic/angular'
|
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 { StatusComponentModule } from 'src/app/components/status/status.component.module'
|
||||||
import { SharingModule } from 'src/app/modules/sharing.module'
|
import { SharingModule } from 'src/app/modules/sharing.module'
|
||||||
import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.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 = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: AppInstalledListPage,
|
component: AppListPage,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ const routes: Routes = [
|
|||||||
BadgeMenuComponentModule,
|
BadgeMenuComponentModule,
|
||||||
],
|
],
|
||||||
declarations: [
|
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>
|
<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>
|
<p class="ion-text-wrap">Get started by installing your first service.</p>
|
||||||
</div>
|
</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>
|
<ion-icon slot="start" name="storefront-outline"></ion-icon>
|
||||||
Marketplace
|
Marketplace
|
||||||
</ion-button>
|
</ion-button>
|
||||||
@@ -24,10 +24,10 @@
|
|||||||
<ng-template #list>
|
<ng-template #list>
|
||||||
<ion-grid>
|
<ion-grid>
|
||||||
<ion-row *ngIf="connectionService.monitor$() | ngrxPush as connection">
|
<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-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', 'installed', (pkg.value | manifest).id]">
|
<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-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>
|
<ion-icon name="rocket-outline"></ion-icon>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -40,8 +40,8 @@
|
|||||||
<img class="bulb-off" *ngIf="pkg.value | displayBulb: 'off' : connection" src="assets/img/off-bulb.png"/>
|
<img class="bulb-off" *ngIf="pkg.value | displayBulb: 'off' : connection" src="assets/img/off-bulb.png"/>
|
||||||
|
|
||||||
<ion-card-header>
|
<ion-card-header>
|
||||||
<status [pkg]="pkg.value" [connection]="connection" size="small"></status>
|
<status [pkg]="pkg.value" [connection]="connection" size="calc(4px + .7vw)" weight="bold"></status>
|
||||||
<p>{{ (pkg.value | manifest).title }}</p>
|
<ion-card-title>{{ (pkg.value | manifest).title }}</ion-card-title>
|
||||||
</ion-card-header>
|
</ion-card-header>
|
||||||
</ion-card>
|
</ion-card>
|
||||||
</ion-col>
|
</ion-col>
|
||||||
@@ -5,21 +5,16 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
ion-card-header {
|
ion-card-header {
|
||||||
padding: 0;
|
padding: 0 10px;
|
||||||
|
|
||||||
status {
|
status {
|
||||||
font-size: 9px;
|
|
||||||
font-weight: bold;
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
ion-card-title {
|
||||||
font-family: 'Montserrat';
|
font-size: calc(8px + .7vw);
|
||||||
font-size: 11px;
|
|
||||||
color: white;
|
color: white;
|
||||||
margin: 0px 12px 8px 12px;
|
margin: 10px 0;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
@@ -72,7 +67,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.disabled {
|
.launch-disabled {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
&:hover {
|
&: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'
|
import { PackageDataEntry } from 'src/app/models/patch-db/data-model'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-installed-list',
|
selector: 'app-list',
|
||||||
templateUrl: './app-installed-list.page.html',
|
templateUrl: './app-list.page.html',
|
||||||
styleUrls: ['./app-installed-list.page.scss'],
|
styleUrls: ['./app-list.page.scss'],
|
||||||
})
|
})
|
||||||
export class AppInstalledListPage {
|
export class AppListPage {
|
||||||
pkgs: PackageDataEntry[] = []
|
pkgs: PackageDataEntry[] = []
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
@@ -6,7 +6,6 @@ import { copyToClipboard } from 'src/app/util/web.util'
|
|||||||
import { AlertController, NavController, PopoverController, ToastController } from '@ionic/angular'
|
import { AlertController, NavController, PopoverController, ToastController } from '@ionic/angular'
|
||||||
import { PackageProperties } from 'src/app/util/properties.util'
|
import { PackageProperties } from 'src/app/util/properties.util'
|
||||||
import { QRComponent } from 'src/app/components/qr/qr.component'
|
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 { PatchDbModel } from 'src/app/models/patch-db/patch-db-model'
|
||||||
import * as JsonPointer from 'json-pointer'
|
import * as JsonPointer from 'json-pointer'
|
||||||
import { FEStatus } from 'src/app/services/pkg-status-rendering.service'
|
import { FEStatus } from 'src/app/services/pkg-status-rendering.service'
|
||||||
@@ -34,7 +33,6 @@ export class AppPropertiesPage {
|
|||||||
private readonly alertCtrl: AlertController,
|
private readonly alertCtrl: AlertController,
|
||||||
private readonly toastCtrl: ToastController,
|
private readonly toastCtrl: ToastController,
|
||||||
private readonly popoverCtrl: PopoverController,
|
private readonly popoverCtrl: PopoverController,
|
||||||
private readonly propertyStore: PropertyStore,
|
|
||||||
private readonly navCtrl: NavController,
|
private readonly navCtrl: NavController,
|
||||||
public readonly patch: PatchDbModel,
|
public readonly patch: PatchDbModel,
|
||||||
) { }
|
) { }
|
||||||
@@ -75,7 +73,7 @@ export class AppPropertiesPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async goToNested (key: string): Promise<any> {
|
async goToNested (key: string): Promise<any> {
|
||||||
this.navCtrl.navigateForward(`/services/installed/${this.pkgId}/properties`, {
|
this.navCtrl.navigateForward(`/services/${this.pkgId}/properties`, {
|
||||||
queryParams: {
|
queryParams: {
|
||||||
pointer: `${this.pointer || ''}/${key}/value`,
|
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 { CommonModule } from '@angular/common'
|
||||||
import { Routes, RouterModule } from '@angular/router'
|
import { Routes, RouterModule } from '@angular/router'
|
||||||
import { IonicModule } from '@ionic/angular'
|
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 { StatusComponentModule } from 'src/app/components/status/status.component.module'
|
||||||
import { SharingModule } from 'src/app/modules/sharing.module'
|
import { SharingModule } from 'src/app/modules/sharing.module'
|
||||||
import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-back.component.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 { 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 { 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 = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: AppInstalledShowPage,
|
component: AppShowPage,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -27,9 +26,8 @@ const routes: Routes = [
|
|||||||
PwaBackComponentModule,
|
PwaBackComponentModule,
|
||||||
BadgeMenuComponentModule,
|
BadgeMenuComponentModule,
|
||||||
InstallWizardComponentModule,
|
InstallWizardComponentModule,
|
||||||
InformationPopoverComponentModule,
|
|
||||||
],
|
],
|
||||||
declarations: [AppInstalledShowPage],
|
declarations: [AppShowPage],
|
||||||
})
|
})
|
||||||
export class AppInstalledShowPageModule { }
|
export class AppShowPageModule { }
|
||||||
|
|
||||||
@@ -41,23 +41,21 @@
|
|||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<ion-item class="no-cushion-item" lines="none" style="margin-bottom: 10px;">
|
<div class="status-readout">
|
||||||
<ion-label class="status-readout">
|
<status size="large" weight="bold" [pkg]="pkg" [connection]="connection"></status>
|
||||||
<status size="bold-large" [pkg]="pkg" [connection]="connection"></status>
|
<ion-button *ngIf="status === FeStatus.NeedsConfig" expand="block" fill="outline" [routerLink]="['config']">
|
||||||
<ion-button *ngIf="status === FeStatus.NeedsConfig" expand="block" fill="outline" [routerLink]="['config']">
|
Configure
|
||||||
Configure
|
</ion-button>
|
||||||
</ion-button>
|
<ion-button *ngIf="[FeStatus.Running, FeStatus.StartingUp, FeStatus.NeedsAttention] | includes : status" expand="block" fill="outline" color="danger" (click)="stop()">
|
||||||
<ion-button *ngIf="[FeStatus.Running, FeStatus.StartingUp, FeStatus.NeedsAttention] | includes : status" expand="block" fill="outline" color="danger" (click)="stop()">
|
Stop
|
||||||
Stop
|
</ion-button>
|
||||||
</ion-button>
|
<ion-button *ngIf="status === FeStatus.DependencyIssue" expand="block" fill="outline" (click)="scrollToRequirements()">
|
||||||
<ion-button *ngIf="status === FeStatus.DependencyIssue" expand="block" fill="outline" (click)="scrollToRequirements()">
|
Fix
|
||||||
Fix
|
</ion-button>
|
||||||
</ion-button>
|
<ion-button *ngIf="status === FeStatus.Stopped" expand="block" fill="outline" color="success" (click)="tryStart()">
|
||||||
<ion-button *ngIf="status === FeStatus.Stopped" expand="block" fill="outline" color="success" (click)="tryStart()">
|
Start
|
||||||
Start
|
</ion-button>
|
||||||
</ion-button>
|
</div>
|
||||||
</ion-label>
|
|
||||||
</ion-item>
|
|
||||||
|
|
||||||
<ion-button size="small" *ngIf="pkg | hasUi" [disabled]="!(pkg | isLaunchable)" class="launch-button" expand="block" (click)="launchUiTab()">
|
<ion-button size="small" *ngIf="pkg | hasUi" [disabled]="!(pkg | isLaunchable)" class="launch-button" expand="block" (click)="launchUiTab()">
|
||||||
Launch Web Interface
|
Launch Web Interface
|
||||||
@@ -69,11 +67,11 @@
|
|||||||
<ion-grid class="ion-text-center" style="margin: 0 6px;">
|
<ion-grid class="ion-text-center" style="margin: 0 6px;">
|
||||||
<ion-row>
|
<ion-row>
|
||||||
<ion-col *ngFor="let button of buttons" sizeMd="4" sizeSm="6" sizeXs="6">
|
<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>
|
<div>
|
||||||
<ion-icon size="large" [name]="button.icon" style="color: #fbe6ea"></ion-icon>
|
<ion-icon size="large" [name]="button.icon"></ion-icon>
|
||||||
<br/><br/>
|
<br/><br/>
|
||||||
<ion-text style="color: #fbe6ea">{{ button.title }}</ion-text>
|
{{ button.title }}
|
||||||
</div>
|
</div>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-col>
|
</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>
|
<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-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
|
View
|
||||||
</ion-button>
|
</ion-button>
|
||||||
|
|
||||||
@@ -111,7 +109,7 @@
|
|||||||
</ion-button>
|
</ion-button>
|
||||||
|
|
||||||
<ng-container *ngIf="localDep && localDep.state === PackageState.Installed">
|
<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
|
Start
|
||||||
</ion-button>
|
</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">
|
<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 {
|
.less-large {
|
||||||
font-size: 20px !important;
|
font-size: 20px !important;
|
||||||
}
|
}
|
||||||
@@ -23,9 +11,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.status-readout {
|
.status-readout {
|
||||||
|
--background: transparent;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 4px 10px;
|
padding: 0 10px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: var(--ion-background-color);
|
background: var(--ion-background-color);
|
||||||
@@ -35,10 +24,6 @@
|
|||||||
border-color: #404040;
|
border-color: #404040;
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-cushion-item {
|
|
||||||
--background: transparent; --padding-start: 0px; --inner-padding-end: 0px; --padding-end: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.launch-button {
|
.launch-button {
|
||||||
--background: rgb(70 193 255 / 75%);
|
--background: rgb(70 193 255 / 75%);
|
||||||
--background-hover: rgb(70 193 255);
|
--background-hover: rgb(70 193 255);
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Component, ViewChild } from '@angular/core'
|
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 { ApiService } from 'src/app/services/api/api.service'
|
||||||
import { ActivatedRoute, NavigationExtras } from '@angular/router'
|
import { ActivatedRoute, NavigationExtras } from '@angular/router'
|
||||||
import { chill, isEmptyObject } from 'src/app/util/misc.util'
|
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 { Observable, of, Subscription } from 'rxjs'
|
||||||
import { wizardModal } from 'src/app/components/install-wizard/install-wizard.component'
|
import { wizardModal } from 'src/app/components/install-wizard/install-wizard.component'
|
||||||
import { WizardBaker } from 'src/app/components/install-wizard/prebaked-wizards'
|
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 { ConfigService, getManifest } from 'src/app/services/config.service'
|
||||||
import { PatchDbModel } from 'src/app/models/patch-db/patch-db-model'
|
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'
|
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'
|
import { Recommendation } from 'src/app/components/recommendation-button/recommendation-button.component'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-installed-show',
|
selector: 'app-show',
|
||||||
templateUrl: './app-installed-show.page.html',
|
templateUrl: './app-show.page.html',
|
||||||
styleUrls: ['./app-installed-show.page.scss'],
|
styleUrls: ['./app-show.page.scss'],
|
||||||
})
|
})
|
||||||
export class AppInstalledShowPage {
|
export class AppShowPage {
|
||||||
error: string
|
error: string
|
||||||
pkgId: string
|
pkgId: string
|
||||||
pkg: PackageDataEntry
|
pkg: PackageDataEntry
|
||||||
@@ -43,7 +42,6 @@ export class AppInstalledShowPage {
|
|||||||
private readonly modalCtrl: ModalController,
|
private readonly modalCtrl: ModalController,
|
||||||
private readonly apiService: ApiService,
|
private readonly apiService: ApiService,
|
||||||
private readonly wizardBaker: WizardBaker,
|
private readonly wizardBaker: WizardBaker,
|
||||||
private readonly popoverController: PopoverController,
|
|
||||||
private readonly config: ConfigService,
|
private readonly config: ConfigService,
|
||||||
public readonly patch: PatchDbModel,
|
public readonly patch: PatchDbModel,
|
||||||
public readonly connectionService: ConnectionService,
|
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 () {
|
scrollToRequirements () {
|
||||||
const el = document.getElementById('dependencies')
|
const el = document.getElementById('dependencies')
|
||||||
if (!el) return
|
if (!el) return
|
||||||
@@ -170,7 +154,7 @@ export class AppInstalledShowPage {
|
|||||||
state: { installRec },
|
state: { installRec },
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.navCtrl.navigateForward(`/services/marketplace/${depId}`, navigationExtras)
|
await this.navCtrl.navigateForward(`/marketplace/${depId}`, navigationExtras)
|
||||||
}
|
}
|
||||||
|
|
||||||
private async configureDep (depId: string): Promise<void> {
|
private async configureDep (depId: string): Promise<void> {
|
||||||
@@ -189,7 +173,7 @@ export class AppInstalledShowPage {
|
|||||||
state: { configRecommendation },
|
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> {
|
private async presentAlertStart (message: string): Promise<void> {
|
||||||
@@ -300,7 +284,7 @@ export class AppInstalledShowPage {
|
|||||||
disabled: [],
|
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',
|
title: 'Marketplace Listing',
|
||||||
icon: 'storefront-outline',
|
icon: 'storefront-outline',
|
||||||
color: 'danger',
|
color: 'danger',
|
||||||
@@ -4,69 +4,57 @@ import { Routes, RouterModule } from '@angular/router'
|
|||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
redirectTo: 'installed',
|
redirectTo: 'list',
|
||||||
pathMatch: 'full',
|
pathMatch: 'full',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'installed',
|
path: 'list',
|
||||||
loadChildren: () => import('./app-installed-list/app-installed-list.module').then(m => m.AppInstalledListPageModule),
|
loadChildren: () => import('./app-list/app-list.module').then(m => m.AppListPageModule),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'installed/:pkgId',
|
path: ':pkgId',
|
||||||
loadChildren: () => import('./app-installed-show/app-installed-show.module').then(m => m.AppInstalledShowPageModule),
|
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),
|
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),
|
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),
|
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),
|
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),
|
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),
|
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),
|
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),
|
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),
|
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),
|
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({
|
@NgModule({
|
||||||
|
|||||||
@@ -8,10 +8,10 @@
|
|||||||
</ion-header>
|
</ion-header>
|
||||||
|
|
||||||
<ion-content>
|
<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>
|
<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;" >
|
<ion-button (click)="setSelected(note.key)" expand="full" color="light" style="height: 50px;" >
|
||||||
<p style="position: absolute; left: 10px;">{{ note.key | displayEmver }}</p>
|
<p style="position: absolute; left: 10px;">{{ note.key | displayEmver }}</p>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Component } from '@angular/core'
|
import { Component } from '@angular/core'
|
||||||
import { ActivatedRoute } from '@angular/router'
|
import { ActivatedRoute } from '@angular/router'
|
||||||
import { AppAvailableService } from '../app-available.service'
|
import { MarketplaceService } from '../marketplace.service'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-release-notes',
|
selector: 'app-release-notes',
|
||||||
@@ -14,7 +14,7 @@ export class AppReleaseNotes {
|
|||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private readonly route: ActivatedRoute,
|
private readonly route: ActivatedRoute,
|
||||||
public aaService: AppAvailableService,
|
public aaService: MarketplaceService,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
@@ -2,7 +2,7 @@ import { NgModule } from '@angular/core'
|
|||||||
import { CommonModule } from '@angular/common'
|
import { CommonModule } from '@angular/common'
|
||||||
import { Routes, RouterModule } from '@angular/router'
|
import { Routes, RouterModule } from '@angular/router'
|
||||||
import { IonicModule } from '@ionic/angular'
|
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 { SharingModule } from '../../../modules/sharing.module'
|
||||||
import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.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 { 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 = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: AppAvailableListPage,
|
component: MarketplaceListPage,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -24,6 +24,6 @@ const routes: Routes = [
|
|||||||
SharingModule,
|
SharingModule,
|
||||||
BadgeMenuComponentModule,
|
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-text class="ion-text-wrap" color="danger">{{ error }}</ion-text>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<div class="scrollable">
|
<ion-card *ngIf="eos" class="eos-card" (click)="updateEos()">
|
||||||
<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-header>
|
<ion-card-header>
|
||||||
<ion-card-subtitle>Now Available...</ion-card-subtitle>
|
<ion-card-subtitle>Now Available...</ion-card-subtitle>
|
||||||
<ion-card-title>EmbassyOS Version {{ eos.version }}</ion-card-title>
|
<ion-card-title>EmbassyOS Version {{ eos.version }}</ion-card-title>
|
||||||
@@ -41,10 +29,42 @@
|
|||||||
</ion-card-content>
|
</ion-card-content>
|
||||||
</ion-card>
|
</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>
|
<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-item style="--inner-border-width: 0 0 .4px 0; --border-color: #525252;">
|
||||||
<ion-avatar style="margin-top: 8px;" slot="start">
|
<ion-avatar style="margin-top: 8px;" slot="start">
|
||||||
<img [src]="pkg.icon" />
|
<img [src]="pkg.icon" />
|
||||||
@@ -81,7 +101,7 @@
|
|||||||
">
|
">
|
||||||
{{ pkg.descriptionShort }}
|
{{ pkg.descriptionShort }}
|
||||||
</ion-card-content>
|
</ion-card-content>
|
||||||
</ion-card>
|
</ion-card> -->
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
@@ -8,8 +8,8 @@
|
|||||||
.scrollable {
|
.scrollable {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
background-color: var(--ion-color-light);
|
// background-color: var(--ion-color-light);
|
||||||
margin-bottom: 16px;
|
height: 80px;
|
||||||
|
|
||||||
/* Hide scrollbar for Chrome, Safari and Opera */
|
/* Hide scrollbar for Chrome, Safari and Opera */
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
@@ -23,6 +23,11 @@
|
|||||||
|
|
||||||
.eos-card {
|
.eos-card {
|
||||||
--background: linear-gradient(45deg, #101010 16%, var(--ion-color-danger) 150%);
|
--background: linear-gradient(45deg, #101010 16%, var(--ion-color-danger) 150%);
|
||||||
margin: 16px 10px;
|
margin: 0 10px 16px 10px;
|
||||||
cursor: pointer;
|
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'
|
import { PackageState } from 'src/app/models/patch-db/data-model'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-available-list',
|
selector: 'marketplace-list',
|
||||||
templateUrl: './app-available-list.page.html',
|
templateUrl: './marketplace-list.page.html',
|
||||||
styleUrls: ['./app-available-list.page.scss'],
|
styleUrls: ['./marketplace-list.page.scss'],
|
||||||
})
|
})
|
||||||
export class AppAvailableListPage {
|
export class MarketplaceListPage {
|
||||||
pageLoading = true
|
pageLoading = true
|
||||||
pkgsLoading = true
|
pkgsLoading = true
|
||||||
error = ''
|
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 { CommonModule } from '@angular/common'
|
||||||
import { Routes, RouterModule } from '@angular/router'
|
import { Routes, RouterModule } from '@angular/router'
|
||||||
import { IonicModule } from '@ionic/angular'
|
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 { SharingModule } from 'src/app/modules/sharing.module'
|
||||||
import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-back.component.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 { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.module'
|
||||||
import { StatusComponentModule } from 'src/app/components/status/status.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 { RecommendationButtonComponentModule } from 'src/app/components/recommendation-button/recommendation-button.component.module'
|
||||||
import { InstallWizardComponentModule } from 'src/app/components/install-wizard/install-wizard.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 = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: AppAvailableShowPage,
|
component: MarketplaceShowPage,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -29,8 +28,7 @@ const routes: Routes = [
|
|||||||
RecommendationButtonComponentModule,
|
RecommendationButtonComponentModule,
|
||||||
BadgeMenuComponentModule,
|
BadgeMenuComponentModule,
|
||||||
InstallWizardComponentModule,
|
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 { Component } from '@angular/core'
|
||||||
import { ActivatedRoute } from '@angular/router'
|
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 { Recommendation } from 'src/app/components/recommendation-button/recommendation-button.component'
|
||||||
import { wizardModal } from 'src/app/components/install-wizard/install-wizard.component'
|
import { wizardModal } from 'src/app/components/install-wizard/install-wizard.component'
|
||||||
import { WizardBaker } from 'src/app/components/install-wizard/prebaked-wizards'
|
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 { Emver } from 'src/app/services/emver.service'
|
||||||
import { displayEmver } from 'src/app/pipes/emver.pipe'
|
import { displayEmver } from 'src/app/pipes/emver.pipe'
|
||||||
import { pauseFor } from 'src/app/util/misc.util'
|
import { pauseFor } from 'src/app/util/misc.util'
|
||||||
import { PatchDbModel } from 'src/app/models/patch-db/patch-db-model'
|
import { PatchDbModel } from 'src/app/models/patch-db/patch-db-model'
|
||||||
import { PackageState } from 'src/app/models/patch-db/data-model'
|
import { PackageState } from 'src/app/models/patch-db/data-model'
|
||||||
import { AppAvailableService } from '../app-available.service'
|
import { MarketplaceService } from '../marketplace.service'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-available-show',
|
selector: 'marketplace-show',
|
||||||
templateUrl: './app-available-show.page.html',
|
templateUrl: './marketplace-show.page.html',
|
||||||
styleUrls: ['./app-available-show.page.scss'],
|
styleUrls: ['./marketplace-show.page.scss'],
|
||||||
})
|
})
|
||||||
export class AppAvailableShowPage {
|
export class MarketplaceShowPage {
|
||||||
error = ''
|
error = ''
|
||||||
pkgId: string
|
pkgId: string
|
||||||
|
|
||||||
@@ -26,18 +25,15 @@ export class AppAvailableShowPage {
|
|||||||
rec: Recommendation | null = null
|
rec: Recommendation | null = null
|
||||||
showRec = true
|
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 (
|
constructor (
|
||||||
private readonly route: ActivatedRoute,
|
private readonly route: ActivatedRoute,
|
||||||
private readonly alertCtrl: AlertController,
|
private readonly alertCtrl: AlertController,
|
||||||
private readonly modalCtrl: ModalController,
|
private readonly modalCtrl: ModalController,
|
||||||
private readonly wizardBaker: WizardBaker,
|
private readonly wizardBaker: WizardBaker,
|
||||||
private readonly navCtrl: NavController,
|
private readonly navCtrl: NavController,
|
||||||
private readonly popoverController: PopoverController,
|
|
||||||
private readonly emver: Emver,
|
private readonly emver: Emver,
|
||||||
public readonly patch: PatchDbModel,
|
public readonly patch: PatchDbModel,
|
||||||
public aaService: AppAvailableService,
|
public marketplaceService: MarketplaceService,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
async ngOnInit () {
|
async ngOnInit () {
|
||||||
@@ -48,38 +44,24 @@ export class AppAvailableShowPage {
|
|||||||
async getPkg (version?: string): Promise<void> {
|
async getPkg (version?: string): Promise<void> {
|
||||||
this.pkgId = this.route.snapshot.paramMap.get('pkgId')
|
this.pkgId = this.route.snapshot.paramMap.get('pkgId')
|
||||||
try {
|
try {
|
||||||
await this.aaService.setPkg(this.pkgId, version)
|
await this.marketplaceService.setPkg(this.pkgId, version)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
this.error = e.message
|
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 () {
|
async presentAlertVersions () {
|
||||||
const alert = await this.alertCtrl.create({
|
const alert = await this.alertCtrl.create({
|
||||||
header: 'Versions',
|
header: 'Versions',
|
||||||
backdropDismiss: false,
|
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 {
|
return {
|
||||||
name: v, // for CSS
|
name: v, // for CSS
|
||||||
type: 'radio',
|
type: 'radio',
|
||||||
label: displayEmver(v), // appearance on screen
|
label: displayEmver(v), // appearance on screen
|
||||||
value: v, // literal SEM version value
|
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: [
|
buttons: [
|
||||||
@@ -99,7 +81,7 @@ export class AppAvailableShowPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async install () {
|
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(
|
const { cancelled } = await wizardModal(
|
||||||
this.modalCtrl,
|
this.modalCtrl,
|
||||||
this.wizardBaker.install({
|
this.wizardBaker.install({
|
||||||
@@ -115,7 +97,7 @@ export class AppAvailableShowPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async update (action: 'update' | 'downgrade') {
|
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 = {
|
const value = {
|
||||||
id,
|
id,
|
||||||
title,
|
title,
|
||||||
@@ -5,7 +5,7 @@ import { ApiService } from 'src/app/services/api/api.service'
|
|||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
})
|
})
|
||||||
export class AppAvailableService {
|
export class MarketplaceService {
|
||||||
pkgs: { [id: string]: AvailableShow } = { }
|
pkgs: { [id: string]: AvailableShow } = { }
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
</h2>
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
{{ not['created-at'] | date: 'short' }}
|
{{ 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'] }}
|
- {{ not['package-id'] }}
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -69,7 +69,6 @@
|
|||||||
<ion-icon slot="icon-only" name="copy-outline"></ion-icon>
|
<ion-icon slot="icon-only" name="copy-outline"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item-divider></ion-item-divider>
|
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ion-item-group>
|
</ion-item-group>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { NgModule } from '@angular/core'
|
import { NgModule } from '@angular/core'
|
||||||
import { CommonModule } from '@angular/common'
|
import { CommonModule } from '@angular/common'
|
||||||
import { IonicModule } from '@ionic/angular'
|
import { IonicModule } from '@ionic/angular'
|
||||||
import { GeneralSettingsPage } from './general-settings.page'
|
import { PreferencesPage } from './preferences.page'
|
||||||
import { Routes, RouterModule } from '@angular/router'
|
import { Routes, RouterModule } from '@angular/router'
|
||||||
import { SharingModule } from 'src/app/modules/sharing.module'
|
import { SharingModule } from 'src/app/modules/sharing.module'
|
||||||
import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-back.component.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 = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: GeneralSettingsPage,
|
component: PreferencesPage,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ const routes: Routes = [
|
|||||||
PwaBackComponentModule,
|
PwaBackComponentModule,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
GeneralSettingsPage,
|
PreferencesPage,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class GeneralSettingsPageModule { }
|
export class PreferencesPageModule { }
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
<ion-buttons slot="start">
|
<ion-buttons slot="start">
|
||||||
<pwa-back-button></pwa-back-button>
|
<pwa-back-button></pwa-back-button>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
<ion-title>General Settings</ion-title>
|
<ion-title>Preferences</ion-title>
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-header>
|
</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'
|
import { PatchDbModel } from 'src/app/models/patch-db/patch-db-model'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'general-settings',
|
selector: 'preferences',
|
||||||
templateUrl: './general-settings.page.html',
|
templateUrl: './preferences.page.html',
|
||||||
styleUrls: ['./general-settings.page.scss'],
|
styleUrls: ['./preferences.page.scss'],
|
||||||
})
|
})
|
||||||
export class GeneralSettingsPage {
|
export class PreferencesPage {
|
||||||
constructor (
|
constructor (
|
||||||
private readonly serverConfigService: ServerConfigService,
|
private readonly serverConfigService: ServerConfigService,
|
||||||
public readonly patch: PatchDbModel,
|
public readonly patch: PatchDbModel,
|
||||||
@@ -23,8 +23,8 @@ const routes: Routes = [
|
|||||||
loadChildren: () => import('./server-logs/server-logs.module').then(m => m.ServerLogsPageModule),
|
loadChildren: () => import('./server-logs/server-logs.module').then(m => m.ServerLogsPageModule),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'settings',
|
path: 'preferences',
|
||||||
loadChildren: () => import('./general-settings/general-settings.module').then(m => m.GeneralSettingsPageModule),
|
loadChildren: () => import('./preferences/preferences.module').then(m => m.PreferencesPageModule),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'wifi',
|
path: 'wifi',
|
||||||
|
|||||||
@@ -7,65 +7,17 @@
|
|||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
|
|
||||||
<ion-content class="ion-padding-top ion-padding-bottom">
|
<ion-content>
|
||||||
|
|
||||||
<ion-item-divider>Backups</ion-item-divider>
|
<ion-grid>
|
||||||
|
<ion-row>
|
||||||
<ion-item [routerLink]="['backup']">
|
<ion-col *ngFor="let cat of settings | keyvalue : asIsOrder" sizeXs="12" sizeMd="6">
|
||||||
<ion-icon slot="start" name="save-outline"></ion-icon>
|
<ion-item-divider>{{ cat.key }}</ion-item-divider>
|
||||||
<ion-label>Create Backup</ion-label>
|
<ion-item style="cursor: pointer;" button *ngFor="let button of cat.value" (click)="button.action()">
|
||||||
</ion-item>
|
<ion-icon slot="start" [name]="button.icon"></ion-icon>
|
||||||
|
<ion-label>{{ button.title }}</ion-label>
|
||||||
<ion-item-divider>Insights</ion-item-divider>
|
</ion-item>
|
||||||
|
</ion-col>
|
||||||
<ion-item-group>
|
</ion-row>
|
||||||
<ion-item [routerLink]="['specs']">
|
</ion-grid>
|
||||||
<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-content>
|
</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 { Component } from '@angular/core'
|
||||||
import { LoadingOptions } from '@ionic/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 { ApiService } from 'src/app/services/api/api.service'
|
||||||
import { LoaderService } from 'src/app/services/loader.service'
|
import { LoaderService } from 'src/app/services/loader.service'
|
||||||
import { PatchDbModel } from 'src/app/models/patch-db/patch-db-model'
|
import { PatchDbModel } from 'src/app/models/patch-db/patch-db-model'
|
||||||
import { ServerStatus } from 'src/app/models/patch-db/data-model'
|
import { ServerStatus } from 'src/app/models/patch-db/data-model'
|
||||||
|
import { ActivatedRoute } from '@angular/router'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'server-show',
|
selector: 'server-show',
|
||||||
@@ -13,15 +14,21 @@ import { ServerStatus } from 'src/app/models/patch-db/data-model'
|
|||||||
})
|
})
|
||||||
export class ServerShowPage {
|
export class ServerShowPage {
|
||||||
ServerStatus = ServerStatus
|
ServerStatus = ServerStatus
|
||||||
|
settings: ServerSettings = { }
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private readonly alertCtrl: AlertController,
|
private readonly alertCtrl: AlertController,
|
||||||
private readonly loader: LoaderService,
|
private readonly loader: LoaderService,
|
||||||
private readonly apiService: ApiService,
|
private readonly apiService: ApiService,
|
||||||
private readonly modalCtrl: ModalController,
|
private readonly navCtrl: NavController,
|
||||||
|
private readonly route: ActivatedRoute,
|
||||||
public readonly patch: PatchDbModel,
|
public readonly patch: PatchDbModel,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
|
ngOnInit () {
|
||||||
|
this.setButtons()
|
||||||
|
}
|
||||||
|
|
||||||
async presentAlertRestart () {
|
async presentAlertRestart () {
|
||||||
const alert = await this.alertCtrl.create({
|
const alert = await this.alertCtrl.create({
|
||||||
backdropDismiss: false,
|
backdropDismiss: false,
|
||||||
@@ -73,7 +80,7 @@ export class ServerShowPage {
|
|||||||
// this.serverModel.markUnreachable()
|
// this.serverModel.markUnreachable()
|
||||||
await this.apiService.restartServer({ })
|
await this.apiService.restartServer({ })
|
||||||
})
|
})
|
||||||
.catch(e => this.setError(e))
|
.catch(console.error)
|
||||||
}
|
}
|
||||||
|
|
||||||
private async shutdown () {
|
private async shutdown () {
|
||||||
@@ -83,11 +90,74 @@ export class ServerShowPage {
|
|||||||
// this.serverModel.markUnreachable()
|
// this.serverModel.markUnreachable()
|
||||||
await this.apiService.shutdownServer({ })
|
await this.apiService.shutdownServer({ })
|
||||||
})
|
})
|
||||||
.catch(e => this.setError(e))
|
.catch(console.error)
|
||||||
}
|
}
|
||||||
|
|
||||||
setError (e: Error) {
|
private setButtons (): void {
|
||||||
console.error(e)
|
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
|
} 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> {
|
async getMarketplaceData (params: RR.GetMarketplaceDataReq): Promise<RR.GetMarketplaceDataRes> {
|
||||||
await pauseFor(2000)
|
await pauseFor(2000)
|
||||||
return {
|
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',
|
id: 'lnd',
|
||||||
title: 'Lightning Network Daemon',
|
title: 'LND',
|
||||||
version: '0.11.1',
|
version: '0.11.1',
|
||||||
descriptionShort: 'A BOLT-compliant, lightning network node.',
|
descriptionShort: 'A BOLT-compliant, lightning network node.',
|
||||||
icon: 'assets/img/service-icons/lnd.png',
|
icon: 'assets/img/service-icons/lnd.png',
|
||||||
@@ -157,7 +157,7 @@ export module Mock {
|
|||||||
|
|
||||||
export const MockManifestLnd: Manifest = {
|
export const MockManifestLnd: Manifest = {
|
||||||
id: 'lnd',
|
id: 'lnd',
|
||||||
title: 'Lightning Network Daemon',
|
title: 'LND',
|
||||||
version: '0.11.1',
|
version: '0.11.1',
|
||||||
description: {
|
description: {
|
||||||
short: 'A bolt spec compliant client.',
|
short: 'A bolt spec compliant client.',
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ function handleInstalledState (status: Status): PkgStatusRendering {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Object.keys(status['dependency-errors']).length) {
|
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) {
|
switch (status.main.status) {
|
||||||
@@ -36,7 +36,7 @@ function handleRunningState (status: MainStatusRunning): PkgStatusRendering {
|
|||||||
if (Object.values(status.health).some(h => h.result === 'failure')) {
|
if (Object.values(status.health).some(h => h.result === 'failure')) {
|
||||||
return { display: 'Needs Attention', color: 'danger', showDots: false, feStatus: FEStatus.NeedsAttention }
|
return { display: 'Needs Attention', color: 'danger', showDots: false, feStatus: FEStatus.NeedsAttention }
|
||||||
} else if (Object.values(status.health).some(h => h.result === 'starting')) {
|
} 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')) {
|
} else if (Object.values(status.health).some(h => h.result === 'loading')) {
|
||||||
const firstLoading = Object.values(status.health).find(h => h.result === 'loading') as HealthCheckResultLoading
|
const firstLoading = Object.values(status.health).find(h => h.result === 'loading') as HealthCheckResultLoading
|
||||||
return { display: firstLoading.message, color: 'warning', showDots: true, feStatus: FEStatus.Loading }
|
return { display: firstLoading.message, color: 'warning', showDots: true, feStatus: FEStatus.Loading }
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ export class StartupAlertsNotifier {
|
|||||||
{
|
{
|
||||||
text: 'View in Marketplace',
|
text: 'View in Marketplace',
|
||||||
handler: () => {
|
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;
|
white-space: normal !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ion-card-title {
|
||||||
|
font-family: 'Montserrat';
|
||||||
|
}
|
||||||
|
|
||||||
ion-title {
|
ion-title {
|
||||||
font-family: 'Montserrat';
|
font-family: 'Montserrat';
|
||||||
font-weight: unset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ion-textarea {
|
ion-textarea {
|
||||||
@@ -272,11 +275,6 @@ ion-avatar {
|
|||||||
--border-radius: var(--icon-border-radius);
|
--border-radius: var(--icon-border-radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-white-space {
|
|
||||||
--white-space: 0;
|
|
||||||
--box-shadow: 3px 3px 10px var(--ion-color-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.notifier-item {
|
.notifier-item {
|
||||||
margin: 12px;
|
margin: 12px;
|
||||||
margin-top: 0px;
|
margin-top: 0px;
|
||||||
@@ -301,7 +299,6 @@ ion-item-divider {
|
|||||||
color: var(--ion-color-medium);
|
color: var(--ion-color-medium);
|
||||||
font-size: medium;
|
font-size: medium;
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
font-weight: unset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dots {
|
.dots {
|
||||||
|
|||||||
Reference in New Issue
Block a user