// 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 {
ActiveIcon,
SetupIcon,
InactiveIcon,
+ ErrorIcon,
} from "components/icon/icon";
import { formatDate, formatFileSize, formatTime } from "common/formatters";
import { resourceLabel } from "common/labels";
import { getUuidPrefix, openRunProcess } from "store/workflow-panel/workflow-panel-actions";
import { openSharingDialog } from "store/sharing-dialog/sharing-dialog-actions";
import { getUserFullname, getUserDisplayName, User, UserResource } from "models/user";
-import { toggleIsAdmin } from "store/users/users-actions";
import { LinkClass, LinkResource } from "models/link";
import { navigateTo, navigateToGroupDetails, navigateToUserProfile } from "store/navigation/navigation-action";
import { withResourceData } from "views-components/data-explorer/with-resources";
import { CopyToClipboardSnackbar } from "components/copy-to-clipboard-snackbar/copy-to-clipboard-snackbar";
import { ProjectResource } from "models/project";
import { ProcessResource } from "models/process";
+import { ServiceRepository } from "services/services";
+import { loadUsersPanel } from "store/users/users-actions";
+import { InlinePulser } from "components/loading/inline-pulser";
+import { ProcessTypeFilter } from "store/resource-type-filters/resource-type-filters";
+
+export const toggleIsAdmin = (uuid: string) =>
+ async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+ const { resources } = getState();
+ const data = getResource<UserResource>(uuid)(resources);
+ const isAdmin = data!.isAdmin;
+ const newActivity = await services.userService.update(uuid, { isAdmin: !isAdmin });
+ dispatch<any>(loadUsersPanel());
+ return newActivity;
+ };
const renderName = (dispatch: Dispatch, item: GroupContentsResource) => {
const navFunc = "groupClass" in item && item.groupClass === GroupClass.ROLE ? navigateToGroupDetails : navigateTo;
<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}
);
};
-const FrozenProject = (props: { item: ProjectResource }) => {
+export const FrozenProject = (props: { item: ProjectResource }) => {
const [fullUsername, setFullusername] = React.useState<any>(null);
const getFullName = React.useCallback(() => {
if (props.item.frozenByUuid) {
export const TokenCreatedByIpAddress = withResourceData("createdByIpAddress", renderCommonDate);
-export const TokenDefaultOwnerUuid = withResourceData("defaultOwnerUuid", renderCommonData);
-
export const TokenExpiresAt = withResourceData("expiresAt", renderCommonDate);
export const TokenLastUsedAt = withResourceData("lastUsedAt", renderCommonDate);
}
};
-const renderResourceLink = (dispatch: Dispatch, item: Resource) => {
+const renderResourceLink = (dispatch: Dispatch, item: Resource ) => {
var displayName = getResourceDisplayName(item);
return (
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));
}}
>
<Typography
style={{ color: theme.palette.primary.main }}
inline
- noWrap
>
{uuid}
</Typography>
<Typography
style={{ color: theme.palette.primary.main }}
inline
- noWrap
>
{userFullname} ({uuid})
</Typography>
);
});
+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);
export const ResourceType = connect((state: RootState, props: { uuid: string }) => {
const resource = getResource<GroupContentsResource>(props.uuid)(state.resources);
- return { type: resource ? resource.kind : "", subtype: resource && resource.kind === ResourceKind.GROUP ? resource.groupClass : "" };
+ return {
+ type: resource ? resource.kind : "",
+ subtype: resource
+ ? resource.kind === ResourceKind.GROUP
+ ? resource.groupClass
+ : resource.kind === ResourceKind.PROCESS
+ ? resource.requestingContainerUuid
+ ? ProcessTypeFilter.CHILD_PROCESS
+ : ProcessTypeFilter.MAIN_PROCESS
+ : ""
+ : ""
+ };
})((props: { type: string; subtype: string }) => renderType(props.type, props.subtype));
export const ResourceStatus = 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} />;
+ }
+}));