diff --git a/lib/ui/src/modules/ui/containers/left_panel.js b/lib/ui/src/modules/ui/containers/left_panel.js index 3ee95809c249..3f3dc11bfd8e 100755 --- a/lib/ui/src/modules/ui/containers/left_panel.js +++ b/lib/ui/src/modules/ui/containers/left_panel.js @@ -8,9 +8,14 @@ export const mapper = (state, props, { actions }) => { const actionMap = actions(); const { stories, selectedKind, selectedStory, uiOptions, storyFilter } = state; const { name, url, sortStoriesByKind, hierarchySeparator } = uiOptions; - const filteredStores = filters.storyFilter(stories, storyFilter, selectedKind, sortStoriesByKind); + const filteredStories = filters.storyFilter( + stories, + storyFilter, + selectedKind, + sortStoriesByKind + ); - const storiesHierarchy = createHierarchy(filteredStores, hierarchySeparator); + const storiesHierarchy = createHierarchy(filteredStories, hierarchySeparator); const selectedHierarchy = resolveStoryHierarchy(selectedKind, hierarchySeparator); const data = { diff --git a/lib/ui/src/modules/ui/libs/filters.js b/lib/ui/src/modules/ui/libs/filters.js index 79d2ef7e9eae..cc327758b818 100755 --- a/lib/ui/src/modules/ui/libs/filters.js +++ b/lib/ui/src/modules/ui/libs/filters.js @@ -11,11 +11,27 @@ export function storyFilter(stories, filter, selectedKind, sortStoriesByKind) { if (!stories) return null; const sorted = sort(stories, sortStoriesByKind); if (!filter) return sorted; - - return sorted.filter(kindInfo => { - if (kindInfo.kind === selectedKind) return true; + return sorted.reduce((acc, kindInfo) => { + // Don't filter out currently selected filter + if (kindInfo.kind === selectedKind) return acc.concat(kindInfo); const needle = filter.toLocaleLowerCase(); const hstack = kindInfo.kind.toLocaleLowerCase(); - return fuzzysearch(needle, hstack); - }); + + // If a match is found in the story hierachy structure return kindInfo + if (fuzzysearch(needle, hstack)) return acc.concat(kindInfo); + + // Now search at individual story level and filter results + const matchedStories = kindInfo.stories.filter(story => { + const storyHstack = story.toLocaleLowerCase(); + return fuzzysearch(needle, storyHstack); + }); + + if (matchedStories.length) + return acc.concat({ + kind: kindInfo.kind, + stories: matchedStories, + }); + + return acc; + }, []); } diff --git a/lib/ui/src/modules/ui/libs/filters.test.js b/lib/ui/src/modules/ui/libs/filters.test.js index 638776289b2e..abfe36c21348 100755 --- a/lib/ui/src/modules/ui/libs/filters.test.js +++ b/lib/ui/src/modules/ui/libs/filters.test.js @@ -54,5 +54,45 @@ describe('manager.ui.libs.filters', () => { expect(res).toEqual([stories[1], stories[2], stories[0]]); }); + + test('should filter on story level', () => { + const stories = [ + { kind: 'aa', stories: ['bb'] }, + { kind: 'cc', stories: ['dd'] }, + { kind: 'ee', stories: ['ff'] }, + ]; + const selectedKind = 'aa'; + const res = storyFilter(stories, 'ff', selectedKind); + + expect(res).toEqual([stories[0], stories[2]]); + }); + + test('should filter out unmatched stories at lowest level', () => { + const stories = [ + { kind: 'aa', stories: ['bb'] }, + { kind: 'cc', stories: ['dd'] }, + { kind: 'ee', stories: ['ff', 'gg'] }, + ]; + const selectedKind = 'aa'; + const res = storyFilter(stories, 'ff', selectedKind); + + expect(res).toEqual([stories[0], { kind: 'ee', stories: ['ff'] }]); + }); + + test('should be case insensitive at tree level', () => { + const stories = [{ kind: 'aA', stories: ['bb'] }, { kind: 'cc', stories: ['dd'] }]; + const selectedKind = 'aA'; + const res = storyFilter(stories, 'aa', selectedKind); + + expect(res).toEqual([stories[0]]); + }); + + test('should be case insensitive at story level', () => { + const stories = [{ kind: 'aa', stories: ['bb'] }, { kind: 'cc', stories: ['dd', 'eE'] }]; + const selectedKind = 'aa'; + const res = storyFilter(stories, 'ee', selectedKind); + + expect(res).toEqual([stories[0], { kind: 'cc', stories: ['eE'] }]); + }); }); });