Merge pull request #2626 from Start9Labs/comments

chore: address comments
This commit is contained in:
Matt Hill
2024-05-21 15:04:13 -06:00
committed by GitHub
19 changed files with 215 additions and 147 deletions

View File

@@ -139,6 +139,10 @@
&:active { &:active {
background: transparent !important; background: transparent !important;
} }
tui-root._mobile &:after {
display: none;
}
} }
tui-dialog { tui-dialog {

View File

@@ -9,13 +9,10 @@ import {
} from '@taiga-ui/core' } from '@taiga-ui/core'
import { TuiButtonModule, TuiIconModule } from '@taiga-ui/experimental' import { TuiButtonModule, TuiIconModule } from '@taiga-ui/experimental'
import { TUI_PROMPT, TuiPromptData } from '@taiga-ui/kit' import { TUI_PROMPT, TuiPromptData } from '@taiga-ui/kit'
import { PatchDB } from 'patch-db-client'
import { filter } from 'rxjs' import { filter } from 'rxjs'
import { ApiService } from 'src/app/services/api/embassy-api.service' import { ApiService } from 'src/app/services/api/embassy-api.service'
import { AuthService } from 'src/app/services/auth.service' import { AuthService } from 'src/app/services/auth.service'
import { ABOUT } from './about.component' import { ABOUT } from './about.component'
import { getAllPackages } from 'src/app/utils/get-package-data'
import { DataModel } from 'src/app/services/patch-db/data-model'
import { HeaderConnectionComponent } from './connection.component' import { HeaderConnectionComponent } from './connection.component'
@Component({ @Component({
@@ -114,7 +111,6 @@ export class HeaderMenuComponent {
private readonly errorService = inject(ErrorService) private readonly errorService = inject(ErrorService)
private readonly loader = inject(LoadingService) private readonly loader = inject(LoadingService)
private readonly auth = inject(AuthService) private readonly auth = inject(AuthService)
private readonly patch = inject(PatchDB<DataModel>)
private readonly dialogs = inject(TuiDialogService) private readonly dialogs = inject(TuiDialogService)
readonly links = [ readonly links = [
@@ -136,10 +132,6 @@ export class HeaderMenuComponent {
] ]
readonly system = [ readonly system = [
{
icon: 'tuiIconTool',
action: 'System Rebuild',
},
{ {
icon: 'tuiIconRefreshCw', icon: 'tuiIconRefreshCw',
action: 'Restart', action: 'Restart',
@@ -159,20 +151,17 @@ export class HeaderMenuComponent {
this.auth.setUnverified() this.auth.setUnverified()
} }
async prompt(action: keyof typeof METHODS) { async prompt(action: 'Restart' | 'Shutdown') {
const minutes =
action === 'System Rebuild'
? Object.keys(await getAllPackages(this.patch)).length * 2
: ''
this.dialogs this.dialogs
.open(TUI_PROMPT, getOptions(action, minutes)) .open(TUI_PROMPT, getOptions(action))
.pipe(filter(Boolean)) .pipe(filter(Boolean))
.subscribe(async () => { .subscribe(async () => {
const loader = this.loader.open(`Beginning ${action}...`).subscribe() const loader = this.loader.open(`Beginning ${action}...`).subscribe()
try { try {
await this.api[METHODS[action]]({}) await this.api[
action === 'Restart' ? 'restartServer' : 'shutdownServer'
]({})
} catch (e: any) { } catch (e: any) {
this.errorService.handleError(e) this.errorService.handleError(e)
} finally { } finally {
@@ -182,19 +171,11 @@ export class HeaderMenuComponent {
} }
} }
const METHODS = {
Restart: 'restartServer',
Shutdown: 'shutdownServer',
'System Rebuild': 'systemRebuild',
} as const
function getOptions( function getOptions(
key: keyof typeof METHODS, operation: 'Restart' | 'Shutdown',
minutes: unknown,
): Partial<TuiDialogOptions<TuiPromptData>> { ): Partial<TuiDialogOptions<TuiPromptData>> {
switch (key) { return operation === 'Restart'
case 'Restart': ? {
return {
label: 'Restart', label: 'Restart',
size: 's', size: 's',
data: { data: {
@@ -204,8 +185,7 @@ function getOptions(
no: 'Cancel', no: 'Cancel',
}, },
} }
case 'Shutdown': : {
return {
label: 'Warning', label: 'Warning',
size: 's', size: 's',
data: { data: {
@@ -215,15 +195,4 @@ function getOptions(
no: 'Cancel', no: 'Cancel',
}, },
} }
default:
return {
label: 'Warning',
size: 's',
data: {
content: `This action will tear down all service containers and rebuild them from scratch. No data will be deleted. This action is useful if your system gets into a bad state, and it should only be performed if you are experiencing general performance or reliability issues. It may take up to ${minutes} minutes to complete. During this time, you will lose all connectivity to your server.`,
yes: 'Rebuild',
no: 'Cancel',
},
}
}
} }

View File

@@ -1,5 +1,11 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core' import {
ChangeDetectionStrategy,
Component,
inject,
Input,
} from '@angular/core'
import { RouterLink } from '@angular/router' import { RouterLink } from '@angular/router'
import { WINDOW } from '@ng-web-apis/common'
import { TuiIconModule } from '@taiga-ui/experimental' import { TuiIconModule } from '@taiga-ui/experimental'
import { Breadcrumb } from 'src/app/services/breadcrumbs.service' import { Breadcrumb } from 'src/app/services/breadcrumbs.service'
@@ -7,8 +13,12 @@ import { Breadcrumb } from 'src/app/services/breadcrumbs.service'
standalone: true, standalone: true,
selector: '[headerMobile]', selector: '[headerMobile]',
template: ` template: `
@if (headerMobile?.length) { @if (headerMobile && headerMobile.length > 1) {
<a [routerLink]="back" [style.padding.rem]="0.75"> <a
[routerLink]="back"
[style.padding.rem]="0.75"
[queryParams]="queryParams"
>
<tui-icon icon="tuiIconArrowLeft" /> <tui-icon icon="tuiIconArrowLeft" />
</a> </a>
} }
@@ -46,6 +56,11 @@ import { Breadcrumb } from 'src/app/services/breadcrumbs.service'
.title { .title {
@include text-overflow(); @include text-overflow();
max-width: calc(100% - 5rem); max-width: calc(100% - 5rem);
text-transform: capitalize;
&:first-child {
margin-inline-start: 1rem;
}
} }
`, `,
], ],
@@ -53,10 +68,15 @@ import { Breadcrumb } from 'src/app/services/breadcrumbs.service'
imports: [TuiIconModule, RouterLink], imports: [TuiIconModule, RouterLink],
}) })
export class HeaderMobileComponent { export class HeaderMobileComponent {
private readonly win = inject(WINDOW)
@Input() headerMobile: readonly Breadcrumb[] | null = [] @Input() headerMobile: readonly Breadcrumb[] | null = []
get title() { get title() {
return this.headerMobile?.[this.headerMobile?.length - 1]?.title || '' return (
this.headerMobile?.[this.headerMobile?.length - 1]?.title ||
(this.win.location.search ? 'Utilities' : 'Services')
)
} }
get back() { get back() {
@@ -65,4 +85,8 @@ export class HeaderMobileComponent {
'/portal/dashboard' '/portal/dashboard'
) )
} }
get queryParams() {
return this.back === '/portal/dashboard' ? { tab: 'utilities' } : null
}
} }

View File

@@ -24,10 +24,8 @@ import { NotificationService } from 'src/app/services/notification.service'
<a <a
tuiTabBarItem tuiTabBarItem
icon="tuiIconActivity" icon="tuiIconActivity"
routerLink="/portal/dashboard" routerLink="/portal/system/metrics"
routerLinkActive routerLinkActive
[routerLinkActiveOptions]="{ exact: true }"
[queryParams]="{ tab: 'metrics' }"
> >
Metrics Metrics
</a> </a>
@@ -58,7 +56,9 @@ import { NotificationService } from 'src/app/services/notification.service'
display: none; display: none;
// TODO: Theme // TODO: Theme
--tui-elevation-01: #333; --tui-elevation-01: #333;
--tui-base-01: #fff;
--tui-base-04: var(--tui-clear); --tui-base-04: var(--tui-clear);
--tui-error-fill: #f52222;
backdrop-filter: blur(1rem); backdrop-filter: blur(1rem);
} }

View File

@@ -67,6 +67,7 @@ import { getManifest } from 'src/app/utils/get-package-data'
:host { :host {
padding: 0; padding: 0;
border: none; border: none;
cursor: default;
} }
:host-context(tui-root._mobile) { :host-context(tui-root._mobile) {

View File

@@ -176,7 +176,8 @@ import { TimeService } from 'src/app/services/time.service'
section { section {
flex-wrap: wrap; flex-wrap: wrap;
padding: 1rem; padding: 0;
margin: 1rem -1rem;
} }
aside { aside {

View File

@@ -4,6 +4,7 @@ import {
Component, Component,
inject, inject,
Input, Input,
OnChanges,
} from '@angular/core' } from '@angular/core'
import { RouterLink } from '@angular/router' import { RouterLink } from '@angular/router'
import { tuiPure } from '@taiga-ui/cdk' import { tuiPure } from '@taiga-ui/cdk'
@@ -19,7 +20,7 @@ import { getManifest } from 'src/app/utils/get-package-data'
selector: 'tr[appService]', selector: 'tr[appService]',
template: ` template: `
<td [style.grid-area]="'1 / 1 / 4'"> <td [style.grid-area]="'1 / 1 / 4'">
<a [routerLink]="routerLink"><img alt="logo" [src]="pkg.icon" /></a> <img alt="logo" [src]="pkg.icon" />
</td> </td>
<td [style.grid-area]="'1 / 2'"> <td [style.grid-area]="'1 / 2'">
<a [routerLink]="routerLink">{{ manifest.title }}</a> <a [routerLink]="routerLink">{{ manifest.title }}</a>
@@ -36,11 +37,25 @@ import { getManifest } from 'src/app/utils/get-package-data'
appControls appControls
[disabled]="!installed || !(connected$ | async)" [disabled]="!installed || !(connected$ | async)"
[pkg]="pkg" [pkg]="pkg"
(click.stop)="(0)"
></fieldset> ></fieldset>
</td> </td>
`, `,
styles: ` styles: `
@import '@taiga-ui/core/styles/taiga-ui-local';
:host {
@include transition(background);
clip-path: inset(0 round 0.5rem);
cursor: pointer;
&:hover {
background: var(--tui-clear);
}
}
img { img {
display: block;
height: 2rem; height: 2rem;
width: 2rem; width: 2rem;
border-radius: 100%; border-radius: 100%;
@@ -80,10 +95,13 @@ import { getManifest } from 'src/app/utils/get-package-data'
} }
} }
`, `,
hostDirectives: [RouterLink],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
imports: [RouterLink, AsyncPipe, StatusComponent, ControlsComponent], imports: [RouterLink, AsyncPipe, StatusComponent, ControlsComponent],
}) })
export class ServiceComponent { export class ServiceComponent implements OnChanges {
private readonly link = inject(RouterLink)
@Input() @Input()
pkg!: PackageDataEntry pkg!: PackageDataEntry
@@ -104,6 +122,10 @@ export class ServiceComponent {
return `/portal/service/${this.manifest.id}` return `/portal/service/${this.manifest.id}`
} }
ngOnChanges() {
this.link.routerLink = this.routerLink
}
@tuiPure @tuiPure
hasError(errors: PkgDependencyErrors = {}): boolean { hasError(errors: PkgDependencyErrors = {}): boolean {
return Object.values(errors).some(Boolean) return Object.values(errors).some(Boolean)

View File

@@ -19,9 +19,7 @@ import { DepErrorService } from 'src/app/services/dep-error.service'
<th>Name</th> <th>Name</th>
<th>Version</th> <th>Version</th>
<th [style.width.rem]="13">Status</th> <th [style.width.rem]="13">Status</th>
<th [style.width.rem]="8" [style.text-align]="'center'"> <th [style.width.rem]="8" [style.text-indent.rem]="1">Controls</th>
Controls
</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>

View File

@@ -9,8 +9,9 @@ import { LogsComponent } from '../../../components/logs/logs.component'
@Component({ @Component({
template: ` template: `
<tui-select <tui-select
tuiTextfieldAppearance="unstyled" tuiTextfieldAppearance="secondary"
tuiTextfieldSize="m" tuiTextfieldSize="m"
[style.max-width.rem]="26"
[(ngModel)]="logs" [(ngModel)]="logs"
> >
{{ subtitle }} {{ subtitle }}
@@ -50,7 +51,7 @@ import { LogsComponent } from '../../../components/logs/logs.component'
} }
logs { logs {
height: calc(100% - 4rem); height: calc(100% - 5rem);
} }
`, `,
], ],

View File

@@ -0,0 +1,17 @@
import { AsyncPipe } from '@angular/common'
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
import { MetricsComponent } from 'src/app/routes/portal/routes/dashboard/metrics.component'
import { MetricsService } from 'src/app/services/metrics.service'
@Component({
template: `
<app-metrics [metrics]="metrics$ | async" />
`,
host: { class: 'g-page' },
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [MetricsComponent, AsyncPipe],
})
export default class SystemMetricsComponent {
readonly metrics$ = inject(MetricsService)
}

View File

@@ -8,7 +8,7 @@ import {
import { RouterLink } from '@angular/router' import { RouterLink } from '@angular/router'
import { T } from '@start9labs/start-sdk' import { T } from '@start9labs/start-sdk'
import { tuiPure } from '@taiga-ui/cdk' import { tuiPure } from '@taiga-ui/cdk'
import { TuiSvgModule } from '@taiga-ui/core' import { TuiLinkModule, TuiSvgModule } from '@taiga-ui/core'
import { TuiLineClampModule } from '@taiga-ui/kit' import { TuiLineClampModule } from '@taiga-ui/kit'
import { PatchDB } from 'patch-db-client' import { PatchDB } from 'patch-db-client'
import { first, Observable } from 'rxjs' import { first, Observable } from 'rxjs'
@@ -20,10 +20,10 @@ import { toRouterLink } from 'src/app/utils/to-router-link'
@Component({ @Component({
selector: '[notificationItem]', selector: '[notificationItem]',
template: ` template: `
<td><ng-content /></td> <td [style.padding-top.rem]="0.4"><ng-content /></td>
<td>{{ notificationItem.createdAt | date: 'MMM d, y, h:mm a' }}</td> <td>{{ notificationItem.createdAt | date: 'MMM d, y, h:mm a' }}</td>
<td [style.color]="color"> <td [style.color]="color">
<tui-svg [style.color]="color" [src]="icon"></tui-svg> <tui-svg [src]="icon" />
{{ notificationItem.title }} {{ notificationItem.title }}
</td> </td>
<td> <td>
@@ -43,20 +43,44 @@ import { toRouterLink } from 'src/app/utils/to-router-link'
[content]="notificationItem.message" [content]="notificationItem.message"
(overflownChange)="overflow = $event" (overflownChange)="overflow = $event"
/> />
<a *ngIf="overflow" (click)="service.viewFull(notificationItem)"> <button
*ngIf="overflow"
tuiLink
(click)="service.viewFull(notificationItem)"
>
View Full View Full
</a> </button>
<a <button
*ngIf="notificationItem.code === 1" *ngIf="notificationItem.code === 1"
tuiLink
(click)="service.viewReport(notificationItem)" (click)="service.viewReport(notificationItem)"
> >
View Report View Report
</a> </button>
</td> </td>
`, `,
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true, standalone: true,
imports: [CommonModule, RouterLink, TuiLineClampModule, TuiSvgModule], host: {
'[class._new]': '!notificationItem.read',
},
styles: `
:host._new {
background: var(--tui-clear);
}
td {
padding: 0.25rem;
vertical-align: top;
}
`,
imports: [
CommonModule,
RouterLink,
TuiLineClampModule,
TuiSvgModule,
TuiLinkModule,
],
}) })
export class NotificationItemComponent { export class NotificationItemComponent {
private readonly patch = inject(PatchDB<DataModel>) private readonly patch = inject(PatchDB<DataModel>)

View File

@@ -14,25 +14,24 @@ import { NotificationsTableComponent } from './table.component'
template: ` template: `
<ng-container *tuiLet="notifications$ | async as notifications"> <ng-container *tuiLet="notifications$ | async as notifications">
<h3 class="g-title"> <h3 class="g-title">
Notifications <tui-hosted-dropdown
<ng-container *ngIf="table.selected$ | async as selected"> *ngIf="table.selected$ | async as selected"
<tui-hosted-dropdown tuiDropdownAlign="right"
tuiDropdownAlign="right" [content]="dropdown"
[content]="dropdown" [sided]="true"
[sided]="true" [(open)]="open"
[(open)]="open" [canOpen]="!!selected.length"
>
<button
appearance="primary"
iconRight="tuiIconChevronDown"
tuiButton
size="xs"
type="button"
[disabled]="!selected.length"
> >
<button Batch Action
appearance="primary" </button>
iconRight="tuiIconChevronDown"
tuiButton
size="xs"
type="button"
[disabled]="!selected.length"
>
Batch Action
</button>
</tui-hosted-dropdown>
<ng-template #dropdown> <ng-template #dropdown>
<tui-data-list> <tui-data-list>
<button tuiOption (click)="markSeen(notifications!, selected)"> <button tuiOption (click)="markSeen(notifications!, selected)">
@@ -46,7 +45,7 @@ import { NotificationsTableComponent } from './table.component'
</button> </button>
</tui-data-list> </tui-data-list>
</ng-template> </ng-template>
</ng-container> </tui-hosted-dropdown>
</h3> </h3>
<table #table class="g-table" [notifications]="notifications"></table> <table #table class="g-table" [notifications]="notifications"></table>
</ng-container> </ng-container>

View File

@@ -1,20 +1,18 @@
import { CommonModule } from '@angular/common'
import { import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
Component, Component,
Input, Input,
OnChanges, OnChanges,
} from '@angular/core' } from '@angular/core'
import { FormsModule } from '@angular/forms'
import { TuiCheckboxModule } from '@taiga-ui/experimental'
import { TuiLineClampModule } from '@taiga-ui/kit'
import { BehaviorSubject } from 'rxjs'
import { import {
ServerNotification, ServerNotification,
ServerNotifications, ServerNotifications,
} from 'src/app/services/api/api.types' } from 'src/app/services/api/api.types'
import { TuiForModule } from '@taiga-ui/cdk'
import { BehaviorSubject } from 'rxjs'
import { TuiLineClampModule } from '@taiga-ui/kit'
import { FormsModule } from '@angular/forms'
import { NotificationItemComponent } from './item.component' import { NotificationItemComponent } from './item.component'
import { TuiCheckboxModule } from '@taiga-ui/experimental'
@Component({ @Component({
selector: 'table[notifications]', selector: 'table[notifications]',
@@ -39,39 +37,40 @@ import { TuiCheckboxModule } from '@taiga-ui/experimental'
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr @if (notifications) {
*ngFor="let notification of notifications; else: loading; empty: blank" @for (notification of notifications; track $index) {
[notificationItem]="notification" <tr
[style.font-weight]="notification.read ? 'normal' : 'bold'" [notificationItem]="notification"
> [style.font-weight]="notification.read ? 'normal' : 'bold'"
<input >
tuiCheckbox <input
size="s" tuiCheckbox
type="checkbox" size="s"
[style.display]="'block'" type="checkbox"
[ngModel]="selected$.value.includes(notification)" [style.display]="'block'"
(ngModelChange)="handleToggle(notification)" [ngModel]="selected$.value.includes(notification)"
/> (ngModelChange)="handleToggle(notification)"
</tr> />
<ng-template #blank> </tr>
<tr> } @empty {
<td colspan="5">You have no notifications</td> <tr>
</tr> <td colspan="5">You have no notifications</td>
</ng-template> </tr>
<ng-template #loading> }
<tr *ngFor="let row of ['', '']"> } @else {
<td colspan="5"><div class="tui-skeleton">Loading</div></td> @for (row of ['', '']; track $index) {
</tr> <tr>
</ng-template> <td colspan="5"><div class="tui-skeleton">Loading</div></td>
</tr>
}
}
</tbody> </tbody>
`, `,
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true, standalone: true,
imports: [ imports: [
CommonModule,
TuiForModule,
TuiCheckboxModule,
FormsModule, FormsModule,
TuiCheckboxModule,
TuiLineClampModule, TuiLineClampModule,
NotificationItemComponent, NotificationItemComponent,
], ],

View File

@@ -27,9 +27,16 @@ import { SettingBtn } from '../settings.types'
<tui-icon *ngIf="button.routerLink" icon="tuiIconChevronRight" /> <tui-icon *ngIf="button.routerLink" icon="tuiIconChevronRight" />
</ng-template> </ng-template>
`, `,
styles: [ styles: `
':host:not(:last-child) { display: block; box-shadow: 0 1px var(--tui-clear); }', :host:not(:last-child) {
], display: block;
box-shadow: 0 1px var(--tui-clear);
}
button {
cursor: pointer;
}
`,
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true, standalone: true,
imports: [CommonModule, TuiIconModule, TuiTitleModule, RouterLink], imports: [CommonModule, TuiIconModule, TuiTitleModule, RouterLink],

View File

@@ -51,7 +51,6 @@ import { SettingsUpdateComponent } from './update.component'
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 1rem; gap: 1rem;
padding-top: 1rem;
} }
`, `,
], ],

View File

@@ -47,10 +47,20 @@ import { UPDATE } from '../modals/update.component'
</div> </div>
</button> </button>
`, `,
styles: [ styles: `
':host { display: block; box-shadow: 0 1px var(--tui-clear); }', :host {
'.small { width: 1rem; height: 1rem; }', display: block;
], box-shadow: 0 1px var(--tui-clear);
}
button {
cursor: pointer;
}
.small {
font-size: 1rem;
}
`,
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true, standalone: true,
imports: [CommonModule, TuiIconModule, TuiTitleModule], imports: [CommonModule, TuiIconModule, TuiTitleModule],

View File

@@ -9,44 +9,29 @@ import { SettingsMenuComponent } from './components/menu.component'
routerLink="/portal/system/settings" routerLink="/portal/system/settings"
routerLinkActive="_current" routerLinkActive="_current"
[routerLinkActiveOptions]="{ exact: true }" [routerLinkActiveOptions]="{ exact: true }"
> ></a>
<tui-icon icon="tuiIconChevronLeft" /> <settings-menu />
Settings
</a>
<settings-menu class="page" />
<router-outlet /> <router-outlet />
`, `,
styles: [ styles: [
` `
:host { :host {
padding-top: 1rem;
::ng-deep tui-notification { ::ng-deep tui-notification {
position: sticky; position: sticky;
left: 0; left: 0;
} }
} }
a { a,
position: sticky; settings-menu {
left: 0;
display: inline-flex;
align-items: center;
gap: 0.5rem;
margin: 1rem 0;
font-size: 1rem;
color: var(--tui-text-01);
}
._current {
display: none; display: none;
} }
.page { ._current + settings-menu {
display: none;
}
._current + .page {
display: flex; display: flex;
max-width: 45rem; max-width: 30rem;
margin: 0 auto; margin: 0 auto;
} }
`, `,

View File

@@ -48,6 +48,12 @@ const ROUTES: Routes = [
loadComponent: () => import('./updates/updates.component'), loadComponent: () => import('./updates/updates.component'),
data: toNavigationItem('/portal/system/updates'), data: toNavigationItem('/portal/system/updates'),
}, },
{
title: systemTabResolver,
path: 'metrics',
loadComponent: () => import('./metrics/metrics.component'),
data: toNavigationItem('/portal/system/metrics'),
},
] ]
@NgModule({ imports: [RouterModule.forChild(ROUTES)] }) @NgModule({ imports: [RouterModule.forChild(ROUTES)] })

View File

@@ -43,7 +43,9 @@ import { hasCurrentDeps } from 'src/app/utils/has-deps'
template: ` template: `
<tui-accordion-item borders="top-bottom"> <tui-accordion-item borders="top-bottom">
<div class="g-action"> <div class="g-action">
<tui-avatar size="s" [src]="marketplacePkg" /> <tui-avatar size="s">
<img alt="" [src]="marketplacePkg.icon" />
</tui-avatar>
<div [style.flex]="1" [style.overflow]="'hidden'"> <div [style.flex]="1" [style.overflow]="'hidden'">
<strong>{{ marketplacePkg.manifest.title }}</strong> <strong>{{ marketplacePkg.manifest.title }}</strong>
<div> <div>