From 5988d5ffcc62421f04931ac134423498d514d8a6 Mon Sep 17 00:00:00 2001 From: Steve Tautonico Date: Fri, 14 Oct 2022 18:14:46 -0400 Subject: [PATCH] Added granular control of expiration + 12/24 hour modes --- frontend/.env.example | 1 + frontend/next.config.js | 3 +- .../share/CreateUploadModalBody.tsx | 90 +++++-- .../upload/showCompletedUploadModal.tsx | 8 +- frontend/src/pages/account/shares.tsx | 228 +++++++++--------- 5 files changed, 199 insertions(+), 131 deletions(-) diff --git a/frontend/.env.example b/frontend/.env.example index dbda902..7e65299 100644 --- a/frontend/.env.example +++ b/frontend/.env.example @@ -1,3 +1,4 @@ SHOW_HOME_PAGE=true ALLOW_REGISTRATION=true MAX_FILE_SIZE=1000000000 +TWELVE_HOUR_TIME=false diff --git a/frontend/next.config.js b/frontend/next.config.js index b2b6bf5..dea14c0 100644 --- a/frontend/next.config.js +++ b/frontend/next.config.js @@ -5,7 +5,8 @@ const nextConfig = { ALLOW_REGISTRATION: process.env.ALLOW_REGISTRATION, SHOW_HOME_PAGE: process.env.SHOW_HOME_PAGE, MAX_FILE_SIZE: process.env.MAX_FILE_SIZE, - BACKEND_URL: process.env.BACKEND_URL + BACKEND_URL: process.env.BACKEND_URL, + TWELVE_HOUR_TIME: process.env.TWELVE_HOUR_TIME } } diff --git a/frontend/src/components/share/CreateUploadModalBody.tsx b/frontend/src/components/share/CreateUploadModalBody.tsx index 14b28ea..24d5b8c 100644 --- a/frontend/src/components/share/CreateUploadModalBody.tsx +++ b/frontend/src/components/share/CreateUploadModalBody.tsx @@ -2,6 +2,7 @@ import { Accordion, Button, Col, + Checkbox, Grid, NumberInput, PasswordInput, @@ -10,11 +11,32 @@ import { Text, TextInput, } from "@mantine/core"; -import { useForm, yupResolver } from "@mantine/form"; -import { useModals } from "@mantine/modals"; +import {useForm, yupResolver} from "@mantine/form"; +import {useModals} from "@mantine/modals"; import * as yup from "yup"; import shareService from "../../services/share.service"; -import { ShareSecurity } from "../../types/share.type"; +import {ShareSecurity} from "../../types/share.type"; +import moment from "moment"; +import getConfig from "next/config"; + +const {publicRuntimeConfig} = getConfig(); + +const PreviewExpiration = ({form}: { form: any }) => { + const value = form.values.never_expires ? "never" : form.values.expiration_num + form.values.expiration_unit; + if (value === "never") return "This share will never expire."; + + const expirationDate = moment() + .add( + value.split("-")[0], + value.split("-")[1] as moment.unitOfTime.DurationConstructor + ) + .toDate(); + + if (publicRuntimeConfig.TWELVE_HOUR_TIME === "true") + return `This share will expire on ${moment(expirationDate).format("MMMM Do YYYY, h:mm a")}`; + else + return `This share will expire on ${moment(expirationDate).format("MMMM DD YYYY, HH:mm")}`; +} const CreateUploadModalBody = ({ uploadCallback, @@ -44,7 +66,9 @@ const CreateUploadModalBody = ({ password: undefined, maxViews: undefined, - expiration: "1-day", + expiration_num: 1, + expiration_unit: "-days", + never_expires: false }, validate: yupResolver(validationSchema), }); @@ -55,7 +79,8 @@ const CreateUploadModalBody = ({ if (!(await shareService.isShareIdAvailable(values.link))) { form.setFieldError("link", "This link is already in use"); } else { - uploadCallback(values.link, values.expiration, { + const expiration = form.values.never_expires ? "never" : form.values.expiration_num + form.values.expiration_unit; + uploadCallback(values.link, expiration, { password: values.password, maxViews: values.maxViews, }); @@ -90,7 +115,7 @@ const CreateUploadModalBody = ({ - ({ color: theme.colors.gray[6], @@ -99,18 +124,47 @@ const CreateUploadModalBody = ({ {window.location.origin}/share/ {form.values.link == "" ? "myAwesomeShare" : form.values.link} - + + + + + {/* Preview expiration date text */} + ({ + color: theme.colors.gray[6], + })} + > + {PreviewExpiration({form})} + + Security options diff --git a/frontend/src/components/upload/showCompletedUploadModal.tsx b/frontend/src/components/upload/showCompletedUploadModal.tsx index 3d8374b..59c194d 100644 --- a/frontend/src/components/upload/showCompletedUploadModal.tsx +++ b/frontend/src/components/upload/showCompletedUploadModal.tsx @@ -14,6 +14,9 @@ import { useRouter } from "next/router"; import { Copy } from "tabler-icons-react"; import { Share } from "../../types/share.type"; import toast from "../../utils/toast.util"; +import getConfig from "next/config"; + +const {publicRuntimeConfig} = getConfig(); const showCompletedUploadModal = ( modals: ModalsContextProps, @@ -62,7 +65,10 @@ const Body = ({share}: { share: Share }) => { {/* If our share.expiration is timestamp 0, show a different message */} {moment(share.expiration).unix() === 0 ? "This share will never expire." - : `This share will expire on ${moment(share.expiration).format("LLL")}`} + : `This share will expire on ${ + (publicRuntimeConfig.TWELVE_HOUR_TIME === "true") + ? moment(share.expiration).format("MMMM Do YYYY, h:mm a") + : moment(share.expiration).format("MMMM DD YYYY, HH:mm")}`} - - - ) : ( - - - - - - - - - - - {shares.map((share) => ( - - - - - - - ))} - -
NameVisitorsExpires at
{share.id}{share.views} - {moment(share.expiration).unix() === 0 - ? "Never" - : moment(share.expiration).format("MMMM DD YYYY, HH:mm")} - - - { - clipboard.copy( - `${window.location.origin}/share/${share.id}` - ); - toast.success("Your link was copied to the keyboard."); - }} - > - - - { - modals.openConfirmModal({ - title: `Delete share ${share.id}`, - children: ( - - Do you really want to delete this share? - - ), - confirmProps: { - color: "red", - }, - labels: { confirm: "Confirm", cancel: "Cancel" }, - onConfirm: () => { - shareService.remove(share.id); - setShares( - shares.filter((item) => item.id !== share.id) - ); - }, - }); - }} - > - - - -
- )} - - ); + if (!shares) return ; + return ( + <> + + + My shares + + {shares.length == 0 ? ( +
+ + It's empty here 👀 + You don't have any shares. + + + +
+ ) : ( + + + + + + + + + + + {shares.map((share) => ( + + + + + + + ))} + +
NameVisitorsExpires at
{share.id}{share.views} + {moment(share.expiration).unix() === 0 + ? "Never" + : (publicRuntimeConfig.TWELVE_HOUR_TIME === "true") + ? moment(share.expiration).format("MMMM Do YYYY, h:mm a") + : moment(share.expiration).format("MMMM DD YYYY, HH:mm") + } + + + { + clipboard.copy( + `${window.location.origin}/share/${share.id}` + ); + toast.success("Your link was copied to the keyboard."); + }} + > + + + { + modals.openConfirmModal({ + title: `Delete share ${share.id}`, + children: ( + + Do you really want to delete this share? + + ), + confirmProps: { + color: "red", + }, + labels: {confirm: "Confirm", cancel: "Cancel"}, + onConfirm: () => { + shareService.remove(share.id); + setShares( + shares.filter((item) => item.id !== share.id) + ); + }, + }); + }} + > + + + +
+ )} + + ); }; export default MyShares;