fix preview versions, icons, and misc styling

This commit is contained in:
Lucy Cifferello
2024-04-02 21:16:14 -04:00
parent 74ba68ff2c
commit 9c4c211233
8 changed files with 140 additions and 86 deletions

View File

@@ -1,16 +1,13 @@
<div class="item-container box-shadow-lg"> <div class="item-container box-shadow-lg">
<!-- color background --> <!-- color background -->
<div class="background"> <div class="background">
<img <img [src]="pkg.icon" alt="{{ pkg.manifest.title }} Icon" />
[src]="pkg.icon| trustUrl"
alt="{{ pkg.manifest.title }} Icon"
/>
</div> </div>
<!-- darkening overlay --> <!-- darkening overlay -->
<div class="overlay"></div> <div class="overlay"></div>
<!-- icon --> <!-- icon -->
<img <img
[src]="pkg.icon | trustUrl" [src]="pkg.icon"
class="icon box-shadow-lg" class="icon box-shadow-lg"
alt="{{ pkg.manifest.title }} Icon" alt="{{ pkg.manifest.title }} Icon"
/> />

View File

@@ -369,7 +369,7 @@ a {
} }
.buttons { .buttons {
margin-top: 0.5rem; margin-top: 1rem;
:first-child { :first-child {
margin-right: 0.5rem; margin-right: 0.5rem;

View File

@@ -34,6 +34,8 @@ import { MARKETPLACE_REGISTRY } from '../modals/registry.component'
padding: 1.25rem; padding: 1.25rem;
font-size: 1rem; font-size: 1rem;
line-height: 1.5rem; line-height: 1.5rem;
background-color: transparent;
background-image: none;
} }
`, `,
], ],

View File

@@ -15,7 +15,6 @@ import { MarketplaceSidebarService } from '../services/sidebar.service'
position: fixed; position: fixed;
inset: 3.5rem 0 0; inset: 3.5rem 0 0;
pointer-events: none; pointer-events: none;
transform: translate3d(0, 0, 0);
} }
`, `,
], ],

View File

@@ -2,8 +2,8 @@ import { CommonModule } from '@angular/common'
import { import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
Component, Component,
Input,
inject, inject,
Input,
} from '@angular/core' } from '@angular/core'
import { ActivatedRoute, Router } from '@angular/router' import { ActivatedRoute, Router } from '@angular/router'
import { ItemModule, MarketplacePkg } from '@start9labs/marketplace' import { ItemModule, MarketplacePkg } from '@start9labs/marketplace'
@@ -30,9 +30,8 @@ import { MarketplaceSidebarService } from '../services/sidebar.service'
direction: 'right'; direction: 'right';
autoWidth: true autoWidth: true
" "
[pkgId]="pkg.manifest.id"
class="preview-wrapper" class="preview-wrapper"
[pkg]="pkg"
(tuiActiveZoneChange)="toggle($event)"
> >
<button <button
tuiAutoFocus tuiAutoFocus
@@ -88,6 +87,7 @@ import { MarketplaceSidebarService } from '../services/sidebar.service'
display: flex; display: flex;
justify-content: flex-start; justify-content: flex-start;
gap: 0.5rem; gap: 0.5rem;
height: 4.5rem;
} }
`, `,
], ],
@@ -113,7 +113,6 @@ import { MarketplaceSidebarService } from '../services/sidebar.service'
}) })
export class MarketplaceTileComponent { export class MarketplaceTileComponent {
private readonly router = inject(Router) private readonly router = inject(Router)
readonly id$ = inject(ActivatedRoute).queryParamMap.pipe( readonly id$ = inject(ActivatedRoute).queryParamMap.pipe(
map(map => map.get('id') || ''), map(map => map.get('id') || ''),
debounceTime(100), debounceTime(100),

View File

@@ -2,10 +2,8 @@ import { CommonModule } from '@angular/common'
import { import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
Component, Component,
EventEmitter,
inject, inject,
Input, Input,
Output,
TemplateRef, TemplateRef,
} from '@angular/core' } from '@angular/core'
import { import {
@@ -17,11 +15,16 @@ import {
MarketplacePackageHeroComponent, MarketplacePackageHeroComponent,
MarketplacePkg, MarketplacePkg,
ReleaseNotesModule, ReleaseNotesModule,
StoreIdentity,
} from '@start9labs/marketplace' } from '@start9labs/marketplace'
import { displayEmver, Emver, SharedPipesModule } from '@start9labs/shared' import { displayEmver, Emver, SharedPipesModule } from '@start9labs/shared'
import { TuiButtonModule } from '@taiga-ui/experimental' import { TuiButtonModule } from '@taiga-ui/experimental'
import { filter, map } from 'rxjs' import { BehaviorSubject, filter, switchMap, tap } from 'rxjs'
import { TuiDialogContext, TuiDialogService } from '@taiga-ui/core' import {
TuiDialogContext,
TuiDialogService,
TuiLoaderModule,
} from '@taiga-ui/core'
import { import {
TuiRadioListModule, TuiRadioListModule,
TuiStringifyContentPipeModule, TuiStringifyContentPipeModule,
@@ -34,63 +37,73 @@ import { Router } from '@angular/router'
template: ` template: `
<div class="outer-container"> <div class="outer-container">
<ng-content select="[slot=close]" /> <ng-content select="[slot=close]" />
<marketplace-package-hero [pkg]="pkg"> @if (pkg$ | async; as pkg) {
<ng-content select="[slot=controls]" /> @if (loading) {
</marketplace-package-hero> <tui-loader class="loading-dots" textContent="Loading" />
@if (url$ | async; as url) { } @else {
<a <marketplace-package-hero [pkg]="pkg">
[href]="url + '/marketplace/' + pkg.manifest.id" <ng-content select="[slot=controls]" />
tuiButton </marketplace-package-hero>
appearance="tertiary-solid" @if (hostInfo$ | async; as info) {
iconRight="tuiIconExternalLink" <a
target="_blank" [href]="constructDetailLink(info, pkg.manifest.id)"
> tuiButton
View more details appearance="tertiary-solid"
</a> iconRight="tuiIconExternalLink"
} target="_blank"
<div class="inner-container"> >
<marketplace-about [pkg]="pkg" /> View more details
@if (!(pkg.manifest.dependencies | empty)) { </a>
<marketplace-dependencies }
[pkg]="pkg" <div class="inner-container">
(open)="open($event)" <marketplace-about [pkg]="pkg" />
></marketplace-dependencies> @if (!(pkg.manifest.dependencies | empty)) {
<marketplace-dependencies
[pkg]="pkg"
(open)="open($event)"
></marketplace-dependencies>
}
<release-notes [pkg]="pkg" />
<marketplace-additional class="additional-wrapper" [pkg]="pkg">
<marketplace-additional-item
(click)="presentAlertVersions(pkg, version)"
data="Click to view all versions"
label="All versions"
icon="tuiIconChevronRightLarge"
class="versions"
></marketplace-additional-item>
<ng-template
#version
let-data="data"
let-completeWith="completeWith"
>
<tui-radio-list
size="l"
[items]="data.items"
[itemContent]="displayEmver | tuiStringifyContent"
[(ngModel)]="data.value"
></tui-radio-list>
<footer class="buttons">
<button
tuiButton
appearance="secondary"
(click)="completeWith(null)"
>
Cancel
</button>
<button
tuiButton
appearance="secondary"
(click)="loading = true; completeWith(data.value)"
>
Ok
</button>
</footer>
</ng-template>
</marketplace-additional>
</div>
} }
<release-notes [pkg]="pkg" /> }
<marketplace-additional class="additional-wrapper" [pkg]="pkg">
<marketplace-additional-item
(click)="presentAlertVersions(version)"
data="Click to view all versions"
label="All versions"
icon="tuiIconChevronRightLarge"
class="item-pointer"
></marketplace-additional-item>
<ng-template #version let-data="data" let-completeWith="completeWith">
<tui-radio-list
size="l"
[items]="data.items"
[itemContent]="displayEmver | tuiStringifyContent"
[(ngModel)]="data.value"
></tui-radio-list>
<footer class="buttons">
<button
tuiButton
appearance="secondary"
(click)="completeWith(null)"
>
Cancel
</button>
<button
tuiButton
appearance="secondary"
(click)="completeWith(data.value)"
>
Ok
</button>
</footer>
</ng-template>
</marketplace-additional>
</div>
</div> </div>
`, `,
styles: [ styles: [
@@ -101,9 +114,9 @@ import { Router } from '@angular/router'
.outer-container { .outer-container {
display: grid; display: grid;
justify-content: center;
gap: 2rem; gap: 2rem;
padding: 1.75rem; padding: 1.75rem;
min-width: 30rem;
} }
.inner-container { .inner-container {
@@ -115,6 +128,18 @@ import { Router } from '@angular/router'
.additional-wrapper { .additional-wrapper {
margin-top: 1.5rem; margin-top: 1.5rem;
} }
.versions {
border: 0;
border-top-width: 1px;
border-bottom-width: 1px;
border-color: rgb(113 113 122);
border-style: solid;
cursor: pointer;
::ng-deep label {
cursor: pointer;
}
}
`, `,
], ],
standalone: true, standalone: true,
@@ -132,20 +157,32 @@ import { Router } from '@angular/router'
TuiStringifyContentPipeModule, TuiStringifyContentPipeModule,
MarketplaceAdditionalItemComponent, MarketplaceAdditionalItemComponent,
TuiRadioListModule, TuiRadioListModule,
TuiLoaderModule,
], ],
}) })
export class MarketplacePreviewComponent { export class MarketplacePreviewComponent {
@Input({ required: true }) @Input({ required: true })
pkg!: MarketplacePkg pkgId!: string
@Output() loading = true
version = new EventEmitter<string>()
readonly displayEmver = displayEmver readonly displayEmver = displayEmver
private readonly router = inject(Router) private readonly router = inject(Router)
readonly url$ = inject(AbstractMarketplaceService) private readonly marketplaceService = inject(AbstractMarketplaceService)
.getSelectedHost$() readonly url =
.pipe(map(({ url }) => url)) this.router.routerState.snapshot.root.queryParamMap.get('url') || undefined
readonly loadVersion$ = new BehaviorSubject<string>('*')
readonly hostInfo$ = this.marketplaceService.getSelectedHost$()
readonly pkg$ = this.loadVersion$.pipe(
switchMap(version =>
this.marketplaceService.getPackage$(this.pkgId, version, this.url),
),
tap(data => {
this.loading = false
return data
}),
)
constructor( constructor(
private readonly dialogs: TuiDialogService, private readonly dialogs: TuiDialogService,
@@ -156,19 +193,27 @@ export class MarketplacePreviewComponent {
this.router.navigate([], { queryParams: { id } }) this.router.navigate([], { queryParams: { id } })
} }
presentAlertVersions(version: TemplateRef<TuiDialogContext>) { constructDetailLink(info: StoreIdentity, id: string) {
const domain = new URL(info.url).hostname
return `https://marketplace.start9.com/${id}?api=${domain}&name=${info.name}`
}
presentAlertVersions(
pkg: MarketplacePkg,
version: TemplateRef<TuiDialogContext>,
) {
this.dialogs this.dialogs
.open<string>(version, { .open<string>(version, {
label: 'Versions', label: 'Versions',
size: 's', size: 's',
data: { data: {
value: this.pkg.manifest.version, value: pkg.manifest.version,
items: [...new Set(this.pkg.versions)].sort( items: [...new Set(pkg.versions)].sort(
(a, b) => -1 * (this.emver.compare(a, b) || 0), (a, b) => -1 * (this.emver.compare(a, b) || 0),
), ),
}, },
}) })
.pipe(filter(Boolean)) .pipe(filter(Boolean))
.subscribe(version => this.version.emit(version)) .subscribe(version => this.loadVersion$.next(version))
} }
} }

View File

@@ -9,12 +9,15 @@ import {
RR, RR,
ServerNotifications, ServerNotifications,
} from './api.types' } from './api.types'
import { BTC_ICON, LND_ICON, PROXY_ICON } from './api-icons'
import { DependencyMetadata, MarketplacePkg } from '@start9labs/marketplace' import { DependencyMetadata, MarketplacePkg } from '@start9labs/marketplace'
import { Log } from '@start9labs/shared' import { Log } from '@start9labs/shared'
import { configBuilderToSpec } from 'src/app/util/configBuilderToSpec' import { configBuilderToSpec } from 'src/app/util/configBuilderToSpec'
import { CT, T, CB } from '@start9labs/start-sdk' import { CT, T, CB } from '@start9labs/start-sdk'
const BTC_ICON = '/assets/img/service-icons/bitcoind.svg'
const LND_ICON = '/assets/img/service-icons/lnd.png'
const PROXY_ICON = '/assets/img/service-icons/btc-rpc-proxy.png'
export module Mock { export module Mock {
export const ServerUpdated: ServerStatusInfo = { export const ServerUpdated: ServerStatusInfo = {
currentBackup: null, currentBackup: null,
@@ -319,8 +322,13 @@ export module Mock {
}, },
} }
export const MarketplacePkgsList: RR.GetMarketplacePackagesRes = export const marketplacePkgsList = (
Object.values(Mock.MarketplacePkgs).map(service => service['latest']) version?: string,
): RR.GetMarketplacePackagesRes => {
return Object.values(Mock.MarketplacePkgs).map(service =>
version ? service[version] : service['latest'],
)
}
export const Notifications: ServerNotifications = [ export const Notifications: ServerNotifications = [
{ {

View File

@@ -462,7 +462,11 @@ export class MockApiService extends ApiService {
} }
return info return info
} else if (path === '/package/v0/index') { } else if (path === '/package/v0/index') {
return Mock.MarketplacePkgsList const version = params['ids']
? (JSON.parse(params['ids']) as { version: string; id: string }[])[0]
.version
: undefined
return Mock.marketplacePkgsList(version)
} else if (path.startsWith('/package/v0/release-notes')) { } else if (path.startsWith('/package/v0/release-notes')) {
return Mock.ReleaseNotes return Mock.ReleaseNotes
} else if (path.includes('instructions') || path.includes('license')) { } else if (path.includes('instructions') || path.includes('license')) {