From: Daniel Kutyła Date: Thu, 28 Jan 2021 21:23:29 +0000 (+0100) Subject: 17205: Added new component to fetch owner name X-Git-Tag: 2.1.2~3^2~3 X-Git-Url: https://git.arvados.org/arvados-workbench2.git/commitdiff_plain/ecf96ade39e828e7456a80adee8399d5653fa1d2 17205: Added new component to fetch owner name Arvados-DCO-1.1-Signed-off-by: Daniel Kutyła --- 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 & 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 = {linkToUuid}; + valueNode = {uuid}; } else { - valueNode = {linkToUuid}; + valueNode = {uuid}; } } else if (link) { valueNode = {value}; } else { valueNode = value; } + return {label} ; + +export interface OwnerNameState { + name: string; + uuid: string; +} + +export const ownerNameUuidEnhancerActions = unionize({ + SET_OWNER_NAME_BY_UUID: ofType() +}); + +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 { @@ -20,7 +21,8 @@ export class ProcessDetails extends DetailsData { getDetails() { return
- + } /> 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 { getIcon(className?: string) { @@ -59,7 +60,8 @@ const ProjectDetailsComponent = connect(null, mapDispatchToProps)( withStyles(styles)( ({ classes, project, onClick }: ProjectDetailsComponentProps) =>
- + } lowercaseValue={true} /> 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(); + + // then + expect(wrapper.html()).toBe('zzzz-tpzed-xxxxxxxxxxxxxxx'); + }); + + it('should render uuid with name', () => { + // given + const fullName = 'John Doe'; + + // setup + props.ownerNamesMap = { + [props.uuid]: fullName + }; + + // when + const wrapper = mount(); + + // then + expect(wrapper.html()).toBe('zzzz-tpzed-xxxxxxxxxxxxxxx (John Doe)'); + }); +}); \ 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 {uuid}{ownerNamesMap[uuid] ? ` (${ownerNamesMap[uuid]})` : ''}; +}; + +const mapStateToProps = (state: RootState): OwnerNameUuidEnhancerRootDataProps => { + return { + ownerNamesMap: state.ownerNameUuidEnhancer, + }; +}; + +const mapDispatchToProps = (dispatch: Dispatch): OwnerNameUuidEnhancerDispatchProps => ({ + fetchOwner: (uuid: string) => dispatch(fetchOwnerNameByUuid(uuid)) +}); + +export default connect(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 + linkToUuid={`${item.uuid} AAAAAAAAAAAAAAAPortable data hash`} /> + label='Owner' linkToUuid={item.ownerUuid} + uuidEnhancer={(uuid: string) => } /> showVersionBrowser()}> {{item.version}}