diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/packages-installed-item.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/packages-installed-item.element.ts new file mode 100644 index 0000000000..c87bee2d30 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/packages-installed-item.element.ts @@ -0,0 +1,94 @@ +import { html, LitElement, nothing } from 'lit'; +import { customElement, property, state } from 'lit/decorators.js'; +import { firstValueFrom, map } from 'rxjs'; + +import { UmbContextConsumerMixin } from '../../../core/context'; +import { createExtensionElement, UmbExtensionRegistry } from '../../../core/extension'; + +import type { ManifestPackageView, PackageInstalled } from '../../../core/models'; +import type { UmbModalService } from '../../../core/services/modal'; + +@customElement('umb-packages-installed-item') +export class UmbPackagesInstalledItem extends UmbContextConsumerMixin(LitElement) { + @property({ type: Object }) + package!: PackageInstalled; + + @state() + private _packageView?: ManifestPackageView; + + private _umbExtensionRegistry?: UmbExtensionRegistry; + private _umbModalService?: UmbModalService; + + constructor() { + super(); + + this.consumeContext('umbExtensionRegistry', (umbExtensionRegistry: UmbExtensionRegistry) => { + this._umbExtensionRegistry = umbExtensionRegistry; + + this.findPackageView(this.package.alias); + }); + + this.consumeContext('umbModalService', (modalService: UmbModalService) => { + this._umbModalService = modalService; + }); + } + + private async findPackageView(alias: string) { + const observable = this._umbExtensionRegistry + ?.extensionsOfType('packageView') + .pipe(map((e) => e.filter((m) => m.meta.packageAlias === alias))); + + if (!observable) { + return; + } + + const views = await firstValueFrom(observable); + if (!views.length) { + return; + } + + this._packageView = views[0]; + } + + render() { + return html` + + + ${this._packageView + ? html`` + : nothing} + + + `; + } + + private async _onConfigure() { + if (!this._packageView?.elementName) { + console.warn('Tried to configure package without view'); + return; + } + + const element = await createExtensionElement(this._packageView); + + if (!element) { + console.warn('Failed to create package view element'); + return; + } + + this._umbModalService?.open(element, { data: this.package, size: 'small', type: 'sidebar' }); + } + + private _onClick() { + window.history.pushState({}, '', `/section/packages/view/repo/${this.package.id}`); + } +} + +declare global { + interface HTMLElementTagNameMap { + 'umb-packages-installed-item': UmbPackagesInstalledItem; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/packages-installed.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/packages-installed.element.ts index 6c5a921116..ae4321a076 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/packages-installed.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/packages-installed.element.ts @@ -1,30 +1,23 @@ +import './packages-installed-item.element'; + import { html, LitElement, nothing } from 'lit'; import { customElement, state } from 'lit/decorators.js'; import { repeat } from 'lit/directives/repeat.js'; -import { until } from 'lit/directives/until.js'; -import { firstValueFrom, map } from 'rxjs'; import { getPackagesInstalled } from '../../../core/api/fetcher'; -import { UmbContextConsumerMixin } from '../../../core/context'; -import { UmbExtensionRegistry } from '../../../core/extension'; import type { PackageInstalled } from '../../../core/models'; + @customElement('umb-packages-installed') -export class UmbPackagesInstalled extends UmbContextConsumerMixin(LitElement) { +export class UmbPackagesInstalled extends LitElement { @state() private _installedPackages: PackageInstalled[] = []; @state() private _errorMessage = ''; - private umbExtensionRegistry?: UmbExtensionRegistry; - constructor() { super(); - - this.consumeContext('umbExtensionRegistry', (umbExtensionRegistry: UmbExtensionRegistry) => { - this.umbExtensionRegistry = umbExtensionRegistry; - }); } connectedCallback(): void { @@ -52,24 +45,6 @@ export class UmbPackagesInstalled extends UmbContextConsumerMixin(LitElement) { } } - private findPackageView(alias: string) { - const observable = this.umbExtensionRegistry - ?.extensionsOfType('packageView') - .pipe(map((e) => e.filter((m) => m.meta.packageAlias === alias))); - return observable ? firstValueFrom(observable) : undefined; - } - - async renderPackage(p: PackageInstalled) { - const packageView = await this.findPackageView(p.alias); - return html` - - - ${packageView?.length ? html`` : nothing} - - - `; - } - render() { return html` @@ -79,7 +54,7 @@ export class UmbPackagesInstalled extends UmbContextConsumerMixin(LitElement) { ${repeat( this._installedPackages, (item) => item.id, - (item) => until(this.renderPackage(item), 'Loading...') + (item) => html`` )}