From 86c357630e60ad53ed4fcf6d7d5ec14f9f7d48e1 Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Tue, 9 Apr 2024 16:45:51 +0200 Subject: [PATCH 01/79] redesign --- .../search-modal/search-modal.element.ts | 216 +++++++++--------- 1 file changed, 112 insertions(+), 104 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts index 98a0c11f88..a87ef068bf 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts @@ -14,7 +14,6 @@ export type SearchItem = { name: string; icon?: string; href: string; - parent: string; url?: string; }; export type SearchGroupItem = { @@ -30,7 +29,20 @@ export class UmbSearchModalElement extends LitElement { private _search = ''; @state() - private _groups: Array = []; + private _searchResults: Array = []; + + @state() + private searchTags: Array = [ + 'Data Type', + 'Document', + 'Document Type', + 'Media', + 'Media Type', + 'Member', + 'Member Type', + 'Users', + 'User Group', + ]; connectedCallback() { super.connectedCallback(); @@ -44,35 +56,24 @@ export class UmbSearchModalElement extends LitElement { const target = event.target as HTMLInputElement; this._search = target.value; - this.#updateGroups(); + this.#updateSearchResults(); } #onClearSearch() { this._search = ''; this._input.value = ''; this._input.focus(); - this.#updateGroups(); + this.#updateSearchResults(); } - #updateGroups() { - const filtered = this.#mockData.filter((item) => { - return item.name.toLowerCase().includes(this._search.toLowerCase()); - }); - - const grouped: Array = filtered.reduce((acc, item) => { - const group = acc.find((group) => group.name === item.parent); - if (group) { - group.items.push(item); - } else { - acc.push({ - name: item.parent, - items: [item], - }); - } - return acc; - }, [] as Array); - - this._groups = grouped; + #updateSearchResults() { + if (this._search) { + this._searchResults = this.#mockApi.getDocuments.filter((item) => + item.name.toLowerCase().includes(this._search.toLowerCase()), + ); + } else { + this._searchResults = []; + } } render() { @@ -87,31 +88,38 @@ export class UmbSearchModalElement extends LitElement { type="text" placeholder="Search..." autocomplete="off" /> -
+
+ + ${this.#renderSearchTags()} ${this._search - ? html`
- ${this._groups.length > 0 - ? repeat( - this._groups, - (group) => group.name, - (group) => this.#renderGroup(group.name, group.items), - ) - : html`
Only mock data for now Search for blog
`} -
` + ? html`
${this._searchResults.length > 0 ? this.#renderResults() : this.#renderNoResults()}
` : nothing} `; } - #renderGroup(name: string, items: Array) { - return html` -
-
${name}
-
${repeat(items, (item) => item.name, this.#renderItem.bind(this))}
-
- `; + #renderSearchTags() { + return html`
+ ${repeat( + this.searchTags, + (provider) => provider, + (provider) => html`
${provider}
`, + )} +
`; + } + + #renderResults() { + return repeat( + this._searchResults, + (item) => item.name, + (item) => this.#renderItem(item), + ); + } + + #renderNoResults() { + return html`
Only mock data for now Search for blog
`; } #renderItem(item: SearchItem) { @@ -139,63 +147,77 @@ export class UmbSearchModalElement extends LitElement { `; } - #mockData: Array = [ - { - name: 'Blog', - href: '#', - icon: 'icon-thumbnail-list', - parent: 'Content', - url: '/blog/', - }, - { - name: 'Popular blogs', - href: '#', - icon: 'icon-article', - parent: 'Content', - url: '/blog/popular-blogs/', - }, - { - name: 'How to write a blog', - href: '#', - icon: 'icon-article', - parent: 'Content', - url: '/blog/how-to-write-a-blog/', - }, - { - name: 'Blog hero', - href: '#', - icon: 'icon-picture', - parent: 'Media', - }, - { - name: 'Contact form for blog', - href: '#', - parent: 'Document Types', - }, - { - name: 'Blog', - href: '#', - parent: 'Document Types', - }, - { - name: 'Blog link item', - href: '#', - parent: 'Document Types', - }, - ]; + #mockApi = { + getDocuments: [ + { + name: 'Blog', + href: '#', + icon: 'icon-thumbnail-list', + url: '/blog/', + }, + { + name: 'Popular blogs', + href: '#', + icon: 'icon-article', + url: '/blog/popular-blogs/', + }, + { + name: 'How to write a blog', + href: '#', + icon: 'icon-article', + url: '/blog/how-to-write-a-blog/', + }, + ], + getMedia: [ + { + name: 'Blog hero', + href: '#', + icon: 'icon-picture', + }, + ], + getDocumentTypes: [ + { + name: 'Contact form for blog', + href: '#', + }, + { + name: 'Blog', + href: '#', + }, + { + name: 'Blog link item', + href: '#', + }, + ], + }; static styles = [ UmbTextStyles, css` + #search-tags { + display: flex; + flex-wrap: wrap; + gap: var(--uui-size-space-2); + padding: 0 var(--uui-size-space-5); + padding-bottom: var(--uui-size-space-2); + } + .search-tag { + padding: var(--uui-size-space-3) var(--uui-size-space-4); + background: var(--uui-color-surface-alt); + line-height: 1; + white-space: nowrap; + border-radius: var(--uui-border-radius); + } :host { display: flex; flex-direction: column; - width: min(500px, 100vw); + width: min(600px, 100vw); height: 100%; - background-color: var(--uui-color-background); + background-color: var(--uui-color-surface); box-sizing: border-box; color: var(--uui-color-text); font-size: 1rem; + padding-bottom: var(--uui-size-space-2); } input { all: unset; @@ -236,31 +258,16 @@ export class UmbSearchModalElement extends LitElement { #main { display: flex; flex-direction: column; - padding: 0px var(--uui-size-space-6) var(--uui-size-space-5) var(--uui-size-space-6); + /* padding: 0px var(--uui-size-space-6) var(--uui-size-space-5) var(--uui-size-space-6); */ height: 100%; - border-top: 1px solid var(--uui-color-border); - } - .group { - margin-top: var(--uui-size-space-4); - } - .group-name { - font-weight: 600; - margin-bottom: var(--uui-size-space-1); - } - .group-items { - display: flex; - flex-direction: column; - gap: var(--uui-size-space-3); } .item { background: var(--uui-color-surface); - border: 1px solid var(--uui-color-border); - padding: var(--uui-size-space-3) var(--uui-size-space-4); + padding: var(--uui-size-space-3) var(--uui-size-space-5); border-radius: var(--uui-border-radius); color: var(--uui-color-interactive); display: grid; grid-template-columns: var(--uui-size-space-6) 1fr var(--uui-size-space-5); - height: min-content; align-items: center; } .item:hover { @@ -309,6 +316,7 @@ export class UmbSearchModalElement extends LitElement { width: 100%; margin-top: var(--uui-size-space-5); color: var(--uui-color-text-alt); + margin: var(--uui-size-space-5) 0; } `, ]; From 66db0d876167a236b0bfb815882241ea224ebffa Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Wed, 10 Apr 2024 13:25:10 +0200 Subject: [PATCH 02/79] designing --- .../search-modal/search-modal.element.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts index a87ef068bf..f1aeb80b7d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts @@ -44,6 +44,9 @@ export class UmbSearchModalElement extends LitElement { 'User Group', ]; + @state() + private _activeSearchTag = 'Document'; + connectedCallback() { super.connectedCallback(); @@ -104,8 +107,9 @@ export class UmbSearchModalElement extends LitElement { return html`
${repeat( this.searchTags, - (provider) => provider, - (provider) => html`
${provider}
`, + (searchTag) => searchTag, + (provider) => + html`
${provider}
`, )}
`; } @@ -207,6 +211,16 @@ export class UmbSearchModalElement extends LitElement { line-height: 1; white-space: nowrap; border-radius: var(--uui-border-radius); + color: var(--uui-color-interactive); + cursor: pointer; + } + .search-tag:hover { + background: var(--uui-color-surface-emphasis); + color: var(--uui-color-interactive-emphasis); + } + .search-tag.active { + background: var(--uui-color-surface-emphasis); + color: var(--uui-color-interactive-emphasis); } :host { display: flex; From da046825977a03af91b57739858f525a8a9fc678 Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Thu, 11 Apr 2024 09:58:08 +0200 Subject: [PATCH 03/79] init manifest --- .../core/extension-registry/models/index.ts | 21 +++++++++++-------- .../models/search-provider.model.ts | 17 +++++++++++++++ 2 files changed, 29 insertions(+), 9 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/search-provider.model.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts index 5729a909c2..60c14d9ae9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts @@ -61,6 +61,7 @@ import type { ManifestEntityUserPermission } from './entity-user-permission.mode import type { ManifestGranularUserPermission } from './user-granular-permission.model.js'; import type { ManifestCollectionAction } from './collection-action.model.js'; import type { ManifestMfaLoginProvider } from './mfa-login-provider.model.js'; +import type { ManifestSearchProvider } from './search-provider.model.js'; import type { ManifestBase, ManifestBundle, @@ -70,15 +71,16 @@ import type { export type * from './auth-provider.model.js'; export type * from './block-editor-custom-view.model.js'; -export type * from './collection.models.js'; export type * from './collection-action.model.js'; export type * from './collection-view.model.js'; +export type * from './collection.models.js'; export type * from './current-user-action.model.js'; export type * from './dashboard-collection.model.js'; export type * from './dashboard.model.js'; export type * from './dynamic-root.model.js'; export type * from './entity-action.model.js'; export type * from './entity-bulk-action.model.js'; +export type * from './entity-user-permission.model.js'; export type * from './external-login-provider.model.js'; export type * from './global-context.model.js'; export type * from './header-app.model.js'; @@ -92,6 +94,7 @@ export type * from './package-view.model.js'; export type * from './property-action.model.js'; export type * from './property-editor.model.js'; export type * from './repository.model.js'; +export type * from './search-provider.model.js'; export type * from './section-sidebar-app.model.js'; export type * from './section-view.model.js'; export type * from './section.model.js'; @@ -101,10 +104,9 @@ export type * from './tinymce-plugin.model.js'; export type * from './tree-item.model.js'; export type * from './tree.model.js'; export type * from './user-granular-permission.model.js'; -export type * from './entity-user-permission.model.js'; export type * from './user-profile-app.model.js'; -export type * from './workspace-action.model.js'; export type * from './workspace-action-menu-item.model.js'; +export type * from './workspace-action.model.js'; export type * from './workspace-context.model.js'; export type * from './workspace-footer-app.model.js'; export type * from './workspace-view.model.js'; @@ -140,27 +142,30 @@ export type ManifestWorkspaceViews = ManifestWorkspaceView | ManifestWorkspaceVi export type ManifestTypes = | ManifestAuthProvider - | ManifestBundle | ManifestBlockEditorCustomView + | ManifestBundle | ManifestCollection - | ManifestCollectionView | ManifestCollectionAction + | ManifestCollectionView + | ManifestCondition | ManifestCurrentUserAction | ManifestCurrentUserActionDefaultKind - | ManifestCondition | ManifestDashboard | ManifestDashboardCollection | ManifestDynamicRootOrigin | ManifestDynamicRootQueryStep | ManifestEntityActions | ManifestEntityBulkAction + | ManifestEntityUserPermission | ManifestEntryPoint | ManifestExternalLoginProvider | ManifestGlobalContext + | ManifestGranularUserPermission | ManifestHeaderApp | ManifestHeaderAppButtonKind | ManifestHealthCheck | ManifestItemStore + | ManifestLocalization | ManifestMenu | ManifestMenuItem | ManifestMenuItemTreeKind @@ -171,6 +176,7 @@ export type ManifestTypes = | ManifestPropertyEditorSchema | ManifestPropertyEditorUi | ManifestRepository + | ManifestSearchProvider | ManifestSection | ManifestSectionSidebarApp | ManifestSectionSidebarAppMenuKind @@ -178,7 +184,6 @@ export type ManifestTypes = | ManifestStore | ManifestTheme | ManifestTinyMcePlugin - | ManifestLocalization | ManifestTree | ManifestTreeItem | ManifestTreeStore @@ -189,6 +194,4 @@ export type ManifestTypes = | ManifestWorkspaceFooterApps | ManifestWorkspaces | ManifestWorkspaceViews - | ManifestEntityUserPermission - | ManifestGranularUserPermission | ManifestBase; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/search-provider.model.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/search-provider.model.ts new file mode 100644 index 0000000000..c59704ef48 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/search-provider.model.ts @@ -0,0 +1,17 @@ +import type { ManifestApi } from '@umbraco-cms/backoffice/extension-api'; + +/** + * Represents an search provider that can be used to search. + */ +export interface ManifestSearchProvider extends ManifestApi { + type: 'searchProvider'; + + meta?: MetaSearchProvider; +} + +export interface MetaSearchProvider { + /** + * The label of the provider that is shown to the user. + */ + label?: string; +} From 9fcb5e5e315383a7432323e6919ac6d79a1ab3df Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Thu, 11 Apr 2024 09:58:18 +0200 Subject: [PATCH 04/79] work --- .../search-modal/search-modal.element.ts | 48 +++++++------------ 1 file changed, 17 insertions(+), 31 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts index f1aeb80b7d..b764ed2d4b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts @@ -62,11 +62,8 @@ export class UmbSearchModalElement extends LitElement { this.#updateSearchResults(); } - #onClearSearch() { - this._search = ''; - this._input.value = ''; - this._input.focus(); - this.#updateSearchResults(); + #onSearchTagClick(tag: string) { + this._activeSearchTag = tag; } #updateSearchResults() { @@ -91,9 +88,6 @@ export class UmbSearchModalElement extends LitElement { type="text" placeholder="Search..." autocomplete="off" /> - ${this.#renderSearchTags()} @@ -108,8 +102,13 @@ export class UmbSearchModalElement extends LitElement { ${repeat( this.searchTags, (searchTag) => searchTag, - (provider) => - html`
${provider}
`, + (searchTag) => + html``, )} `; } @@ -213,6 +212,7 @@ export class UmbSearchModalElement extends LitElement { border-radius: var(--uui-border-radius); color: var(--uui-color-interactive); cursor: pointer; + border: 2px solid transparent; } .search-tag:hover { background: var(--uui-color-surface-emphasis); @@ -221,6 +221,7 @@ export class UmbSearchModalElement extends LitElement { .search-tag.active { background: var(--uui-color-surface-emphasis); color: var(--uui-color-interactive-emphasis); + border-color: var(--uui-color-focus); } :host { display: flex; @@ -238,32 +239,18 @@ export class UmbSearchModalElement extends LitElement { height: 100%; width: 100%; } - #search-icon, - #close-icon { + button { + font-family: unset; + font-size: unset; + cursor: pointer; + } + #search-icon { display: flex; align-items: center; justify-content: center; aspect-ratio: 1; height: 100%; } - #close-icon { - padding: 0 var(--uui-size-space-4); - } - #close-icon > button { - background: var(--uui-color-surface-alt); - border: 1px solid var(--uui-color-border); - padding: 3px 6px 4px 6px; - line-height: 1; - border-radius: 3px; - color: var(--uui-color-text-alt); - font-weight: 800; - font-size: 12px; - cursor: pointer; - } - #close-icon > button:hover { - border-color: var(--uui-color-focus); - color: var(--uui-color-focus); - } #top { background-color: var(--uui-color-surface); display: flex; @@ -272,7 +259,6 @@ export class UmbSearchModalElement extends LitElement { #main { display: flex; flex-direction: column; - /* padding: 0px var(--uui-size-space-6) var(--uui-size-space-5) var(--uui-size-space-6); */ height: 100%; } .item { From 31648ac5d8e5f9191b1793c122bf632f02307bf3 Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Thu, 11 Apr 2024 10:24:31 +0200 Subject: [PATCH 05/79] manifests --- .../src/packages/data-type/manifests.ts | 14 +++++++------ .../search/data-type.search-provider.ts | 11 ++++++++++ .../packages/data-type/search/manifests.ts | 14 +++++++++++++ .../packages/documents/documents/manifests.ts | 10 ++++++---- .../search/document.search-provider.ts | 11 ++++++++++ .../documents/documents/search/manifests.ts | 14 +++++++++++++ .../search-modal/search-modal.element.ts | 20 ++++++++++++++++++- 7 files changed, 83 insertions(+), 11 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/data-type/search/data-type.search-provider.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/data-type/search/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document.search-provider.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/manifests.ts index 907c67310c..06dbf00ad2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/manifests.ts @@ -1,17 +1,19 @@ +import { manifests as collectionManifests } from './collection/manifests.js'; import { manifests as entityActions } from './entity-actions/manifests.js'; -import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as menuManifests } from './menu/manifests.js'; +import { manifests as modalManifests } from './modals/manifests.js'; +import { manifests as repositoryManifests } from './repository/manifests.js'; +import { manifests as searchProviderManifests } from './search/manifests.js'; import { manifests as treeManifests } from './tree/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; -import { manifests as modalManifests } from './modals/manifests.js'; -import { manifests as collectionManifests } from './collection/manifests.js'; export const manifests = [ + ...collectionManifests, ...entityActions, - ...repositoryManifests, ...menuManifests, + ...modalManifests, + ...repositoryManifests, + ...searchProviderManifests, ...treeManifests, ...workspaceManifests, - ...modalManifests, - ...collectionManifests, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/search/data-type.search-provider.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/search/data-type.search-provider.ts new file mode 100644 index 0000000000..e29aed4eff --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/search/data-type.search-provider.ts @@ -0,0 +1,11 @@ +import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; + +export class UmbDataTypeSearchProvider implements UmbApi { + constructor() { + console.log('UmbDataTypeSearchProvider hello world'); + } + + destroy(): void { + throw new Error('Method not implemented.'); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/search/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/search/manifests.ts new file mode 100644 index 0000000000..3b79a769dc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/search/manifests.ts @@ -0,0 +1,14 @@ +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + name: 'Data Type Search Provider', + alias: 'Umb.SearchProvider.DataType', + type: 'searchProvider', + api: () => import('./data-type.search-provider.js'), + weight: 900, + meta: { + label: 'Data Types', + }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/manifests.ts index 1d2db8ffa2..2718c6c38e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/manifests.ts @@ -1,29 +1,31 @@ import { manifests as collectionManifests } from './collection/manifests.js'; import { manifests as entityActionManifests } from './entity-actions/manifests.js'; import { manifests as entityBulkActionManifests } from './entity-bulk-actions/manifests.js'; -import { manifests as modalManifests } from './modals/manifests.js'; +import { manifests as globalContextManifests } from './global-contexts/manifests.js'; import { manifests as menuManifests } from './menu/manifests.js'; +import { manifests as modalManifests } from './modals/manifests.js'; import { manifests as propertyEditorManifests } from './property-editors/manifests.js'; import { manifests as recycleBinManifests } from './recycle-bin/manifests.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; +import { manifests as searchProviderManifests } from './search/manifests.js'; import { manifests as trackedReferenceManifests } from './reference/manifests.js'; import { manifests as treeManifests } from './tree/manifests.js'; import { manifests as userPermissionManifests } from './user-permissions/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; -import { manifests as globalContextManifests } from './global-contexts/manifests.js'; export const manifests = [ ...collectionManifests, ...entityActionManifests, ...entityBulkActionManifests, - ...modalManifests, + ...globalContextManifests, ...menuManifests, + ...modalManifests, ...propertyEditorManifests, ...recycleBinManifests, ...repositoryManifests, + ...searchProviderManifests, ...trackedReferenceManifests, ...treeManifests, ...userPermissionManifests, ...workspaceManifests, - ...globalContextManifests, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document.search-provider.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document.search-provider.ts new file mode 100644 index 0000000000..23bbc2ab10 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document.search-provider.ts @@ -0,0 +1,11 @@ +import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; + +export class UmbDocumentSearchProvider implements UmbApi { + constructor() { + console.log('UmbDocumentSearchProvider hello world'); + } + + destroy(): void { + throw new Error('Method not implemented.'); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/manifests.ts new file mode 100644 index 0000000000..3aea6f690d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/manifests.ts @@ -0,0 +1,14 @@ +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + name: 'Document Search Provider', + alias: 'Umb.SearchProvider.Document', + type: 'searchProvider', + api: () => import('./document.search-provider.js'), + weight: 1000, + meta: { + label: 'Documents', + }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts index b764ed2d4b..85d7dbff70 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts @@ -9,6 +9,9 @@ import { query, state, } from '@umbraco-cms/backoffice/external/lit'; +import { ManifestSearchProvider, umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbExtensionsManifestInitializer } from '@umbraco-cms/backoffice/extension-api'; export type SearchItem = { name: string; @@ -21,7 +24,7 @@ export type SearchGroupItem = { items: Array; }; @customElement('umb-search-modal') -export class UmbSearchModalElement extends LitElement { +export class UmbSearchModalElement extends UmbLitElement { @query('input') private _input!: HTMLInputElement; @@ -47,6 +50,21 @@ export class UmbSearchModalElement extends LitElement { @state() private _activeSearchTag = 'Document'; + /** + * + */ + constructor() { + super(); + + this.#observeViews(); + } + + #observeViews() { + return new UmbExtensionsManifestInitializer(this, umbExtensionsRegistry, 'searchProvider', null, (providers) => { + this.searchTags = providers.map((provider) => provider.manifest.meta?.label || provider.manifest.name); + }); + } + connectedCallback() { super.connectedCallback(); From 2972cb82098bd930a58a12af002fb738f7aac141 Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Thu, 11 Apr 2024 11:04:15 +0200 Subject: [PATCH 06/79] search provider extension --- .../search/data-type.search-provider.ts | 6 +++ .../search/document-search.repository.ts | 19 +++++++ .../search/document.search-provider.ts | 13 +++-- .../documents/documents/search/manifests.ts | 9 ++++ .../search/rollback.server.data-source.ts | 37 ++++++++++++++ .../documents/documents/search/types.ts | 3 ++ .../search-modal/search-modal.element.ts | 50 +++++++++++++------ 7 files changed, 120 insertions(+), 17 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search.repository.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/rollback.server.data-source.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/search/data-type.search-provider.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/search/data-type.search-provider.ts index e29aed4eff..4a13750fd6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/search/data-type.search-provider.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/search/data-type.search-provider.ts @@ -5,7 +5,13 @@ export class UmbDataTypeSearchProvider implements UmbApi { console.log('UmbDataTypeSearchProvider hello world'); } + search(): void { + alert('search'); + } + destroy(): void { throw new Error('Method not implemented.'); } } + +export { UmbDataTypeSearchProvider as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search.repository.ts new file mode 100644 index 0000000000..8d4c9e4d53 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search.repository.ts @@ -0,0 +1,19 @@ +import { UmbDocumentSearchServerDataSource } from './rollback.server.data-source.js'; +import type { UmbSearchRequestArgs } from './types.js'; +import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; + +export class UmbDocumentSearchRepository extends UmbControllerBase implements UmbApi { + #dataSource: UmbDocumentSearchServerDataSource; + + constructor(host: UmbControllerHost) { + super(host); + + this.#dataSource = new UmbDocumentSearchServerDataSource(this); + } + + async search(args: UmbSearchRequestArgs) { + return await this.#dataSource.search(args); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document.search-provider.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document.search-provider.ts index 23bbc2ab10..4072442ab3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document.search-provider.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document.search-provider.ts @@ -1,11 +1,18 @@ +import { UmbDocumentSearchRepository } from './document-search.repository.js'; +import type { UmbSearchRequestArgs } from './types.js'; import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; +import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; -export class UmbDocumentSearchProvider implements UmbApi { - constructor() { - console.log('UmbDocumentSearchProvider hello world'); +export class UmbDocumentSearchProvider extends UmbControllerBase implements UmbApi { + #repository = new UmbDocumentSearchRepository(this); + + search(args: UmbSearchRequestArgs) { + return this.#repository.search(args); } destroy(): void { throw new Error('Method not implemented.'); } } + +export { UmbDocumentSearchProvider as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/manifests.ts index 3aea6f690d..e138c643cd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/manifests.ts @@ -11,4 +11,13 @@ export const manifests: Array = [ label: 'Documents', }, }, + { + name: 'Document Search Result Item ', + alias: 'Umb.SearchResultItem.Document', + type: 'searchResultItem', + element: () => import('./document-search-result-item.element.js'), + meta: { + label: 'Documents', + }, + }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/rollback.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/rollback.server.data-source.ts new file mode 100644 index 0000000000..05e7649eed --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/rollback.server.data-source.ts @@ -0,0 +1,37 @@ +import type { UmbSearchRequestArgs } from './types.js'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { DocumentService } from '@umbraco-cms/backoffice/external/backend-api'; +import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; + +/** + * A data source for the Rollback that fetches data from the server + * @export + * @class UmbDocumentSearchServerDataSource + * @implements {RepositoryDetailDataSource} + */ +export class UmbDocumentSearchServerDataSource { + #host: UmbControllerHost; + + /** + * Creates an instance of UmbDocumentSearchServerDataSource. + * @param {UmbControllerHost} host + * @memberof UmbDocumentSearchServerDataSource + */ + constructor(host: UmbControllerHost) { + this.#host = host; + } + + /** + * Get a list of versions for a document + * @return {*} + * @memberof UmbDocumentSearchServerDataSource + */ + search(args: UmbSearchRequestArgs) { + return tryExecuteAndNotify( + this.#host, + DocumentService.getItemDocumentSearch({ + query: args.query, + }), + ); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/types.ts new file mode 100644 index 0000000000..20267d66ab --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/types.ts @@ -0,0 +1,3 @@ +export type UmbSearchRequestArgs = { + query: string; +}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts index 85d7dbff70..6c8b403142 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts @@ -11,7 +11,7 @@ import { } from '@umbraco-cms/backoffice/external/lit'; import { ManifestSearchProvider, umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UmbExtensionsManifestInitializer } from '@umbraco-cms/backoffice/extension-api'; +import { UmbExtensionsManifestInitializer, createExtensionApi } from '@umbraco-cms/backoffice/extension-api'; export type SearchItem = { name: string; @@ -50,6 +50,15 @@ export class UmbSearchModalElement extends UmbLitElement { @state() private _activeSearchTag = 'Document'; + @state() + private _searchProviders: Array<{ + name: string; + providerPromise: any; + alias: string; + }> = []; + + #currentProvider: any; + /** * */ @@ -60,8 +69,12 @@ export class UmbSearchModalElement extends UmbLitElement { } #observeViews() { - return new UmbExtensionsManifestInitializer(this, umbExtensionsRegistry, 'searchProvider', null, (providers) => { - this.searchTags = providers.map((provider) => provider.manifest.meta?.label || provider.manifest.name); + new UmbExtensionsManifestInitializer(this, umbExtensionsRegistry, 'searchProvider', null, (providers) => { + this._searchProviders = providers.map((provider) => ({ + name: provider.manifest.meta?.label || provider.manifest.name, + providerPromise: createExtensionApi(this, provider.manifest), + alias: provider.alias, + })); }); } @@ -80,15 +93,24 @@ export class UmbSearchModalElement extends UmbLitElement { this.#updateSearchResults(); } - #onSearchTagClick(tag: string) { - this._activeSearchTag = tag; + async #onSearchTagClick(searchProvider: any) { + console.log(searchProvider); + const api = await searchProvider.providerPromise; + + this.#currentProvider = api; + this._activeSearchTag = searchProvider.alias; } #updateSearchResults() { if (this._search) { - this._searchResults = this.#mockApi.getDocuments.filter((item) => - item.name.toLowerCase().includes(this._search.toLowerCase()), - ); + const { data, error } = this.#currentProvider.search({ + query: this._search, + }); + + console.log(data, error); + // this._searchResults = this.#mockApi.getDocuments.filter((item) => + // item.name.toLowerCase().includes(this._search.toLowerCase()), + // ); } else { this._searchResults = []; } @@ -118,14 +140,14 @@ export class UmbSearchModalElement extends UmbLitElement { #renderSearchTags() { return html`
${repeat( - this.searchTags, - (searchTag) => searchTag, - (searchTag) => + this._searchProviders, + (searchProvider) => searchProvider, + (searchProvider) => html``, )}
`; From a27ff6ef045b5b9d53130718cbcb06b00b7672b8 Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Thu, 11 Apr 2024 11:37:28 +0200 Subject: [PATCH 07/79] document search --- .../core/extension-registry/models/index.ts | 3 ++ .../models/search-result-item.model.ts | 9 +++++ .../document-search-result-item.element.ts | 22 ++++++++++ .../search/document-search.repository.ts | 6 +-- ... => document-search.server.data-source.ts} | 33 ++++++++++++++- .../documents/documents/search/manifests.ts | 5 +-- .../search-modal/search-modal.element.ts | 40 ++++++++++--------- .../search-result-item.element.ts | 21 ++++++++++ 8 files changed, 113 insertions(+), 26 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/search-result-item.model.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search-result-item.element.ts rename src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/{rollback.server.data-source.ts => document-search.server.data-source.ts} (50%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-result-item.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts index 60c14d9ae9..d01657f8ef 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts @@ -62,6 +62,7 @@ import type { ManifestGranularUserPermission } from './user-granular-permission. import type { ManifestCollectionAction } from './collection-action.model.js'; import type { ManifestMfaLoginProvider } from './mfa-login-provider.model.js'; import type { ManifestSearchProvider } from './search-provider.model.js'; +import type { ManifestSearchResultItem } from './search-result-item.model.js'; import type { ManifestBase, ManifestBundle, @@ -95,6 +96,7 @@ export type * from './property-action.model.js'; export type * from './property-editor.model.js'; export type * from './repository.model.js'; export type * from './search-provider.model.js'; +export type * from './search-result-item.model.js'; export type * from './section-sidebar-app.model.js'; export type * from './section-view.model.js'; export type * from './section.model.js'; @@ -177,6 +179,7 @@ export type ManifestTypes = | ManifestPropertyEditorUi | ManifestRepository | ManifestSearchProvider + | ManifestSearchResultItem | ManifestSection | ManifestSectionSidebarApp | ManifestSectionSidebarAppMenuKind diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/search-result-item.model.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/search-result-item.model.ts new file mode 100644 index 0000000000..26d3b338d1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/search-result-item.model.ts @@ -0,0 +1,9 @@ +import type { ManifestElement } from '@umbraco-cms/backoffice/extension-api'; + +/** + * Represents a search result element. + */ +export interface ManifestSearchResultItem extends ManifestElement { + type: 'searchResultItem'; + forEntityTypes: Array; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search-result-item.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search-result-item.element.ts new file mode 100644 index 0000000000..e016ddf597 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search-result-item.element.ts @@ -0,0 +1,22 @@ +import type { UmbDocumentItemModel } from '../repository/index.js'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { customElement, html, property } from '@umbraco-cms/backoffice/external/lit'; + +const elementName = 'umb-document-search-result-item'; +@customElement(elementName) +export class UmbDocumentSearchResultItemElement extends UmbLitElement { + @property({ attribute: false }) + item?: UmbDocumentItemModel; + + render() { + return html`HELLO WORLD ${this.item?.unique}`; + } +} + +export { UmbDocumentSearchResultItemElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbDocumentSearchResultItemElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search.repository.ts index 8d4c9e4d53..a852a74409 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search.repository.ts @@ -1,4 +1,4 @@ -import { UmbDocumentSearchServerDataSource } from './rollback.server.data-source.js'; +import { UmbDocumentSearchServerDataSource } from './document-search.server.data-source.js'; import type { UmbSearchRequestArgs } from './types.js'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; @@ -13,7 +13,7 @@ export class UmbDocumentSearchRepository extends UmbControllerBase implements Um this.#dataSource = new UmbDocumentSearchServerDataSource(this); } - async search(args: UmbSearchRequestArgs) { - return await this.#dataSource.search(args); + search(args: UmbSearchRequestArgs) { + return this.#dataSource.search(args); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/rollback.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search.server.data-source.ts similarity index 50% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/rollback.server.data-source.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search.server.data-source.ts index 05e7649eed..ae8446097a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/rollback.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search.server.data-source.ts @@ -2,6 +2,7 @@ import type { UmbSearchRequestArgs } from './types.js'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { DocumentService } from '@umbraco-cms/backoffice/external/backend-api'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { UMB_DOCUMENT_ENTITY_TYPE } from '../entity.js'; /** * A data source for the Rollback that fetches data from the server @@ -26,12 +27,40 @@ export class UmbDocumentSearchServerDataSource { * @return {*} * @memberof UmbDocumentSearchServerDataSource */ - search(args: UmbSearchRequestArgs) { - return tryExecuteAndNotify( + async search(args: UmbSearchRequestArgs) { + const { data, error } = await tryExecuteAndNotify( this.#host, DocumentService.getItemDocumentSearch({ query: args.query, }), ); + + if (data) { + const mappedItems = data.items.map((item) => { + return { + entityType: UMB_DOCUMENT_ENTITY_TYPE, + unique: item.id, + isTrashed: item.isTrashed, + isProtected: item.isProtected, + documentType: { + unique: item.documentType.id, + icon: item.documentType.icon, + collection: item.documentType.collection ? { unique: item.documentType.collection.id } : null, + }, + variants: item.variants.map((variant) => { + return { + culture: variant.culture || null, + name: variant.name, + state: variant.state, + }; + }), + name: item.variants[0]?.name, // TODO: this is not correct. We need to get it from the variants. This is a temp solution. + }; + }); + + return { data: { items: mappedItems, total: data.total } }; + } + + return { error }; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/manifests.ts index e138c643cd..4420f0747f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_DOCUMENT_ENTITY_TYPE } from '../entity.js'; import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ @@ -16,8 +17,6 @@ export const manifests: Array = [ alias: 'Umb.SearchResultItem.Document', type: 'searchResultItem', element: () => import('./document-search-result-item.element.js'), - meta: { - label: 'Documents', - }, + forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts index 6c8b403142..dc3df95850 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts @@ -1,23 +1,14 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { - css, - html, - LitElement, - nothing, - repeat, - customElement, - query, - state, -} from '@umbraco-cms/backoffice/external/lit'; -import { ManifestSearchProvider, umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; +import { css, html, nothing, repeat, customElement, query, state } from '@umbraco-cms/backoffice/external/lit'; +import type { ManifestSearchResultItem } from '@umbraco-cms/backoffice/extension-registry'; +import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbExtensionsManifestInitializer, createExtensionApi } from '@umbraco-cms/backoffice/extension-api'; +import './search-result-item.element.js'; + export type SearchItem = { - name: string; - icon?: string; - href: string; - url?: string; + entityType: string; }; export type SearchGroupItem = { name: string; @@ -101,13 +92,19 @@ export class UmbSearchModalElement extends UmbLitElement { this._activeSearchTag = searchProvider.alias; } - #updateSearchResults() { + async #updateSearchResults() { if (this._search) { - const { data, error } = this.#currentProvider.search({ + const { data, error } = await this.#currentProvider.search({ query: this._search, }); - console.log(data, error); + console.log('data', data); + + if (!data) return; + + this._searchResults = data.items; + + console.log('reults', this._searchResults); // this._searchResults = this.#mockApi.getDocuments.filter((item) => // item.name.toLowerCase().includes(this._search.toLowerCase()), // ); @@ -166,6 +163,13 @@ export class UmbSearchModalElement extends UmbLitElement { } #renderItem(item: SearchItem) { + return html` + manifest.forEntityTypes.includes(item.entityType)} + default-element="umb-search-result-item"> + `; return html` diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-result-item.element.ts b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-result-item.element.ts new file mode 100644 index 0000000000..fee8a881de --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-result-item.element.ts @@ -0,0 +1,21 @@ +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { customElement, html, property } from '@umbraco-cms/backoffice/external/lit'; + +const elementName = 'umb-search-result-item'; +@customElement(elementName) +export class UmbSearchResultItemElement extends UmbLitElement { + @property({ type: Object }) + item: any; + + render() { + return html`Helloasasdas`; + } +} + +export { UmbSearchResultItemElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbSearchResultItemElement; + } +} From 2fa9aee666b4ede337805b2c1f33b5120b1a3fee Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Thu, 11 Apr 2024 12:44:54 +0200 Subject: [PATCH 08/79] search result --- src/Umbraco.Web.UI.Client/package.json | 1 + .../document-search-result-item.element.ts | 24 ++++++++++--- .../src/packages/search/index.ts | 1 + .../search-modal/search-modal.element.ts | 2 +- .../search-result-item.element.ts | 21 ----------- .../search-result-item.element.ts | 36 +++++++++++++++++++ .../src/packages/search/types.ts | 5 +++ src/Umbraco.Web.UI.Client/tsconfig.json | 1 + 8 files changed, 64 insertions(+), 27 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/search/index.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-result-item.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/search/search-result/search-result-item.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/search/types.ts diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 8b9792bc73..e8ea2524c6 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -68,6 +68,7 @@ "./repository": "./dist-cms/packages/core/repository/index.js", "./resources": "./dist-cms/packages/core/resources/index.js", "./router": "./dist-cms/packages/core/router/index.js", + "./search": "./dist-cms/packages/search/index.js", "./section": "./dist-cms/packages/core/section/index.js", "./server-file-system": "./dist-cms/packages/core/server-file-system/index.js", "./sorter": "./dist-cms/packages/core/sorter/index.js", diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search-result-item.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search-result-item.element.ts index e016ddf597..8e1556711a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search-result-item.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search-result-item.element.ts @@ -1,16 +1,30 @@ -import type { UmbDocumentItemModel } from '../repository/index.js'; +import type { UmbSearchResultItemModel } from '@umbraco-cms/backoffice/search'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { customElement, html, property } from '@umbraco-cms/backoffice/external/lit'; +import { css, customElement, html, property } from '@umbraco-cms/backoffice/external/lit'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; const elementName = 'umb-document-search-result-item'; @customElement(elementName) export class UmbDocumentSearchResultItemElement extends UmbLitElement { - @property({ attribute: false }) - item?: UmbDocumentItemModel; + @property({ type: Object }) + item?: UmbSearchResultItemModel; render() { - return html`HELLO WORLD ${this.item?.unique}`; + return html` +
ICON
+
${this.item?.name}
+ `; } + + static styles = [ + UmbTextStyles, + css` + :host { + display: flex; + gap: 12px; + } + `, + ]; } export { UmbDocumentSearchResultItemElement as element }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/index.ts b/src/Umbraco.Web.UI.Client/src/packages/search/index.ts new file mode 100644 index 0000000000..9b7dfb03df --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/search/index.ts @@ -0,0 +1 @@ +export { type UmbSearchResultItemModel } from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts index dc3df95850..52fc2f1b33 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts @@ -5,7 +5,7 @@ import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registr import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbExtensionsManifestInitializer, createExtensionApi } from '@umbraco-cms/backoffice/extension-api'; -import './search-result-item.element.js'; +import '../search-result/search-result-item.element.js'; export type SearchItem = { entityType: string; diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-result-item.element.ts b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-result-item.element.ts deleted file mode 100644 index fee8a881de..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-result-item.element.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { customElement, html, property } from '@umbraco-cms/backoffice/external/lit'; - -const elementName = 'umb-search-result-item'; -@customElement(elementName) -export class UmbSearchResultItemElement extends UmbLitElement { - @property({ type: Object }) - item: any; - - render() { - return html`Helloasasdas`; - } -} - -export { UmbSearchResultItemElement as element }; - -declare global { - interface HTMLElementTagNameMap { - [elementName]: UmbSearchResultItemElement; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/search-result/search-result-item.element.ts b/src/Umbraco.Web.UI.Client/src/packages/search/search-result/search-result-item.element.ts new file mode 100644 index 0000000000..103fa70187 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/search/search-result/search-result-item.element.ts @@ -0,0 +1,36 @@ +import type { UmbSearchResultItemModel } from '../types.js'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { css, customElement, html, property } from '@umbraco-cms/backoffice/external/lit'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; + +const elementName = 'umb-search-result-item'; +@customElement(elementName) +export class UmbSearchResultItemElement extends UmbLitElement { + @property({ type: Object }) + item?: UmbSearchResultItemModel; + + render() { + return html` +
ICON
+
${this.item?.name}
+ `; + } + + static styles = [ + UmbTextStyles, + css` + :host { + display: flex; + gap: 12px; + } + `, + ]; +} + +export { UmbSearchResultItemElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbSearchResultItemElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/types.ts b/src/Umbraco.Web.UI.Client/src/packages/search/types.ts new file mode 100644 index 0000000000..e4952bdd42 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/search/types.ts @@ -0,0 +1,5 @@ +export type UmbSearchResultItemModel = { + icon?: string; + name: string; + unique: string; +}; diff --git a/src/Umbraco.Web.UI.Client/tsconfig.json b/src/Umbraco.Web.UI.Client/tsconfig.json index eee2db6359..736aea9e17 100644 --- a/src/Umbraco.Web.UI.Client/tsconfig.json +++ b/src/Umbraco.Web.UI.Client/tsconfig.json @@ -86,6 +86,7 @@ "@umbraco-cms/backoffice/repository": ["./src/packages/core/repository/index.ts"], "@umbraco-cms/backoffice/resources": ["./src/packages/core/resources/index.ts"], "@umbraco-cms/backoffice/router": ["./src/packages/core/router/index.ts"], + "@umbraco-cms/backoffice/search": ["./src/packages/search/index.ts"], "@umbraco-cms/backoffice/section": ["./src/packages/core/section/index.ts"], "@umbraco-cms/backoffice/server-file-system": ["./src/packages/core/server-file-system/index.ts"], "@umbraco-cms/backoffice/sorter": ["./src/packages/core/sorter/index.ts"], From b66b336c915cdd4b6f3e1f07ef7cc538a4ce3cbe Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Thu, 11 Apr 2024 13:06:37 +0200 Subject: [PATCH 09/79] default search item --- .../document-search-result-item.element.ts | 36 ---- .../documents/documents/search/manifests.ts | 1 - .../search-modal/search-modal.element.ts | 157 ++---------------- .../search-result-item.element.ts | 74 ++++++++- .../src/packages/search/types.ts | 1 + 5 files changed, 86 insertions(+), 183 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search-result-item.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search-result-item.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search-result-item.element.ts deleted file mode 100644 index 8e1556711a..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search-result-item.element.ts +++ /dev/null @@ -1,36 +0,0 @@ -import type { UmbSearchResultItemModel } from '@umbraco-cms/backoffice/search'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { css, customElement, html, property } from '@umbraco-cms/backoffice/external/lit'; -import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; - -const elementName = 'umb-document-search-result-item'; -@customElement(elementName) -export class UmbDocumentSearchResultItemElement extends UmbLitElement { - @property({ type: Object }) - item?: UmbSearchResultItemModel; - - render() { - return html` -
ICON
-
${this.item?.name}
- `; - } - - static styles = [ - UmbTextStyles, - css` - :host { - display: flex; - gap: 12px; - } - `, - ]; -} - -export { UmbDocumentSearchResultItemElement as element }; - -declare global { - interface HTMLElementTagNameMap { - [elementName]: UmbDocumentSearchResultItemElement; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/manifests.ts index 4420f0747f..1514c91f3a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/manifests.ts @@ -16,7 +16,6 @@ export const manifests: Array = [ name: 'Document Search Result Item ', alias: 'Umb.SearchResultItem.Document', type: 'searchResultItem', - element: () => import('./document-search-result-item.element.js'), forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts index 52fc2f1b33..81bde5a234 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts @@ -1,3 +1,4 @@ +import type { UmbSearchResultItemModel } from '../types.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, nothing, repeat, customElement, query, state } from '@umbraco-cms/backoffice/external/lit'; import type { ManifestSearchResultItem } from '@umbraco-cms/backoffice/extension-registry'; @@ -7,13 +8,6 @@ import { UmbExtensionsManifestInitializer, createExtensionApi } from '@umbraco-c import '../search-result/search-result-item.element.js'; -export type SearchItem = { - entityType: string; -}; -export type SearchGroupItem = { - name: string; - items: Array; -}; @customElement('umb-search-modal') export class UmbSearchModalElement extends UmbLitElement { @query('input') @@ -23,7 +17,7 @@ export class UmbSearchModalElement extends UmbLitElement { private _search = ''; @state() - private _searchResults: Array = []; + private _searchResults: Array = []; @state() private searchTags: Array = [ @@ -94,20 +88,9 @@ export class UmbSearchModalElement extends UmbLitElement { async #updateSearchResults() { if (this._search) { - const { data, error } = await this.#currentProvider.search({ - query: this._search, - }); - - console.log('data', data); - + const { data } = await this.#currentProvider.search({ query: this._search }); if (!data) return; - this._searchResults = data.items; - - console.log('reults', this._searchResults); - // this._searchResults = this.#mockApi.getDocuments.filter((item) => - // item.name.toLowerCase().includes(this._search.toLowerCase()), - // ); } else { this._searchResults = []; } @@ -135,7 +118,7 @@ export class UmbSearchModalElement extends UmbLitElement { } #renderSearchTags() { - return html`
+ return html`
${repeat( this._searchProviders, (searchProvider) => searchProvider, @@ -143,7 +126,7 @@ export class UmbSearchModalElement extends UmbLitElement { html``, )} @@ -153,16 +136,12 @@ export class UmbSearchModalElement extends UmbLitElement { #renderResults() { return repeat( this._searchResults, - (item) => item.name, - (item) => this.#renderItem(item), + (item) => item.unique, + (item) => this.#renderResultItem(item), ); } - #renderNoResults() { - return html`
Only mock data for now Search for blog
`; - } - - #renderItem(item: SearchItem) { + #renderResultItem(item: UmbSearchResultItemModel) { return html` manifest.forEntityTypes.includes(item.entityType)} default-element="umb-search-result-item"> `; - return html` -
- - ${item.icon ? html`` : this.#renderHashTag()} - - - ${item.name} ${item.url ? html`${item.url}` : nothing} - - > - - `; } - #renderHashTag() { - return html` - - - - - `; + #renderNoResults() { + return html`
Only mock data for now Search for blog
`; } - #mockApi = { - getDocuments: [ - { - name: 'Blog', - href: '#', - icon: 'icon-thumbnail-list', - url: '/blog/', - }, - { - name: 'Popular blogs', - href: '#', - icon: 'icon-article', - url: '/blog/popular-blogs/', - }, - { - name: 'How to write a blog', - href: '#', - icon: 'icon-article', - url: '/blog/how-to-write-a-blog/', - }, - ], - getMedia: [ - { - name: 'Blog hero', - href: '#', - icon: 'icon-picture', - }, - ], - getDocumentTypes: [ - { - name: 'Contact form for blog', - href: '#', - }, - { - name: 'Blog', - href: '#', - }, - { - name: 'Blog link item', - href: '#', - }, - ], - }; - static styles = [ UmbTextStyles, css` - #search-tags { + #search-providers { display: flex; flex-wrap: wrap; gap: var(--uui-size-space-2); padding: 0 var(--uui-size-space-5); padding-bottom: var(--uui-size-space-2); } - .search-tag { + .search-provider { padding: var(--uui-size-space-3) var(--uui-size-space-4); background: var(--uui-color-surface-alt); line-height: 1; @@ -258,11 +175,11 @@ export class UmbSearchModalElement extends UmbLitElement { cursor: pointer; border: 2px solid transparent; } - .search-tag:hover { + .search-provider:hover { background: var(--uui-color-surface-emphasis); color: var(--uui-color-interactive-emphasis); } - .search-tag.active { + .search-provider.active { background: var(--uui-color-surface-emphasis); color: var(--uui-color-interactive-emphasis); border-color: var(--uui-color-focus); @@ -305,52 +222,6 @@ export class UmbSearchModalElement extends UmbLitElement { flex-direction: column; height: 100%; } - .item { - background: var(--uui-color-surface); - padding: var(--uui-size-space-3) var(--uui-size-space-5); - border-radius: var(--uui-border-radius); - color: var(--uui-color-interactive); - display: grid; - grid-template-columns: var(--uui-size-space-6) 1fr var(--uui-size-space-5); - align-items: center; - } - .item:hover { - background-color: var(--uui-color-surface-emphasis); - color: var(--uui-color-interactive-emphasis); - } - .item:hover .item-symbol { - font-weight: unset; - opacity: 1; - } - .item-icon { - margin-bottom: auto; - margin-top: 5px; - } - .item-icon, - .item-symbol { - opacity: 0.4; - } - .item-url { - font-size: 0.8rem; - line-height: 1.2; - font-weight: 100; - } - .item-name { - display: flex; - flex-direction: column; - } - .item-icon > * { - height: 1rem; - display: flex; - width: min-content; - } - .item-symbol { - font-weight: 100; - } - a { - text-decoration: none; - color: inherit; - } #no-results { display: flex; flex-direction: column; diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/search-result/search-result-item.element.ts b/src/Umbraco.Web.UI.Client/src/packages/search/search-result/search-result-item.element.ts index 103fa70187..41a9b41b09 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/search/search-result/search-result-item.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/search/search-result/search-result-item.element.ts @@ -1,6 +1,6 @@ import type { UmbSearchResultItemModel } from '../types.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { css, customElement, html, property } from '@umbraco-cms/backoffice/external/lit'; +import { css, customElement, html, nothing, property } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; const elementName = 'umb-search-result-item'; @@ -10,9 +10,29 @@ export class UmbSearchResultItemElement extends UmbLitElement { item?: UmbSearchResultItemModel; render() { + if (!this.item) return nothing; + + const url = 'url/goes/here'; + return html` -
ICON
-
${this.item?.name}
+ + + ${this.item.icon ? html`` : this.#renderHashTag()} + + ${this.item.name} ${url ? html`${url}` : nothing} + > + + `; + } + + #renderHashTag() { + return html` + + + + `; } @@ -22,6 +42,54 @@ export class UmbSearchResultItemElement extends UmbLitElement { :host { display: flex; gap: 12px; + width: 100%; + } + .item { + background: var(--uui-color-surface); + padding: var(--uui-size-space-3) var(--uui-size-space-5); + border-radius: var(--uui-border-radius); + color: var(--uui-color-interactive); + display: grid; + grid-template-columns: var(--uui-size-space-6) 1fr var(--uui-size-space-5); + align-items: center; + width: 100%; + } + .item:hover { + background-color: var(--uui-color-surface-emphasis); + color: var(--uui-color-interactive-emphasis); + } + .item:hover .item-symbol { + font-weight: unset; + opacity: 1; + } + .item-icon { + margin-bottom: auto; + margin-top: 5px; + } + .item-icon, + .item-symbol { + opacity: 0.4; + } + .item-url { + font-size: 0.8rem; + line-height: 1.2; + font-weight: 100; + } + .item-name { + display: flex; + flex-direction: column; + } + .item-icon > * { + height: 1rem; + display: flex; + width: min-content; + } + .item-symbol { + font-weight: 100; + } + a { + text-decoration: none; + color: inherit; } `, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/types.ts b/src/Umbraco.Web.UI.Client/src/packages/search/types.ts index e4952bdd42..1967a24bf4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/search/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/search/types.ts @@ -1,4 +1,5 @@ export type UmbSearchResultItemModel = { + entityType: string; icon?: string; name: string; unique: string; From 9f37bebdbe1d089deb5444f7271791d072046353 Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Thu, 11 Apr 2024 13:13:14 +0200 Subject: [PATCH 10/79] cleanup --- .../search-modal/search-modal.element.ts | 38 +++++++------------ 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts index 81bde5a234..ca9192cfb2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts @@ -19,22 +19,6 @@ export class UmbSearchModalElement extends UmbLitElement { @state() private _searchResults: Array = []; - @state() - private searchTags: Array = [ - 'Data Type', - 'Document', - 'Document Type', - 'Media', - 'Media Type', - 'Member', - 'Member Type', - 'Users', - 'User Group', - ]; - - @state() - private _activeSearchTag = 'Document'; - @state() private _searchProviders: Array<{ name: string; @@ -42,7 +26,11 @@ export class UmbSearchModalElement extends UmbLitElement { alias: string; }> = []; - #currentProvider: any; + @state() + _currentProvider?: { + api: any; + alias: string; + }; /** * @@ -79,16 +67,16 @@ export class UmbSearchModalElement extends UmbLitElement { } async #onSearchTagClick(searchProvider: any) { - console.log(searchProvider); const api = await searchProvider.providerPromise; - - this.#currentProvider = api; - this._activeSearchTag = searchProvider.alias; + this._currentProvider = { + api, + alias: searchProvider.alias, + }; } async #updateSearchResults() { - if (this._search) { - const { data } = await this.#currentProvider.search({ query: this._search }); + if (this._search && this._currentProvider) { + const { data } = await this._currentProvider.api.search({ query: this._search }); if (!data) return; this._searchResults = data.items; } else { @@ -126,7 +114,7 @@ export class UmbSearchModalElement extends UmbLitElement { html``, )} @@ -152,7 +140,7 @@ export class UmbSearchModalElement extends UmbLitElement { } #renderNoResults() { - return html`
Only mock data for now Search for blog
`; + return html`
No results found
`; } static styles = [ From d03adace843e0c20da0a955e1cd58ce8c2a1eaa8 Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Thu, 11 Apr 2024 13:15:20 +0200 Subject: [PATCH 11/79] cleanup --- .../search/search-modal/search-modal.element.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts index ca9192cfb2..4a7b57fdc8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts @@ -32,9 +32,6 @@ export class UmbSearchModalElement extends UmbLitElement { alias: string; }; - /** - * - */ constructor() { super(); @@ -55,10 +52,14 @@ export class UmbSearchModalElement extends UmbLitElement { super.connectedCallback(); requestAnimationFrame(() => { - this._input.focus(); + this.#focusInput(); }); } + #focusInput() { + this._input.focus(); + } + #onSearchChange(event: InputEvent) { const target = event.target as HTMLInputElement; this._search = target.value; @@ -72,6 +73,8 @@ export class UmbSearchModalElement extends UmbLitElement { api, alias: searchProvider.alias, }; + + this.#focusInput(); } async #updateSearchResults() { From ecb9857ae771b4afc20d59325924ea811c85ffc7 Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Thu, 11 Apr 2024 13:16:41 +0200 Subject: [PATCH 12/79] select first provider --- .../packages/search/search-modal/search-modal.element.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts index 4a7b57fdc8..fceaf940de 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts @@ -45,6 +45,10 @@ export class UmbSearchModalElement extends UmbLitElement { providerPromise: createExtensionApi(this, provider.manifest), alias: provider.alias, })); + + if (this._searchProviders.length > 0) { + this.#setCurrentProvider(this._searchProviders[0]); + } }); } @@ -67,7 +71,7 @@ export class UmbSearchModalElement extends UmbLitElement { this.#updateSearchResults(); } - async #onSearchTagClick(searchProvider: any) { + async #setCurrentProvider(searchProvider: any) { const api = await searchProvider.providerPromise; this._currentProvider = { api, @@ -115,7 +119,7 @@ export class UmbSearchModalElement extends UmbLitElement { (searchProvider) => searchProvider, (searchProvider) => html`
`; } + #closeModal(event: MouseEvent | KeyboardEvent) { + if (event instanceof KeyboardEvent && event.key !== 'Enter') return; + this.modalContext?.reject(); + } + static styles = [ UmbTextStyles, css` @@ -430,6 +453,11 @@ export class UmbSearchModalElement extends UmbLitElement { outline-offset: -3px; display: flex; } + .search-item:focus { + outline: 2px solid var(--uui-color-interactive-emphasis); + border-radius: 6px; + outline-offset: -4px; + } .search-item.active:not(:focus-within) { outline: 2px solid var(--uui-color-border); border-radius: 6px; From b4c7b6b8132b7d58ea2b4008d4236fd0d751ea52 Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Wed, 24 Apr 2024 18:56:05 +0200 Subject: [PATCH 47/79] responsive --- .../src/packages/search/search-modal/search-modal.element.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts index 71adab12b8..ed2566b54f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts @@ -346,7 +346,8 @@ export class UmbSearchModalElement extends UmbLitElement { display: flex; flex-direction: column; width: min(610px, 100vw); - height: 80dvh; + height: max(600px, 80dvh); + max-height: 100dvh; background-color: var(--uui-color-surface); box-sizing: border-box; color: var(--uui-color-text); @@ -363,6 +364,7 @@ export class UmbSearchModalElement extends UmbLitElement { display: flex; flex-direction: column; height: 100%; + overflow: auto; } #search-providers { display: flex; From 3dfba7e3913cdc91ed6a74a7d5dd2355a09be681 Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Wed, 24 Apr 2024 19:08:04 +0200 Subject: [PATCH 48/79] document types --- .../documents/search/document-search.repository.ts | 8 ++++++-- .../search/document-search.server.data-source.ts | 7 ++++--- .../documents/search/document.search-provider.ts | 12 +++++++++--- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search.repository.ts index 6a2f556a19..c5471d0e5d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search.repository.ts @@ -1,10 +1,14 @@ import { UmbDocumentSearchServerDataSource } from './document-search.server.data-source.js'; -import type { UmbSearchRequestArgs } from '@umbraco-cms/backoffice/search'; +import type { UmbDocumentSearchItemModel } from './document.search-provider.js'; +import type { UmbSearchRepository, UmbSearchRequestArgs } from '@umbraco-cms/backoffice/search'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; -export class UmbDocumentSearchRepository extends UmbControllerBase implements UmbApi { +export class UmbDocumentSearchRepository + extends UmbControllerBase + implements UmbSearchRepository, UmbApi +{ #dataSource: UmbDocumentSearchServerDataSource; constructor(host: UmbControllerHost) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search.server.data-source.ts index 46c99963cc..824dd544ec 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search.server.data-source.ts @@ -1,5 +1,6 @@ import { UMB_DOCUMENT_ENTITY_TYPE } from '../entity.js'; -import type { UmbSearchRequestArgs } from '@umbraco-cms/backoffice/search'; +import type { UmbDocumentSearchItemModel } from './document.search-provider.js'; +import type { UmbSearchDataSource, UmbSearchRequestArgs } from '@umbraco-cms/backoffice/search'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { DocumentService } from '@umbraco-cms/backoffice/external/backend-api'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; @@ -10,7 +11,7 @@ import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; * @class UmbDocumentSearchServerDataSource * @implements {RepositoryDetailDataSource} */ -export class UmbDocumentSearchServerDataSource { +export class UmbDocumentSearchServerDataSource implements UmbSearchDataSource { #host: UmbControllerHost; /** @@ -36,7 +37,7 @@ export class UmbDocumentSearchServerDataSource { ); if (data) { - const mappedItems = data.items.map((item) => { + const mappedItems: Array = data.items.map((item) => { return { href: '/section/content/workspace/document/edit/' + item.id, entityType: UMB_DOCUMENT_ENTITY_TYPE, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document.search-provider.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document.search-provider.ts index 760b37f3ce..7029cfba73 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document.search-provider.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document.search-provider.ts @@ -1,9 +1,15 @@ +import type { UmbDocumentItemModel } from '../index.js'; import { UmbDocumentSearchRepository } from './document-search.repository.js'; -import type { UmbSearchRequestArgs } from '@umbraco-cms/backoffice/search'; -import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; +import type { UmbSearchProvider, UmbSearchRequestArgs } from '@umbraco-cms/backoffice/search'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; +export interface UmbDocumentSearchItemModel extends UmbDocumentItemModel { + href: string; +} -export class UmbDocumentSearchProvider extends UmbControllerBase implements UmbApi { +export class UmbDocumentSearchProvider + extends UmbControllerBase + implements UmbSearchProvider +{ #repository = new UmbDocumentSearchRepository(this); search(args: UmbSearchRequestArgs) { From 9d6239fc7c5ebd6b9cb430bfaa29b75a32cc2e9e Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Wed, 24 Apr 2024 19:08:18 +0200 Subject: [PATCH 49/79] media href --- .../media/media/search/media-search.server.data-source.ts | 1 + .../src/packages/media/media/search/media.search-provider.ts | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/search/media-search.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/search/media-search.server.data-source.ts index bc3a660932..21a2ae1858 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/search/media-search.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/search/media-search.server.data-source.ts @@ -39,6 +39,7 @@ export class UmbMediaSearchServerDataSource implements UmbSearchDataSource = data.items.map((item) => { return { + href: '/section/media/workspace/media/edit/' + item.id, entityType: UMB_MEDIA_ENTITY_TYPE, unique: item.id, isTrashed: item.isTrashed, diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/search/media.search-provider.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/search/media.search-provider.ts index 89f3b95cfb..9b5655ec82 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/search/media.search-provider.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/search/media.search-provider.ts @@ -3,7 +3,9 @@ import { UmbMediaSearchRepository } from './media-search.repository.js'; import type { UmbSearchProvider, UmbSearchRequestArgs } from '@umbraco-cms/backoffice/search'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; -export interface UmbMediaSearchItemModel extends UmbMediaItemModel {} +export interface UmbMediaSearchItemModel extends UmbMediaItemModel { + href: string; +} export class UmbMediaSearchProvider extends UmbControllerBase implements UmbSearchProvider { #repository = new UmbMediaSearchRepository(this); From 96e42e93b3f1a4b3fcb9c84ecbf767d7e9d0f645 Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Wed, 24 Apr 2024 19:09:19 +0200 Subject: [PATCH 50/79] data type href --- .../data-type/search/data-type-search.server.data-source.ts | 1 + .../packages/data-type/search/data-type.search-provider.ts | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/search/data-type-search.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/search/data-type-search.server.data-source.ts index 2dcd9a55aa..20f021a3c5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/search/data-type-search.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/search/data-type-search.server.data-source.ts @@ -39,6 +39,7 @@ export class UmbDataTypeSearchServerDataSource implements UmbSearchDataSource = data.items.map((item) => { return { + href: '/section/settings/workspace/data-type/edit/' + item.id, entityType: UMB_DATA_TYPE_ENTITY_TYPE, unique: item.id, name: item.name, diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/search/data-type.search-provider.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/search/data-type.search-provider.ts index a315d0904c..276e663587 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/search/data-type.search-provider.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/search/data-type.search-provider.ts @@ -3,7 +3,9 @@ import { UmbDataTypeSearchRepository } from './data-type-search.repository.js'; import type { UmbSearchProvider, UmbSearchRequestArgs } from '@umbraco-cms/backoffice/search'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; -export interface UmbDataTypeSearchItemModel extends UmbDataTypeItemModel {} +export interface UmbDataTypeSearchItemModel extends UmbDataTypeItemModel { + href: string; +} export class UmbDataTypeSearchProvider extends UmbControllerBase From 261e0eee36005074b80d7aad3446091762b1f41a Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Wed, 24 Apr 2024 19:10:13 +0200 Subject: [PATCH 51/79] document type href --- .../search/document-type-search.server.data-source.ts | 1 + .../document-types/search/document-type.search-provider.ts | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/search/document-type-search.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/search/document-type-search.server.data-source.ts index 7b8c2c0f56..beb2bc9f0a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/search/document-type-search.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/search/document-type-search.server.data-source.ts @@ -39,6 +39,7 @@ export class UmbDocumentTypeSearchServerDataSource implements UmbSearchDataSourc if (data) { const mappedItems: Array = data.items.map((item) => { return { + href: '/section/settings/workspace/document-type/edit/' + item.id, entityType: UMB_DOCUMENT_TYPE_ENTITY_TYPE, isElement: item.isElement, icon: item.icon, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/search/document-type.search-provider.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/search/document-type.search-provider.ts index 2d4a51bfc3..d70845fc0a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/search/document-type.search-provider.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/search/document-type.search-provider.ts @@ -3,7 +3,9 @@ import { UmbDocumentTypeSearchRepository } from './document-type-search.reposito import type { UmbSearchProvider, UmbSearchRequestArgs } from '@umbraco-cms/backoffice/search'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; -export interface UmbDocumentTypeSearchItemModel extends UmbDocumentTypeItemModel {} +export interface UmbDocumentTypeSearchItemModel extends UmbDocumentTypeItemModel { + href: string; +} export class UmbDocumentTypeSearchProvider extends UmbControllerBase From 4f6378a064ced1409ad0146f3d7ef6b4f5507025 Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Wed, 24 Apr 2024 19:11:04 +0200 Subject: [PATCH 52/79] media type href --- .../search/media-type-search.server.data-source.ts | 1 + .../media/media-types/search/media-type.search-provider.ts | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/search/media-type-search.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/search/media-type-search.server.data-source.ts index a05b50817a..b49edd53b6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/search/media-type-search.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/search/media-type-search.server.data-source.ts @@ -39,6 +39,7 @@ export class UmbMediaTypeSearchServerDataSource implements UmbSearchDataSource = data.items.map((item) => { return { + href: '/section/settings/workspace/media-type/edit/' + item.id, entityType: UMB_MEDIA_TYPE_ENTITY_TYPE, unique: item.id, name: item.name, diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/search/media-type.search-provider.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/search/media-type.search-provider.ts index e85cc21cc8..746805fd58 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/search/media-type.search-provider.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/search/media-type.search-provider.ts @@ -3,7 +3,9 @@ import { UmbMediaTypeSearchRepository } from './media-type-search.repository.js' import type { UmbSearchProvider, UmbSearchRequestArgs } from '@umbraco-cms/backoffice/search'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; -export interface UmbMediaTypeSearchItemModel extends UmbMediaTypeItemModel {} +export interface UmbMediaTypeSearchItemModel extends UmbMediaTypeItemModel { + href: string; +} export class UmbMediaTypeSearchProvider extends UmbControllerBase From efd3995f127566c26d07d397605ed656843de48e Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Wed, 24 Apr 2024 19:14:29 +0200 Subject: [PATCH 53/79] member href --- .../members/member/search/member-search.server.data-source.ts | 1 + .../packages/members/member/search/member.search-provider.ts | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/search/member-search.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/search/member-search.server.data-source.ts index ec3ee432bd..b56ebd9dc6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/search/member-search.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/search/member-search.server.data-source.ts @@ -39,6 +39,7 @@ export class UmbMemberSearchServerDataSource implements UmbSearchDataSource = data.items.map((item) => { return { + href: '/section/member-management/workspace/member/edit/' + item.id, entityType: UMB_MEMBER_ENTITY_TYPE, unique: item.id, name: item.variants[0].name || '', diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/search/member.search-provider.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/search/member.search-provider.ts index 99ec93e170..535a812f31 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/search/member.search-provider.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/search/member.search-provider.ts @@ -3,7 +3,9 @@ import { UmbMemberSearchRepository } from './member-search.repository.js'; import type { UmbSearchProvider, UmbSearchRequestArgs } from '@umbraco-cms/backoffice/search'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; -export interface UmbMemberSearchItemModel extends UmbMemberItemModel {} +export interface UmbMemberSearchItemModel extends UmbMemberItemModel { + href: string; +} export class UmbMemberSearchProvider extends UmbControllerBase implements UmbSearchProvider { #repository = new UmbMemberSearchRepository(this); From 53f343bbb0509a8f8bc96023829453557e54fbc4 Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Wed, 24 Apr 2024 19:14:34 +0200 Subject: [PATCH 54/79] member type href --- .../search/member-type-search.server.data-source.ts | 1 + .../members/member-type/search/member-type.search-provider.ts | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/search/member-type-search.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/search/member-type-search.server.data-source.ts index 79b16fed9e..0fc23e69bb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/search/member-type-search.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/search/member-type-search.server.data-source.ts @@ -39,6 +39,7 @@ export class UmbMemberTypeSearchServerDataSource implements UmbSearchDataSource< if (data) { const mappedItems: Array = data.items.map((item) => { return { + href: '/section/settings/workspace/member-type/edit/' + item.id, entityType: UMB_MEMBER_TYPE_ENTITY_TYPE, unique: item.id, name: item.name, diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/search/member-type.search-provider.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/search/member-type.search-provider.ts index 852f7089e0..f46a3093e3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/search/member-type.search-provider.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/search/member-type.search-provider.ts @@ -3,7 +3,9 @@ import { UmbMemberTypeSearchRepository } from './member-type-search.repository.j import type { UmbSearchProvider, UmbSearchRequestArgs } from '@umbraco-cms/backoffice/search'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; -export interface UmbMemberTypeSearchItemModel extends UmbMemberTypeItemModel {} +export interface UmbMemberTypeSearchItemModel extends UmbMemberTypeItemModel { + href: string; +} export class UmbMemberTypeSearchProvider extends UmbControllerBase From 3fb1f893a5d58bf131dd4931ebee9e8ba296cc23 Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Wed, 24 Apr 2024 19:14:40 +0200 Subject: [PATCH 55/79] template href --- .../templates/search/template-search.server.data-source.ts | 1 + .../templating/templates/search/template.search-provider.ts | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/search/template-search.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/search/template-search.server.data-source.ts index a502683fbe..ba85e4e73c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/search/template-search.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/search/template-search.server.data-source.ts @@ -39,6 +39,7 @@ export class UmbTemplateSearchServerDataSource implements UmbSearchDataSource = data.items.map((item) => { return { + href: '/section/settings/workspace/template/edit/' + item.id, entityType: UMB_TEMPLATE_ENTITY_TYPE, unique: item.id, name: item.name, diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/search/template.search-provider.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/search/template.search-provider.ts index 28477776d5..a1e8b90235 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/search/template.search-provider.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/search/template.search-provider.ts @@ -3,7 +3,9 @@ import { UmbTemplateSearchRepository } from './template-search.repository.js'; import type { UmbSearchProvider, UmbSearchRequestArgs } from '@umbraco-cms/backoffice/search'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; -export interface UmbTemplateSearchItemModel extends UmbTemplateItemModel {} +export interface UmbTemplateSearchItemModel extends UmbTemplateItemModel { + href: string; +} export class UmbTemplateSearchProvider extends UmbControllerBase From ea2fa841f6841c0ce66198723068dd7e7f605c22 Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Wed, 24 Apr 2024 19:17:38 +0200 Subject: [PATCH 56/79] remove results on provider change --- .../src/packages/search/search-modal/search-modal.element.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts index ed2566b54f..9c68c6a5d4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts @@ -242,6 +242,7 @@ export class UmbSearchModalElement extends UmbLitElement { this.#focusInput(); this._loading = true; + this._searchResults = []; this.#updateSearchResults(); } From f03db2b55ce53f258ff6702c37c75e8f316d47b5 Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Wed, 24 Apr 2024 19:32:38 +0200 Subject: [PATCH 57/79] fix document styling --- .../document-search-result-item.element.ts | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search-result-item.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search-result-item.element.ts index ad021f5241..98d35db29e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search-result-item.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search-result-item.element.ts @@ -87,28 +87,13 @@ export class UmbSearchResultItemElement extends UmbLitElement { UmbTextStyles, css` :host { - background: var(--uui-color-surface); padding: var(--uui-size-space-3) var(--uui-size-space-5); border-radius: var(--uui-border-radius); - color: var(--uui-color-interactive); display: grid; grid-template-columns: var(--uui-size-space-6) 1fr var(--uui-size-space-5); align-items: center; width: 100%; - } - .item { - background: var(--uui-color-surface); - padding: var(--uui-size-space-3) var(--uui-size-space-5); - border-radius: var(--uui-border-radius); - color: var(--uui-color-interactive); - display: grid; - grid-template-columns: var(--uui-size-space-6) 1fr var(--uui-size-space-5); - align-items: center; - width: 100%; - } - .item:hover { - background-color: var(--uui-color-surface-emphasis); - color: var(--uui-color-interactive-emphasis); + outline-offset: -3px; } .item-icon { margin-bottom: auto; From e3215d2670da230b84f2a1306fbbe433cff1677f Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Wed, 24 Apr 2024 19:32:50 +0200 Subject: [PATCH 58/79] fix keyboard navigation --- .../search/search-modal/search-modal.element.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts index 9c68c6a5d4..5bc1c8484f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts @@ -337,7 +337,12 @@ export class UmbSearchModalElement extends UmbLitElement { #closeModal(event: MouseEvent | KeyboardEvent) { if (event instanceof KeyboardEvent && event.key !== 'Enter') return; - this.modalContext?.reject(); + + requestAnimationFrame(() => { + // In the case where the browser has not triggered focus-visible and we keyboard navigate and press enter. + // It is necessary to wait one frame. + this.modalContext?.reject(); + }); } static styles = [ @@ -456,6 +461,10 @@ export class UmbSearchModalElement extends UmbLitElement { outline-offset: -3px; display: flex; } + .search-item:hover { + background: var(--uui-color-surface-emphasis); + color: var(--uui-color-interactive-emphasis); + } .search-item:focus { outline: 2px solid var(--uui-color-interactive-emphasis); border-radius: 6px; From e0db6f628265393b6254f9d3a76bae5b95ff19a6 Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Wed, 24 Apr 2024 19:44:14 +0200 Subject: [PATCH 59/79] cleanup --- .../src/packages/search/search-modal/search-modal.element.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts index 5bc1c8484f..f2d6b6eb82 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts @@ -172,8 +172,6 @@ export class UmbSearchModalElement extends UmbLitElement { } async #setSearchItemNavIndex(index: number) { - await this.updateComplete; - const prevElement = this.shadowRoot?.querySelector( `a[data-item-index="${this.#searchItemNavIndex}"]`, ) as HTMLElement | null; From 25e5d9ec500295976faffd7f5b1d3f5501bd4459 Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Wed, 24 Apr 2024 19:54:49 +0200 Subject: [PATCH 60/79] cleanup --- .../search-modal/search-modal.element.ts | 257 +++++++++--------- 1 file changed, 127 insertions(+), 130 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts index f2d6b6eb82..eccd95f917 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts @@ -57,10 +57,20 @@ export class UmbSearchModalElement extends UmbLitElement { constructor() { super(); - this.#observeViews(); + this.#observeProviders(); } - #observeViews() { + connectedCallback() { + super.connectedCallback(); + + this.addEventListener('keydown', this.#onKeydown); + + requestAnimationFrame(() => { + this.#focusInput(); + }); + } + + #observeProviders() { new UmbExtensionsManifestInitializer(this, umbExtensionsRegistry, 'searchProvider', null, async (providers) => { const searchProviders: Array = []; @@ -83,94 +93,6 @@ export class UmbSearchModalElement extends UmbLitElement { }); } - connectedCallback() { - super.connectedCallback(); - - this.addEventListener('keydown', this.#onKeydown); - - requestAnimationFrame(() => { - this.#focusInput(); - }); - } - - #onKeydown(event: KeyboardEvent) { - const root = this.shadowRoot; - if (!root) return; - - if (event.key === 'Tab') { - const isFirstProvider = (element: Element) => element === root.querySelector('.search-provider:first-child'); - const isLastProvider = (element: Element) => element === root.querySelector('.search-provider:last-child'); - const setActiveProviderFocus = (element?: Element | null) => (element as HTMLElement)?.focus(); - - const activeProvider = root.querySelector('.search-provider.active') as HTMLElement | null; - - if (!activeProvider) return; - - // When moving backwards in search providers - if (event.shiftKey) { - // If the FOCUS is on a provider, and it is the first in the list, we need to wrap around and focus the LAST one - if (this.#providerHasFocus) { - if (this.#isFocusingFirstProvider) { - setActiveProviderFocus(root.querySelector('.search-provider:last-child')); - event.preventDefault(); - } - return; - } - - // If the currently ACTIVE provider is the first in the list, we need to wrap around and focus the LAST one - if (isFirstProvider(activeProvider)) { - setActiveProviderFocus(root.querySelector('.search-provider:last-child')); - event.preventDefault(); - return; - } - - // We set the focus to current provider, and because we don't prevent the default tab behavior, the previous provider will be focused - setActiveProviderFocus(activeProvider); - } - // When moving forwards in search providers - else { - // If the FOCUS is on a provider, and it is the last in the list, we need to wrap around and focus the FIRST one - if (this.#providerHasFocus) { - if (this.#isFocusingLastProvider) { - setActiveProviderFocus(root.querySelector('.search-provider:first-child')); - event.preventDefault(); - } - return; - } - - // If the currently ACTIVE provider is the last in the list, we need to wrap around and focus the FIRST one - if (isLastProvider(activeProvider)) { - setActiveProviderFocus(root.querySelector('.search-provider:first-child')); - event.preventDefault(); - return; - } - - // We set the focus to current provider, and because we don't prevent the default tab behavior, the next provider will be focused - setActiveProviderFocus(activeProvider); - } - } - - switch (event.key) { - case 'Tab': - case 'Shift': - case 'Escape': - case 'Enter': - break; - case 'ArrowDown': - event.preventDefault(); - this.#setSearchItemNavIndex(Math.min(this.#searchItemNavIndex + 1, this._searchResults.length - 1)); - break; - case 'ArrowUp': - event.preventDefault(); - this.#setSearchItemNavIndex(Math.max(this.#searchItemNavIndex - 1, 0)); - break; - default: - if (this._input === root.activeElement) return; - this.#focusInput(); - break; - } - } - async #setSearchItemNavIndex(index: number) { const prevElement = this.shadowRoot?.querySelector( `a[data-item-index="${this.#searchItemNavIndex}"]`, @@ -192,36 +114,6 @@ export class UmbSearchModalElement extends UmbLitElement { this._input.focus(); } - get #providerHasFocus() { - const providerElements = this.shadowRoot?.querySelectorAll('.search-provider') || []; - return Array.from(providerElements).some((element) => element === this.shadowRoot?.activeElement); - } - - get #isFocusingLastProvider() { - const providerElements = this.shadowRoot?.querySelectorAll('.search-provider') || []; - return providerElements[providerElements.length - 1] === this.shadowRoot?.activeElement; - } - - get #isFocusingFirstProvider() { - const providerElements = this.shadowRoot?.querySelectorAll('.search-provider') || []; - return providerElements[0] === this.shadowRoot?.activeElement; - } - - #onSearchChange(event: InputEvent) { - const target = event.target as HTMLInputElement; - this._search = target.value.trim(); - - clearTimeout(this.#inputTimer); - if (!this._search) { - this._loading = false; - this._searchResults = []; - return; - } - - this._loading = true; - this.#inputTimer = setTimeout(() => this.#updateSearchResults(), this.#inputTimerAmount); - } - async #setShowFakeCursor(show: boolean) { if (show) { await new Promise((resolve) => requestAnimationFrame(resolve)); @@ -257,6 +149,121 @@ export class UmbSearchModalElement extends UmbLitElement { this.#searchItemNavIndex = -1; } + #closeModal(event: MouseEvent | KeyboardEvent) { + if (event instanceof KeyboardEvent && event.key !== 'Enter') return; + + requestAnimationFrame(() => { + // In the case where the browser has not triggered focus-visible and we keyboard navigate and press enter. + // It is necessary to wait one frame. + this.modalContext?.reject(); + }); + } + + #onSearchChange(event: InputEvent) { + const target = event.target as HTMLInputElement; + this._search = target.value.trim(); + + clearTimeout(this.#inputTimer); + if (!this._search) { + this._loading = false; + this._searchResults = []; + return; + } + + this._loading = true; + this.#inputTimer = setTimeout(() => this.#updateSearchResults(), this.#inputTimerAmount); + } + + #onKeydown(event: KeyboardEvent) { + const root = this.shadowRoot; + if (!root) return; + + if (event.key === 'Tab') { + const isFirstProvider = (element: Element) => element === root.querySelector('.search-provider:first-child'); + const isLastProvider = (element: Element) => element === root.querySelector('.search-provider:last-child'); + const setFocus = (element?: Element | null) => (element as HTMLElement)?.focus(); + const providerHasFocus = () => { + const providerElements = root.querySelectorAll('.search-provider') || []; + return Array.from(providerElements).some((element) => element === root.activeElement); + }; + const isFocusingLastProvider = () => { + const providerElements = root.querySelectorAll('.search-provider') || []; + return providerElements[providerElements.length - 1] === root.activeElement; + }; + const isFocusingFirstProvider = () => { + const providerElements = root.querySelectorAll('.search-provider') || []; + return providerElements[0] === root.activeElement; + }; + + const activeProvider = root.querySelector('.search-provider.active') as HTMLElement | null; + + if (!activeProvider) return; + + // When moving backwards in search providers + if (event.shiftKey) { + // If the FOCUS is on a provider, and it is the first in the list, we need to wrap around and focus the LAST one + if (providerHasFocus()) { + if (isFocusingFirstProvider()) { + setFocus(root.querySelector('.search-provider:last-child')); + event.preventDefault(); + } + return; + } + + // If the currently ACTIVE provider is the first in the list, we need to wrap around and focus the LAST one + if (isFirstProvider(activeProvider)) { + setFocus(root.querySelector('.search-provider:last-child')); + event.preventDefault(); + return; + } + + // We set the focus to current provider, and because we don't prevent the default tab behavior, the previous provider will be focused + setFocus(activeProvider); + } + // When moving forwards in search providers + else { + // If the FOCUS is on a provider, and it is the last in the list, we need to wrap around and focus the FIRST one + if (providerHasFocus()) { + if (isFocusingLastProvider()) { + setFocus(root.querySelector('.search-provider:first-child')); + event.preventDefault(); + } + return; + } + + // If the currently ACTIVE provider is the last in the list, we need to wrap around and focus the FIRST one + if (isLastProvider(activeProvider)) { + setFocus(root.querySelector('.search-provider:first-child')); + event.preventDefault(); + return; + } + + // We set the focus to current provider, and because we don't prevent the default tab behavior, the next provider will be focused + setFocus(activeProvider); + } + } + + switch (event.key) { + case 'Tab': + case 'Shift': + case 'Escape': + case 'Enter': + break; + case 'ArrowDown': + event.preventDefault(); + this.#setSearchItemNavIndex(Math.min(this.#searchItemNavIndex + 1, this._searchResults.length - 1)); + break; + case 'ArrowUp': + event.preventDefault(); + this.#setSearchItemNavIndex(Math.max(this.#searchItemNavIndex - 1, 0)); + break; + default: + if (this._input === root.activeElement) return; + this.#focusInput(); + break; + } + } + render() { return html`
@@ -333,16 +340,6 @@ export class UmbSearchModalElement extends UmbLitElement { return this._loading ? nothing : html`
${this.localize.term('general_searchNoResult')}
`; } - #closeModal(event: MouseEvent | KeyboardEvent) { - if (event instanceof KeyboardEvent && event.key !== 'Enter') return; - - requestAnimationFrame(() => { - // In the case where the browser has not triggered focus-visible and we keyboard navigate and press enter. - // It is necessary to wait one frame. - this.modalContext?.reject(); - }); - } - static styles = [ UmbTextStyles, css` From d84d1fc55d73458b10aea6be63491cb48ebef22d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Sun, 28 Apr 2024 13:11:40 +0200 Subject: [PATCH 61/79] only render context menu when it is open --- .../section-sidebar.element.ts | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.element.ts index 65da98a094..c330a5a1dd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.element.ts @@ -1,20 +1,31 @@ import { UmbSectionSidebarContext } from './section-sidebar.context.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, state, nothing } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; @customElement('umb-section-sidebar') export class UmbSectionSidebarElement extends UmbLitElement { + @state() + private _isOpen = false; + #sectionSidebarContext = new UmbSectionSidebarContext(this); + constructor() { + super(); + + this.observe(this.#sectionSidebarContext.contextMenuIsOpen, (value) => { + this._isOpen = value; + }); + } + render() { - return html` - - - - - - `; + return this._isOpen + ? html` ${this.#renderScrollContainer()} ` + : this.#renderScrollContainer(); + } + + #renderScrollContainer() { + return html` `; } static styles = [ From 341ca9dd21ddfcd9436f0a25c13a40d751af95d6 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Sun, 28 Apr 2024 14:02:37 +0200 Subject: [PATCH 62/79] require host in open/toggle method --- .../section-sidebar.context.ts | 21 +++++++++++++------ .../core/section/section-sidebar/types.ts | 5 +++++ 2 files changed, 20 insertions(+), 6 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.context.ts index 839d76ae90..e845b8eff7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.context.ts @@ -1,3 +1,4 @@ +import type { UmbOpenContextMenuArgs } from './types.js'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; @@ -16,21 +17,24 @@ export class UmbSectionSidebarContext extends UmbContextBase(undefined); headline = this.#headline.asObservable(); + #contextElement: HTMLElement | undefined = undefined; + constructor(host: UmbControllerHost) { super(host, UMB_SECTION_SIDEBAR_CONTEXT); } - toggleContextMenu(entityType: string, unique: string | null | undefined, headline: string | undefined) { - this.openContextMenu(entityType, unique, headline); + toggleContextMenu(host: HTMLElement, args: UmbOpenContextMenuArgs) { + this.openContextMenu(host, args); } // TODO: we wont get notified about tree item name changes because we don't have a subscription // we need to figure out how we best can handle this when we only know the entity and unique id - openContextMenu(entityType: string, unique: string | null | undefined, headline: string | undefined) { - this.#entityType.setValue(entityType); - this.#unique.setValue(unique); - this.#headline.setValue(headline); + openContextMenu(host: HTMLElement, args: UmbOpenContextMenuArgs) { + this.#entityType.setValue(args.entityType); + this.#unique.setValue(args.unique); + this.#headline.setValue(args.headline); this.#contextMenuIsOpen.setValue(true); + this.#contextElement = host; } closeContextMenu() { @@ -38,6 +42,11 @@ export class UmbSectionSidebarContext extends UmbContextBase Date: Sun, 28 Apr 2024 14:05:17 +0200 Subject: [PATCH 63/79] align method names --- .../core/section/section-sidebar/section-sidebar.context.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.context.ts index e845b8eff7..69d9348efb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.context.ts @@ -45,7 +45,7 @@ export class UmbSectionSidebarContext extends UmbContextBase Date: Sun, 28 Apr 2024 14:11:30 +0200 Subject: [PATCH 64/79] proxy context requests --- .../section-sidebar-context-menu.element.ts | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar-context-menu/section-sidebar-context-menu.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar-context-menu/section-sidebar-context-menu.element.ts index b17d9635c8..16cd02b42e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar-context-menu/section-sidebar-context-menu.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar-context-menu/section-sidebar-context-menu.element.ts @@ -4,6 +4,8 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, nothing, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { observeMultiple } from '@umbraco-cms/backoffice/observable-api'; +import type { UmbContextRequestEvent } from '@umbraco-cms/backoffice/context-api'; +import { UMB_CONTENT_REQUEST_EVENT_TYPE } from '@umbraco-cms/backoffice/context-api'; @customElement('umb-section-sidebar-context-menu') export class UmbSectionSidebarContextMenuElement extends UmbLitElement { @@ -39,6 +41,19 @@ export class UmbSectionSidebarContextMenuElement extends UmbLitElement { this.removeUmbControllerByAlias('_observeHeadline'); } }); + + this.addEventListener(UMB_CONTENT_REQUEST_EVENT_TYPE, this.#proxyContextRequests as EventListener); + } + + #proxyContextRequests(event: UmbContextRequestEvent) { + if (!this.#sectionSidebarContext) return; + // Note for this hack (The if-sentence): [NL] + // We do not currently have a good enough control to ensure that the proxy is last, meaning if another context is provided at this element, it might respond after the proxy event has been dispatched. + // To avoid such this hack just prevents proxying the event if its a request for its own context. + if (event.contextAlias !== UMB_SECTION_SIDEBAR_CONTEXT.contextAlias) { + event.stopImmediatePropagation(); + this.#sectionSidebarContext.getContextElement()?.dispatchEvent(event.clone()); + } } #observeEntityModel() { @@ -94,6 +109,11 @@ export class UmbSectionSidebarContextMenuElement extends UmbLitElement { : nothing; } + disconnectedCallback(): void { + super.disconnectedCallback(); + this.removeEventListener(UMB_CONTENT_REQUEST_EVENT_TYPE, this.#proxyContextRequests as EventListener); + } + static styles = [ UmbTextStyles, css` From ce33c144369305e3499c2afaf01b5196d77b5fad Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Sun, 28 Apr 2024 14:12:33 +0200 Subject: [PATCH 65/79] pass host and args --- .../entity-actions-bundle/entity-actions-bundle.element.ts | 6 +++++- .../tree/tree-item/tree-item-base/tree-item-context-base.ts | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts index 98b3c13bea..71090ba875 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts @@ -75,7 +75,11 @@ export class UmbEntityActionsBundleElement extends UmbLitElement { #openContextMenu() { if (!this.entityType) throw new Error('Entity type is not defined'); if (this.unique === undefined) throw new Error('Unique is not defined'); - this.#sectionSidebarContext?.toggleContextMenu(this.entityType, this.unique, this.label); + this.#sectionSidebarContext?.toggleContextMenu(this, { + entityType: this.entityType, + unique: this.unique, + headline: this.label, + }); } async #onFirstActionClick(event: PointerEvent) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts index 3c7a25dfac..93825c96df 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts @@ -180,7 +180,11 @@ export abstract class UmbTreeItemContextBase Date: Mon, 29 Apr 2024 08:52:55 +0200 Subject: [PATCH 66/79] Revert "only render context menu when it is open" This reverts commit d84d1fc55d73458b10aea6be63491cb48ebef22d. --- .../section-sidebar.element.ts | 27 ++++++------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.element.ts index c330a5a1dd..65da98a094 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.element.ts @@ -1,31 +1,20 @@ import { UmbSectionSidebarContext } from './section-sidebar.context.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { css, html, customElement, state, nothing } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; @customElement('umb-section-sidebar') export class UmbSectionSidebarElement extends UmbLitElement { - @state() - private _isOpen = false; - #sectionSidebarContext = new UmbSectionSidebarContext(this); - constructor() { - super(); - - this.observe(this.#sectionSidebarContext.contextMenuIsOpen, (value) => { - this._isOpen = value; - }); - } - render() { - return this._isOpen - ? html` ${this.#renderScrollContainer()} ` - : this.#renderScrollContainer(); - } - - #renderScrollContainer() { - return html` `; + return html` + + + + + + `; } static styles = [ From e503d38f3837a17bd1b99fb670aa0aa55c7a8924 Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Mon, 29 Apr 2024 10:05:24 +0200 Subject: [PATCH 67/79] fix imports --- src/Umbraco.Web.UI.Client/src/packages/data-type/manifests.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/manifests.ts index 9f7e47216d..a7ed758226 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/manifests.ts @@ -6,8 +6,6 @@ import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as searchProviderManifests } from './search/manifests.js'; import { manifests as treeManifests } from './tree/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; -import { manifests as modalManifests } from './modals/manifests.js'; -import { manifests as collectionManifests } from './collection/manifests.js'; import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ From c3d39f5cdb5aab105f66ccda38d734fb0d958876 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 29 Apr 2024 18:30:22 +0100 Subject: [PATCH 68/79] Replaces "owner" with "creator" for consistency with the server-side. --- .../src/mocks/data/data-type/data-type.data.ts | 4 ++-- .../documents/documents/collection/views/index.ts | 3 +-- .../table/media-table-collection-view.element.ts | 1 + ...put-collection-content-type-property.element.ts | 14 ++++++++++++-- .../template-field-dropdown-list.element.ts | 2 +- 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts index e677d461ff..f26833d53e 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts @@ -804,7 +804,7 @@ export const data: Array = [ value: [ { alias: 'sortOrder', header: 'Sort order', isSystem: true, nameTemplate: '' }, { alias: 'updateDate', header: 'Last edited', isSystem: true }, - { alias: 'owner', header: 'Created by', isSystem: true }, + { alias: 'creator', header: 'Created by', isSystem: true }, ], }, { alias: 'orderBy', value: 'updateDate' }, @@ -849,7 +849,7 @@ export const data: Array = [ value: [ { alias: 'sortOrder', header: 'Sort order', isSystem: true, nameTemplate: '' }, { alias: 'updateDate', header: 'Last edited', isSystem: true }, - { alias: 'owner', header: 'Created by', isSystem: true }, + { alias: 'creator', header: 'Created by', isSystem: true }, ], }, { alias: 'orderBy', value: 'updateDate' }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/index.ts index cbc7466fb6..ff87bbdd59 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/index.ts @@ -9,13 +9,12 @@ export function getPropertyValueByAlias(sortOrder: number, item: UmbDocumentColl case 'createDate': return item.createDate.toLocaleString(); case 'creator': + case 'owner': return item.creator; case 'entityName': return item.name; case 'entityState': return item.state.replace(/([A-Z])/g, ' $1'); - case 'owner': - return item.creator; case 'published': return item.state !== 'Draft' ? 'True' : 'False'; case 'sortOrder': diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts index 96b09094ba..64b1a0123e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts @@ -151,6 +151,7 @@ export class UmbMediaTableCollectionViewElement extends UmbLitElement { return item.createDate.toLocaleString(); case 'entityName': return item.name; + case 'creator': case 'owner': return item.creator; case 'sortOrder': diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/config/column/components/input-collection-content-type-property.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/config/column/components/input-collection-content-type-property.element.ts index f640501968..3c54003ba6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/config/column/components/input-collection-content-type-property.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/config/column/components/input-collection-content-type-property.element.ts @@ -57,7 +57,12 @@ export class UmbInputCollectionContentTypePropertyElement extends UUIFormControl value: 'createDate', icon: 'icon-settings', }, - { label: this.localize.term('content_createBy'), description: 'owner', value: 'owner', icon: 'icon-settings' }, + { + label: this.localize.term('content_createBy'), + description: 'creator', + value: 'creator', + icon: 'icon-settings', + }, { label: this.localize.term('content_isPublished'), description: 'published', @@ -124,7 +129,12 @@ export class UmbInputCollectionContentTypePropertyElement extends UUIFormControl value: 'createDate', icon: 'icon-settings', }, - { label: this.localize.term('content_createBy'), description: 'owner', value: 'owner', icon: 'icon-settings' }, + { + label: this.localize.term('content_createBy'), + description: 'creator', + value: 'creator', + icon: 'icon-settings', + }, { label: this.localize.term('general_sort'), description: 'sortOrder', diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/components/template-field-dropdown-list/template-field-dropdown-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/components/template-field-dropdown-list/template-field-dropdown-list.element.ts index 725cf34067..cd6a70cece 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/components/template-field-dropdown-list/template-field-dropdown-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/components/template-field-dropdown-list/template-field-dropdown-list.element.ts @@ -69,7 +69,7 @@ export class UmbTemplateFieldDropdownListElement extends UmbLitElement { { alias: 'updateDate', name: this.localize.term('content_updateDate') }, { alias: 'updater', name: this.localize.term('content_updatedBy') }, { alias: 'createDate', name: this.localize.term('content_createDate') }, - { alias: 'owner', name: this.localize.term('content_createBy') }, + { alias: 'creator', name: this.localize.term('content_createBy') }, { alias: 'published', name: this.localize.term('content_isPublished') }, { alias: 'contentTypeAlias', name: this.localize.term('content_documentType') }, ]; From 5d49ed805b38966eb8181be2a5096abf014a5d4c Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 29 Apr 2024 18:31:06 +0100 Subject: [PATCH 69/79] Replaces "entityName" with "name" for consistency with the server-side. --- .../packages/documents/documents/collection/views/index.ts | 2 +- .../views/table/document-table-collection-view.element.ts | 2 +- .../views/table/media-table-collection-view.element.ts | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/index.ts index ff87bbdd59..095a5a088c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/index.ts @@ -11,7 +11,7 @@ export function getPropertyValueByAlias(sortOrder: number, item: UmbDocumentColl case 'creator': case 'owner': return item.creator; - case 'entityName': + case 'name': return item.name; case 'entityState': return item.state.replace(/([A-Z])/g, ' $1'); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/document-table-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/document-table-collection-view.element.ts index a7f20868bd..f24df1ca1b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/document-table-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/document-table-collection-view.element.ts @@ -41,7 +41,7 @@ export class UmbDocumentTableCollectionViewElement extends UmbLitElement { #systemColumns: Array = [ { name: this.localize.term('general_name'), - alias: 'entityName', + alias: 'name', elementName: 'umb-document-table-column-name', allowSorting: true, }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts index 64b1a0123e..bf64d7a0f2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts @@ -39,7 +39,7 @@ export class UmbMediaTableCollectionViewElement extends UmbLitElement { #systemColumns: Array = [ { name: this.localize.term('general_name'), - alias: 'entityName', + alias: 'name', elementName: 'umb-media-table-column-name', allowSorting: true, }, @@ -149,7 +149,7 @@ export class UmbMediaTableCollectionViewElement extends UmbLitElement { switch (alias) { case 'createDate': return item.createDate.toLocaleString(); - case 'entityName': + case 'name': return item.name; case 'creator': case 'owner': From 0c4651eb472d45c8c63ab0421b151619f2a70538 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 29 Apr 2024 18:34:39 +0100 Subject: [PATCH 70/79] Replaces "entityState" with "state" for consistency with the server-side. --- .../packages/documents/documents/collection/views/index.ts | 5 +++-- .../views/table/document-table-collection-view.element.ts | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/index.ts index 095a5a088c..daed2df844 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/index.ts @@ -1,4 +1,5 @@ import type { UmbDocumentCollectionItemModel } from '../types.js'; +import { fromCamelCase } from '@umbraco-cms/backoffice/utils'; export { UMB_DOCUMENT_GRID_COLLECTION_VIEW_ALIAS, UMB_DOCUMENT_TABLE_COLLECTION_VIEW_ALIAS } from './manifests.js'; @@ -13,8 +14,8 @@ export function getPropertyValueByAlias(sortOrder: number, item: UmbDocumentColl return item.creator; case 'name': return item.name; - case 'entityState': - return item.state.replace(/([A-Z])/g, ' $1'); + case 'state': + return fromCamelCase(item.state); case 'published': return item.state !== 'Draft' ? 'True' : 'False'; case 'sortOrder': diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/document-table-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/document-table-collection-view.element.ts index f24df1ca1b..c74937fa10 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/document-table-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/document-table-collection-view.element.ts @@ -47,9 +47,9 @@ export class UmbDocumentTableCollectionViewElement extends UmbLitElement { }, { name: this.localize.term('content_publishStatus'), - alias: 'entityState', + alias: 'state', elementName: 'umb-document-table-column-state', - allowSorting: true, + allowSorting: false, }, ]; From cfb24ade8f2bc303240814ee455dc7c45b65d465 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 29 Apr 2024 18:35:45 +0100 Subject: [PATCH 71/79] Implements correct `sortOrder` property Removes the faux sort order value. --- .../document-collection.server.data-source.ts | 1 + .../packages/documents/documents/collection/types.ts | 1 + .../grid/document-grid-collection-view.element.ts | 12 +++++------- .../documents/documents/collection/views/index.ts | 4 ++-- .../table/document-table-collection-view.element.ts | 6 ++---- .../media-collection.server.data-source.ts | 1 + .../src/packages/media/media/collection/types.ts | 1 + .../table/media-table-collection-view.element.ts | 10 ++++------ .../property-editors/collection/manifests.ts | 2 +- 9 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/repository/document-collection.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/repository/document-collection.server.data-source.ts index c6899b78ed..6c726464d5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/repository/document-collection.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/repository/document-collection.server.data-source.ts @@ -43,6 +43,7 @@ export class UmbDocumentCollectionServerDataSource implements UmbCollectionDataS creator: item.creator, icon: item.documentType.icon, name: variant.name, + sortOrder: item.sortOrder, state: variant.state, updateDate: new Date(variant.updateDate), updater: item.updater, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/types.ts index 103dde6ac0..ffcbcb13d3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/types.ts @@ -17,6 +17,7 @@ export interface UmbDocumentCollectionItemModel { creator?: string | null; icon: string; name: string; + sortOrder: number; state: string; updateDate: Date; updater?: string | null; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/grid/document-grid-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/grid/document-grid-collection-view.element.ts index ac83466e2f..8ec535ba7f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/grid/document-grid-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/grid/document-grid-collection-view.element.ts @@ -96,14 +96,13 @@ export class UmbDocumentGridCollectionViewElement extends UmbLitElement { ${repeat( this._items, (item) => item.unique, - (item, index) => this.#renderCard(index, item), + (item) => this.#renderCard(item), )}
`; } - #renderCard(index: number, item: UmbDocumentCollectionItemModel) { - const sortOrder = this._skip + index; + #renderCard(item: UmbDocumentCollectionItemModel) { return html` this.#onSelect(item)} @deselected=${() => this.#onDeselect(item)}> - ${this.#renderState(item)} ${this.#renderProperties(sortOrder, item)} + ${this.#renderState(item)} ${this.#renderProperties(item)} `; } @@ -142,15 +141,14 @@ export class UmbDocumentGridCollectionViewElement extends UmbLitElement { } } - #renderProperties(sortOrder: number, item: UmbDocumentCollectionItemModel) { + #renderProperties(item: UmbDocumentCollectionItemModel) { if (!this._userDefinedProperties) return; return html`
    ${repeat( this._userDefinedProperties, (column) => column.alias, - (column) => - html`
  • ${column.header}: ${getPropertyValueByAlias(sortOrder, item, column.alias)}
  • `, + (column) => html`
  • ${column.header}: ${getPropertyValueByAlias(item, column.alias)}
  • `, )}
`; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/index.ts index daed2df844..bad7d3c6de 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/index.ts @@ -3,7 +3,7 @@ import { fromCamelCase } from '@umbraco-cms/backoffice/utils'; export { UMB_DOCUMENT_GRID_COLLECTION_VIEW_ALIAS, UMB_DOCUMENT_TABLE_COLLECTION_VIEW_ALIAS } from './manifests.js'; -export function getPropertyValueByAlias(sortOrder: number, item: UmbDocumentCollectionItemModel, alias: string) { +export function getPropertyValueByAlias(item: UmbDocumentCollectionItemModel, alias: string) { switch (alias) { case 'contentTypeAlias': return item.contentTypeAlias; @@ -19,7 +19,7 @@ export function getPropertyValueByAlias(sortOrder: number, item: UmbDocumentColl case 'published': return item.state !== 'Draft' ? 'True' : 'False'; case 'sortOrder': - return sortOrder; + return item.sortOrder; case 'updateDate': return item.updateDate.toLocaleString(); case 'updater': diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/document-table-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/document-table-collection-view.element.ts index c74937fa10..943588f16e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/document-table-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/document-table-collection-view.element.ts @@ -126,16 +126,14 @@ export class UmbDocumentTableCollectionViewElement extends UmbLitElement { } #createTableItems(items: Array) { - this._tableItems = items.map((item, rowIndex) => { + this._tableItems = items.map((item) => { if (!item.unique) throw new Error('Item id is missing.'); - const sortOrder = this._skip + rowIndex; - const data = this._tableColumns?.map((column) => { return { columnAlias: column.alias, - value: column.elementName ? item : getPropertyValueByAlias(sortOrder, item, column.alias), + value: column.elementName ? item : getPropertyValueByAlias(item, column.alias), }; }) ?? []; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/repository/media-collection.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/repository/media-collection.server.data-source.ts index d8a243868f..b75fadfff8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/repository/media-collection.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/repository/media-collection.server.data-source.ts @@ -36,6 +36,7 @@ export class UmbMediaCollectionServerDataSource implements UmbCollectionDataSour creator: item.creator, icon: item.mediaType.icon, name: variant.name, + sortOrder: item.sortOrder, updateDate: new Date(variant.updateDate), values: item.values.map((item) => { return { alias: item.alias, value: item.value as string }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/types.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/types.ts index 9a5246af9f..1ae06b64f7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/types.ts @@ -14,6 +14,7 @@ export interface UmbMediaCollectionItemModel { creator?: string | null; icon: string; name: string; + sortOrder: number; updateDate: Date; values: Array<{ alias: string; value: string }>; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts index bf64d7a0f2..044508a91e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts @@ -124,16 +124,14 @@ export class UmbMediaTableCollectionViewElement extends UmbLitElement { this.#createTableHeadings(); } - this._tableItems = items.map((item, rowIndex) => { + this._tableItems = items.map((item) => { if (!item.unique) throw new Error('Item id is missing.'); - const sortOrder = this._skip + rowIndex; - const data = this._tableColumns?.map((column) => { return { columnAlias: column.alias, - value: column.elementName ? item : this.#getPropertyValueByAlias(sortOrder, item, column.alias), + value: column.elementName ? item : this.#getPropertyValueByAlias(item, column.alias), }; }) ?? []; @@ -145,7 +143,7 @@ export class UmbMediaTableCollectionViewElement extends UmbLitElement { }); } - #getPropertyValueByAlias(sortOrder: number, item: UmbMediaCollectionItemModel, alias: string) { + #getPropertyValueByAlias(item: UmbMediaCollectionItemModel, alias: string) { switch (alias) { case 'createDate': return item.createDate.toLocaleString(); @@ -155,7 +153,7 @@ export class UmbMediaTableCollectionViewElement extends UmbLitElement { case 'owner': return item.creator; case 'sortOrder': - return sortOrder; + return item.sortOrder; case 'updateDate': return item.updateDate.toLocaleString(); default: diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/manifests.ts index aa4f383b1c..c008f1a678 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/manifests.ts @@ -89,7 +89,7 @@ const propertyEditorUiManifest: ManifestPropertyEditorUi = { ], }, { alias: 'pageSize', value: 10 }, - { alias: 'orderBy', value: 'updateDate' }, + { alias: 'orderBy', value: 'sortOrder' }, { alias: 'orderDirection', value: 'desc' }, { alias: 'bulkActionPermissions', From 545ba506073a43e47e03edb354e2d74d4e9ad1a5 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Tue, 30 Apr 2024 11:35:03 +0100 Subject: [PATCH 72/79] Changed the `skip`/`take` fallback to use a logical OR (`||`) instead of a nullish coalescing (`??`), as the value may be a `NaN` or even `0`. --- .../repository/document-collection.server.data-source.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/repository/document-collection.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/repository/document-collection.server.data-source.ts index 6c726464d5..99091d6d97 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/repository/document-collection.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/repository/document-collection.server.data-source.ts @@ -24,8 +24,8 @@ export class UmbDocumentCollectionServerDataSource implements UmbCollectionDataS orderCulture: query.orderCulture ?? 'en-US', orderDirection: query.orderDirection === 'asc' ? DirectionModel.ASCENDING : DirectionModel.DESCENDING, filter: query.filter, - skip: query.skip ?? 0, - take: query.take ?? 100, + skip: query.skip || 0, + take: query.take || 100, }; const { data, error } = await tryExecuteAndNotify(this.#host, DocumentService.getCollectionDocumentById(params)); From 0186527c44aa8d4c1fc94f908001dd401dd4948d Mon Sep 17 00:00:00 2001 From: leekelleher Date: Tue, 30 Apr 2024 11:37:15 +0100 Subject: [PATCH 73/79] Temporary fix for the child name button to navigate through to the target document. --- .../document-table-column-name.element.ts | 45 ++++++++++--------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/column-layouts/document-table-column-name.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/column-layouts/document-table-column-name.element.ts index 2ee3f9321e..100d870c1d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/column-layouts/document-table-column-name.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/column-layouts/document-table-column-name.element.ts @@ -1,7 +1,7 @@ import type { UmbDocumentCollectionItemModel } from '../../../types.js'; import { css, customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UMB_WORKSPACE_MODAL, UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/modal'; +//import { UMB_WORKSPACE_MODAL, UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/modal'; import type { UmbTableColumn, UmbTableColumnLayoutElement, UmbTableItem } from '@umbraco-cms/backoffice/components'; @customElement('umb-document-table-column-name') @@ -21,30 +21,33 @@ export class UmbDocumentTableColumnNameElement extends UmbLitElement implements constructor() { super(); - new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL) - .addAdditionalPath('document') - .onSetup(() => { - return { data: { entityType: 'document', preset: {} } }; - }) - .observeRouteBuilder((routeBuilder) => { - this._editDocumentPath = routeBuilder({}); - }); + // new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL) + // .addAdditionalPath('document') + // .onSetup(() => { + // return { data: { entityType: 'document', preset: {} } }; + // }) + // .observeRouteBuilder((routeBuilder) => { + // this._editDocumentPath = routeBuilder({}); + // }); + + this._editDocumentPath = '/section/content/workspace/document/'; } - #onClick(event: Event) { - // TODO: [LK] Review the `stopPropagation` usage, as it causes a page reload. - // But we still need a say to prevent the `umb-table` from triggering a selection event. - event.stopPropagation(); - } + // #onClick(event: Event) { + // // TODO: [LK] Review the `stopPropagation` usage, as it causes a page reload. + // // But we still need a say to prevent the `umb-table` from triggering a selection event. + // event.stopPropagation(); + // } render() { - return html``; + return html` + + `; } static styles = [ From 026a52847a07d00541255ab05570fd4b3e9d1f31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 30 Apr 2024 12:56:40 +0200 Subject: [PATCH 74/79] move proxy event handler --- .../section-sidebar-context-menu.element.ts | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar-context-menu/section-sidebar-context-menu.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar-context-menu/section-sidebar-context-menu.element.ts index 16cd02b42e..7e4c545168 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar-context-menu/section-sidebar-context-menu.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar-context-menu/section-sidebar-context-menu.element.ts @@ -41,19 +41,6 @@ export class UmbSectionSidebarContextMenuElement extends UmbLitElement { this.removeUmbControllerByAlias('_observeHeadline'); } }); - - this.addEventListener(UMB_CONTENT_REQUEST_EVENT_TYPE, this.#proxyContextRequests as EventListener); - } - - #proxyContextRequests(event: UmbContextRequestEvent) { - if (!this.#sectionSidebarContext) return; - // Note for this hack (The if-sentence): [NL] - // We do not currently have a good enough control to ensure that the proxy is last, meaning if another context is provided at this element, it might respond after the proxy event has been dispatched. - // To avoid such this hack just prevents proxying the event if its a request for its own context. - if (event.contextAlias !== UMB_SECTION_SIDEBAR_CONTEXT.contextAlias) { - event.stopImmediatePropagation(); - this.#sectionSidebarContext.getContextElement()?.dispatchEvent(event.clone()); - } } #observeEntityModel() { @@ -81,6 +68,17 @@ export class UmbSectionSidebarContextMenuElement extends UmbLitElement { this.#closeContextMenu(); } + #proxyContextRequests(event: UmbContextRequestEvent) { + if (!this.#sectionSidebarContext) return; + // Note for this hack (The if-sentence): [NL] + // We do not currently have a good enough control to ensure that the proxy is last, meaning if another context is provided at this element, it might respond after the proxy event has been dispatched. + // To avoid such this hack just prevents proxying the event if its a request for its own context. + if (event.contextAlias !== UMB_SECTION_SIDEBAR_CONTEXT.contextAlias) { + event.stopImmediatePropagation(); + this.#sectionSidebarContext.getContextElement()?.dispatchEvent(event.clone()); + } + } + render() { return html` ${this.#renderBackdrop()} @@ -99,7 +97,7 @@ export class UmbSectionSidebarContextMenuElement extends UmbLitElement { #renderModal() { return this._isOpen && this._unique !== undefined && this._entityType - ? html`
+ ? html`
${this._headline ? html`

${this.localize.string(this._headline)}

` : nothing} Date: Tue, 30 Apr 2024 13:44:07 +0200 Subject: [PATCH 75/79] align element type with modals --- .../core/section/section-sidebar/section-sidebar.context.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.context.ts index 69d9348efb..5fad1202bb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.context.ts @@ -17,19 +17,19 @@ export class UmbSectionSidebarContext extends UmbContextBase(undefined); headline = this.#headline.asObservable(); - #contextElement: HTMLElement | undefined = undefined; + #contextElement: Element | undefined = undefined; constructor(host: UmbControllerHost) { super(host, UMB_SECTION_SIDEBAR_CONTEXT); } - toggleContextMenu(host: HTMLElement, args: UmbOpenContextMenuArgs) { + toggleContextMenu(host: Element, args: UmbOpenContextMenuArgs) { this.openContextMenu(host, args); } // TODO: we wont get notified about tree item name changes because we don't have a subscription // we need to figure out how we best can handle this when we only know the entity and unique id - openContextMenu(host: HTMLElement, args: UmbOpenContextMenuArgs) { + openContextMenu(host: Element, args: UmbOpenContextMenuArgs) { this.#entityType.setValue(args.entityType); this.#unique.setValue(args.unique); this.#headline.setValue(args.headline); From 9f6f1ecfd9eb0ccbdfe5fe23f8daddab8418eabe Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 30 Apr 2024 13:44:18 +0200 Subject: [PATCH 76/79] pass host element instead of class --- .../tree/tree-item/tree-item-base/tree-item-context-base.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts index 93825c96df..d86bd67532 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts @@ -180,7 +180,7 @@ export abstract class UmbTreeItemContextBase Date: Tue, 30 Apr 2024 13:55:43 +0100 Subject: [PATCH 77/79] Fixes the child name button to open the document editor modal. --- .../document-table-column-name.element.ts | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/column-layouts/document-table-column-name.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/column-layouts/document-table-column-name.element.ts index 100d870c1d..1d9e39d4b3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/column-layouts/document-table-column-name.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/column-layouts/document-table-column-name.element.ts @@ -1,8 +1,9 @@ import type { UmbDocumentCollectionItemModel } from '../../../types.js'; import { css, customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -//import { UMB_WORKSPACE_MODAL, UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/modal'; +import { UMB_WORKSPACE_MODAL, UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/modal'; import type { UmbTableColumn, UmbTableColumnLayoutElement, UmbTableItem } from '@umbraco-cms/backoffice/components'; +import type { UUIButtonElement } from '@umbraco-cms/backoffice/external/uui'; @customElement('umb-document-table-column-name') export class UmbDocumentTableColumnNameElement extends UmbLitElement implements UmbTableColumnLayoutElement { @@ -21,32 +22,29 @@ export class UmbDocumentTableColumnNameElement extends UmbLitElement implements constructor() { super(); - // new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL) - // .addAdditionalPath('document') - // .onSetup(() => { - // return { data: { entityType: 'document', preset: {} } }; - // }) - // .observeRouteBuilder((routeBuilder) => { - // this._editDocumentPath = routeBuilder({}); - // }); - - this._editDocumentPath = '/section/content/workspace/document/'; + new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL) + .addAdditionalPath('document') + .onSetup(() => { + return { data: { entityType: 'document', preset: {} } }; + }) + .observeRouteBuilder((routeBuilder) => { + this._editDocumentPath = routeBuilder({}); + }); } - // #onClick(event: Event) { - // // TODO: [LK] Review the `stopPropagation` usage, as it causes a page reload. - // // But we still need a say to prevent the `umb-table` from triggering a selection event. - // event.stopPropagation(); - // } + #onClick(event: Event & { target: UUIButtonElement }) { + event.preventDefault(); + event.stopPropagation(); + window.history.pushState({}, '', event.target.href); + } render() { return html` + label=${this.value.name} + @click=${this.#onClick}> `; } From 48706124418f746a56f76cf5f2674e2d154437f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 30 Apr 2024 15:25:14 +0200 Subject: [PATCH 78/79] fix --- .../property-editor-ui-picker-modal.element.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/property-editor-ui-picker/property-editor-ui-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/property-editor-ui-picker/property-editor-ui-picker-modal.element.ts index 7a1894f23f..6c19375a8e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/property-editor-ui-picker/property-editor-ui-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/property-editor-ui-picker/property-editor-ui-picker-modal.element.ts @@ -30,14 +30,13 @@ export class UmbPropertyEditorUIPickerModalElement extends UmbModalBaseElement< connectedCallback(): void { super.connectedCallback(); - this._submitLabel = this.data?.submitLabel ?? this._submitLabel; + // TODO: We never parse on a submit label, so this seem weird as we don't enable this of other places. + //this._submitLabel = this.data?.submitLabel ?? this._submitLabel; this.#usePropertyEditorUIs(); } #usePropertyEditorUIs() { - if (!this.data) return; - this.observe(umbExtensionsRegistry.byType('propertyEditorUi'), (propertyEditorUIs) => { // Only include Property Editor UIs which has Property Editor Schema Alias this._propertyEditorUIs = propertyEditorUIs.filter( From 561bbdb0249cdd53fa9871f981ae098dc2dc6719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 30 Apr 2024 20:08:13 +0200 Subject: [PATCH 79/79] clean up --- .../section-sidebar-context-menu.element.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar-context-menu/section-sidebar-context-menu.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar-context-menu/section-sidebar-context-menu.element.ts index 7e4c545168..c1cdbe7762 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar-context-menu/section-sidebar-context-menu.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar-context-menu/section-sidebar-context-menu.element.ts @@ -107,11 +107,6 @@ export class UmbSectionSidebarContextMenuElement extends UmbLitElement { : nothing; } - disconnectedCallback(): void { - super.disconnectedCallback(); - this.removeEventListener(UMB_CONTENT_REQUEST_EVENT_TYPE, this.#proxyContextRequests as EventListener); - } - static styles = [ UmbTextStyles, css`