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 }>()
});
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]));
export interface CollectionPanelState {
item: CollectionResource | null;
- numberOfCollectionsWithSamePDH: number;
}
const initialState = {
- item: null,
- numberOfCollectionsWithSamePDH: 0
+ item: null
};
export const collectionPanelReducer = (state: CollectionPanelState = initialState, action: CollectionPanelAction) =>
collectionPanelActions.match(action, {
default: () => state,
SET_COLLECTION: (item) => ({ ...state, item }),
- LOAD_COLLECTION_SUCCESS: ({ item }) => ({ ...state, item }),
- SET_NUMBER_OF_COLLECTIONS_WITH_SAME_PDH: (num) => ({ ...state, numberOfCollectionsWithSamePDH: num }),
+ LOAD_COLLECTION_SUCCESS: ({ item }) => ({ ...state, item })
});
import { updateFavorites } from '~/store/favorites/favorites-actions';
import { updatePublicFavorites } from '~/store/public-favorites/public-favorites-actions';
import { setBreadcrumbs } from '../breadcrumbs/breadcrumbs-actions';
+import { ResourceKind, extractUuidKind } from '~/models/resource';
+import { ownerNameActions } from '~/store/owner-name/owner-name-actions';
export class CollectionsWithSameContentAddressMiddlewareService extends DataExplorerMiddlewareService {
constructor(private services: ServiceRepository, id: string) {
.addILike("name", dataExplorer.searchValue)
.getFilters()
});
+ const userUuids = response.items.map(it => {
+ if (extractUuidKind(it.ownerUuid) === ResourceKind.USER) {
+ return it.ownerUuid;
+ } else {
+ return '';
+ }
+ }
+ );
+ const groupUuids = response.items.map(it => {
+ if (extractUuidKind(it.ownerUuid) === ResourceKind.GROUP) {
+ return it.ownerUuid;
+ } else {
+ return '';
+ }
+ });
+ const responseUsers = await this.services.userService.list({
+ limit: dataExplorer.rowsPerPage,
+ offset: dataExplorer.page * dataExplorer.rowsPerPage,
+ filters: new FilterBuilder()
+ .addIn('uuid', userUuids)
+ .getFilters()
+ });
+ const responseGroups = await this.services.groupsService.list({
+ limit: dataExplorer.rowsPerPage,
+ offset: dataExplorer.page * dataExplorer.rowsPerPage,
+ filters: new FilterBuilder()
+ .addIn('uuid', groupUuids)
+ .getFilters()
+ });
+ responseUsers.items.map(it=>{
+ api.dispatch<any>(ownerNameActions.SET_OWNER_NAME({name: it.uuid === userUuid ? 'User: Me' : `User: ${it.firstName} ${it.lastName}`, uuid: it.uuid}));
+ });
+ responseGroups.items.map(it=>{
+ api.dispatch<any>(ownerNameActions.SET_OWNER_NAME({name: `Project: ${it.name}`, uuid: it.uuid}));
+ });
api.dispatch<any>(setBreadcrumbs([{ label: 'Projects', uuid: userUuid }]));
api.dispatch<any>(updateFavorites(response.items.map(item => item.uuid)));
api.dispatch<any>(updatePublicFavorites(response.items.map(item => item.uuid)));
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { unionize, ofType, UnionOf } from '~/common/unionize';
+
+export const ownerNameActions = unionize({
+ SET_OWNER_NAME: ofType<OwnerNameState>()
+});
+
+interface OwnerNameState {
+ name: string;
+ uuid: string;
+}
+
+export type OwnerNameAction = UnionOf<typeof ownerNameActions>;
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { ownerNameActions, OwnerNameAction } from './owner-name-actions';
+
+export const ownerNameReducer = (state = [], action: OwnerNameAction) =>
+ ownerNameActions.match(action, {
+ SET_OWNER_NAME: data => [...state, { uuid: data.uuid, name: data.name }],
+ default: () => state,
+ });
\ No newline at end of file
import { publicFavoritesReducer } from '~/store/public-favorites/public-favorites-reducer';
import { CollectionsWithSameContentAddressMiddlewareService } from '~/store/collections-content-address-panel/collections-content-address-middleware-service';
import { COLLECTIONS_CONTENT_ADDRESS_PANEL_ID } from '~/store/collections-content-address-panel/collections-content-address-panel-actions';
+import { ownerNameReducer } from '~/store/owner-name/owner-name-reducer';
const composeEnhancers =
(process.env.NODE_ENV === 'development' &&
detailsPanel: detailsPanelReducer,
dialog: dialogReducer,
favorites: favoritesReducer,
+ ownerName: ownerNameReducer,
publicFavorites: publicFavoritesReducer,
form: formReducer,
processLogsPanel: processLogsPanelReducer,
import { LinkResource } from '~/models/link';
import { navigateTo } from '~/store/navigation/navigation-action';
import { withResourceData } from '~/views-components/data-explorer/with-resources';
-import { extractUuidKind } from '~/models/resource';
-const renderName = (item: { name: string; uuid: string, kind: string }) =>
+const renderName = (dispatch: Dispatch, item: { name: string; uuid: string, kind: string }) =>
<Grid container alignItems="center" wrap="nowrap" spacing={16}>
<Grid item>
{renderIcon(item.kind)}
</Grid>
<Grid item>
- <Typography color="primary" style={{ width: 'auto' }}>
+ <Typography color="primary" style={{ width: 'auto', cursor: 'pointer' }} onClick={() => dispatch<any>(navigateTo(item.uuid))}>
{item.name}
</Typography>
</Grid>
(state: RootState, props: { uuid: string }) => {
const resource = getResource<GroupContentsResource>(props.uuid)(state.resources);
return resource || { name: '', uuid: '', kind: '' };
- })(renderName);
+ })((resource: { name: string; uuid: string, kind: string } & DispatchProp<any>) => renderName(resource.dispatch, resource));
const renderIcon = (kind: string) => {
switch (kind) {
})((props: { fileSize?: number }) => renderFileSize(props.fileSize));
const renderOwner = (owner: string) =>
- <Typography noWrap color="primary" >
+ <Typography noWrap>
{owner}
</Typography>;
return { owner: resource ? resource.ownerUuid : '' };
})((props: { owner: string }) => renderOwner(props.owner));
+export const ResourceOwnerName = connect(
+ (state: RootState, props: { uuid: string }) => {
+ const resource = getResource<GroupContentsResource>(props.uuid)(state.resources);
+ const ownerNameState = state.ownerName;
+ const ownerName = ownerNameState.find(it => it.uuid === resource!.ownerUuid);
+ return { owner: ownerName ? ownerName!.name : resource!.ownerUuid };
+ })((props: { owner: string }) => renderOwner(props.owner));
+
const renderType = (type: string) =>
<Typography noWrap>
{resourceLabel(type)}
<DetailsAttribute label='Owner' value={this.item.ownerUuid} lowercaseValue={true} />
<DetailsAttribute label='Last modified' value={formatDate(this.item.modifiedAt)} />
<DetailsAttribute label='Created at' value={formatDate(this.item.createdAt)} />
- {/* Links but we dont have view */}
<DetailsAttribute label='Collection UUID' linkInsideCard={this.item.uuid} value={this.item.uuid} />
- <DetailsAttribute label='Content address' linkInsideCard={this.numberOfCollectionsByPDH === 1 ? this.item.uuid : this.item.portableDataHash} value={this.item.portableDataHash} />
+ <DetailsAttribute label='Content address' linkInsideCard={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)} />
}
};
-const mapStateToProps = ({ detailsPanel, resources, resourcesData, collectionPanelFiles, collectionPanel }: RootState) => {
+const mapStateToProps = ({ detailsPanel, resources, resourcesData, collectionPanelFiles }: 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, numberOfCollectionsByPDH),
+ item: getItem(resource || (file && file.value) || EMPTY_RESOURCE, resourceData),
};
};
import { DataColumns } from '~/components/data-table/data-table';
import { SortDirection } from '~/components/data-table/data-column';
import { createTree } from '~/models/tree';
-import { ResourceName, ResourceOwner, ResourceLastModifiedDate } from '~/views-components/data-explorer/renderers';
+import { ResourceName, ResourceOwnerName, ResourceLastModifiedDate } from '~/views-components/data-explorer/renderers';
type CssRules = 'backLink' | 'backIcon' | 'card' | 'title' | 'iconHeader' | 'link';
selected: true,
configurable: true,
filters: createTree(),
- render: uuid => <ResourceOwner uuid={uuid} />
+ render: uuid => <ResourceOwnerName uuid={uuid} />
},
{
name: CollectionContentAddressPanelColumnNames.LAST_MODIFIED,