mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 20:14:49 +00:00
port 040 config (#2657)
* port 040 config, WIP * update fixtures * use taiga modal for backups too * fix: update Taiga UI and refactor everything to work * chore: package-lock * fix interfaces and mocks for interfaces * better mocks * function to transform old spec to new * delete unused fns * delete unused FE config utils * fix exports from sdk * reorganize exports * functions to translate config * rename unionSelectKey and unionValueKey * Adding in the transformation of the getConfig to the new types. * chore: add Taiga UI to preloader --------- Co-authored-by: waterplea <alexander@inkin.ru> Co-authored-by: Aiden McClelland <me@drbonez.dev> Co-authored-by: J H <dragondef@gmail.com>
This commit is contained in:
@@ -1,17 +0,0 @@
|
||||
import { NgModule } from '@angular/core'
|
||||
import { CommonModule } from '@angular/common'
|
||||
import { IonicModule } from '@ionic/angular'
|
||||
import { MarketplaceSettingsPage } from './marketplace-settings.page'
|
||||
import { SharedPipesModule } from '@start9labs/shared'
|
||||
import { StoreIconComponentModule } from 'src/app/components/store-icon/store-icon.component.module'
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
IonicModule,
|
||||
SharedPipesModule,
|
||||
StoreIconComponentModule,
|
||||
],
|
||||
declarations: [MarketplaceSettingsPage],
|
||||
})
|
||||
export class MarketplaceSettingsPageModule {}
|
||||
@@ -1,67 +1,30 @@
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Change Registry</ion-title>
|
||||
<ion-buttons slot="end">
|
||||
<ion-button (click)="dismiss()">
|
||||
<ion-icon slot="icon-only" name="close"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content class="ion-padding-top">
|
||||
<ion-item-group *ngIf="stores$ | async as stores">
|
||||
<ion-item-divider>Default Registries</ion-item-divider>
|
||||
<ion-item
|
||||
*ngFor="let s of stores.standard"
|
||||
detail="false"
|
||||
[button]="!s.selected"
|
||||
(click)="s.selected ? '' : presentAction(s)"
|
||||
<ng-container *ngIf="stores$ | async as stores">
|
||||
<h3 class="g-title">Default Registries</h3>
|
||||
<button
|
||||
*ngFor="let registry of stores.standard"
|
||||
tuiCell
|
||||
[disabled]="registry.selected"
|
||||
[registry]="registry"
|
||||
(click)="connect(registry.url)"
|
||||
></button>
|
||||
<h3 class="g-title">Custom Registries</h3>
|
||||
<button tuiCell (click)="add()" [style.width]="'-webkit-fill-available'">
|
||||
<tui-icon icon="tuiIconPlus" [style.margin-inline.rem]="'0.5'"></tui-icon>
|
||||
<div tuiTitle>Add custom registry</div>
|
||||
</button>
|
||||
<div *ngFor="let registry of stores.alt" class="connect-container">
|
||||
<button
|
||||
tuiCell
|
||||
[registry]="registry"
|
||||
(click)="connect(registry.url)"
|
||||
></button>
|
||||
<button
|
||||
tuiIconButton
|
||||
appearance="icon"
|
||||
iconLeft="tuiIconTrash"
|
||||
(click)="delete(registry.url, registry.name)"
|
||||
>
|
||||
<ion-avatar slot="start">
|
||||
<store-icon [url]="s.url"></store-icon>
|
||||
</ion-avatar>
|
||||
<ion-label>
|
||||
<h2>{{ s.name }}</h2>
|
||||
<p>{{ s.url }}</p>
|
||||
</ion-label>
|
||||
<ion-icon
|
||||
*ngIf="s.selected"
|
||||
slot="end"
|
||||
size="large"
|
||||
name="checkmark"
|
||||
color="success"
|
||||
></ion-icon>
|
||||
</ion-item>
|
||||
|
||||
<ion-item-divider>Custom Registries</ion-item-divider>
|
||||
<ion-item button detail="false" (click)="presentModalAdd()">
|
||||
<ion-icon slot="start" name="add" color="dark"></ion-icon>
|
||||
<ion-label>
|
||||
<ion-text color="dark">
|
||||
<b>Add custom registry</b>
|
||||
</ion-text>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item
|
||||
*ngFor="let a of stores.alt"
|
||||
detail="false"
|
||||
[button]="!a.selected"
|
||||
(click)="a.selected ? '' : presentAction(a, true)"
|
||||
>
|
||||
<store-icon slot="start" [url]="a.url" size="36px"></store-icon>
|
||||
<ion-label>
|
||||
<h2>{{ a.name }}</h2>
|
||||
<p>{{ a.url }}</p>
|
||||
</ion-label>
|
||||
<ion-icon
|
||||
*ngIf="a.selected"
|
||||
slot="end"
|
||||
size="large"
|
||||
name="checkmark"
|
||||
color="success"
|
||||
></ion-icon>
|
||||
</ion-item>
|
||||
</ion-item-group>
|
||||
</ion-content>
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
.connect-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@@ -1,276 +1,230 @@
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
Inject,
|
||||
ViewChild,
|
||||
} from '@angular/core'
|
||||
import {
|
||||
ActionSheetController,
|
||||
AlertController,
|
||||
LoadingController,
|
||||
ModalController,
|
||||
} from '@ionic/angular'
|
||||
import { ActionSheetButton } from '@ionic/core'
|
||||
import { ErrorToastService, sameUrl, toUrl } from '@start9labs/shared'
|
||||
import { CommonModule } from '@angular/common'
|
||||
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
|
||||
import { AbstractMarketplaceService } from '@start9labs/marketplace'
|
||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||
import { ValueSpecObject } from 'src/app/pkg-config/config-types'
|
||||
import { GenericFormPage } from 'src/app/modals/generic-form/generic-form.page'
|
||||
import {
|
||||
ErrorService,
|
||||
LoadingService,
|
||||
sameUrl,
|
||||
toUrl,
|
||||
} from '@start9labs/shared'
|
||||
import { CT } from '@start9labs/start-sdk'
|
||||
import { TuiDialogOptions, TuiDialogService } from '@taiga-ui/core'
|
||||
import {
|
||||
TuiButtonModule,
|
||||
TuiCellModule,
|
||||
TuiIconModule,
|
||||
TuiTitleModule,
|
||||
} from '@taiga-ui/experimental'
|
||||
import { TUI_PROMPT, TuiPromptData } from '@taiga-ui/kit'
|
||||
import { PolymorpheusComponent } from '@tinkoff/ng-polymorpheus'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import { DataModel, UIStore } from 'src/app/services/patch-db/data-model'
|
||||
import { MarketplaceService } from 'src/app/services/marketplace.service'
|
||||
import { combineLatest, filter, firstValueFrom, Subscription } from 'rxjs'
|
||||
import { map } from 'rxjs/operators'
|
||||
import { combineLatest, firstValueFrom } from 'rxjs'
|
||||
import { FormComponent } from 'src/app/components/form.component'
|
||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||
import { FormDialogService } from 'src/app/services/form-dialog.service'
|
||||
import { MarketplaceService } from 'src/app/services/marketplace.service'
|
||||
import { DataModel, UIStore } from 'src/app/services/patch-db/data-model'
|
||||
|
||||
import { MarketplaceRegistryComponent } from './registry.component'
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
imports: [
|
||||
CommonModule,
|
||||
TuiCellModule,
|
||||
TuiIconModule,
|
||||
TuiTitleModule,
|
||||
TuiButtonModule,
|
||||
MarketplaceRegistryComponent,
|
||||
],
|
||||
selector: 'marketplace-settings',
|
||||
templateUrl: 'marketplace-settings.page.html',
|
||||
styleUrls: ['marketplace-settings.page.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class MarketplaceSettingsPage {
|
||||
stores$ = combineLatest([
|
||||
this.marketplaceService.getKnownHosts$(),
|
||||
this.marketplaceService.getSelectedHost$(),
|
||||
]).pipe(
|
||||
map(([stores, selected]) => {
|
||||
const toSlice = stores.map(s => ({
|
||||
...s,
|
||||
selected: sameUrl(s.url, selected.url),
|
||||
}))
|
||||
// 0 and 1 are prod and community
|
||||
const standard = toSlice.slice(0, 2)
|
||||
// 2 and beyond are alts
|
||||
const alt = toSlice.slice(2)
|
||||
|
||||
return { standard, alt }
|
||||
}),
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly loader = inject(LoadingService)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
private readonly formDialog = inject(FormDialogService)
|
||||
private readonly dialogs = inject(TuiDialogService)
|
||||
private readonly marketplace = inject(
|
||||
AbstractMarketplaceService,
|
||||
) as MarketplaceService
|
||||
private readonly hosts$ = inject(PatchDB<DataModel>).watch$(
|
||||
'ui',
|
||||
'marketplace',
|
||||
'knownHosts',
|
||||
)
|
||||
|
||||
constructor(
|
||||
private readonly api: ApiService,
|
||||
private readonly loadingCtrl: LoadingController,
|
||||
private readonly modalCtrl: ModalController,
|
||||
private readonly errToast: ErrorToastService,
|
||||
private readonly actionCtrl: ActionSheetController,
|
||||
@Inject(AbstractMarketplaceService)
|
||||
private readonly marketplaceService: MarketplaceService,
|
||||
private readonly patch: PatchDB<DataModel>,
|
||||
private readonly alertCtrl: AlertController,
|
||||
) {}
|
||||
readonly stores$ = combineLatest([
|
||||
this.marketplace.getKnownHosts$(),
|
||||
this.marketplace.getSelectedHost$(),
|
||||
]).pipe(
|
||||
map(([stores, selected]) =>
|
||||
stores.map(s => ({
|
||||
...s,
|
||||
selected: sameUrl(s.url, selected.url),
|
||||
})),
|
||||
),
|
||||
// 0 and 1 are prod and community, 2 and beyond are alts
|
||||
map(stores => ({ standard: stores.slice(0, 2), alt: stores.slice(2) })),
|
||||
)
|
||||
|
||||
async dismiss() {
|
||||
this.modalCtrl.dismiss()
|
||||
}
|
||||
|
||||
async presentModalAdd() {
|
||||
async add() {
|
||||
const { name, spec } = getMarketplaceValueSpec()
|
||||
const modal = await this.modalCtrl.create({
|
||||
component: GenericFormPage,
|
||||
componentProps: {
|
||||
title: name,
|
||||
|
||||
this.formDialog.open(FormComponent, {
|
||||
label: name,
|
||||
data: {
|
||||
spec,
|
||||
buttons: [
|
||||
{
|
||||
text: 'Save for Later',
|
||||
handler: (value: { url: string }) => {
|
||||
this.saveOnly(value.url)
|
||||
},
|
||||
handler: async ({ url }: { url: string }) => this.save(url),
|
||||
},
|
||||
{
|
||||
text: 'Save and Connect',
|
||||
handler: (value: { url: string }) => {
|
||||
this.saveAndConnect(value.url)
|
||||
},
|
||||
handler: async ({ url }: { url: string }) => this.save(url, true),
|
||||
isSubmit: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
cssClass: 'alertlike-modal',
|
||||
})
|
||||
|
||||
await modal.present()
|
||||
}
|
||||
delete(url: string, name: string = '') {
|
||||
this.dialogs
|
||||
.open(TUI_PROMPT, getPromptOptions(name))
|
||||
.pipe(filter(Boolean))
|
||||
.subscribe(async () => {
|
||||
const loader = this.loader.open('Deleting...').subscribe()
|
||||
const hosts = await firstValueFrom(this.hosts$)
|
||||
const filtered: { [url: string]: UIStore } = Object.keys(hosts)
|
||||
.filter(key => !sameUrl(key, url))
|
||||
.reduce(
|
||||
(prev, curr) => ({
|
||||
...prev,
|
||||
[curr]: hosts[curr],
|
||||
}),
|
||||
{},
|
||||
)
|
||||
|
||||
async presentAction(
|
||||
{ url, name }: { url: string; name?: string },
|
||||
canDelete = false,
|
||||
) {
|
||||
const buttons: ActionSheetButton[] = [
|
||||
{
|
||||
text: 'Connect',
|
||||
handler: () => {
|
||||
this.connect(url)
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
if (canDelete) {
|
||||
buttons.unshift({
|
||||
text: 'Delete',
|
||||
role: 'destructive',
|
||||
handler: () => {
|
||||
this.presentAlertDelete(url, name!)
|
||||
},
|
||||
try {
|
||||
await this.api.setDbValue(['marketplace', 'knownHosts'], filtered)
|
||||
} catch (e: any) {
|
||||
this.errorService.handleError(e)
|
||||
} finally {
|
||||
loader.unsubscribe()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const action = await this.actionCtrl.create({
|
||||
header: name,
|
||||
mode: 'ios',
|
||||
buttons,
|
||||
})
|
||||
|
||||
await action.present()
|
||||
}
|
||||
|
||||
private async presentAlertDelete(url: string, name: string) {
|
||||
const alert = await this.alertCtrl.create({
|
||||
header: 'Confirm',
|
||||
message: `Are you sure you want to delete ${name}?`,
|
||||
buttons: [
|
||||
{
|
||||
text: 'Cancel',
|
||||
role: 'cancel',
|
||||
},
|
||||
{
|
||||
text: 'Delete',
|
||||
handler: () => this.delete(url),
|
||||
cssClass: 'enter-click',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
await alert.present()
|
||||
}
|
||||
|
||||
private async connect(
|
||||
async connect(
|
||||
url: string,
|
||||
loader?: HTMLIonLoadingElement,
|
||||
loader: Subscription = new Subscription(),
|
||||
): Promise<void> {
|
||||
const message = 'Changing Registry...'
|
||||
if (!loader) {
|
||||
loader = await this.loadingCtrl.create({ message })
|
||||
await loader.present()
|
||||
} else {
|
||||
loader.message = message
|
||||
}
|
||||
loader.unsubscribe()
|
||||
loader.closed = false
|
||||
loader.add(this.loader.open('Changing Registry...').subscribe())
|
||||
|
||||
try {
|
||||
await this.api.setDbValue<string>(['marketplace', 'selected-url'], url)
|
||||
await this.api.setDbValue<string>(['marketplace', 'selectedUrl'], url)
|
||||
} catch (e: any) {
|
||||
this.errToast.present(e)
|
||||
this.errorService.handleError(e)
|
||||
} finally {
|
||||
loader.dismiss()
|
||||
this.dismiss()
|
||||
loader.unsubscribe()
|
||||
}
|
||||
}
|
||||
|
||||
private async saveOnly(rawUrl: string): Promise<void> {
|
||||
const loader = await this.loadingCtrl.create()
|
||||
private async save(rawUrl: string, connect = false): Promise<boolean> {
|
||||
const loader = this.loader.open('Loading').subscribe()
|
||||
const url = new URL(rawUrl).toString()
|
||||
|
||||
try {
|
||||
const url = new URL(rawUrl).toString()
|
||||
await this.validateAndSave(url, loader)
|
||||
if (connect) await this.connect(url, loader)
|
||||
return true
|
||||
} catch (e: any) {
|
||||
this.errToast.present(e)
|
||||
this.errorService.handleError(e)
|
||||
return false
|
||||
} finally {
|
||||
loader.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
private async saveAndConnect(rawUrl: string): Promise<void> {
|
||||
const loader = await this.loadingCtrl.create()
|
||||
|
||||
try {
|
||||
const url = new URL(rawUrl).toString()
|
||||
await this.validateAndSave(url, loader)
|
||||
await this.connect(url, loader)
|
||||
} catch (e: any) {
|
||||
this.errToast.present(e)
|
||||
} finally {
|
||||
loader.dismiss()
|
||||
this.dismiss()
|
||||
loader.unsubscribe()
|
||||
}
|
||||
}
|
||||
|
||||
private async validateAndSave(
|
||||
url: string,
|
||||
loader: HTMLIonLoadingElement,
|
||||
loader: Subscription,
|
||||
): Promise<void> {
|
||||
// Error on duplicates
|
||||
const hosts = await firstValueFrom(
|
||||
this.patch.watch$('ui', 'marketplace', 'knownHosts'),
|
||||
)
|
||||
const hosts = await firstValueFrom(this.hosts$)
|
||||
const currentUrls = Object.keys(hosts).map(toUrl)
|
||||
if (currentUrls.includes(url)) throw new Error('marketplace already added')
|
||||
if (currentUrls.includes(url)) throw new Error('Marketplace already added')
|
||||
|
||||
// Validate
|
||||
loader.message = 'Validating marketplace...'
|
||||
await loader.present()
|
||||
loader.unsubscribe()
|
||||
loader.closed = false
|
||||
loader.add(this.loader.open('Validating marketplace...').subscribe())
|
||||
|
||||
const { name } = await firstValueFrom(
|
||||
this.marketplaceService.fetchInfo$(url),
|
||||
)
|
||||
const { name } = await firstValueFrom(this.marketplace.fetchInfo$(url))
|
||||
|
||||
// Save
|
||||
loader.message = 'Saving...'
|
||||
loader.unsubscribe()
|
||||
loader.closed = false
|
||||
loader.add(this.loader.open('Saving...').subscribe())
|
||||
|
||||
await this.api.setDbValue<{ name: string }>(
|
||||
['marketplace', 'knownHosts', url],
|
||||
{ name },
|
||||
)
|
||||
}
|
||||
|
||||
private async delete(url: string): Promise<void> {
|
||||
const loader = await this.loadingCtrl.create({
|
||||
message: 'Deleting...',
|
||||
})
|
||||
await loader.present()
|
||||
|
||||
const hosts = await firstValueFrom(
|
||||
this.patch.watch$('ui', 'marketplace', 'knownHosts'),
|
||||
)
|
||||
|
||||
const filtered: { [url: string]: UIStore } = Object.keys(hosts)
|
||||
.filter(key => !sameUrl(key, url))
|
||||
.reduce((prev, curr) => {
|
||||
const name = hosts[curr]
|
||||
return {
|
||||
...prev,
|
||||
[curr]: name,
|
||||
}
|
||||
}, {})
|
||||
|
||||
try {
|
||||
await this.api.setDbValue<{ [url: string]: UIStore }>(
|
||||
['marketplace', 'knownHosts'],
|
||||
filtered,
|
||||
)
|
||||
} catch (e: any) {
|
||||
this.errToast.present(e)
|
||||
} finally {
|
||||
loader.dismiss()
|
||||
}
|
||||
await this.api.setDbValue(['marketplace', 'knownHosts', url], { name })
|
||||
}
|
||||
}
|
||||
|
||||
function getMarketplaceValueSpec(): ValueSpecObject {
|
||||
export const MARKETPLACE_REGISTRY = new PolymorpheusComponent(
|
||||
MarketplaceSettingsPage,
|
||||
)
|
||||
|
||||
function getMarketplaceValueSpec(): CT.ValueSpecObject {
|
||||
return {
|
||||
type: 'object',
|
||||
name: 'Add Custom Registry',
|
||||
description: null,
|
||||
warning: null,
|
||||
spec: {
|
||||
url: {
|
||||
type: 'string',
|
||||
type: 'text',
|
||||
name: 'URL',
|
||||
description: 'A fully-qualified URL of the custom registry',
|
||||
nullable: false,
|
||||
inputmode: 'url',
|
||||
required: true,
|
||||
masked: false,
|
||||
copyable: false,
|
||||
pattern: `https?:\/\/[a-zA-Z0-9][a-zA-Z0-9-\.]+[a-zA-Z0-9]\.[^\s]{2,}`,
|
||||
'pattern-description': 'Must be a valid URL',
|
||||
minLength: null,
|
||||
maxLength: null,
|
||||
patterns: [
|
||||
{
|
||||
regex: `https?:\/\/[a-zA-Z0-9][a-zA-Z0-9-\.]+[a-zA-Z0-9]\.[^\s]{2,}`,
|
||||
description: 'Must be a valid URL',
|
||||
},
|
||||
],
|
||||
placeholder: 'e.g. https://example.org',
|
||||
default: null,
|
||||
warning: null,
|
||||
disabled: false,
|
||||
immutable: false,
|
||||
generate: null,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function getPromptOptions(
|
||||
name: string,
|
||||
): Partial<TuiDialogOptions<TuiPromptData>> {
|
||||
return {
|
||||
label: 'Confirm',
|
||||
size: 's',
|
||||
data: {
|
||||
content: `Are you sure you want to delete ${name}?`,
|
||||
yes: 'Delete',
|
||||
no: 'Cancel',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import { NgIf } from '@angular/common'
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
inject,
|
||||
Input,
|
||||
} from '@angular/core'
|
||||
import { TuiIconModule, TuiTitleModule } from '@taiga-ui/experimental'
|
||||
import { ConfigService } from 'src/app/services/config.service'
|
||||
|
||||
import { StoreIconComponent } from './store-icon.component'
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: '[registry]',
|
||||
template: `
|
||||
<store-icon
|
||||
[url]="registry.url"
|
||||
[marketplace]="marketplace"
|
||||
size="40px"
|
||||
></store-icon>
|
||||
<div tuiTitle>
|
||||
{{ registry.name }}
|
||||
<div tuiSubtitle>{{ registry.url }}</div>
|
||||
</div>
|
||||
<tui-icon
|
||||
*ngIf="registry.selected; else content"
|
||||
icon="tuiIconCheck"
|
||||
[style.color]="'var(--tui-positive)'"
|
||||
></tui-icon>
|
||||
<ng-template #content><ng-content></ng-content></ng-template>
|
||||
`,
|
||||
styles: [':host { border-radius: 0.25rem; width: stretch; }'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [NgIf, StoreIconComponent, TuiIconModule, TuiTitleModule],
|
||||
})
|
||||
export class MarketplaceRegistryComponent {
|
||||
readonly marketplace = inject(ConfigService).marketplace
|
||||
|
||||
@Input()
|
||||
registry!: { url: string; selected: boolean; name?: string }
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import { NgIf } from '@angular/common'
|
||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
|
||||
import { sameUrl } from '@start9labs/shared'
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: 'store-icon',
|
||||
template: `
|
||||
<img
|
||||
*ngIf="icon; else noIcon"
|
||||
[style.border-radius.%]="100"
|
||||
[style.max-width]="size || '100%'"
|
||||
[src]="icon"
|
||||
alt="Marketplace Icon"
|
||||
/>
|
||||
<ng-template #noIcon>
|
||||
<img
|
||||
[style.max-width]="size || '100%'"
|
||||
[style.border-radius]="0"
|
||||
src="assets/img/storefront-outline.png"
|
||||
alt="Marketplace Icon"
|
||||
/>
|
||||
</ng-template>
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [NgIf],
|
||||
})
|
||||
export class StoreIconComponent {
|
||||
@Input()
|
||||
url = ''
|
||||
@Input()
|
||||
size?: string
|
||||
@Input()
|
||||
marketplace!: any
|
||||
|
||||
get icon() {
|
||||
const { start9, community } = this.marketplace
|
||||
|
||||
if (sameUrl(this.url, start9)) {
|
||||
return 'assets/img/icon_transparent.png'
|
||||
} else if (sameUrl(this.url, community)) {
|
||||
return 'assets/img/community-store.png'
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user