From 6bfb660d3f9c9a7c2730ca0dab9bed0c69104e89 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Mon, 8 May 2023 12:52:18 +0200 Subject: [PATCH] tags repository and store --- .../src/backoffice/backoffice.element.ts | 1 + .../tags-input/tags-input.element.ts | 16 +++++----- .../tags/property-editor-ui-tags.element.ts | 21 +++++++++++-- .../src/backoffice/tags/index.ts | 10 +++++++ .../tags/repository/tag.repository.ts | 30 +++++++++++++++---- .../backoffice/tags/repository/tag.store.ts | 22 ++++++++++---- .../src/backoffice/tags/umbraco-package.ts | 10 +++++++ 7 files changed, 89 insertions(+), 21 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/tags/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/tags/umbraco-package.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts index 3e90e86cf2..36f83f663c 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts @@ -25,6 +25,7 @@ const CORE_PACKAGES = [ import('./search/umbraco-package'), import('./templating/umbraco-package'), import('./umbraco-news/umbraco-package'), + import('./tags/umbraco-package'), ]; @defineElement('umb-backoffice') diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/core/components/tags-input/tags-input.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/core/components/tags-input/tags-input.element.ts index a90a6c5e0f..2ee6389f8a 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/core/components/tags-input/tags-input.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/core/components/tags-input/tags-input.element.ts @@ -4,15 +4,18 @@ import { customElement, property, query, queryAll, state } from 'lit/decorators. import { FormControlMixin } from '@umbraco-ui/uui-base/lib/mixins'; import { repeat } from 'lit/directives/repeat.js'; import { UUIInputElement, UUIInputEvent, UUITagElement } from '@umbraco-ui/uui'; +import { UmbTagRepository } from '../../../tags/repository/tag.repository'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; -import { TagResource, TagResponseModel } from '@umbraco-cms/backoffice/backend-api'; +import { TagResponseModel } from '@umbraco-cms/backoffice/backend-api'; @customElement('umb-tags-input') export class UmbTagsInputElement extends FormControlMixin(UmbLitElement) { @property({ type: String }) group?: string; + @property({ type: String }) + culture?: string | null; + _items: string[] = []; @property({ type: Array }) public set items(newTags: string[]) { @@ -41,6 +44,8 @@ export class UmbTagsInputElement extends FormControlMixin(UmbLitElement) { @queryAll('.options') private _optionCollection?: HTMLCollectionOf; + #repository = new UmbTagRepository(this); + public focus() { this._tagInput.focus(); } @@ -50,11 +55,8 @@ export class UmbTagsInputElement extends FormControlMixin(UmbLitElement) { } async #getExistingTags(query: string) { - //TODO: Culture - const { data } = await tryExecuteAndNotify( - this, - TagResource.getTag({ query, skip: 0, take: 5, tagGroup: this.group }) - ); + if (!this.group || this.culture === undefined) return; + const { data } = await this.#repository.queryTags(this.group, this.culture, query); if (!data) return; this._matches = data.items; } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/core/property-editors/uis/tags/property-editor-ui-tags.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/core/property-editors/uis/tags/property-editor-ui-tags.element.ts index 2b097b857c..f557538fbb 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/core/property-editors/uis/tags/property-editor-ui-tags.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/core/property-editors/uis/tags/property-editor-ui-tags.element.ts @@ -3,6 +3,7 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, property, state } from 'lit/decorators.js'; import { ifDefined } from 'lit/directives/if-defined.js'; import { UmbTagsInputElement } from '../../../components/tags-input/tags-input.element'; +import { UMB_WORKSPACE_PROPERTY_CONTEXT_TOKEN } from '../../../components/workspace-property/workspace-property.context'; import { UmbPropertyEditorExtensionElement } from '@umbraco-cms/backoffice/extensions-registry'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { DataTypePropertyPresentationModel } from '@umbraco-cms/backoffice/backend-api'; @@ -18,6 +19,10 @@ export class UmbPropertyEditorUITagsElement extends UmbLitElement implements Umb @state() private _group?: string; + @state() + private _culture?: string | null; + //TODO: Use type from VariantID + @property({ type: Array, attribute: false }) public set config(config: Array) { const group = config.find((x) => x.alias === 'group'); @@ -27,6 +32,17 @@ export class UmbPropertyEditorUITagsElement extends UmbLitElement implements Umb if (items) this.value = items.value as Array; } + constructor() { + super(); + this.consumeContext(UMB_WORKSPACE_PROPERTY_CONTEXT_TOKEN, (context) => { + this.observe(context.variantId, (id) => { + if (id && id.culture !== undefined) { + this._culture = id.culture; + } + }); + }); + } + private _onChange(event: CustomEvent) { this.value = ((event.target as UmbTagsInputElement).value as string).split(','); this.dispatchEvent(new CustomEvent('property-value-change')); @@ -35,8 +51,9 @@ export class UmbPropertyEditorUITagsElement extends UmbLitElement implements Umb render() { return html``; + .culture=${this._culture} + .items=${this.value} + @change=${this._onChange}>`; } static styles = [UUITextStyles]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/tags/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/tags/index.ts new file mode 100644 index 0000000000..ca1066dcb4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/tags/index.ts @@ -0,0 +1,10 @@ +import { manifests as repositoryManifests } from './repository/manifests'; + +import { UmbEntrypointOnInit } from '@umbraco-cms/backoffice/extensions-api'; + +export const manifests = [...repositoryManifests]; + +export const onInit: UmbEntrypointOnInit = (host, extensionRegistry) => { + console.log('tags registrer'); + extensionRegistry.registerMany(manifests); +}; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/tags/repository/tag.repository.ts b/src/Umbraco.Web.UI.Client/src/backoffice/tags/repository/tag.repository.ts index 53ed6acf9b..37efa072a2 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/tags/repository/tag.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/tags/repository/tag.repository.ts @@ -2,8 +2,6 @@ import { UmbTagServerDataSource } from './sources/tag.server.data'; import { UmbTagStore, UMB_TAG_STORE_CONTEXT_TOKEN } from './tag.store'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller'; import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api'; -import { UmbNotificationContext, UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification'; -import { TagResponseModel, ProblemDetailsModel } from '@umbraco-cms/backoffice/backend-api'; export class UmbTagRepository { #init!: Promise; @@ -26,16 +24,36 @@ export class UmbTagRepository { } async requestTags( - { query, skip, take, tagGroup, culture } = { query: '', skip: 0, take: 1000, tagGroup: 'default', culture: '' } + tagGroupName: string, + culture: string | null, + { skip, take, query } = { skip: 0, take: 1000, query: '' } ) { await this.#init; - const { data, error } = await this.#dataSource.getCollection({ query, skip, take, tagGroup, culture }); + const requestCulture = culture || ''; + + const { data, error } = await this.#dataSource.getCollection({ + skip, + take, + tagGroup: tagGroupName, + culture: requestCulture, + query, + }); if (data) { - this.#tagStore?.appendItems(data.items); + // TODO: allow to append an array of items to the store + data.items.forEach((x) => this.#tagStore?.append(x)); } - return { data, error, asObservable: () => this.#tagStore?.byGroup(tagGroup) }; + return { data, error, asObservable: () => this.#tagStore!.byQuery(tagGroupName, requestCulture, query) }; + } + + async queryTags( + tagGroupName: string, + culture: string | null, + query: string, + { skip, take } = { skip: 0, take: 1000 } + ) { + return this.requestTags(tagGroupName, culture, { skip, take, query }); } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/tags/repository/tag.store.ts b/src/Umbraco.Web.UI.Client/src/backoffice/tags/repository/tag.store.ts index e0b3e5b3d8..5ddf7e15c9 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/tags/repository/tag.store.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/tags/repository/tag.store.ts @@ -12,6 +12,8 @@ export const UMB_TAG_STORE_CONTEXT_TOKEN = new UmbContextToken('Umb * @description - Data Store for Template Details */ export class UmbTagStore extends UmbStoreBase { + public readonly data = this._data.asObservable(); + /** * Creates an instance of UmbTagStore. * @param {UmbControllerHostElement} host @@ -19,6 +21,7 @@ export class UmbTagStore extends UmbStoreBase { */ constructor(host: UmbControllerHostElement) { super(host, UMB_TAG_STORE_CONTEXT_TOKEN.toString(), new UmbArrayState([], (x) => x.id)); + console.log('Store is open'); } /** @@ -39,15 +42,22 @@ export class UmbTagStore extends UmbStoreBase { return this._data.getObservablePart((x) => x.find((y) => y.id === id)); } - // TODO - byGroup(group: TagResponseModel['group']) { - return this._data.getObservablePart((x) => x.filter((y) => y.group === group)); + items(group: TagResponseModel['group'], culture: string) { + return this._data.getObservablePart((items) => + items.filter((item) => item.group === group && item.culture === culture) + ); } - // TODO - byText(text: string) { + //TODO Skriv god kommentar til filter/exclude + + byQuery(group: TagResponseModel['group'], culture: string, query: string) { return this._data.getObservablePart((items) => - items.filter((item) => item.text?.toLocaleLowerCase().includes(text.toLocaleLowerCase())) + items.filter( + (item) => + item.group === group && + item.culture === culture && + item.query?.toLocaleLowerCase().includes(query.toLocaleLowerCase()) + ) ); } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/tags/umbraco-package.ts b/src/Umbraco.Web.UI.Client/src/backoffice/tags/umbraco-package.ts new file mode 100644 index 0000000000..6f6c4e8434 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/tags/umbraco-package.ts @@ -0,0 +1,10 @@ +export const name = 'Umbraco.Core.UserManagement'; +export const version = '0.0.1'; +export const extensions = [ + { + name: 'Tags Management Entry Point', + alias: 'Umb.EntryPoint.TagsManagement', + type: 'entryPoint', + loader: () => import('./index'), + }, +];