Feature: Data mapping extension + aligning reference lists (#18318)
* wip entity-item-ref extension point * clean up * add ref list element * fix styling * Update document-item-ref.element.ts * move item repo * implement for input member * enable action slot * add null check * fix sorting again * fix sorting again * use member element * add draft styling back * move item repository * implement for user input * pass readonly and standalone props * make editPath a state * Update member-item-ref.element.ts * Fix user item ref * remove open button * remove unused * remove unused * check for section permission * add fallback element * wip data mapper concept * add unique to modal route registration * add unique to modal router * remove unused id * Update member-item-ref.element.ts * append unique * compare with old value * only recreate the controller if the entity type changes * fix console warning * implement for document item ref * Added $type to ReferenceResponseModels * move logic to item data resolver * render draft as a tag * Update document-item-ref.element.ts * generate server models * add more helpers to data resolver * export resolver * add observables * use observables in document item ref * add data resolver to tree item * add observable state * use const * align models * get icon from document type object * observe name and state * update observed value when a new item is set * update method name * update method names * pass model type * pass context type * use api prop instead of context * use api prop instead of context * fix types * use addUniquePaths for modal registration * add fallback * use ref list * use reference items for media * make mapper name more generic * make default ref item always readonly * export types * temp fake variants array * add variants array to model * Update media-references-workspace-info-app.element.ts * add variants to model * hardcode fake array * register media ref item * update mock data * dot not allow conditions for data mappers * add data mapper * prefix info routes * prefix all ref routes * return undefined if there is not edit path * fix name collision * require data source identifier * use management api mapper * add management api mapper * fix type errors * Update index.ts * align naming * add todo comment * implement path pattern for media item * clean up * more clean up * sort imports * member edit path pattern * clean up --------- Co-authored-by: Sven Geusens <sge@umbraco.dk> Co-authored-by: Niels Lyngsø <niels.lyngso@gmail.com>
This commit is contained in:
@@ -79,6 +79,7 @@ export class UmbClipboardPastePropertyValueTranslatorValueResolver<
|
||||
}
|
||||
|
||||
// Pick the manifest with the highest priority
|
||||
// TODO: This should have been handled in the extension registry, but until then we do it here: [NL]
|
||||
return supportedManifests.sort((a: ManifestBase, b: ManifestBase): number => (b.weight || 0) - (a.weight || 0))[0];
|
||||
}
|
||||
|
||||
|
||||
@@ -7,9 +7,6 @@ export class UmbDefaultItemRefElement extends UmbLitElement {
|
||||
@property({ type: Object })
|
||||
item?: UmbDefaultItemModel;
|
||||
|
||||
@property({ type: Boolean })
|
||||
readonly = false;
|
||||
|
||||
@property({ type: Boolean })
|
||||
standalone = false;
|
||||
|
||||
@@ -17,7 +14,7 @@ export class UmbDefaultItemRefElement extends UmbLitElement {
|
||||
if (!this.item) return nothing;
|
||||
|
||||
return html`
|
||||
<uui-ref-node name=${this.item.name} ?readonly=${this.readonly} ?standalone=${this.standalone}>
|
||||
<uui-ref-node name=${this.item.name} ?standalone=${this.standalone} readonly>
|
||||
<slot name="actions" slot="actions"></slot>
|
||||
${this.#renderIcon(this.item)}
|
||||
</uui-ref-node>
|
||||
|
||||
@@ -7,6 +7,7 @@ import { UMB_MARK_ATTRIBUTE_NAME } from '@umbraco-cms/backoffice/const';
|
||||
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
import './default-item-ref.element.js';
|
||||
import { UmbRoutePathAddendumContext } from '@umbraco-cms/backoffice/router';
|
||||
|
||||
@customElement('umb-entity-item-ref')
|
||||
export class UmbEntityItemRefElement extends UmbLitElement {
|
||||
@@ -33,6 +34,8 @@ export class UmbEntityItemRefElement extends UmbLitElement {
|
||||
return;
|
||||
}
|
||||
|
||||
this.#pathAddendum.setAddendum('ref/' + value.entityType + '/' + value.unique);
|
||||
|
||||
// If the component is already created, but the entity type is different, we need to destroy the component.
|
||||
this.#createController(value.entityType);
|
||||
}
|
||||
@@ -63,6 +66,8 @@ export class UmbEntityItemRefElement extends UmbLitElement {
|
||||
}
|
||||
}
|
||||
|
||||
#pathAddendum = new UmbRoutePathAddendumContext(this);
|
||||
|
||||
protected override firstUpdated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void {
|
||||
super.firstUpdated(_changedProperties);
|
||||
this.setAttribute(UMB_MARK_ATTRIBUTE_NAME, 'entity-item-ref');
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export * from './data-mapper/constants.js';
|
||||
@@ -0,0 +1 @@
|
||||
export * from './management-api/constants.js';
|
||||
@@ -0,0 +1,43 @@
|
||||
import { UmbDataMappingResolver } from './mapping/data-mapping-resolver.js';
|
||||
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
|
||||
|
||||
export interface UmbDataMapperMapArgs<fromModelType = unknown, toModelType = unknown> {
|
||||
forDataModel: string;
|
||||
forDataSource: string;
|
||||
data: fromModelType;
|
||||
fallback?: (data: fromModelType) => Promise<toModelType>;
|
||||
}
|
||||
|
||||
export class UmbDataMapper<fromModelType = unknown, toModelType = unknown> extends UmbControllerBase {
|
||||
#dataMappingResolver = new UmbDataMappingResolver(this);
|
||||
|
||||
async map(args: UmbDataMapperMapArgs<fromModelType, toModelType>) {
|
||||
if (!args.forDataSource) {
|
||||
throw new Error('data source identifier is required');
|
||||
}
|
||||
|
||||
if (!args.forDataModel) {
|
||||
throw new Error('data identifier is required');
|
||||
}
|
||||
|
||||
if (!args.data) {
|
||||
throw new Error('data is required');
|
||||
}
|
||||
|
||||
const dataMapping = await this.#dataMappingResolver.resolve(args.forDataSource, args.forDataModel);
|
||||
|
||||
if (!dataMapping && !args.fallback) {
|
||||
throw new Error('Data mapping not found and no fallback provided.');
|
||||
}
|
||||
|
||||
if (!dataMapping && args.fallback) {
|
||||
return args.fallback(args.data);
|
||||
}
|
||||
|
||||
if (!dataMapping?.map) {
|
||||
throw new Error('Data mapping does not have a map method.');
|
||||
}
|
||||
|
||||
return dataMapping.map(args.data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export * from './data-mapper.js';
|
||||
export * from './mapping/index.js';
|
||||
export * from './management-api/management-api-data-mapper.js';
|
||||
@@ -0,0 +1 @@
|
||||
export const UMB_MANAGEMENT_API_DATA_SOURCE_IDENTIFIER = 'Umb.ManagementApi';
|
||||
@@ -0,0 +1,19 @@
|
||||
import { UmbDataMapper, type UmbDataMapperMapArgs } from '../data-mapper.js';
|
||||
import { UMB_MANAGEMENT_API_DATA_SOURCE_IDENTIFIER } from './constants.js';
|
||||
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
export class UmbManagementApiDataMapper extends UmbControllerBase {
|
||||
#dataMapper = new UmbDataMapper(this);
|
||||
|
||||
constructor(host: UmbControllerHost) {
|
||||
super(host);
|
||||
}
|
||||
|
||||
map(args: Omit<UmbDataMapperMapArgs, 'forDataSource'>) {
|
||||
return this.#dataMapper.map({
|
||||
...args,
|
||||
forDataSource: UMB_MANAGEMENT_API_DATA_SOURCE_IDENTIFIER,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import type { UmbDataMapping } from './types.js';
|
||||
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
|
||||
import { createExtensionApi, type ManifestBase } from '@umbraco-cms/backoffice/extension-api';
|
||||
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export class UmbDataMappingResolver extends UmbControllerBase {
|
||||
#apiCache = new Map<string, UmbDataMapping>();
|
||||
|
||||
async resolve(forDataSource: string, forDataModel: string): Promise<UmbDataMapping | undefined> {
|
||||
if (!forDataSource) {
|
||||
throw new Error('data source identifier is required');
|
||||
}
|
||||
|
||||
if (!forDataModel) {
|
||||
throw new Error('data identifier is required');
|
||||
}
|
||||
|
||||
const manifest = this.#getManifestWithBestFit(forDataSource, forDataModel);
|
||||
|
||||
if (!manifest) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Check the cache before creating a new instance
|
||||
if (this.#apiCache.has(manifest.alias)) {
|
||||
return this.#apiCache.get(manifest.alias)!;
|
||||
}
|
||||
|
||||
const dataMapping = await createExtensionApi<UmbDataMapping>(this, manifest);
|
||||
|
||||
if (!dataMapping) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!dataMapping.map) {
|
||||
throw new Error('Data Mapping does not have a map method.');
|
||||
}
|
||||
|
||||
// Cache the api instance for future use
|
||||
this.#apiCache.set(manifest.alias, dataMapping);
|
||||
|
||||
return dataMapping;
|
||||
}
|
||||
|
||||
#getManifestWithBestFit(forDataSource: string, forDataModel: string) {
|
||||
const supportedManifests = this.#getSupportedManifests(forDataSource, forDataModel);
|
||||
|
||||
if (!supportedManifests.length) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Pick the manifest with the highest priority
|
||||
// TODO: This should have been handled in the extension registry, but until then we do it here: [NL]
|
||||
return supportedManifests.sort((a: ManifestBase, b: ManifestBase): number => (b.weight || 0) - (a.weight || 0))[0];
|
||||
}
|
||||
|
||||
#getSupportedManifests(forDataSource: string, forDataModel: string) {
|
||||
const supportedManifests = umbExtensionsRegistry.getByTypeAndFilter('dataMapping', (manifest) => {
|
||||
return manifest.forDataSource === forDataSource && manifest.forDataModel === forDataModel;
|
||||
});
|
||||
|
||||
return supportedManifests;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import type { UmbDataMapping } from './types.js';
|
||||
import type { ManifestApi } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export interface ManifestDataMapping<MetaType extends MetaDataMapping = MetaDataMapping>
|
||||
extends ManifestApi<UmbDataMapping> {
|
||||
type: 'dataMapping';
|
||||
forDataSource: string;
|
||||
forDataModel: string;
|
||||
meta: MetaType;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||
export interface MetaDataMapping {}
|
||||
|
||||
declare global {
|
||||
interface UmbExtensionManifestMap {
|
||||
umbManifestDataMapping: ManifestDataMapping;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './data-mapping-resolver.js';
|
||||
@@ -0,0 +1,6 @@
|
||||
import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
|
||||
export type * from './data-mapping.extension.js';
|
||||
|
||||
export interface UmbDataMapping<fromModelType = any, toModelType = any> extends UmbApi {
|
||||
map: (data: fromModelType) => Promise<toModelType>;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export type * from './mapping/types.js';
|
||||
@@ -1,8 +1,9 @@
|
||||
export * from './repository-items.manager.js';
|
||||
export * from './repository-base.js';
|
||||
|
||||
export * from './item/index.js';
|
||||
export * from './constants.js';
|
||||
export * from './data-mapper/index.js';
|
||||
export * from './detail/index.js';
|
||||
export * from './item/index.js';
|
||||
export * from './repository-base.js';
|
||||
export * from './repository-items.manager.js';
|
||||
|
||||
export type { UmbDataSourceResponse, UmbDataSourceErrorResponse } from './data-source-response.interface.js';
|
||||
export type * from './types.js';
|
||||
|
||||
@@ -14,3 +14,5 @@ export interface UmbRepositoryErrorResponse extends UmbDataSourceErrorResponse {
|
||||
export interface UmbRepositoryResponseWithAsObservable<T> extends UmbRepositoryResponse<T> {
|
||||
asObservable: () => Observable<T | undefined>;
|
||||
}
|
||||
|
||||
export type * from './data-mapper/mapping/types.js';
|
||||
|
||||
@@ -16,19 +16,7 @@ export class UmbDocumentItemRefElement extends UmbLitElement {
|
||||
return this.#item.getData();
|
||||
}
|
||||
public set item(value: UmbDocumentItemModel | undefined) {
|
||||
const oldValue = this.#item.getData();
|
||||
this.#item.setData(value);
|
||||
|
||||
if (!value) {
|
||||
this.#modalRoute?.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldValue?.unique === value.unique) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.#modalRoute?.setUniquePathValue('unique', value.unique);
|
||||
}
|
||||
|
||||
@property({ type: Boolean })
|
||||
@@ -55,13 +43,10 @@ export class UmbDocumentItemRefElement extends UmbLitElement {
|
||||
@state()
|
||||
_editPath = '';
|
||||
|
||||
#modalRoute?: any;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.#modalRoute = new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL)
|
||||
.addAdditionalPath(UMB_DOCUMENT_ENTITY_TYPE)
|
||||
new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL)
|
||||
.addUniquePaths(['unique'])
|
||||
.onSetup(() => {
|
||||
return { data: { entityType: UMB_DOCUMENT_ENTITY_TYPE, preset: {} } };
|
||||
@@ -78,6 +63,7 @@ export class UmbDocumentItemRefElement extends UmbLitElement {
|
||||
}
|
||||
|
||||
#getHref() {
|
||||
if (!this._unique) return;
|
||||
const path = UMB_EDIT_DOCUMENT_WORKSPACE_PATH_PATTERN.generateLocal({ unique: this._unique });
|
||||
return `${this._editPath}/${path}`;
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
export type { UmbDocumentItemModel } from './repository/types.js';
|
||||
export type * from './repository/types.js';
|
||||
|
||||
@@ -1,20 +1,14 @@
|
||||
import { UmbDocumentReferenceRepository } from '../repository/index.js';
|
||||
import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '../../constants.js';
|
||||
import { css, customElement, html, nothing, repeat, state, when } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { isDefaultReference, isDocumentReference, isMediaReference } from '@umbraco-cms/backoffice/relations';
|
||||
import { css, customElement, html, nothing, repeat, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router';
|
||||
import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace';
|
||||
import type { UmbReferenceModel } from '@umbraco-cms/backoffice/relations';
|
||||
import type { UmbReferenceItemModel } from '@umbraco-cms/backoffice/relations';
|
||||
import type { UUIPaginationEvent } from '@umbraco-cms/backoffice/external/uui';
|
||||
import type { UmbEntityUnique } from '@umbraco-cms/backoffice/entity';
|
||||
|
||||
@customElement('umb-document-references-workspace-info-app')
|
||||
export class UmbDocumentReferencesWorkspaceInfoAppElement extends UmbLitElement {
|
||||
@state()
|
||||
private _editDocumentPath = '';
|
||||
|
||||
@state()
|
||||
private _currentPage = 1;
|
||||
|
||||
@@ -22,7 +16,7 @@ export class UmbDocumentReferencesWorkspaceInfoAppElement extends UmbLitElement
|
||||
private _total = 0;
|
||||
|
||||
@state()
|
||||
private _items?: Array<UmbReferenceModel> = [];
|
||||
private _items?: Array<UmbReferenceItemModel> = [];
|
||||
|
||||
#itemsPerPage = 10;
|
||||
#referenceRepository = new UmbDocumentReferenceRepository(this);
|
||||
@@ -32,15 +26,6 @@ export class UmbDocumentReferencesWorkspaceInfoAppElement extends UmbLitElement
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL)
|
||||
.addAdditionalPath('document')
|
||||
.onSetup(() => {
|
||||
return { data: { entityType: 'document', preset: {} } };
|
||||
})
|
||||
.observeRouteBuilder((routeBuilder) => {
|
||||
this._editDocumentPath = routeBuilder({});
|
||||
});
|
||||
|
||||
this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, (context) => {
|
||||
this.#workspaceContext = context;
|
||||
this.#observeDocumentUnique();
|
||||
@@ -91,98 +76,28 @@ export class UmbDocumentReferencesWorkspaceInfoAppElement extends UmbLitElement
|
||||
this.#getReferences();
|
||||
}
|
||||
|
||||
#getIcon(item: UmbReferenceModel) {
|
||||
if (isDocumentReference(item)) {
|
||||
return item.documentType.icon ?? 'icon-document';
|
||||
}
|
||||
if (isMediaReference(item)) {
|
||||
return item.mediaType.icon ?? 'icon-picture';
|
||||
}
|
||||
if (isDefaultReference(item)) {
|
||||
return item.icon ?? 'icon-document';
|
||||
}
|
||||
return 'icon-document';
|
||||
}
|
||||
|
||||
#getPublishedStatus(item: UmbReferenceModel) {
|
||||
return isDocumentReference(item) ? item.published : true;
|
||||
}
|
||||
|
||||
#getContentTypeName(item: UmbReferenceModel) {
|
||||
if (isDocumentReference(item)) {
|
||||
return item.documentType.name;
|
||||
}
|
||||
if (isMediaReference(item)) {
|
||||
return item.mediaType.name;
|
||||
}
|
||||
if (isDefaultReference(item)) {
|
||||
return item.type;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
#getContentType(item: UmbReferenceModel) {
|
||||
if (isDocumentReference(item)) {
|
||||
return item.documentType.alias;
|
||||
}
|
||||
if (isMediaReference(item)) {
|
||||
return item.mediaType.alias;
|
||||
}
|
||||
if (isDefaultReference(item)) {
|
||||
return item.type;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
override render() {
|
||||
if (!this._items?.length) return nothing;
|
||||
return html`
|
||||
<umb-workspace-info-app-layout headline="#references_labelUsedByItems">
|
||||
<uui-table>
|
||||
<uui-table-head>
|
||||
<uui-table-head-cell></uui-table-head-cell>
|
||||
<uui-table-head-cell><umb-localize key="general_name">Name</umb-localize></uui-table-head-cell>
|
||||
<uui-table-head-cell><umb-localize key="general_status">Status</umb-localize></uui-table-head-cell>
|
||||
<uui-table-head-cell><umb-localize key="general_typeName">Type Name</umb-localize></uui-table-head-cell>
|
||||
<uui-table-head-cell><umb-localize key="general_type">Type</umb-localize></uui-table-head-cell>
|
||||
</uui-table-head>
|
||||
${repeat(
|
||||
this._items,
|
||||
(item) => item.id,
|
||||
(item) => html`
|
||||
<uui-table-row>
|
||||
<uui-table-cell style="text-align:center;">
|
||||
<umb-icon name=${this.#getIcon(item)}></umb-icon>
|
||||
</uui-table-cell>
|
||||
<uui-table-cell class="link-cell">
|
||||
${when(
|
||||
isDocumentReference(item),
|
||||
() => html`
|
||||
<uui-button
|
||||
label="${this.localize.term('general_edit')} ${item.name}"
|
||||
href="${this._editDocumentPath}edit/${item.id}">
|
||||
${item.name}
|
||||
</uui-button>
|
||||
`,
|
||||
() => item.name,
|
||||
)}
|
||||
</uui-table-cell>
|
||||
<uui-table-cell>
|
||||
${this.#getPublishedStatus(item)
|
||||
? this.localize.term('content_published')
|
||||
: this.localize.term('content_unpublished')}
|
||||
</uui-table-cell>
|
||||
<uui-table-cell>${this.#getContentTypeName(item)}</uui-table-cell>
|
||||
<uui-table-cell>${this.#getContentType(item)}</uui-table-cell>
|
||||
</uui-table-row>
|
||||
`,
|
||||
)}
|
||||
</uui-table>
|
||||
${this.#renderReferencePagination()}
|
||||
${this.#renderItems()} ${this.#renderReferencePagination()}
|
||||
</umb-workspace-info-app-layout>
|
||||
`;
|
||||
}
|
||||
|
||||
#renderItems() {
|
||||
if (!this._items) return;
|
||||
return html`
|
||||
<uui-ref-list>
|
||||
${repeat(
|
||||
this._items,
|
||||
(item) => item.unique,
|
||||
(item) => html`<umb-entity-item-ref .item=${item}></umb-entity-item-ref>`,
|
||||
)}
|
||||
</uui-ref-list>
|
||||
`;
|
||||
}
|
||||
|
||||
#renderReferencePagination() {
|
||||
if (!this._total) return nothing;
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import type { UmbDocumentReferenceModel } from '../types.js';
|
||||
import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js';
|
||||
import {
|
||||
DocumentVariantStateModel,
|
||||
type DocumentReferenceResponseModel,
|
||||
} from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
|
||||
import type { UmbDataMapping } from '@umbraco-cms/backoffice/repository';
|
||||
|
||||
export class UmbDocumentReferenceResponseManagementApiDataMapping
|
||||
extends UmbControllerBase
|
||||
implements UmbDataMapping<DocumentReferenceResponseModel, UmbDocumentReferenceModel>
|
||||
{
|
||||
async map(data: DocumentReferenceResponseModel): Promise<UmbDocumentReferenceModel> {
|
||||
return {
|
||||
documentType: {
|
||||
alias: data.documentType.alias,
|
||||
icon: data.documentType.icon,
|
||||
name: data.documentType.name,
|
||||
},
|
||||
entityType: UMB_DOCUMENT_ENTITY_TYPE,
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
published: data.published,
|
||||
// TODO: this is a hardcoded array until the server can return the correct variants array
|
||||
variants: [
|
||||
{
|
||||
culture: null,
|
||||
name: data.name ?? '',
|
||||
state: data.published ? DocumentVariantStateModel.PUBLISHED : null,
|
||||
},
|
||||
],
|
||||
unique: data.id,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export { UmbDocumentReferenceResponseManagementApiDataMapping as api };
|
||||
@@ -1,30 +1,47 @@
|
||||
import { DocumentService } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
|
||||
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
|
||||
import { UmbManagementApiDataMapper } from '@umbraco-cms/backoffice/repository';
|
||||
|
||||
/**
|
||||
* @class UmbDocumentReferenceServerDataSource
|
||||
* @implements {RepositoryDetailDataSource}
|
||||
*/
|
||||
export class UmbDocumentReferenceServerDataSource {
|
||||
#host: UmbControllerHost;
|
||||
|
||||
/**
|
||||
* Creates an instance of UmbDocumentReferenceServerDataSource.
|
||||
* @param {UmbControllerHost} host - The controller host for this controller to be appended to
|
||||
* @memberof UmbDocumentReferenceServerDataSource
|
||||
*/
|
||||
constructor(host: UmbControllerHost) {
|
||||
this.#host = host;
|
||||
}
|
||||
export class UmbDocumentReferenceServerDataSource extends UmbControllerBase {
|
||||
#dataMapper = new UmbManagementApiDataMapper(this);
|
||||
|
||||
/**
|
||||
* Fetches the item for the given unique from the server
|
||||
* @param {string} id
|
||||
* @param {string} unique - The unique identifier of the item to fetch
|
||||
* @returns {*}
|
||||
* @memberof UmbDocumentReferenceServerDataSource
|
||||
*/
|
||||
async getReferencedBy(id: string, skip = 0, take = 20) {
|
||||
return await tryExecuteAndNotify(this.#host, DocumentService.getDocumentByIdReferencedBy({ id, skip, take }));
|
||||
async getReferencedBy(unique: string, skip = 0, take = 20) {
|
||||
const { data, error } = await tryExecuteAndNotify(
|
||||
this,
|
||||
DocumentService.getDocumentByIdReferencedBy({ id: unique, skip, take }),
|
||||
);
|
||||
|
||||
if (data) {
|
||||
const promises = data.items.map(async (item) => {
|
||||
return this.#dataMapper.map({
|
||||
forDataModel: item.$type,
|
||||
data: item,
|
||||
fallback: async () => {
|
||||
return {
|
||||
...item,
|
||||
unique: item.id,
|
||||
entityType: 'unknown',
|
||||
};
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
const items = await Promise.all(promises);
|
||||
|
||||
return { data: { items, total: data.total } };
|
||||
}
|
||||
|
||||
return { data, error };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { UMB_DOCUMENT_REFERENCE_REPOSITORY_ALIAS } from './constants.js';
|
||||
import { UMB_MANAGEMENT_API_DATA_SOURCE_IDENTIFIER } from '@umbraco-cms/backoffice/repository';
|
||||
|
||||
export const manifests: Array<UmbExtensionManifest> = [
|
||||
{
|
||||
@@ -7,4 +8,12 @@ export const manifests: Array<UmbExtensionManifest> = [
|
||||
name: 'Document Reference Repository',
|
||||
api: () => import('./document-reference.repository.js'),
|
||||
},
|
||||
{
|
||||
type: 'dataMapping',
|
||||
alias: 'Umb.DataMapping.ManagementApi.DocumentReferenceResponse',
|
||||
name: 'Document Reference Response Management Api Data Mapping',
|
||||
api: () => import('./document-reference-response.management-api.mapping.js'),
|
||||
forDataSource: UMB_MANAGEMENT_API_DATA_SOURCE_IDENTIFIER,
|
||||
forDataModel: 'DocumentReferenceResponseModel',
|
||||
},
|
||||
];
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import type { UmbDocumentItemVariantModel } from '../item/types.js';
|
||||
import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity';
|
||||
import type { TrackedReferenceDocumentTypeModel } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
|
||||
export interface UmbDocumentReferenceModel extends UmbEntityModel {
|
||||
/**
|
||||
* @deprecated use unique instead
|
||||
* @type {string}
|
||||
* @memberof UmbDocumentReferenceModel
|
||||
*/
|
||||
id: string;
|
||||
|
||||
/**
|
||||
* @deprecated use name on the variant array instead
|
||||
* @type {(string | null)}
|
||||
* @memberof UmbDocumentReferenceModel
|
||||
*/
|
||||
name?: string | null;
|
||||
|
||||
/**
|
||||
* @deprecated use state on variant array instead
|
||||
* @type {boolean}
|
||||
* @memberof UmbDocumentReferenceModel
|
||||
*/
|
||||
published?: boolean | null;
|
||||
documentType: TrackedReferenceDocumentTypeModel;
|
||||
variants: Array<UmbDocumentItemVariantModel>;
|
||||
}
|
||||
@@ -60,7 +60,7 @@ export class UmbDocumentWorkspaceViewInfoElement extends UmbLitElement {
|
||||
super();
|
||||
|
||||
new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL)
|
||||
.addAdditionalPath(':entityType')
|
||||
.addAdditionalPath('general/:entityType')
|
||||
.onSetup((params) => {
|
||||
return { data: { entityType: params.entityType, preset: {} } };
|
||||
})
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import { UMB_MEDIA_ENTITY_TYPE } from '../entity.js';
|
||||
|
||||
export const manifests: Array<UmbExtensionManifest> = [
|
||||
{
|
||||
type: 'entityItemRef',
|
||||
alias: 'Umb.EntityItemRef.Media',
|
||||
name: 'Member Entity Item Reference',
|
||||
element: () => import('./media-item-ref.element.js'),
|
||||
forEntityTypes: [UMB_MEDIA_ENTITY_TYPE],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,93 @@
|
||||
import type { UmbMediaItemModel } from '../repository/types.js';
|
||||
import { UMB_MEDIA_SECTION_ALIAS } from '../../media-section/constants.js';
|
||||
import { UMB_MEDIA_ENTITY_TYPE } from '../entity.js';
|
||||
import { UMB_EDIT_MEDIA_WORKSPACE_PATH_PATTERN } from '../paths.js';
|
||||
import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import { customElement, html, ifDefined, nothing, property, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router';
|
||||
import { UMB_SECTION_USER_PERMISSION_CONDITION_ALIAS } from '@umbraco-cms/backoffice/section';
|
||||
import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace';
|
||||
|
||||
@customElement('umb-media-item-ref')
|
||||
export class UmbMediaItemRefElement extends UmbLitElement {
|
||||
#item?: UmbMediaItemModel | undefined;
|
||||
|
||||
@property({ type: Object })
|
||||
public get item(): UmbMediaItemModel | undefined {
|
||||
return this.#item;
|
||||
}
|
||||
public set item(value: UmbMediaItemModel | undefined) {
|
||||
this.#item = value;
|
||||
}
|
||||
|
||||
@property({ type: Boolean })
|
||||
readonly = false;
|
||||
|
||||
@property({ type: Boolean })
|
||||
standalone = false;
|
||||
|
||||
@state()
|
||||
_editPath = '';
|
||||
|
||||
@state()
|
||||
_userHasSectionAccess = false;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
createExtensionApiByAlias(this, UMB_SECTION_USER_PERMISSION_CONDITION_ALIAS, [
|
||||
{
|
||||
config: {
|
||||
match: UMB_MEDIA_SECTION_ALIAS,
|
||||
},
|
||||
onChange: (permitted: boolean) => {
|
||||
this._userHasSectionAccess = permitted;
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL)
|
||||
.addUniquePaths(['unique'])
|
||||
.onSetup(() => {
|
||||
return { data: { entityType: UMB_MEDIA_ENTITY_TYPE, preset: {} } };
|
||||
})
|
||||
.observeRouteBuilder((routeBuilder) => {
|
||||
this._editPath = routeBuilder({});
|
||||
});
|
||||
}
|
||||
|
||||
#getHref(item: UmbMediaItemModel) {
|
||||
if (!this._editPath) return;
|
||||
const path = UMB_EDIT_MEDIA_WORKSPACE_PATH_PATTERN.generateLocal({ unique: item.unique });
|
||||
return `${this._editPath}/${path}`;
|
||||
}
|
||||
|
||||
override render() {
|
||||
if (!this.item) return nothing;
|
||||
|
||||
return html`
|
||||
<uui-ref-node
|
||||
name=${this.item.name}
|
||||
href=${ifDefined(this.#getHref(this.item))}
|
||||
?readonly=${this.readonly || !this._userHasSectionAccess}
|
||||
?standalone=${this.standalone}>
|
||||
<slot name="actions" slot="actions"></slot>
|
||||
${this.#renderIcon(this.item)}
|
||||
</uui-ref-node>
|
||||
`;
|
||||
}
|
||||
|
||||
#renderIcon(item: UmbMediaItemModel) {
|
||||
if (!item.mediaType.icon) return;
|
||||
return html`<umb-icon slot="icon" name=${item.mediaType.icon}></umb-icon>`;
|
||||
}
|
||||
}
|
||||
|
||||
export { UmbMediaItemRefElement as element };
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-media-item-ref': UmbMediaItemRefElement;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import { manifests as dropzoneManifests } from './dropzone/manifests.js';
|
||||
import { manifests as entityActionsManifests } from './entity-actions/manifests.js';
|
||||
import { manifests as entityBulkActionsManifests } from './entity-bulk-actions/manifests.js';
|
||||
import { manifests as fileUploadPreviewManifests } from './components/input-upload-field/manifests.js';
|
||||
import { manifests as itemManifests } from './item/manifests.js';
|
||||
import { manifests as menuManifests } from './menu/manifests.js';
|
||||
import { manifests as modalManifests } from './modals/manifests.js';
|
||||
import { manifests as propertyEditorsManifests } from './property-editors/manifests.js';
|
||||
@@ -23,6 +24,7 @@ export const manifests: Array<UmbExtensionManifest> = [
|
||||
...entityActionsManifests,
|
||||
...entityBulkActionsManifests,
|
||||
...fileUploadPreviewManifests,
|
||||
...itemManifests,
|
||||
...menuManifests,
|
||||
...modalManifests,
|
||||
...propertyEditorsManifests,
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
import { UmbMediaReferenceRepository } from '../repository/index.js';
|
||||
import { UMB_MEDIA_WORKSPACE_CONTEXT } from '../../workspace/constants.js';
|
||||
import { css, customElement, html, nothing, repeat, state, when } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { isDefaultReference, isDocumentReference, isMediaReference } from '@umbraco-cms/backoffice/relations';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router';
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace';
|
||||
import type { UmbReferenceModel } from '@umbraco-cms/backoffice/relations';
|
||||
import type { UmbModalRouteBuilder } from '@umbraco-cms/backoffice/router';
|
||||
import type { UmbReferenceItemModel } from '@umbraco-cms/backoffice/relations';
|
||||
import type { UUIPaginationEvent } from '@umbraco-cms/backoffice/external/uui';
|
||||
import type { UmbEntityUnique } from '@umbraco-cms/backoffice/entity';
|
||||
|
||||
@@ -17,8 +13,6 @@ export class UmbMediaReferencesWorkspaceInfoAppElement extends UmbLitElement {
|
||||
|
||||
#referenceRepository;
|
||||
|
||||
#routeBuilder?: UmbModalRouteBuilder;
|
||||
|
||||
@state()
|
||||
private _currentPage = 1;
|
||||
|
||||
@@ -26,7 +20,7 @@ export class UmbMediaReferencesWorkspaceInfoAppElement extends UmbLitElement {
|
||||
private _total = 0;
|
||||
|
||||
@state()
|
||||
private _items?: Array<UmbReferenceModel> = [];
|
||||
private _items?: Array<UmbReferenceItemModel> = [];
|
||||
|
||||
@state()
|
||||
private _loading = true;
|
||||
@@ -38,15 +32,6 @@ export class UmbMediaReferencesWorkspaceInfoAppElement extends UmbLitElement {
|
||||
super();
|
||||
this.#referenceRepository = new UmbMediaReferenceRepository(this);
|
||||
|
||||
new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL)
|
||||
.addAdditionalPath(':entityType')
|
||||
.onSetup((params) => {
|
||||
return { data: { entityType: params.entityType, preset: {} } };
|
||||
})
|
||||
.observeRouteBuilder((routeBuilder) => {
|
||||
this.#routeBuilder = routeBuilder;
|
||||
});
|
||||
|
||||
this.consumeContext(UMB_MEDIA_WORKSPACE_CONTEXT, (context) => {
|
||||
this.#workspaceContext = context;
|
||||
this.#observeMediaUnique();
|
||||
@@ -106,54 +91,6 @@ export class UmbMediaReferencesWorkspaceInfoAppElement extends UmbLitElement {
|
||||
this.#getReferences();
|
||||
}
|
||||
|
||||
#getEditPath(item: UmbReferenceModel) {
|
||||
const entityType = this.#getEntityType(item);
|
||||
return this.#routeBuilder && entityType ? `${this.#routeBuilder({ entityType })}edit/${item.id}` : '#';
|
||||
}
|
||||
|
||||
#getIcon(item: UmbReferenceModel) {
|
||||
if (isDocumentReference(item)) {
|
||||
return item.documentType.icon ?? 'icon-document';
|
||||
}
|
||||
if (isMediaReference(item)) {
|
||||
return item.mediaType.icon ?? 'icon-picture';
|
||||
}
|
||||
if (isDefaultReference(item)) {
|
||||
return item.icon ?? 'icon-document';
|
||||
}
|
||||
return 'icon-document';
|
||||
}
|
||||
|
||||
#getPublishedStatus(item: UmbReferenceModel) {
|
||||
return isDocumentReference(item) ? item.published : true;
|
||||
}
|
||||
|
||||
#getContentTypeName(item: UmbReferenceModel) {
|
||||
if (isDocumentReference(item)) {
|
||||
return item.documentType.name;
|
||||
}
|
||||
if (isMediaReference(item)) {
|
||||
return item.mediaType.name;
|
||||
}
|
||||
if (isDefaultReference(item)) {
|
||||
return item.type;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
#getEntityType(item: UmbReferenceModel) {
|
||||
if (isDocumentReference(item)) {
|
||||
return 'document';
|
||||
}
|
||||
if (isMediaReference(item)) {
|
||||
return 'media';
|
||||
}
|
||||
if (isDefaultReference(item)) {
|
||||
return item.type;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
override render() {
|
||||
if (!this._items?.length) return nothing;
|
||||
return html`
|
||||
@@ -168,44 +105,15 @@ export class UmbMediaReferencesWorkspaceInfoAppElement extends UmbLitElement {
|
||||
}
|
||||
|
||||
#renderItems() {
|
||||
if (!this._items?.length) return nothing;
|
||||
if (!this._items) return;
|
||||
return html`
|
||||
<uui-table>
|
||||
<uui-table-head>
|
||||
<uui-table-head-cell><umb-localize key="general_name">Name</umb-localize></uui-table-head-cell>
|
||||
<uui-table-head-cell><umb-localize key="general_status">Status</umb-localize></uui-table-head-cell>
|
||||
<uui-table-head-cell><umb-localize key="general_typeName">Type Name</umb-localize></uui-table-head-cell>
|
||||
<uui-table-head-cell><umb-localize key="general_type">Type</umb-localize></uui-table-head-cell>
|
||||
</uui-table-head>
|
||||
<uui-ref-list>
|
||||
${repeat(
|
||||
this._items,
|
||||
(item) => item.id,
|
||||
(item) => html`
|
||||
<uui-table-row>
|
||||
<uui-table-cell>
|
||||
<uui-ref-node name=${item.name!} href=${this.#getEditPath(item)}>
|
||||
<umb-icon slot="icon" name=${this.#getIcon(item)}></umb-icon>
|
||||
</uui-ref-node>
|
||||
</uui-table-cell>
|
||||
<uui-table-cell>
|
||||
${when(
|
||||
this.#getPublishedStatus(item),
|
||||
() =>
|
||||
html`<uui-tag color="positive" look="secondary"
|
||||
>${this.localize.term('content_published')}</uui-tag
|
||||
>`,
|
||||
() =>
|
||||
html`<uui-tag color="default" look="secondary"
|
||||
>${this.localize.term('content_unpublished')}</uui-tag
|
||||
>`,
|
||||
)}
|
||||
</uui-table-cell>
|
||||
<uui-table-cell>${this.#getContentTypeName(item)}</uui-table-cell>
|
||||
<uui-table-cell>${this.#getEntityType(item)}</uui-table-cell>
|
||||
</uui-table-row>
|
||||
`,
|
||||
(item) => item.unique,
|
||||
(item) => html`<umb-entity-item-ref .item=${item}></umb-entity-item-ref>`,
|
||||
)}
|
||||
</uui-table>
|
||||
</uui-ref-list>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { UMB_MEDIA_REFERENCE_REPOSITORY_ALIAS } from './constants.js';
|
||||
import { UMB_MANAGEMENT_API_DATA_SOURCE_IDENTIFIER } from '@umbraco-cms/backoffice/repository';
|
||||
|
||||
export const manifests: Array<UmbExtensionManifest> = [
|
||||
{
|
||||
@@ -7,4 +8,12 @@ export const manifests: Array<UmbExtensionManifest> = [
|
||||
name: 'Media Reference Repository',
|
||||
api: () => import('./media-reference.repository.js'),
|
||||
},
|
||||
{
|
||||
type: 'dataMapping',
|
||||
alias: 'Umb.DataMapping.ManagementApi.MediaReferenceResponse',
|
||||
name: 'Media Reference Response Management Api Data Mapping',
|
||||
api: () => import('./media-reference-response.management-api.mapping.js'),
|
||||
forDataSource: UMB_MANAGEMENT_API_DATA_SOURCE_IDENTIFIER,
|
||||
forDataModel: 'MediaReferenceResponseModel',
|
||||
},
|
||||
];
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { UMB_MEDIA_ENTITY_TYPE } from '../../entity.js';
|
||||
import type { UmbMediaReferenceModel } from './types.js';
|
||||
import type { MediaReferenceResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
|
||||
import type { UmbDataMapping } from '@umbraco-cms/backoffice/repository';
|
||||
|
||||
export class UmbMediaReferenceResponseManagementApiDataMapping
|
||||
extends UmbControllerBase
|
||||
implements UmbDataMapping<MediaReferenceResponseModel, UmbMediaReferenceModel>
|
||||
{
|
||||
async map(data: MediaReferenceResponseModel): Promise<UmbMediaReferenceModel> {
|
||||
return {
|
||||
entityType: UMB_MEDIA_ENTITY_TYPE,
|
||||
id: data.id,
|
||||
mediaType: {
|
||||
alias: data.mediaType.alias,
|
||||
icon: data.mediaType.icon,
|
||||
name: data.mediaType.name,
|
||||
},
|
||||
name: data.name,
|
||||
// TODO: this is a hardcoded array until the server can return the correct variants array
|
||||
variants: [
|
||||
{
|
||||
culture: null,
|
||||
name: data.name ?? '',
|
||||
},
|
||||
],
|
||||
unique: data.id,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export { UmbMediaReferenceResponseManagementApiDataMapping as api };
|
||||
@@ -1,30 +1,47 @@
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
|
||||
import { MediaService } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import { UmbManagementApiDataMapper } from '@umbraco-cms/backoffice/repository';
|
||||
import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
|
||||
|
||||
/**
|
||||
* @class UmbMediaReferenceServerDataSource
|
||||
* @implements {RepositoryDetailDataSource}
|
||||
*/
|
||||
export class UmbMediaReferenceServerDataSource {
|
||||
#host: UmbControllerHost;
|
||||
|
||||
/**
|
||||
* Creates an instance of UmbMediaReferenceServerDataSource.
|
||||
* @param {UmbControllerHost} host - The controller host for this controller to be appended to
|
||||
* @memberof UmbMediaReferenceServerDataSource
|
||||
*/
|
||||
constructor(host: UmbControllerHost) {
|
||||
this.#host = host;
|
||||
}
|
||||
export class UmbMediaReferenceServerDataSource extends UmbControllerBase {
|
||||
#dataMapper = new UmbManagementApiDataMapper(this);
|
||||
|
||||
/**
|
||||
* Fetches the item for the given id from the server
|
||||
* @param {Array<string>} ids
|
||||
* @param {string} unique - The unique identifier of the item to fetch
|
||||
* @returns {*}
|
||||
* @memberof UmbMediaReferenceServerDataSource
|
||||
*/
|
||||
async getReferencedBy(id: string, skip = 0, take = 20) {
|
||||
return await tryExecuteAndNotify(this.#host, MediaService.getMediaByIdReferencedBy({ id, skip, take }));
|
||||
async getReferencedBy(unique: string, skip = 0, take = 20) {
|
||||
const { data, error } = await tryExecuteAndNotify(
|
||||
this,
|
||||
MediaService.getMediaByIdReferencedBy({ id: unique, skip, take }),
|
||||
);
|
||||
|
||||
if (data) {
|
||||
const promises = data.items.map(async (item) => {
|
||||
return this.#dataMapper.map({
|
||||
forDataModel: item.$type,
|
||||
data: item,
|
||||
fallback: async () => {
|
||||
return {
|
||||
...item,
|
||||
unique: item.id,
|
||||
entityType: 'unknown',
|
||||
};
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
const items = await Promise.all(promises);
|
||||
|
||||
return { data: { items, total: data.total } };
|
||||
}
|
||||
|
||||
return { data, error };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import type { UmbMediaItemVariantModel } from '../../repository/item/types.js';
|
||||
import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity';
|
||||
import type { TrackedReferenceMediaTypeModel } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
|
||||
export interface UmbMediaReferenceModel extends UmbEntityModel {
|
||||
/**
|
||||
* @deprecated use unique instead
|
||||
* @type {string}
|
||||
* @memberof UmbMediaReferenceModel
|
||||
*/
|
||||
id: string;
|
||||
|
||||
/**
|
||||
* @deprecated use name on the variant array instead
|
||||
* @type {(string | null)}
|
||||
* @memberof UmbMediaReferenceModel
|
||||
*/
|
||||
name?: string | null;
|
||||
|
||||
/**
|
||||
* @deprecated use state on variant array instead
|
||||
* @type {boolean}
|
||||
* @memberof UmbMediaReferenceModel
|
||||
*/
|
||||
published?: boolean | null;
|
||||
mediaType: TrackedReferenceMediaTypeModel;
|
||||
variants: Array<UmbMediaItemVariantModel>;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { UMB_MEMBER_ENTITY_TYPE } from '../entity.js';
|
||||
import { UMB_MEMBER_MANAGEMENT_SECTION_ALIAS } from '../../section/constants.js';
|
||||
import { UMB_EDIT_MEMBER_WORKSPACE_PATH_PATTERN } from '../paths.js';
|
||||
import type { UmbMemberItemModel } from './repository/types.js';
|
||||
import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import { customElement, html, ifDefined, nothing, property, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
@@ -17,18 +18,7 @@ export class UmbMemberItemRefElement extends UmbLitElement {
|
||||
return this.#item;
|
||||
}
|
||||
public set item(value: UmbMemberItemModel | undefined) {
|
||||
const oldValue = this.#item;
|
||||
this.#item = value;
|
||||
|
||||
if (!this.#item) {
|
||||
this.#modalRoute?.destroy();
|
||||
return;
|
||||
}
|
||||
if (oldValue?.unique === this.#item.unique) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.#modalRoute?.setUniquePathValue('unique', this.#item.unique);
|
||||
}
|
||||
|
||||
@property({ type: Boolean })
|
||||
@@ -43,8 +33,6 @@ export class UmbMemberItemRefElement extends UmbLitElement {
|
||||
@state()
|
||||
_userHasSectionAccess = false;
|
||||
|
||||
#modalRoute?: any;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
@@ -59,9 +47,7 @@ export class UmbMemberItemRefElement extends UmbLitElement {
|
||||
},
|
||||
]);
|
||||
|
||||
this.#modalRoute = new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL)
|
||||
.addAdditionalPath(UMB_MEMBER_ENTITY_TYPE)
|
||||
.addUniquePaths(['unique'])
|
||||
new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL)
|
||||
.onSetup(() => {
|
||||
return { data: { entityType: UMB_MEMBER_ENTITY_TYPE, preset: {} } };
|
||||
})
|
||||
@@ -71,7 +57,9 @@ export class UmbMemberItemRefElement extends UmbLitElement {
|
||||
}
|
||||
|
||||
#getHref(item: UmbMemberItemModel) {
|
||||
return `${this._editPath}/edit/${item.unique}`;
|
||||
if (!this._editPath) return;
|
||||
const path = UMB_EDIT_MEMBER_WORKSPACE_PATH_PATTERN.generateLocal({ unique: item.unique });
|
||||
return `${this._editPath}/${path}`;
|
||||
}
|
||||
|
||||
override render() {
|
||||
|
||||
@@ -16,3 +16,5 @@ export const UMB_MEMBER_ROOT_WORKSPACE_PATH = UMB_WORKSPACE_PATH_PATTERN.generat
|
||||
export const UMB_CREATE_MEMBER_WORKSPACE_PATH_PATTERN = new UmbPathPattern<{
|
||||
memberTypeUnique: string;
|
||||
}>('create/:memberTypeUnique', UMB_MEMBER_WORKSPACE_PATH);
|
||||
|
||||
export const UMB_EDIT_MEMBER_WORKSPACE_PATH_PATTERN = new UmbPathPattern<{ unique: string }>('edit/:unique');
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { UmbRelationEntityType } from './entity.js';
|
||||
import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity';
|
||||
import type {
|
||||
DefaultReferenceResponseModel,
|
||||
DocumentReferenceResponseModel,
|
||||
@@ -23,6 +24,9 @@ export interface UmbRelationDetailModel {
|
||||
comment: string | null;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||
export interface UmbReferenceItemModel extends UmbEntityModel {}
|
||||
|
||||
export type UmbReferenceModel =
|
||||
| DefaultReferenceResponseModel
|
||||
| DocumentReferenceResponseModel
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { UMB_USER_ENTITY_TYPE } from '../entity.js';
|
||||
import type { UmbUserItemModel } from '../repository/index.js';
|
||||
import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from '../../section/constants.js';
|
||||
import { css, customElement, html, nothing, property, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UMB_EDIT_USER_WORKSPACE_PATH_PATTERN } from '../paths.js';
|
||||
import { css, customElement, html, ifDefined, nothing, property, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router';
|
||||
import { UMB_SECTION_USER_PERMISSION_CONDITION_ALIAS } from '@umbraco-cms/backoffice/section';
|
||||
@@ -17,19 +18,7 @@ export class UmbUserItemRefElement extends UmbLitElement {
|
||||
return this.#item;
|
||||
}
|
||||
public set item(value: UmbUserItemModel | undefined) {
|
||||
const oldValue = this.#item;
|
||||
this.#item = value;
|
||||
|
||||
if (!this.#item) {
|
||||
this.#modalRoute?.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldValue?.unique === this.#item.unique) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.#modalRoute?.setUniquePathValue('unique', this.#item.unique);
|
||||
}
|
||||
|
||||
@property({ type: Boolean })
|
||||
@@ -44,8 +33,6 @@ export class UmbUserItemRefElement extends UmbLitElement {
|
||||
@state()
|
||||
_userHasSectionAccess = false;
|
||||
|
||||
#modalRoute?: any;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
@@ -60,9 +47,7 @@ export class UmbUserItemRefElement extends UmbLitElement {
|
||||
},
|
||||
]);
|
||||
|
||||
this.#modalRoute = new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL)
|
||||
.addAdditionalPath(UMB_USER_ENTITY_TYPE)
|
||||
.addUniquePaths(['unique'])
|
||||
new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL)
|
||||
.onSetup(() => {
|
||||
return { data: { entityType: UMB_USER_ENTITY_TYPE, preset: {} } };
|
||||
})
|
||||
@@ -72,7 +57,9 @@ export class UmbUserItemRefElement extends UmbLitElement {
|
||||
}
|
||||
|
||||
#getHref(item: UmbUserItemModel) {
|
||||
return `${this._editPath}/edit/${item.unique}`;
|
||||
if (!this._editPath) return;
|
||||
const path = UMB_EDIT_USER_WORKSPACE_PATH_PATTERN.generateLocal({ unique: item.unique });
|
||||
return `${this._editPath}/${path}`;
|
||||
}
|
||||
|
||||
override render() {
|
||||
@@ -81,7 +68,7 @@ export class UmbUserItemRefElement extends UmbLitElement {
|
||||
return html`
|
||||
<uui-ref-node-user
|
||||
name=${this.item.name}
|
||||
href=${this.#getHref(this.item)}
|
||||
href=${ifDefined(this.#getHref(this.item))}
|
||||
?readonly=${this.readonly || !this._userHasSectionAccess}
|
||||
?standalone=${this.standalone}>
|
||||
<umb-user-avatar
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { UMB_USER_SECTION_PATHNAME } from '../section/paths.js';
|
||||
import { UMB_USER_ENTITY_TYPE, UMB_USER_ROOT_ENTITY_TYPE } from './entity.js';
|
||||
import { UmbPathPattern } from '@umbraco-cms/backoffice/router';
|
||||
import { UMB_WORKSPACE_PATH_PATTERN } from '@umbraco-cms/backoffice/workspace';
|
||||
|
||||
export const UMB_USER_WORKSPACE_PATH = UMB_WORKSPACE_PATH_PATTERN.generateAbsolute({
|
||||
@@ -11,3 +12,5 @@ export const UMB_USER_ROOT_WORKSPACE_PATH = UMB_WORKSPACE_PATH_PATTERN.generateA
|
||||
sectionName: UMB_USER_SECTION_PATHNAME,
|
||||
entityType: UMB_USER_ROOT_ENTITY_TYPE,
|
||||
});
|
||||
|
||||
export const UMB_EDIT_USER_WORKSPACE_PATH_PATTERN = new UmbPathPattern<{ unique: string }>('edit/:unique');
|
||||
|
||||
Reference in New Issue
Block a user