'use client'; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { getTranslation } from '@payloadcms/translations'; import { dequal } from 'dequal/lite'; import { transformWhereQuery, validateWhereQuery } from 'payload/shared'; import React, { useMemo } from 'react'; import { useAuth } from '../../providers/Auth/index.js'; import { useListQuery } from '../../providers/ListQuery/index.js'; import { useTranslation } from '../../providers/Translation/index.js'; import { reduceFieldsToOptions } from '../../utilities/reduceFieldsToOptions.js'; import { Button } from '../Button/index.js'; import { Condition } from './Condition/index.js'; import './index.scss'; import { fieldTypeConditions, getValidFieldOperators } from './field-types.js'; const baseClass = 'where-builder'; /** * The WhereBuilder component is used to render the filter controls for a collection's list view. * It is part of the {@link ListControls} component which is used to render the controls (search, filter, where). */ export const WhereBuilder = props => { const { collectionPluralLabel, collectionSlug, fields, renderedFilters, resolvedFilterOptions } = props; const { i18n, t } = useTranslation(); const { permissions } = useAuth(); const fieldPermissions = permissions?.collections?.[collectionSlug]?.fields; const reducedFields = useMemo(() => reduceFieldsToOptions({ fieldPermissions, fields, i18n }), [fieldPermissions, fields, i18n]); const { handleWhereChange, query } = useListQuery(); const conditions = useMemo(() => { const whereFromSearch = query.where; if (whereFromSearch) { if (validateWhereQuery(whereFromSearch)) { return whereFromSearch.or; } // Transform the where query to be in the right format. This will transform something simple like [text][equals]=example%20post to the right format const transformedWhere = transformWhereQuery(whereFromSearch); if (validateWhereQuery(transformedWhere)) { return transformedWhere.or; } console.warn(`Invalid where query in URL: ${JSON.stringify(whereFromSearch)}`); // eslint-disable-line no-console } return []; }, [query.where]); const addCondition = React.useCallback(async ({ andIndex, field, orIndex, relation }) => { const newConditions = [...conditions]; const defaultOperator = fieldTypeConditions[field.field.type].operators[0].value; if (relation === 'and') { newConditions[orIndex].and.splice(andIndex, 0, { [String(field.value)]: { [defaultOperator]: undefined } }); } else { newConditions.push({ and: [{ [String(field.value)]: { [defaultOperator]: undefined } }] }); } await handleWhereChange({ or: newConditions }); }, [conditions, handleWhereChange]); const updateCondition = React.useCallback(async ({ andIndex: andIndex_0, field: field_0, operator: incomingOperator, orIndex: orIndex_0, value }) => { const existingCondition = conditions[orIndex_0].and[andIndex_0]; if (typeof existingCondition === 'object' && field_0.value) { const { validOperator } = getValidFieldOperators({ field: field_0.field, operator: incomingOperator }); // Skip if nothing changed const existingValue = existingCondition[String(field_0.value)]?.[validOperator]; if (typeof existingValue !== 'undefined' && existingValue === value) { return; } const newRowCondition = { [String(field_0.value)]: { [validOperator]: value } }; if (dequal(existingCondition, newRowCondition)) { return; } const newConditions_0 = [...conditions]; newConditions_0[orIndex_0].and[andIndex_0] = newRowCondition; await handleWhereChange({ or: newConditions_0 }); } }, [conditions, handleWhereChange]); const removeCondition = React.useCallback(async ({ andIndex: andIndex_1, orIndex: orIndex_1 }) => { const newConditions_1 = [...conditions]; newConditions_1[orIndex_1].and.splice(andIndex_1, 1); if (newConditions_1[orIndex_1].and.length === 0) { newConditions_1.splice(orIndex_1, 1); } await handleWhereChange({ or: newConditions_1 }); }, [conditions, handleWhereChange]); return /*#__PURE__*/_jsxs("div", { className: baseClass, children: [conditions.length > 0 && /*#__PURE__*/_jsxs(React.Fragment, { children: [/*#__PURE__*/_jsx("p", { className: `${baseClass}__label`, children: t('general:filterWhere', { label: getTranslation(collectionPluralLabel, i18n) }) }), /*#__PURE__*/_jsx("ul", { className: `${baseClass}__or-filters`, children: conditions.map((or, orIndex_2) => { const compoundOrKey = `${orIndex_2}_${Array.isArray(or?.and) ? or.and.length : ''}`; return /*#__PURE__*/_jsxs("li", { children: [orIndex_2 !== 0 && /*#__PURE__*/_jsx("div", { className: `${baseClass}__label`, children: t('general:or') }), /*#__PURE__*/_jsx("ul", { className: `${baseClass}__and-filters`, children: Array.isArray(or?.and) && or.and.map((_, andIndex_2) => { const condition = conditions[orIndex_2].and[andIndex_2]; const fieldPath = Object.keys(condition)[0]; const operator = Object.keys(condition?.[fieldPath] || {})?.[0] || undefined; const value_0 = condition?.[fieldPath]?.[operator] || undefined; return /*#__PURE__*/_jsxs("li", { children: [andIndex_2 !== 0 && /*#__PURE__*/_jsx("div", { className: `${baseClass}__label`, children: t('general:and') }), /*#__PURE__*/_jsx(Condition, { addCondition: addCondition, andIndex: andIndex_2, fieldPath: fieldPath, filterOptions: resolvedFilterOptions?.get(fieldPath), operator: operator, orIndex: orIndex_2, reducedFields: reducedFields, removeCondition: removeCondition, RenderedFilter: renderedFilters?.get(fieldPath), updateCondition: updateCondition, value: value_0 })] }, andIndex_2); }) })] }, compoundOrKey); }) }), /*#__PURE__*/_jsx(Button, { buttonStyle: "icon-label", className: `${baseClass}__add-or`, icon: "plus", iconPosition: "left", iconStyle: "with-border", onClick: async () => { await addCondition({ andIndex: 0, field: reducedFields.find(field_1 => !field_1.field.admin?.disableListFilter), orIndex: conditions.length, relation: 'or' }); }, children: t('general:or') })] }), conditions.length === 0 && /*#__PURE__*/_jsxs("div", { className: `${baseClass}__no-filters`, children: [/*#__PURE__*/_jsx("div", { className: `${baseClass}__label`, children: t('general:noFiltersSet') }), /*#__PURE__*/_jsx(Button, { buttonStyle: "icon-label", className: `${baseClass}__add-first-filter`, icon: "plus", iconPosition: "left", iconStyle: "with-border", onClick: async () => { if (reducedFields.length > 0) { await addCondition({ andIndex: 0, field: reducedFields.find(field_2 => !field_2.field.admin?.disableListFilter), orIndex: conditions.length, relation: 'or' }); } }, children: t('general:addFilter') })] })] }); }; //# sourceMappingURL=index.js.map