[ARVADOS-WORKBENCH2] created: 2.1.0-185-gecf96ade
Git user
git at public.arvados.org
Thu Jan 28 21:24:49 UTC 2021
at ecf96ade39e828e7456a80adee8399d5653fa1d2 (commit)
commit ecf96ade39e828e7456a80adee8399d5653fa1d2
Author: Daniel Kutyła <daniel.kutyla at contractors.roche.com>
Date: Thu Jan 28 22:23:29 2021 +0100
17205: Added new component to fetch owner name
Arvados-DCO-1.1-Signed-off-by: Daniel Kutyła <daniel.kutyla at contractors.roche.com>
diff --git a/src/components/details-attribute/details-attribute.tsx b/src/components/details-attribute/details-attribute.tsx
index 01276c57..7633b71a 100644
--- a/src/components/details-attribute/details-attribute.tsx
+++ b/src/components/details-attribute/details-attribute.tsx
@@ -62,6 +62,7 @@ interface DetailsAttributeDataProps {
onValueClick?: () => void;
linkToUuid?: string;
copyValue?: string;
+ uuidEnhancer?: Function;
}
type DetailsAttributeProps = DetailsAttributeDataProps & WithStyles<CssRules> & FederationConfig & DispatchProp;
@@ -84,23 +85,25 @@ export const DetailsAttribute = connect(mapStateToProps)(withStyles(styles)(
}
render() {
- const { label, link, value, children, classes, classLabel,
+ const { uuidEnhancer, label, link, value, children, classes, classLabel,
classValue, lowercaseValue, onValueClick, linkToUuid,
localCluster, remoteHostsConfig, sessions, copyValue } = this.props;
let valueNode: React.ReactNode;
if (linkToUuid) {
+ const uuid = uuidEnhancer ? uuidEnhancer(linkToUuid) : linkToUuid;
const linkUrl = getNavUrl(linkToUuid || "", { localCluster, remoteHostsConfig, sessions });
if (linkUrl[0] === '/') {
- valueNode = <Link to={linkUrl} className={classes.link}>{linkToUuid}</Link>;
+ valueNode = <Link to={linkUrl} className={classes.link}>{uuid}</Link>;
} else {
- valueNode = <a href={linkUrl} className={classes.link} target='_blank'>{linkToUuid}</a>;
+ valueNode = <a href={linkUrl} className={classes.link} target='_blank'>{uuid}</a>;
}
} else if (link) {
valueNode = <a href={link} className={classes.link} target='_blank'>{value}</a>;
} else {
valueNode = value;
}
+
return <Typography component="div" className={classes.attribute}>
<Typography component="div" className={classnames([classes.label, classLabel])}>{label}</Typography>
<Typography
diff --git a/src/store/owner-name-uuid-enhancer/owner-name-uuid-enhancer-actions.ts b/src/store/owner-name-uuid-enhancer/owner-name-uuid-enhancer-actions.ts
new file mode 100644
index 00000000..cb95c12c
--- /dev/null
+++ b/src/store/owner-name-uuid-enhancer/owner-name-uuid-enhancer-actions.ts
@@ -0,0 +1,52 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { Dispatch } from 'redux';
+import { unionize, ofType, UnionOf } from '~/common/unionize';
+import { extractUuidObjectType, ResourceObjectType } from '~/models/resource';
+import { ServiceRepository } from '~/services/services';
+import { RootState } from '../store';
+
+export type OwnerNameUuidEnhancerAction = UnionOf<typeof ownerNameUuidEnhancerActions>;
+
+export interface OwnerNameState {
+ name: string;
+ uuid: string;
+}
+
+export const ownerNameUuidEnhancerActions = unionize({
+ SET_OWNER_NAME_BY_UUID: ofType<OwnerNameState>()
+});
+
+export const fetchOwnerNameByUuid = (uuid: string) =>
+ (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+ const objectType = extractUuidObjectType(uuid);
+
+ switch (objectType) {
+ case ResourceObjectType.USER:
+ services.userService.get(uuid, false)
+ .then((data) =>
+ dispatch(
+ ownerNameUuidEnhancerActions.SET_OWNER_NAME_BY_UUID({
+ uuid,
+ name: (data as any).fullName,
+ })
+ )
+ );
+ break;
+ case ResourceObjectType.GROUP:
+ services.groupsService.get(uuid, false)
+ .then((data) =>
+ dispatch(
+ ownerNameUuidEnhancerActions.SET_OWNER_NAME_BY_UUID({
+ uuid,
+ name: (data as any).name,
+ })
+ )
+ );
+ break;
+ default:
+ break;
+ }
+ };
\ No newline at end of file
diff --git a/src/store/owner-name-uuid-enhancer/owner-name-uuid-enhancer-reducer.ts b/src/store/owner-name-uuid-enhancer/owner-name-uuid-enhancer-reducer.ts
new file mode 100644
index 00000000..39707928
--- /dev/null
+++ b/src/store/owner-name-uuid-enhancer/owner-name-uuid-enhancer-reducer.ts
@@ -0,0 +1,11 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { ownerNameUuidEnhancerActions, OwnerNameUuidEnhancerAction, OwnerNameState } from './owner-name-uuid-enhancer-actions';
+
+export const ownerNameUuidEnhancerReducer = (state = {}, action: OwnerNameUuidEnhancerAction) =>
+ ownerNameUuidEnhancerActions.match(action, {
+ SET_OWNER_NAME_BY_UUID: (data: OwnerNameState) => ({...state, [data.uuid]: data.name }),
+ default: () => state,
+ });
\ No newline at end of file
diff --git a/src/store/store.ts b/src/store/store.ts
index 517368aa..929ca616 100644
--- a/src/store/store.ts
+++ b/src/store/store.ts
@@ -66,6 +66,7 @@ import { linkAccountPanelReducer } from './link-account-panel/link-account-panel
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';
+import { ownerNameUuidEnhancerReducer } from './owner-name-uuid-enhancer/owner-name-uuid-enhancer-reducer';
import { SubprocessMiddlewareService } from '~/store/subprocess-panel/subprocess-panel-middleware-service';
import { SUBPROCESS_PANEL_ID } from '~/store/subprocess-panel/subprocess-panel-actions';
import { ALL_PROCESSES_PANEL_ID } from './all-processes-panel/all-processes-panel-action';
@@ -178,6 +179,7 @@ const createRootReducer = (services: ServiceRepository) => combineReducers({
dialog: dialogReducer,
favorites: favoritesReducer,
ownerName: ownerNameReducer,
+ ownerNameUuidEnhancer: ownerNameUuidEnhancerReducer,
publicFavorites: publicFavoritesReducer,
form: formReducer,
processLogsPanel: processLogsPanelReducer,
diff --git a/src/views-components/details-panel/process-details.tsx b/src/views-components/details-panel/process-details.tsx
index aa1b3a1d..a065d91e 100644
--- a/src/views-components/details-panel/process-details.tsx
+++ b/src/views-components/details-panel/process-details.tsx
@@ -10,6 +10,7 @@ import { ResourceKind } from '~/models/resource';
import { resourceLabel } from '~/common/labels';
import { DetailsData } from "./details-data";
import { DetailsAttribute } from "~/components/details-attribute/details-attribute";
+import OwnerNameUuidEnhancer from '../owner-name-uuid-enhancer/owner-name-uuid-enhancer';
export class ProcessDetails extends DetailsData<ProcessResource> {
@@ -20,7 +21,8 @@ export class ProcessDetails extends DetailsData<ProcessResource> {
getDetails() {
return <div>
<DetailsAttribute label='Type' value={resourceLabel(ResourceKind.PROCESS)} />
- <DetailsAttribute label='Owner' linkToUuid={this.item.ownerUuid} value={this.item.ownerUuid} />
+ <DetailsAttribute label='Owner' linkToUuid={this.item.ownerUuid} value={this.item.ownerUuid}
+ uuidEnhancer={(uuid: string) => <OwnerNameUuidEnhancer uuid={uuid} />} />
<DetailsAttribute label='Status' value={this.item.state} />
<DetailsAttribute label='Last modified' value={formatDate(this.item.modifiedAt)} />
diff --git a/src/views-components/details-panel/project-details.tsx b/src/views-components/details-panel/project-details.tsx
index b901abce..eb613bf2 100644
--- a/src/views-components/details-panel/project-details.tsx
+++ b/src/views-components/details-panel/project-details.tsx
@@ -17,6 +17,7 @@ import { withStyles, StyleRulesCallback, WithStyles } from '@material-ui/core';
import { ArvadosTheme } from '~/common/custom-theme';
import { Dispatch } from 'redux';
import { getPropertyChip } from '../resource-properties-form/property-chip';
+import OwnerNameUuidEnhancer from '../owner-name-uuid-enhancer/owner-name-uuid-enhancer';
export class ProjectDetails extends DetailsData<ProjectResource> {
getIcon(className?: string) {
@@ -59,7 +60,8 @@ const ProjectDetailsComponent = connect(null, mapDispatchToProps)(
withStyles(styles)(
({ classes, project, onClick }: ProjectDetailsComponentProps) => <div>
<DetailsAttribute label='Type' value={resourceLabel(ResourceKind.PROJECT)} />
- <DetailsAttribute label='Owner' linkToUuid={project.ownerUuid} lowercaseValue={true} />
+ <DetailsAttribute label='Owner' linkToUuid={project.ownerUuid}
+ uuidEnhancer={(uuid: string) => <OwnerNameUuidEnhancer uuid={uuid} />} lowercaseValue={true} />
<DetailsAttribute label='Last modified' value={formatDate(project.modifiedAt)} />
<DetailsAttribute label='Created at' value={formatDate(project.createdAt)} />
<DetailsAttribute label='Project UUID' linkToUuid={project.uuid} value={project.uuid} />
diff --git a/src/views-components/owner-name-uuid-enhancer/owner-name-uuid-enhancer.test.tsx b/src/views-components/owner-name-uuid-enhancer/owner-name-uuid-enhancer.test.tsx
new file mode 100644
index 00000000..1df5fafa
--- /dev/null
+++ b/src/views-components/owner-name-uuid-enhancer/owner-name-uuid-enhancer.test.tsx
@@ -0,0 +1,46 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from 'react';
+import { mount, configure } from 'enzyme';
+import * as Adapter from "enzyme-adapter-react-16";
+import { OwnerNameUuidEnhancer, OwnerNameUuidEnhancerProps } from './owner-name-uuid-enhancer';
+
+configure({ adapter: new Adapter() });
+
+describe('NotFoundPanelRoot', () => {
+ let props: OwnerNameUuidEnhancerProps;
+
+ beforeEach(() => {
+ props = {
+ ownerNamesMap: {},
+ fetchOwner: () => {},
+ uuid: 'zzzz-tpzed-xxxxxxxxxxxxxxx',
+ };
+ });
+
+ it('should render uuid without name', () => {
+ // when
+ const wrapper = mount(<OwnerNameUuidEnhancer {...props} />);
+
+ // then
+ expect(wrapper.html()).toBe('<span>zzzz-tpzed-xxxxxxxxxxxxxxx</span>');
+ });
+
+ it('should render uuid with name', () => {
+ // given
+ const fullName = 'John Doe';
+
+ // setup
+ props.ownerNamesMap = {
+ [props.uuid]: fullName
+ };
+
+ // when
+ const wrapper = mount(<OwnerNameUuidEnhancer {...props} />);
+
+ // then
+ expect(wrapper.html()).toBe('<span>zzzz-tpzed-xxxxxxxxxxxxxxx (John Doe)</span>');
+ });
+});
\ No newline at end of file
diff --git a/src/views-components/owner-name-uuid-enhancer/owner-name-uuid-enhancer.tsx b/src/views-components/owner-name-uuid-enhancer/owner-name-uuid-enhancer.tsx
new file mode 100644
index 00000000..b4431fa4
--- /dev/null
+++ b/src/views-components/owner-name-uuid-enhancer/owner-name-uuid-enhancer.tsx
@@ -0,0 +1,46 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from 'react';
+import { Dispatch } from 'redux';
+import { RootState } from '~/store/store';
+import { connect } from 'react-redux';
+import { fetchOwnerNameByUuid } from '~/store/owner-name-uuid-enhancer/owner-name-uuid-enhancer-actions';
+
+export interface OwnerNameUuidEnhancerOwnProps {
+ uuid: string;
+}
+
+export interface OwnerNameUuidEnhancerRootDataProps {
+ ownerNamesMap: any;
+}
+
+export interface OwnerNameUuidEnhancerDispatchProps {
+ fetchOwner: Function;
+}
+
+export type OwnerNameUuidEnhancerProps = OwnerNameUuidEnhancerOwnProps & OwnerNameUuidEnhancerRootDataProps & OwnerNameUuidEnhancerDispatchProps;
+
+export const OwnerNameUuidEnhancer = ({ uuid, ownerNamesMap, fetchOwner }: OwnerNameUuidEnhancerProps) => {
+ React.useEffect(() => {
+ if (!ownerNamesMap[uuid]) {
+ fetchOwner(uuid);
+ }
+ }, [uuid, ownerNamesMap, fetchOwner]);
+
+ return <span>{uuid}{ownerNamesMap[uuid] ? ` (${ownerNamesMap[uuid]})` : ''}</span>;
+};
+
+const mapStateToProps = (state: RootState): OwnerNameUuidEnhancerRootDataProps => {
+ return {
+ ownerNamesMap: state.ownerNameUuidEnhancer,
+ };
+};
+
+const mapDispatchToProps = (dispatch: Dispatch): OwnerNameUuidEnhancerDispatchProps => ({
+ fetchOwner: (uuid: string) => dispatch<any>(fetchOwnerNameByUuid(uuid))
+});
+
+export default connect<OwnerNameUuidEnhancerRootDataProps, OwnerNameUuidEnhancerDispatchProps, OwnerNameUuidEnhancerOwnProps>(mapStateToProps, mapDispatchToProps)
+ (OwnerNameUuidEnhancer);
diff --git a/src/views/collection-panel/collection-panel.tsx b/src/views/collection-panel/collection-panel.tsx
index 685bb78b..e75073ae 100644
--- a/src/views/collection-panel/collection-panel.tsx
+++ b/src/views/collection-panel/collection-panel.tsx
@@ -30,6 +30,7 @@ import { UserResource } from '~/models/user';
import { getUserUuid } from '~/common/getuser';
import { getProgressIndicator } from '~/store/progress-indicator/progress-indicator-reducer';
import { COLLECTION_PANEL_LOAD_FILES, loadCollectionFiles, COLLECTION_PANEL_LOAD_FILES_THRESHOLD } from '~/store/collection-panel/collection-panel-files/collection-panel-files-actions';
+import OwnerNameUuidEnhancer from '../../views-components/owner-name-uuid-enhancer/owner-name-uuid-enhancer';
import { Link } from 'react-router-dom';
import { Link as ButtonLink } from '@material-ui/core';
@@ -288,7 +289,7 @@ export const CollectionDetailsAttributes = (props: { item: CollectionResource, t
<Grid item xs={12} md={mdSize}>
<DetailsAttribute classLabel={classes.label} classValue={classes.value}
label={isOldVersion ? "This version's UUID" : "Collection UUID"}
- linkToUuid={item.uuid} />
+ linkToUuid={`${item.uuid} AAAAAAAAAAAAAAAPortable data hash`} />
</Grid>
<Grid item xs={12} md={mdSize}>
<DetailsAttribute classLabel={classes.label} classValue={classes.value}
@@ -297,7 +298,8 @@ export const CollectionDetailsAttributes = (props: { item: CollectionResource, t
</Grid>
<Grid item xs={12} md={mdSize}>
<DetailsAttribute classLabel={classes.label} classValue={classes.value}
- label='Owner' linkToUuid={item.ownerUuid} />
+ label='Owner' linkToUuid={item.ownerUuid}
+ uuidEnhancer={(uuid: string) => <OwnerNameUuidEnhancer uuid={uuid} />} />
</Grid>
<Grid item xs={12} md={mdSize}>
<DetailsAttribute classLabel={classes.label} classValue={classes.value}
@@ -309,7 +311,7 @@ export const CollectionDetailsAttributes = (props: { item: CollectionResource, t
<DetailsAttribute
classLabel={classes.label} classValue={classes.value}
label='Version number'
- value={ showVersionBrowser !== undefined
+ value={showVersionBrowser !== undefined
? <Tooltip title="Open version browser"><ButtonLink underline='none' className={classes.button} onClick={() => showVersionBrowser()}>
{<span data-cy='collection-version-number'>{item.version}</span>}
</ButtonLink></Tooltip>
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list