diff --git a/h/static/scripts/group-forms/components/CreateEditGroupForm.tsx b/h/static/scripts/group-forms/components/CreateEditGroupForm.tsx
index 4b314475283..346e51918ba 100644
--- a/h/static/scripts/group-forms/components/CreateEditGroupForm.tsx
+++ b/h/static/scripts/group-forms/components/CreateEditGroupForm.tsx
@@ -6,6 +6,7 @@ import {
Input,
RadioGroup,
Textarea,
+ ModalDialog,
useWarnOnPageUnload,
} from '@hypothesis/frontend-shared';
import { readConfig } from '../config';
@@ -17,6 +18,7 @@ import type {
} from '../utils/api';
import { setLocation } from '../utils/set-location';
import SaveStateIcon from './SaveStateIcon';
+import WarningDialog from './WarningDialog';
function Star() {
return *;
@@ -133,6 +135,68 @@ function TextField({
);
}
+/**
+ * Dialog that warns users about existing annotations in a group being exposed
+ * or hidden from public view when the group type is changed.
+ */
+function GroupTypeChangeWarning({
+ name,
+ newType,
+ annotationCount: count,
+ onConfirm,
+ onCancel,
+}: {
+ /** Name of the group. */
+ name: string;
+
+ /**
+ * The new type for the group. If this is private, the old type is inferred
+ * to be public and vice-versa.
+ */
+ newType: GroupType;
+
+ /** Number of annotations in the group. */
+ annotationCount: number;
+
+ onConfirm: () => void;
+ onCancel: () => void;
+}) {
+ const newTypeIsPrivate = newType === 'private';
+
+ let title;
+ let confirmAction;
+ let message;
+ if (newTypeIsPrivate) {
+ title = `Make ${count} annotations private?`;
+ confirmAction = 'Make annotations private';
+ message = `Are you sure you want to make "${name}" a private group? ${count} annotations that are publicly visible will become visible only to members of "${name}".`;
+ } else {
+ let groupDescription = 'a public group';
+ switch (newType) {
+ case 'open':
+ groupDescription = 'an open group';
+ break;
+ case 'restricted':
+ groupDescription = 'a restricted group';
+ break;
+ }
+
+ title = `Make ${count} annotations public?`;
+ confirmAction = 'Make annotations public';
+ message = `Are you sure you want to make "${name}" ${groupDescription}? ${count} annotations that are visible only to members of "${name}" will become publicly visible.`;
+ }
+
+ return (
+
+ );
+}
+
export default function CreateEditGroupForm() {
const config = useMemo(() => readConfig(), []);
const group = config.context.group;
@@ -143,6 +207,12 @@ export default function CreateEditGroupForm() {
group?.type ?? 'private',
);
+ // Set when the user selects a new group type if confirmation is required.
+ // Cleared after confirmation.
+ const [pendingGroupType, setPendingGroupType] = useState(
+ null,
+ );
+
const [errorMessage, setErrorMessage] = useState('');
const [saveState, setSaveState] = useState<
'unmodified' | 'unsaved' | 'saving' | 'saved'
@@ -249,6 +319,18 @@ export default function CreateEditGroupForm() {
const groupTypeLabel = useId();
+ const changeGroupType = (newType: GroupType) => {
+ const count = group?.num_annotations ?? 0;
+ const oldTypeIsPrivate = groupType === 'private';
+ const newTypeIsPrivate = newType === 'private';
+
+ if (count === 0 || oldTypeIsPrivate === newTypeIsPrivate) {
+ setGroupType(newType);
+ } else {
+ setPendingGroupType(newType);
+ }
+ };
+
return (