diff --git a/web/projects/marketplace/src/pages/show/additional/additional.component.html b/web/projects/marketplace/src/pages/show/additional/additional.component.html index 4f1d5b6da..f7e58147d 100644 --- a/web/projects/marketplace/src/pages/show/additional/additional.component.html +++ b/web/projects/marketplace/src/pages/show/additional/additional.component.html @@ -28,7 +28,7 @@ () + readonly static = new EventEmitter<'license' | 'instructions'>() constructor( readonly copyService: CopyService, diff --git a/web/projects/shared/src/components/initializing.component.ts b/web/projects/shared/src/components/initializing.component.ts index 1930a8301..84cb1755b 100644 --- a/web/projects/shared/src/components/initializing.component.ts +++ b/web/projects/shared/src/components/initializing.component.ts @@ -21,7 +21,7 @@ import { i18nPipe } from '../i18n/i18n.pipe' [style.margin]="'1rem auto'" [attr.value]="progress.total" > -

{{ progress.message }}

+

`, diff --git a/web/projects/shared/src/i18n/dictionaries/english.ts b/web/projects/shared/src/i18n/dictionaries/english.ts index 413af7be7..070b8d788 100644 --- a/web/projects/shared/src/i18n/dictionaries/english.ts +++ b/web/projects/shared/src/i18n/dictionaries/english.ts @@ -486,4 +486,5 @@ export const ENGLISH = { 'Refresh the page. If refreshing the page does not work, you may need to quit and re-open your browser, then revisit this page.': 484, 'StartOS UI': 485, 'WiFi': 486, + 'Instructions': 487, } as const diff --git a/web/projects/shared/src/i18n/dictionaries/german.ts b/web/projects/shared/src/i18n/dictionaries/german.ts index b8e979529..2d8d1a32d 100644 --- a/web/projects/shared/src/i18n/dictionaries/german.ts +++ b/web/projects/shared/src/i18n/dictionaries/german.ts @@ -487,4 +487,5 @@ export default { 484: 'Laden Sie die Seite neu. Wenn das nicht funktioniert, beenden Sie Ihren Browser und öffnen Sie ihn erneut, um diese Seite erneut zu besuchen.', 485: 'StartOS-Benutzeroberfläche', 486: 'WiFi', + 487: 'Anleitungen', } satisfies i18n diff --git a/web/projects/shared/src/i18n/dictionaries/polish.ts b/web/projects/shared/src/i18n/dictionaries/polish.ts index 677497b90..2f2d0cdb0 100644 --- a/web/projects/shared/src/i18n/dictionaries/polish.ts +++ b/web/projects/shared/src/i18n/dictionaries/polish.ts @@ -487,4 +487,5 @@ export default { 484: 'Odśwież stronę. Jeśli to nie pomoże, zamknij i ponownie otwórz przeglądarkę, a następnie wróć do tej strony.', 485: 'Interfejs StartOS', 486: 'WiFi', + 487: 'instrukcje', } satisfies i18n diff --git a/web/projects/shared/src/i18n/dictionaries/spanish.ts b/web/projects/shared/src/i18n/dictionaries/spanish.ts index 209a667fa..128c3d593 100644 --- a/web/projects/shared/src/i18n/dictionaries/spanish.ts +++ b/web/projects/shared/src/i18n/dictionaries/spanish.ts @@ -487,4 +487,5 @@ export default { 484: 'Actualiza la página. Si actualizar no funciona, puede que necesites cerrar y volver a abrir tu navegador, y luego volver a esta página.', 485: 'Interfaz de StartOS', 486: 'WiFi', + 487: 'Instrucciones', } as any satisfies i18n diff --git a/web/projects/ui/src/app/routes/diagnostic/home/home.page.ts b/web/projects/ui/src/app/routes/diagnostic/home/home.page.ts index 13aae5680..00a2a4171 100644 --- a/web/projects/ui/src/app/routes/diagnostic/home/home.page.ts +++ b/web/projects/ui/src/app/routes/diagnostic/home/home.page.ts @@ -5,7 +5,6 @@ import { filter } from 'rxjs' import { ApiService } from 'src/app/services/api/embassy-api.service' import { ConfigService } from 'src/app/services/config.service' -// @TODO Alex how to use i18nPipe in this component since not standalone? @Component({ selector: 'diagnostic-home', templateUrl: 'home.page.html', diff --git a/web/projects/ui/src/app/routes/portal/routes/marketplace/components/controls.component.ts b/web/projects/ui/src/app/routes/portal/routes/marketplace/components/controls.component.ts index 92a3db677..8239d0b4d 100644 --- a/web/projects/ui/src/app/routes/portal/routes/marketplace/components/controls.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/marketplace/components/controls.component.ts @@ -4,6 +4,7 @@ import { ChangeDetectionStrategy, Component, inject, + input, Input, } from '@angular/core' import { Router } from '@angular/router' @@ -29,6 +30,7 @@ import { getAllPackages, getManifest } from 'src/app/utils/get-package-data' import { dryUpdate } from 'src/app/utils/dry-update' import { MarketplaceAlertsService } from '../services/alerts.service' import { ToManifestPipe } from 'src/app/routes/portal/pipes/to-manifest' +import { ApiService } from 'src/app/services/api/embassy-api.service' @Component({ selector: 'marketplace-controls', @@ -108,6 +110,7 @@ export class MarketplaceControlsComponent { private readonly exver = inject(Exver) private readonly router = inject(Router) private readonly marketplaceService = inject(MarketplaceService) + private readonly api = inject(ApiService) @Input({ required: true }) pkg!: MarketplacePkgBase @@ -118,18 +121,25 @@ export class MarketplaceControlsComponent { @Input() localFlavor!: boolean - async tryInstall() { - const currentUrl = await firstValueFrom( - this.marketplaceService.getRegistryUrl$(), - ) - const originalUrl = this.localPkg?.registry || '' - if (!this.localPkg) { - if (await this.alerts.alertInstall(this.pkg)) this.install(currentUrl) + // only present if side loading + @Input() + file?: File + async tryInstall() { + const currentUrl = this.file + ? null + : await firstValueFrom(this.marketplaceService.getRegistryUrl$()) + const originalUrl = this.localPkg?.registry || '' + + if (!this.localPkg) { + if (await this.alerts.alertInstall(this.pkg)) { + this.installOrUpload(currentUrl) + } return } if ( + currentUrl && !sameUrl(currentUrl, originalUrl) && !(await this.alerts.alertMarketplace(currentUrl, originalUrl)) ) { @@ -144,7 +154,7 @@ export class MarketplaceControlsComponent { ) { this.dryInstall(currentUrl) } else { - this.install(currentUrl) + this.installOrUpload(currentUrl) } } @@ -152,7 +162,7 @@ export class MarketplaceControlsComponent { this.router.navigate(['/portal/services', this.pkg.id]) } - private async dryInstall(url: string) { + private async dryInstall(url: string | null) { const breakages = dryUpdate( this.pkg, await getAllPackages(this.patch), @@ -163,6 +173,14 @@ export class MarketplaceControlsComponent { isEmptyObject(breakages) || (await this.alerts.alertBreakages(breakages)) ) { + this.installOrUpload(url) + } + } + + private async installOrUpload(url: string | null) { + if (this.file) { + await this.upload() + } else if (url) { this.install(url) } } @@ -179,4 +197,17 @@ export class MarketplaceControlsComponent { loader.unsubscribe() } } + + private async upload() { + const loader = this.loader.open('Starting upload').subscribe() + + try { + const { upload } = await this.api.sideloadPackage() + this.api.uploadPackage(upload, this.file!).catch(console.error) + } catch (e: any) { + this.errorService.handleError(e) + } finally { + loader.unsubscribe() + } + } } diff --git a/web/projects/ui/src/app/routes/portal/routes/marketplace/modals/preview.component.ts b/web/projects/ui/src/app/routes/portal/routes/marketplace/modals/preview.component.ts index ad3f96c7e..9139a6874 100644 --- a/web/projects/ui/src/app/routes/portal/routes/marketplace/modals/preview.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/marketplace/modals/preview.component.ts @@ -226,7 +226,7 @@ export class MarketplacePreviewComponent { this.router.navigate([], { queryParams: { id } }) } - onStatic(type: 'License' | 'Instructions') { + onStatic(type: 'license' | 'instructions') { // @TODO Alex need to display License or Instructions. This requires an API request, check out next/minor } diff --git a/web/projects/ui/src/app/routes/portal/routes/services/components/additional-item.component.ts b/web/projects/ui/src/app/routes/portal/routes/services/components/additional-item.component.ts index 80b57ded6..832187b31 100644 --- a/web/projects/ui/src/app/routes/portal/routes/services/components/additional-item.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/services/components/additional-item.component.ts @@ -34,7 +34,7 @@ export interface AdditionalItem { target: '_blank', '[class._disabled]': 'disabled', '[attr.href]': - 'additionalItem.description.startsWith("http") ? additionalItem.description : null', + 'additionalItem.value.startsWith("http") ? additionalItem.value : null', }, changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, diff --git a/web/projects/ui/src/app/routes/portal/routes/sideload/package.component.ts b/web/projects/ui/src/app/routes/portal/routes/sideload/package.component.ts index afacc440c..4cbbd00f4 100644 --- a/web/projects/ui/src/app/routes/portal/routes/sideload/package.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/sideload/package.component.ts @@ -5,15 +5,13 @@ import { AdditionalModule, MarketplaceDependenciesComponent, MarketplacePackageHeroComponent, - MarketplacePkgBase, } from '@start9labs/marketplace' import { - ErrorService, + DialogService, Exver, - LoadingService, + MARKDOWN, SharedPipesModule, } from '@start9labs/shared' -import { ApiService } from 'src/app/services/api/embassy-api.service' import { MarketplaceControlsComponent } from '../marketplace/components/controls.component' import { filter, first, map } from 'rxjs' import { PatchDB } from 'patch-db-client' @@ -33,6 +31,7 @@ import { MarketplacePkgSideload } from './sideload.utils' [pkg]="pkg" [localPkg]="local$ | async" [localFlavor]="!!(flavor$ | async)" + [file]="file" />
@@ -105,11 +104,9 @@ import { MarketplacePkgSideload } from './sideload.utils' ], }) export class SideloadPackageComponent { - private readonly loader = inject(LoadingService) - private readonly api = inject(ApiService) - private readonly errorService = inject(ErrorService) private readonly exver = inject(Exver) private readonly patch = inject>(PatchDB) + private readonly dialog = inject(DialogService) // @Input({ required: true }) // pkg!: MarketplacePkgSideload @@ -133,20 +130,17 @@ export class SideloadPackageComponent { readonly flavor$ = this.local$.pipe(map(pkg => !pkg)) - onStatic(type: 'License' | 'Instructions') { - // @TODO Matt display License or Instructions - } - - async upload() { - const loader = this.loader.open('Starting upload').subscribe() - - try { - const { upload } = await this.api.sideloadPackage() - this.api.uploadPackage(upload, this.file).catch(console.error) - } catch (e: any) { - this.errorService.handleError(e) - } finally { - loader.unsubscribe() - } + // @TODO Alex, struggling to get this working. I don't understand how to use this markdown component, only one other example, and it's very different. + onStatic(type: 'license' | 'instructions') { + this.dialog + .openComponent(MARKDOWN, { + label: type === 'license' ? 'License' : 'Instructions', + size: 'l', + data: { + content: + this.pkg[type === 'license' ? 'fullLicense' : 'instructions'], + }, + }) + .subscribe() } } diff --git a/web/projects/ui/src/app/routes/portal/routes/sideload/sideload.utils.ts b/web/projects/ui/src/app/routes/portal/routes/sideload/sideload.utils.ts index ad1e76901..4d69a301c 100644 --- a/web/projects/ui/src/app/routes/portal/routes/sideload/sideload.utils.ts +++ b/web/projects/ui/src/app/routes/portal/routes/sideload/sideload.utils.ts @@ -41,7 +41,7 @@ async function parseS9pk(file: File): Promise { icon: await s9pk.icon(), sourceVersion: s9pk.manifest.canMigrateFrom, flavor: ExtendedVersion.parse(s9pk.manifest.version).flavor, - license: await s9pk.license(), + fullLicense: await s9pk.license(), instructions: await s9pk.instructions(), } } @@ -77,6 +77,6 @@ function compare(a: Uint8Array, b: Uint8Array) { } export type MarketplacePkgSideload = MarketplacePkgBase & { - license: string instructions: string + fullLicense: string }