diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/modals/query-builder/query-builder-filter.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/modals/query-builder/query-builder-filter.element.ts index 70380db2f0..717f5aadf9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/modals/query-builder/query-builder-filter.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/modals/query-builder/query-builder-filter.element.ts @@ -1,5 +1,5 @@ import { UUITextStyles } from '@umbraco-ui/uui-css'; -import { css, html } from 'lit'; +import { PropertyValueMap, css, html } from 'lit'; import { customElement, property, query, state } from 'lit/decorators.js'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { @@ -22,8 +22,11 @@ export class UmbQueryBuilderFilterElement extends UmbLitElement { @property({ type: Object, attribute: false }) filter: TemplateQueryExecuteFilterPresentationModel = {}; + @property({ type: Boolean }) + unremovable = false; + @property({ type: Object, attribute: false }) - settings: TemplateQuerySettingsResponseModel | null = null; + settings?: TemplateQuerySettingsResponseModel; @state() currentPropertyType: TemplateQueryPropertyTypeModel | null = null; @@ -53,6 +56,32 @@ export class UmbQueryBuilderFilterElement extends UmbLitElement { this.filter = { ...this.filter, operator: undefined }; } + #resetFilter() { + this.filter = {}; + } + + #removeOrReset() { + if (this.unremovable) this.#resetFilter(); + else this.dispatchEvent(new Event('remove-filter')); + } + + #addFilter() { + this.dispatchEvent(new Event('add-filter')); + } + + get isFilterValid(): boolean { + return Object.keys(this.filter).length === 3 && Object.values(this.filter).every((v) => !!v); + } + + protected willUpdate(_changedProperties: PropertyValueMap | Map): void { + if (_changedProperties.has('filter')) { + + if (this.isFilterValid) { + this.dispatchEvent(new Event('update-query')); + } + } + } + private _renderOperatorsDropdown() { return html` ${this.filter?.operator ?? ''} @@ -85,7 +114,8 @@ export class UmbQueryBuilderFilterElement extends UmbLitElement { } render() { - return html`where + return html` + ${this.unremovable ? 'where' : 'and'} ${this.filter?.propertyAlias ?? ''} @@ -98,7 +128,16 @@ export class UmbQueryBuilderFilterElement extends UmbLitElement { ${this.filter?.propertyAlias ? this._renderOperatorsDropdown() : ''} - ${this.filter?.operator ? this._renderConstraintValueInput() : ''} `; + ${this.filter?.operator ? this._renderConstraintValueInput() : ''} + + + + + `; } static styles = [ @@ -106,7 +145,10 @@ export class UmbQueryBuilderFilterElement extends UmbLitElement { css` :host { display: flex; + gap: 10px; + border-bottom: 1px solid #f3f3f5; align-items: center; + padding: 20px 0; } .options-list { diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/modals/query-builder/query-builder.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/modals/query-builder/query-builder.element.ts index 2d83f6d137..712a18ab8e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/modals/query-builder/query-builder.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/modals/query-builder/query-builder.element.ts @@ -1,6 +1,6 @@ import { UmbTemplateRepository } from '../../repository/template.repository.js'; import { UUIComboboxListElement, UUITextStyles } from '@umbraco-cms/backoffice/external/uui'; -import { css, html, customElement, state, query } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, state, query, queryAll } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/internal/modal'; import { UMB_DOCUMENT_PICKER_MODAL, @@ -8,6 +8,7 @@ import { UmbModalManagerContext, } from '@umbraco-cms/backoffice/modal'; import { + TemplateQueryExecuteFilterPresentationModel, TemplateQueryExecuteModel, TemplateQueryResultResponseModel, TemplateQuerySettingsResponseModel, @@ -15,6 +16,7 @@ import { import { UmbDocumentRepository } from '@umbraco-cms/backoffice/document'; import { UmbButtonWithDropdownElement } from '@umbraco-cms/backoffice/components'; import './query-builder-filter.element.js'; +import UmbQueryBuilderFilterElement from './query-builder-filter.element.js'; export interface TemplateQueryBuilderModalData { hidePartialViews?: boolean; @@ -32,6 +34,12 @@ export default class UmbChooseInsertTypeModalElement extends UmbModalBaseElement @query('#content-type-dropdown') private _contentTypeDropdown?: UmbButtonWithDropdownElement; + @query('#filter-container') + private _filterContainer?: HTMLElement; + + @queryAll('umb-query-builder-filter') + private _filterElements!: UmbQueryBuilderFilterElement[]; + #close() { this.modalContext?.reject(); } @@ -50,6 +58,7 @@ export default class UmbChooseInsertTypeModalElement extends UmbModalBaseElement #updateQueryRequest(update: TemplateQueryExecuteModel) { this._queryRequest = { ...this._queryRequest, ...update }; + this.#postTemplateQuery(); } @state() @@ -83,13 +92,13 @@ export default class UmbChooseInsertTypeModalElement extends UmbModalBaseElement if (data) this._queryBuilderSettings = data; } - async #postTemplateQuery() { + #postTemplateQuery = async () => { const { data, error } = await this.#templateRepository.postTemplateQueryExecute({ requestBody: this._queryRequest, }); console.log(this._queryRequest); if (data) this._templateQuery = { ...data }; - } + }; #openDocumentPicker = () => { this.#modalManagerContext @@ -117,13 +126,37 @@ export default class UmbChooseInsertTypeModalElement extends UmbModalBaseElement } } + #createFilterElement() { + const filterElement = document.createElement('umb-query-builder-filter'); + filterElement.settings = this._queryBuilderSettings; + filterElement.classList.add('row'); + filterElement.addEventListener('add-filter', this.#addFilterElement); + filterElement.addEventListener('remove-filter', this.#removeFilter); + filterElement.addEventListener('update-query', this.#updateFilters); + return filterElement; + } + #setContentType(event: Event) { const target = event.target as UUIComboboxListElement; this.#updateQueryRequest({ contentTypeAlias: (target.value as string) ?? '' }); - this.#postTemplateQuery(); this._contentTypeDropdown!.closePopover(); } + #addFilterElement = () => { + this._filterContainer?.appendChild(this.#createFilterElement()); + }; + + #updateFilters = () => { + + this.#updateQueryRequest({ filters: Array.from(this._filterElements)?.map((filter) => filter.filter) ?? [] }); + }; + + #removeFilter = (event: Event) => { + const target = event.target as UmbQueryBuilderFilterElement; + this._filterContainer?.removeChild(target); + this.#updateFilters(); + }; + render() { return html` @@ -148,7 +181,15 @@ export default class UmbChooseInsertTypeModalElement extends UmbModalBaseElement >${this._selectedRootContentName} - +
+ +
ordered by (allowed properties) ascending/descending @@ -199,6 +240,11 @@ export default class UmbChooseInsertTypeModalElement extends UmbModalBaseElement align-items: center; padding: 20px 0; } + + #filter-container { + flex-direction: column; + justify-content: flex-start; + } `, ]; }