mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 10:21:52 +00:00
fix preview versions, icons, and misc styling
This commit is contained in:
@@ -1,16 +1,13 @@
|
||||
<div class="item-container box-shadow-lg">
|
||||
<!-- color background -->
|
||||
<div class="background">
|
||||
<img
|
||||
[src]="pkg.icon| trustUrl"
|
||||
alt="{{ pkg.manifest.title }} Icon"
|
||||
/>
|
||||
<img [src]="pkg.icon" alt="{{ pkg.manifest.title }} Icon" />
|
||||
</div>
|
||||
<!-- darkening overlay -->
|
||||
<div class="overlay"></div>
|
||||
<!-- icon -->
|
||||
<img
|
||||
[src]="pkg.icon | trustUrl"
|
||||
[src]="pkg.icon"
|
||||
class="icon box-shadow-lg"
|
||||
alt="{{ pkg.manifest.title }} Icon"
|
||||
/>
|
||||
|
||||
@@ -369,7 +369,7 @@ a {
|
||||
}
|
||||
|
||||
.buttons {
|
||||
margin-top: 0.5rem;
|
||||
margin-top: 1rem;
|
||||
|
||||
:first-child {
|
||||
margin-right: 0.5rem;
|
||||
|
||||
@@ -34,6 +34,8 @@ import { MARKETPLACE_REGISTRY } from '../modals/registry.component'
|
||||
padding: 1.25rem;
|
||||
font-size: 1rem;
|
||||
line-height: 1.5rem;
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
}
|
||||
`,
|
||||
],
|
||||
|
||||
@@ -15,7 +15,6 @@ import { MarketplaceSidebarService } from '../services/sidebar.service'
|
||||
position: fixed;
|
||||
inset: 3.5rem 0 0;
|
||||
pointer-events: none;
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
`,
|
||||
],
|
||||
|
||||
@@ -2,8 +2,8 @@ import { CommonModule } from '@angular/common'
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
Input,
|
||||
inject,
|
||||
Input,
|
||||
} from '@angular/core'
|
||||
import { ActivatedRoute, Router } from '@angular/router'
|
||||
import { ItemModule, MarketplacePkg } from '@start9labs/marketplace'
|
||||
@@ -30,9 +30,8 @@ import { MarketplaceSidebarService } from '../services/sidebar.service'
|
||||
direction: 'right';
|
||||
autoWidth: true
|
||||
"
|
||||
[pkgId]="pkg.manifest.id"
|
||||
class="preview-wrapper"
|
||||
[pkg]="pkg"
|
||||
(tuiActiveZoneChange)="toggle($event)"
|
||||
>
|
||||
<button
|
||||
tuiAutoFocus
|
||||
@@ -88,6 +87,7 @@ import { MarketplaceSidebarService } from '../services/sidebar.service'
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
gap: 0.5rem;
|
||||
height: 4.5rem;
|
||||
}
|
||||
`,
|
||||
],
|
||||
@@ -113,7 +113,6 @@ import { MarketplaceSidebarService } from '../services/sidebar.service'
|
||||
})
|
||||
export class MarketplaceTileComponent {
|
||||
private readonly router = inject(Router)
|
||||
|
||||
readonly id$ = inject(ActivatedRoute).queryParamMap.pipe(
|
||||
map(map => map.get('id') || ''),
|
||||
debounceTime(100),
|
||||
|
||||
@@ -2,10 +2,8 @@ import { CommonModule } from '@angular/common'
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
EventEmitter,
|
||||
inject,
|
||||
Input,
|
||||
Output,
|
||||
TemplateRef,
|
||||
} from '@angular/core'
|
||||
import {
|
||||
@@ -17,11 +15,16 @@ import {
|
||||
MarketplacePackageHeroComponent,
|
||||
MarketplacePkg,
|
||||
ReleaseNotesModule,
|
||||
StoreIdentity,
|
||||
} from '@start9labs/marketplace'
|
||||
import { displayEmver, Emver, SharedPipesModule } from '@start9labs/shared'
|
||||
import { TuiButtonModule } from '@taiga-ui/experimental'
|
||||
import { filter, map } from 'rxjs'
|
||||
import { TuiDialogContext, TuiDialogService } from '@taiga-ui/core'
|
||||
import { BehaviorSubject, filter, switchMap, tap } from 'rxjs'
|
||||
import {
|
||||
TuiDialogContext,
|
||||
TuiDialogService,
|
||||
TuiLoaderModule,
|
||||
} from '@taiga-ui/core'
|
||||
import {
|
||||
TuiRadioListModule,
|
||||
TuiStringifyContentPipeModule,
|
||||
@@ -34,63 +37,73 @@ import { Router } from '@angular/router'
|
||||
template: `
|
||||
<div class="outer-container">
|
||||
<ng-content select="[slot=close]" />
|
||||
<marketplace-package-hero [pkg]="pkg">
|
||||
<ng-content select="[slot=controls]" />
|
||||
</marketplace-package-hero>
|
||||
@if (url$ | async; as url) {
|
||||
<a
|
||||
[href]="url + '/marketplace/' + pkg.manifest.id"
|
||||
tuiButton
|
||||
appearance="tertiary-solid"
|
||||
iconRight="tuiIconExternalLink"
|
||||
target="_blank"
|
||||
>
|
||||
View more details
|
||||
</a>
|
||||
}
|
||||
<div class="inner-container">
|
||||
<marketplace-about [pkg]="pkg" />
|
||||
@if (!(pkg.manifest.dependencies | empty)) {
|
||||
<marketplace-dependencies
|
||||
[pkg]="pkg"
|
||||
(open)="open($event)"
|
||||
></marketplace-dependencies>
|
||||
@if (pkg$ | async; as pkg) {
|
||||
@if (loading) {
|
||||
<tui-loader class="loading-dots" textContent="Loading" />
|
||||
} @else {
|
||||
<marketplace-package-hero [pkg]="pkg">
|
||||
<ng-content select="[slot=controls]" />
|
||||
</marketplace-package-hero>
|
||||
@if (hostInfo$ | async; as info) {
|
||||
<a
|
||||
[href]="constructDetailLink(info, pkg.manifest.id)"
|
||||
tuiButton
|
||||
appearance="tertiary-solid"
|
||||
iconRight="tuiIconExternalLink"
|
||||
target="_blank"
|
||||
>
|
||||
View more details
|
||||
</a>
|
||||
}
|
||||
<div class="inner-container">
|
||||
<marketplace-about [pkg]="pkg" />
|
||||
@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>
|
||||
`,
|
||||
styles: [
|
||||
@@ -101,9 +114,9 @@ import { Router } from '@angular/router'
|
||||
|
||||
.outer-container {
|
||||
display: grid;
|
||||
justify-content: center;
|
||||
gap: 2rem;
|
||||
padding: 1.75rem;
|
||||
min-width: 30rem;
|
||||
}
|
||||
|
||||
.inner-container {
|
||||
@@ -115,6 +128,18 @@ import { Router } from '@angular/router'
|
||||
.additional-wrapper {
|
||||
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,
|
||||
@@ -132,20 +157,32 @@ import { Router } from '@angular/router'
|
||||
TuiStringifyContentPipeModule,
|
||||
MarketplaceAdditionalItemComponent,
|
||||
TuiRadioListModule,
|
||||
TuiLoaderModule,
|
||||
],
|
||||
})
|
||||
export class MarketplacePreviewComponent {
|
||||
@Input({ required: true })
|
||||
pkg!: MarketplacePkg
|
||||
pkgId!: string
|
||||
|
||||
@Output()
|
||||
version = new EventEmitter<string>()
|
||||
loading = true
|
||||
|
||||
readonly displayEmver = displayEmver
|
||||
private readonly router = inject(Router)
|
||||
readonly url$ = inject(AbstractMarketplaceService)
|
||||
.getSelectedHost$()
|
||||
.pipe(map(({ url }) => url))
|
||||
private readonly marketplaceService = inject(AbstractMarketplaceService)
|
||||
readonly 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(
|
||||
private readonly dialogs: TuiDialogService,
|
||||
@@ -156,19 +193,27 @@ export class MarketplacePreviewComponent {
|
||||
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
|
||||
.open<string>(version, {
|
||||
label: 'Versions',
|
||||
size: 's',
|
||||
data: {
|
||||
value: this.pkg.manifest.version,
|
||||
items: [...new Set(this.pkg.versions)].sort(
|
||||
value: pkg.manifest.version,
|
||||
items: [...new Set(pkg.versions)].sort(
|
||||
(a, b) => -1 * (this.emver.compare(a, b) || 0),
|
||||
),
|
||||
},
|
||||
})
|
||||
.pipe(filter(Boolean))
|
||||
.subscribe(version => this.version.emit(version))
|
||||
.subscribe(version => this.loadVersion$.next(version))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,12 +9,15 @@ import {
|
||||
RR,
|
||||
ServerNotifications,
|
||||
} from './api.types'
|
||||
import { BTC_ICON, LND_ICON, PROXY_ICON } from './api-icons'
|
||||
import { DependencyMetadata, MarketplacePkg } from '@start9labs/marketplace'
|
||||
import { Log } from '@start9labs/shared'
|
||||
import { configBuilderToSpec } from 'src/app/util/configBuilderToSpec'
|
||||
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 const ServerUpdated: ServerStatusInfo = {
|
||||
currentBackup: null,
|
||||
@@ -319,8 +322,13 @@ export module Mock {
|
||||
},
|
||||
}
|
||||
|
||||
export const MarketplacePkgsList: RR.GetMarketplacePackagesRes =
|
||||
Object.values(Mock.MarketplacePkgs).map(service => service['latest'])
|
||||
export const marketplacePkgsList = (
|
||||
version?: string,
|
||||
): RR.GetMarketplacePackagesRes => {
|
||||
return Object.values(Mock.MarketplacePkgs).map(service =>
|
||||
version ? service[version] : service['latest'],
|
||||
)
|
||||
}
|
||||
|
||||
export const Notifications: ServerNotifications = [
|
||||
{
|
||||
|
||||
@@ -462,7 +462,11 @@ export class MockApiService extends ApiService {
|
||||
}
|
||||
return info
|
||||
} 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')) {
|
||||
return Mock.ReleaseNotes
|
||||
} else if (path.includes('instructions') || path.includes('license')) {
|
||||
|
||||
Reference in New Issue
Block a user