diff --git a/frontend/projects/marketplace/src/pages/list/categories/categories.component.html b/frontend/projects/marketplace/src/pages/list/categories/categories.component.html index 61cbab592..f04d2dd83 100644 --- a/frontend/projects/marketplace/src/pages/list/categories/categories.component.html +++ b/frontend/projects/marketplace/src/pages/list/categories/categories.component.html @@ -2,12 +2,8 @@ *ngFor="let cat of categories" fill="clear" class="category" - [color]="cat === 'updates' && updatesAvailable ? 'success' : undefined" - [class.category_selected]="cat === category" + [class.category_selected]="cat === category && !disableCategories" (click)="switchCategory(cat)" > {{ cat }} - -   ({{ updatesAvailable }}) - diff --git a/frontend/projects/marketplace/src/pages/list/categories/categories.component.ts b/frontend/projects/marketplace/src/pages/list/categories/categories.component.ts index 17e27bf4d..67d5c0559 100644 --- a/frontend/projects/marketplace/src/pages/list/categories/categories.component.ts +++ b/frontend/projects/marketplace/src/pages/list/categories/categories.component.ts @@ -23,7 +23,7 @@ export class CategoriesComponent { category = '' @Input() - updatesAvailable = 0 + disableCategories = false @Output() readonly categoryChange = new EventEmitter() diff --git a/frontend/projects/marketplace/src/pages/show/additional/additional.component.html b/frontend/projects/marketplace/src/pages/show/additional/additional.component.html index 733facaba..c1e70f53c 100644 --- a/frontend/projects/marketplace/src/pages/show/additional/additional.component.html +++ b/frontend/projects/marketplace/src/pages/show/additional/additional.component.html @@ -1,110 +1,108 @@ Additional Info - - - - - - + + + + + + +

Git Hash

+

{{ gitHash }}

+
+ +
+ +

Git Hash

-

{{ gitHash }}

+

Unknown

-
- - - -

Git Hash

-

Unknown

-
-
-
- - -

Other Versions

-

Click to view other versions

-
- -
- - -

License

-

{{ manifest.license }}

-
- -
- - -

Instructions

-

Click to view instructions

-
- -
-
-
- - - - -

Source Repository

-

{{ manifest['upstream-repo'] }}

-
- -
- - -

Wrapper Repository

-

{{ manifest['wrapper-repo'] }}

-
- -
- - -

Support Site

-

{{ manifest['support-site'] || 'Not provided' }}

-
- -
- - -

Marketing Site

-

{{ manifest['marketing-site'] || 'Not provided' }}

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

Other Versions

+

Click to view other versions

+
+ +
+ + +

License

+

{{ manifest.license }}

+
+ +
+ + +

Instructions

+

Click to view instructions

+
+ +
+ + + + + + +

Source Repository

+

{{ manifest['upstream-repo'] }}

+
+ +
+ + +

Wrapper Repository

+

{{ manifest['wrapper-repo'] }}

+
+ +
+ + +

Support Site

+

{{ manifest['support-site'] || 'Not provided' }}

+
+ +
+ + +

Marketing Site

+

{{ manifest['marketing-site'] || 'Not provided' }}

+
+ +
+
+
+ + diff --git a/frontend/projects/marketplace/src/pipes/filter-packages.pipe.ts b/frontend/projects/marketplace/src/pipes/filter-packages.pipe.ts index 733c05add..c5aea9f8c 100644 --- a/frontend/projects/marketplace/src/pipes/filter-packages.pipe.ts +++ b/frontend/projects/marketplace/src/pipes/filter-packages.pipe.ts @@ -1,6 +1,6 @@ import { NgModule, Pipe, PipeTransform } from '@angular/core' import { Emver } from '@start9labs/shared' -import { MarketplaceManifest, MarketplacePkg } from '../types' +import { MarketplacePkg } from '../types' import Fuse from 'fuse.js' @Pipe({ @@ -13,75 +13,40 @@ export class FilterPackagesPipe implements PipeTransform { packages: MarketplacePkg[], query: string, category: string, - local: Record = {}, ): MarketplacePkg[] { // query if (query) { let options: Fuse.IFuseOptions = { includeScore: true, includeMatches: true, + ignoreLocation: true, + useExtendedSearch: true, + keys: [ + { + name: 'manifest.title', + weight: 1, + }, + { + name: 'manifest.id', + weight: 0.5, + }, + { + name: 'manifest.description.short', + weight: 0.4, + }, + { + name: 'manifest.description.long', + weight: 0.1, + }, + ], } - if (query.length < 4) { - options = { - ...options, - threshold: 0, - location: 0, - distance: 1, - keys: [ - { - name: 'manifest.title', - weight: 1, - }, - { - name: 'manifest.id', - weight: 0.5, - }, - ], - } - } else { - options = { - ...options, - ignoreLocation: true, - useExtendedSearch: true, - keys: [ - { - name: 'manifest.title', - weight: 1, - }, - { - name: 'manifest.id', - weight: 0.5, - }, - { - name: 'manifest.description.short', - weight: 0.4, - }, - { - name: 'manifest.description.long', - weight: 0.1, - }, - ], - } - query = `'${query}` - } + query = `'${query}` const fuse = new Fuse(packages, options) return fuse.search(query).map(p => p.item) } - // updates - if (category === 'updates') { - return packages.filter( - ({ manifest }) => - local[manifest.id] && - this.emver.compare( - manifest.version, - local[manifest.id].manifest.version, - ) === 1, - ) - } - // category return packages .filter(p => category === 'all' || p.categories.includes(category)) diff --git a/frontend/projects/ui/src/app/pages/apps-routes/app-show/app-show.module.ts b/frontend/projects/ui/src/app/pages/apps-routes/app-show/app-show.module.ts index d338e9a81..5a8429a52 100644 --- a/frontend/projects/ui/src/app/pages/apps-routes/app-show/app-show.module.ts +++ b/frontend/projects/ui/src/app/pages/apps-routes/app-show/app-show.module.ts @@ -8,7 +8,6 @@ import { StatusComponentModule } from 'src/app/components/status/status.componen import { AppConfigPageModule } from 'src/app/modals/app-config/app-config.module' import { LaunchablePipeModule } from 'src/app/pipes/launchable/launchable.module' import { UiPipeModule } from 'src/app/pipes/ui/ui.module' -import { AppShowHeaderComponent } from './components/app-show-header/app-show-header.component' import { AppShowProgressComponent } from './components/app-show-progress/app-show-progress.component' import { AppShowStatusComponent } from './components/app-show-status/app-show-status.component' import { AppShowDependenciesComponent } from './components/app-show-dependencies/app-show-dependencies.component' @@ -38,7 +37,6 @@ const routes: Routes = [ ToButtonsPipe, ToDependenciesPipe, ToStatusPipe, - AppShowHeaderComponent, AppShowProgressComponent, AppShowStatusComponent, AppShowDependenciesComponent, diff --git a/frontend/projects/ui/src/app/pages/apps-routes/app-show/app-show.page.html b/frontend/projects/ui/src/app/pages/apps-routes/app-show/app-show.page.html index 60e8b1b4b..39758cf11 100644 --- a/frontend/projects/ui/src/app/pages/apps-routes/app-show/app-show.page.html +++ b/frontend/projects/ui/src/app/pages/apps-routes/app-show/app-show.page.html @@ -1,7 +1,20 @@ - - + + + + + + Service Details + + + + + +
+ +

{{ pkg.manifest.title }}

+

{{ pkg.manifest.version | displayEmver }}

+
- - -
+
+ diff --git a/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-additional/app-show-additional.component.html b/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-additional/app-show-additional.component.html index 066ed85b6..ee60aeec0 100644 --- a/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-additional/app-show-additional.component.html +++ b/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-additional/app-show-additional.component.html @@ -1,85 +1,83 @@ Additional Info - - - - - + + + + + + +

Version

+

{{ manifest.version | displayEmver }}

+
+
+ + +

Git Hash

+

{{ gitHash }}

+
+ +
+ - -

Version

-

{{ manifest.version | displayEmver }}

-
-
-

Git Hash

-

{{ gitHash }}

+

Unknown

-
- - - -

Git Hash

-

Unknown

-
-
-
- - -

License

-

{{ manifest.license }}

-
- -
-
-
- - - - -

Source Repository

-

{{ manifest['upstream-repo'] }}

-
- -
- - -

Wrapper Repository

-

{{ manifest['wrapper-repo'] }}

-
- -
- - -

Support Site

-

{{ manifest['support-site'] || 'Not provided' }}

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

License

+

{{ manifest.license }}

+
+ +
+ + + + + + +

Source Repository

+

{{ manifest['upstream-repo'] }}

+
+ +
+ + +

Wrapper Repository

+

{{ manifest['wrapper-repo'] }}

+
+ +
+ + +

Support Site

+

{{ manifest['support-site'] || 'Not provided' }}

+
+ +
+
+
+ + diff --git a/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-header/app-show-header.component.html b/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-header/app-show-header.component.html deleted file mode 100644 index fc869729f..000000000 --- a/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-header/app-show-header.component.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - -

- {{ pkg.manifest.title }} -

-

{{ pkg.manifest.version | displayEmver }}

-
-
-
-
diff --git a/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-header/app-show-header.component.scss b/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-header/app-show-header.component.scss deleted file mode 100644 index 0dd950e80..000000000 --- a/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-header/app-show-header.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -.less-large { - font-size: 18px !important; -} diff --git a/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-header/app-show-header.component.ts b/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-header/app-show-header.component.ts deleted file mode 100644 index fd234a9e9..000000000 --- a/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-header/app-show-header.component.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { ChangeDetectionStrategy, Component, Input } from '@angular/core' -import { PackageDataEntry } from 'src/app/services/patch-db/data-model' - -@Component({ - selector: 'app-show-header', - templateUrl: './app-show-header.component.html', - styleUrls: ['./app-show-header.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class AppShowHeaderComponent { - @Input() - pkg!: PackageDataEntry -} diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.page.html b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.page.html index 12d77e7a8..d57325eb1 100644 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.page.html +++ b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.page.html @@ -36,46 +36,35 @@ - - + -
+
- -
+ + -

All services are up to date!

-
- - - - - - - - -
-
+ + + +
+
+ diff --git a/frontend/projects/ui/src/app/pages/updates/updates.page.html b/frontend/projects/ui/src/app/pages/updates/updates.page.html index 3d2f802be..52751be7b 100644 --- a/frontend/projects/ui/src/app/pages/updates/updates.page.html +++ b/frontend/projects/ui/src/app/pages/updates/updates.page.html @@ -30,11 +30,19 @@ > - + -

{{ pkg.manifest.title }}

+

+ {{ pkg.manifest.title }} +

{{ local.manifest.version }}    @@ -43,6 +51,9 @@

+

+ {{ error }} +

@@ -62,11 +73,11 @@ > - Update + {{ errors[pkg.manifest.id] ? 'Retry' : 'Update' }} diff --git a/frontend/projects/ui/src/app/pages/updates/updates.page.scss b/frontend/projects/ui/src/app/pages/updates/updates.page.scss index 04ecc4019..546be123f 100644 --- a/frontend/projects/ui/src/app/pages/updates/updates.page.scss +++ b/frontend/projects/ui/src/app/pages/updates/updates.page.scss @@ -1,6 +1,7 @@ .service-avatar { position: absolute; top: 6px; + cursor: pointer; } ion-label { diff --git a/frontend/projects/ui/src/app/pages/updates/updates.page.ts b/frontend/projects/ui/src/app/pages/updates/updates.page.ts index 3669cfc35..0804d44b2 100644 --- a/frontend/projects/ui/src/app/pages/updates/updates.page.ts +++ b/frontend/projects/ui/src/app/pages/updates/updates.page.ts @@ -14,10 +14,18 @@ import { MarketplacePkg, StoreIdentity, } from '@start9labs/marketplace' -import { Emver } from '@start9labs/shared' +import { Emver, isEmptyObject } from '@start9labs/shared' import { Pipe, PipeTransform } from '@angular/core' import { combineLatest, Observable } from 'rxjs' import { PrimaryRendering } from '../../services/pkg-status-rendering.service' +import { + AlertController, + LoadingController, + NavController, +} from '@ionic/angular' +import { hasCurrentDeps } from 'src/app/util/has-deps' +import { getAllPackages } from 'src/app/util/get-package-data' +import { Breakages } from 'src/app/services/api/api.types' interface UpdatesData { hosts: StoreIdentity[] @@ -33,6 +41,7 @@ interface UpdatesData { }) export class UpdatesPage { queued: Record = {} + errors: Record = {} readonly data$: Observable = combineLatest({ hosts: this.marketplaceService.getKnownHosts$(), @@ -49,11 +58,115 @@ export class UpdatesPage { private readonly marketplaceService: MarketplaceService, private readonly api: ApiService, private readonly patch: PatchDB, + private readonly navCtrl: NavController, + private readonly loadingCtrl: LoadingController, + private readonly alertCtrl: AlertController, ) {} - async update(id: string, url: string): Promise { + viewInMarketplace(pkg: PackageDataEntry) { + const url = pkg.installed?.['marketplace-url'] + const queryParams = url ? { url } : {} + + this.navCtrl.navigateForward([`marketplace/${pkg.manifest.id}`], { + queryParams, + }) + } + + async tryUpdate( + manifest: MarketplaceManifest, + url: string, + local: PackageDataEntry, + ): Promise { + const { id, version } = manifest + + delete this.errors[id] this.queued[id] = true - this.api.installPackage({ id, 'marketplace-url': url }) + + if (hasCurrentDeps(local)) { + this.dryUpdate(manifest, url) + } else { + this.update(id, version, url) + } + } + + private async dryUpdate(manifest: MarketplaceManifest, url: string) { + const loader = await this.loadingCtrl.create({ + message: 'Checking dependent services...', + }) + await loader.present() + + const { id, version } = manifest + + try { + const breakages = await this.api.dryUpdatePackage({ + id, + version: `${version}`, + }) + await loader.dismiss() + + if (isEmptyObject(breakages)) { + this.update(id, version, url) + } else { + const proceed = await this.presentAlertBreakages( + manifest.title, + breakages, + ) + if (proceed) { + this.update(id, version, url) + } else { + delete this.queued[id] + } + } + } catch (e: any) { + delete this.queued[id] + this.errors[id] = e.message + } + } + + private async presentAlertBreakages( + title: string, + breakages: Breakages, + ): Promise { + let message: string = `As a result of updating ${title}, the following services will no longer work properly and may crash:
    ` + const localPkgs = await getAllPackages(this.patch) + const bullets = Object.keys(breakages).map(id => { + const title = localPkgs[id].manifest.title + return `
  • ${title}
  • ` + }) + message = `${message}${bullets.join('')}
` + + return new Promise(async resolve => { + const alert = await this.alertCtrl.create({ + header: 'Warning', + message, + buttons: [ + { + text: 'Cancel', + role: 'cancel', + handler: () => { + resolve(false) + }, + }, + { + text: 'Continue', + handler: () => { + resolve(true) + }, + cssClass: 'enter-click', + }, + ], + cssClass: 'alert-warning-message', + }) + + await alert.present() + }) + } + + private update(id: string, version: string, url: string) { + this.marketplaceService.installPackage(id, version, url).catch(e => { + delete this.queued[id] + this.errors[id] = e.message + }) } } diff --git a/frontend/projects/ui/src/styles.scss b/frontend/projects/ui/src/styles.scss index c75384649..eaaf238c1 100644 --- a/frontend/projects/ui/src/styles.scss +++ b/frontend/projects/ui/src/styles.scss @@ -155,6 +155,13 @@ img { border-radius: 100%; } +ion-back-button { + margin-left: 16px; + &::part(native) { + border: 1px solid white; + } +} + ion-card-title { font-family: 'Montserrat'; }