Path: blob/master/src/packages/frontend/collaborators/current-collabs.tsx
1496 views
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45import { Button, Card, Popconfirm } from "antd";6import React from "react";7import { FormattedMessage, useIntl } from "react-intl";8import { CSS, redux, useRedux } from "@cocalc/frontend/app-framework";9import {10Gap,11Icon,12Paragraph,13SettingBox,14Title,15} from "@cocalc/frontend/components";16import { useStudentProjectFunctionality } from "@cocalc/frontend/course";17import { labels } from "@cocalc/frontend/i18n";18import { CancelText } from "@cocalc/frontend/i18n/components";19import { Project } from "@cocalc/frontend/project/settings/types";20import { COLORS } from "@cocalc/util/theme";21import { FIX_BORDER } from "../project/page/common";22import { User } from "../users";2324interface Props {25project: Project;26user_map?: any;27mode?: "project" | "flyout";28}2930export const CurrentCollaboratorsPanel: React.FC<Props> = (props: Props) => {31const { project, user_map, mode = "project" } = props;32const isFlyout = mode === "flyout";33const intl = useIntl();34const get_account_id = useRedux("account", "get_account_id");35const sort_by_activity = useRedux("projects", "sort_by_activity");36const student = useStudentProjectFunctionality(project.get("project_id"));3738function remove_collaborator(account_id: string) {39const project_id = project.get("project_id");40redux.getActions("projects").remove_collaborator(project_id, account_id);41if (account_id === get_account_id()) {42(redux.getActions("page") as any).close_project_tab(project_id);43// TODO: better types44}45}4647function user_remove_confirm_text(account_id: string) {48const style: CSS = { maxWidth: "300px" };49if (account_id === get_account_id()) {50return (51<div style={style}>52<FormattedMessage53id="collaborators.current-collabs.remove_self"54defaultMessage={`Are you sure you want to remove <b>yourself</b> from this project?55You will no longer have access to this project and cannot add yourself back.`}56/>57</div>58);59} else {60return (61<div style={style}>62<FormattedMessage63id="collaborators.current-collabs.remove_other"64defaultMessage={`Are you sure you want to remove {user} from this project?65They will no longer have access to this project.`}66values={{67user: <User account_id={account_id} user_map={user_map} />,68}}69/>70</div>71);72}73}7475function user_remove_button(account_id: string, group?: string) {76if (student.disableCollaborators) return;77const text = user_remove_confirm_text(account_id);78const isOwner = group === "owner";79return (80<Popconfirm81title={text}82onConfirm={() => remove_collaborator(account_id)}83okText={"Yes, remove collaborator"}84cancelText={<CancelText />}85disabled={isOwner}86>87<Button88disabled={isOwner}89type={isFlyout ? "link" : "default"}90style={{91marginBottom: "0",92float: "right",93...(isFlyout ? { color: COLORS.ANTD_RED_WARN } : {}),94}}95>96<Icon name="user-times" /> {intl.formatMessage(labels.remove)} ...97</Button>98</Popconfirm>99);100}101102function render_user(user: any, is_last?: boolean) {103const style = {104width: "100%",105flex: "1 1 auto",106...(!is_last ? { marginBottom: "20px" } : {}),107};108return (109<div key={user.account_id} style={style}>110<User111account_id={user.account_id}112user_map={user_map}113last_active={user.last_active}114show_avatar={true}115/>116<span>117<Gap />({user.group})118</span>119{user_remove_button(user.account_id, user.group)}120</div>121);122}123124function render_users() {125const u = project.get("users");126if (u === undefined) {127return;128}129const users = u130.map((v, k) => ({ account_id: k, group: v.get("group") }))131.toList()132.toJS();133return sort_by_activity(users, project.get("project_id")).map((u, i) =>134render_user(u, i === users.length - 1),135);136}137138function render_collaborators_list() {139const style: CSS = {140maxHeight: "20em",141overflowY: "auto",142overflowX: "hidden",143marginBottom: "0",144display: "flex",145flexDirection: "column",146};147if (isFlyout) {148return (149<div style={{ ...style, borderBottom: FIX_BORDER }}>150{render_users()}151</div>152);153} else {154return (155<Card style={{ ...style, backgroundColor: COLORS.GRAY_LLL }}>156{render_users()}157</Card>158);159}160}161162const introText = intl.formatMessage({163id: "collaborators.current-collabs.intro",164defaultMessage:165"Everybody listed below can collaboratively work with you on any Jupyter Notebook, Linux Terminal or file in this project, and add or remove other collaborators.",166});167168switch (mode) {169case "project":170return (171<SettingBox title="Current Collaborators" icon="user">172{introText}173<hr />174{render_collaborators_list()}175</SettingBox>176);177case "flyout":178return (179<div style={{ paddingLeft: "5px" }}>180<Title level={3}>181<Icon name="user" />{" "}182<FormattedMessage183id="collaborators.current-collabs.title"184defaultMessage={"Current Collaborators"}185description={186"Title of a table listing users collaborating on that project"187}188/>189</Title>190<Paragraph191type="secondary"192ellipsis={{ rows: 1, expandable: true, symbol: "more" }}193>194{introText}195</Paragraph>196{render_collaborators_list()}197</div>198);199}200};201202203