check-for-collections-with-same-content-adress
authorPawel Kowalczyk <pawel.kowalczyk@contractors.roche.com>
Mon, 6 May 2019 10:06:59 +0000 (12:06 +0200)
committerPawel Kowalczyk <pawel.kowalczyk@contractors.roche.com>
Mon, 6 May 2019 10:06:59 +0000 (12:06 +0200)
Feature #15020

Arvados-DCO-1.1-Signed-off-by: Pawel Kowalczyk <pawel.kowalczyk@contractors.roche.com>

src/store/collection-panel/collection-panel-action.ts
src/store/collection-panel/collection-panel-files/collection-panel-files-actions.ts
src/store/collection-panel/collection-panel-reducer.ts
src/store/workbench/workbench-actions.ts
src/views-components/details-panel/collection-details.tsx
src/views-components/details-panel/details-data.tsx
src/views-components/details-panel/details-panel.tsx

index cd4264710cb8feb93e264a3cfb90c78fd9cc8bce..76a40dcbea4f09b50ce6129e485585dddd822ba0 100644 (file)
@@ -7,7 +7,7 @@ import { loadCollectionFiles } from "./collection-panel-files/collection-panel-f
 import { CollectionResource } from '~/models/collection';
 import { collectionPanelFilesAction } from "./collection-panel-files/collection-panel-files-actions";
 import { createTree } from "~/models/tree";
-import { RootState } from "../store";
+import { RootState } from "~/store/store";
 import { ServiceRepository } from "~/services/services";
 import { TagProperty } from "~/models/tag";
 import { snackbarActions } from "../snackbar/snackbar-actions";
@@ -15,9 +15,12 @@ import { resourcesActions } from "~/store/resources/resources-actions";
 import { unionize, ofType, UnionOf } from '~/common/unionize';
 import { SnackbarKind } from '~/store/snackbar/snackbar-actions';
 import { navigateTo } from '~/store/navigation/navigation-action';
+import { FilterBuilder } from "~/services/api/filter-builder";
+import { loadDetailsPanel } from '~/store/details-panel/details-panel-action';
 
 export const collectionPanelActions = unionize({
     SET_COLLECTION: ofType<CollectionResource>(),
+    SET_NUMBER_OF_COLLECTIONS_WITH_SAME_PDH: ofType<number>(),
     LOAD_COLLECTION: ofType<{ uuid: string }>(),
     LOAD_COLLECTION_SUCCESS: ofType<{ item: CollectionResource }>()
 });
@@ -31,6 +34,13 @@ export const loadCollectionPanel = (uuid: string) =>
         dispatch(collectionPanelActions.LOAD_COLLECTION({ uuid }));
         dispatch(collectionPanelFilesAction.SET_COLLECTION_FILES({ files: createTree() }));
         const collection = await services.collectionService.get(uuid);
+        const collectionsByPDH = await services.collectionService.list({
+            filters: new FilterBuilder()
+                .addEqual('portableDataHash', collection.portableDataHash)
+                .getFilters()
+        });
+        dispatch(collectionPanelActions.SET_NUMBER_OF_COLLECTIONS_WITH_SAME_PDH(collectionsByPDH.itemsAvailable));
+        dispatch(loadDetailsPanel(collection.uuid));
         dispatch(collectionPanelActions.LOAD_COLLECTION_SUCCESS({ item: collection }));
         dispatch(resourcesActions.SET_RESOURCES([collection]));
         dispatch<any>(loadCollectionFiles(collection.uuid));
index b75de94a7e890ac74871b496b565bf270c3d861e..534d70d480e2fcf263db814a1e46b539619ababd 100644 (file)
@@ -77,8 +77,8 @@ export const openFileRemoveDialog = (filePath: string) =>
                 ? 'Are you sure you want to remove this directory?'
                 : 'Are you sure you want to remove this file?';
             const info = isDirectory
-                ? 'Removing files will change content adress.'
-                : 'Removing a file will change content adress.';
+                ? 'Removing files will change content address.'
+                : 'Removing a file will change content address.';
 
             dispatch(dialogActions.OPEN_DIALOG({
                 id: FILE_REMOVE_DIALOG,
@@ -101,7 +101,7 @@ export const openMultipleFilesRemoveDialog = () =>
         data: {
             title: 'Removing files',
             text: 'Are you sure you want to remove selected files?',
-            info: 'Removing files will change content adress.',
+            info: 'Removing files will change content address.',
             confirmButtonLabel: 'Remove'
         }
     });
index 55829cb5d094b8e4b9dbddd313dffa256f78eb6f..4207a3930410069a0871d5a4938d6df18a98fe1f 100644 (file)
@@ -7,10 +7,12 @@ import { CollectionResource } from "~/models/collection";
 
 export interface CollectionPanelState {
     item: CollectionResource | null;
+    numberOfCollectionsWithSamePDH: number;
 }
 
 const initialState = {
-    item: null
+    item: null,
+    numberOfCollectionsWithSamePDH: 0
 };
 
 export const collectionPanelReducer = (state: CollectionPanelState = initialState, action: CollectionPanelAction) =>
@@ -18,4 +20,5 @@ export const collectionPanelReducer = (state: CollectionPanelState = initialStat
         default: () => state,
         SET_COLLECTION: (item) => ({ ...state, item }),
         LOAD_COLLECTION_SUCCESS: ({ item }) => ({ ...state, item }),
+        SET_NUMBER_OF_COLLECTIONS_WITH_SAME_PDH: (num) => ({ ...state, numberOfCollectionsWithSamePDH: num }),
     });
index adf3fa15aeeb416f927ed99a3f483e4ae7894325..378bb8de541fedad7af6b9f1b073c6464e2ca94b 100644 (file)
@@ -68,8 +68,7 @@ import { FilterBuilder } from '~/services/api/filter-builder';
 import { GroupContentsResource } from '~/services/groups-service/groups-service';
 import { MatchCases, ofType, unionize, UnionOf } from '~/common/unionize';
 import { loadRunProcessPanel } from '~/store/run-process-panel/run-process-panel-actions';
-import { loadCollectionFiles } from '~/store/collection-panel/collection-panel-files/collection-panel-files-actions';
-import { collectionPanelActions } from "~/store/collection-panel/collection-panel-action";
+import { collectionPanelActions, loadCollectionPanel } from "~/store/collection-panel/collection-panel-action";
 import { CollectionResource } from "~/models/collection";
 import {
     loadSearchResultsPanel,
@@ -256,22 +255,22 @@ export const loadCollection = (uuid: string) =>
                         dispatch(collectionPanelActions.SET_COLLECTION(collection as CollectionResource));
                         dispatch(updateResources([collection]));
                         await dispatch(activateSidePanelTreeItem(collection.ownerUuid));
-                        dispatch(setSidePanelBreadcrumbs(collection.ownerUuid));
-                        dispatch(loadCollectionFiles(collection.uuid));
+                        dispatch(setSidePanelBreadcrumbs(collection.ownerUuid));              
+                        dispatch(loadCollectionPanel(collection.uuid));
                     },
                     SHARED: collection => {
                         dispatch(collectionPanelActions.SET_COLLECTION(collection as CollectionResource));
                         dispatch(updateResources([collection]));
                         dispatch<any>(setSharedWithMeBreadcrumbs(collection.ownerUuid));
                         dispatch(activateSidePanelTreeItem(collection.ownerUuid));
-                        dispatch(loadCollectionFiles(collection.uuid));
+                        dispatch(loadCollectionPanel(collection.uuid));
                     },
                     TRASHED: collection => {
                         dispatch(collectionPanelActions.SET_COLLECTION(collection as CollectionResource));
                         dispatch(updateResources([collection]));
                         dispatch(setTrashBreadcrumbs(''));
                         dispatch(activateSidePanelTreeItem(SidePanelTreeCategory.TRASH));
-                        dispatch(loadCollectionFiles(collection.uuid));
+                        dispatch(loadCollectionPanel(collection.uuid));
                     },
 
                 });
index 98fa388640757d4bd5a09d9cfbdd9d806a617b47..01b867b3fc47a7ec0a03cd0e40c990896fbbce05 100644 (file)
@@ -26,7 +26,7 @@ export class CollectionDetails extends DetailsData<CollectionResource> {
             <DetailsAttribute label='Created at' value={formatDate(this.item.createdAt)} />
             {/* Links but we dont have view */}
             <DetailsAttribute label='Collection UUID' link={this.item.uuid} value={this.item.uuid} />
-            <DetailsAttribute label='Content address' link={this.item.portableDataHash} value={this.item.portableDataHash} />
+            <DetailsAttribute label='Content address' link={this.numberOfCollectionsByPDH === 1 ? this.item.uuid : 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)} />
index 45afb02b5a4a562b41a90cd94fcca3c8c3c9eb4e..1a67a55dc1eda3c1ffcaadc238a33bcb7eab5b91 100644 (file)
@@ -7,7 +7,7 @@ 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, protected data?: ResourceData) {}
+    constructor(protected item: T, protected data?: ResourceData, protected numberOfCollectionsByPDH?: number) {}
 
     getTitle(): string {
         return this.item.name || 'Projects';
index 2a30ae4783d75d426d29bc82574cd19a086058b3..5c8ebe7479226b8a41e425201e1fb4d86315afab 100644 (file)
@@ -62,13 +62,13 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
 
 const EMPTY_RESOURCE: EmptyResource = { kind: undefined, name: 'Projects' };
 
-const getItem = (res: DetailsResource, resourceData?: ResourceData): DetailsData => {
+const getItem = (res: DetailsResource, resourceData?: ResourceData, numberOfCollectionsByPDH?: number): DetailsData => {
     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, resourceData, numberOfCollectionsByPDH);
             case ResourceKind.PROCESS:
                 return new ProcessDetails(res);
             default:
@@ -79,13 +79,14 @@ const getItem = (res: DetailsResource, resourceData?: ResourceData): DetailsData
     }
 };
 
-const mapStateToProps = ({ detailsPanel, resources, resourcesData, collectionPanelFiles }: RootState) => {
+const mapStateToProps = ({ detailsPanel, resources, resourcesData, collectionPanelFiles, collectionPanel }: RootState) => {
     const resource = getResource(detailsPanel.resourceUuid)(resources) as DetailsResource | undefined;
     const file = getNode(detailsPanel.resourceUuid)(collectionPanelFiles);
     const resourceData = getResourceData(detailsPanel.resourceUuid)(resourcesData);
+    const numberOfCollectionsByPDH = collectionPanel.numberOfCollectionsWithSamePDH;
     return {
         isOpened: detailsPanel.isOpened,
-        item: getItem(resource || (file && file.value) || EMPTY_RESOURCE, resourceData)
+        item: getItem(resource || (file && file.value) || EMPTY_RESOURCE, resourceData, numberOfCollectionsByPDH),
     };
 };