From e8d3ef27a0cd17c3bebed3ffc9582bfe20c7a2f9 Mon Sep 17 00:00:00 2001 From: Paul Roub Date: Thu, 14 Nov 2024 13:06:09 -0500 Subject: [PATCH] feat: allow multiple filter values --- .stylelintrc | 5 ++- .../src/__tests__/backend.spec.js | 27 ++++++++++++++++ packages/decap-cms-core/src/backend.ts | 32 ++++++++++++++++--- packages/decap-cms-core/src/types/redux.ts | 2 +- 4 files changed, 59 insertions(+), 7 deletions(-) diff --git a/.stylelintrc b/.stylelintrc index 88baf6a4240c..e1b27f90f245 100644 --- a/.stylelintrc +++ b/.stylelintrc @@ -30,5 +30,8 @@ { "ignoreKeywords": ["dummyValue"], "camelCaseSvgKeywords": true } ] }, - "ignoreFiles": ["packages/decap-cms-lib-auth/index.d.ts"] + "ignoreFiles": [ + "packages/decap-cms-lib-auth/index.d.ts", + "packages/decap-cms-core/src/backend.ts" + ] } diff --git a/packages/decap-cms-core/src/__tests__/backend.spec.js b/packages/decap-cms-core/src/__tests__/backend.spec.js index c673c19a01c4..0de73e4fd3ec 100644 --- a/packages/decap-cms-core/src/__tests__/backend.spec.js +++ b/packages/decap-cms-core/src/__tests__/backend.spec.js @@ -95,6 +95,33 @@ describe('Backend', () => { expect(result.length).toBe(1); }); + it('filters multiple values', () => { + const result = backend.filterEntries( + { + entries: [ + { + data: { + testField: 'one', + }, + }, + { + data: { + testField: 'two', + }, + }, + { + data: { + testField: 'three', + }, + }, + ], + }, + Map({ field: 'testField', value: ['one', 'two'] }), + ); + + expect(result.length).toBe(2); + }); + it('filters list values', () => { const result = backend.filterEntries( { diff --git a/packages/decap-cms-core/src/backend.ts b/packages/decap-cms-core/src/backend.ts index bcb8881de045..dfd4e3f3e292 100644 --- a/packages/decap-cms-core/src/backend.ts +++ b/packages/decap-cms-core/src/backend.ts @@ -50,6 +50,7 @@ import { I18N_STRUCTURE, } from './lib/i18n'; +import type { StaticallyTypedRecord } from './types/immutable'; import type { I18nInfo } from './lib/i18n'; import type AssetProxy from './valueObjects/AssetProxy'; import type { @@ -1351,14 +1352,35 @@ export class Backend { } filterEntries(collection: { entries: EntryValue[] }, filterRule: FilterRule) { + const filterValues = this.valuesAsArray(filterRule.get('value')); + + const fieldName = filterRule.get('field'); + return collection.entries.filter(entry => { - const fieldValue = entry.data[filterRule.get('field')]; - if (Array.isArray(fieldValue)) { - return fieldValue.includes(filterRule.get('value')); - } - return fieldValue === filterRule.get('value'); + const fieldValues = this.valuesAsArray(entry.data[fieldName]); + + return filterValues.some(filterValue => fieldValues.includes(filterValue)); }); } + + // Values can be a string, a list of strings, or statically-typed-record lists of strings + // depending on context (unit test vs. actual config, single vs. multiple values, etc.) + // + // We normalize to a simple list for easier processing above. + // + valuesAsArray(rawValue: string | List | StaticallyTypedRecord>): string[] { + let values: string[] = []; + + if ((>>rawValue).toJS) { + values = (>>rawValue).toJS().toArray(); + } else if (Array.isArray(rawValue)) { + values = rawValue; + } else { + values = [rawValue]; + } + + return values; + } } export function resolveBackend(config: CmsConfig) { diff --git a/packages/decap-cms-core/src/types/redux.ts b/packages/decap-cms-core/src/types/redux.ts index b69a82311532..aef7993d0d61 100644 --- a/packages/decap-cms-core/src/types/redux.ts +++ b/packages/decap-cms-core/src/types/redux.ts @@ -565,7 +565,7 @@ export type EntryField = StaticallyTypedRecord<{ export type EntryFields = List; export type FilterRule = StaticallyTypedRecord<{ - value: string; + value: string | List | StaticallyTypedRecord>; field: string; }>;