15840: Project panel uses collection attributes for file count and size
authorEric Biagiotti <ebiagiotti@veritasgenetics.com>
Thu, 24 Oct 2019 17:46:06 +0000 (13:46 -0400)
committerEric Biagiotti <ebiagiotti@veritasgenetics.com>
Tue, 19 Nov 2019 21:23:22 +0000 (16:23 -0500)
- Previously, the project panel loaded the entire collection file tree to sum file count and  total size. Now it uses the file_count and file_size_total collection attributes.
- Also updated the collection service to not do any tree manipulation when using propfind for files.

Arvados-DCO-1.1-Signed-off-by: Eric Biagiotti <ebiagiotti@veritasgenetics.com>

16 files changed:
src/models/collection.ts
src/services/collection-service/collection-service-files-response.ts
src/services/collection-service/collection-service.ts
src/store/advanced-tab/advanced-tab.tsx
src/store/collection-panel/collection-panel-files/collection-panel-files-actions.ts
src/store/project-panel/project-panel-middleware-service.ts
src/store/resources-data/resources-data-actions.ts [deleted file]
src/store/resources-data/resources-data-reducer.ts [deleted file]
src/store/resources-data/resources-data.ts [deleted file]
src/store/store.ts
src/store/tree-picker/tree-picker-actions.ts
src/views-components/data-explorer/renderers.tsx
src/views-components/details-panel/collection-details.tsx
src/views-components/details-panel/details-data.tsx
src/views-components/details-panel/details-panel.tsx
src/views/collection-panel/collection-panel.tsx

index ca2b4b36d6965e42cba58467bf7041f9beee85b4..baa25c7af11f145b533e26c5d3d054dda4f751dc 100644 (file)
@@ -21,6 +21,8 @@ export interface CollectionResource extends TrashableResource {
     version: number;
     preserveVersion: boolean;
     unsignedManifestText?: string;
     version: number;
     preserveVersion: boolean;
     unsignedManifestText?: string;
+    fileCount: number;
+    fileSizeTotal: number;
 }
 
 export const getCollectionUrl = (uuid: string) => {
 }
 
 export const getCollectionUrl = (uuid: string) => {
index 619a4fc78582270558aa51ac07986ba578ed1c02..f3a2147e26c5810705282d7abd322845508ce66c 100644 (file)
@@ -2,16 +2,10 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import { createCollectionFilesTree, CollectionDirectory, CollectionFile, CollectionFileType, createCollectionDirectory, createCollectionFile } from "../../models/collection-file";
+import { CollectionDirectory, CollectionFile, CollectionFileType, createCollectionDirectory, createCollectionFile } from "../../models/collection-file";
 import { getTagValue } from "~/common/xml";
 import { getNodeChildren, Tree, mapTree } from '~/models/tree';
 
 import { getTagValue } from "~/common/xml";
 import { getNodeChildren, Tree, mapTree } from '~/models/tree';
 
-export const parseFilesResponse = (document: Document) => {
-    const files = extractFilesData(document);
-    const tree = createCollectionFilesTree(files);
-    return sortFilesTree(tree);
-};
-
 export const sortFilesTree = (tree: Tree<CollectionDirectory | CollectionFile>) => {
     return mapTree<CollectionDirectory | CollectionFile>(node => {
         const children = getNodeChildren(node.id)(tree);
 export const sortFilesTree = (tree: Tree<CollectionDirectory | CollectionFile>) => {
     return mapTree<CollectionDirectory | CollectionFile>(node => {
         const children = getNodeChildren(node.id)(tree);
index c787cf7b1a14da4c87f643d42facef5ca4409c59..6eb9b5ba664f15892d570206051a93803050987b 100644 (file)
@@ -7,8 +7,7 @@ import { AxiosInstance } from "axios";
 import { CollectionFile, CollectionDirectory } from "~/models/collection-file";
 import { WebDAV } from "~/common/webdav";
 import { AuthService } from "../auth-service/auth-service";
 import { CollectionFile, CollectionDirectory } from "~/models/collection-file";
 import { WebDAV } from "~/common/webdav";
 import { AuthService } from "../auth-service/auth-service";
-import { mapTreeValues } from "~/models/tree";
-import { parseFilesResponse } from "./collection-service-files-response";
+import { extractFilesData } from "./collection-service-files-response";
 import { TrashableResourceService } from "~/services/common-service/trashable-resource-service";
 import { ApiActions } from "~/services/api/api-actions";
 
 import { TrashableResourceService } from "~/services/common-service/trashable-resource-service";
 import { ApiActions } from "~/services/api/api-actions";
 
@@ -22,8 +21,7 @@ export class CollectionService extends TrashableResourceService<CollectionResour
     async files(uuid: string) {
         const request = await this.webdavClient.propfind(`c=${uuid}`);
         if (request.responseXML != null) {
     async files(uuid: string) {
         const request = await this.webdavClient.propfind(`c=${uuid}`);
         if (request.responseXML != null) {
-            const filesTree = parseFilesResponse(request.responseXML);
-            return mapTreeValues(this.extendFileURL)(filesTree);
+            return extractFilesData(request.responseXML);
         }
         return Promise.reject();
     }
         }
         return Promise.reject();
     }
@@ -53,7 +51,7 @@ export class CollectionService extends TrashableResourceService<CollectionResour
         );
     }
 
         );
     }
 
-    private extendFileURL = (file: CollectionDirectory | CollectionFile) => {
+    extendFileURL = (file: CollectionDirectory | CollectionFile) => {
         const baseUrl = this.webdavClient.defaults.baseURL.endsWith('/')
             ? this.webdavClient.defaults.baseURL.slice(0, -1)
             : this.webdavClient.defaults.baseURL;
         const baseUrl = this.webdavClient.defaults.baseURL.endsWith('/')
             ? this.webdavClient.defaults.baseURL.slice(0, -1)
             : this.webdavClient.defaults.baseURL;
index c7bb677aa3f98429d3ecdbe05bf74fbc760b23da..be82547b813c9e9161a5ff834aa4c5cfceb8f438 100644 (file)
@@ -435,7 +435,7 @@ const containerRequestApiResponse = (apiResponse: ContainerRequestResource) => {
 const collectionApiResponse = (apiResponse: CollectionResource) => {
     const { uuid, ownerUuid, createdAt, modifiedAt, modifiedByClientUuid, modifiedByUserUuid, name, description, properties, portableDataHash, replicationDesired,
         replicationConfirmedAt, replicationConfirmed, manifestText, deleteAt, trashAt, isTrashed, storageClassesDesired,
 const collectionApiResponse = (apiResponse: CollectionResource) => {
     const { uuid, ownerUuid, createdAt, modifiedAt, modifiedByClientUuid, modifiedByUserUuid, name, description, properties, portableDataHash, replicationDesired,
         replicationConfirmedAt, replicationConfirmed, manifestText, deleteAt, trashAt, isTrashed, storageClassesDesired,
-        storageClassesConfirmed, storageClassesConfirmedAt, currentVersionUuid, version, preserveVersion } = apiResponse;
+        storageClassesConfirmed, storageClassesConfirmedAt, currentVersionUuid, version, preserveVersion, fileCount, fileSizeTotal } = apiResponse;
     const response = `
 "uuid": "${uuid}",
 "owner_uuid": "${ownerUuid}",
     const response = `
 "uuid": "${uuid}",
 "owner_uuid": "${ownerUuid}",
@@ -459,7 +459,9 @@ const collectionApiResponse = (apiResponse: CollectionResource) => {
 "storage_classes_confirmed_at": ${stringify(storageClassesConfirmedAt)},
 "current_version_uuid": ${stringify(currentVersionUuid)},
 "version": ${version},
 "storage_classes_confirmed_at": ${stringify(storageClassesConfirmedAt)},
 "current_version_uuid": ${stringify(currentVersionUuid)},
 "version": ${version},
-"preserve_version": ${preserveVersion}`;
+"preserve_version": ${preserveVersion},
+"file_count": ${fileCount},
+"file_size_total": ${fileSizeTotal}`;
 
     return <span style={{ marginLeft: '-15px' }}>{'{'} {response} {'\n'} <span style={{ marginLeft: '-15px' }}>{'}'}</span></span>;
 };
 
     return <span style={{ marginLeft: '-15px' }}>{'{'} {response} {'\n'} <span style={{ marginLeft: '-15px' }}>{'}'}</span></span>;
 };
index c661d9f8b2d9c2ee8c95e90ca04953f8629e4f3e..27e4d4e68f08e6e10ca07396d1cd9edf2573c462 100644 (file)
@@ -4,17 +4,16 @@
 
 import { unionize, ofType, UnionOf } from "~/common/unionize";
 import { Dispatch } from "redux";
 
 import { unionize, ofType, UnionOf } from "~/common/unionize";
 import { Dispatch } from "redux";
-import { CollectionFilesTree, CollectionFileType } from "~/models/collection-file";
+import { CollectionFilesTree, CollectionFileType, createCollectionFilesTree } from "~/models/collection-file";
 import { ServiceRepository } from "~/services/services";
 import { RootState } from "../../store";
 import { snackbarActions, SnackbarKind } from "../../snackbar/snackbar-actions";
 import { dialogActions } from '../../dialog/dialog-actions';
 import { ServiceRepository } from "~/services/services";
 import { RootState } from "../../store";
 import { snackbarActions, SnackbarKind } from "../../snackbar/snackbar-actions";
 import { dialogActions } from '../../dialog/dialog-actions';
-import { getNodeValue } from "~/models/tree";
+import { getNodeValue, mapTreeValues } from "~/models/tree";
 import { filterCollectionFilesBySelection } from './collection-panel-files-state';
 import { startSubmit, stopSubmit, initialize, FormErrors } from 'redux-form';
 import { getDialog } from "~/store/dialog/dialog-reducer";
 import { filterCollectionFilesBySelection } from './collection-panel-files-state';
 import { startSubmit, stopSubmit, initialize, FormErrors } 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";
+import { getFileFullPath, sortFilesTree } from "~/services/collection-service/collection-service-files-response";
 
 export const collectionPanelFilesAction = unionize({
     SET_COLLECTION_FILES: ofType<CollectionFilesTree>(),
 
 export const collectionPanelFilesAction = unionize({
     SET_COLLECTION_FILES: ofType<CollectionFilesTree>(),
@@ -29,8 +28,10 @@ export type CollectionPanelFilesAction = UnionOf<typeof collectionPanelFilesActi
 export const loadCollectionFiles = (uuid: string) =>
     async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
         const files = await services.collectionService.files(uuid);
 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 }));
+        const tree = createCollectionFilesTree(files);
+        const sorted = sortFilesTree(tree);
+        const mapped = mapTreeValues(services.collectionService.extendFileURL)(sorted);
+        dispatch(collectionPanelFilesAction.SET_COLLECTION_FILES(mapped));
     };
 
 export const removeCollectionFiles = (filePaths: string[]) =>
     };
 
 export const removeCollectionFiles = (filePaths: string[]) =>
index 361825d43fb113a2af85ebf451c4eb496309dfd8..3a42d07eb897677d28889555c6f50fad7069a714 100644 (file)
@@ -28,9 +28,6 @@ import { DataExplorer, getDataExplorer } from '~/store/data-explorer/data-explor
 import { ListResults } from '~/services/common-service/common-service';
 import { loadContainers } from '~/store/processes/processes-actions';
 import { ResourceKind } from '~/models/resource';
 import { ListResults } from '~/services/common-service/common-service';
 import { loadContainers } from '~/store/processes/processes-actions';
 import { ResourceKind } from '~/models/resource';
-import { getResource } from "~/store/resources/resources";
-import { CollectionResource } from "~/models/collection";
-import { resourcesDataActions } from "~/store/resources-data/resources-data-actions";
 import { getSortColumn } from "~/store/data-explorer/data-explorer-reducer";
 import { serializeResourceTypeFilters } from '~/store/resource-type-filters/resource-type-filters';
 import { updatePublicFavorites } from '~/store/public-favorites/public-favorites-actions';
 import { getSortColumn } from "~/store/data-explorer/data-explorer-reducer";
 import { serializeResourceTypeFilters } from '~/store/resource-type-filters/resource-type-filters';
 import { updatePublicFavorites } from '~/store/public-favorites/public-favorites-actions';
@@ -58,7 +55,6 @@ export class ProjectPanelMiddlewareService extends DataExplorerMiddlewareService
                 api.dispatch<any>(updateFavorites(resourceUuids));
                 api.dispatch<any>(updatePublicFavorites(resourceUuids));
                 api.dispatch(updateResources(response.items));
                 api.dispatch<any>(updateFavorites(resourceUuids));
                 api.dispatch<any>(updatePublicFavorites(resourceUuids));
                 api.dispatch(updateResources(response.items));
-                api.dispatch<any>(updateResourceData(resourceUuids));
                 await api.dispatch<any>(loadMissingProcessesInformation(response.items));
                 api.dispatch(setItems(response));
             } catch (e) {
                 await api.dispatch<any>(loadMissingProcessesInformation(response.items));
                 api.dispatch(setItems(response));
             } catch (e) {
@@ -91,19 +87,6 @@ export const loadMissingProcessesInformation = (resources: GroupContentsResource
         }
     };
 
         }
     };
 
-export const updateResourceData = (resourceUuids: string[]) =>
-    async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
-        resourceUuids.map(async uuid => {
-            const resource = getResource<CollectionResource>(uuid)(getState().resources);
-            if (resource && resource.kind === ResourceKind.COLLECTION) {
-                const files = await services.collectionService.files(uuid);
-                if (files) {
-                    dispatch(resourcesDataActions.SET_FILES({ uuid, files }));
-                }
-            }
-        });
-    };
-
 export const setItems = (listResults: ListResults<GroupContentsResource>) =>
     projectPanelActions.SET_ITEMS({
         ...listResultsToDataExplorerItemsMeta(listResults),
 export const setItems = (listResults: ListResults<GroupContentsResource>) =>
     projectPanelActions.SET_ITEMS({
         ...listResultsToDataExplorerItemsMeta(listResults),
diff --git a/src/store/resources-data/resources-data-actions.ts b/src/store/resources-data/resources-data-actions.ts
deleted file mode 100644 (file)
index 7bc0e94..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-import { unionize, ofType, UnionOf } from "~/common/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
deleted file mode 100644 (file)
index 07a3a66..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-// 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
deleted file mode 100644 (file)
index 48c1e2b..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// 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];
index 8a2ca2400cb1cbd3f1229cce96294291e91c8d66..2e27a56f74ce1c09cb607a449d313532fee12731 100644 (file)
@@ -43,7 +43,6 @@ 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 { 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";
 import { virtualMachinesReducer } from "~/store/virtual-machines/virtual-machines-reducer";
 import { repositoriesReducer } from '~/store/repositories/repositories-reducer';
 import { keepServicesReducer } from '~/store/keep-services/keep-services-reducer';
 import { virtualMachinesReducer } from "~/store/virtual-machines/virtual-machines-reducer";
 import { repositoriesReducer } from '~/store/repositories/repositories-reducer';
 import { keepServicesReducer } from '~/store/keep-services/keep-services-reducer';
@@ -161,7 +160,6 @@ const createRootReducer = (services: ServiceRepository) => combineReducers({
     processLogsPanel: processLogsPanelReducer,
     properties: propertiesReducer,
     resources: resourcesReducer,
     processLogsPanel: processLogsPanelReducer,
     properties: propertiesReducer,
     resources: resourcesReducer,
-    resourcesData: resourcesDataReducer,
     router: routerReducer,
     snackbar: snackbarReducer,
     treePicker: treePickerReducer,
     router: routerReducer,
     snackbar: snackbarReducer,
     treePicker: treePickerReducer,
index e4d6d9339508893208d43ef784983ccad501c8f0..1ec49141e36b8043d2c607ef510132a0dc85ddbe 100644 (file)
@@ -4,6 +4,7 @@
 
 import { unionize, ofType, UnionOf } from "~/common/unionize";
 import { TreeNode, initTreeNode, getNodeDescendants, TreeNodeStatus, getNode, TreePickerId, Tree } from '~/models/tree';
 
 import { unionize, ofType, UnionOf } from "~/common/unionize";
 import { TreeNode, initTreeNode, getNodeDescendants, TreeNodeStatus, getNode, TreePickerId, Tree } from '~/models/tree';
+import { createCollectionFilesTree } from "~/models/collection-file";
 import { Dispatch } from 'redux';
 import { RootState } from '~/store/store';
 import { ServiceRepository } from '~/services/services';
 import { Dispatch } from 'redux';
 import { RootState } from '~/store/store';
 import { ServiceRepository } from '~/services/services';
@@ -17,6 +18,8 @@ import { OrderBuilder } from '~/services/api/order-builder';
 import { ProjectResource } from '~/models/project';
 import { mapTree } from '../../models/tree';
 import { LinkResource, LinkClass } from "~/models/link";
 import { ProjectResource } from '~/models/project';
 import { mapTree } from '../../models/tree';
 import { LinkResource, LinkClass } from "~/models/link";
+import { mapTreeValues } from "~/models/tree";
+import { sortFilesTree } from "~/services/collection-service/collection-service-files-response";
 
 export const treePickerActions = unionize({
     LOAD_TREE_PICKER_NODE: ofType<{ id: string, pickerId: string }>(),
 
 export const treePickerActions = unionize({
     LOAD_TREE_PICKER_NODE: ofType<{ id: string, pickerId: string }>(),
@@ -139,7 +142,10 @@ export const loadCollection = (id: string, pickerId: string) =>
             const node = getNode(id)(picker);
             if (node && 'kind' in node.value && node.value.kind === ResourceKind.COLLECTION) {
 
             const node = getNode(id)(picker);
             if (node && 'kind' in node.value && node.value.kind === ResourceKind.COLLECTION) {
 
-                const filesTree = await services.collectionService.files(node.value.portableDataHash);
+                const files = await services.collectionService.files(node.value.portableDataHash);
+                const tree = createCollectionFilesTree(files);
+                const sorted = sortFilesTree(tree);
+                const filesTree = mapTreeValues(services.collectionService.extendFileURL)(sorted);
 
                 dispatch(
                     treePickerActions.APPEND_TREE_PICKER_NODE_SUBTREE({
 
                 dispatch(
                     treePickerActions.APPEND_TREE_PICKER_NODE_SUBTREE({
index 32e14c5a08cd04e202251ab33681be9bdbdae4b0..4179d60eb3f25120dbd0940eb0f93f2159f7207f 100644 (file)
@@ -19,13 +19,13 @@ import { compose, Dispatch } from 'redux';
 import { WorkflowResource } from '~/models/workflow';
 import { ResourceStatus } from '~/views/workflow-panel/workflow-panel-view';
 import { getUuidPrefix, openRunProcess } from '~/store/workflow-panel/workflow-panel-actions';
 import { WorkflowResource } from '~/models/workflow';
 import { ResourceStatus } from '~/views/workflow-panel/workflow-panel-view';
 import { getUuidPrefix, openRunProcess } from '~/store/workflow-panel/workflow-panel-actions';
-import { getResourceData } from "~/store/resources-data/resources-data";
 import { openSharingDialog } from '~/store/sharing-dialog/sharing-dialog-actions';
 import { UserResource } from '~/models/user';
 import { toggleIsActive, toggleIsAdmin } from '~/store/users/users-actions';
 import { LinkResource } from '~/models/link';
 import { navigateTo } from '~/store/navigation/navigation-action';
 import { withResourceData } from '~/views-components/data-explorer/with-resources';
 import { openSharingDialog } from '~/store/sharing-dialog/sharing-dialog-actions';
 import { UserResource } from '~/models/user';
 import { toggleIsActive, toggleIsAdmin } from '~/store/users/users-actions';
 import { LinkResource } from '~/models/link';
 import { navigateTo } from '~/store/navigation/navigation-action';
 import { withResourceData } from '~/views-components/data-explorer/with-resources';
+import { CollectionResource } from '~/models/collection';
 
 const renderName = (dispatch: Dispatch, item: { name: string; uuid: string, kind: string }) =>
     <Grid container alignItems="center" wrap="nowrap" spacing={16}>
 
 const renderName = (dispatch: Dispatch, item: { name: string; uuid: string, kind: string }) =>
     <Grid container alignItems="center" wrap="nowrap" spacing={16}>
@@ -398,8 +398,8 @@ export const renderFileSize = (fileSize?: number) =>
 
 export const ResourceFileSize = connect(
     (state: RootState, props: { uuid: string }) => {
 
 export const ResourceFileSize = connect(
     (state: RootState, props: { uuid: string }) => {
-        const resource = getResourceData(props.uuid)(state.resourcesData);
-        return { fileSize: resource ? resource.fileSize : 0 };
+        const resource = getResource<CollectionResource>(props.uuid)(state.resources);
+        return { fileSize: resource ? resource.fileSizeTotal : 0 };
     })((props: { fileSize?: number }) => renderFileSize(props.fileSize));
 
 const renderOwner = (owner: string) =>
     })((props: { fileSize?: number }) => renderFileSize(props.fileSize));
 
 const renderOwner = (owner: string) =>
index a523d6fca8e1176c438779c9fee33493add23e55..999d4c79ffe2d5f240ab69af47debe1ff605ec71 100644 (file)
@@ -27,8 +27,8 @@ export class CollectionDetails extends DetailsData<CollectionResource> {
             <DetailsAttribute label='Collection UUID' linkToUuid={this.item.uuid} value={this.item.uuid} />
             <DetailsAttribute label='Content address' linkToUuid={this.item.portableDataHash} value={this.item.portableDataHash} />
             {/* Missing attrs */}
             <DetailsAttribute label='Collection UUID' linkToUuid={this.item.uuid} value={this.item.uuid} />
             <DetailsAttribute label='Content address' linkToUuid={this.item.portableDataHash} value={this.item.portableDataHash} />
             {/* Missing attrs */}
-            <DetailsAttribute label='Number of files' value={this.data && this.data.fileCount} />
-            <DetailsAttribute label='Content size' value={formatFileSize(this.data && this.data.fileSize)} />
+            <DetailsAttribute label='Number of files' value={this.item.fileCount} />
+            <DetailsAttribute label='Content size' value={formatFileSize(this.item.fileSizeTotal)} />
         </div>;
     }
 }
         </div>;
     }
 }
index 45afb02b5a4a562b41a90cd94fcca3c8c3c9eb4e..ca8e2cd7dd86d661af91500515add9b809dcaf13 100644 (file)
@@ -4,10 +4,9 @@
 
 import * as React from 'react';
 import { DetailsResource } from "~/models/details";
 
 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> {
 
 export abstract class DetailsData<T extends DetailsResource = DetailsResource> {
-    constructor(protected item: T, protected data?: ResourceData) {}
+    constructor(protected item: T) { }
 
     getTitle(): string {
         return this.item.name || 'Projects';
 
     getTitle(): string {
         return this.item.name || 'Projects';
@@ -17,6 +16,6 @@ export abstract class DetailsData<T extends DetailsResource = DetailsResource> {
     abstract getDetails(): React.ReactElement<any>;
 
     getActivity(): React.ReactElement<any> {
     abstract getDetails(): React.ReactElement<any>;
 
     getActivity(): React.ReactElement<any> {
-        return <div/>;
+        return <div />;
     }
 }
     }
 }
index f4aaa8436f753face5dd8bf97a5a80eaea85f134..8244e15f06473f1d472177708830909077db20c8 100644 (file)
@@ -21,8 +21,6 @@ import { EmptyDetails } from "./empty-details";
 import { DetailsData } from "./details-data";
 import { DetailsResource } from "~/models/details";
 import { getResource } from '~/store/resources/resources';
 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";
 import { toggleDetailsPanel, SLIDE_TIMEOUT } from '~/store/details-panel/details-panel-action';
 import { FileDetails } from '~/views-components/details-panel/file-details';
 import { getNode } from '~/models/tree';
 import { toggleDetailsPanel, SLIDE_TIMEOUT } from '~/store/details-panel/details-panel-action';
 import { FileDetails } from '~/views-components/details-panel/file-details';
 import { getNode } from '~/models/tree';
@@ -62,13 +60,13 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
 
 const EMPTY_RESOURCE: EmptyResource = { kind: undefined, name: 'Projects' };
 
 
 const EMPTY_RESOURCE: EmptyResource = { kind: undefined, name: 'Projects' };
 
-const getItem = (res: DetailsResource, resourceData?: ResourceData): DetailsData => {
+const getItem = (res: DetailsResource): DetailsData => {
     if ('kind' in res) {
         switch (res.kind) {
             case ResourceKind.PROJECT:
                 return new ProjectDetails(res);
             case ResourceKind.COLLECTION:
     if ('kind' in res) {
         switch (res.kind) {
             case ResourceKind.PROJECT:
                 return new ProjectDetails(res);
             case ResourceKind.COLLECTION:
-                return new CollectionDetails(res, resourceData);
+                return new CollectionDetails(res);
             case ResourceKind.PROCESS:
                 return new ProcessDetails(res);
             default:
             case ResourceKind.PROCESS:
                 return new ProcessDetails(res);
             default:
@@ -79,13 +77,12 @@ const getItem = (res: DetailsResource, resourceData?: ResourceData): DetailsData
     }
 };
 
     }
 };
 
-const mapStateToProps = ({ detailsPanel, resources, resourcesData, collectionPanelFiles }: RootState) => {
+const mapStateToProps = ({ detailsPanel, resources, collectionPanelFiles }: RootState) => {
     const resource = getResource(detailsPanel.resourceUuid)(resources) as DetailsResource | undefined;
     const file = getNode(detailsPanel.resourceUuid)(collectionPanelFiles);
     const resource = getResource(detailsPanel.resourceUuid)(resources) as DetailsResource | undefined;
     const file = getNode(detailsPanel.resourceUuid)(collectionPanelFiles);
-    const resourceData = getResourceData(detailsPanel.resourceUuid)(resourcesData);
     return {
         isOpened: detailsPanel.isOpened,
     return {
         isOpened: detailsPanel.isOpened,
-        item: getItem(resource || (file && file.value) || EMPTY_RESOURCE, resourceData),
+        item: getItem(resource || (file && file.value) || EMPTY_RESOURCE),
     };
 };
 
     };
 };
 
index 28ae2f05eddd1e70c83868ef03b341c16a204e87..5c4b28df005f13081449bc28c0e40da5f8340bab 100644 (file)
@@ -21,8 +21,6 @@ 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 { 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";
 import { openDetailsPanel } from '~/store/details-panel/details-panel-action';
 import { snackbarActions, SnackbarKind } from '~/store/snackbar/snackbar-actions';
 import { PropertyChipComponent } from '~/views-components/resource-properties-form/property-chip';
 import { openDetailsPanel } from '~/store/details-panel/details-panel-action';
 import { snackbarActions, SnackbarKind } from '~/store/snackbar/snackbar-actions';
 import { PropertyChipComponent } from '~/views-components/resource-properties-form/property-chip';
@@ -59,22 +57,21 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
 
 interface CollectionPanelDataProps {
     item: CollectionResource;
 
 interface CollectionPanelDataProps {
     item: CollectionResource;
-    data: ResourceData;
 }
 
 type CollectionPanelProps = CollectionPanelDataProps & DispatchProp
     & WithStyles<CssRules> & RouteComponentProps<{ id: string }>;
 
 export const CollectionPanel = withStyles(styles)(
 }
 
 type CollectionPanelProps = CollectionPanelDataProps & DispatchProp
     & WithStyles<CssRules> & RouteComponentProps<{ id: string }>;
 
 export const CollectionPanel = withStyles(styles)(
-        connect((state: RootState, props: RouteComponentProps<{ id: string }>) => {
-            const item = getResource(props.match.params.id)(state.resources);
-            const data = getResourceData(props.match.params.id)(state.resourcesData);
-            return { item, data };
-        })(
+    connect((state: RootState, props: RouteComponentProps<{ id: string }>) => {
+        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() {
         class extends React.Component<CollectionPanelProps> {
 
             render() {
-                const { classes, item, data, dispatch } = this.props;
+                const { classes, item, dispatch } = this.props;
                 return item
                     ? <>
                         <Card className={classes.card}>
                 return item
                     ? <>
                         <Card className={classes.card}>
@@ -107,9 +104,9 @@ export const CollectionPanel = withStyles(styles)(
                                             label='Portable data hash'
                                             linkToUuid={item && item.portableDataHash} />
                                         <DetailsAttribute classLabel={classes.label} classValue={classes.value}
                                             label='Portable data hash'
                                             linkToUuid={item && item.portableDataHash} />
                                         <DetailsAttribute classLabel={classes.label} classValue={classes.value}
-                                            label='Number of files' value={data && data.fileCount} />
+                                            label='Number of files' value={item && item.fileCount} />
                                         <DetailsAttribute classLabel={classes.label} classValue={classes.value}
                                         <DetailsAttribute classLabel={classes.label} classValue={classes.value}
-                                            label='Content size' value={data && formatFileSize(data.fileSize)} />
+                                            label='Content size' value={item && formatFileSize(item.fileSizeTotal)} />
                                         <DetailsAttribute classLabel={classes.label} classValue={classes.value}
                                             label='Owner' linkToUuid={item && item.ownerUuid} />
                                         {(item.properties.container_request || item.properties.containerRequest) &&
                                         <DetailsAttribute classLabel={classes.label} classValue={classes.value}
                                             label='Owner' linkToUuid={item && item.ownerUuid} />
                                         {(item.properties.container_request || item.properties.containerRequest) &&