Files
pingvin-share/frontend/src/components/share/modals/showCreateReverseShareModal.tsx
Ivan Li fe735f9704 feat: add more options to reverse shares (#495)
* feat(reverse-share): optional simplified interface for reverse sharing. issue #155.

* chore: Remove useless form validation.

* feat: Share Ready modal adds a prompt that an email has been sent to the reverse share creator.

* fix: Simplified reverse shared interface elements lack spacing when not logged in.

* fix: Share Ready modal prompt contrast is too low in dark mode.

* feat: add public access options to reverse share.

* feat: remember reverse share simplified and publicAccess options in cookies.

* style: npm run format.

* chore(i18n): Improve translation.

Co-authored-by: Elias Schneider <login@eliasschneider.com>

Update frontend/src/i18n/translations/en-US.ts

Co-authored-by: Elias Schneider <login@eliasschneider.com>

Update frontend/src/i18n/translations/en-US.ts

Co-authored-by: Elias Schneider <login@eliasschneider.com>

chore(i18n): Improve translation.

* chore: Improved variable naming.

* chore(i18n): Improve translation. x2.

* fix(backend/shares): Misjudged the permission of the share of the reverse share.
2024-07-30 08:26:56 +02:00

254 lines
8.1 KiB
TypeScript

import {
Button,
Col,
Grid,
Group,
NumberInput,
Select,
Stack,
Switch,
Text,
} from "@mantine/core";
import { useForm } from "@mantine/form";
import { useModals } from "@mantine/modals";
import { ModalsContextProps } from "@mantine/modals/lib/context";
import moment from "moment";
import { FormattedMessage } from "react-intl";
import useTranslate, {
translateOutsideContext,
} from "../../../hooks/useTranslate.hook";
import shareService from "../../../services/share.service";
import { getExpirationPreview } from "../../../utils/date.util";
import toast from "../../../utils/toast.util";
import FileSizeInput from "../FileSizeInput";
import showCompletedReverseShareModal from "./showCompletedReverseShareModal";
import { getCookie, setCookie } from "cookies-next";
const showCreateReverseShareModal = (
modals: ModalsContextProps,
showSendEmailNotificationOption: boolean,
maxExpirationInHours: number,
getReverseShares: () => void,
) => {
const t = translateOutsideContext();
return modals.openModal({
title: t("account.reverseShares.modal.title"),
children: (
<Body
showSendEmailNotificationOption={showSendEmailNotificationOption}
getReverseShares={getReverseShares}
maxExpirationInHours={maxExpirationInHours}
/>
),
});
};
const Body = ({
getReverseShares,
showSendEmailNotificationOption,
maxExpirationInHours,
}: {
getReverseShares: () => void;
showSendEmailNotificationOption: boolean;
maxExpirationInHours: number;
}) => {
const modals = useModals();
const t = useTranslate();
const form = useForm({
initialValues: {
maxShareSize: 104857600,
maxUseCount: 1,
sendEmailNotification: false,
expiration_num: 1,
expiration_unit: "-days",
simplified: !!(getCookie("reverse-share.simplified") ?? false),
publicAccess: !!(getCookie("reverse-share.public-access") ?? true),
},
});
const onSubmit = form.onSubmit(async (values) => {
// remember simplified and publicAccess in cookies
setCookie("reverse-share.simplified", values.simplified);
setCookie("reverse-share.public-access", values.publicAccess);
const expirationDate = moment().add(
form.values.expiration_num,
form.values.expiration_unit.replace(
"-",
"",
) as moment.unitOfTime.DurationConstructor,
);
if (
maxExpirationInHours != 0 &&
expirationDate.isAfter(moment().add(maxExpirationInHours, "hours"))
) {
form.setFieldError(
"expiration_num",
t("upload.modal.expires.error.too-long", {
max: moment.duration(maxExpirationInHours, "hours").humanize(),
}),
);
return;
}
shareService
.createReverseShare(
values.expiration_num + values.expiration_unit,
values.maxShareSize,
values.maxUseCount,
values.sendEmailNotification,
values.simplified,
values.publicAccess,
)
.then(({ link }) => {
modals.closeAll();
showCompletedReverseShareModal(modals, link, getReverseShares);
})
.catch(toast.axiosError);
});
return (
<Group>
<form onSubmit={onSubmit}>
<Stack align="stretch">
<div>
<Grid align={form.errors.expiration_num ? "center" : "flex-end"}>
<Col xs={6}>
<NumberInput
min={1}
max={99999}
precision={0}
variant="filled"
label={t("account.reverseShares.modal.expiration.label")}
{...form.getInputProps("expiration_num")}
/>
</Col>
<Col xs={6}>
<Select
{...form.getInputProps("expiration_unit")}
data={[
// Set the label to singular if the number is 1, else plural
{
value: "-minutes",
label:
form.values.expiration_num == 1
? t("upload.modal.expires.minute-singular")
: t("upload.modal.expires.minute-plural"),
},
{
value: "-hours",
label:
form.values.expiration_num == 1
? t("upload.modal.expires.hour-singular")
: t("upload.modal.expires.hour-plural"),
},
{
value: "-days",
label:
form.values.expiration_num == 1
? t("upload.modal.expires.day-singular")
: t("upload.modal.expires.day-plural"),
},
{
value: "-weeks",
label:
form.values.expiration_num == 1
? t("upload.modal.expires.week-singular")
: t("upload.modal.expires.week-plural"),
},
{
value: "-months",
label:
form.values.expiration_num == 1
? t("upload.modal.expires.month-singular")
: t("upload.modal.expires.month-plural"),
},
{
value: "-years",
label:
form.values.expiration_num == 1
? t("upload.modal.expires.year-singular")
: t("upload.modal.expires.year-plural"),
},
]}
/>
</Col>
</Grid>
<Text
mt="sm"
italic
size="xs"
sx={(theme) => ({
color: theme.colors.gray[6],
})}
>
{getExpirationPreview(
{
expiresOn: t("account.reverseShare.expires-on"),
neverExpires: t("account.reverseShare.never-expires"),
},
form,
)}
</Text>
</div>
<FileSizeInput
label={t("account.reverseShares.modal.max-size.label")}
value={form.values.maxShareSize}
onChange={(number) => form.setFieldValue("maxShareSize", number)}
/>
<NumberInput
min={1}
max={1000}
precision={0}
variant="filled"
label={t("account.reverseShares.modal.max-use.label")}
description={t("account.reverseShares.modal.max-use.description")}
{...form.getInputProps("maxUseCount")}
/>
{showSendEmailNotificationOption && (
<Switch
mt="xs"
labelPosition="left"
label={t("account.reverseShares.modal.send-email")}
description={t(
"account.reverseShares.modal.send-email.description",
)}
{...form.getInputProps("sendEmailNotification", {
type: "checkbox",
})}
/>
)}
<Switch
mt="xs"
labelPosition="left"
label={t("account.reverseShares.modal.simplified")}
description={t(
"account.reverseShares.modal.simplified.description",
)}
{...form.getInputProps("simplified", {
type: "checkbox",
})}
/>
<Switch
mt="xs"
labelPosition="left"
label={t("account.reverseShares.modal.public-access")}
description={t(
"account.reverseShares.modal.public-access.description",
)}
{...form.getInputProps("publicAccess", {
type: "checkbox",
})}
/>
<Button mt="md" type="submit">
<FormattedMessage id="common.button.create" />
</Button>
</Stack>
</form>
</Group>
);
};
export default showCreateReverseShareModal;