[ARVADOS-WORKBENCH2] created: 1.2.0-674-gd531ed8
Git user
git at public.curoverse.com
Tue Oct 16 07:44:57 EDT 2018
at d531ed8429325807f54943f33fdb750573b0694e (commit)
commit d531ed8429325807f54943f33fdb750573b0694e
Author: Daniel Kos <daniel.kos at contractors.roche.com>
Date: Tue Oct 16 13:44:23 2018 +0200
Add getting file size and number of collection files in main panel and side panel
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 f8e38f9..735ffa8 100644
--- a/src/models/collection.ts
+++ b/src/models/collection.ts
@@ -14,6 +14,8 @@ export interface CollectionResource extends TrashableResource {
replicationDesired: number;
replicationConfirmed: number;
replicationConfirmedAt: string;
+ fileSize: number;
+ fileCount: number;
}
export const getCollectionUrl = (uuid: string) => {
diff --git a/src/models/tree.ts b/src/models/tree.ts
index f0b53b4..6136011 100644
--- a/src/models/tree.ts
+++ b/src/models/tree.ts
@@ -86,7 +86,7 @@ export const getNodeDescendantsIds = (id: string, limit = Infinity) => <T>(tree:
const node = getNode(id)(tree);
const children = node ? node.children :
id === TREE_ROOT_ID
- ? getRootNodeChildren(tree)
+ ? getRootNodeChildrenIds(tree)
: [];
return children
@@ -207,11 +207,12 @@ const toggleParentNodeSelection = (id: string) => <T>(tree: Tree<T>) => {
const mapNodeValue = <T, R>(mapFn: (value: T) => R) => (node: TreeNode<T>): TreeNode<R> =>
({ ...node, value: mapFn(node.value) });
-const getRootNodeChildren = <T>(tree: Tree<T>) =>
+const getRootNodeChildrenIds = <T>(tree: Tree<T>) =>
Object
.keys(tree)
.filter(id => getNode(id)(tree)!.parent === TREE_ROOT_ID);
+
const addChild = (parentId: string, childId: string) => <T>(tree: Tree<T>): Tree<T> => {
const node = getNode(parentId)(tree);
if (node) {
diff --git a/src/store/project-panel/project-panel-middleware-service.ts b/src/store/project-panel/project-panel-middleware-service.ts
index 09e76ae..27efcd0 100644
--- a/src/store/project-panel/project-panel-middleware-service.ts
+++ b/src/store/project-panel/project-panel-middleware-service.ts
@@ -2,7 +2,12 @@
//
// SPDX-License-Identifier: AGPL-3.0
-import { DataExplorerMiddlewareService, getDataExplorerColumnFilters, dataExplorerToListParams, listResultsToDataExplorerItemsMeta } from '../data-explorer/data-explorer-middleware-service';
+import {
+ DataExplorerMiddlewareService,
+ dataExplorerToListParams,
+ getDataExplorerColumnFilters,
+ listResultsToDataExplorerItemsMeta
+} from '../data-explorer/data-explorer-middleware-service';
import { ProjectPanelColumnNames, ProjectPanelFilter } from "~/views/project-panel/project-panel";
import { RootState } from "../store";
import { DataColumns } from "~/components/data-table/data-table";
@@ -10,19 +15,23 @@ import { ServiceRepository } from "~/services/services";
import { SortDirection } from "~/components/data-table/data-column";
import { OrderBuilder, OrderDirection } from "~/services/api/order-builder";
import { FilterBuilder } from "~/services/api/filter-builder";
-import { GroupContentsResourcePrefix, GroupContentsResource } from "~/services/groups-service/groups-service";
+import { GroupContentsResource, GroupContentsResourcePrefix } from "~/services/groups-service/groups-service";
import { updateFavorites } from "../favorites/favorites-actions";
-import { projectPanelActions, PROJECT_PANEL_CURRENT_UUID } from './project-panel-action';
+import { PROJECT_PANEL_CURRENT_UUID, projectPanelActions } from './project-panel-action';
import { Dispatch, MiddlewareAPI } from "redux";
import { ProjectResource } from "~/models/project";
-import { updateResources } from "~/store/resources/resources-actions";
+import { resourcesActions, 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 { ResourceKind } from '~/models/resource';
+import { Resource, 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";
export class ProjectPanelMiddlewareService extends DataExplorerMiddlewareService {
constructor(private services: ServiceRepository, id: string) {
@@ -42,8 +51,10 @@ export class ProjectPanelMiddlewareService extends DataExplorerMiddlewareService
api.dispatch(progressIndicatorActions.START_WORKING(this.getId()));
const response = await this.services.groupsService.contents(projectUuid, getParams(dataExplorer));
api.dispatch(progressIndicatorActions.PERSIST_STOP_WORKING(this.getId()));
- api.dispatch<any>(updateFavorites(response.items.map(item => item.uuid)));
+ const resourceUuids = response.items.map(item => item.uuid);
+ api.dispatch<any>(updateFavorites(resourceUuids));
api.dispatch(updateResources(response.items));
+ api.dispatch<any>(updateFilesInfo(resourceUuids));
await api.dispatch<any>(loadMissingProcessesInformation(response.items));
api.dispatch(setItems(response));
} catch (e) {
@@ -76,6 +87,30 @@ export const loadMissingProcessesInformation = (resources: GroupContentsResource
}
};
+export const updateFilesInfo = (resourceUuids: string[]) =>
+ async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+ const resources = await Promise.all(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);
+ }
+
+ resource.fileCount = fileCount;
+ resource.fileSize = fileSize;
+ }
+ return resource;
+ }));
+ dispatch(resourcesActions.SET_RESOURCES(resources.filter(res => res) as Resource[]));
+ };
+
export const setItems = (listResults: ListResults<GroupContentsResource>) =>
projectPanelActions.SET_ITEMS({
...listResultsToDataExplorerItemsMeta(listResults),
diff --git a/src/views-components/data-explorer/renderers.tsx b/src/views-components/data-explorer/renderers.tsx
index 12e1be7..e76600e 100644
--- a/src/views-components/data-explorer/renderers.tsx
+++ b/src/views-components/data-explorer/renderers.tsx
@@ -19,6 +19,7 @@ import { compose } from 'redux';
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";
export const renderName = (item: { name: string; uuid: string, kind: string }) =>
<Grid container alignItems="center" wrap="nowrap" spacing={16}>
@@ -149,8 +150,8 @@ export const renderFileSize = (fileSize?: number) =>
export const ResourceFileSize = connect(
(state: RootState, props: { uuid: string }) => {
- const resource = getResource<GroupContentsResource>(props.uuid)(state.resources);
- return {};
+ const resource = getResource<CollectionResource>(props.uuid)(state.resources);
+ return { fileSize: resource ? resource.fileSize : 0 };
})((props: { fileSize?: number }) => renderFileSize(props.fileSize));
export const renderOwner = (owner: string) =>
diff --git a/src/views-components/details-panel/collection-details.tsx b/src/views-components/details-panel/collection-details.tsx
index 721418e..aec9911 100644
--- a/src/views-components/details-panel/collection-details.tsx
+++ b/src/views-components/details-panel/collection-details.tsx
@@ -5,7 +5,7 @@
import * as React from 'react';
import { CollectionIcon } from '~/components/icon/icon';
import { CollectionResource } from '~/models/collection';
-import { formatDate } from '~/common/formatters';
+import { formatDate, formatFileSize } from '~/common/formatters';
import { resourceLabel } from '~/common/labels';
import { ResourceKind } from '~/models/resource';
import { DetailsData } from "./details-data";
@@ -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='20' />
- <DetailsAttribute label='Content size' value='54 MB' />
+ <DetailsAttribute label='Number of files' value={this.item.fileCount} />
+ <DetailsAttribute label='Content size' value={formatFileSize(this.item.fileSize)} />
</div>;
}
}
diff --git a/src/views-components/details-panel/project-details.tsx b/src/views-components/details-panel/project-details.tsx
index 331952f..18affba 100644
--- a/src/views-components/details-panel/project-details.tsx
+++ b/src/views-components/details-panel/project-details.tsx
@@ -27,12 +27,12 @@ export class ProjectDetails extends DetailsData<ProjectResource> {
<DetailsAttribute label='Last modified' value={formatDate(this.item.modifiedAt)} />
<DetailsAttribute label='Created at' value={formatDate(this.item.createdAt)} />
{/* Missing attr */}
- <DetailsAttribute label='File size' value='1.4 GB' />
+ {/*<DetailsAttribute label='File size' value='1.4 GB' />*/}
<DetailsAttribute label='Description'>
- {this.item.description ?
+ {this.item.description ?
<RichTextEditorLink
title={`Description of ${this.item.name}`}
- content={this.item.description}
+ content={this.item.description}
label='Show full description' />
: '---'
}
diff --git a/src/views/collection-panel/collection-panel.tsx b/src/views/collection-panel/collection-panel.tsx
index 96c2fc9..7defc07 100644
--- a/src/views/collection-panel/collection-panel.tsx
+++ b/src/views/collection-panel/collection-panel.tsx
@@ -22,6 +22,7 @@ import { snackbarActions } from '~/store/snackbar/snackbar-actions';
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";
type CssRules = 'card' | 'iconHeader' | 'tag' | 'copyIcon' | 'label' | 'value';
@@ -99,9 +100,9 @@ export const CollectionPanel = withStyles(styles)(
</Tooltip>
</DetailsAttribute>
<DetailsAttribute classLabel={classes.label} classValue={classes.value}
- label='Number of files' value='14' />
+ label='Number of files' value={item && item.fileCount} />
<DetailsAttribute classLabel={classes.label} classValue={classes.value}
- label='Content size' value='54 MB' />
+ label='Content size' value={item && formatFileSize(item.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