17782: Disabling typechecking for some common Field component usage.
[arvados-workbench2.git] / src / store / collection-panel / collection-panel-files / collection-panel-files-reducer.ts
index 08a717596f62df17779a590ebe4c7bb56d75327d..775930bd7fd192ae1631d56cb84a93271ab41ed9 100644 (file)
@@ -4,29 +4,89 @@
 
 import { CollectionPanelFilesState, CollectionPanelFile, CollectionPanelDirectory, mapCollectionFileToCollectionPanelFile, mergeCollectionPanelFilesStates } from './collection-panel-files-state';
 import { CollectionPanelFilesAction, collectionPanelFilesAction } from "./collection-panel-files-actions";
-import { createTree, mapTreeValues, getNode, setNode, getNodeAncestorsIds, getNodeDescendantsIds, setNodeValueWith, mapTree } from "~/models/tree";
-import { CollectionFileType } from "~/models/collection-file";
+import { createTree, mapTreeValues, getNode, setNode, getNodeAncestorsIds, getNodeDescendantsIds, setNodeValueWith, mapTree } from "models/tree";
+import { CollectionFileType } from "models/collection-file";
+
+let fetchedFiles: any = {};
 
 export const collectionPanelFilesReducer = (state: CollectionPanelFilesState = createTree(), action: CollectionPanelFilesAction) => {
     // Low-level tree handling setNode() func does in-place data modifications
     // for performance reasons, so we pass a copy of 'state' to avoid side effects.
     return collectionPanelFilesAction.match(action, {
-        SET_COLLECTION_FILES: files =>
-            mergeCollectionPanelFilesStates({...state}, mapTree(mapCollectionFileToCollectionPanelFile)(files)),
+        SET_COLLECTION_FILES: files => {
+            fetchedFiles = files;
+            return mergeCollectionPanelFilesStates({ ...state }, mapTree(mapCollectionFileToCollectionPanelFile)(files));
+        },
 
         TOGGLE_COLLECTION_FILE_COLLAPSE: data =>
-            toggleCollapse(data.id)({...state}),
+            toggleCollapse(data.id)({ ...state }),
 
-        TOGGLE_COLLECTION_FILE_SELECTION: data => [{...state}]
+        TOGGLE_COLLECTION_FILE_SELECTION: data => [{ ...state }]
             .map(toggleSelected(data.id))
             .map(toggleAncestors(data.id))
             .map(toggleDescendants(data.id))[0],
 
+        ON_SEARCH_CHANGE: (searchValue) => {
+            const fileIds: string[] = [];
+            const directoryIds: string[] = [];
+            const filteredFiles = Object.keys(fetchedFiles)
+                .filter((key: string) => {
+                    const node = fetchedFiles[key];
+
+                    if (node.value === undefined) {
+                        return false;
+                    }
+
+                    const { id, value: { type, name } } = node;
+
+                    if (type === CollectionFileType.DIRECTORY) {
+                        directoryIds.push(id);
+                        return true;
+                    }
+
+                    const includeFile = name.toLowerCase().indexOf(searchValue.toLowerCase()) > -1;
+
+                    if (includeFile) {
+                        fileIds.push(id);
+                    }
+
+                    return includeFile;
+                })
+                .reduce((prev, next) => {
+                    const node = JSON.parse(JSON.stringify(fetchedFiles[next]));
+                    const { value: { type }, children } = node;
+
+                    node.children = node.children.filter((key: string) => {
+                        const isFile = directoryIds.indexOf(key) === -1;
+                        return isFile ?
+                          fileIds.indexOf(key) > -1 :
+                          !!fileIds.find(id => id.indexOf(key) > -1);
+                    });
+
+                    if (type === CollectionFileType.FILE || children.length > 0) {
+                        prev[next] = node;
+                    }
+
+                    return prev;
+                }, {});
+
+            return mapTreeValues((v: CollectionPanelDirectory | CollectionPanelFile) => {
+                if (v.type === CollectionFileType.DIRECTORY) {
+                    return ({
+                        ...v,
+                        collapsed: searchValue.length === 0,
+                    });
+                }
+
+                return ({ ...v });
+            })({ ...filteredFiles });
+        },
+
         SELECT_ALL_COLLECTION_FILES: () =>
-            mapTreeValues(v => ({ ...v, selected: true }))({...state}),
+            mapTreeValues((v: any) => ({ ...v, selected: true }))({ ...state }),
 
         UNSELECT_ALL_COLLECTION_FILES: () =>
-            mapTreeValues(v => ({ ...v, selected: false }))({...state}),
+            mapTreeValues((v: any) => ({ ...v, selected: false }))({ ...state }),
 
         default: () => state
     }) as CollectionPanelFilesState;
@@ -48,7 +108,7 @@ const toggleDescendants = (id: string) => (tree: CollectionPanelFilesState) => {
     if (node && node.value.type === CollectionFileType.DIRECTORY) {
         return getNodeDescendantsIds(id)(tree)
             .reduce((newTree, id) =>
-                setNodeValueWith(v => ({ ...v, selected: node.value.selected }))(id)(newTree), tree);
+                setNodeValueWith((v: any) => ({ ...v, selected: node.value.selected }))(id)(newTree), tree);
     }
     return tree;
 };
@@ -66,7 +126,7 @@ const toggleParentNode = (id: string) => (tree: CollectionPanelFilesState) => {
             const selected = parentNode.children
                 .map(id => getNode(id)(tree))
                 .every(node => node !== undefined && node.value.selected);
-            return setNodeValueWith(v => ({ ...v, selected }))(parentNode.id)(tree);
+            return setNodeValueWith((v: any) => ({ ...v, selected }))(parentNode.id)(tree);
         }
         return setNode(node)(tree);
     }