mirror of
https://github.com/urbit/shrub.git
synced 2024-12-25 21:12:56 +03:00
hark-fe: toggle mute in group settings
This commit is contained in:
parent
0510b723d7
commit
ab781cfbc3
@ -1,173 +0,0 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { AsyncButton } from "~/views/components/AsyncButton";
|
||||
import * as Yup from "yup";
|
||||
import {
|
||||
Box,
|
||||
ManagedTextInputField as Input,
|
||||
ManagedCheckboxField as Checkbox,
|
||||
Col,
|
||||
Label,
|
||||
Button,
|
||||
} from "@tlon/indigo-react";
|
||||
import { Formik, Form, useFormikContext, FormikHelpers } from "formik";
|
||||
import { FormError } from "~/views/components/FormError";
|
||||
import { Group, GroupPolicy } from "~/types/group-update";
|
||||
import { Enc } from "~/types/noun";
|
||||
import { Association } from "~/types/metadata-update";
|
||||
import GlobalApi from "~/logic/api/global";
|
||||
import { resourceFromPath, roleForShip } from "~/logic/lib/group";
|
||||
import { StatelessAsyncButton } from "~/views/components/StatelessAsyncButton";
|
||||
import { ColorInput } from "~/views/components/ColorInput";
|
||||
import { useHistory } from "react-router-dom";
|
||||
|
||||
import { uxToHex } from '~/logic/lib/util';
|
||||
|
||||
|
||||
interface FormSchema {
|
||||
title: string;
|
||||
description: string;
|
||||
color: string;
|
||||
isPrivate: boolean;
|
||||
}
|
||||
|
||||
const formSchema = Yup.object({
|
||||
title: Yup.string().required("Group must have a name"),
|
||||
description: Yup.string(),
|
||||
color: Yup.string(),
|
||||
isPrivate: Yup.boolean(),
|
||||
});
|
||||
|
||||
interface GroupSettingsProps {
|
||||
group: Group;
|
||||
association: Association;
|
||||
api: GlobalApi;
|
||||
}
|
||||
export function GroupSettings(props: GroupSettingsProps) {
|
||||
const { group, association } = props;
|
||||
const { metadata } = association;
|
||||
const history = useHistory();
|
||||
const currentPrivate = "invite" in props.group.policy;
|
||||
const initialValues: FormSchema = {
|
||||
title: metadata?.title,
|
||||
description: metadata?.description,
|
||||
color: metadata?.color,
|
||||
isPrivate: currentPrivate,
|
||||
};
|
||||
|
||||
const onSubmit = async (
|
||||
values: FormSchema,
|
||||
actions: FormikHelpers<FormSchema>
|
||||
) => {
|
||||
try {
|
||||
const { title, description, color, isPrivate } = values;
|
||||
const uxColor = uxToHex(color);
|
||||
await props.api.metadata.update(props.association, {
|
||||
title,
|
||||
description,
|
||||
color: uxColor
|
||||
});
|
||||
if (isPrivate !== currentPrivate) {
|
||||
const resource = resourceFromPath(props.association["group-path"]);
|
||||
const newPolicy: Enc<GroupPolicy> = isPrivate
|
||||
? { invite: { pending: [] } }
|
||||
: { open: { banRanks: [], banned: [] } };
|
||||
const diff = { replace: newPolicy };
|
||||
await props.api.groups.changePolicy(resource, diff);
|
||||
}
|
||||
|
||||
actions.setStatus({ success: null });
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
actions.setStatus({ error: e.message });
|
||||
}
|
||||
};
|
||||
|
||||
const onDelete = async () => {
|
||||
await props.api.contacts.delete(association["group-path"]);
|
||||
history.push("/");
|
||||
};
|
||||
|
||||
const disabled =
|
||||
resourceFromPath(association["group-path"]).ship.slice(1) !== window.ship &&
|
||||
roleForShip(group, window.ship) !== "admin";
|
||||
|
||||
return (
|
||||
<Box height="100%" overflowY="auto">
|
||||
<Formik
|
||||
validationSchema={formSchema}
|
||||
initialValues={initialValues}
|
||||
onSubmit={onSubmit}
|
||||
>
|
||||
<Form style={{ display: "contents" }}>
|
||||
<Box
|
||||
maxWidth="300px"
|
||||
gridTemplateColumns="1fr"
|
||||
gridAutoRows="auto"
|
||||
display="grid"
|
||||
gridRowGap={4}
|
||||
my={3}
|
||||
mx={4}
|
||||
>
|
||||
{!disabled ? (
|
||||
<Col>
|
||||
<Label>Delete Group</Label>
|
||||
<Label gray mt="2">
|
||||
Permanently delete this group. (All current members will no
|
||||
longer see this group.)
|
||||
</Label>
|
||||
<StatelessAsyncButton onClick={onDelete} mt={2} destructive>
|
||||
Delete this group
|
||||
</StatelessAsyncButton>
|
||||
</Col>
|
||||
) : (
|
||||
<Col>
|
||||
<Label>Leave Group</Label>
|
||||
<Label gray mt="2">
|
||||
Leave this group. You can rejoin if it is an open group, or if
|
||||
you are reinvited
|
||||
</Label>
|
||||
<StatelessAsyncButton onClick={onDelete} mt={2} destructive>
|
||||
Leave this group
|
||||
</StatelessAsyncButton>
|
||||
</Col>
|
||||
)}
|
||||
<Box borderBottom={1} borderBottomColor="washedGray" />
|
||||
<Input
|
||||
id="title"
|
||||
label="Group Name"
|
||||
caption="The name for your group to be called by"
|
||||
disabled={disabled}
|
||||
/>
|
||||
<Input
|
||||
id="description"
|
||||
label="Group Description"
|
||||
caption="The description of your group"
|
||||
disabled={disabled}
|
||||
/>
|
||||
<ColorInput
|
||||
id="color"
|
||||
label="Group color"
|
||||
caption="A color to represent your group"
|
||||
disabled={disabled}
|
||||
/>
|
||||
<Checkbox
|
||||
id="isPrivate"
|
||||
label="Private group"
|
||||
caption="If enabled, users must be invited to join the group"
|
||||
disabled={disabled}
|
||||
/>
|
||||
<AsyncButton
|
||||
disabled={disabled}
|
||||
primary
|
||||
loadingText="Updating.."
|
||||
border
|
||||
>
|
||||
Save
|
||||
</AsyncButton>
|
||||
<FormError message="Failed to update settings" />
|
||||
</Box>
|
||||
</Form>
|
||||
</Formik>
|
||||
</Box>
|
||||
);
|
||||
}
|
@ -0,0 +1,134 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { AsyncButton } from "~/views/components/AsyncButton";
|
||||
import * as Yup from "yup";
|
||||
import {
|
||||
Box,
|
||||
ManagedTextInputField as Input,
|
||||
ManagedToggleSwitchField as Checkbox,
|
||||
Col,
|
||||
Label,
|
||||
Button,
|
||||
} from "@tlon/indigo-react";
|
||||
import { Formik, Form, useFormikContext, FormikHelpers } from "formik";
|
||||
import { FormError } from "~/views/components/FormError";
|
||||
import { Group, GroupPolicy } from "~/types/group-update";
|
||||
import { Enc } from "~/types/noun";
|
||||
import { Association } from "~/types/metadata-update";
|
||||
import GlobalApi from "~/logic/api/global";
|
||||
import { resourceFromPath, roleForShip } from "~/logic/lib/group";
|
||||
import { StatelessAsyncButton } from "~/views/components/StatelessAsyncButton";
|
||||
import { ColorInput } from "~/views/components/ColorInput";
|
||||
import { useHistory } from "react-router-dom";
|
||||
|
||||
import { uxToHex } from "~/logic/lib/util";
|
||||
|
||||
interface FormSchema {
|
||||
title: string;
|
||||
description: string;
|
||||
color: string;
|
||||
isPrivate: boolean;
|
||||
}
|
||||
|
||||
const formSchema = Yup.object({
|
||||
title: Yup.string().required("Group must have a name"),
|
||||
description: Yup.string(),
|
||||
color: Yup.string(),
|
||||
isPrivate: Yup.boolean(),
|
||||
});
|
||||
|
||||
interface GroupAdminSettingsProps {
|
||||
group: Group;
|
||||
association: Association;
|
||||
api: GlobalApi;
|
||||
}
|
||||
|
||||
export function GroupAdminSettings(props: GroupAdminSettingsProps) {
|
||||
const { group, association } = props;
|
||||
const { metadata } = association;
|
||||
const history = useHistory();
|
||||
const currentPrivate = "invite" in props.group.policy;
|
||||
const initialValues: FormSchema = {
|
||||
title: metadata?.title,
|
||||
description: metadata?.description,
|
||||
color: metadata?.color,
|
||||
isPrivate: currentPrivate,
|
||||
};
|
||||
|
||||
const onSubmit = async (
|
||||
values: FormSchema,
|
||||
actions: FormikHelpers<FormSchema>
|
||||
) => {
|
||||
try {
|
||||
const { title, description, color, isPrivate } = values;
|
||||
const uxColor = uxToHex(color);
|
||||
await props.api.metadata.update(props.association, {
|
||||
title,
|
||||
description,
|
||||
color: uxColor,
|
||||
});
|
||||
if (isPrivate !== currentPrivate) {
|
||||
const resource = resourceFromPath(props.association["group-path"]);
|
||||
const newPolicy: Enc<GroupPolicy> = isPrivate
|
||||
? { invite: { pending: [] } }
|
||||
: { open: { banRanks: [], banned: [] } };
|
||||
const diff = { replace: newPolicy };
|
||||
await props.api.groups.changePolicy(resource, diff);
|
||||
}
|
||||
|
||||
actions.setStatus({ success: null });
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
actions.setStatus({ error: e.message });
|
||||
}
|
||||
};
|
||||
|
||||
const disabled =
|
||||
resourceFromPath(association["group-path"]).ship.slice(1) !== window.ship &&
|
||||
roleForShip(group, window.ship) !== "admin";
|
||||
|
||||
return (
|
||||
<Formik
|
||||
validationSchema={formSchema}
|
||||
initialValues={initialValues}
|
||||
onSubmit={onSubmit}
|
||||
>
|
||||
<Form>
|
||||
<Col gapY={4}>
|
||||
<Input
|
||||
id="title"
|
||||
label="Group Name"
|
||||
caption="The name for your group to be called by"
|
||||
disabled={disabled}
|
||||
/>
|
||||
<Input
|
||||
id="description"
|
||||
label="Group Description"
|
||||
caption="The description of your group"
|
||||
disabled={disabled}
|
||||
/>
|
||||
<ColorInput
|
||||
id="color"
|
||||
label="Group color"
|
||||
caption="A color to represent your group"
|
||||
disabled={disabled}
|
||||
/>
|
||||
<Checkbox
|
||||
id="isPrivate"
|
||||
label="Private group"
|
||||
caption="If enabled, users must be invited to join the group"
|
||||
disabled={disabled}
|
||||
/>
|
||||
<AsyncButton
|
||||
disabled={disabled}
|
||||
primary
|
||||
loadingText="Updating.."
|
||||
border
|
||||
>
|
||||
Save
|
||||
</AsyncButton>
|
||||
<FormError message="Failed to update settings" />
|
||||
</Col>
|
||||
</Form>
|
||||
</Formik>
|
||||
);
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { AsyncButton } from "~/views/components/AsyncButton";
|
||||
import * as Yup from "yup";
|
||||
import {
|
||||
Box,
|
||||
ManagedTextInputField as Input,
|
||||
ManagedToggleSwitchField as Checkbox,
|
||||
Col,
|
||||
Label,
|
||||
Button,
|
||||
} from "@tlon/indigo-react";
|
||||
import { Formik, Form, useFormikContext, FormikHelpers } from "formik";
|
||||
import { FormError } from "~/views/components/FormError";
|
||||
import { Group, GroupPolicy } from "~/types/group-update";
|
||||
import { Enc } from "~/types/noun";
|
||||
import { Association } from "~/types/metadata-update";
|
||||
import GlobalApi from "~/logic/api/global";
|
||||
import { resourceFromPath, roleForShip } from "~/logic/lib/group";
|
||||
import { StatelessAsyncButton } from "~/views/components/StatelessAsyncButton";
|
||||
import { ColorInput } from "~/views/components/ColorInput";
|
||||
import { useHistory } from "react-router-dom";
|
||||
|
||||
import { uxToHex } from "~/logic/lib/util";
|
||||
import { GroupAdminSettings } from "./Admin";
|
||||
import { GroupPersonalSettings } from "./Personal";
|
||||
import {GroupNotificationsConfig} from "~/types";
|
||||
|
||||
interface GroupSettingsProps {
|
||||
group: Group;
|
||||
association: Association;
|
||||
api: GlobalApi;
|
||||
notificationsGroupConfig: GroupNotificationsConfig;
|
||||
}
|
||||
export function GroupSettings(props: GroupSettingsProps) {
|
||||
return (
|
||||
<Box height="100%" overflowY="auto">
|
||||
<Col maxWidth="384px" p="4" gapY="4">
|
||||
<GroupPersonalSettings {...props} />
|
||||
<Box borderBottom="1" borderBottomColor="washedGray" />
|
||||
<GroupAdminSettings {...props} />
|
||||
</Col>
|
||||
</Box>
|
||||
);
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
import React, { useCallback } from "react";
|
||||
|
||||
import { AsyncButton } from "~/views/components/AsyncButton";
|
||||
import * as Yup from "yup";
|
||||
import {
|
||||
Box,
|
||||
ManagedTextInputField as Input,
|
||||
ManagedToggleSwitchField as Toggle,
|
||||
Col,
|
||||
Label,
|
||||
Button,
|
||||
} from "@tlon/indigo-react";
|
||||
import { Formik, Form, useFormikContext, FormikHelpers } from "formik";
|
||||
import { FormError } from "~/views/components/FormError";
|
||||
import { Group, GroupPolicy } from "~/types/group-update";
|
||||
import { Enc } from "~/types/noun";
|
||||
import { Association } from "~/types/metadata-update";
|
||||
import GlobalApi from "~/logic/api/global";
|
||||
import { resourceFromPath, roleForShip } from "~/logic/lib/group";
|
||||
import { StatelessAsyncButton } from "~/views/components/StatelessAsyncButton";
|
||||
import { ColorInput } from "~/views/components/ColorInput";
|
||||
import { useHistory } from "react-router-dom";
|
||||
|
||||
import { uxToHex } from "~/logic/lib/util";
|
||||
import { FormikOnBlur } from "~/views/components/FormikOnBlur";
|
||||
import {GroupNotificationsConfig} from "~/types";
|
||||
|
||||
function DeleteGroup(props: {
|
||||
owner: boolean;
|
||||
api: GlobalApi;
|
||||
association: Association;
|
||||
}) {
|
||||
const history = useHistory();
|
||||
const onDelete = async () => {
|
||||
await props.api.contacts.delete(props.association["group-path"]);
|
||||
history.push("/");
|
||||
};
|
||||
|
||||
const action = props.owner ? "Delete" : "Leave";
|
||||
const description = props.owner
|
||||
? "Permanently delete this group. (All current members will no longer see this group.)"
|
||||
: "Leave this group. You can rejoin if it is an open group, or if you are reinvited";
|
||||
|
||||
return (
|
||||
<Col>
|
||||
<Label>{action} Group</Label>
|
||||
<Label gray mt="2">
|
||||
{description}
|
||||
</Label>
|
||||
<StatelessAsyncButton onClick={onDelete} mt={2} destructive>
|
||||
{action} this group
|
||||
</StatelessAsyncButton>
|
||||
</Col>
|
||||
);
|
||||
}
|
||||
|
||||
interface FormSchema {
|
||||
watching: boolean;
|
||||
}
|
||||
|
||||
export function GroupPersonalSettings(props: {
|
||||
api: GlobalApi;
|
||||
association: Association;
|
||||
notificationsGroupConfig: GroupNotificationsConfig;
|
||||
}) {
|
||||
|
||||
const groupPath = props.association['group-path'];
|
||||
|
||||
const watching = props.notificationsGroupConfig.findIndex(g => g === groupPath) !== -1;
|
||||
|
||||
const initialValues: FormSchema = {
|
||||
watching
|
||||
};
|
||||
const onSubmit = async (values: FormSchema) => {
|
||||
if(values.watching === watching) {
|
||||
return;
|
||||
}
|
||||
const func = values.watching ? 'listenGroup' : 'ignoreGroup';
|
||||
await props.api.hark[func](groupPath);
|
||||
};
|
||||
|
||||
return (
|
||||
<Col gapY="4">
|
||||
<FormikOnBlur initialValues={initialValues} onSubmit={onSubmit}>
|
||||
<Toggle
|
||||
id="watching"
|
||||
label="Notify me on group activity"
|
||||
caption="Send me notifications when this group changes"
|
||||
/>
|
||||
</FormikOnBlur>
|
||||
<DeleteGroup association={props.association} owner api={props.api} />
|
||||
</Col>
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue
Block a user