[ARVADOS-WORKBENCH2] updated: 1.2.0-675-g3f51c12

Git user git at public.curoverse.com
Mon Oct 22 15:54:44 EDT 2018


Summary of changes:
 src/models/collection.ts                           |  2 --
 .../collection-panel-files-actions.ts              |  2 ++
 .../project-panel-middleware-service.ts            | 30 ++++++--------------
 src/store/resources-data/resources-data-actions.ts | 14 +++++++++
 src/store/resources-data/resources-data-reducer.ts | 33 ++++++++++++++++++++++
 src/store/resources-data/resources-data.ts         |  8 ++++++
 src/store/resources/resources.ts                   |  2 +-
 src/store/store.ts                                 |  2 ++
 src/views-components/data-explorer/renderers.tsx   |  3 +-
 .../details-panel/collection-details.tsx           |  4 +--
 .../details-panel/details-data.tsx                 |  3 +-
 .../details-panel/details-panel.tsx                | 11 +++++---
 src/views/collection-panel/collection-panel.tsx    | 16 ++++++-----
 13 files changed, 91 insertions(+), 39 deletions(-)
 create mode 100644 src/store/resources-data/resources-data-actions.ts
 create mode 100644 src/store/resources-data/resources-data-reducer.ts
 create mode 100644 src/store/resources-data/resources-data.ts

       via  3f51c120dab4eafb820f9c2a5e4f836cc9b04982 (commit)
      from  d531ed8429325807f54943f33fdb750573b0694e (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit 3f51c120dab4eafb820f9c2a5e4f836cc9b04982
Author: Daniel Kos <daniel.kos at contractors.roche.com>
Date:   Mon Oct 22 21:53:46 2018 +0200

    Remove resource extending, add separate resource data store
    
    Feature #14349
    
    Arvados-DCO-1.1-Signed-off-by: Daniel Kos <daniel.kos at contractors.roche.com>

diff --git a/src/models/collection.ts b/src/models/collection.ts
index 735ffa8..f8e38f9 100644
--- a/src/models/collection.ts
+++ b/src/models/collection.ts
@@ -14,8 +14,6 @@ export interface CollectionResource extends TrashableResource {
     replicationDesired: number;
     replicationConfirmed: number;
     replicationConfirmedAt: string;
-    fileSize: number;
-    fileCount: number;
 }
 
 export const getCollectionUrl = (uuid: string) => {
diff --git a/src/store/collection-panel/collection-panel-files/collection-panel-files-actions.ts b/src/store/collection-panel/collection-panel-files/collection-panel-files-actions.ts
index 99ab682..9a1d645 100644
--- a/src/store/collection-panel/collection-panel-files/collection-panel-files-actions.ts
+++ b/src/store/collection-panel/collection-panel-files/collection-panel-files-actions.ts
@@ -14,6 +14,7 @@ import { filterCollectionFilesBySelection } from './collection-panel-files-state
 import { startSubmit, stopSubmit, reset } from 'redux-form';
 import { getDialog } from "~/store/dialog/dialog-reducer";
 import { getFileFullPath } from "~/services/collection-service/collection-service-files-response";
+import { resourcesDataActions } from "~/store/resources-data/resources-data-actions";
 
 export const collectionPanelFilesAction = unionize({
     SET_COLLECTION_FILES: ofType<CollectionFilesTree>(),
@@ -29,6 +30,7 @@ export const loadCollectionFiles = (uuid: string) =>
     async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
         const files = await services.collectionService.files(uuid);
         dispatch(collectionPanelFilesAction.SET_COLLECTION_FILES(files));
+        dispatch(resourcesDataActions.SET_FILES({ uuid, files }));
     };
 
 export const removeCollectionFiles = (filePaths: string[]) =>
diff --git a/src/store/project-panel/project-panel-middleware-service.ts b/src/store/project-panel/project-panel-middleware-service.ts
index 27efcd0..0da669a 100644
--- a/src/store/project-panel/project-panel-middleware-service.ts
+++ b/src/store/project-panel/project-panel-middleware-service.ts
@@ -20,18 +20,17 @@ import { updateFavorites } from "../favorites/favorites-actions";
 import { PROJECT_PANEL_CURRENT_UUID, projectPanelActions } from './project-panel-action';
 import { Dispatch, MiddlewareAPI } from "redux";
 import { ProjectResource } from "~/models/project";
-import { resourcesActions, updateResources } from "~/store/resources/resources-actions";
+import { updateResources } from "~/store/resources/resources-actions";
 import { getProperty } from "~/store/properties/properties";
 import { snackbarActions, SnackbarKind } from '../snackbar/snackbar-actions';
 import { progressIndicatorActions } from '~/store/progress-indicator/progress-indicator-actions.ts';
 import { DataExplorer, getDataExplorer } from '../data-explorer/data-explorer-reducer';
 import { ListResults } from '~/services/common-service/common-resource-service';
 import { loadContainers } from '../processes/processes-actions';
-import { Resource, ResourceKind } from '~/models/resource';
+import { ResourceKind } from '~/models/resource';
 import { getResource } from "~/store/resources/resources";
 import { CollectionResource } from "~/models/collection";
-import { getNode, getNodeDescendantsIds, TreeNode } from "~/models/tree";
-import { CollectionDirectory, CollectionFile, CollectionFileType } from "~/models/collection-file";
+import { resourcesDataActions } from "~/store/resources-data/resources-data-actions";
 
 export class ProjectPanelMiddlewareService extends DataExplorerMiddlewareService {
     constructor(private services: ServiceRepository, id: string) {
@@ -54,7 +53,7 @@ export class ProjectPanelMiddlewareService extends DataExplorerMiddlewareService
                 const resourceUuids = response.items.map(item => item.uuid);
                 api.dispatch<any>(updateFavorites(resourceUuids));
                 api.dispatch(updateResources(response.items));
-                api.dispatch<any>(updateFilesInfo(resourceUuids));
+                api.dispatch<any>(updateResourceData(resourceUuids));
                 await api.dispatch<any>(loadMissingProcessesInformation(response.items));
                 api.dispatch(setItems(response));
             } catch (e) {
@@ -87,28 +86,17 @@ export const loadMissingProcessesInformation = (resources: GroupContentsResource
         }
     };
 
-export const updateFilesInfo = (resourceUuids: string[]) =>
+export const updateResourceData = (resourceUuids: string[]) =>
     async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
-        const resources = await Promise.all(resourceUuids.map(async uuid => {
+        resourceUuids.map(async uuid => {
             const resource = getResource<CollectionResource>(uuid)(getState().resources);
             if (resource && resource.kind === ResourceKind.COLLECTION) {
                 const files = await services.collectionService.files(uuid);
-                const flattenFiles: (TreeNode<CollectionFile | CollectionDirectory> | undefined)[] = getNodeDescendantsIds('')(files).map(id => getNode(id)(files));
-                let fileSize = 0;
-                let fileCount = 0;
-                if (flattenFiles) {
-                    fileCount = flattenFiles.length;
-                    fileSize = flattenFiles.reduce((acc, f) => {
-                        return acc + (f && f.value.type === CollectionFileType.FILE ? f.value.size : 0);
-                    }, 0);
+                if (files) {
+                    dispatch(resourcesDataActions.SET_FILES({ uuid, files }));
                 }
-
-                resource.fileCount = fileCount;
-                resource.fileSize = fileSize;
             }
-            return resource;
-        }));
-        dispatch(resourcesActions.SET_RESOURCES(resources.filter(res => res) as Resource[]));
+        });
     };
 
 export const setItems = (listResults: ListResults<GroupContentsResource>) =>
diff --git a/src/store/resources-data/resources-data-actions.ts b/src/store/resources-data/resources-data-actions.ts
new file mode 100644
index 0000000..660699c
--- /dev/null
+++ b/src/store/resources-data/resources-data-actions.ts
@@ -0,0 +1,14 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { unionize } from "src/common/unionize";
+import { ofType, UnionOf } from "unionize";
+import { CollectionDirectory, CollectionFile } from "~/models/collection-file";
+import { Tree } from "~/models/tree";
+
+export const resourcesDataActions = unionize({
+    SET_FILES: ofType<{uuid: string, files: Tree<CollectionFile | CollectionDirectory>}>()
+});
+
+export type ResourcesDataActions = UnionOf<typeof resourcesDataActions>;
diff --git a/src/store/resources-data/resources-data-reducer.ts b/src/store/resources-data/resources-data-reducer.ts
new file mode 100644
index 0000000..07a3a66
--- /dev/null
+++ b/src/store/resources-data/resources-data-reducer.ts
@@ -0,0 +1,33 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { ResourcesDataActions, resourcesDataActions } from "~/store/resources-data/resources-data-actions";
+import { getNodeDescendantsIds, TREE_ROOT_ID } from "~/models/tree";
+import { CollectionFileType } from "~/models/collection-file";
+
+export interface ResourceData {
+    fileCount: number;
+    fileSize: number;
+}
+
+export type ResourcesDataState = {
+    [key: string]: ResourceData
+};
+
+export const resourcesDataReducer = (state: ResourcesDataState = {}, action: ResourcesDataActions) =>
+    resourcesDataActions.match(action, {
+        SET_FILES: ({uuid, files}) => {
+            const flattenFiles = getNodeDescendantsIds(TREE_ROOT_ID)(files).map(id => files[id]);
+            const [fileSize, fileCount] = flattenFiles.reduce(([size, cnt], f) =>
+                f && f.value.type === CollectionFileType.FILE
+                ? [size + f.value.size, cnt + 1]
+                : [size, cnt]
+            , [0, 0]);
+            return {
+                ...state,
+                [uuid]: { fileCount, fileSize }
+            };
+        },
+        default: () => state,
+    });
diff --git a/src/store/resources-data/resources-data.ts b/src/store/resources-data/resources-data.ts
new file mode 100644
index 0000000..48c1e2b
--- /dev/null
+++ b/src/store/resources-data/resources-data.ts
@@ -0,0 +1,8 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { ResourceData, ResourcesDataState } from "~/store/resources-data/resources-data-reducer";
+
+export const getResourceData = (id: string) =>
+    (state: ResourcesDataState): ResourceData | undefined => state[id];
diff --git a/src/store/resources/resources.ts b/src/store/resources/resources.ts
index 10c82ff..e7153de 100644
--- a/src/store/resources/resources.ts
+++ b/src/store/resources/resources.ts
@@ -3,7 +3,7 @@
 // SPDX-License-Identifier: AGPL-3.0
 
 import { Resource } from "~/models/resource";
-import { ResourceKind } from '../../models/resource';
+import { ResourceKind } from '~/models/resource';
 
 export type ResourcesState = { [key: string]: Resource };
 
diff --git a/src/store/store.ts b/src/store/store.ts
index 7a0d58f..fa2a5be 100644
--- a/src/store/store.ts
+++ b/src/store/store.ts
@@ -42,6 +42,7 @@ import { appInfoReducer } from '~/store/app-info/app-info-reducer';
 import { searchBarReducer } from './search-bar/search-bar-reducer';
 import { SEARCH_RESULTS_PANEL_ID } from '~/store/search-results-panel/search-results-panel-actions';
 import { SearchResultsMiddlewareService } from './search-results-panel/search-results-middleware-service';
+import { resourcesDataReducer } from "~/store/resources-data/resources-data-reducer";
 
 const composeEnhancers =
     (process.env.NODE_ENV === 'development' &&
@@ -101,6 +102,7 @@ const createRootReducer = (services: ServiceRepository) => combineReducers({
     processLogsPanel: processLogsPanelReducer,
     properties: propertiesReducer,
     resources: resourcesReducer,
+    resourcesData: resourcesDataReducer,
     router: routerReducer,
     snackbar: snackbarReducer,
     treePicker: treePickerReducer,
diff --git a/src/views-components/data-explorer/renderers.tsx b/src/views-components/data-explorer/renderers.tsx
index e76600e..6e25508 100644
--- a/src/views-components/data-explorer/renderers.tsx
+++ b/src/views-components/data-explorer/renderers.tsx
@@ -20,6 +20,7 @@ import { WorkflowResource } from '~/models/workflow';
 import { ResourceStatus } from '~/views/workflow-panel/workflow-panel-view';
 import { getUuidPrefix } from '~/store/workflow-panel/workflow-panel-actions';
 import { CollectionResource } from "~/models/collection";
+import { getResourceData } from "~/store/resources-data/resources-data";
 
 export const renderName = (item: { name: string; uuid: string, kind: string }) =>
     <Grid container alignItems="center" wrap="nowrap" spacing={16}>
@@ -150,7 +151,7 @@ export const renderFileSize = (fileSize?: number) =>
 
 export const ResourceFileSize = connect(
     (state: RootState, props: { uuid: string }) => {
-        const resource = getResource<CollectionResource>(props.uuid)(state.resources);
+        const resource = getResourceData(props.uuid)(state.resourcesData);
         return { fileSize: resource ? resource.fileSize : 0 };
     })((props: { fileSize?: number }) => renderFileSize(props.fileSize));
 
diff --git a/src/views-components/details-panel/collection-details.tsx b/src/views-components/details-panel/collection-details.tsx
index aec9911..98fa388 100644
--- a/src/views-components/details-panel/collection-details.tsx
+++ b/src/views-components/details-panel/collection-details.tsx
@@ -28,8 +28,8 @@ export class CollectionDetails extends DetailsData<CollectionResource> {
             <DetailsAttribute label='Collection UUID' link={this.item.uuid} value={this.item.uuid} />
             <DetailsAttribute label='Content address' link={this.item.portableDataHash} value={this.item.portableDataHash} />
             {/* Missing attrs */}
-            <DetailsAttribute label='Number of files' value={this.item.fileCount} />
-            <DetailsAttribute label='Content size' value={formatFileSize(this.item.fileSize)} />
+            <DetailsAttribute label='Number of files' value={this.data && this.data.fileCount} />
+            <DetailsAttribute label='Content size' value={formatFileSize(this.data && this.data.fileSize)} />
         </div>;
     }
 }
diff --git a/src/views-components/details-panel/details-data.tsx b/src/views-components/details-panel/details-data.tsx
index b5ebc36..45afb02 100644
--- a/src/views-components/details-panel/details-data.tsx
+++ b/src/views-components/details-panel/details-data.tsx
@@ -4,9 +4,10 @@
 
 import * as React from 'react';
 import { DetailsResource } from "~/models/details";
+import { ResourceData } from "~/store/resources-data/resources-data-reducer";
 
 export abstract class DetailsData<T extends DetailsResource = DetailsResource> {
-    constructor(protected item: T) {}
+    constructor(protected item: T, protected data?: ResourceData) {}
 
     getTitle(): string {
         return this.item.name || 'Projects';
diff --git a/src/views-components/details-panel/details-panel.tsx b/src/views-components/details-panel/details-panel.tsx
index f007555..5e5ccef 100644
--- a/src/views-components/details-panel/details-panel.tsx
+++ b/src/views-components/details-panel/details-panel.tsx
@@ -22,6 +22,8 @@ import { EmptyDetails } from "./empty-details";
 import { DetailsData } from "./details-data";
 import { DetailsResource } from "~/models/details";
 import { getResource } from '~/store/resources/resources';
+import { ResourceData } from "~/store/resources-data/resources-data-reducer";
+import { getResourceData } from "~/store/resources-data/resources-data";
 
 type CssRules = 'root' | 'container' | 'opened' | 'headerContainer' | 'headerIcon' | 'tabContainer';
 
@@ -57,13 +59,13 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
     },
 });
 
-const getItem = (resource: DetailsResource): DetailsData => {
+const getItem = (resource: DetailsResource, resourceData?: ResourceData): DetailsData => {
     const res = resource || { kind: undefined, name: 'Projects' };
     switch (res.kind) {
         case ResourceKind.PROJECT:
             return new ProjectDetails(res);
         case ResourceKind.COLLECTION:
-            return new CollectionDetails(res);
+            return new CollectionDetails(res, resourceData);
         case ResourceKind.PROCESS:
             return new ProcessDetails(res);
         default:
@@ -71,11 +73,12 @@ const getItem = (resource: DetailsResource): DetailsData => {
     }
 };
 
-const mapStateToProps = ({ detailsPanel, resources }: RootState) => {
+const mapStateToProps = ({ detailsPanel, resources, resourcesData }: RootState) => {
     const resource = getResource(detailsPanel.resourceUuid)(resources) as DetailsResource;
+    const resourceData = getResourceData(detailsPanel.resourceUuid)(resourcesData);
     return {
         isOpened: detailsPanel.isOpened,
-        item: getItem(resource)
+        item: getItem(resource, resourceData)
     };
 };
 
diff --git a/src/views/collection-panel/collection-panel.tsx b/src/views/collection-panel/collection-panel.tsx
index 7defc07..42f7787 100644
--- a/src/views/collection-panel/collection-panel.tsx
+++ b/src/views/collection-panel/collection-panel.tsx
@@ -23,6 +23,8 @@ import { getResource } from '~/store/resources/resources';
 import { openContextMenu } from '~/store/context-menu/context-menu-actions';
 import { ContextMenuKind } from '~/views-components/context-menu/context-menu';
 import { formatFileSize } from "~/common/formatters";
+import { getResourceData } from "~/store/resources-data/resources-data";
+import { ResourceData } from "~/store/resources-data/resources-data-reducer";
 
 type CssRules = 'card' | 'iconHeader' | 'tag' | 'copyIcon' | 'label' | 'value';
 
@@ -55,6 +57,7 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
 
 interface CollectionPanelDataProps {
     item: CollectionResource;
+    data: ResourceData;
 }
 
 type CollectionPanelProps = CollectionPanelDataProps & DispatchProp
@@ -63,14 +66,13 @@ type CollectionPanelProps = CollectionPanelDataProps & DispatchProp
 
 export const CollectionPanel = withStyles(styles)(
     connect((state: RootState, props: RouteComponentProps<{ id: string }>) => {
-        const collection = getResource(props.match.params.id)(state.resources);
-        return {
-            item: collection
-        };
+        const item = getResource(props.match.params.id)(state.resources);
+        const data = getResourceData(props.match.params.id)(state.resourcesData);
+        return { item, data };
     })(
         class extends React.Component<CollectionPanelProps> {
             render() {
-                const { classes, item } = this.props;
+                const { classes, item, data } = this.props;
                 return item
                     ? <>
                         <Card className={classes.card}>
@@ -100,9 +102,9 @@ export const CollectionPanel = withStyles(styles)(
                                             </Tooltip>
                                         </DetailsAttribute>
                                         <DetailsAttribute classLabel={classes.label} classValue={classes.value}
-                                            label='Number of files' value={item && item.fileCount} />
+                                            label='Number of files' value={data && data.fileCount} />
                                         <DetailsAttribute classLabel={classes.label} classValue={classes.value}
-                                            label='Content size' value={item && formatFileSize(item.fileSize)} />
+                                            label='Content size' value={data && formatFileSize(data.fileSize)} />
                                         <DetailsAttribute classLabel={classes.label} classValue={classes.value}
                                             label='Owner' value={item && item.ownerUuid} />
                                     </Grid>

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list