X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/525e81bdbe18ea369f5a61a713e743608bab2e42..8d3cf07be66fb6b8a58c3999783ebc753c30428f:/services/workbench2/src/views-components/data-explorer/renderers.tsx

diff --git a/services/workbench2/src/views-components/data-explorer/renderers.tsx b/services/workbench2/src/views-components/data-explorer/renderers.tsx
index 257eacfb29..4ecbc7e10b 100644
--- a/services/workbench2/src/views-components/data-explorer/renderers.tsx
+++ b/services/workbench2/src/views-components/data-explorer/renderers.tsx
@@ -3,7 +3,7 @@
 // SPDX-License-Identifier: AGPL-3.0
 
 import React from "react";
-import { Grid, Typography, withStyles, Tooltip, IconButton, Checkbox, Chip } from "@material-ui/core";
+import { Grid, Typography, withStyles, Tooltip, IconButton, Checkbox, Chip, withTheme } from "@material-ui/core";
 import { FavoriteStar, PublicFavoriteStar } from "../favorite-star/favorite-star";
 import { Resource, ResourceKind, TrashableResource } from "models/resource";
 import {
@@ -21,6 +21,7 @@ import {
     ActiveIcon,
     SetupIcon,
     InactiveIcon,
+    ErrorIcon,
 } from "components/icon/icon";
 import { formatDate, formatFileSize, formatTime } from "common/formatters";
 import { resourceLabel } from "common/labels";
@@ -53,6 +54,7 @@ import { VirtualMachinesResource } from "models/virtual-machines";
 import { CopyToClipboardSnackbar } from "components/copy-to-clipboard-snackbar/copy-to-clipboard-snackbar";
 import { ProjectResource } from "models/project";
 import { ProcessResource } from "models/process";
+import { InlinePulser } from "components/loading/inline-pulser";
 
 const renderName = (dispatch: Dispatch, item: GroupContentsResource) => {
     const navFunc = "groupClass" in item && item.groupClass === GroupClass.ROLE ? navigateToGroupDetails : navigateTo;
@@ -68,7 +70,10 @@ const renderName = (dispatch: Dispatch, item: GroupContentsResource) => {
                 <Typography
                     color="primary"
                     style={{ width: "auto", cursor: "pointer" }}
-                    onClick={() => dispatch<any>(navFunc(item.uuid))}
+                    onClick={(ev) => {
+                        ev.stopPropagation()
+                        dispatch<any>(navFunc(item.uuid))
+                    }}
                 >
                     {item.kind === ResourceKind.PROJECT || item.kind === ResourceKind.COLLECTION ? <IllegalNamingWarning name={item.name} /> : null}
                     {item.name}
@@ -512,7 +517,7 @@ const getResourceDisplayName = (resource: Resource): string => {
     }
 };
 
-const renderResourceLink = (dispatch: Dispatch, item: Resource) => {
+const renderResourceLink = (dispatch: Dispatch, item: Resource ) => {
     var displayName = getResourceDisplayName(item);
 
     return (
@@ -523,6 +528,8 @@ const renderResourceLink = (dispatch: Dispatch, item: Resource) => {
             onClick={() => {
                 item.kind === ResourceKind.GROUP && (item as GroupResource).groupClass === "role"
                     ? dispatch<any>(navigateToGroupDetails(item.uuid))
+                    : item.kind === ResourceKind.USER
+                    ? dispatch<any>(navigateToUserProfile(item.uuid))
                     : dispatch<any>(navigateTo(item.uuid));
             }}
         >
@@ -914,6 +921,30 @@ const _resourceWithName = withStyles(
     );
 });
 
+const _resourceWithNameLink = withStyles(
+    {},
+    { withTheme: true }
+)((props: { uuid: string; userFullname: string; dispatch: Dispatch; theme: ArvadosTheme }) => {
+    const { uuid, userFullname, dispatch, theme } = props;
+    if (!userFullname) {
+        dispatch<any>(loadResource(uuid, false));
+    }
+
+    return (
+        <Typography
+            style={{ color: theme.palette.primary.main, cursor: 'pointer' }}
+            inline
+            noWrap
+            onClick={() => dispatch<any>(navigateTo(uuid))}
+        >
+            {userFullname ? userFullname : uuid}
+        </Typography>
+    )
+});
+
+
+export const ResourceOwnerWithNameLink = ownerFromResourceId(_resourceWithNameLink);
+
 export const ResourceOwnerWithName = ownerFromResourceId(_resourceWithName);
 
 export const ResourceWithName = userFromID(_resourceWithName);
@@ -1106,3 +1137,30 @@ export const ContainerRunTime = connect((state: RootState, props: { uuid: string
         }
     }
 );
+
+export const GroupMembersCount = connect(
+    (state: RootState, props: { uuid: string }) => {
+        const group = getResource<GroupResource>(props.uuid)(state.resources);
+
+        return {
+            value: group?.memberCount,
+        };
+
+    }
+)(withTheme()((props: {value: number | null | undefined, theme:ArvadosTheme}) => {
+    if (props.value === undefined) {
+        // Loading
+        return <Typography component={"div"}>
+            <InlinePulser />
+        </Typography>;
+    } else if (props.value === null) {
+        // Error
+        return <Typography>
+            <Tooltip title="Failed to load member count">
+                <ErrorIcon style={{color: props.theme.customs.colors.greyL}}/>
+            </Tooltip>
+        </Typography>;
+    } else {
+        return <Typography children={props.value} />;
+    }
+}));
