--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { default as unionize, ofType, UnionOf } from "unionize";
+import { CollectionPanelFilesState, CollectionPanelFile } from "./collection-panel-files-state";
+
+export const collectionPanelFilesAction = unionize({
+ SET_COLLECTION_FILES: ofType<{ files: CollectionPanelFilesState }>(),
+ TOGGLE_COLLECTION_FILE_COLLAPSE: ofType<{ id: string }>(),
+ TOGGLE_COLLECTION_FILE_SELECTION: ofType<{ id: string }>()
+}, { tag: 'type', value: 'payload' });
+
+export type CollectionPanelFilesAction = UnionOf<typeof collectionPanelFilesAction>;
\ No newline at end of file
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+export type CollectionPanelFilesState = Array<CollectionPanelFile>;
+
+export interface CollectionPanelFile {
+ parentId: string;
+ id: string;
+ name: string;
+ size: number;
+ collapsed: boolean;
+ selected: boolean;
+ type: string;
+}
\ No newline at end of file
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { CollectionPanelFilesState } from "./collection-panel-files-state";
+import { CollectionPanelFilesAction, collectionPanelFilesAction } from "./collection-panel-files-actions";
+
+export const collectionPanelFilesReducer = (state: CollectionPanelFilesState = [], action: CollectionPanelFilesAction) => {
+ return collectionPanelFilesAction.match(action, {
+ SET_COLLECTION_FILES: data => data.files,
+ TOGGLE_COLLECTION_FILE_COLLAPSE: data => toggle(state, data.id, "collapsed"),
+ TOGGLE_COLLECTION_FILE_SELECTION: data => toggle(state, data.id, "selected"),
+ default: () => state
+ });
+};
+
+const toggle = (state: CollectionPanelFilesState, id: string, key: "collapsed" | "selected") =>
+ state.map(file => file.id === id
+ ? { ...file, [key]: !file[key] }
+ : file);
\ No newline at end of file