Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/frontend/collaborators/collaborators-setting.tsx
5819 views
1
/*
2
* This file is part of CoCalc: Copyright © 2025 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
import { Alert } from "antd";
7
import { useState } from "react";
8
import { FormattedMessage, useIntl } from "react-intl";
9
10
import { Switch } from "@cocalc/frontend/antd-bootstrap";
11
import { SettingBox, Tip } from "@cocalc/frontend/components";
12
import { useTypedRedux } from "@cocalc/frontend/app-framework";
13
import { webapp_client } from "@cocalc/frontend/webapp-client";
14
import type { Project } from "@cocalc/frontend/project/settings/types";
15
16
interface Props {
17
project: Project;
18
withSettingBox?: boolean;
19
}
20
21
export function CollaboratorsSetting({
22
project,
23
withSettingBox = true,
24
}: Readonly<Props>) {
25
const intl = useIntl();
26
const [error, setError] = useState<string>("");
27
const [saving, setSaving] = useState<boolean>(false);
28
29
const project_id = project.get("project_id");
30
const siteEnforced =
31
useTypedRedux("customize", "strict_collaborator_management") ?? false;
32
const manage_users_owner_only =
33
siteEnforced || project.get("manage_users_owner_only") || false;
34
35
// Check if current user is an owner
36
const account_id = webapp_client.account_id;
37
const userGroup = project.getIn(["users", account_id, "group"]);
38
const isOwner = userGroup === "owner";
39
40
async function handleChange(checked: boolean): Promise<void> {
41
if (siteEnforced) return;
42
if (!isOwner) return;
43
44
setError("");
45
setSaving(true);
46
47
try {
48
await webapp_client.async_query({
49
query: {
50
projects: {
51
project_id,
52
manage_users_owner_only: checked,
53
},
54
},
55
});
56
} catch (err) {
57
setError(`Error updating setting: ${err}`);
58
} finally {
59
setSaving(false);
60
}
61
}
62
63
const switchComponent = (
64
<Switch
65
checked={manage_users_owner_only}
66
onChange={(e) => handleChange(e.target.checked)}
67
disabled={siteEnforced || !isOwner || saving}
68
>
69
<FormattedMessage
70
id="project.settings.manage_users_owner_only"
71
defaultMessage="Only allow owners to manage collaborators."
72
/>
73
</Switch>
74
);
75
76
const content = (
77
<>
78
{!isOwner ? (
79
<Tip
80
title={intl.formatMessage({
81
id: "project.settings.manage_users_owner_only.note",
82
defaultMessage:
83
"This setting can only be changed by project owners.",
84
})}
85
>
86
{switchComponent}
87
</Tip>
88
) : (
89
switchComponent
90
)}
91
92
{siteEnforced && (
93
<Alert
94
type="info"
95
showIcon
96
style={{ marginTop: 10 }}
97
message={
98
<FormattedMessage
99
id="project.settings.manage_users_owner_only.site_enforced"
100
defaultMessage="This setting is enforced by the site administrator for all projects."
101
/>
102
}
103
/>
104
)}
105
106
{error && (
107
<Alert
108
type="error"
109
style={{ marginTop: 10 }}
110
closable
111
onClose={() => setError("")}
112
message={error}
113
/>
114
)}
115
</>
116
);
117
118
if (!withSettingBox) {
119
return content;
120
}
121
122
return (
123
<SettingBox
124
title={intl.formatMessage({
125
id: "project.settings.collaborators.title",
126
defaultMessage: "Collaborator Management",
127
})}
128
icon="users"
129
>
130
{content}
131
</SettingBox>
132
);
133
}
134
135