diff --git a/frontend/projects/diagnostic-ui/src/app/app.module.ts b/frontend/projects/diagnostic-ui/src/app/app.module.ts index 53a13cc74..2e436e695 100644 --- a/frontend/projects/diagnostic-ui/src/app/app.module.ts +++ b/frontend/projects/diagnostic-ui/src/app/app.module.ts @@ -8,9 +8,8 @@ import { HttpClientModule } from '@angular/common/http' import { ApiService } from './services/api/api.service' import { MockApiService } from './services/api/mock-api.service' import { LiveApiService } from './services/api/live-api.service' -import { HttpService } from './services/http.service' import { GlobalErrorHandler } from './services/global-error-handler.service' -import { WorkspaceConfig } from '@start9labs/shared' +import { AbstractApiService, WorkspaceConfig } from '@start9labs/shared' const { useMocks } = require('../../../../config.json') as WorkspaceConfig @@ -29,14 +28,11 @@ const { useMocks } = require('../../../../config.json') as WorkspaceConfig { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }, { provide: ApiService, - useFactory: (http: HttpService) => { - if (useMocks) { - return new MockApiService() - } else { - return new LiveApiService(http) - } - }, - deps: [HttpService], + useClass: useMocks ? MockApiService : LiveApiService, + }, + { + provide: AbstractApiService, + useExisting: ApiService, }, { provide: ErrorHandler, useClass: GlobalErrorHandler }, ], diff --git a/frontend/projects/marketplace/src/pages/list/categories/categories.component.html b/frontend/projects/marketplace/src/pages/list/categories/categories.component.html new file mode 100644 index 000000000..4e99a21c2 --- /dev/null +++ b/frontend/projects/marketplace/src/pages/list/categories/categories.component.html @@ -0,0 +1,9 @@ + + {{ cat }} + diff --git a/frontend/projects/marketplace/src/pages/list/categories/categories.component.scss b/frontend/projects/marketplace/src/pages/list/categories/categories.component.scss new file mode 100644 index 000000000..f558e8c32 --- /dev/null +++ b/frontend/projects/marketplace/src/pages/list/categories/categories.component.scss @@ -0,0 +1,14 @@ +:host { + display: block; +} + +.category { + font-weight: 300; + color: var(--ion-color-dark-shade); + + &_selected { + font-weight: bold; + font-size: 17px; + color: var(--color); + } +} diff --git a/frontend/projects/marketplace/src/pages/list/categories/categories.component.ts b/frontend/projects/marketplace/src/pages/list/categories/categories.component.ts new file mode 100644 index 000000000..6719cce99 --- /dev/null +++ b/frontend/projects/marketplace/src/pages/list/categories/categories.component.ts @@ -0,0 +1,32 @@ +import { + ChangeDetectionStrategy, + Component, + EventEmitter, + Input, + Output, +} from '@angular/core' + +@Component({ + selector: 'marketplace-categories', + templateUrl: 'categories.component.html', + styleUrls: ['categories.component.scss'], + host: { + class: 'hidden-scrollbar ion-text-center', + }, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class CategoriesComponent { + @Input() + categories = new Set() + + @Input() + category = '' + + @Output() + readonly categoryChange = new EventEmitter() + + switchCategory(category: string): void { + this.category = category + this.categoryChange.emit(category) + } +} diff --git a/frontend/projects/marketplace/src/pages/list/categories/categories.module.ts b/frontend/projects/marketplace/src/pages/list/categories/categories.module.ts new file mode 100644 index 000000000..b792ae891 --- /dev/null +++ b/frontend/projects/marketplace/src/pages/list/categories/categories.module.ts @@ -0,0 +1,12 @@ +import { CommonModule } from '@angular/common' +import { NgModule } from '@angular/core' +import { IonicModule } from '@ionic/angular' + +import { CategoriesComponent } from './categories.component' + +@NgModule({ + imports: [CommonModule, IonicModule], + declarations: [CategoriesComponent], + exports: [CategoriesComponent], +}) +export class CategoriesModule {} diff --git a/frontend/projects/marketplace/src/pages/list/item/item.component.html b/frontend/projects/marketplace/src/pages/list/item/item.component.html new file mode 100644 index 000000000..47478892a --- /dev/null +++ b/frontend/projects/marketplace/src/pages/list/item/item.component.html @@ -0,0 +1,10 @@ + + + + + +

{{ pkg.manifest.title }}

+

{{ pkg.manifest.description.short }}

+ +
+
diff --git a/frontend/projects/marketplace/src/pages/list/item/item.component.scss b/frontend/projects/marketplace/src/pages/list/item/item.component.scss new file mode 100644 index 000000000..1b98d2b7f --- /dev/null +++ b/frontend/projects/marketplace/src/pages/list/item/item.component.scss @@ -0,0 +1,4 @@ +.pkg-title { + font-family: 'Montserrat', sans-serif; + font-weight: bold; +} diff --git a/frontend/projects/marketplace/src/pages/list/item/item.component.ts b/frontend/projects/marketplace/src/pages/list/item/item.component.ts new file mode 100644 index 000000000..4997e8764 --- /dev/null +++ b/frontend/projects/marketplace/src/pages/list/item/item.component.ts @@ -0,0 +1,14 @@ +import { ChangeDetectionStrategy, Component, Input } from '@angular/core' + +import { MarketplacePkg } from '../../../types/marketplace-pkg' + +@Component({ + selector: 'marketplace-item', + templateUrl: 'item.component.html', + styleUrls: ['item.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class ItemComponent { + @Input() + pkg: MarketplacePkg +} diff --git a/frontend/projects/marketplace/src/pages/list/item/item.module.ts b/frontend/projects/marketplace/src/pages/list/item/item.module.ts new file mode 100644 index 000000000..df6302ce3 --- /dev/null +++ b/frontend/projects/marketplace/src/pages/list/item/item.module.ts @@ -0,0 +1,13 @@ +import { NgModule } from '@angular/core' +import { IonicModule } from '@ionic/angular' +import { RouterModule } from '@angular/router' +import { SharedPipesModule } from '@start9labs/shared' + +import { ItemComponent } from './item.component' + +@NgModule({ + imports: [IonicModule, RouterModule, SharedPipesModule], + declarations: [ItemComponent], + exports: [ItemComponent], +}) +export class ItemModule {} diff --git a/frontend/projects/marketplace/src/pages/list/search/search.component.html b/frontend/projects/marketplace/src/pages/list/search/search.component.html new file mode 100644 index 000000000..e0b261d79 --- /dev/null +++ b/frontend/projects/marketplace/src/pages/list/search/search.component.html @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/frontend/projects/marketplace/src/pages/list/search/search.component.scss b/frontend/projects/marketplace/src/pages/list/search/search.component.scss new file mode 100644 index 000000000..4b1475f5b --- /dev/null +++ b/frontend/projects/marketplace/src/pages/list/search/search.component.scss @@ -0,0 +1,4 @@ +:host { + display: block; + padding-bottom: 32px; +} diff --git a/frontend/projects/marketplace/src/pages/list/search/search.component.ts b/frontend/projects/marketplace/src/pages/list/search/search.component.ts new file mode 100644 index 000000000..73729a392 --- /dev/null +++ b/frontend/projects/marketplace/src/pages/list/search/search.component.ts @@ -0,0 +1,26 @@ +import { + ChangeDetectionStrategy, + Component, + EventEmitter, + Input, + Output, +} from '@angular/core' + +@Component({ + selector: 'marketplace-search', + templateUrl: 'search.component.html', + styleUrls: ['search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class SearchComponent { + @Input() + query = '' + + @Output() + readonly queryChange = new EventEmitter() + + onModelChange(query: string) { + this.query = query + this.queryChange.emit(query) + } +} diff --git a/frontend/projects/marketplace/src/pages/list/search/search.module.ts b/frontend/projects/marketplace/src/pages/list/search/search.module.ts new file mode 100644 index 000000000..9c346a709 --- /dev/null +++ b/frontend/projects/marketplace/src/pages/list/search/search.module.ts @@ -0,0 +1,12 @@ +import { NgModule } from '@angular/core' +import { FormsModule } from '@angular/forms' +import { IonicModule } from '@ionic/angular' + +import { SearchComponent } from './search.component' + +@NgModule({ + imports: [IonicModule, FormsModule], + declarations: [SearchComponent], + exports: [SearchComponent], +}) +export class SearchModule {} diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list-skeleton/marketplace-list-skeleton.component.html b/frontend/projects/marketplace/src/pages/list/skeleton/skeleton.component.html similarity index 100% rename from frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list-skeleton/marketplace-list-skeleton.component.html rename to frontend/projects/marketplace/src/pages/list/skeleton/skeleton.component.html diff --git a/frontend/projects/marketplace/src/pages/list/skeleton/skeleton.component.ts b/frontend/projects/marketplace/src/pages/list/skeleton/skeleton.component.ts new file mode 100644 index 000000000..8903a8e3e --- /dev/null +++ b/frontend/projects/marketplace/src/pages/list/skeleton/skeleton.component.ts @@ -0,0 +1,8 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core' + +@Component({ + selector: 'marketplace-skeleton', + templateUrl: 'skeleton.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class SkeletonComponent {} diff --git a/frontend/projects/marketplace/src/pages/list/skeleton/skeleton.module.ts b/frontend/projects/marketplace/src/pages/list/skeleton/skeleton.module.ts new file mode 100644 index 000000000..a1405f009 --- /dev/null +++ b/frontend/projects/marketplace/src/pages/list/skeleton/skeleton.module.ts @@ -0,0 +1,12 @@ +import { CommonModule } from '@angular/common' +import { NgModule } from '@angular/core' +import { IonicModule } from '@ionic/angular' + +import { SkeletonComponent } from './skeleton.component' + +@NgModule({ + imports: [CommonModule, IonicModule], + declarations: [SkeletonComponent], + exports: [SkeletonComponent], +}) +export class SkeletonModule {} diff --git a/frontend/projects/marketplace/src/pages/release-notes/release-notes.component.html b/frontend/projects/marketplace/src/pages/release-notes/release-notes.component.html new file mode 100644 index 000000000..6fef89363 --- /dev/null +++ b/frontend/projects/marketplace/src/pages/release-notes/release-notes.component.html @@ -0,0 +1,32 @@ + + +
+ +

{{ note.key | displayEmver }}

+
+ + + +
+
+ + + + +
diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/release-notes/release-notes.page.scss b/frontend/projects/marketplace/src/pages/release-notes/release-notes.component.scss similarity index 89% rename from frontend/projects/ui/src/app/pages/marketplace-routes/release-notes/release-notes.page.scss rename to frontend/projects/marketplace/src/pages/release-notes/release-notes.component.scss index d822599c3..cd74c7a04 100644 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/release-notes/release-notes.page.scss +++ b/frontend/projects/marketplace/src/pages/release-notes/release-notes.component.scss @@ -1,3 +1,7 @@ +:host { + flex: 1 1 0; +} + .panel { margin: 0; padding: 0 24px; diff --git a/frontend/projects/marketplace/src/pages/release-notes/release-notes.component.ts b/frontend/projects/marketplace/src/pages/release-notes/release-notes.component.ts new file mode 100644 index 000000000..a1dd976e5 --- /dev/null +++ b/frontend/projects/marketplace/src/pages/release-notes/release-notes.component.ts @@ -0,0 +1,38 @@ +import { ChangeDetectionStrategy, Component, ElementRef } from '@angular/core' +import { ActivatedRoute } from '@angular/router' +import { AbstractMarketplaceService } from '../../services/marketplace.service' + +@Component({ + selector: 'release-notes', + templateUrl: './release-notes.component.html', + styleUrls: ['./release-notes.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class ReleaseNotesComponent { + private readonly pkgId = this.route.snapshot.paramMap.get('pkgId') + + private selected: string | null = null + + readonly notes$ = this.marketplaceService.getReleaseNotes(this.pkgId) + + constructor( + private readonly route: ActivatedRoute, + private readonly marketplaceService: AbstractMarketplaceService, + ) {} + + isSelected(key: string): boolean { + return this.selected === key + } + + setSelected(selected: string) { + this.selected = this.isSelected(selected) ? null : selected + } + + getDocSize(key: string, { nativeElement }: ElementRef) { + return this.isSelected(key) ? nativeElement.scrollHeight : 0 + } + + asIsOrder(a: any, b: any) { + return 0 + } +} diff --git a/frontend/projects/ui/src/app/modals/markdown/markdown.module.ts b/frontend/projects/marketplace/src/pages/release-notes/release-notes.module.ts similarity index 57% rename from frontend/projects/ui/src/app/modals/markdown/markdown.module.ts rename to frontend/projects/marketplace/src/pages/release-notes/release-notes.module.ts index 867bdd017..65602c1ea 100644 --- a/frontend/projects/ui/src/app/modals/markdown/markdown.module.ts +++ b/frontend/projects/marketplace/src/pages/release-notes/release-notes.module.ts @@ -1,20 +1,25 @@ import { NgModule } from '@angular/core' import { CommonModule } from '@angular/common' import { IonicModule } from '@ionic/angular' -import { MarkdownPage } from './markdown.page' import { + EmverPipesModule, MarkdownPipeModule, TextSpinnerComponentModule, + ElementModule, } from '@start9labs/shared' +import { ReleaseNotesComponent } from './release-notes.component' + @NgModule({ - declarations: [MarkdownPage], imports: [ CommonModule, IonicModule, - MarkdownPipeModule, TextSpinnerComponentModule, + EmverPipesModule, + MarkdownPipeModule, + ElementModule, ], - exports: [MarkdownPage], + declarations: [ReleaseNotesComponent], + exports: [ReleaseNotesComponent], }) -export class MarkdownPageModule {} +export class ReleaseNotesModule {} diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-about/marketplace-show-about.component.html b/frontend/projects/marketplace/src/pages/show/about/about.component.html similarity index 100% rename from frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-about/marketplace-show-about.component.html rename to frontend/projects/marketplace/src/pages/show/about/about.component.html diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-about/marketplace-show-about.component.scss b/frontend/projects/marketplace/src/pages/show/about/about.component.scss similarity index 100% rename from frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-about/marketplace-show-about.component.scss rename to frontend/projects/marketplace/src/pages/show/about/about.component.scss diff --git a/frontend/projects/marketplace/src/pages/show/about/about.component.ts b/frontend/projects/marketplace/src/pages/show/about/about.component.ts new file mode 100644 index 000000000..1a681b5db --- /dev/null +++ b/frontend/projects/marketplace/src/pages/show/about/about.component.ts @@ -0,0 +1,14 @@ +import { ChangeDetectionStrategy, Component, Input } from '@angular/core' + +import { MarketplacePkg } from '../../../types/marketplace-pkg' + +@Component({ + selector: 'marketplace-about', + templateUrl: 'about.component.html', + styleUrls: ['about.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class AboutComponent { + @Input() + pkg: MarketplacePkg +} diff --git a/frontend/projects/marketplace/src/pages/show/about/about.module.ts b/frontend/projects/marketplace/src/pages/show/about/about.module.ts new file mode 100644 index 000000000..b48bbcbaa --- /dev/null +++ b/frontend/projects/marketplace/src/pages/show/about/about.module.ts @@ -0,0 +1,20 @@ +import { CommonModule } from '@angular/common' +import { NgModule } from '@angular/core' +import { RouterModule } from '@angular/router' +import { IonicModule } from '@ionic/angular' +import { EmverPipesModule, MarkdownPipeModule } from '@start9labs/shared' + +import { AboutComponent } from './about.component' + +@NgModule({ + imports: [ + CommonModule, + RouterModule, + IonicModule, + MarkdownPipeModule, + EmverPipesModule, + ], + declarations: [AboutComponent], + exports: [AboutComponent], +}) +export class AboutModule {} diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-additional/marketplace-show-additional.component.html b/frontend/projects/marketplace/src/pages/show/additional/additional.component.html similarity index 100% rename from frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-additional/marketplace-show-additional.component.html rename to frontend/projects/marketplace/src/pages/show/additional/additional.component.html diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-additional/marketplace-show-additional.component.ts b/frontend/projects/marketplace/src/pages/show/additional/additional.component.ts similarity index 69% rename from frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-additional/marketplace-show-additional.component.ts rename to frontend/projects/marketplace/src/pages/show/additional/additional.component.ts index 799696660..e71a4fe9e 100644 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-additional/marketplace-show-additional.component.ts +++ b/frontend/projects/marketplace/src/pages/show/additional/additional.component.ts @@ -6,17 +6,17 @@ import { Output, } from '@angular/core' import { AlertController, ModalController } from '@ionic/angular' -import { MarketplacePkg } from '@start9labs/marketplace' -import { displayEmver, Emver } from '@start9labs/shared' +import { displayEmver, Emver, MarkdownComponent } from '@start9labs/shared' -import { MarkdownPage } from 'src/app/modals/markdown/markdown.page' +import { AbstractMarketplaceService } from '../../../services/marketplace.service' +import { MarketplacePkg } from '../../../types/marketplace-pkg' @Component({ - selector: 'marketplace-show-additional', - templateUrl: 'marketplace-show-additional.component.html', + selector: 'marketplace-additional', + templateUrl: 'additional.component.html', changeDetection: ChangeDetectionStrategy.OnPush, }) -export class MarketplaceShowAdditionalComponent { +export class AdditionalComponent { @Input() pkg: MarketplacePkg @@ -27,6 +27,7 @@ export class MarketplaceShowAdditionalComponent { private readonly alertCtrl: AlertController, private readonly modalCtrl: ModalController, private readonly emver: Emver, + private readonly marketplaceService: AbstractMarketplaceService, ) {} async presentAlertVersions() { @@ -58,12 +59,14 @@ export class MarketplaceShowAdditionalComponent { } async presentModalMd(title: string) { + const content = this.marketplaceService.getPackageMarkdown( + title, + this.pkg.manifest.id, + ) + const modal = await this.modalCtrl.create({ - componentProps: { - title, - contentUrl: `/marketplace${this.pkg[title]}`, - }, - component: MarkdownPage, + componentProps: { title, content }, + component: MarkdownComponent, }) await modal.present() diff --git a/frontend/projects/marketplace/src/pages/show/additional/additional.module.ts b/frontend/projects/marketplace/src/pages/show/additional/additional.module.ts new file mode 100644 index 000000000..48f474c0d --- /dev/null +++ b/frontend/projects/marketplace/src/pages/show/additional/additional.module.ts @@ -0,0 +1,12 @@ +import { NgModule } from '@angular/core' +import { IonicModule } from '@ionic/angular' +import { MarkdownModule } from '@start9labs/shared' + +import { AdditionalComponent } from './additional.component' + +@NgModule({ + imports: [IonicModule, MarkdownModule], + declarations: [AdditionalComponent], + exports: [AdditionalComponent], +}) +export class AdditionalModule {} diff --git a/frontend/projects/marketplace/src/pages/show/dependencies/dependencies.component.html b/frontend/projects/marketplace/src/pages/show/dependencies/dependencies.component.html new file mode 100644 index 000000000..5c3e1a9a1 --- /dev/null +++ b/frontend/projects/marketplace/src/pages/show/dependencies/dependencies.component.html @@ -0,0 +1,30 @@ +Dependencies + + + + + + + + +

+ {{ pkg['dependency-metadata'][dep.key].title }} + + (required) + (required by default) + (optional) + +

+

+ {{ dep.value.version | displayEmver }} +

+

{{ dep.value.description }}

+
+
+
+
+
diff --git a/frontend/projects/marketplace/src/pages/show/dependencies/dependencies.component.ts b/frontend/projects/marketplace/src/pages/show/dependencies/dependencies.component.ts new file mode 100644 index 000000000..6b3781896 --- /dev/null +++ b/frontend/projects/marketplace/src/pages/show/dependencies/dependencies.component.ts @@ -0,0 +1,17 @@ +import { ChangeDetectionStrategy, Component, Input } from '@angular/core' + +import { MarketplacePkg } from '../../../types/marketplace-pkg' + +@Component({ + selector: 'marketplace-dependencies', + templateUrl: 'dependencies.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class DependenciesComponent { + @Input() + pkg: MarketplacePkg + + getImg(key: string): string { + return 'data:image/png;base64,' + this.pkg['dependency-metadata'][key].icon + } +} diff --git a/frontend/projects/marketplace/src/pages/show/dependencies/dependencies.module.ts b/frontend/projects/marketplace/src/pages/show/dependencies/dependencies.module.ts new file mode 100644 index 000000000..16321d03c --- /dev/null +++ b/frontend/projects/marketplace/src/pages/show/dependencies/dependencies.module.ts @@ -0,0 +1,20 @@ +import { CommonModule } from '@angular/common' +import { NgModule } from '@angular/core' +import { RouterModule } from '@angular/router' +import { IonicModule } from '@ionic/angular' +import { EmverPipesModule, SharedPipesModule } from '@start9labs/shared' + +import { DependenciesComponent } from './dependencies.component' + +@NgModule({ + imports: [ + CommonModule, + RouterModule, + IonicModule, + SharedPipesModule, + EmverPipesModule, + ], + declarations: [DependenciesComponent], + exports: [DependenciesComponent], +}) +export class DependenciesModule {} diff --git a/frontend/projects/marketplace/src/pages/show/package/package.component.html b/frontend/projects/marketplace/src/pages/show/package/package.component.html new file mode 100644 index 000000000..5bc3712d3 --- /dev/null +++ b/frontend/projects/marketplace/src/pages/show/package/package.component.html @@ -0,0 +1,29 @@ + + + +
+ +
+

{{ pkg.manifest.title }}

+

{{ pkg.manifest.version | displayEmver }}

+ +
+
+
+ + + +
+ +
diff --git a/frontend/projects/marketplace/src/pages/show/package/package.component.scss b/frontend/projects/marketplace/src/pages/show/package/package.component.scss new file mode 100644 index 000000000..13ac702c6 --- /dev/null +++ b/frontend/projects/marketplace/src/pages/show/package/package.component.scss @@ -0,0 +1,26 @@ +.header { + font-family: 'Montserrat', sans-serif; + padding: 2%; +} + +.logo { + min-width: 15%; + max-width: 18%; +} + +.text { + margin-left: 5%; + display: inline-block; + vertical-align: top; +} + +.title { + margin: 0 0 0 -2px; + font-size: calc(20px + 3vw); +} + +.version { + padding: 4px 0 12px 0; + margin: 0; + font-size: calc(10px + 1vw); +} diff --git a/frontend/projects/marketplace/src/pages/show/package/package.component.ts b/frontend/projects/marketplace/src/pages/show/package/package.component.ts new file mode 100644 index 000000000..2c9a89bf5 --- /dev/null +++ b/frontend/projects/marketplace/src/pages/show/package/package.component.ts @@ -0,0 +1,14 @@ +import { ChangeDetectionStrategy, Component, Input } from '@angular/core' + +import { MarketplacePkg } from '../../../types/marketplace-pkg' + +@Component({ + selector: 'marketplace-package', + templateUrl: 'package.component.html', + styleUrls: ['package.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class PackageComponent { + @Input() + pkg: MarketplacePkg +} diff --git a/frontend/projects/marketplace/src/pages/show/package/package.module.ts b/frontend/projects/marketplace/src/pages/show/package/package.module.ts new file mode 100644 index 000000000..d970b3d21 --- /dev/null +++ b/frontend/projects/marketplace/src/pages/show/package/package.module.ts @@ -0,0 +1,12 @@ +import { NgModule } from '@angular/core' +import { IonicModule } from '@ionic/angular' +import { EmverPipesModule, SharedPipesModule } from '@start9labs/shared' + +import { PackageComponent } from './package.component' + +@NgModule({ + imports: [IonicModule, SharedPipesModule, EmverPipesModule], + declarations: [PackageComponent], + exports: [PackageComponent], +}) +export class PackageModule {} diff --git a/frontend/projects/marketplace/src/pipes/filter-packages.pipe.ts b/frontend/projects/marketplace/src/pipes/filter-packages.pipe.ts index af8b9972d..74b282956 100644 --- a/frontend/projects/marketplace/src/pipes/filter-packages.pipe.ts +++ b/frontend/projects/marketplace/src/pipes/filter-packages.pipe.ts @@ -1,8 +1,8 @@ -import { Pipe, PipeTransform } from '@angular/core' +import { NgModule, Pipe, PipeTransform } from '@angular/core' import Fuse from 'fuse.js/dist/fuse.min.js' -import { LocalPkg } from '../types/local-pkg' import { MarketplacePkg } from '../types/marketplace-pkg' +import { MarketplaceManifest } from '../types/marketplace-manifest' const defaultOps = { isCaseSensitive: false, @@ -31,9 +31,9 @@ const defaultOps = { export class FilterPackagesPipe implements PipeTransform { transform( packages: MarketplacePkg[] | null, - local: Record, query: string, category: string, + local: Record = {}, ): MarketplacePkg[] | null { if (!packages) { return null @@ -63,3 +63,9 @@ export class FilterPackagesPipe implements PipeTransform { .map(p => p.item) } } + +@NgModule({ + declarations: [FilterPackagesPipe], + exports: [FilterPackagesPipe], +}) +export class FilterPackagesPipeModule {} diff --git a/frontend/projects/marketplace/src/pipes/marketplace-pipes.module.ts b/frontend/projects/marketplace/src/pipes/marketplace-pipes.module.ts deleted file mode 100644 index bea2421d3..000000000 --- a/frontend/projects/marketplace/src/pipes/marketplace-pipes.module.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { NgModule } from '@angular/core' -import { InstallProgressPipe } from './install-progress.pipe' -import { TrustPipe } from './trust.pipe' -import { FilterPackagesPipe } from './filter-packages.pipe' - -@NgModule({ - declarations: [InstallProgressPipe, TrustPipe, FilterPackagesPipe], - exports: [InstallProgressPipe, TrustPipe, FilterPackagesPipe], -}) -export class MarketplacePipesModule {} diff --git a/frontend/projects/marketplace/src/public-api.ts b/frontend/projects/marketplace/src/public-api.ts index cf9062ed5..2bc7bee38 100644 --- a/frontend/projects/marketplace/src/public-api.ts +++ b/frontend/projects/marketplace/src/public-api.ts @@ -2,16 +2,31 @@ * Public API Surface of @start9labs/marketplace */ -export * from './pipes/install-progress.pipe' -export * from './pipes/trust.pipe' -export * from './pipes/marketplace-pipes.module' +export * from './pages/list/categories/categories.component' +export * from './pages/list/categories/categories.module' +export * from './pages/list/item/item.component' +export * from './pages/list/item/item.module' +export * from './pages/list/search/search.component' +export * from './pages/list/search/search.module' +export * from './pages/list/skeleton/skeleton.component' +export * from './pages/list/skeleton/skeleton.module' +export * from './pages/release-notes/release-notes.component' +export * from './pages/release-notes/release-notes.module' +export * from './pages/show/about/about.component' +export * from './pages/show/about/about.module' +export * from './pages/show/additional/additional.component' +export * from './pages/show/additional/additional.module' +export * from './pages/show/dependencies/dependencies.component' +export * from './pages/show/dependencies/dependencies.module' +export * from './pages/show/package/package.component' +export * from './pages/show/package/package.module' + +export * from './pipes/filter-packages.pipe' export * from './services/marketplace.service' -export * from './types/local-pkg' +export * from './types/dependency' export * from './types/marketplace' export * from './types/marketplace-data' export * from './types/marketplace-manifest' export * from './types/marketplace-pkg' - -export * from './utils/spread-progress' diff --git a/frontend/projects/marketplace/src/services/marketplace.service.ts b/frontend/projects/marketplace/src/services/marketplace.service.ts index 62c381b74..7d40d1bcf 100644 --- a/frontend/projects/marketplace/src/services/marketplace.service.ts +++ b/frontend/projects/marketplace/src/services/marketplace.service.ts @@ -13,5 +13,7 @@ export abstract class AbstractMarketplaceService { abstract getPackages(): Observable + abstract getPackageMarkdown(type: string, pkgId: string): Observable + abstract getPackage(id: string, version: string): Observable } diff --git a/frontend/projects/marketplace/src/types/dependency.ts b/frontend/projects/marketplace/src/types/dependency.ts new file mode 100644 index 000000000..22947aec4 --- /dev/null +++ b/frontend/projects/marketplace/src/types/dependency.ts @@ -0,0 +1,17 @@ +export interface Dependency { + version: string + requirement: + | { + type: 'opt-in' + how: string + } + | { + type: 'opt-out' + how: string + } + | { + type: 'required' + } + description: string | null + config: T +} diff --git a/frontend/projects/marketplace/src/types/local-pkg.ts b/frontend/projects/marketplace/src/types/local-pkg.ts deleted file mode 100644 index 6ccd43d3c..000000000 --- a/frontend/projects/marketplace/src/types/local-pkg.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { PackageState } from '@start9labs/shared' - -import { MarketplaceManifest } from './marketplace-manifest' - -export interface LocalPkg { - state: PackageState - manifest: MarketplaceManifest -} diff --git a/frontend/projects/marketplace/src/types/marketplace-manifest.ts b/frontend/projects/marketplace/src/types/marketplace-manifest.ts index 6e040efd4..1d0342119 100644 --- a/frontend/projects/marketplace/src/types/marketplace-manifest.ts +++ b/frontend/projects/marketplace/src/types/marketplace-manifest.ts @@ -1,6 +1,8 @@ import { Url } from '@start9labs/shared' -export interface MarketplaceManifest { +import { Dependency } from './dependency' + +export interface MarketplaceManifest { id: string title: string version: string @@ -22,4 +24,5 @@ export interface MarketplaceManifest { start: string | null stop: string | null } + dependencies: Record> } diff --git a/frontend/projects/marketplace/src/utils/spread-progress.ts b/frontend/projects/marketplace/src/utils/spread-progress.ts deleted file mode 100644 index 4347e1b08..000000000 --- a/frontend/projects/marketplace/src/utils/spread-progress.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { LocalPkg } from '../types/local-pkg' - -export function spreadProgress(pkg: LocalPkg) { - pkg['install-progress'] = { ...pkg['install-progress'] } -} diff --git a/frontend/projects/shared/src/components/markdown/markdown.component.html b/frontend/projects/shared/src/components/markdown/markdown.component.html new file mode 100644 index 000000000..090070c4e --- /dev/null +++ b/frontend/projects/shared/src/components/markdown/markdown.component.html @@ -0,0 +1,29 @@ + + + {{ title | titlecase }} + + + + + + + + + + + + {{ error }} + + + +
+ + + + +
diff --git a/frontend/projects/ui/src/app/modals/markdown/markdown.page.scss b/frontend/projects/shared/src/components/markdown/markdown.component.scss similarity index 100% rename from frontend/projects/ui/src/app/modals/markdown/markdown.page.scss rename to frontend/projects/shared/src/components/markdown/markdown.component.scss diff --git a/frontend/projects/shared/src/components/markdown/markdown.component.ts b/frontend/projects/shared/src/components/markdown/markdown.component.ts new file mode 100644 index 000000000..0249a2179 --- /dev/null +++ b/frontend/projects/shared/src/components/markdown/markdown.component.ts @@ -0,0 +1,47 @@ +import { Component, Input, Optional } from '@angular/core' +import { ModalController } from '@ionic/angular' + +import { getErrorMessage } from '../../services/error-toast.service' +import { AbstractApiService } from '../../services/api.service' +import { defer, from, isObservable, Observable, of } from 'rxjs' +import { catchError, ignoreElements, share } from 'rxjs/operators' + +@Component({ + selector: 'markdown', + templateUrl: './markdown.component.html', + styleUrls: ['./markdown.component.scss'], +}) +export class MarkdownComponent { + @Input() contentUrl?: string + @Input() content?: string | Observable + @Input() title = '' + + private readonly data$ = defer(() => this.contentObservable).pipe(share()) + + readonly error$ = this.data$.pipe( + ignoreElements(), + catchError(e => of(getErrorMessage(e))), + ) + + readonly content$ = this.data$.pipe(catchError(() => of([]))) + + constructor( + private readonly modalCtrl: ModalController, + @Optional() + private readonly embassyApi: AbstractApiService | null, + ) {} + + async dismiss() { + return this.modalCtrl.dismiss(true) + } + + private get contentObservable() { + if (isObservable(this.content)) { + return this.content + } + + return this.contentUrl + ? from(this.embassyApi?.getStatic(this.contentUrl)) + : of(this.content) + } +} diff --git a/frontend/projects/shared/src/components/markdown/markdown.module.ts b/frontend/projects/shared/src/components/markdown/markdown.module.ts new file mode 100644 index 000000000..6da4673d1 --- /dev/null +++ b/frontend/projects/shared/src/components/markdown/markdown.module.ts @@ -0,0 +1,21 @@ +import { NgModule } from '@angular/core' +import { CommonModule } from '@angular/common' +import { IonicModule } from '@ionic/angular' + +import { MarkdownPipeModule } from '../../pipes/markdown/markdown.module' +import { SafeLinksModule } from '../../directives/safe-links/safe-links.module' +import { TextSpinnerComponentModule } from '../text-spinner/text-spinner.component.module' +import { MarkdownComponent } from './markdown.component' + +@NgModule({ + declarations: [MarkdownComponent], + imports: [ + CommonModule, + IonicModule, + MarkdownPipeModule, + TextSpinnerComponentModule, + SafeLinksModule, + ], + exports: [MarkdownComponent], +}) +export class MarkdownModule {} diff --git a/frontend/projects/shared/src/directives/safe-links/safe-links.directive.ts b/frontend/projects/shared/src/directives/safe-links/safe-links.directive.ts new file mode 100644 index 000000000..a757fbe29 --- /dev/null +++ b/frontend/projects/shared/src/directives/safe-links/safe-links.directive.ts @@ -0,0 +1,27 @@ +import { AfterViewInit, Directive, ElementRef, Inject } from '@angular/core' +import { DOCUMENT } from '@angular/common' + +// TODO: Refactor to use `MutationObserver` so it works with dynamic content +@Directive({ + selector: '[safeLinks]', +}) +export class SafeLinksDirective implements AfterViewInit { + constructor( + @Inject(DOCUMENT) private readonly document: Document, + private readonly elementRef: ElementRef, + ) {} + + ngAfterViewInit() { + Array.from(this.document.links) + .filter( + link => + link.hostname !== this.document.location.hostname && + this.elementRef.nativeElement.contains(link), + ) + .forEach(link => { + link.target = '_blank' + link.setAttribute('rel', 'noreferrer') + link.classList.add('externalLink') + }) + } +} diff --git a/frontend/projects/shared/src/directives/safe-links/safe-links.module.ts b/frontend/projects/shared/src/directives/safe-links/safe-links.module.ts new file mode 100644 index 000000000..7268e9b01 --- /dev/null +++ b/frontend/projects/shared/src/directives/safe-links/safe-links.module.ts @@ -0,0 +1,8 @@ +import { NgModule } from '@angular/core' +import { SafeLinksDirective } from './safe-links.directive' + +@NgModule({ + declarations: [SafeLinksDirective], + exports: [SafeLinksDirective], +}) +export class SafeLinksModule {} diff --git a/frontend/projects/shared/src/pipes/shared/shared.module.ts b/frontend/projects/shared/src/pipes/shared/shared.module.ts index 1f3004e4b..a9f282d67 100644 --- a/frontend/projects/shared/src/pipes/shared/shared.module.ts +++ b/frontend/projects/shared/src/pipes/shared/shared.module.ts @@ -1,9 +1,10 @@ import { NgModule } from '@angular/core' import { IncludesPipe } from './includes.pipe' import { EmptyPipe } from './empty.pipe' +import { TrustUrlPipe } from './trust.pipe' @NgModule({ - declarations: [IncludesPipe, EmptyPipe], - exports: [IncludesPipe, EmptyPipe], + declarations: [IncludesPipe, EmptyPipe, TrustUrlPipe], + exports: [IncludesPipe, EmptyPipe, TrustUrlPipe], }) export class SharedPipesModule {} diff --git a/frontend/projects/marketplace/src/pipes/trust.pipe.ts b/frontend/projects/shared/src/pipes/shared/trust.pipe.ts similarity index 81% rename from frontend/projects/marketplace/src/pipes/trust.pipe.ts rename to frontend/projects/shared/src/pipes/shared/trust.pipe.ts index 283ad3a76..0acd65761 100644 --- a/frontend/projects/marketplace/src/pipes/trust.pipe.ts +++ b/frontend/projects/shared/src/pipes/shared/trust.pipe.ts @@ -2,9 +2,9 @@ import { Pipe, PipeTransform } from '@angular/core' import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser' @Pipe({ - name: 'trust', + name: 'trustUrl', }) -export class TrustPipe implements PipeTransform { +export class TrustUrlPipe implements PipeTransform { constructor(public readonly sanitizer: DomSanitizer) {} transform(base64Icon: string): SafeResourceUrl { diff --git a/frontend/projects/shared/src/public-api.ts b/frontend/projects/shared/src/public-api.ts index 81b5486b9..3287078fa 100644 --- a/frontend/projects/shared/src/public-api.ts +++ b/frontend/projects/shared/src/public-api.ts @@ -2,11 +2,15 @@ * Public API Surface of @start9labs/shared */ +export * from './components/markdown/markdown.component' +export * from './components/markdown/markdown.module' export * from './components/text-spinner/text-spinner.component.module' export * from './components/text-spinner/text-spinner.component' export * from './directives/element/element.directive' export * from './directives/element/element.module' +export * from './directives/safe-links/safe-links.directive' +export * from './directives/safe-links/safe-links.module' export * from './pipes/emver/emver.module' export * from './pipes/emver/emver.pipe' @@ -15,19 +19,17 @@ export * from './pipes/markdown/markdown.pipe' export * from './pipes/shared/shared.module' export * from './pipes/shared/empty.pipe' export * from './pipes/shared/includes.pipe' +export * from './pipes/shared/trust.pipe' export * from './pipes/unit-conversion/unit-conversion.module' export * from './pipes/unit-conversion/unit-conversion.pipe' +export * from './services/api.service' export * from './services/destroy.service' export * from './services/emver.service' export * from './services/error-toast.service' -export * from './types/dependent-info' -export * from './types/install-progress' -export * from './types/package-state' -export * from './types/progress-data' export * from './types/url' export * from './types/workspace-config' export * from './util/misc.util' -export * from './util/package-loading-progress' +export * from './util/unused' diff --git a/frontend/projects/shared/src/services/api.service.ts b/frontend/projects/shared/src/services/api.service.ts new file mode 100644 index 000000000..e88eae83f --- /dev/null +++ b/frontend/projects/shared/src/services/api.service.ts @@ -0,0 +1,4 @@ +export abstract class AbstractApiService { + // for getting static files: ex icons, instructions, licenses + abstract getStatic(url: string): Promise +} diff --git a/frontend/projects/shared/src/util/misc.util.ts b/frontend/projects/shared/src/util/misc.util.ts index 199e9572f..44a0f0ca4 100644 --- a/frontend/projects/shared/src/util/misc.util.ts +++ b/frontend/projects/shared/src/util/misc.util.ts @@ -1,56 +1,3 @@ -import { OperatorFunction } from 'rxjs' -import { map } from 'rxjs/operators' - -export function trace(t: T): T { - console.log(`TRACE`, t) - return t -} - -// curried description. This allows e.g somePromise.thentraceDesc('my result')) -export function traceDesc(description: string): (t: T) => T { - return t => { - console.log(`TRACE`, description, t) - return t - } -} - -// for use in observables. This allows e.g. someObservable.pipe(traceM('my result')) -// the practical equivalent of `tap(t => console.log(t, description))` -export function traceWheel(description?: string): OperatorFunction { - return description ? map(traceDesc(description)) : map(trace) -} - -export function traceThrowDesc(description: string, t: T | undefined): T { - if (!t) throw new Error(description) - return t -} - -export function inMs( - count: number, - unit: 'days' | 'hours' | 'minutes' | 'seconds', -) { - switch (unit) { - case 'seconds': - return count * 1000 - case 'minutes': - return inMs(count * 60, 'seconds') - case 'hours': - return inMs(count * 60, 'minutes') - case 'days': - return inMs(count * 24, 'hours') - } -} - -// arr1 - arr2 -export function diff(arr1: T[], arr2: T[]): T[] { - return arr1.filter(x => !arr2.includes(x)) -} - -// arr1 & arr2 -export function both(arr1: T[], arr2: T[]): T[] { - return arr1.filter(x => arr2.includes(x)) -} - export function isObject(val: any): boolean { return val && typeof val === 'object' && !Array.isArray(val) } @@ -63,79 +10,6 @@ export function pauseFor(ms: number): Promise { return new Promise(resolve => setTimeout(resolve, ms)) } -export function toObject(t: T[], map: (t0: T) => string): Record { - return t.reduce((acc, next) => { - acc[map(next)] = next - return acc - }, {} as Record) -} - -export function update( - t: Record, - u: Record, -): Record { - return { ...t, ...u } -} - -export function deepCloneUnknown(value: T): T { - if (typeof value !== 'object' || value === null) { - return value - } - if (Array.isArray(value)) { - return deepCloneArray(value) - } - return deepCloneObject(value) -} - -export function deepCloneObject(source: T) { - const result = {} - Object.keys(source).forEach(key => { - const value = source[key] - result[key] = deepCloneUnknown(value) - }, {}) - return result as T -} - -export function deepCloneArray(collection: any) { - return collection.map(value => { - return deepCloneUnknown(value) - }) -} - -export function partitionArray( - ts: T[], - condition: (t: T) => boolean, -): [T[], T[]] { - const yes = [] as T[] - const no = [] as T[] - ts.forEach(t => { - if (condition(t)) { - yes.push(t) - } else { - no.push(t) - } - }) - return [yes, no] -} - -export function uniqueBy( - ts: T[], - uniqueBy: (t: T) => string, - prioritize: (t1: T, t2: T) => T, -) { - return Object.values( - ts.reduce((acc, next) => { - const previousValue = acc[uniqueBy(next)] - if (previousValue) { - acc[uniqueBy(next)] = prioritize(acc[uniqueBy(next)], previousValue) - } else { - acc[uniqueBy(next)] = previousValue - } - return acc - }, {}), - ) -} - export function capitalizeFirstLetter(string: string): string { return string.charAt(0).toUpperCase() + string.slice(1) } diff --git a/frontend/projects/shared/src/util/unused.ts b/frontend/projects/shared/src/util/unused.ts new file mode 100644 index 000000000..2326a7fbb --- /dev/null +++ b/frontend/projects/shared/src/util/unused.ts @@ -0,0 +1,130 @@ +import { OperatorFunction } from 'rxjs' +import { map } from 'rxjs/operators' + +/** + * These utils are not used anywhere + * They are candidates for removal + */ + +export function trace(t: T): T { + console.log(`TRACE`, t) + return t +} + +// curried description. This allows e.g somePromise.thentraceDesc('my result')) +export function traceDesc(description: string): (t: T) => T { + return t => { + console.log(`TRACE`, description, t) + return t + } +} + +// for use in observables. This allows e.g. someObservable.pipe(traceM('my result')) +// the practical equivalent of `tap(t => console.log(t, description))` +export function traceWheel(description?: string): OperatorFunction { + return description ? map(traceDesc(description)) : map(trace) +} + +export function traceThrowDesc(description: string, t: T | undefined): T { + if (!t) throw new Error(description) + return t +} + +export function inMs( + count: number, + unit: 'days' | 'hours' | 'minutes' | 'seconds', +) { + switch (unit) { + case 'seconds': + return count * 1000 + case 'minutes': + return inMs(count * 60, 'seconds') + case 'hours': + return inMs(count * 60, 'minutes') + case 'days': + return inMs(count * 24, 'hours') + } +} + +// arr1 - arr2 +export function diff(arr1: T[], arr2: T[]): T[] { + return arr1.filter(x => !arr2.includes(x)) +} + +// arr1 & arr2 +export function both(arr1: T[], arr2: T[]): T[] { + return arr1.filter(x => arr2.includes(x)) +} + +export function toObject(t: T[], map: (t0: T) => string): Record { + return t.reduce((acc, next) => { + acc[map(next)] = next + return acc + }, {} as Record) +} + +export function deepCloneUnknown(value: T): T { + if (typeof value !== 'object' || value === null) { + return value + } + if (Array.isArray(value)) { + return deepCloneArray(value) + } + return deepCloneObject(value) +} + +export function deepCloneObject(source: T) { + const result = {} + Object.keys(source).forEach(key => { + const value = source[key] + result[key] = deepCloneUnknown(value) + }, {}) + return result as T +} + +export function deepCloneArray(collection: any) { + return collection.map(value => { + return deepCloneUnknown(value) + }) +} + +export function partitionArray( + ts: T[], + condition: (t: T) => boolean, +): [T[], T[]] { + const yes = [] as T[] + const no = [] as T[] + ts.forEach(t => { + if (condition(t)) { + yes.push(t) + } else { + no.push(t) + } + }) + return [yes, no] +} + +export function update( + t: Record, + u: Record, +): Record { + return { ...t, ...u } +} + +export function uniqueBy( + ts: T[], + uniqueBy: (t: T) => string, + prioritize: (t1: T, t2: T) => T, +) { + return Object.values( + ts.reduce((acc, next) => { + const previousValue = acc[uniqueBy(next)] + if (previousValue) { + acc[uniqueBy(next)] = prioritize(acc[uniqueBy(next)], previousValue) + } else { + acc[uniqueBy(next)] = previousValue + } + return acc + }, {}), + ) +} diff --git a/frontend/projects/ui/src/app/app.module.ts b/frontend/projects/ui/src/app/app.module.ts index a0416e613..b063ad1c0 100644 --- a/frontend/projects/ui/src/app/app.module.ts +++ b/frontend/projects/ui/src/app/app.module.ts @@ -12,7 +12,6 @@ import { PatchDbServiceFactory } from './services/patch-db/patch-db.factory' import { ConfigService } from './services/config.service' import { QrCodeModule } from 'ng-qrcode' import { OSWelcomePageModule } from './modals/os-welcome/os-welcome.module' -import { MarkdownPageModule } from './modals/markdown/markdown.module' import { PatchDbService } from './services/patch-db/patch-db.service' import { LocalStorageBootstrap } from './services/patch-db/local-storage-bootstrap' import { FormBuilder } from '@angular/forms' @@ -22,7 +21,11 @@ import { GlobalErrorHandler } from './services/global-error-handler.service' import { MockApiService } from './services/api/embassy-mock-api.service' import { LiveApiService } from './services/api/embassy-live-api.service' import { MonacoEditorModule } from '@materia-ui/ngx-monaco-editor' -import { SharedPipesModule, WorkspaceConfig } from '@start9labs/shared' +import { + MarkdownModule, + SharedPipesModule, + WorkspaceConfig, +} from '@start9labs/shared' import { MarketplaceModule } from './marketplace.module' const { useMocks } = require('../../../../config.json') as WorkspaceConfig @@ -45,7 +48,7 @@ const { useMocks } = require('../../../../config.json') as WorkspaceConfig }), QrCodeModule, OSWelcomePageModule, - MarkdownPageModule, + MarkdownModule, GenericInputComponentModule, MonacoEditorModule, SharedPipesModule, diff --git a/frontend/projects/ui/src/app/modals/app-config/app-config.page.ts b/frontend/projects/ui/src/app/modals/app-config/app-config.page.ts index 48b7fcc11..c2d1e92ba 100644 --- a/frontend/projects/ui/src/app/modals/app-config/app-config.page.ts +++ b/frontend/projects/ui/src/app/modals/app-config/app-config.page.ts @@ -10,10 +10,10 @@ import { ApiService } from 'src/app/services/api/embassy-api.service' import { ErrorToastService, getErrorMessage, - DependentInfo, isEmptyObject, isObject, } from '@start9labs/shared' +import { DependentInfo } from 'src/app/types/dependent-info' import { wizardModal } from 'src/app/components/install-wizard/install-wizard.component' import { WizardBaker } from 'src/app/components/install-wizard/prebaked-wizards' import { ConfigSpec } from 'src/app/pkg-config/config-types' diff --git a/frontend/projects/ui/src/app/modals/markdown/markdown.page.html b/frontend/projects/ui/src/app/modals/markdown/markdown.page.html deleted file mode 100644 index 146a315eb..000000000 --- a/frontend/projects/ui/src/app/modals/markdown/markdown.page.html +++ /dev/null @@ -1,29 +0,0 @@ - - - {{ title | titlecase }} - - - - - - - - - - - - - - - - - {{ loadingError }} - - - - - -
-
-
-
diff --git a/frontend/projects/ui/src/app/modals/markdown/markdown.page.ts b/frontend/projects/ui/src/app/modals/markdown/markdown.page.ts deleted file mode 100644 index 0cc06dd1c..000000000 --- a/frontend/projects/ui/src/app/modals/markdown/markdown.page.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Component, Input } from '@angular/core' -import { ModalController, IonicSafeString } from '@ionic/angular' -import { ApiService } from 'src/app/services/api/embassy-api.service' -import { getErrorMessage, pauseFor } from '@start9labs/shared' - -@Component({ - selector: 'markdown', - templateUrl: './markdown.page.html', - styleUrls: ['./markdown.page.scss'], -}) -export class MarkdownPage { - @Input() contentUrl?: string - @Input() content?: string - @Input() title: string - loading = true - loadingError: string | IonicSafeString - - constructor( - private readonly modalCtrl: ModalController, - private readonly embassyApi: ApiService, - ) {} - - async ngOnInit() { - try { - if (!this.content) { - this.content = await this.embassyApi.getStatic(this.contentUrl) - } - this.loading = false - await pauseFor(50) - const links = document.links - for (let i = 0, linksLength = links.length; i < linksLength; i++) { - if (links[i].hostname != window.location.hostname) { - links[i].target = '_blank' - links[i].setAttribute('rel', 'noreferrer') - links[i].className += ' externalLink' - } - } - } catch (e) { - this.loadingError = getErrorMessage(e) - this.loading = false - } - } - - async dismiss() { - return this.modalCtrl.dismiss(true) - } -} diff --git a/frontend/projects/ui/src/app/pages/apps-routes/app-show/app-show.page.ts b/frontend/projects/ui/src/app/pages/apps-routes/app-show/app-show.page.ts index 4bb15c46b..90214995f 100644 --- a/frontend/projects/ui/src/app/pages/apps-routes/app-show/app-show.page.ts +++ b/frontend/projects/ui/src/app/pages/apps-routes/app-show/app-show.page.ts @@ -2,7 +2,7 @@ import { ChangeDetectionStrategy, Component } from '@angular/core' import { NavController } from '@ionic/angular' import { PatchDbService } from 'src/app/services/patch-db/patch-db.service' import { PackageDataEntry } from 'src/app/services/patch-db/data-model' -import { PackageState } from '@start9labs/shared' +import { PackageState } from 'src/app/types/package-state' import { PackageStatus, PrimaryStatus, diff --git a/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-progress/app-show-progress.component.ts b/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-progress/app-show-progress.component.ts index 4360152ba..cb173f467 100644 --- a/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-progress/app-show-progress.component.ts +++ b/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-progress/app-show-progress.component.ts @@ -1,6 +1,7 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core' import { PackageDataEntry } from 'src/app/services/patch-db/data-model' -import { InstallProgress, ProgressData } from '@start9labs/shared' +import { InstallProgress } from 'src/app/types/install-progress' +import { ProgressData } from 'src/app/types/progress-data' @Component({ selector: 'app-show-progress', diff --git a/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-status/app-show-status.component.ts b/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-status/app-show-status.component.ts index 70077795a..75a4d7ffb 100644 --- a/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-status/app-show-status.component.ts +++ b/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-status/app-show-status.component.ts @@ -10,11 +10,8 @@ import { PackageDataEntry, Status, } from 'src/app/services/patch-db/data-model' -import { - isEmptyObject, - ErrorToastService, - PackageState, -} from '@start9labs/shared' +import { ErrorToastService } from '@start9labs/shared' +import { PackageState } from 'src/app/types/package-state' import { wizardModal } from 'src/app/components/install-wizard/install-wizard.component' import { AlertController, diff --git a/frontend/projects/ui/src/app/pages/apps-routes/app-show/pipes/install-state.pipe.ts b/frontend/projects/ui/src/app/pages/apps-routes/app-show/pipes/install-state.pipe.ts index 8cb655099..fb00d5a18 100644 --- a/frontend/projects/ui/src/app/pages/apps-routes/app-show/pipes/install-state.pipe.ts +++ b/frontend/projects/ui/src/app/pages/apps-routes/app-show/pipes/install-state.pipe.ts @@ -1,6 +1,7 @@ import { Pipe, PipeTransform } from '@angular/core' import { PackageDataEntry } from 'src/app/services/patch-db/data-model' -import { ProgressData, packageLoadingProgress } from '@start9labs/shared' +import { ProgressData } from 'src/app/types/progress-data' +import { packageLoadingProgress } from 'src/app/util/package-loading-progress' @Pipe({ name: 'installState', diff --git a/frontend/projects/ui/src/app/pages/apps-routes/app-show/pipes/to-buttons.pipe.ts b/frontend/projects/ui/src/app/pages/apps-routes/app-show/pipes/to-buttons.pipe.ts index 117e3e882..696a597ea 100644 --- a/frontend/projects/ui/src/app/pages/apps-routes/app-show/pipes/to-buttons.pipe.ts +++ b/frontend/projects/ui/src/app/pages/apps-routes/app-show/pipes/to-buttons.pipe.ts @@ -2,8 +2,8 @@ import { Inject, Pipe, PipeTransform } from '@angular/core' import { ActivatedRoute } from '@angular/router' import { DOCUMENT } from '@angular/common' import { AlertController, ModalController, NavController } from '@ionic/angular' +import { MarkdownComponent } from '@start9labs/shared' import { PackageDataEntry } from 'src/app/services/patch-db/data-model' -import { MarkdownPage } from 'src/app/modals/markdown/markdown.page' import { ModalService } from 'src/app/services/modal.service' export interface Button { @@ -105,7 +105,7 @@ export class ToButtonsPipe implements PipeTransform { title: 'Instructions', contentUrl: pkg['static-files']['instructions'], }, - component: MarkdownPage, + component: MarkdownComponent, }) await modal.present() diff --git a/frontend/projects/ui/src/app/pages/apps-routes/app-show/pipes/to-dependencies.pipe.ts b/frontend/projects/ui/src/app/pages/apps-routes/app-show/pipes/to-dependencies.pipe.ts index 6999512f3..16d7cad27 100644 --- a/frontend/projects/ui/src/app/pages/apps-routes/app-show/pipes/to-dependencies.pipe.ts +++ b/frontend/projects/ui/src/app/pages/apps-routes/app-show/pipes/to-dependencies.pipe.ts @@ -8,7 +8,8 @@ import { DependencyErrorType, PackageDataEntry, } from 'src/app/services/patch-db/data-model' -import { DependentInfo, exists } from '@start9labs/shared' +import { exists } from '@start9labs/shared' +import { DependentInfo } from 'src/app/types/dependent-info' import { PatchDbService } from 'src/app/services/patch-db/patch-db.service' import { ModalService } from 'src/app/services/modal.service' diff --git a/frontend/projects/ui/src/app/pages/developer-routes/dev-config/dev-config.page.ts b/frontend/projects/ui/src/app/pages/developer-routes/dev-config/dev-config.page.ts index 816b63185..a9e122067 100644 --- a/frontend/projects/ui/src/app/pages/developer-routes/dev-config/dev-config.page.ts +++ b/frontend/projects/ui/src/app/pages/developer-routes/dev-config/dev-config.page.ts @@ -5,9 +5,8 @@ import * as yaml from 'js-yaml' import { take } from 'rxjs/operators' import { ApiService } from 'src/app/services/api/embassy-api.service' import { PatchDbService } from 'src/app/services/patch-db/patch-db.service' -import { debounce } from '../../../../../../shared/src/util/misc.util' import { GenericFormPage } from '../../../modals/generic-form/generic-form.page' -import { ErrorToastService } from '@start9labs/shared' +import { debounce, ErrorToastService } from '@start9labs/shared' @Component({ selector: 'dev-config', diff --git a/frontend/projects/ui/src/app/pages/developer-routes/dev-instructions/dev-instructions.page.ts b/frontend/projects/ui/src/app/pages/developer-routes/dev-instructions/dev-instructions.page.ts index 15cfc90ec..aedc88709 100644 --- a/frontend/projects/ui/src/app/pages/developer-routes/dev-instructions/dev-instructions.page.ts +++ b/frontend/projects/ui/src/app/pages/developer-routes/dev-instructions/dev-instructions.page.ts @@ -3,10 +3,12 @@ import { ActivatedRoute } from '@angular/router' import { ModalController } from '@ionic/angular' import { take } from 'rxjs/operators' import { ApiService } from 'src/app/services/api/embassy-api.service' -import { ErrorToastService } from '@start9labs/shared' +import { + debounce, + ErrorToastService, + MarkdownComponent, +} from '@start9labs/shared' import { PatchDbService } from 'src/app/services/patch-db/patch-db.service' -import { debounce } from '../../../../../../shared/src/util/misc.util' -import { MarkdownPage } from '../../../modals/markdown/markdown.page' @Component({ selector: 'dev-instructions', @@ -44,7 +46,7 @@ export class DevInstructionsPage { title: 'Instructions Sample', content: this.code, }, - component: MarkdownPage, + component: MarkdownComponent, }) await modal.present() diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list-content/marketplace-list-content.component.html b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list-content/marketplace-list-content.component.html index 1d3dc074c..a9acc2d5c 100644 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list-content/marketplace-list-content.component.html +++ b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list-content/marketplace-list-content.component.html @@ -1,62 +1,34 @@

{{ name }}

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

All services are up to date!

- - - - - -

- {{ pkg.manifest.title }} -

-

{{ pkg.manifest.description.short }}

- -
-
+ + +
- + diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list-content/marketplace-list-content.component.scss b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list-content/marketplace-list-content.component.scss index 960ac8c80..61046d840 100644 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list-content/marketplace-list-content.component.scss +++ b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list-content/marketplace-list-content.component.scss @@ -12,35 +12,6 @@ text-align: center; } -.grid { - padding-bottom: 32px; -} - -.pkg-title { - font-family: 'Montserrat', sans-serif; - font-weight: bold; -} - -.eos-item { - --border-style: none; - --background: linear-gradient( - 45deg, - var(--ion-color-dark) -380%, - var(--ion-color-medium) 100% - ); -} - -.category { - font-weight: 300; - color: var(--ion-color-dark-shade); - - &_selected { - font-weight: bold; - font-size: 17px; - color: var(--color); - } -} - .status { font-size: 14px; } diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list-content/marketplace-list-content.component.ts b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list-content/marketplace-list-content.component.ts index e9555f279..9fb97efc6 100644 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list-content/marketplace-list-content.component.ts +++ b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list-content/marketplace-list-content.component.ts @@ -1,5 +1,7 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core' -import { LocalPkg, MarketplacePkg } from '@start9labs/marketplace' +import { MarketplacePkg } from '@start9labs/marketplace' + +import { PackageDataEntry } from 'src/app/services/patch-db/data-model' @Component({ selector: 'marketplace-list-content', @@ -12,7 +14,7 @@ export class MarketplaceListContentComponent { pkgs: MarketplacePkg[] | null = null @Input() - localPkgs: Record = {} + localPkgs: Record = {} @Input() categories: Set | null = null @@ -23,11 +25,7 @@ export class MarketplaceListContentComponent { category = 'featured' query = '' - isSelected(category: string) { - return category === this.category && !this.query - } - - switchCategory(category: string): void { + onCategoryChange(category: string): void { this.category = category this.query = '' } diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list-header/marketplace-list-header.component.html b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list-header/marketplace-list-header.component.html deleted file mode 100644 index 33e24d7b9..000000000 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list-header/marketplace-list-header.component.html +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list-header/marketplace-list-header.component.ts b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list-header/marketplace-list-header.component.ts deleted file mode 100644 index c13ea6f63..000000000 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list-header/marketplace-list-header.component.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { ChangeDetectionStrategy, Component } from '@angular/core' - -@Component({ - selector: 'marketplace-list-header', - templateUrl: 'marketplace-list-header.component.html', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class MarketplaceListHeaderComponent {} diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list-skeleton/marketplace-list-skeleton.component.ts b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list-skeleton/marketplace-list-skeleton.component.ts deleted file mode 100644 index fe08787bf..000000000 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list-skeleton/marketplace-list-skeleton.component.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { ChangeDetectionStrategy, Component } from '@angular/core' - -@Component({ - selector: 'marketplace-list-skeleton', - templateUrl: 'marketplace-list-skeleton.component.html', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class MarketplaceListSkeletonComponent {} diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.module.ts b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.module.ts index 32dd3b956..c0ab34564 100644 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.module.ts +++ b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.module.ts @@ -8,13 +8,17 @@ import { EmverPipesModule, TextSpinnerComponentModule, } from '@start9labs/shared' -import { MarketplacePipesModule } from '@start9labs/marketplace' +import { + FilterPackagesPipeModule, + CategoriesModule, + ItemModule, + SearchModule, + SkeletonModule, +} from '@start9labs/marketplace' import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.module' import { MarketplaceStatusModule } from '../marketplace-status/marketplace-status.module' import { MarketplaceListPage } from './marketplace-list.page' -import { MarketplaceListHeaderComponent } from './marketplace-list-header/marketplace-list-header.component' -import { MarketplaceListSkeletonComponent } from './marketplace-list-skeleton/marketplace-list-skeleton.component' import { MarketplaceListContentComponent } from './marketplace-list-content/marketplace-list-content.component' const routes: Routes = [ @@ -33,21 +37,15 @@ const routes: Routes = [ TextSpinnerComponentModule, SharedPipesModule, EmverPipesModule, - MarketplacePipesModule, + FilterPackagesPipeModule, MarketplaceStatusModule, BadgeMenuComponentModule, + ItemModule, + CategoriesModule, + SearchModule, + SkeletonModule, ], - declarations: [ - MarketplaceListPage, - MarketplaceListHeaderComponent, - MarketplaceListContentComponent, - MarketplaceListSkeletonComponent, - ], - exports: [ - MarketplaceListPage, - MarketplaceListHeaderComponent, - MarketplaceListContentComponent, - MarketplaceListSkeletonComponent, - ], + declarations: [MarketplaceListPage, MarketplaceListContentComponent], + exports: [MarketplaceListPage, MarketplaceListContentComponent], }) export class MarketplaceListPageModule {} 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 67955c0bb..d56e85af5 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 @@ -1,4 +1,10 @@ - + + + + + + + > = defer(() => - this.patch.watch$('package-data'), + readonly localPkgs$: Observable> = defer( + () => this.patch.watch$('package-data'), ).pipe( filter(data => exists(data) && !isEmptyObject(data)), tap(pkgs => Object.values(pkgs).forEach(spreadProgress)), diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-about/marketplace-show-about.component.ts b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-about/marketplace-show-about.component.ts deleted file mode 100644 index 257898dfa..000000000 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-about/marketplace-show-about.component.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { ChangeDetectionStrategy, Component, Input } from '@angular/core' -import { MarketplacePkg } from '@start9labs/marketplace' - -@Component({ - selector: 'marketplace-show-about', - templateUrl: 'marketplace-show-about.component.html', - styleUrls: ['marketplace-show-about.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class MarketplaceShowAboutComponent { - @Input() - pkg: MarketplacePkg -} diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-controls/marketplace-show-controls.component.ts b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-controls/marketplace-show-controls.component.ts index 9a04022a1..4d5bb543b 100644 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-controls/marketplace-show-controls.component.ts +++ b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-controls/marketplace-show-controls.component.ts @@ -3,11 +3,14 @@ import { AlertController, ModalController, NavController } from '@ionic/angular' import { AbstractMarketplaceService, MarketplacePkg, - LocalPkg, } from '@start9labs/marketplace' -import { pauseFor, PackageState } from '@start9labs/shared' +import { pauseFor } from '@start9labs/shared' -import { Manifest } from 'src/app/services/patch-db/data-model' +import { PackageState } from 'src/app/types/package-state' +import { + Manifest, + PackageDataEntry, +} from 'src/app/services/patch-db/data-model' import { wizardModal } from 'src/app/components/install-wizard/install-wizard.component' import { WizardBaker } from 'src/app/components/install-wizard/prebaked-wizards' import { LocalStorageService } from 'src/app/services/local-storage.service' @@ -22,7 +25,7 @@ export class MarketplaceShowControlsComponent { pkg: MarketplacePkg @Input() - localPkg: LocalPkg + localPkg: PackageDataEntry readonly PackageState = PackageState diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-dependencies/marketplace-show-dependencies.component.html b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-dependencies/marketplace-show-dependencies.component.html deleted file mode 100644 index 71af3a9d3..000000000 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-dependencies/marketplace-show-dependencies.component.html +++ /dev/null @@ -1,32 +0,0 @@ - - Dependencies - - - - - - - - -

- {{ pkg['dependency-metadata'][dep.key].title }} - - (required) - (required by default) - (optional) - -

-

- {{ dep.value.version | displayEmver }} -

-

{{ dep.value.description }}

-
-
-
-
-
-
diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-dependencies/marketplace-show-dependencies.component.ts b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-dependencies/marketplace-show-dependencies.component.ts deleted file mode 100644 index 450149c95..000000000 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-dependencies/marketplace-show-dependencies.component.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ChangeDetectionStrategy, Component, Input } from '@angular/core' -import { MarketplacePkg } from '@start9labs/marketplace' - -import { DependencyInfo, Manifest } from 'src/app/services/patch-db/data-model' - -@Component({ - selector: 'marketplace-show-dependencies', - templateUrl: 'marketplace-show-dependencies.component.html', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class MarketplaceShowDependenciesComponent { - @Input() - pkg: MarketplacePkg - - get dependencies(): DependencyInfo { - // TODO: Fix type - return (this.pkg.manifest as Manifest).dependencies - } - - getImg(key: string): string { - return 'data:image/png;base64,' + this.pkg['dependency-metadata'][key].icon - } -} diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-dependent/marketplace-show-dependent.component.html b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-dependent/marketplace-show-dependent.component.html index 99722c191..6827c6337 100644 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-dependent/marketplace-show-dependent.component.html +++ b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-dependent/marketplace-show-dependent.component.html @@ -1,5 +1,5 @@ - +

diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-dependent/marketplace-show-dependent.component.ts b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-dependent/marketplace-show-dependent.component.ts index 224bc4001..4b74cacf8 100644 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-dependent/marketplace-show-dependent.component.ts +++ b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-dependent/marketplace-show-dependent.component.ts @@ -1,6 +1,12 @@ -import { ChangeDetectionStrategy, Component, Input } from '@angular/core' +import { + ChangeDetectionStrategy, + Component, + Inject, + Input, +} from '@angular/core' import { MarketplacePkg } from '@start9labs/marketplace' -import { DependentInfo } from '@start9labs/shared' +import { DOCUMENT } from '@angular/common' +import { DependentInfo } from 'src/app/types/dependent-info' @Component({ selector: 'marketplace-show-dependent', @@ -12,7 +18,10 @@ export class MarketplaceShowDependentComponent { @Input() pkg: MarketplacePkg - readonly dependentInfo?: DependentInfo = history.state?.dependentInfo + readonly dependentInfo?: DependentInfo = + this.document.defaultView?.history.state?.dependentInfo + + constructor(@Inject(DOCUMENT) private readonly document: Document) {} get title(): string { return this.pkg?.manifest.title || '' diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show.module.ts b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show.module.ts index 40c5aeb60..985d8b1fa 100644 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show.module.ts +++ b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show.module.ts @@ -8,16 +8,18 @@ import { MarkdownPipeModule, TextSpinnerComponentModule, } from '@start9labs/shared' -import { MarketplacePipesModule } from '@start9labs/marketplace' +import { + PackageModule, + AboutModule, + AdditionalModule, + DependenciesModule, +} from '@start9labs/marketplace' import { InstallWizardComponentModule } from 'src/app/components/install-wizard/install-wizard.component.module' import { MarketplaceStatusModule } from '../marketplace-status/marketplace-status.module' import { MarketplaceShowPage } from './marketplace-show.page' import { MarketplaceShowHeaderComponent } from './marketplace-show-header/marketplace-show-header.component' import { MarketplaceShowDependentComponent } from './marketplace-show-dependent/marketplace-show-dependent.component' -import { MarketplaceShowDependenciesComponent } from './marketplace-show-dependencies/marketplace-show-dependencies.component' -import { MarketplaceShowAdditionalComponent } from './marketplace-show-additional/marketplace-show-additional.component' -import { MarketplaceShowAboutComponent } from './marketplace-show-about/marketplace-show-about.component' import { MarketplaceShowControlsComponent } from './marketplace-show-controls/marketplace-show-controls.component' const routes: Routes = [ @@ -36,27 +38,24 @@ const routes: Routes = [ SharedPipesModule, EmverPipesModule, MarkdownPipeModule, - MarketplacePipesModule, MarketplaceStatusModule, InstallWizardComponentModule, + PackageModule, + AboutModule, + DependenciesModule, + AdditionalModule, ], declarations: [ MarketplaceShowPage, MarketplaceShowHeaderComponent, MarketplaceShowControlsComponent, MarketplaceShowDependentComponent, - MarketplaceShowAboutComponent, - MarketplaceShowDependenciesComponent, - MarketplaceShowAdditionalComponent, ], exports: [ MarketplaceShowPage, MarketplaceShowHeaderComponent, MarketplaceShowControlsComponent, MarketplaceShowDependentComponent, - MarketplaceShowAboutComponent, - MarketplaceShowDependenciesComponent, - MarketplaceShowAdditionalComponent, ], }) export class MarketplaceShowPageModule {} diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show.page.html b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show.page.html index 78af9db43..5b6ce46d8 100644 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show.page.html +++ b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show.page.html @@ -2,72 +2,53 @@ - - - -
- -
-

{{ pkg.manifest.title }}

-

- {{ pkg.manifest.version | displayEmver }} -

- -
-
-
- - - -
- - - + + + + + - View Service - - - -
+ + View Service + + + + - + - - + + + + - - - - + (version)="loadVersion$.next($event)" + > +
diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show.page.scss b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show.page.scss index 5f2fdf00f..e8f9e8e0c 100644 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show.page.scss +++ b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show.page.scss @@ -1,30 +1,3 @@ -.header { - font-family: 'Montserrat', sans-serif; - padding: 2%; - - img { - min-width: 15%; - max-width: 18%; - } - - .header-text { - margin-left: 5%; - display: inline-block; - vertical-align: top; - - .header-title { - margin: 0 0 0 -2px; - font-size: calc(20px + 3vw); - } - - .header-version { - padding: 4px 0 12px 0; - margin: 0; - font-size: calc(10px + 1vw); - } - - .header-status { - font-size: calc(16px + 1vw); - } - } +.status { + font-size: calc(16px + 1vw); } diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show.page.ts b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show.page.ts index 49a1df720..2df7ac541 100644 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show.page.ts +++ b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show.page.ts @@ -2,21 +2,15 @@ import { ChangeDetectionStrategy, Component } from '@angular/core' import { ActivatedRoute } from '@angular/router' import { ErrorToastService } from '@start9labs/shared' import { - LocalPkg, MarketplacePkg, AbstractMarketplaceService, - spreadProgress, } from '@start9labs/marketplace' import { PatchDbService } from 'src/app/services/patch-db/patch-db.service' +import { PackageDataEntry } from 'src/app/services/patch-db/data-model' import { BehaviorSubject, defer, Observable, of } from 'rxjs' -import { - catchError, - filter, - shareReplay, - startWith, - switchMap, - tap, -} from 'rxjs/operators' +import { catchError, filter, shareReplay, switchMap, tap } from 'rxjs/operators' + +import { spreadProgress } from '../utils/spread-progress' @Component({ selector: 'marketplace-show', @@ -32,16 +26,14 @@ export class MarketplaceShowPage { readonly localPkg$ = defer(() => this.patch.watch$('package-data', this.pkgId), ).pipe( - filter(Boolean), + filter(Boolean), tap(spreadProgress), shareReplay({ bufferSize: 1, refCount: true }), ) readonly pkg$: Observable = this.loadVersion$.pipe( switchMap(version => - this.marketplaceService - .getPackage(this.pkgId, version) - .pipe(startWith(null)), + this.marketplaceService.getPackage(this.pkgId, version), ), // TODO: Better fallback catchError(e => this.errToast.present(e) && of({} as MarketplacePkg)), @@ -57,16 +49,4 @@ export class MarketplaceShowPage { getIcon(icon: string): string { return `data:image/png;base64,${icon}` } - - // async getPkg(version: string): Promise { - // this.loading = true - // try { - // this.pkg = await this.marketplaceService.getPkg(this.pkgId, version) - // } catch (e) { - // this.errToast.present(e) - // } finally { - // await pauseFor(100) - // this.loading = false - // } - // } } diff --git a/frontend/projects/marketplace/src/pipes/install-progress.pipe.ts b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-status/install-progress.pipe.ts similarity index 70% rename from frontend/projects/marketplace/src/pipes/install-progress.pipe.ts rename to frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-status/install-progress.pipe.ts index c7474b9b8..2c20f7a1f 100644 --- a/frontend/projects/marketplace/src/pipes/install-progress.pipe.ts +++ b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-status/install-progress.pipe.ts @@ -1,5 +1,6 @@ import { Pipe, PipeTransform } from '@angular/core' -import { InstallProgress, packageLoadingProgress } from '@start9labs/shared' +import { InstallProgress } from 'src/app/types/install-progress' +import { packageLoadingProgress } from 'src/app/util/package-loading-progress' @Pipe({ name: 'installProgress', diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-status/marketplace-status.component.html b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-status/marketplace-status.component.html index d1bcee7ab..84ab641d2 100644 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-status/marketplace-status.component.html +++ b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-status/marketplace-status.component.html @@ -24,5 +24,5 @@ -
Not Installed
+ Not Installed
diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-status/marketplace-status.component.ts b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-status/marketplace-status.component.ts index 2827d5afe..9c7d4ac1f 100644 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-status/marketplace-status.component.ts +++ b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-status/marketplace-status.component.ts @@ -1,6 +1,6 @@ import { Component, Input } from '@angular/core' -import { LocalPkg } from '@start9labs/marketplace' -import { PackageState } from '@start9labs/shared' +import { PackageState } from 'src/app/types/package-state' +import { PackageDataEntry } from 'src/app/services/patch-db/data-model' @Component({ selector: 'marketplace-status', @@ -8,7 +8,7 @@ import { PackageState } from '@start9labs/shared' }) export class MarketplaceStatusComponent { @Input() - pkg?: LocalPkg + pkg?: PackageDataEntry PackageState = PackageState diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-status/marketplace-status.module.ts b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-status/marketplace-status.module.ts index 783266bb7..5568b26c4 100644 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-status/marketplace-status.module.ts +++ b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-status/marketplace-status.module.ts @@ -2,18 +2,13 @@ import { CommonModule } from '@angular/common' import { NgModule } from '@angular/core' import { IonicModule } from '@ionic/angular' import { EmverPipesModule } from '@start9labs/shared' -import { MarketplacePipesModule } from '@start9labs/marketplace' +import { InstallProgressPipe } from './install-progress.pipe' import { MarketplaceStatusComponent } from './marketplace-status.component' @NgModule({ - imports: [ - CommonModule, - IonicModule, - EmverPipesModule, - MarketplacePipesModule, - ], - declarations: [MarketplaceStatusComponent], + imports: [CommonModule, IonicModule, EmverPipesModule], + declarations: [MarketplaceStatusComponent, InstallProgressPipe], exports: [MarketplaceStatusComponent], }) export class MarketplaceStatusModule {} diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/release-notes/release-notes-header/release-notes-header.component.html b/frontend/projects/ui/src/app/pages/marketplace-routes/release-notes/release-notes-header/release-notes-header.component.html deleted file mode 100644 index 3c8c19d7f..000000000 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/release-notes/release-notes-header/release-notes-header.component.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - Release Notes - - diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/release-notes/release-notes-header/release-notes-header.component.ts b/frontend/projects/ui/src/app/pages/marketplace-routes/release-notes/release-notes-header/release-notes-header.component.ts deleted file mode 100644 index 7e4e405a7..000000000 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/release-notes/release-notes-header/release-notes-header.component.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { ChangeDetectionStrategy, Component } from '@angular/core' -import { ActivatedRoute } from '@angular/router' - -@Component({ - selector: 'release-notes-header', - templateUrl: 'release-notes-header.component.html', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class ReleaseNotesHeaderComponent { - readonly href = `/marketplace/${this.route.snapshot.paramMap.get('pkgId')}` - - constructor(private readonly route: ActivatedRoute) {} -} diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/release-notes/release-notes.module.ts b/frontend/projects/ui/src/app/pages/marketplace-routes/release-notes/release-notes.module.ts index 0788c5b60..dfff311b3 100644 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/release-notes/release-notes.module.ts +++ b/frontend/projects/ui/src/app/pages/marketplace-routes/release-notes/release-notes.module.ts @@ -1,17 +1,9 @@ import { NgModule } from '@angular/core' -import { CommonModule } from '@angular/common' import { Routes, RouterModule } from '@angular/router' import { IonicModule } from '@ionic/angular' -import { - EmverPipesModule, - MarkdownPipeModule, - TextSpinnerComponentModule, - ElementModule, -} from '@start9labs/shared' -import { MarketplacePipesModule } from '@start9labs/marketplace' +import { ReleaseNotesModule } from '@start9labs/marketplace' import { ReleaseNotesPage } from './release-notes.page' -import { ReleaseNotesHeaderComponent } from './release-notes-header/release-notes-header.component' const routes: Routes = [ { @@ -21,17 +13,8 @@ const routes: Routes = [ ] @NgModule({ - imports: [ - CommonModule, - IonicModule, - RouterModule.forChild(routes), - TextSpinnerComponentModule, - EmverPipesModule, - MarkdownPipeModule, - MarketplacePipesModule, - ElementModule, - ], - declarations: [ReleaseNotesPage, ReleaseNotesHeaderComponent], - exports: [ReleaseNotesPage, ReleaseNotesHeaderComponent], + imports: [IonicModule, ReleaseNotesModule, RouterModule.forChild(routes)], + declarations: [ReleaseNotesPage], + exports: [ReleaseNotesPage], }) export class ReleaseNotesPageModule {} diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/release-notes/release-notes.page.html b/frontend/projects/ui/src/app/pages/marketplace-routes/release-notes/release-notes.page.html index 1b6666027..df9605253 100644 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/release-notes/release-notes.page.html +++ b/frontend/projects/ui/src/app/pages/marketplace-routes/release-notes/release-notes.page.html @@ -1,34 +1,10 @@ - + + + + + + Release Notes + + - - -
- -

{{ note.key | displayEmver }}

-
- - - -
-
- - - - -
+ diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/release-notes/release-notes.page.ts b/frontend/projects/ui/src/app/pages/marketplace-routes/release-notes/release-notes.page.ts index 1139c07eb..de0487c24 100644 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/release-notes/release-notes.page.ts +++ b/frontend/projects/ui/src/app/pages/marketplace-routes/release-notes/release-notes.page.ts @@ -1,38 +1,12 @@ -import { ChangeDetectionStrategy, Component, ElementRef } from '@angular/core' +import { ChangeDetectionStrategy, Component } from '@angular/core' import { ActivatedRoute } from '@angular/router' -import { AbstractMarketplaceService } from '@start9labs/marketplace' @Component({ - selector: 'release-notes', templateUrl: './release-notes.page.html', - styleUrls: ['./release-notes.page.scss'], changeDetection: ChangeDetectionStrategy.OnPush, }) export class ReleaseNotesPage { - private readonly pkgId = this.route.snapshot.paramMap.get('pkgId') + readonly href = `/marketplace/${this.route.snapshot.paramMap.get('pkgId')}` - private selected: string | null = null - - readonly notes$ = this.marketplaceService.getReleaseNotes(this.pkgId) - - constructor( - private readonly route: ActivatedRoute, - private readonly marketplaceService: AbstractMarketplaceService, - ) {} - - isSelected(key: string): boolean { - return this.selected === key - } - - setSelected(selected: string) { - this.selected = this.isSelected(selected) ? null : selected - } - - getDocSize(key: string, { nativeElement }: ElementRef) { - return this.isSelected(key) ? nativeElement.scrollHeight : 0 - } - - asIsOrder(a: any, b: any) { - return 0 - } + constructor(private readonly route: ActivatedRoute) {} } diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/utils/spread-progress.ts b/frontend/projects/ui/src/app/pages/marketplace-routes/utils/spread-progress.ts new file mode 100644 index 000000000..3c31eb869 --- /dev/null +++ b/frontend/projects/ui/src/app/pages/marketplace-routes/utils/spread-progress.ts @@ -0,0 +1,5 @@ +import { PackageDataEntry } from 'src/app/services/patch-db/data-model' + +export function spreadProgress(pkg: PackageDataEntry) { + pkg['install-progress'] = { ...pkg['install-progress'] } +} diff --git a/frontend/projects/ui/src/app/pipes/launchable/launchable.pipe.ts b/frontend/projects/ui/src/app/pipes/launchable/launchable.pipe.ts index b664ab142..100c0eed9 100644 --- a/frontend/projects/ui/src/app/pipes/launchable/launchable.pipe.ts +++ b/frontend/projects/ui/src/app/pipes/launchable/launchable.pipe.ts @@ -1,5 +1,5 @@ import { Pipe, PipeTransform } from '@angular/core' -import { PackageState } from '@start9labs/shared' +import { PackageState } from 'src/app/types/package-state' import { InterfaceDef, PackageMainStatus, diff --git a/frontend/projects/ui/src/app/services/api/api.fixures.ts b/frontend/projects/ui/src/app/services/api/api.fixures.ts index 882252e14..9b0772add 100644 --- a/frontend/projects/ui/src/app/services/api/api.fixures.ts +++ b/frontend/projects/ui/src/app/services/api/api.fixures.ts @@ -1,4 +1,4 @@ -import { PackageState } from '@start9labs/shared' +import { PackageState } from 'src/app/types/package-state' import { ConfigSpec } from 'src/app/pkg-config/config-types' import { DependencyErrorType, diff --git a/frontend/projects/ui/src/app/services/api/embassy-api.service.ts b/frontend/projects/ui/src/app/services/api/embassy-api.service.ts index cf863c7c6..d07b54191 100644 --- a/frontend/projects/ui/src/app/services/api/embassy-api.service.ts +++ b/frontend/projects/ui/src/app/services/api/embassy-api.service.ts @@ -1,3 +1,4 @@ +import { AbstractApiService } from '@start9labs/shared' import { Subject, Observable } from 'rxjs' import { Http, @@ -13,7 +14,10 @@ import { DataModel } from 'src/app/services/patch-db/data-model' import { RequestError } from '../http.service' import { map } from 'rxjs/operators' -export abstract class ApiService implements Source, Http { +export abstract class ApiService + extends AbstractApiService + implements Source, Http +{ protected readonly sync$ = new Subject>() /** PatchDb Source interface. Post/Patch requests provide a source of patches to the db. */ @@ -24,9 +28,6 @@ export abstract class ApiService implements Source, Http { .pipe(map(result => ({ result, jsonrpc: '2.0' }))) } - // for getting static files: ex icons, instructions, licenses - abstract getStatic(url: string): Promise - // db abstract getRevisions(since: number): Promise diff --git a/frontend/projects/ui/src/app/services/api/embassy-mock-api.service.ts b/frontend/projects/ui/src/app/services/api/embassy-mock-api.service.ts index 174cc0293..1f29a630d 100644 --- a/frontend/projects/ui/src/app/services/api/embassy-mock-api.service.ts +++ b/frontend/projects/ui/src/app/services/api/embassy-mock-api.service.ts @@ -1,8 +1,9 @@ import { Injectable } from '@angular/core' -import { InstallProgress, pauseFor } from '@start9labs/shared' +import { pauseFor } from '@start9labs/shared' import { ApiService } from './embassy-api.service' import { PatchOp, Update, Operation, RemoveOperation } from 'patch-db-client' -import { PackageState } from '@start9labs/shared' +import { PackageState } from 'src/app/types/package-state' +import { InstallProgress } from 'src/app/types/install-progress' import { DataModel, DependencyErrorType, @@ -192,6 +193,8 @@ export class MockApiService extends ApiService { return Mock.MarketplacePkgsList } else if (path.startsWith('/package/v0/release-notes')) { return Mock.ReleaseNotes + } else if (path.includes('instructions') || path.includes('license')) { + return markdown } } diff --git a/frontend/projects/ui/src/app/services/api/mock-patch.ts b/frontend/projects/ui/src/app/services/api/mock-patch.ts index 02e039e07..6b44313ae 100644 --- a/frontend/projects/ui/src/app/services/api/mock-patch.ts +++ b/frontend/projects/ui/src/app/services/api/mock-patch.ts @@ -1,4 +1,4 @@ -import { PackageState } from '@start9labs/shared' +import { PackageState } from 'src/app/types/package-state' import { DataModel, DependencyErrorType, diff --git a/frontend/projects/ui/src/app/services/config.service.ts b/frontend/projects/ui/src/app/services/config.service.ts index 05cc718d5..c580dea1f 100644 --- a/frontend/projects/ui/src/app/services/config.service.ts +++ b/frontend/projects/ui/src/app/services/config.service.ts @@ -1,5 +1,6 @@ import { Injectable } from '@angular/core' -import { WorkspaceConfig, PackageState } from '@start9labs/shared' +import { WorkspaceConfig } from '@start9labs/shared' +import { PackageState } from 'src/app/types/package-state' import { InterfaceDef, PackageDataEntry, diff --git a/frontend/projects/ui/src/app/services/marketplace.service.ts b/frontend/projects/ui/src/app/services/marketplace.service.ts index edf938fbd..42646770d 100644 --- a/frontend/projects/ui/src/app/services/marketplace.service.ts +++ b/frontend/projects/ui/src/app/services/marketplace.service.ts @@ -15,9 +15,9 @@ import { ServerInfo } from 'src/app/services/patch-db/data-model' import { PatchDbService } from 'src/app/services/patch-db/patch-db.service' import { catchError, - finalize, map, shareReplay, + startWith, switchMap, tap, } from 'rxjs/operators' @@ -56,11 +56,11 @@ export class MarketplaceService extends AbstractMarketplaceService { constructor( private readonly api: ApiService, - private readonly emver: Emver, private readonly patch: PatchDbService, private readonly config: ConfigService, private readonly loadingCtrl: LoadingController, private readonly errToast: ErrorToastService, + private readonly emver: Emver, ) { super() } @@ -79,12 +79,17 @@ export class MarketplaceService extends AbstractMarketplaceService { getPackage(id: string, version: string): Observable { const params = { ids: [{ id, version }] } - - return this.init$.pipe( + const fallback$ = this.init$.pipe( switchMap(({ url }) => from(this.getMarketplacePkgs(params, url))), - map(pkgs => pkgs.find(pkg => pkg.manifest.id == id)), + map(pkgs => this.findPackage(pkgs, id, version)), + startWith(null), + ) + + return this.getPackages().pipe( + map(pkgs => this.findPackage(pkgs, id, version)), + switchMap(pkg => (pkg ? of(pkg) : fallback$)), tap(pkg => { - if (!pkg) { + if (pkg === undefined) { throw new Error(`No results for ${id}${version ? ' ' + version : ''}`) } }), @@ -103,26 +108,6 @@ export class MarketplaceService extends AbstractMarketplaceService { ) } - // async install(id: string, version?: string): Promise { - // const loader = await this.loadingCtrl.create({ - // spinner: 'lines', - // message: 'Beginning Installation', - // cssClass: 'loader', - // }) - // loader.present() - // - // try { - // await this.installPackage({ - // id, - // 'version-spec': version ? `=${version}` : undefined, - // }) - // } catch (e) { - // this.errToast.present(e) - // } finally { - // loader.dismiss() - // } - // } - install(id: string, version?: string): Observable { return defer(() => from( @@ -161,6 +146,20 @@ export class MarketplaceService extends AbstractMarketplaceService { ) } + getPackageMarkdown(type: string, pkgId: string): Observable { + return this.getMarketplace().pipe( + switchMap(({ url }) => + from( + this.api.marketplaceProxy( + `/package/v0/${type}/${pkgId}`, + {}, + url, + ), + ), + ), + ) + } + async getMarketplaceData( params: RR.GetMarketplaceDataReq, url: string, @@ -217,4 +216,18 @@ export class MarketplaceService extends AbstractMarketplaceService { }) } } + + private findPackage( + pkgs: readonly MarketplacePkg[], + id: string, + version: string, + ): MarketplacePkg | undefined { + return pkgs.find(pkg => { + const versionIsSame = + version === '*' || + this.emver.compare(pkg.manifest.version, version) === 0 + + return pkg.manifest.id === id && versionIsSame + }) + } } diff --git a/frontend/projects/ui/src/app/services/modal.service.ts b/frontend/projects/ui/src/app/services/modal.service.ts index df8174333..147492709 100644 --- a/frontend/projects/ui/src/app/services/modal.service.ts +++ b/frontend/projects/ui/src/app/services/modal.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core' import { ActivatedRoute } from '@angular/router' import { ModalController } from '@ionic/angular' -import { DependentInfo } from '@start9labs/shared' +import { DependentInfo } from 'src/app/types/dependent-info' import { AppConfigPage } from 'src/app/modals/app-config/app-config.page' @Injectable({ diff --git a/frontend/projects/ui/src/app/services/patch-db/data-model.ts b/frontend/projects/ui/src/app/services/patch-db/data-model.ts index 55268a846..41a38da12 100644 --- a/frontend/projects/ui/src/app/services/patch-db/data-model.ts +++ b/frontend/projects/ui/src/app/services/patch-db/data-model.ts @@ -1,7 +1,9 @@ import { ConfigSpec } from 'src/app/pkg-config/config-types' -import { InstallProgress, PackageState, Url } from '@start9labs/shared' +import { Url } from '@start9labs/shared' import { MarketplaceManifest } from '@start9labs/marketplace' import { BasicInfo } from 'src/app/pages/developer-routes/developer-menu/form-info' +import { PackageState } from 'src/app/types/package-state' +import { InstallProgress } from 'src/app/types/install-progress' export interface DataModel { 'server-info': ServerInfo @@ -111,7 +113,7 @@ export interface CurrentDependencyInfo { 'health-checks': string[] // array of health check IDs } -export interface Manifest extends MarketplaceManifest { +export interface Manifest extends MarketplaceManifest { main: ActionImpl 'health-checks': Record< string, @@ -125,7 +127,11 @@ export interface Manifest extends MarketplaceManifest { migrations: Migrations actions: Record permissions: any // @TODO 0.3.1 - dependencies: DependencyInfo +} + +export interface DependencyConfig { + check: ActionImpl + 'auto-configure': ActionImpl } export interface ActionImpl { @@ -352,28 +358,3 @@ export interface DependencyErrorHealthChecksFailed { export interface DependencyErrorTransitive { type: DependencyErrorType.Transitive } - -export interface DependencyInfo { - [id: string]: DependencyEntry -} - -export interface DependencyEntry { - version: string - requirement: - | { - type: 'opt-in' - how: string - } - | { - type: 'opt-out' - how: string - } - | { - type: 'required' - } - description: string | null - config: { - check: ActionImpl - 'auto-configure': ActionImpl - } -} diff --git a/frontend/projects/ui/src/app/services/pkg-status-rendering.service.ts b/frontend/projects/ui/src/app/services/pkg-status-rendering.service.ts index 3ff832d9f..fcb5f6f8a 100644 --- a/frontend/projects/ui/src/app/services/pkg-status-rendering.service.ts +++ b/frontend/projects/ui/src/app/services/pkg-status-rendering.service.ts @@ -1,4 +1,5 @@ -import { isEmptyObject, PackageState } from '@start9labs/shared' +import { isEmptyObject } from '@start9labs/shared' +import { PackageState } from 'src/app/types/package-state' import { PackageDataEntry, PackageMainStatus, diff --git a/frontend/projects/shared/src/types/dependent-info.ts b/frontend/projects/ui/src/app/types/dependent-info.ts similarity index 100% rename from frontend/projects/shared/src/types/dependent-info.ts rename to frontend/projects/ui/src/app/types/dependent-info.ts diff --git a/frontend/projects/shared/src/types/install-progress.ts b/frontend/projects/ui/src/app/types/install-progress.ts similarity index 100% rename from frontend/projects/shared/src/types/install-progress.ts rename to frontend/projects/ui/src/app/types/install-progress.ts diff --git a/frontend/projects/shared/src/types/package-state.ts b/frontend/projects/ui/src/app/types/package-state.ts similarity index 100% rename from frontend/projects/shared/src/types/package-state.ts rename to frontend/projects/ui/src/app/types/package-state.ts diff --git a/frontend/projects/shared/src/types/progress-data.ts b/frontend/projects/ui/src/app/types/progress-data.ts similarity index 100% rename from frontend/projects/shared/src/types/progress-data.ts rename to frontend/projects/ui/src/app/types/progress-data.ts diff --git a/frontend/projects/ui/src/app/util/get-package-info.ts b/frontend/projects/ui/src/app/util/get-package-info.ts index c130a5cba..f49d6df48 100644 --- a/frontend/projects/ui/src/app/util/get-package-info.ts +++ b/frontend/projects/ui/src/app/util/get-package-info.ts @@ -6,8 +6,9 @@ import { renderPkgStatus, StatusRendering, } from '../services/pkg-status-rendering.service' -import { packageLoadingProgress, ProgressData } from '@start9labs/shared' +import { ProgressData } from 'src/app/types/progress-data' import { Subscription } from 'rxjs' +import { packageLoadingProgress } from './package-loading-progress' export function getPackageInfo(entry: PackageDataEntry): PkgInfo { const statuses = renderPkgStatus(entry) diff --git a/frontend/projects/shared/src/util/package-loading-progress.ts b/frontend/projects/ui/src/app/util/package-loading-progress.ts similarity index 87% rename from frontend/projects/shared/src/util/package-loading-progress.ts rename to frontend/projects/ui/src/app/util/package-loading-progress.ts index a1e276324..566103c0f 100644 --- a/frontend/projects/shared/src/util/package-loading-progress.ts +++ b/frontend/projects/ui/src/app/util/package-loading-progress.ts @@ -1,6 +1,6 @@ -import { isEmptyObject } from './misc.util' -import { InstallProgress } from '../types/install-progress' -import { ProgressData } from '../types/progress-data' +import { isEmptyObject } from '@start9labs/shared' +import { InstallProgress } from 'src/app/types/install-progress' +import { ProgressData } from 'src/app/types/progress-data' export function packageLoadingProgress( loadData: InstallProgress,