From 5d710dbd69c6490eef9278aa929a1d6ac677ae6c Mon Sep 17 00:00:00 2001 From: Erez Rokah Date: Thu, 25 Jun 2020 17:41:32 +0300 Subject: [PATCH] fix: search file collections using top level file fields (#3948) --- .../src/__tests__/backend.spec.js | 47 +++++++++++++++++++ packages/netlify-cms-core/src/backend.ts | 39 ++++++++++----- 2 files changed, 73 insertions(+), 13 deletions(-) diff --git a/packages/netlify-cms-core/src/__tests__/backend.spec.js b/packages/netlify-cms-core/src/__tests__/backend.spec.js index 6d96d1a2..c49a09c3 100644 --- a/packages/netlify-cms-core/src/__tests__/backend.spec.js +++ b/packages/netlify-cms-core/src/__tests__/backend.spec.js @@ -2,6 +2,7 @@ import { resolveBackend, Backend, extractSearchFields } from '../backend'; import registry from 'Lib/registry'; import { FOLDER } from 'Constants/collectionTypes'; import { Map, List, fromJS } from 'immutable'; +import { FILES } from '../constants/collectionTypes'; jest.mock('Lib/registry'); jest.mock('netlify-cms-lib-util'); @@ -555,6 +556,23 @@ describe('Backend', () => { { path: 'pages/not-me.md', slug: 'not-me', data: { title: 'not me' } }, ]; + const files = [ + { + path: 'files/file1.md', + slug: 'file1', + data: { + author: 'find me by author', + }, + }, + { + path: 'files/file2.md', + slug: 'file2', + data: { + other: 'find me by other', + }, + }, + ]; + const implementation = { init: jest.fn(() => implementation), }; @@ -570,6 +588,9 @@ describe('Backend', () => { if (collection.get('name') === 'pages') { return Promise.resolve(pages); } + if (collection.get('name') === 'files') { + return Promise.resolve(files); + } return Promise.resolve([]); }); }); @@ -609,6 +630,32 @@ describe('Backend', () => { }); }); + it('should search in file collection using top level fields', async () => { + const collections = [ + fromJS({ + name: 'files', + files: [ + { + name: 'file1', + fields: [{ name: 'author', widget: 'string' }], + }, + { + name: 'file2', + fields: [{ name: 'other', widget: 'string' }], + }, + ], + type: FILES, + }), + ]; + + expect(await backend.search(collections, 'find me by author')).toEqual({ + entries: [files[0]], + }); + expect(await backend.search(collections, 'find me by other')).toEqual({ + entries: [files[1]], + }); + }); + it('should query collections by title', async () => { const results = await backend.query(collections[0], ['title'], 'find me by title'); diff --git a/packages/netlify-cms-core/src/backend.ts b/packages/netlify-cms-core/src/backend.ts index ff41519c..ca21cdd2 100644 --- a/packages/netlify-cms-core/src/backend.ts +++ b/packages/netlify-cms-core/src/backend.ts @@ -36,6 +36,7 @@ import { blobToFileObj, asyncLock, AsyncLock, + UnpublishedEntry, } from 'netlify-cms-lib-util'; import { basename, join, extname, dirname } from 'path'; import { status } from './constants/publishModes'; @@ -54,7 +55,6 @@ import { import AssetProxy from './valueObjects/AssetProxy'; import { FOLDER, FILES } from './constants/collectionTypes'; import { selectCustomPath } from './reducers/entryDraft'; -import { UnpublishedEntry } from 'netlify-cms-lib-util/src/implementation'; const { extractTemplateVars, dateParsers } = stringTemplate; @@ -446,20 +446,33 @@ export class Backend { const summaryFields = extractTemplateVars(summary); // TODO: pass search fields in as an argument - const searchFields = [ - selectInferedField(collection, 'title'), - selectInferedField(collection, 'shortTitle'), - selectInferedField(collection, 'author'), - ...summaryFields.map(elem => { - if (dateParsers[elem]) { - return selectInferedField(collection, 'date'); - } - return elem; - }), - ].filter(Boolean) as string[]; + let searchFields: (string | null | undefined)[] = []; + + if (collection.get('type') === FILES) { + collection.get('files')?.forEach(f => { + const topLevelFields = f! + .get('fields') + .map(f => f!.get('name')) + .toArray(); + searchFields = [...searchFields, ...topLevelFields]; + }); + } else { + searchFields = [ + selectInferedField(collection, 'title'), + selectInferedField(collection, 'shortTitle'), + selectInferedField(collection, 'author'), + ...summaryFields.map(elem => { + if (dateParsers[elem]) { + return selectInferedField(collection, 'date'); + } + return elem; + }), + ]; + } + const filteredSearchFields = searchFields.filter(Boolean) as string[]; const collectionEntries = await this.listAllEntries(collection); return fuzzy.filter(searchTerm, collectionEntries, { - extract: extractSearchFields(uniq(searchFields)), + extract: extractSearchFields(uniq(filteredSearchFields)), }); }) .map(p =>