X-Git-Url: https://git.arvados.org/arvados-workbench2.git/blobdiff_plain/73122efb6429184611d17b3278ecbe9c2e26a6c2..703a2e1813ed1ff80d2ccd3214233240802b4754:/src/views-components/data-explorer/renderers.tsx

diff --git a/src/views-components/data-explorer/renderers.tsx b/src/views-components/data-explorer/renderers.tsx
index 314390e2..71b82b6f 100644
--- a/src/views-components/data-explorer/renderers.tsx
+++ b/src/views-components/data-explorer/renderers.tsx
@@ -6,7 +6,7 @@ import React from 'react';
 import { Grid, Typography, withStyles, Tooltip, IconButton, Checkbox } from '@material-ui/core';
 import { FavoriteStar, PublicFavoriteStar } from '../favorite-star/favorite-star';
 import { Resource, ResourceKind, TrashableResource } from 'models/resource';
-import { ProjectIcon, FilterGroupIcon, CollectionIcon, ProcessIcon, DefaultIcon, ShareIcon, CollectionOldVersionIcon, WorkflowIcon } from 'components/icon/icon';
+import { ProjectIcon, FilterGroupIcon, CollectionIcon, ProcessIcon, DefaultIcon, ShareIcon, CollectionOldVersionIcon, WorkflowIcon, RemoveIcon } from 'components/icon/icon';
 import { formatDate, formatFileSize, formatTime } from 'common/formatters';
 import { resourceLabel } from 'common/labels';
 import { connect, DispatchProp } from 'react-redux';
@@ -20,7 +20,7 @@ import { WorkflowResource } from 'models/workflow';
 import { ResourceStatus as WorkflowStatus } from 'views/workflow-panel/workflow-panel-view';
 import { getUuidPrefix, openRunProcess } from 'store/workflow-panel/workflow-panel-actions';
 import { openSharingDialog } from 'store/sharing-dialog/sharing-dialog-actions';
-import { getUserFullname, User, UserResource } from 'models/user';
+import { getUserFullname, getUserDisplayName, User, UserResource } from 'models/user';
 import { toggleIsActive, toggleIsAdmin } from 'store/users/users-actions';
 import { LinkResource } from 'models/link';
 import { navigateTo } from 'store/navigation/navigation-action';
@@ -29,6 +29,7 @@ import { CollectionResource } from 'models/collection';
 import { IllegalNamingWarning } from 'components/warning/warning';
 import { loadResource } from 'store/resources/resources-actions';
 import { GroupClass } from 'models/group';
+import { openRemoveGroupMemberDialog } from 'store/group-details-panel/group-details-panel-actions';
 
 const renderName = (dispatch: Dispatch, item: GroupContentsResource) =>
     <Grid container alignItems="center" wrap="nowrap" spacing={16}>
@@ -131,11 +132,11 @@ export const ResourceShare = connect(
     })((props: { ownerUuid?: string, uuidPrefix: string, uuid?: string } & DispatchProp<any>) =>
         resourceShare(props.dispatch, props.uuidPrefix, props.ownerUuid, props.uuid));
 
+// User Resources
 const renderFirstName = (item: { firstName: string }) => {
     return <Typography noWrap>{item.firstName}</Typography>;
 };
 
-// User Resources
 export const ResourceFirstName = connect(
     (state: RootState, props: { uuid: string }) => {
         const resource = getResource<UserResource>(props.uuid)(state.resources);
@@ -151,6 +152,16 @@ export const ResourceLastName = connect(
         return resource || { lastName: '' };
     })(renderLastName);
 
+const renderFullName = (item: { firstName: string, lastName: string }) =>
+    <Typography noWrap>{(item.firstName + " " + item.lastName).trim()}</Typography>;
+
+export const ResourceFullName = connect(
+    (state: RootState, props: { uuid: string }) => {
+        const resource = getResource<UserResource>(props.uuid)(state.resources);
+        return resource || { firstName: '', lastName: '' };
+    })(renderFullName);
+
+
 const renderUuid = (item: { uuid: string }) =>
     <Typography noWrap>{item.uuid}</Typography>;
 
@@ -276,45 +287,43 @@ export const ResourceLinkClass = connect(
         return resource || { linkClass: '' };
     })(renderLinkClass);
 
-const renderLinkTail = (dispatch: Dispatch, item: { uuid: string, tailUuid: string, tailKind: string }) => {
-    const currentLabel = resourceLabel(item.tailKind);
-    const isUnknow = currentLabel === "Unknown";
-    return (<div>
-        {!isUnknow ? (
-            renderLink(dispatch, item.tailUuid, currentLabel)
-        ) : (
-                <Typography noWrap color="default">
-                    {item.tailUuid}
-                </Typography>
-            )}
-    </div>);
-};
+const renderLink = (dispatch: Dispatch, item: Resource) => {
+    var displayName = '';
 
-const renderLink = (dispatch: Dispatch, uuid: string, label: string) =>
-    <Typography noWrap color="primary" style={{ 'cursor': 'pointer' }} onClick={() => dispatch<any>(navigateTo(uuid))}>
-        {label}: {uuid}
+    if ((item as UserResource).kind === ResourceKind.USER
+          && typeof (item as UserResource).firstName !== 'undefined') {
+        // We can be sure the resource is UserResource
+        displayName = getUserDisplayName(item as UserResource);
+    } else {
+        displayName = (item as GroupContentsResource).name;
+    }
+
+    return <Typography noWrap color="primary" style={{ 'cursor': 'pointer' }} onClick={() => dispatch<any>(navigateTo(item.uuid))}>
+        {resourceLabel(item.kind)}: {displayName || item.uuid}
     </Typography>;
+}
 
 export const ResourceLinkTail = connect(
     (state: RootState, props: { uuid: string }) => {
         const resource = getResource<LinkResource>(props.uuid)(state.resources);
+        const tailResource = getResource<Resource>(resource?.tailUuid || '')(state.resources);
+
         return {
-            item: resource || { uuid: '', tailUuid: '', tailKind: ResourceKind.NONE }
+            item: tailResource || { uuid: resource?.tailUuid || '', kind: resource?.tailKind || ResourceKind.NONE }
         };
-    })((props: { item: any } & DispatchProp<any>) =>
-        renderLinkTail(props.dispatch, props.item));
-
-const renderLinkHead = (dispatch: Dispatch, item: { uuid: string, headUuid: string, headKind: ResourceKind }) =>
-    renderLink(dispatch, item.headUuid, resourceLabel(item.headKind));
+    })((props: { item: Resource } & DispatchProp<any>) =>
+        renderLink(props.dispatch, props.item));
 
 export const ResourceLinkHead = connect(
     (state: RootState, props: { uuid: string }) => {
         const resource = getResource<LinkResource>(props.uuid)(state.resources);
+        const headResource = getResource<Resource>(resource?.headUuid || '')(state.resources);
+
         return {
-            item: resource || { uuid: '', headUuid: '', headKind: ResourceKind.NONE }
+            item: headResource || { uuid: resource?.headUuid || '', kind: resource?.headKind || ResourceKind.NONE }
         };
-    })((props: { item: any } & DispatchProp<any>) =>
-        renderLinkHead(props.dispatch, props.item));
+    })((props: { item: Resource } & DispatchProp<any>) =>
+        renderLink(props.dispatch, props.item));
 
 export const ResourceLinkUuid = connect(
     (state: RootState, props: { uuid: string }) => {
@@ -322,6 +331,59 @@ export const ResourceLinkUuid = connect(
         return resource || { uuid: '' };
     })(renderUuid);
 
+export const ResourceLinkHeadUuid = connect(
+    (state: RootState, props: { uuid: string }) => {
+        const link = getResource<LinkResource>(props.uuid)(state.resources);
+        const headResource = getResource<Resource>(link?.headUuid || '')(state.resources);
+
+        return headResource || { uuid: '' };
+    })(renderUuid);
+
+export const ResourceLinkTailUuid = connect(
+    (state: RootState, props: { uuid: string }) => {
+        const link = getResource<LinkResource>(props.uuid)(state.resources);
+        const tailResource = getResource<Resource>(link?.tailUuid || '')(state.resources);
+
+        return tailResource || { uuid: '' };
+    })(renderUuid);
+
+const renderLinkDelete = (dispatch: Dispatch, item: LinkResource) => {
+    if (item.uuid) {
+        return <Typography noWrap>
+            <IconButton onClick={() => dispatch<any>(openRemoveGroupMemberDialog(item.uuid))}>
+                <RemoveIcon />
+            </IconButton>
+        </Typography>;
+    } else {
+      return <Typography noWrap></Typography>;
+    }
+}
+
+export const ResourceLinkDelete = connect(
+    (state: RootState, props: { uuid: string }) => {
+        const link = getResource<LinkResource>(props.uuid)(state.resources);
+        return {
+            item: link || { uuid: '', kind: ResourceKind.NONE }
+        };
+    })((props: { item: LinkResource } & DispatchProp<any>) =>
+      renderLinkDelete(props.dispatch, props.item));
+
+export const ResourceLinkTailEmail = connect(
+    (state: RootState, props: { uuid: string }) => {
+        const link = getResource<LinkResource>(props.uuid)(state.resources);
+        const resource = getResource<UserResource>(link?.tailUuid || '')(state.resources);
+
+        return resource || { email: '' };
+    })(renderEmail);
+
+export const ResourceLinkTailUsername = connect(
+    (state: RootState, props: { uuid: string }) => {
+        const link = getResource<LinkResource>(props.uuid)(state.resources);
+        const resource = getResource<UserResource>(link?.tailUuid || '')(state.resources);
+
+        return resource || { username: '' };
+    })(renderUsername);
+
 // Process Resources
 const resourceRunProcess = (dispatch: Dispatch, uuid: string) => {
     return (
@@ -425,24 +487,27 @@ export const ResourceOwnerName = connect(
         return { owner: ownerName ? ownerName!.name : resource!.ownerUuid };
     })((props: { owner: string }) => renderOwner(props.owner));
 
-export const ResourceOwnerWithName =
-    compose(
-        connect(
-            (state: RootState, props: { uuid: string }) => {
-                let ownerName = '';
-                const resource = getResource<GroupContentsResource & UserResource>(props.uuid)(state.resources);
+const userFromID =
+    connect(
+        (state: RootState, props: { uuid: string }) => {
+            let userFullname = '';
+            const resource = getResource<GroupContentsResource & UserResource>(props.uuid)(state.resources);
 
-                if (resource) {
-                    ownerName = getUserFullname(resource as User) || (resource as GroupContentsResource).name;
-                }
+            if (resource) {
+                userFullname = getUserFullname(resource as User) || (resource as GroupContentsResource).name;
+            }
 
-                return { uuid: props.uuid, ownerName };
-            }),
+            return { uuid: props.uuid, userFullname };
+        });
+
+export const ResourceOwnerWithName =
+    compose(
+        userFromID,
         withStyles({}, { withTheme: true }))
-        ((props: { uuid: string, ownerName: string, dispatch: Dispatch, theme: ArvadosTheme }) => {
-            const { uuid, ownerName, dispatch, theme } = props;
+        ((props: { uuid: string, userFullname: string, dispatch: Dispatch, theme: ArvadosTheme }) => {
+            const { uuid, userFullname, dispatch, theme } = props;
 
-            if (ownerName === '') {
+            if (userFullname === '') {
                 dispatch<any>(loadResource(uuid, false));
                 return <Typography style={{ color: theme.palette.primary.main }} inline noWrap>
                     {uuid}
@@ -450,10 +515,23 @@ export const ResourceOwnerWithName =
             }
 
             return <Typography style={{ color: theme.palette.primary.main }} inline noWrap>
-                {ownerName} ({uuid})
+                {userFullname} ({uuid})
             </Typography>;
         });
 
+export const UserNameFromID =
+    compose(userFromID)(
+        (props: { uuid: string, userFullname: string, dispatch: Dispatch }) => {
+            const { uuid, userFullname, dispatch } = props;
+
+            if (userFullname === '') {
+                dispatch<any>(loadResource(uuid, false));
+            }
+            return <span>
+                {userFullname ? userFullname : uuid}
+            </span>;
+        });
+
 export const ResponsiblePerson =
     compose(
         connect(
