Adds trashed/draft state to document search result items (#19057)

* Corrected class name

* Reverted `elementName` constant

* Replaced `UmbAppLanguageContext` type usage

with `typeof UMB_APP_LANGUAGE_CONTEXT.TYPE`.

* Refactored `render` method

- "Trashed", adds tag + faded text + strike-through
- "Draft", adds tag + faded text
- Replaced fallback hashtag icon with "icon-document"
- Reworked CSS rules
This commit is contained in:
Lee Kelleher
2025-04-17 08:16:30 +01:00
committed by GitHub
parent a9043a543e
commit 2fcf1c7812

View File

@@ -1,14 +1,20 @@
import type { UmbDocumentItemModel, UmbDocumentItemVariantModel } from '../item/repository/types.js';
import type { UmbSearchResultItemModel } from '@umbraco-cms/backoffice/search';
import {
classMap,
css,
customElement,
html,
nothing,
property,
state,
when,
} from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { css, customElement, html, nothing, property, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import type { UmbAppLanguageContext } from '@umbraco-cms/backoffice/language';
import { UMB_APP_LANGUAGE_CONTEXT } from '@umbraco-cms/backoffice/language';
import type { UmbSearchResultItemModel } from '@umbraco-cms/backoffice/search';
const elementName = 'umb-document-search-result-item';
@customElement(elementName)
export class UmbSearchResultItemElement extends UmbLitElement {
@customElement('umb-document-search-result-item')
export class UmbDocumentSearchResultItemElement extends UmbLitElement {
@property({ type: Object })
item?: UmbSearchResultItemModel & UmbDocumentItemModel;
@@ -30,14 +36,14 @@ export class UmbSearchResultItemElement extends UmbLitElement {
});
}
#observeAppCulture(context: UmbAppLanguageContext) {
#observeAppCulture(context: typeof UMB_APP_LANGUAGE_CONTEXT.TYPE) {
this.observe(context.appLanguageCulture, (value) => {
this._currentCulture = value;
this._variant = this.#getVariant(value);
});
}
#observeDefaultCulture(context: UmbAppLanguageContext) {
#observeDefaultCulture(context: typeof UMB_APP_LANGUAGE_CONTEXT.TYPE) {
this.observe(context.appDefaultLanguage, (value) => {
this._defaultCulture = value?.unique;
});
@@ -47,13 +53,8 @@ export class UmbSearchResultItemElement extends UmbLitElement {
return this.item?.variants.find((x) => x.culture === culture);
}
#isInvariant() {
const firstVariant = this.item?.variants[0];
return firstVariant?.culture === null;
}
#getLabel() {
if (this.#isInvariant()) {
if (this.item?.variants[0]?.culture === null) {
return this.item?.name ?? 'Unknown';
}
@@ -61,68 +62,76 @@ export class UmbSearchResultItemElement extends UmbLitElement {
return this._variant?.name ?? `(${fallbackName})`;
}
#getDraftState(): boolean {
if (this.item?.isTrashed) return false;
return this._variant?.state === 'Draft' || this.item?.variants[0]?.state === 'Draft';
}
override render() {
if (!this.item) return nothing;
return html`
<span class="item-icon">
${this.item.icon ? html`<umb-icon name="${this.item.icon}"></umb-icon>` : this.#renderHashTag()}
</span>
<span class="item-name"> ${this.#getLabel()} </span>
`;
}
const label = this.#getLabel();
const isDraft = this.#getDraftState();
const classes = {
trashed: this.item.isTrashed,
hasState: this.item.isTrashed || isDraft,
};
#renderHashTag() {
return html`
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path fill="none" d="M0 0h24v24H0z" />
<path
fill="currentColor"
d="M7.784 14l.42-4H4V8h4.415l.525-5h2.011l-.525 5h3.989l.525-5h2.011l-.525 5H20v2h-3.784l-.42 4H20v2h-4.415l-.525 5h-2.011l.525-5H9.585l-.525 5H7.049l.525-5H4v-2h3.784zm2.011 0h3.99l.42-4h-3.99l-.42 4z" />
</svg>
${when(
this.item.documentType.icon ?? this.item.icon,
(icon) => html`<umb-icon name=${icon}></umb-icon>`,
() => html`<uui-icon name="icon-document"></uui-icon>`,
)}
<span class=${classMap(classes)}>${label}</span>
<div class="extra">
${when(
this.item.isTrashed,
() => html`
<uui-tag look="secondary">
<umb-localize key="mediaPicker_trashed">Trashed</umb-localize>
</uui-tag>
`,
)}
${when(!this.item.isTrashed && isDraft, () => html`<uui-tag look="secondary">Draft</uui-tag>`)}
</div>
`;
}
static override styles = [
UmbTextStyles,
css`
:host {
padding: var(--uui-size-space-3) var(--uui-size-space-5);
border-radius: var(--uui-border-radius);
display: grid;
grid-template-columns: var(--uui-size-space-6) 1fr var(--uui-size-space-5);
align-items: center;
width: 100%;
outline-offset: -3px;
}
.item-icon {
margin-bottom: auto;
margin-top: 5px;
}
.item-icon {
opacity: 0.4;
}
.item-name {
padding: var(--uui-size-space-3) var(--uui-size-space-5);
display: flex;
flex-direction: column;
}
.item-icon > * {
height: 1rem;
display: flex;
width: min-content;
}
a {
text-decoration: none;
color: inherit;
gap: var(--uui-size-space-3);
align-items: center;
width: 100%;
> span {
flex: 1;
&.hasState {
opacity: 0.6;
}
&.trashed {
text-decoration: line-through;
}
}
}
`,
];
}
export { UmbSearchResultItemElement as element };
export { UmbDocumentSearchResultItemElement as element };
declare global {
interface HTMLElementTagNameMap {
[elementName]: UmbSearchResultItemElement;
'umb-document-search-result-item': UmbDocumentSearchResultItemElement;
}
}