How to get details of a document in typescript

Hi All,

Managed to solve this one. If anyone needs something similar here is my code:

import { html, customElement, LitElement, property, css, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';
import { UmbMediaDetailRepository } from '@umbraco-cms/backoffice/media';
import type { UmbBlockDataType } from '@umbraco-cms/backoffice/block';
import type { UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/block-custom-view';
import type { UmbMediaPickerPropertyValue } from '@umbraco-cms/backoffice/media';

@customElement('document-block-view')
export class DocumentBlockViewElement extends UmbElementMixin(LitElement) implements UmbBlockEditorCustomViewElement {

    @property({ attribute: false })
    content?: UmbBlockDataType;

    @state()
    document: UmbMediaPickerPropertyValue[] = [];

    @state()
    private _documentDetails: Map<string, { name: string, url: string, extension: string, size: number }> = new Map();

    #mediaRepository = new UmbMediaDetailRepository(this);

    override async updated(changedProperties: Map<string | number | symbol, unknown>) {
        super.updated(changedProperties);
        if (changedProperties.has('content') && this.content?.document) {
            this.document = this.content.document as UmbMediaPickerPropertyValue[];
            await this.fetchDocumentDetails();
        }
    }

    async fetchDocumentDetails() {
        if (!this.document) return;

        for (const doc of this.document) {
            if (doc.mediaKey && !this._documentDetails.has(doc.mediaKey)) {
                const mediaItem = await this.resolveMediaItem(doc.mediaKey);
                if (mediaItem) {
                    // Find properties by their unique alias
                    const uploadField = mediaItem.values.find(v => v.alias === 'umbracoFile');
                    const extensionField = mediaItem.values.find(v => v.alias === 'umbracoExtension');
                    const sizeField = mediaItem.values.find(v => v.alias === 'umbracoBytes');

                    // Check that the properties exist before using them
                    if (uploadField && extensionField && sizeField) {
                        this._documentDetails.set(doc.mediaKey, {
                            name: mediaItem.variants[0].name,
                            url: (uploadField.value as { src: string }).src,
                            extension: extensionField.value as string,
                            size: sizeField.value as number
                        });

                        this.requestUpdate();
                    }
                }
            }
        }
    }

    async resolveMediaItem(mediaKey: string) {
        const { data } = await this.#mediaRepository.requestByUnique(mediaKey);
        return data;
    }

    render() {
        return html`
            <ul class="document-list">
                ${this.document.map((doc) => {
                    const details = this._documentDetails.get(doc.mediaKey || '');
                    return html`
                        <li>
                            <a href="${details?.url}" target="_blank" rel="noopener noreferrer">
                                ${details ? `${details.name} (${details.extension}, ${details.size} bytes)` : 'Loading...'}
                            </a>
                        </li>
                    `;
                })}
            </ul>`;
    }

    static styles = [
        css`
            :host {
                display: block;
                height: 100%;
                box-sizing: border-box;
                background-color: white;
                border-radius: 9px;
                padding: 12px;
            }

            .document-list {
                list-style-type:- disclosure-closed;
                padding-inline-start: 20px;
            }

            .document-list a {
                text-decoration: none;
                color: var(--uui-color-interactive, #2152a3);
            }

            .document-list a:hover {
                text-decoration: underline;
            }
        `,
    ];
}

export default DocumentBlockViewElement;

declare global {
    interface HTMLElementTagNameMap {
        'document-block-view': DocumentBlockViewElement;
    }
}
1 Like