From 0dc4c51e2fc0f5a1952f5e39ac9e232d3811f640 Mon Sep 17 00:00:00 2001 From: Pawan Paudel Date: Fri, 26 Apr 2024 22:36:00 +0545 Subject: [PATCH 1/2] fix: Prevent closing modal when submitting --- .../CreateProfileModal/CreateProfileModal.tsx | 1 + .../DragonDeploy/ArNSUpdateModal.tsx | 7 ++- src/components/DragonDeploy/DragonDeploy.tsx | 1 + src/pages/home/components/NewRepoModal.tsx | 3 ++ .../issue/read/tabs/bounty/NewBountyModal.tsx | 6 ++- .../read/tabs/bounty/ReadBountyModal.tsx | 16 ++++-- src/pages/repository/components/ForkModal.tsx | 1 + .../tabs/code-tab/CommitFilesModal.tsx | 1 + .../tabs/code-tab/header/AddFilesModal.tsx | 49 ++++++++++--------- .../tabs/code-tab/header/NewBranchModal.tsx | 1 + src/stores/issues/index.ts | 5 ++ 11 files changed, 63 insertions(+), 28 deletions(-) diff --git a/src/components/CreateProfileModal/CreateProfileModal.tsx b/src/components/CreateProfileModal/CreateProfileModal.tsx index 9fda54b2..d7a2854a 100644 --- a/src/components/CreateProfileModal/CreateProfileModal.tsx +++ b/src/components/CreateProfileModal/CreateProfileModal.tsx @@ -41,6 +41,7 @@ export default function CreateProfileModal({ setIsOpen, isOpen }: NewRepoModalPr }) function closeModal() { + if (isSubmitting) return setIsOpen(false) } diff --git a/src/components/DragonDeploy/ArNSUpdateModal.tsx b/src/components/DragonDeploy/ArNSUpdateModal.tsx index 2f6c9192..9cb68abe 100644 --- a/src/components/DragonDeploy/ArNSUpdateModal.tsx +++ b/src/components/DragonDeploy/ArNSUpdateModal.tsx @@ -41,6 +41,7 @@ export default function ArNSDomainModal() { }, [deployment, domainTxId, domain]) function closeModal() { + if (isLoading) return setIsOpen(false) } @@ -198,7 +199,11 @@ export default function ArNSDomainModal() { {!updateNeeded && !isUpdated && isOnline && Update in progress...} {updateNeeded && Update to latest deployment?} - {!isOnline && Note: It might take ~30 minutes for the domain to go live.} + {!isOnline && ( + + Note: It might take ~30 minutes for the domain to go live. + + )}
diff --git a/src/components/DragonDeploy/DragonDeploy.tsx b/src/components/DragonDeploy/DragonDeploy.tsx index ebd85ed8..db132043 100644 --- a/src/components/DragonDeploy/DragonDeploy.tsx +++ b/src/components/DragonDeploy/DragonDeploy.tsx @@ -53,6 +53,7 @@ export default function DragonDeploy() { }, [isOpen]) function closeModal() { + if (isDeploying) return setIsOpen(false) } diff --git a/src/pages/home/components/NewRepoModal.tsx b/src/pages/home/components/NewRepoModal.tsx index 4ddb6ca7..f76a0906 100644 --- a/src/pages/home/components/NewRepoModal.tsx +++ b/src/pages/home/components/NewRepoModal.tsx @@ -51,6 +51,7 @@ export default function NewRepoModal({ setIsOpen, isOpen }: NewRepoModalProps) { }) function closeModal() { + if (isSubmitting) return setIsOpen(false) } @@ -96,7 +97,9 @@ export default function NewRepoModal({ setIsOpen, isOpen }: NewRepoModalProps) { } } catch (error) { trackGoogleAnalyticsEvent('Repository', 'Failed to create a new repo', 'Create new repo') + toast.error(`Failed to create new repository.`) } + setIsSubmitting(false) } function handleRepositoryVisibilityChange(event: ChangeEvent) { diff --git a/src/pages/issue/read/tabs/bounty/NewBountyModal.tsx b/src/pages/issue/read/tabs/bounty/NewBountyModal.tsx index f1277385..38172990 100644 --- a/src/pages/issue/read/tabs/bounty/NewBountyModal.tsx +++ b/src/pages/issue/read/tabs/bounty/NewBountyModal.tsx @@ -10,6 +10,7 @@ import * as yup from 'yup' import ArweaveLogo from '@/assets/arweave.svg' import CloseCrossIcon from '@/assets/icons/close-cross.svg' import { Button } from '@/components/common/buttons' +import { withAsync } from '@/helpers/withAsync' import { useGlobalStore } from '@/stores/globalStore' type NewBountyModalProps = { @@ -49,14 +50,15 @@ export default function NewBountyModal({ isOpen, setIsOpen }: NewBountyModalProp const unixTimestampOfExpiry = Math.floor(data.expiry.getTime() / 1000) - await addBounty(+issueId!, data.amount, unixTimestampOfExpiry) + const { error } = await withAsync(() => addBounty(+issueId!, data.amount, unixTimestampOfExpiry)) setIsSubmitting(false) - closeModal() + if (!error) closeModal() } function closeModal() { + if (isSubmitting) return setIsOpen(false) } diff --git a/src/pages/issue/read/tabs/bounty/ReadBountyModal.tsx b/src/pages/issue/read/tabs/bounty/ReadBountyModal.tsx index 0c68edec..46698f0f 100644 --- a/src/pages/issue/read/tabs/bounty/ReadBountyModal.tsx +++ b/src/pages/issue/read/tabs/bounty/ReadBountyModal.tsx @@ -2,12 +2,14 @@ import { Dialog, Transition } from '@headlessui/react' import clsx from 'clsx' import { differenceInDays } from 'date-fns' import React, { Fragment } from 'react' +import toast from 'react-hot-toast' import SVG from 'react-inlinesvg' import { useParams } from 'react-router-dom' import ArweaveLogo from '@/assets/arweave.svg' import CloseCrossIcon from '@/assets/icons/close-cross.svg' import { Button } from '@/components/common/buttons' +import { withAsync } from '@/helpers/withAsync' import { useGlobalStore } from '@/stores/globalStore' import { Bounty } from '@/types/repository' @@ -39,17 +41,25 @@ export default function ReadBountyModal({ isOpen, setIsOpen, bounty, author }: N async function handleCloseButtonClick() { setIsSubmitting(true) + let error if (bountyComplete && payTxId.length > 0) { - await completeBounty(+issueId!, bounty.id, payTxId) + ;({ error } = await withAsync(() => completeBounty(+issueId!, bounty.id, payTxId))) + if (error) { + toast.error('Failed to complete bounty.') + } } else { - await closeBounty(+issueId!, bounty.id) + ;({ error } = await withAsync(() => closeBounty(+issueId!, bounty.id))) + if (error) { + toast.error('Failed to close bounty.') + } } setIsSubmitting(false) - closeModal() + if (!error) closeModal() } function closeModal() { + if (isSubmitting) return setIsOpen(false) } diff --git a/src/pages/repository/components/ForkModal.tsx b/src/pages/repository/components/ForkModal.tsx index c5f6fceb..be281aa9 100644 --- a/src/pages/repository/components/ForkModal.tsx +++ b/src/pages/repository/components/ForkModal.tsx @@ -52,6 +52,7 @@ export default function ForkModal({ setIsOpen, isOpen, repo }: NewRepoModalProps }) function closeModal() { + if (isSubmitting) return setIsOpen(false) } diff --git a/src/pages/repository/components/tabs/code-tab/CommitFilesModal.tsx b/src/pages/repository/components/tabs/code-tab/CommitFilesModal.tsx index 59b1e2a3..eea790c0 100644 --- a/src/pages/repository/components/tabs/code-tab/CommitFilesModal.tsx +++ b/src/pages/repository/components/tabs/code-tab/CommitFilesModal.tsx @@ -63,6 +63,7 @@ export default function CommitFilesModal({ setIsOpen, setIsCommited, isOpen, fil }, [files]) function closeModal() { + if (isSubmitting) return setIsOpen(false) } diff --git a/src/pages/repository/components/tabs/code-tab/header/AddFilesModal.tsx b/src/pages/repository/components/tabs/code-tab/header/AddFilesModal.tsx index c0be8ff5..89ae9d5d 100644 --- a/src/pages/repository/components/tabs/code-tab/header/AddFilesModal.tsx +++ b/src/pages/repository/components/tabs/code-tab/header/AddFilesModal.tsx @@ -62,6 +62,7 @@ export default function AddFilesModal({ setIsOpen, isOpen }: NewBranchModal) { }, [files]) function closeModal() { + if (isSubmitting) return setIsOpen(false) } @@ -75,33 +76,37 @@ export default function AddFilesModal({ setIsOpen, isOpen }: NewBranchModal) { async function handleCommitSubmit(data: yup.InferType) { if (files.length > 0 && userRepo) { - setIsSubmitting(true) - - const basePath = getCurrentFolderPath() - - const updatedFiles = files.map((file) => { - const updatedPath = joinPaths(basePath, file.path!) - const updatedFile = new File([file], file.name, { - lastModified: file.lastModified, - type: file.type + try { + setIsSubmitting(true) + + const basePath = getCurrentFolderPath() + + const updatedFiles = files.map((file) => { + const updatedPath = joinPaths(basePath, file.path!) + const updatedFile = new File([file], file.name, { + lastModified: file.lastModified, + type: file.type + }) + Object.defineProperty(updatedFile, 'path', { value: updatedPath }) + return updatedFile as FileWithPath }) - Object.defineProperty(updatedFile, 'path', { value: updatedPath }) - return updatedFile as FileWithPath - }) - await addFiles({ - files: updatedFiles, - id: id!, - message: data.commit, - name: userRepo.name, - owner: address!, - defaultBranch: userRepo.defaultBranch || 'master' - }) + await addFiles({ + files: updatedFiles, + id: id!, + message: data.commit, + name: userRepo.name, + owner: address!, + defaultBranch: userRepo.defaultBranch || 'master' + }) - await reloadFilesOnCurrentFolder() + await reloadFilesOnCurrentFolder() + closeModal() + } catch (error) { + toast.error(`Failed to upload new file${files.length > 1 ? 's' : ''}.`) + } setIsSubmitting(false) - closeModal() } else { toast.error('Please select atleast one file.') } diff --git a/src/pages/repository/components/tabs/code-tab/header/NewBranchModal.tsx b/src/pages/repository/components/tabs/code-tab/header/NewBranchModal.tsx index caffd645..2055797f 100644 --- a/src/pages/repository/components/tabs/code-tab/header/NewBranchModal.tsx +++ b/src/pages/repository/components/tabs/code-tab/header/NewBranchModal.tsx @@ -53,6 +53,7 @@ export default function NewBranchModal({ setIsOpen, isOpen, addNewBranch }: NewB }) function closeModal() { + if (isSubmitting) return setIsOpen(false) } diff --git a/src/stores/issues/index.ts b/src/stores/issues/index.ts index 91ed60ec..cc4b9950 100644 --- a/src/stores/issues/index.ts +++ b/src/stores/issues/index.ts @@ -374,6 +374,7 @@ const createPullRequestSlice: StateCreator { @@ -403,6 +404,8 @@ const createPullRequestSlice: StateCreator { @@ -462,6 +465,8 @@ const createPullRequestSlice: StateCreator Date: Mon, 29 Apr 2024 11:11:11 +0545 Subject: [PATCH 2/2] refactor: Add cursor not allowded style & disable input on submitting modal form --- .../DragonDeploy/ArNSUpdateModal.tsx | 12 +++++---- src/components/DragonDeploy/DragonDeploy.tsx | 9 ++++--- src/helpers/hooks/useCursorNotAllowded.ts | 7 +++++ src/pages/home/components/NewRepoModal.tsx | 27 ++++++++++++++----- .../issue/read/tabs/bounty/NewBountyModal.tsx | 16 +++++++---- .../read/tabs/bounty/ReadBountyModal.tsx | 16 +++++++---- src/pages/repository/components/ForkModal.tsx | 16 +++++++---- .../tabs/code-tab/CommitFilesModal.tsx | 12 ++++++--- .../tabs/code-tab/header/AddFilesModal.tsx | 20 +++++++++----- .../tabs/code-tab/header/NewBranchModal.tsx | 12 ++++++--- 10 files changed, 102 insertions(+), 45 deletions(-) create mode 100644 src/helpers/hooks/useCursorNotAllowded.ts diff --git a/src/components/DragonDeploy/ArNSUpdateModal.tsx b/src/components/DragonDeploy/ArNSUpdateModal.tsx index 9cb68abe..354fa0a4 100644 --- a/src/components/DragonDeploy/ArNSUpdateModal.tsx +++ b/src/components/DragonDeploy/ArNSUpdateModal.tsx @@ -7,6 +7,7 @@ import SVG from 'react-inlinesvg' import CloseCrossIcon from '@/assets/icons/close-cross.svg' import { Button } from '@/components/common/buttons' +import useCursorNotAllowed from '@/helpers/hooks/useCursorNotAllowded' import { withAsync } from '@/helpers/withAsync' import { getANT, getDomainStatus, updateArNSDomain } from '@/lib/dragondeploy/arns' import { useGlobalStore } from '@/stores/globalStore' @@ -19,7 +20,7 @@ export default function ArNSDomainModal() { const [isLoading, setIsLoading] = useState(false) const [domainTxId, setDomainTxId] = useState('') const [intervalValue, setIntervalValue] = useState() - + const { cursorNotAllowed, closeModalCursor } = useCursorNotAllowed(isLoading) const [connectedAddress, selectedRepo, updateDomain] = useGlobalStore((state) => [ state.authState.address, state.repoCoreState.selectedRepo.repo, @@ -146,7 +147,7 @@ export default function ArNSDomainModal() { ArNS Domain - + ArNS Domain - +
@@ -208,7 +209,7 @@ export default function ArNSDomainModal() {
diff --git a/src/components/DragonDeploy/DragonDeploy.tsx b/src/components/DragonDeploy/DragonDeploy.tsx index db132043..bde28894 100644 --- a/src/components/DragonDeploy/DragonDeploy.tsx +++ b/src/components/DragonDeploy/DragonDeploy.tsx @@ -1,4 +1,5 @@ import { Dialog, Transition } from '@headlessui/react' +import clsx from 'clsx' import { useEffect, useState } from 'react' import { Fragment } from 'react' import toast from 'react-hot-toast' @@ -7,6 +8,7 @@ import SVG from 'react-inlinesvg' import CloseCrossIcon from '@/assets/icons/close-cross.svg' import { Button } from '@/components/common/buttons' import CostEstimatesToolTip from '@/components/CostEstimatesToolTip' +import useCursorNotAllowed from '@/helpers/hooks/useCursorNotAllowded' import { type Commit, type File, @@ -28,6 +30,7 @@ export default function DragonDeploy() { const [currentDeployment, setCurrentDeployment] = useState() const [uploadPercent, setUploadPercent] = useState(0) const [branchToRestore, setBranchToRestore] = useState('') + const { cursorNotAllowed, closeModalCursor } = useCursorNotAllowed(isDeploying) const [currentBranch, selectedRepo, branchState, branchActions, addDeployment] = useGlobalStore((state) => [ state.branchState.currentBranch, state.repoCoreState.selectedRepo.repo, @@ -116,7 +119,7 @@ export default function DragonDeploy() { Dragon Deploy - + Dragon Deploy - +
@@ -189,7 +192,7 @@ export default function DragonDeploy() {
@@ -149,9 +152,11 @@ export default function NewRepoModal({ setIsOpen, isOpen }: NewRepoModalProps) { {...register('title')} className={clsx( 'bg-white border-[1px] text-gray-900 text-base rounded-lg hover:shadow-[0px_2px_4px_0px_rgba(0,0,0,0.10)] focus:border-primary-500 focus:border-[1.5px] block w-full px-3 py-[10px] outline-none', - errors.title ? 'border-red-500' : 'border-gray-300' + errors.title ? 'border-red-500' : 'border-gray-300', + cursorNotAllowed )} placeholder="my-cool-repo" + disabled={isSubmitting} /> {errors.title &&

{errors.title?.message}

}
@@ -164,9 +169,11 @@ export default function NewRepoModal({ setIsOpen, isOpen }: NewRepoModalProps) { {...register('description')} className={clsx( 'bg-white border-[1px] text-gray-900 text-base rounded-lg hover:shadow-[0px_2px_4px_0px_rgba(0,0,0,0.10)] focus:border-primary-500 focus:border-[1.5px] block w-full px-3 py-[10px] outline-none', - errors.description ? 'border-red-500' : 'border-gray-300' + errors.description ? 'border-red-500' : 'border-gray-300', + cursorNotAllowed )} placeholder="A really cool repo fully decentralized" + disabled={isSubmitting} /> {errors.description && (

{errors.description?.message}

@@ -182,7 +189,10 @@ export default function NewRepoModal({ setIsOpen, isOpen }: NewRepoModalProps) { onChange={handleRepositoryVisibilityChange} value="public" defaultChecked - className="mr-2 rounded-full h-4 w-4 checked:accent-primary-700 accent-primary-600 bg-white focus:ring-primary-600 outline-none" + className={clsx( + 'mr-2 rounded-full h-4 w-4 checked:accent-primary-700 accent-primary-600 bg-white focus:ring-primary-600 outline-none', + cursorNotAllowed + )} /> Public @@ -193,7 +203,10 @@ export default function NewRepoModal({ setIsOpen, isOpen }: NewRepoModalProps) { disabled={authState.method === 'othent'} onChange={handleRepositoryVisibilityChange} value="private" - className="mr-2 rounded-full h-4 w-4 checked:accent-primary-700 accent-primary-600 bg-white focus:ring-primary-600 outline-none" + className={clsx( + 'mr-2 rounded-full h-4 w-4 checked:accent-primary-700 accent-primary-600 bg-white focus:ring-primary-600 outline-none', + cursorNotAllowed + )} /> Private @@ -208,7 +221,7 @@ export default function NewRepoModal({ setIsOpen, isOpen }: NewRepoModalProps) {
@@ -117,12 +119,14 @@ export default function NewBountyModal({ isOpen, setIsOpen }: NewBountyModalProp {...register('amount')} className={clsx( 'bg-white border-[1px] text-gray-900 text-base rounded-lg hover:shadow-[0px_2px_4px_0px_rgba(0,0,0,0.10)] focus:border-primary-500 focus:border-[1.5px] block w-full px-3 py-[10px] outline-none', - errors.amount ? 'border-red-500' : 'border-gray-300' + errors.amount ? 'border-red-500' : 'border-gray-300', + cursorNotAllowed )} step="0.5" type="number" placeholder="2" min={'0'} + disabled={isSubmitting} />
AR @@ -139,11 +143,13 @@ export default function NewBountyModal({ isOpen, setIsOpen }: NewBountyModalProp {...register('expiry')} className={clsx( 'bg-white border-[1px] text-gray-900 text-base rounded-lg hover:shadow-[0px_2px_4px_0px_rgba(0,0,0,0.10)] focus:border-primary-500 focus:border-[1.5px] block w-full px-3 py-[10px] outline-none', - errors.expiry ? 'border-red-500' : 'border-gray-300' + errors.expiry ? 'border-red-500' : 'border-gray-300', + cursorNotAllowed )} type="date" min={new Date().toISOString().split('T')[0]} placeholder="2" + disabled={isSubmitting} />
{errors.expiry &&

{errors.expiry.message}

} @@ -153,7 +159,7 @@ export default function NewBountyModal({ isOpen, setIsOpen }: NewBountyModalProp
@@ -117,7 +119,8 @@ export default function ReadBountyModal({ isOpen, setIsOpen, bounty, author }: N setBountyComplete(evt.target.checked)} + disabled={isSubmitting} /> Mark this bounty complete?
@@ -159,18 +163,20 @@ export default function ReadBountyModal({ isOpen, setIsOpen, bounty, author }: N setPayTxId(evt.target.value)} + disabled={isSubmitting} />
)}
@@ -147,9 +149,11 @@ export default function ForkModal({ setIsOpen, isOpen, repo }: NewRepoModalProps {...register('title')} className={clsx( 'bg-white border-[1px] text-gray-900 text-base rounded-lg hover:shadow-[0px_2px_4px_0px_rgba(0,0,0,0.10)] focus:border-primary-500 focus:border-[1.5px] block w-full px-3 py-[10px] outline-none', - errors.title ? 'border-red-500' : 'border-gray-300' + errors.title ? 'border-red-500' : 'border-gray-300', + cursorNotAllowed )} placeholder="my-cool-repo" + disabled={isSubmitting} /> {errors.title &&

{errors.title?.message}

}
@@ -162,9 +166,11 @@ export default function ForkModal({ setIsOpen, isOpen, repo }: NewRepoModalProps {...register('description')} className={clsx( 'bg-white border-[1px] text-gray-900 text-base rounded-lg hover:shadow-[0px_2px_4px_0px_rgba(0,0,0,0.10)] focus:border-primary-500 focus:border-[1.5px] block w-full px-3 py-[10px] outline-none', - errors.description ? 'border-red-500' : 'border-gray-300' + errors.description ? 'border-red-500' : 'border-gray-300', + cursorNotAllowed )} placeholder="A really cool repo fully decentralized" + disabled={isSubmitting} /> {errors.description && (

{errors.description?.message}

@@ -176,7 +182,7 @@ export default function ForkModal({ setIsOpen, isOpen, repo }: NewRepoModalProps
@@ -149,9 +151,11 @@ export default function CommitFilesModal({ setIsOpen, setIsCommited, isOpen, fil {...register('commit')} className={clsx( 'bg-white border-[1px] text-gray-900 text-base rounded-lg hover:shadow-[0px_2px_4px_0px_rgba(0,0,0,0.10)] focus:border-primary-500 focus:border-[1.5px] block w-full px-3 py-[10px] outline-none', - errors.commit ? 'border-red-500' : 'border-gray-300' + errors.commit ? 'border-red-500' : 'border-gray-300', + cursorNotAllowed )} placeholder="Example: Add README.md file" + disabled={isSubmitting} /> {errors.commit &&

{errors.commit?.message}

}
@@ -163,7 +167,7 @@ export default function CommitFilesModal({ setIsOpen, setIsCommited, isOpen, fil
Upload files
- + {files.length === 0 && (
{!isDragActive && ( @@ -206,9 +210,11 @@ export default function AddFilesModal({ setIsOpen, isOpen }: NewBranchModal) { {...register('commit')} className={clsx( 'bg-white border-[1px] text-gray-900 text-base rounded-lg hover:shadow-[0px_2px_4px_0px_rgba(0,0,0,0.10)] focus:border-primary-500 focus:border-[1.5px] block w-full px-3 py-[10px] outline-none', - errors.commit ? 'border-red-500' : 'border-gray-300' + errors.commit ? 'border-red-500' : 'border-gray-300', + cursorNotAllowed )} placeholder="Example: Add README.md file" + disabled={isSubmitting} /> {errors.commit &&

{errors.commit?.message}

}
@@ -220,7 +226,7 @@ export default function AddFilesModal({ setIsOpen, isOpen }: NewBranchModal) {
@@ -142,9 +144,11 @@ export default function NewBranchModal({ setIsOpen, isOpen, addNewBranch }: NewB {...register('name')} className={clsx( 'bg-white border-[1px] text-gray-900 text-base rounded-lg hover:shadow-[0px_2px_4px_0px_rgba(0,0,0,0.10)] focus:border-primary-500 focus:border-[1.5px] block w-full px-3 py-[10px] outline-none', - errors.name ? 'border-red-500' : 'border-gray-300' + errors.name ? 'border-red-500' : 'border-gray-300', + cursorNotAllowed )} placeholder="feature/my-cool-feature" + disabled={isSubmitting} /> {errors.name &&

{errors.name?.message}

}
@@ -153,7 +157,7 @@ export default function NewBranchModal({ setIsOpen, isOpen, addNewBranch }: NewB