Merge 27--07-25-upd
This commit is contained in:
commit
6344d015db
|
|
@ -300,7 +300,7 @@ const CommonNav: React.FC<AccountNavProps> = () => {
|
||||||
aria-expanded={open}
|
aria-expanded={open}
|
||||||
aria-haspopup="true"
|
aria-haspopup="true"
|
||||||
>
|
>
|
||||||
<div className="w-8 h-8 rounded-full overflow-hidden bg-gradient-to-br from-green-500 to-blue-600 flex items-center justify-center text-white font-semibold text-sm shadow-md">
|
<div className="w-8 h-8 rounded-full overflow-hidden bg-[var(--primaryLight2)] flex items-center justify-center text-white font-semibold text-sm shadow-md">
|
||||||
{user ? (
|
{user ? (
|
||||||
<span className="w-full h-full object-cover p-1.5 font-bold">
|
<span className="w-full h-full object-cover p-1.5 font-bold">
|
||||||
{(user?.name?.slice(0, 2)).toUpperCase()}
|
{(user?.name?.slice(0, 2)).toUpperCase()}
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,11 @@ const ProcessStepOne = () => {
|
||||||
dispatch(toggleToTemplates());
|
dispatch(toggleToTemplates());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const [editCase , setEditCase] = useState<string>("")
|
||||||
|
const [editRecipient , setEditRecipient] = useState({})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// if (!accountId || !transactionId) {
|
// if (!accountId || !transactionId) {
|
||||||
// window.location.href = "/";
|
// window.location.href = "/";
|
||||||
// return null;
|
// return null;
|
||||||
|
|
@ -57,6 +62,7 @@ const ProcessStepOne = () => {
|
||||||
console.log("selectedRecipients", selectedRecipients)
|
console.log("selectedRecipients", selectedRecipients)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
<<<<<<< HEAD
|
||||||
// Fetching Transaction Details - START
|
// Fetching Transaction Details - START
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
|
|
@ -68,6 +74,12 @@ const ProcessStepOne = () => {
|
||||||
})()
|
})()
|
||||||
// Fetching Transaction Details - END
|
// Fetching Transaction Details - END
|
||||||
|
|
||||||
|
=======
|
||||||
|
(async () => {
|
||||||
|
const res = await api.get(`/api/accounts/${accountId}/${transactionTemplateToggle}/${transactionId}`)
|
||||||
|
console.log(res.data);
|
||||||
|
})()
|
||||||
|
>>>>>>> origin/main
|
||||||
|
|
||||||
selectedRecipients.length === 0 && dispatch(fetchRecipients({ accountId, transactionId }));
|
selectedRecipients.length === 0 && dispatch(fetchRecipients({ accountId, transactionId }));
|
||||||
selectedDocuments.length === 0 && dispatch(fetchDocuments({ accountId, transactionId }));
|
selectedDocuments.length === 0 && dispatch(fetchDocuments({ accountId, transactionId }));
|
||||||
|
|
@ -164,7 +176,9 @@ const ProcessStepOne = () => {
|
||||||
accessCodeDelivery: true,
|
accessCodeDelivery: true,
|
||||||
language: "en",
|
language: "en",
|
||||||
name: `${recipient.firstName} ${recipient.lastName}`,
|
name: `${recipient.firstName} ${recipient.lastName}`,
|
||||||
roleName: recipient.roleName
|
roleName: recipient.roleName,
|
||||||
|
allowSenderToEdit: recipient.allowSenderToEdit ,
|
||||||
|
allowSenderToDelete: recipient.allowSenderToDelete,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let recipientsDataTemp = recipientsData;
|
let recipientsDataTemp = recipientsData;
|
||||||
|
|
@ -334,9 +348,9 @@ const ProcessStepOne = () => {
|
||||||
{
|
{
|
||||||
signType !== SignTypeEnum.selfSign &&
|
signType !== SignTypeEnum.selfSign &&
|
||||||
<div className="flex flex-col gap-4 align-start">
|
<div className="flex flex-col gap-4 align-start">
|
||||||
<RecipientCards />
|
<RecipientCards transactionTemplateToggle={transactionTemplateToggle} setEditRecipient={setEditRecipient} setEditCase={setEditCase}/>
|
||||||
{/* {signType !== "self-sign" && <RecipientAddCard />} */}
|
{/* {signType !== "self-sign" && <RecipientAddCard />} */}
|
||||||
<RecipientAddCard transactionTemplateToggle={transactionTemplateToggle} />
|
<RecipientAddCard transactionTemplateToggle={transactionTemplateToggle} editRecipient={editRecipient} editCase={editCase} setEditRecipient={setEditRecipient} setEditCase={setEditCase}/>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { FaPlus } from "react-icons/fa";
|
import { FaPlus } from "react-icons/fa";
|
||||||
import { addRecipient, Recipient, recipientType } from "../../../store/slices/selectedRecipientsSlice";
|
import { addRecipient, Recipient, recipientType, updateRecipient } from "../../../store/slices/selectedRecipientsSlice";
|
||||||
import { useDispatch } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
import { AppDispatch } from "../../../store/store";
|
import { AppDispatch } from "../../../store/store";
|
||||||
import api from "../../../config/api";
|
import api from "../../../config/api";
|
||||||
|
|
@ -8,6 +8,8 @@ import ContactModal from "./ContactModal";
|
||||||
import useDebouncedEffect from "../../../utlity/useDebounce";
|
import useDebouncedEffect from "../../../utlity/useDebounce";
|
||||||
import { IoIosSettings } from "react-icons/io";
|
import { IoIosSettings } from "react-icons/io";
|
||||||
import { FiEdit, FiTrash } from "react-icons/fi";
|
import { FiEdit, FiTrash } from "react-icons/fi";
|
||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
|
|
||||||
interface ContactType {
|
interface ContactType {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
@ -21,7 +23,8 @@ export interface ContactTypeObj {
|
||||||
contacts: ContactType[];
|
contacts: ContactType[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const RecipientAddCard = ({ transactionTemplateToggle }) => {
|
|
||||||
|
const RecipientAddCard = ({ transactionTemplateToggle, editRecipient, editCase ,setEditRecipient, setEditCase }) => {
|
||||||
|
|
||||||
const [contactData, setContactData] = useState<ContactTypeObj>({ type: "", contacts: [] });
|
const [contactData, setContactData] = useState<ContactTypeObj>({ type: "", contacts: [] });
|
||||||
const [openContactModal, setOpenContactModal] = useState(false);
|
const [openContactModal, setOpenContactModal] = useState(false);
|
||||||
|
|
@ -29,29 +32,79 @@ const RecipientAddCard = ({ transactionTemplateToggle }) => {
|
||||||
const dispatch = useDispatch<AppDispatch>();
|
const dispatch = useDispatch<AppDispatch>();
|
||||||
const formRef = useRef<HTMLFormElement | null>(null);
|
const formRef = useRef<HTMLFormElement | null>(null);
|
||||||
|
|
||||||
const [recipient, setRecipients] = useState<Recipient>({ firstName: "", lastName: "", email: "", hostName: "", hostEmail: "", roleName: "", type: recipientType.SIGNER, allowSenderToEdit: Boolean, allowSenderToRemove: Boolean });
|
const [recipient, setRecipients] = useState<Recipient>({ uuid:null, newOne:false, firstName: "", lastName: "", email: "", hostName: "", hostEmail: "", roleName: "", type: recipientType.SIGNER, allowSenderToEdit: false, allowSenderToDelete: false });
|
||||||
|
|
||||||
const [showAdvanceSettings, setShowAdvanceSettings] = useState(false)
|
const [showAdvanceSettings, setShowAdvanceSettings] = useState(false)
|
||||||
console.log(recipient)
|
console.log(recipient)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (editCase === "Edit" && editRecipient) {
|
||||||
|
setRecipients({
|
||||||
|
// id:editRecipient.id,
|
||||||
|
firstName: editRecipient.firstName || "",
|
||||||
|
lastName: editRecipient.lastName || "",
|
||||||
|
email: editRecipient.email || "",
|
||||||
|
hostName: editRecipient.hostName || "",
|
||||||
|
hostEmail: editRecipient.hostEmail || "",
|
||||||
|
roleName: editRecipient.roleName || "",
|
||||||
|
type: editRecipient.type || recipientType.SIGNER,
|
||||||
|
allowSenderToEdit: editRecipient.allowSenderToEdit ?? false,
|
||||||
|
allowSenderToDelete: editRecipient.allowSenderToDelete ?? false,
|
||||||
|
uuid: String(editRecipient?.id ?? editRecipient?.uuid ?? ''),
|
||||||
|
newOne:editRecipient.newOne ?? false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [editCase, editRecipient]);
|
||||||
|
|
||||||
|
|
||||||
const handleRecipientAdd = (e: React.FormEvent<HTMLFormElement>) => {
|
const handleRecipientAdd = (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
if (recipient.lastName === "" || recipient.email === "" || !recipient.type) return;
|
console.log("recipientrecipient",recipient)
|
||||||
|
|
||||||
// Validate Email Format
|
if (!recipient.lastName || !recipient.email || !recipient.type) return;
|
||||||
|
|
||||||
|
// ✅ Email format validation
|
||||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
if (!emailRegex.test(recipient.email)) {
|
if (!emailRegex.test(recipient.email)) {
|
||||||
console.log("Invalid email format");
|
console.log("Invalid email format");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Validation Ends
|
|
||||||
|
|
||||||
dispatch(addRecipient(recipient));
|
if (editCase === 'Edit') {
|
||||||
setRecipients({ firstName: "", lastName: "", email: "", hostName: "", hostEmail: "", roleName: "", type: recipientType.SIGNER, allowSenderToEdit: Boolean, allowSenderToRemove: Boolean });
|
dispatch(updateRecipient(recipient));
|
||||||
formRef.current?.reset();
|
} else {
|
||||||
|
dispatch(addRecipient({
|
||||||
|
...recipient,
|
||||||
|
uuid:uuidv4(),
|
||||||
|
newOne:true
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ✅ Reset state and form
|
||||||
|
setRecipients({
|
||||||
|
firstName: "",
|
||||||
|
lastName: "",
|
||||||
|
email: "",
|
||||||
|
hostName: "",
|
||||||
|
hostEmail: "",
|
||||||
|
roleName: "",
|
||||||
|
type: recipientType.SIGNER,
|
||||||
|
allowSenderToEdit: false,
|
||||||
|
allowSenderToDelete: false,
|
||||||
|
uuid:"",
|
||||||
|
newOne:false
|
||||||
|
});
|
||||||
|
|
||||||
|
// setRecipients(null),
|
||||||
|
setEditCase("")
|
||||||
|
|
||||||
|
formRef.current?.reset();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// useEffect(() => {
|
// useEffect(() => {
|
||||||
// if (!recipient.firstName.length) return;
|
// if (!recipient.firstName.length) return;
|
||||||
|
|
||||||
|
|
@ -133,10 +186,10 @@ const RecipientAddCard = ({ transactionTemplateToggle }) => {
|
||||||
} overflow-hidden`}
|
} overflow-hidden`}
|
||||||
>
|
>
|
||||||
<div className="text-sm text-gray-600">
|
<div className="text-sm text-gray-600">
|
||||||
{recipient.allowSenderToEdit && recipient.allowSenderToRemove && "Full permissions granted"}
|
{recipient.allowSenderToEdit && recipient.allowSenderToDelete && "Full permissions granted"}
|
||||||
{recipient.allowSenderToEdit && !recipient.allowSenderToRemove && "Edit permission granted"}
|
{recipient.allowSenderToEdit && !recipient.allowSenderToDelete && "Edit permission granted"}
|
||||||
{!recipient.allowSenderToEdit && recipient.allowSenderToRemove && "Delete permission granted"}
|
{!recipient.allowSenderToEdit && recipient.allowSenderToDelete && "Delete permission granted"}
|
||||||
{!recipient.allowSenderToEdit && !recipient.allowSenderToRemove && "No permissions granted"}
|
{!recipient.allowSenderToEdit && !recipient.allowSenderToDelete && "No permissions granted"}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/* Animated Permission Controls */}
|
{/* Animated Permission Controls */}
|
||||||
|
|
@ -178,23 +231,23 @@ const RecipientAddCard = ({ transactionTemplateToggle }) => {
|
||||||
{/* Delete Permission */}
|
{/* Delete Permission */}
|
||||||
<div className="relative group">
|
<div className="relative group">
|
||||||
<label
|
<label
|
||||||
className={`relative flex items-center justify-center w-6 h-6 border-2 rounded-lg cursor-pointer transition-all duration-300 transform hover:scale-105 ${recipient.allowSenderToRemove
|
className={`relative flex items-center justify-center w-6 h-6 border-2 rounded-lg cursor-pointer transition-all duration-300 transform hover:scale-105 ${recipient.allowSenderToDelete
|
||||||
? 'bg-red-100 border-red-500 shadow-lg'
|
? 'bg-red-100 border-red-500 shadow-lg'
|
||||||
: 'bg-white border-gray-300 hover:border-red-400'
|
: 'bg-white border-gray-300 hover:border-red-400'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={recipient.allowSenderToRemove}
|
checked={recipient.allowSenderToDelete}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setRecipients({ ...recipient, allowSenderToRemove: e.target.checked })
|
setRecipients({ ...recipient, allowSenderToDelete: e.target.checked })
|
||||||
}
|
}
|
||||||
onFocus={() => setOpenContactModal(true)}
|
onFocus={() => setOpenContactModal(true)}
|
||||||
onBlur={handleContactModalBlur}
|
onBlur={handleContactModalBlur}
|
||||||
className="absolute w-full h-full opacity-0 cursor-pointer"
|
className="absolute w-full h-full opacity-0 cursor-pointer"
|
||||||
/>
|
/>
|
||||||
<FiTrash
|
<FiTrash
|
||||||
className={`w-3 h-3 pointer-events-none transition-all duration-300 ${recipient.allowSenderToRemove ? 'text-red-600' : 'text-gray-400'
|
className={`w-3 h-3 pointer-events-none transition-all duration-300 ${recipient.allowSenderToDelete ? 'text-red-600' : 'text-gray-400'
|
||||||
}`}
|
}`}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
@ -332,7 +385,7 @@ const RecipientAddCard = ({ transactionTemplateToggle }) => {
|
||||||
type="submit"
|
type="submit"
|
||||||
className="inline-flex items-center gap-2 bg-[var(--primary)] hover:bg-[var(--primaryLight2)] text-white text-sm font-semibold px-5 py-2 rounded-md transition"
|
className="inline-flex items-center gap-2 bg-[var(--primary)] hover:bg-[var(--primaryLight2)] text-white text-sm font-semibold px-5 py-2 rounded-md transition"
|
||||||
>
|
>
|
||||||
<FaPlus size={14} /> Add Recipient
|
<FaPlus size={14} /> {editCase === "Edit" ? "Edit Recipient" : "Add Recipient"}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import { useState } from "react";
|
||||||
import SigningOrderDiagram from "../../../SigningOrderDiagram ";
|
import SigningOrderDiagram from "../../../SigningOrderDiagram ";
|
||||||
import { IoCloseOutline } from "react-icons/io5";
|
import { IoCloseOutline } from "react-icons/io5";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
|
import { FiEdit } from "react-icons/fi";
|
||||||
|
|
||||||
const getInitials = (name: string) => {
|
const getInitials = (name: string) => {
|
||||||
if (!name) return "";
|
if (!name) return "";
|
||||||
|
|
@ -23,7 +24,13 @@ const getInitials = (name: string) => {
|
||||||
.toUpperCase();
|
.toUpperCase();
|
||||||
};
|
};
|
||||||
|
|
||||||
const RecipientCards = () => {
|
type CardsData = {
|
||||||
|
setEditRecipient: (recipient: any) => void; // Replace `any` with the actual type if known
|
||||||
|
setEditCase: (string: any) => void;
|
||||||
|
transactionTemplateToggle: string
|
||||||
|
};
|
||||||
|
|
||||||
|
const RecipientCards = ({ setEditRecipient, setEditCase, transactionTemplateToggle }: CardsData) => {
|
||||||
const templateId = useParams<{ templateId: string }>().templateId;
|
const templateId = useParams<{ templateId: string }>().templateId;
|
||||||
let { accountId, transactionId } = useParams<{ accountId: string, transactionId: string }>();
|
let { accountId, transactionId } = useParams<{ accountId: string, transactionId: string }>();
|
||||||
|
|
||||||
|
|
@ -34,7 +41,7 @@ const RecipientCards = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const recipients = useSelector((state: RootState) => state.selectedRecipients.recipients);
|
const recipients = useSelector((state: RootState) => state.selectedRecipients.recipients);
|
||||||
console.log("recipients.length",recipients)
|
console.log("recipients.length", recipients)
|
||||||
// const signingOrder = useSelector((state: RootState) => state.selectedRecipients.signingOrder);
|
// const signingOrder = useSelector((state: RootState) => state.selectedRecipients.signingOrder);
|
||||||
const signType = useSelector((state: RootState) => state.selectedDocuments.signType);
|
const signType = useSelector((state: RootState) => state.selectedDocuments.signType);
|
||||||
|
|
||||||
|
|
@ -44,8 +51,15 @@ const RecipientCards = () => {
|
||||||
dispatch(updateRecipientOrder({ id, routingOrder: value }));
|
dispatch(updateRecipientOrder({ id, routingOrder: value }));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleEditRecipient = (recipient) => {
|
||||||
|
// alert(JSON.stringify(recipient))
|
||||||
|
setEditCase('Edit')
|
||||||
|
setEditRecipient(recipient)
|
||||||
|
}
|
||||||
|
|
||||||
const handleRemoveRecipient = (recipient) => {
|
const handleRemoveRecipient = (recipient) => {
|
||||||
if (!accountId || !transactionId) return;
|
if (!accountId || !transactionId) return;
|
||||||
|
<<<<<<< HEAD
|
||||||
// dispatch(removeSelectedRecipient(recipient))
|
// dispatch(removeSelectedRecipient(recipient))
|
||||||
dispatch(removeRecipientAsync([{
|
dispatch(removeRecipientAsync([{
|
||||||
recipientId: recipient.id,
|
recipientId: recipient.id,
|
||||||
|
|
@ -53,6 +67,18 @@ const RecipientCards = () => {
|
||||||
accountId: accountId,
|
accountId: accountId,
|
||||||
transactionId: transactionId,
|
transactionId: transactionId,
|
||||||
}]))
|
}]))
|
||||||
|
=======
|
||||||
|
if (recipient.uuid) {
|
||||||
|
dispatch(removeSelectedRecipient(recipient))
|
||||||
|
} else {
|
||||||
|
dispatch(removeRecipientAsync({
|
||||||
|
recipientId: recipient.id,
|
||||||
|
email: recipient.email,
|
||||||
|
accountId: accountId,
|
||||||
|
transactionId: transactionId,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
>>>>>>> origin/main
|
||||||
if (recipients.length === 2) {
|
if (recipients.length === 2) {
|
||||||
let leftRecipient = recipients.filter((obj) => {
|
let leftRecipient = recipients.filter((obj) => {
|
||||||
if ("id" in obj && "id" in recipient) {
|
if ("id" in obj && "id" in recipient) {
|
||||||
|
|
@ -144,14 +170,45 @@ const RecipientCards = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{signType !== "self-sign" && (
|
{signType !== "self-sign" && (
|
||||||
|
<div className="flex justify-between gap-2 items-center">
|
||||||
|
{/* Edit Button */}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
title="Edit recipient"
|
||||||
|
aria-label={`Edit recipient ${recipient.firstName}`}
|
||||||
|
onClick={() => handleEditRecipient(recipient)}
|
||||||
|
disabled={
|
||||||
|
// For templates: always enabled (never disabled)
|
||||||
|
['templates'].includes(transactionTemplateToggle)
|
||||||
|
? false
|
||||||
|
: // For transactions: disabled if not newOne AND not allowed to edit
|
||||||
|
(!recipient.newOne && !recipient.allowSenderToEdit)
|
||||||
|
}
|
||||||
|
className="text-gray-400 hover:text-blue-600 transition-colors cursor-pointer disabled:opacity-50"
|
||||||
|
>
|
||||||
|
<FiEdit size={16} />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{/* Delete Button */}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
title="Remove recipient"
|
||||||
aria-label={`Remove recipient ${recipient.firstName}`}
|
aria-label={`Remove recipient ${recipient.firstName}`}
|
||||||
onClick={() => handleRemoveRecipient(recipient)}
|
onClick={() => handleRemoveRecipient(recipient)}
|
||||||
className="text-gray-400 hover:text-red-600 transition-colors"
|
disabled={
|
||||||
|
// For templates: always enabled (never disabled)
|
||||||
|
['templates'].includes(transactionTemplateToggle)
|
||||||
|
? false
|
||||||
|
: // For transactions: disabled if not newOne AND not allowed to delete
|
||||||
|
(!recipient.newOne && !recipient.allowSenderToDelete)
|
||||||
|
}
|
||||||
|
className="text-gray-400 hover:text-red-600 transition-colors cursor-pointer disabled:opacity-50"
|
||||||
>
|
>
|
||||||
<ImBin size={16} />
|
<ImBin size={16} />
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,11 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
|
||||||
// const selectedDocuments = useSelector((state: RootState) => state.selectedDocuments.selectedDocuments)
|
// const selectedDocuments = useSelector((state: RootState) => state.selectedDocuments.selectedDocuments)
|
||||||
const selectedDocuments = useSelector((state: RootState) => state.documents.documents)
|
const selectedDocuments = useSelector((state: RootState) => state.documents.documents)
|
||||||
|
|
||||||
|
console.log("selectedDocuments",selectedDocuments)
|
||||||
|
|
||||||
|
const [droppedItems, setDroppedItems] = useState<DroppedItemsObj>({});
|
||||||
|
console.log("droppedItems", droppedItems)
|
||||||
|
|
||||||
// const [uniqGroupIds, setUniqGroupIds] = useState<string[]>([]);
|
// const [uniqGroupIds, setUniqGroupIds] = useState<string[]>([]);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -106,7 +111,7 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
|
||||||
|
|
||||||
// FETCHING TAG - END
|
// FETCHING TAG - END
|
||||||
|
|
||||||
const [droppedItems, setDroppedItems] = useState<DroppedItemsObj>({});
|
|
||||||
const [droppedItemsCounter, setDroppedItemsCounter] = useState<number>(1);
|
const [droppedItemsCounter, setDroppedItemsCounter] = useState<number>(1);
|
||||||
const [selectedTag, setSelectedTag] = useState<{ key: string, index: number } | null>(null);
|
const [selectedTag, setSelectedTag] = useState<{ key: string, index: number } | null>(null);
|
||||||
|
|
||||||
|
|
@ -312,6 +317,7 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
|
||||||
|
|
||||||
const dragElemData = JSON.parse(data); // Get the dropped label
|
const dragElemData = JSON.parse(data); // Get the dropped label
|
||||||
|
|
||||||
|
|
||||||
const field = { ...dragElemData }
|
const field = { ...dragElemData }
|
||||||
if (!field.label) return;
|
if (!field.label) return;
|
||||||
|
|
||||||
|
|
@ -329,8 +335,8 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
|
||||||
properties: data.properties,
|
properties: data.properties,
|
||||||
icon: typeToIconMap[field.label.toUpperCase()] || <FaQuestionCircle />,
|
icon: typeToIconMap[field.label.toUpperCase()] || <FaQuestionCircle />,
|
||||||
type: dragElemData.label,
|
type: dragElemData.label,
|
||||||
subType: (dragElemData.label in droppedTagsDefaultField) ? droppedTagsDefaultField[dragElemData.label] : '',
|
|
||||||
label: dragElemData.label,
|
label: dragElemData.label,
|
||||||
|
subType: (dragElemData.label in droppedTagsDefaultField) ? droppedTagsDefaultField[dragElemData.label] : '',
|
||||||
dimensions: {
|
dimensions: {
|
||||||
left: x,
|
left: x,
|
||||||
top: y,
|
top: y,
|
||||||
|
|
@ -369,6 +375,8 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
|
||||||
prepData.currentTimeStamp = true;
|
prepData.currentTimeStamp = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (prepData.type.toLowerCase() === "number") {
|
if (prepData.type.toLowerCase() === "number") {
|
||||||
prepData.decimalPlace = 0;
|
prepData.decimalPlace = 0;
|
||||||
prepData.isCurrency = false;
|
prepData.isCurrency = false;
|
||||||
|
|
@ -412,6 +420,7 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
|
||||||
// setDroppedItems(dataToSet);
|
// setDroppedItems(dataToSet);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
console.log("data311", dataToSet)
|
||||||
setDroppedItems(dataToSet);
|
setDroppedItems(dataToSet);
|
||||||
setDroppedItemsCounter((prev) => prev + 1);
|
setDroppedItemsCounter((prev) => prev + 1);
|
||||||
|
|
||||||
|
|
@ -423,13 +432,11 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
|
||||||
// HANDLE DROP - END
|
// HANDLE DROP - END
|
||||||
|
|
||||||
// HANDLE TAG MOUSE DOWN - START
|
// HANDLE TAG MOUSE DOWN - START
|
||||||
|
// Updated handleTagMouseDown function with proper group border positioning
|
||||||
const handleTagMouseDown = (event: React.MouseEvent<HTMLDivElement>, key: string, index: number) => {
|
const handleTagMouseDown = (event: React.MouseEvent<HTMLDivElement>, key: string, index: number) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
let targetContainer = event?.currentTarget?.parentElement?.parentElement;
|
let targetContainer = event?.currentTarget?.parentElement?.parentElement;
|
||||||
|
|
||||||
console.log(targetContainer, "targetContainer line 421")
|
|
||||||
|
|
||||||
let targetElement = event?.currentTarget?.parentElement;
|
let targetElement = event?.currentTarget?.parentElement;
|
||||||
|
|
||||||
if (!targetContainer || !targetElement) return;
|
if (!targetContainer || !targetElement) return;
|
||||||
|
|
@ -450,9 +457,11 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
|
||||||
groupId = event.currentTarget.getAttribute("group");
|
groupId = event.currentTarget.getAttribute("group");
|
||||||
}
|
}
|
||||||
|
|
||||||
let groupElements: NodeListOf<HTMLElement> | null = null
|
let groupElements: NodeListOf<HTMLElement> | null = null;
|
||||||
if (isGroupAttr && groupId) {
|
if (isGroupAttr && groupId) {
|
||||||
groupElements = document.querySelectorAll(`div[group="${groupId}"]`);
|
groupElements = document.querySelectorAll(`div[group="${groupId}"]`);
|
||||||
|
// Show initial border position during drag start
|
||||||
|
handleGroupBorderPosition(groupElements, containerRect, offsetX, offsetY);
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleMouseMove = (event: MouseEvent) => {
|
const handleMouseMove = (event: MouseEvent) => {
|
||||||
|
|
@ -460,26 +469,52 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
|
||||||
let left = event.clientX - containerRect.left - offsetX;
|
let left = event.clientX - containerRect.left - offsetX;
|
||||||
let top = event.clientY - containerRect.top - offsetY;
|
let top = event.clientY - containerRect.top - offsetY;
|
||||||
|
|
||||||
|
// Restrict movement within container bounds
|
||||||
// **Restrict movement within container bounds**
|
|
||||||
left = Math.max(0, Math.min(left, conScrollWidth - elementRect.width));
|
left = Math.max(0, Math.min(left, conScrollWidth - elementRect.width));
|
||||||
top = Math.max(0, Math.min(top, conScrollHeight - elementRect.height));
|
top = Math.max(0, Math.min(top, conScrollHeight - elementRect.height));
|
||||||
|
|
||||||
if (groupElements != null && groupElements.length) handleGroupBorderPosition(groupElements, containerRect, offsetX, offsetY);
|
// Apply the movement to the element first
|
||||||
|
setDroppedItems(prevState => ({
|
||||||
// Apply the movement to the element
|
...prevState,
|
||||||
setDroppedItems({
|
[key]: Array.isArray(prevState[key])
|
||||||
...droppedItems,
|
? prevState[key].map((item, i) =>
|
||||||
[key]: Array.isArray(droppedItems[key]) // Ensure it's an array
|
|
||||||
? droppedItems[key].map((item, i) =>
|
|
||||||
i === index ? { ...item, dimensions: { ...item.dimensions, left, top }, update: true } : item
|
i === index ? { ...item, dimensions: { ...item.dimensions, left, top }, update: true } : item
|
||||||
)
|
)
|
||||||
: [], // Provide a fallback in case it's undefined or not an array
|
: [],
|
||||||
});
|
}));
|
||||||
|
|
||||||
|
// Update group border position during drag if it's a group element
|
||||||
|
if (groupElements != null && groupElements.length) {
|
||||||
|
// Use a small timeout to ensure DOM is updated before recalculating borders
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
handleGroupBorderPosition(groupElements!, containerRect, offsetX, offsetY);
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMouseUp = () => {
|
const handleMouseUp = () => {
|
||||||
|
// CRITICAL: Ensure group borders are properly positioned after drag ends
|
||||||
|
if (groupElements != null && groupElements.length && groupId) {
|
||||||
|
// Multiple approaches to ensure the positioning works:
|
||||||
|
|
||||||
|
// 1. Immediate update
|
||||||
|
setTimeout(() => {
|
||||||
|
handleIGroupBorderPosition(groupId);
|
||||||
|
}, 10);
|
||||||
|
|
||||||
|
// 2. Secondary update to ensure it's properly positioned
|
||||||
|
setTimeout(() => {
|
||||||
|
handleIGroupBorderPosition(groupId);
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
// 3. Final update using requestAnimationFrame for DOM sync
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
handleIGroupBorderPosition(groupId);
|
||||||
|
}, 50);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
document.removeEventListener("pointermove", handleMouseMove);
|
document.removeEventListener("pointermove", handleMouseMove);
|
||||||
document.removeEventListener("pointerup", handleMouseUp);
|
document.removeEventListener("pointerup", handleMouseUp);
|
||||||
};
|
};
|
||||||
|
|
@ -550,13 +585,14 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
|
||||||
setSelectedTag({ key, index })
|
setSelectedTag({ key, index })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Updated handleRemoveTag function with your existing API logic and group handling
|
||||||
const handleRemoveTag = (key: string, targetIndex: number) => {
|
const handleRemoveTag = (key: string, targetIndex: number) => {
|
||||||
const tag = droppedItems[key][targetIndex];
|
const tag = droppedItems[key][targetIndex];
|
||||||
const recipientId = tag.recipientId;
|
const recipientId = tag.recipientId;
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
if ("id" in tag) {
|
if ("id" in tag) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
const response = await api.delete(`/api/accounts/${accountId}/${transactionTemplateToggle}/${transactionId}/recipients/${recipientId}/tags/${tag.id}`)
|
const response = await api.delete(`/api/accounts/${accountId}/${transactionTemplateToggle}/${transactionId}/recipients/${recipientId}/tags/${tag.id}`)
|
||||||
if (response.status !== 200) throw "Tag Deletion error"
|
if (response.status !== 200) throw "Tag Deletion error"
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
@ -564,41 +600,302 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setSelectedTag(null)
|
|
||||||
|
setSelectedTag(null);
|
||||||
|
|
||||||
|
// Check if this item has a group for special group handling
|
||||||
|
if ('group' in tag && tag.group) {
|
||||||
|
const groupId = tag.group;
|
||||||
|
|
||||||
|
// Find all items in the same group
|
||||||
|
const groupItems = droppedItems[key]
|
||||||
|
.map((item, idx) => ({ item, index: idx }))
|
||||||
|
.filter(({ item }) => 'group' in item && item.group === groupId && !item.isDeleted);
|
||||||
|
|
||||||
|
// Sort group items by their top position to identify the parent (top-most)
|
||||||
|
groupItems.sort((a, b) => a.item.dimensions.top - b.item.dimensions.top);
|
||||||
|
|
||||||
|
// Check if the item being removed is the parent (top-most item)
|
||||||
|
const isParentItem = groupItems.length > 0 && groupItems[0].index === targetIndex;
|
||||||
|
|
||||||
|
if (isParentItem && groupItems.length > 1) {
|
||||||
|
// If removing the parent and there are child items, mark all items in the group as deleted
|
||||||
|
console.log(`Removing parent item and all children for group: ${groupId}`);
|
||||||
|
|
||||||
|
// Get indices of all group items to mark as deleted
|
||||||
|
const indicesToDelete = groupItems.map(({ index }) => index);
|
||||||
|
|
||||||
|
setDroppedItems(prevState => ({
|
||||||
|
...prevState,
|
||||||
|
[key]: prevState[key].map((item, index) =>
|
||||||
|
indicesToDelete.includes(index) ? { ...item, isDeleted: true } : item
|
||||||
|
)
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Remove group border elements after state update
|
||||||
|
setTimeout(() => {
|
||||||
|
removeGroupBorders(groupId);
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// If removing a child item or the only item in group, just mark this item as deleted
|
||||||
|
console.log(`Removing individual item from group: ${groupId}`);
|
||||||
|
|
||||||
setDroppedItems(prevState => ({
|
setDroppedItems(prevState => ({
|
||||||
...prevState,
|
...prevState,
|
||||||
[key]: prevState[key].map((item, index) =>
|
[key]: prevState[key].map((item, index) =>
|
||||||
index === targetIndex ? { ...item, isDeleted: true } : item
|
index === targetIndex ? { ...item, isDeleted: true } : item
|
||||||
)
|
)
|
||||||
}));
|
}));
|
||||||
})()
|
|
||||||
|
// Check if this was the last item in the group after state update
|
||||||
|
setTimeout(() => {
|
||||||
|
const remainingGroupItems = droppedItems[key].filter(item =>
|
||||||
|
'group' in item && item.group === groupId && !item.isDeleted
|
||||||
|
);
|
||||||
|
|
||||||
|
if (remainingGroupItems.length === 0) {
|
||||||
|
// Remove group borders if no items left
|
||||||
|
removeGroupBorders(groupId);
|
||||||
|
} else {
|
||||||
|
// Update group borders for remaining items
|
||||||
|
handleIGroupBorderPosition(groupId);
|
||||||
}
|
}
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Handle non-group item removal (your existing logic)
|
||||||
|
setDroppedItems(prevState => ({
|
||||||
|
...prevState,
|
||||||
|
[key]: prevState[key].map((item, index) =>
|
||||||
|
index === targetIndex ? { ...item, isDeleted: true } : item
|
||||||
|
)
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper function to remove group border elements from DOM
|
||||||
|
const removeGroupBorders = (groupId: string) => {
|
||||||
|
console.log(`Removing borders for group: ${groupId}`);
|
||||||
|
|
||||||
|
const borderPositions = ['top', 'right', 'bottom', 'left'];
|
||||||
|
|
||||||
|
borderPositions.forEach(position => {
|
||||||
|
const borderElement = document.querySelector(`[border-group='${groupId}'][border-pos='${position}']`);
|
||||||
|
if (borderElement && borderElement.parentNode) {
|
||||||
|
borderElement.parentNode.removeChild(borderElement);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// const handleAddRadioClick = (key:string) => {
|
// const handleAddRadioClick = (key:string) => {
|
||||||
// console.log("Handle Radio Clicled", key)
|
// console.log("Handle Radio Clicled", key)
|
||||||
// console.log(droppedItems, "line 525")
|
// console.log(droppedItems, "line 525")
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
const handleIGroupBorderPosition = (groupId: string) => {
|
||||||
|
console.log("handleIGroupBorderPosition for group:", groupId);
|
||||||
|
|
||||||
const handleAddGroupItemClicked = (key: string, item) => {
|
const groupElements: NodeListOf<HTMLElement> = document.querySelectorAll(`div[group="${groupId}"]`);
|
||||||
|
|
||||||
|
if (groupElements.length === 0) {
|
||||||
|
console.log("No group elements found for:", groupId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let targetContainer = groupElements[0].parentElement?.parentElement;
|
||||||
|
|
||||||
|
if (!targetContainer) {
|
||||||
|
console.log("No target container found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const containerRect = targetContainer.getBoundingClientRect();
|
||||||
|
|
||||||
|
// Use consistent offset values
|
||||||
|
const offsetX = 10;
|
||||||
|
const offsetY = 10;
|
||||||
|
|
||||||
|
// Ensure DOM is fully updated before positioning
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
handleGroupBorderPosition(groupElements, containerRect, offsetX, offsetY);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Enhanced handleGroupBorderPosition with better positioning logic
|
||||||
|
const handleGroupBorderPosition = (groupElements: NodeListOf<HTMLElement>, containerRect: DOMRect, offsetX: number, offsetY: number) => {
|
||||||
|
if (!groupElements || groupElements.length === 0) return;
|
||||||
|
|
||||||
|
const groupId = groupElements[0].getAttribute('group');
|
||||||
|
if (!groupId) return;
|
||||||
|
|
||||||
|
// Calculate the bounding box of all group elements
|
||||||
|
let minLeft = Infinity, minTop = Infinity, maxRight = -Infinity, maxBottom = -Infinity;
|
||||||
|
|
||||||
|
groupElements.forEach(element => {
|
||||||
|
const parentElement = element.parentElement;
|
||||||
|
if (!parentElement) return;
|
||||||
|
|
||||||
|
const rect = parentElement.getBoundingClientRect();
|
||||||
|
const relativeLeft = rect.left - containerRect.left;
|
||||||
|
const relativeTop = rect.top - containerRect.top;
|
||||||
|
const relativeRight = relativeLeft + rect.width;
|
||||||
|
const relativeBottom = relativeTop + rect.height;
|
||||||
|
|
||||||
|
minLeft = Math.min(minLeft, relativeLeft);
|
||||||
|
minTop = Math.min(minTop, relativeTop);
|
||||||
|
maxRight = Math.max(maxRight, relativeRight);
|
||||||
|
maxBottom = Math.max(maxBottom, relativeBottom);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add some padding around the group
|
||||||
|
const padding = 10;
|
||||||
|
minLeft -= padding;
|
||||||
|
minTop -= padding;
|
||||||
|
maxRight += padding;
|
||||||
|
maxBottom += padding;
|
||||||
|
|
||||||
|
const width = maxRight - minLeft;
|
||||||
|
const height = maxBottom - minTop;
|
||||||
|
|
||||||
|
// Update or create border elements
|
||||||
|
const borderPositions = ['top', 'right', 'bottom', 'left'];
|
||||||
|
|
||||||
|
borderPositions.forEach(position => {
|
||||||
|
let borderElement = document.querySelector(`[border-group='${groupId}'][border-pos='${position}']`) as HTMLElement;
|
||||||
|
|
||||||
|
if (!borderElement) {
|
||||||
|
// Create border element if it doesn't exist
|
||||||
|
borderElement = document.createElement('div');
|
||||||
|
borderElement.className = `group-border ${position === 'bottom' ? 'bottom-border' : ''}`;
|
||||||
|
borderElement.setAttribute('border-group', groupId);
|
||||||
|
borderElement.setAttribute('border-pos', position);
|
||||||
|
|
||||||
|
// Add the + icon for bottom border
|
||||||
|
if (position === 'bottom') {
|
||||||
|
const addIcon = document.createElement('div');
|
||||||
|
addIcon.innerHTML = '<IoAdd />'; // You might need to adjust this based on your icon system
|
||||||
|
addIcon.onclick = () => {
|
||||||
|
// Find the original item to pass to handleAddGroupItemClicked
|
||||||
|
const originalItem = droppedItems[key]?.find(item => 'group' in item && item.group === groupId);
|
||||||
|
if (originalItem) {
|
||||||
|
handleAddGroupItemClicked(key, originalItem);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
borderElement.appendChild(addIcon);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append to container
|
||||||
|
groupElements[0].parentElement?.parentElement?.appendChild(borderElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Position the border element
|
||||||
|
borderElement.style.position = 'absolute';
|
||||||
|
borderElement.style.pointerEvents = position === 'bottom' ? 'auto' : 'none';
|
||||||
|
|
||||||
|
switch (position) {
|
||||||
|
case 'top':
|
||||||
|
borderElement.style.left = `${minLeft}px`;
|
||||||
|
borderElement.style.top = `${minTop}px`;
|
||||||
|
borderElement.style.width = `${width}px`;
|
||||||
|
borderElement.style.height = '2px';
|
||||||
|
break;
|
||||||
|
case 'right':
|
||||||
|
borderElement.style.left = `${maxRight - 2}px`;
|
||||||
|
borderElement.style.top = `${minTop}px`;
|
||||||
|
borderElement.style.width = '2px';
|
||||||
|
borderElement.style.height = `${height}px`;
|
||||||
|
break;
|
||||||
|
case 'bottom':
|
||||||
|
borderElement.style.left = `${minLeft}px`;
|
||||||
|
borderElement.style.top = `${maxBottom - 2}px`;
|
||||||
|
borderElement.style.width = `${width}px`;
|
||||||
|
borderElement.style.height = '2px';
|
||||||
|
break;
|
||||||
|
case 'left':
|
||||||
|
borderElement.style.left = `${minLeft}px`;
|
||||||
|
borderElement.style.top = `${minTop}px`;
|
||||||
|
borderElement.style.width = '2px';
|
||||||
|
borderElement.style.height = `${height}px`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAddGroupItemClicked = (key: string, item: any) => {
|
||||||
|
console.log("handleAddGroupItemClicked", item);
|
||||||
|
|
||||||
const groupId = item.group;
|
const groupId = item.group;
|
||||||
|
|
||||||
item = { ...item, dimensions: { ...item.dimensions, top: item.dimensions.top + item.dimensions.height + 20 } }
|
// Find all existing items in this group to determine the bottom-most position
|
||||||
|
const existingGroupItems = droppedItems[key]?.filter(existingItem =>
|
||||||
|
'group' in existingItem && existingItem.group === groupId
|
||||||
|
) || [];
|
||||||
|
|
||||||
// dimensions: { ...item.dimensions, left: newLeft, top: newTop }
|
// Find the bottom-most item in the group
|
||||||
|
let bottomMostItem = item;
|
||||||
setTimeout(() => {
|
if (existingGroupItems.length > 0) {
|
||||||
handleIGroupBorderPosition(item.group)
|
bottomMostItem = existingGroupItems.reduce((lowest, current) => {
|
||||||
}, 0)
|
const currentBottom = current.dimensions.top + current.dimensions.height;
|
||||||
|
const lowestBottom = lowest.dimensions.top + lowest.dimensions.height;
|
||||||
setDroppedItems({
|
return currentBottom > lowestBottom ? current : lowest;
|
||||||
...droppedItems,
|
|
||||||
[key]: [...droppedItems[key], { ...item, isGroupExist: true }],
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate new position: place below the bottom-most item
|
||||||
|
const spacing = 10; // Adjust spacing as needed
|
||||||
|
const newTop = bottomMostItem.dimensions.top + bottomMostItem.dimensions.height + spacing;
|
||||||
|
|
||||||
|
// Use the same left position as the parent (original) item
|
||||||
|
const newItem = {
|
||||||
|
...item,
|
||||||
|
dimensions: {
|
||||||
|
...item.dimensions,
|
||||||
|
left: item.dimensions.left, // Keep same horizontal position as parent
|
||||||
|
top: newTop // Position below the bottom-most item
|
||||||
|
},
|
||||||
|
isGroupExist: true
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update the dropped items
|
||||||
|
setDroppedItems({
|
||||||
|
...droppedItems,
|
||||||
|
[key]: [...droppedItems[key], newItem],
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update group borders after adding the new item
|
||||||
|
// Use setTimeout to ensure state update is processed
|
||||||
|
setTimeout(() => {
|
||||||
|
handleIGroupBorderPosition(groupId);
|
||||||
|
}, 50); // Slightly longer timeout to ensure DOM updates
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Initialize group borders for all existing groups after component updates
|
||||||
|
const timeoutId = setTimeout(() => {
|
||||||
|
const allGroupElements = document.querySelectorAll('[group]');
|
||||||
|
const groupIds = new Set<string>();
|
||||||
|
|
||||||
|
allGroupElements.forEach((element) => {
|
||||||
|
const groupId = element.getAttribute('group');
|
||||||
|
if (groupId) {
|
||||||
|
groupIds.add(groupId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
groupIds.forEach((groupId) => {
|
||||||
|
handleIGroupBorderPosition(groupId);
|
||||||
|
});
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
return () => clearTimeout(timeoutId);
|
||||||
|
}, [droppedItems]); // Re-run when droppedItems changes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// const handleAddRadio = (e: React.MouseEvent<HTMLElement>, key: string, index: number) => {
|
// const handleAddRadio = (e: React.MouseEvent<HTMLElement>, key: string, index: number) => {
|
||||||
// // const dataToSet: DroppedItemsObj = {
|
// // const dataToSet: DroppedItemsObj = {
|
||||||
|
|
@ -702,6 +999,7 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
|
||||||
|
|
||||||
|
|
||||||
// NEW DIRECTIONAL MOVEMENT HANDLER - START
|
// NEW DIRECTIONAL MOVEMENT HANDLER - START
|
||||||
|
|
||||||
const handleDirectionalMove = (direction: 'up' | 'down' | 'left' | 'right', stepSize: number = 5) => {
|
const handleDirectionalMove = (direction: 'up' | 'down' | 'left' | 'right', stepSize: number = 5) => {
|
||||||
if (!selectedTag) return;
|
if (!selectedTag) return;
|
||||||
|
|
||||||
|
|
@ -740,28 +1038,43 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create a wrapper that matches DirectionalControls' expected signature
|
|
||||||
const directionalControlsHandler = (direction: 'up' | 'down' | 'left' | 'right') => {
|
const directionalControlsHandler = (direction: 'up' | 'down' | 'left' | 'right') => {
|
||||||
handleDirectionalMove(direction, 5); // Use default stepSize of 5
|
handleDirectionalMove(direction, 5); // Use default stepSize of 5
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Add this new handler function to your parent component
|
||||||
|
const handleDirectPositionChange = (newLeft: number, newTop: number) => {
|
||||||
|
console.log("handleDirectPositionChange",newLeft,newTop)
|
||||||
|
if (!selectedTag) return;
|
||||||
|
|
||||||
|
const { key, index } = selectedTag;
|
||||||
|
const currentItem = droppedItems[key]?.[index];
|
||||||
|
|
||||||
|
if (!currentItem) return;
|
||||||
|
|
||||||
function handleIGroupBorderPosition(groupId: string) {
|
// Ensure values are not negative
|
||||||
|
const clampedLeft = Math.max(0, newLeft);
|
||||||
|
const clampedTop = Math.max(0, newTop);
|
||||||
|
|
||||||
const groupElements: NodeListOf<HTMLElement> = document.querySelectorAll(`div[group="${groupId}"]`);
|
setDroppedItems({
|
||||||
|
...droppedItems,
|
||||||
let targetContainer = groupElements[0].parentElement?.parentElement;
|
[key]: Array.isArray(droppedItems[key])
|
||||||
console.log(targetContainer, "targetContainer line 421")
|
? droppedItems[key].map((item, i) =>
|
||||||
let targetElement = groupElements[0].parentElement;
|
i === index
|
||||||
|
? {
|
||||||
if (!targetContainer || !targetElement) return;
|
...item,
|
||||||
const containerRect = targetContainer.getBoundingClientRect();
|
dimensions: {
|
||||||
|
...item.dimensions,
|
||||||
handleGroupBorderPosition(groupElements, containerRect, 40, 40);
|
left: clampedLeft,
|
||||||
|
top: clampedTop
|
||||||
|
},
|
||||||
|
update: true
|
||||||
}
|
}
|
||||||
|
: item
|
||||||
|
)
|
||||||
|
: [],
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
@ -815,7 +1128,7 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
|
||||||
|
|
||||||
{/* If Selected Tag Recipient Info- START */}
|
{/* If Selected Tag Recipient Info- START */}
|
||||||
{selectedTag?.key && selectedTag.key === key && selectedTag.index === index &&
|
{selectedTag?.key && selectedTag.key === key && selectedTag.index === index &&
|
||||||
<div className='absolute flex justify-between items-center w-full max-w-max bg-white top-[-22px] shadow z-20 text-sm rounded-t-sm'>
|
<div className='absolute flex justify-between items-center w-full max-w-max bg-white top-[-22px] shadow z-20 text-sm rounded-t-sm' >
|
||||||
<div className='flex justify-center items-center gap-1 bg-white px-2 shadow'>
|
<div className='flex justify-center items-center gap-1 bg-white px-2 shadow'>
|
||||||
<p className='w-2.5 h-2.5 rounded'
|
<p className='w-2.5 h-2.5 rounded'
|
||||||
style={{ background: selectedRecipient[0]?.color }}
|
style={{ background: selectedRecipient[0]?.color }}
|
||||||
|
|
@ -922,6 +1235,7 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
|
||||||
|
|
||||||
{selectedTag && <RightSideBar selectedTag={droppedItems[selectedTag.key][selectedTag.index]} setDroppedItems={setDroppedItems} selTagKey={selectedTag.key} selTagIndx={selectedTag.index} DirectionalControlsProps={{
|
{selectedTag && <RightSideBar selectedTag={droppedItems[selectedTag.key][selectedTag.index]} setDroppedItems={setDroppedItems} selTagKey={selectedTag.key} selTagIndx={selectedTag.index} DirectionalControlsProps={{
|
||||||
onMove: directionalControlsHandler,
|
onMove: directionalControlsHandler,
|
||||||
|
onPositionChange: handleDirectPositionChange,
|
||||||
disabled: false,
|
disabled: false,
|
||||||
stepSize: 5,
|
stepSize: 5,
|
||||||
className: ''
|
className: ''
|
||||||
|
|
@ -929,6 +1243,6 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
|
||||||
{/* Center Doc Container - END */}
|
{/* Center Doc Container - END */}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DocumentContainer;
|
export default DocumentContainer;
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@ interface CommonAttrDropDownInt {
|
||||||
|
|
||||||
const CommonAttrDropDown: React.FC<CommonAttrDropDownInt> = ({selectedType, subType, dropDownToggle, setDropDownToggle, handlePropertyChange}) => {
|
const CommonAttrDropDown: React.FC<CommonAttrDropDownInt> = ({selectedType, subType, dropDownToggle, setDropDownToggle, handlePropertyChange}) => {
|
||||||
|
|
||||||
|
console.log("selectedType, subType,",selectedType, subType)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<label htmlFor="" className="">Type</label>
|
<label htmlFor="" className="">Type</label>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import React, { useEffect, useRef } from 'react';
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
import { FaArrowUp, FaArrowDown, FaArrowLeft, FaArrowRight, FaRegCircle } from 'react-icons/fa';
|
import { FaArrowUp, FaArrowDown, FaArrowLeft, FaArrowRight } from 'react-icons/fa';
|
||||||
|
|
||||||
interface DirectionalControlsProps {
|
interface DirectionalControlsProps {
|
||||||
onMove: (direction: 'up' | 'down' | 'left' | 'right', stepSize?: number) => void;
|
onMove: (direction: 'up' | 'down' | 'left' | 'right', stepSize?: number) => void;
|
||||||
|
onPositionChange?: (left: number, top: number) => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
stepSize?: number;
|
stepSize?: number;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
|
@ -16,23 +17,67 @@ interface DirectionalControlsProps {
|
||||||
|
|
||||||
const DirectionalControls: React.FC<DirectionalControlsProps> = ({
|
const DirectionalControls: React.FC<DirectionalControlsProps> = ({
|
||||||
onMove,
|
onMove,
|
||||||
|
onPositionChange,
|
||||||
disabled = false,
|
disabled = false,
|
||||||
stepSize = 1,
|
stepSize = 1,
|
||||||
className = '',
|
className = '',
|
||||||
selectedType,
|
selectedType,
|
||||||
}) => {
|
}) => {
|
||||||
const onMoveRef = useRef(onMove);
|
const onMoveRef = useRef(onMove);
|
||||||
|
const [leftValue, setLeftValue] = useState('');
|
||||||
|
const [topValue, setTopValue] = useState('');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
onMoveRef.current = onMove;
|
onMoveRef.current = onMove;
|
||||||
}, [onMove]);
|
}, [onMove]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const { top = 0, left = 0 } = selectedType || {};
|
||||||
|
setLeftValue(Math.round(left).toString());
|
||||||
|
setTopValue(Math.round(top).toString());
|
||||||
|
}, [selectedType]);
|
||||||
|
|
||||||
const handleMove = (direction: 'up' | 'down' | 'left' | 'right') => {
|
const handleMove = (direction: 'up' | 'down' | 'left' | 'right') => {
|
||||||
if (!disabled) {
|
if (!disabled) {
|
||||||
onMoveRef.current(direction, stepSize);
|
onMoveRef.current(direction, stepSize);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handlePositionInputChange = (type: 'left' | 'top', value: string) => {
|
||||||
|
if (type === 'left') {
|
||||||
|
setLeftValue(value);
|
||||||
|
} else {
|
||||||
|
setTopValue(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePositionInputBlur = (type: 'left' | 'top') => {
|
||||||
|
if (!onPositionChange) return;
|
||||||
|
|
||||||
|
const numericValue = parseFloat(type === 'left' ? leftValue : topValue);
|
||||||
|
if (isNaN(numericValue)) {
|
||||||
|
const { top = 0, left = 0 } = selectedType || {};
|
||||||
|
if (type === 'left') {
|
||||||
|
setLeftValue(Math.round(left).toString());
|
||||||
|
} else {
|
||||||
|
setTopValue(Math.round(top).toString());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { top = 0, left = 0 } = selectedType || {};
|
||||||
|
const newLeft = type === 'left' ? numericValue : left;
|
||||||
|
const newTop = type === 'top' ? numericValue : top;
|
||||||
|
|
||||||
|
onPositionChange(newLeft, newTop);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleKeyPress = (e: React.KeyboardEvent, type: 'left' | 'top') => {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
handlePositionInputBlur(type);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleKeyDown = (event: KeyboardEvent) => {
|
const handleKeyDown = (event: KeyboardEvent) => {
|
||||||
if (disabled) return;
|
if (disabled) return;
|
||||||
|
|
@ -66,55 +111,111 @@ const DirectionalControls: React.FC<DirectionalControlsProps> = ({
|
||||||
${disabled
|
${disabled
|
||||||
? 'bg-gray-100 text-gray-400 cursor-not-allowed'
|
? 'bg-gray-100 text-gray-400 cursor-not-allowed'
|
||||||
: 'bg-white text-gray-600 hover:bg-blue-100 active:bg-blue-200 cursor-pointer'}
|
: 'bg-white text-gray-600 hover:bg-blue-100 active:bg-blue-200 cursor-pointer'}
|
||||||
flex items-center justify-center w-6 h-6
|
flex items-center justify-center w-6 h-6 `;
|
||||||
`;
|
|
||||||
|
|
||||||
|
const inputClass = `
|
||||||
|
w-12 h-6 text-[10px] text-center border rounded px-1 bg-white
|
||||||
|
${disabled
|
||||||
|
? 'bg-gray-100 text-gray-400 cursor-not-allowed border-gray-300'
|
||||||
|
: 'text-gray-600 border-gray-300 focus:border-blue-400 focus:outline-none'}
|
||||||
|
`;
|
||||||
|
|
||||||
const { top = 0, left = 0, width = 0, height = 0 } = selectedType || {};
|
const { top = 0, left = 0, width = 0, height = 0 } = selectedType || {};
|
||||||
|
|
||||||
const right = left + width;
|
|
||||||
const bottom = top + height;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`grid grid-cols-3 grid-rows-1 text-[10px] text-gray-700 ${className}`}>
|
<div className={`flex flex-col items-center space-y-4 text-[10px] text-gray-700 ${className}`}>
|
||||||
{/* Top Row */}
|
{/* Top Button */}
|
||||||
<div></div>
|
<div className="flex justify-center me-4">
|
||||||
<div className="flex flex-col items-center">
|
<div className="flex flex-col items-center">
|
||||||
<button onClick={() => handleMove('up')} disabled={disabled} className={buttonClass} title="Move up" type="button">
|
<button
|
||||||
|
onClick={() => handleMove('up')}
|
||||||
|
disabled={disabled}
|
||||||
|
className={buttonClass}
|
||||||
|
title="Move up"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
<FaArrowUp size={12} />
|
<FaArrowUp size={12} />
|
||||||
</button>
|
</button>
|
||||||
<span className="mt-1">Top: {Math.round(top)}px</span>
|
<span className="mt-1">Top</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div></div>
|
|
||||||
|
|
||||||
{/* Middle Row */}
|
{/* Middle Row: Left - Center (Inputs) - Right */}
|
||||||
<div className="flex flex-col items-center justify-center">
|
<div className="flex items-center space-x-1">
|
||||||
<button onClick={() => handleMove('left')} disabled={disabled} className={buttonClass} title="Move left" type="button">
|
{/* Left Button */}
|
||||||
|
<div className="flex flex-col items-center">
|
||||||
|
<button
|
||||||
|
onClick={() => handleMove('left')}
|
||||||
|
disabled={disabled}
|
||||||
|
className={buttonClass}
|
||||||
|
title="Move left"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
<FaArrowLeft size={12} />
|
<FaArrowLeft size={12} />
|
||||||
</button>
|
</button>
|
||||||
<span className="mt-1">Left: {Math.round(left)}px</span>
|
<span className="mt-1">Left</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="w-8 h-8 flex items-center justify-center text-xs text-gray-400 ps-5"><FaRegCircle/></div>
|
{/* Center Panel */}
|
||||||
|
<div className="relative flex items-center justify-center bg-white rounded-lg px-1 py-2 w-24">
|
||||||
|
{/* Floating dimensions tooltip */}
|
||||||
|
<div className="absolute -top-2 left-1/2 -translate-x-1/2 px-2 py-[1px] text-[10px] font-mono text-black z-10 rounded-sm flex items-center gap-[2px]">
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
value={leftValue}
|
||||||
|
onChange={(e) => handlePositionInputChange('left', e.target.value)}
|
||||||
|
onBlur={() => handlePositionInputBlur('left')}
|
||||||
|
onKeyPress={(e) => handleKeyPress(e, 'left')}
|
||||||
|
disabled={disabled}
|
||||||
|
className="w-[40px] h-[16px] text-[10px] text-center border-none focus:outline-none text-black font-mono"
|
||||||
|
/>
|
||||||
|
<span className="mx-[1px]">×</span>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
value={topValue}
|
||||||
|
onChange={(e) => handlePositionInputChange('top', e.target.value)}
|
||||||
|
onBlur={() => handlePositionInputBlur('top')}
|
||||||
|
onKeyPress={(e) => handleKeyPress(e, 'top')}
|
||||||
|
disabled={disabled}
|
||||||
|
className="w-[40px] h-[16px] text-[10px] text-center border-none focus:outline-none text-black font-mono"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col items-center justify-center">
|
|
||||||
<button onClick={() => handleMove('right')} disabled={disabled} className={buttonClass} title="Move right" type="button">
|
{/* Right Button */}
|
||||||
|
<div className="flex flex-col items-center">
|
||||||
|
<button
|
||||||
|
onClick={() => handleMove('right')}
|
||||||
|
disabled={disabled}
|
||||||
|
className={buttonClass}
|
||||||
|
title="Move right"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
<FaArrowRight size={12} />
|
<FaArrowRight size={12} />
|
||||||
</button>
|
</button>
|
||||||
{/* <span className="mt-1">Right: {Math.round(right)}px</span> */}
|
<span className="mt-1">Right</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Bottom Row */}
|
{/* Bottom Button */}
|
||||||
<div></div>
|
<div className="flex justify-center me-4">
|
||||||
<div className="flex flex-col items-center">
|
<div className="flex flex-col items-center">
|
||||||
<button onClick={() => handleMove('down')} disabled={disabled} className={buttonClass} title="Move down" type="button">
|
<button
|
||||||
|
onClick={() => handleMove('down')}
|
||||||
|
disabled={disabled}
|
||||||
|
className={buttonClass}
|
||||||
|
title="Move down"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
<FaArrowDown size={12} />
|
<FaArrowDown size={12} />
|
||||||
</button>
|
</button>
|
||||||
{/* <span className="mt-1">Bottom: {Math.round(bottom)}px</span> */}
|
<span className="mt-1">Bottom</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div></div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DirectionalControls;
|
export default DirectionalControls;
|
||||||
|
|
@ -107,7 +107,7 @@ const RightSideBar: React.FC<DroppedItemProps> = ({ selectedTag, setDroppedItems
|
||||||
|
|
||||||
const selectedType = selectedTag.type in enumMap && enumMap[selectedTag.type as keyof typeof enumMap];
|
const selectedType = selectedTag.type in enumMap && enumMap[selectedTag.type as keyof typeof enumMap];
|
||||||
|
|
||||||
// console.log("selectedTag", selectedTag, selectedType)
|
console.log("selectedTag", selectedTag, selectedType)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -118,25 +118,33 @@ const RightSideBar: React.FC<DroppedItemProps> = ({ selectedTag, setDroppedItems
|
||||||
const [styleOpen, setStyleOpen] = useState(false);
|
const [styleOpen, setStyleOpen] = useState(false);
|
||||||
|
|
||||||
const handlePropertyChange = (changeTo: string, changeWith: string | boolean | number, is24Hrs = null) => {
|
const handlePropertyChange = (changeTo: string, changeWith: string | boolean | number, is24Hrs = null) => {
|
||||||
console.log("Handle Property Change Called", "changeTo", changeTo, "changeWith", changeWith)
|
|
||||||
|
console.log("changeTo", changeTo, "changeWith", changeWith)
|
||||||
if (changeTo === '' || changeWith === '') return
|
if (changeTo === '' || changeWith === '') return
|
||||||
|
|
||||||
|
if (changeWith === "paragraph") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (changeTo === "subType" && (changeWith === TEMPORAL.DATE || changeWith === TEMPORAL.DATE_TIME || changeWith === TEMPORAL.TIME)) {
|
if (changeTo === "subType" && (changeWith === TEMPORAL.DATE || changeWith === TEMPORAL.DATE_TIME || changeWith === TEMPORAL.TIME)) {
|
||||||
// let change: string = changeWith;
|
// let change: string = changeWith;
|
||||||
// if (change === "DATE TIME") {
|
// if (change === "DATE TIME") {
|
||||||
// change = "DATE_TIME"
|
// change = "DATE_TIME"
|
||||||
// }
|
// }
|
||||||
setDroppedItems((prev) => (
|
setDroppedItems((prev) => {
|
||||||
{
|
console.log("Temporal30", prev);
|
||||||
|
return {
|
||||||
...prev,
|
...prev,
|
||||||
[selTagKey]: Array.isArray(prev[selTagKey]) // Ensure it's an array
|
[selTagKey]: Array.isArray(prev[selTagKey]) // Ensure it's an array
|
||||||
? prev[selTagKey].map((item, i) =>
|
? prev[selTagKey].map((item, i) =>
|
||||||
i === selTagIndx ? { ...item, [changeTo]: changeWith || "", format: "", update: true } : item
|
i === selTagIndx ? { ...item, [changeTo]: changeWith || "", format: "", update: true } : item
|
||||||
)
|
)
|
||||||
: [],
|
: [], // Fallback in case it's undefined or not an array
|
||||||
}// Provide a fallback in case it's undefined or not an array
|
};
|
||||||
));
|
});
|
||||||
|
|
||||||
} else if (changeTo === "subType" && typeof changeWith === "string" && changeWith.toLowerCase() === "password") {
|
} else if (changeTo === "subType" && typeof changeWith === "string" && changeWith.toLowerCase() === "password") {
|
||||||
|
console.log("Second check")
|
||||||
console.log("Line 161")
|
console.log("Line 161")
|
||||||
setDroppedItems((prev) => (
|
setDroppedItems((prev) => (
|
||||||
{
|
{
|
||||||
|
|
@ -150,6 +158,7 @@ const RightSideBar: React.FC<DroppedItemProps> = ({ selectedTag, setDroppedItems
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
else if (changeTo === "subType" && (changeWith === NUMBER.CURRENCY || changeWith === NUMBER.INTEGER || changeWith === NUMBER.DECIMAL)) {
|
else if (changeTo === "subType" && (changeWith === NUMBER.CURRENCY || changeWith === NUMBER.INTEGER || changeWith === NUMBER.DECIMAL)) {
|
||||||
|
console.log("Third check")
|
||||||
let decPlace = changeWith !== NUMBER.DECIMAL ? 0 : decimalPlace;
|
let decPlace = changeWith !== NUMBER.DECIMAL ? 0 : decimalPlace;
|
||||||
const isCurrency = changeWith === NUMBER.CURRENCY;
|
const isCurrency = changeWith === NUMBER.CURRENCY;
|
||||||
// const currencyType = null
|
// const currencyType = null
|
||||||
|
|
@ -166,24 +175,34 @@ const RightSideBar: React.FC<DroppedItemProps> = ({ selectedTag, setDroppedItems
|
||||||
));
|
));
|
||||||
|
|
||||||
} else if (changeTo === "format" && selectedTag.subType === TEMPORAL.DATE_TIME) {
|
} else if (changeTo === "format" && selectedTag.subType === TEMPORAL.DATE_TIME) {
|
||||||
|
console.log("Fourth Check")
|
||||||
let val = timeFormats[0].format;
|
let val = timeFormats[0].format;
|
||||||
if (!is24Hrs) {
|
if (!is24Hrs) {
|
||||||
val = timeFormats[1].format
|
val = timeFormats[1].format
|
||||||
}
|
}
|
||||||
setDroppedItems((prev) => (
|
console.log("val", val)
|
||||||
{
|
|
||||||
|
setDroppedItems((prev) => {
|
||||||
|
const updatedArray = Array.isArray(prev[selTagKey])
|
||||||
|
? prev[selTagKey].map((item, i) => {
|
||||||
|
if (i === selTagIndx) {
|
||||||
|
const updatedItem = { ...item, [changeTo]: changeWith + " " + val, update: true };
|
||||||
|
console.log('Updating item at index', i, 'with:', updatedItem);
|
||||||
|
return updatedItem;
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
})
|
||||||
|
: [];
|
||||||
|
|
||||||
|
return {
|
||||||
...prev,
|
...prev,
|
||||||
[selTagKey]: Array.isArray(prev[selTagKey]) // Ensure it's an array
|
[selTagKey]: updatedArray,
|
||||||
? prev[selTagKey].map((item, i) =>
|
};
|
||||||
i === selTagIndx ? { ...item, [changeTo]: changeWith + " " + val, update: true } : item
|
});
|
||||||
)
|
|
||||||
: [],
|
|
||||||
}// Provide a fallback in case it's undefined or not an array
|
|
||||||
));
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
setDroppedItems((prev) => {
|
setDroppedItems((prev) => {
|
||||||
console.log('Previous state:', prev);
|
|
||||||
|
|
||||||
const updatedItems = Array.isArray(prev[selTagKey])
|
const updatedItems = Array.isArray(prev[selTagKey])
|
||||||
? prev[selTagKey].map((item, i) =>
|
? prev[selTagKey].map((item, i) =>
|
||||||
|
|
@ -302,7 +321,7 @@ const RightSideBar: React.FC<DroppedItemProps> = ({ selectedTag, setDroppedItems
|
||||||
<RecipientsAttrCon selectedRecipientId={selectedTag.recipientId} handlePropertyChange={handlePropertyChange} />
|
<RecipientsAttrCon selectedRecipientId={selectedTag.recipientId} handlePropertyChange={handlePropertyChange} />
|
||||||
}
|
}
|
||||||
|
|
||||||
<DirectionalControls {...DirectionalControlsProps} selectedType={selectedTag.dimensions}/>
|
<DirectionalControls {...DirectionalControlsProps} selectedType={selectedTag.dimensions} />
|
||||||
|
|
||||||
|
|
||||||
{selectedTag.label &&
|
{selectedTag.label &&
|
||||||
|
|
@ -388,7 +407,7 @@ const RightSideBar: React.FC<DroppedItemProps> = ({ selectedTag, setDroppedItems
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{
|
{(selectedTag.type.toLowerCase() !== TagsTypes.SIGNATURE && selectedTag.type.toLowerCase() !== TagsTypes.INITIALS) &&
|
||||||
<div className="">
|
<div className="">
|
||||||
<div className="flex items-center justify-between mr-2 cursor-pointer"
|
<div className="flex items-center justify-between mr-2 cursor-pointer"
|
||||||
onClick={() => setStyleOpen(!styleOpen)}
|
onClick={() => setStyleOpen(!styleOpen)}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@ interface TemporalDateAttrInt {
|
||||||
}
|
}
|
||||||
|
|
||||||
const TemporalDateAttr: React.FC<TemporalDateAttrInt> = ({ subType, format, dropDownToggle, setDropDownToggle, handlePropertyChange }) => {
|
const TemporalDateAttr: React.FC<TemporalDateAttrInt> = ({ subType, format, dropDownToggle, setDropDownToggle, handlePropertyChange }) => {
|
||||||
|
|
||||||
|
|
||||||
const [is24Hrs, setIs24Hrs] = useState<boolean>(true);
|
const [is24Hrs, setIs24Hrs] = useState<boolean>(true);
|
||||||
|
|
||||||
const handleIs24HrsClick = (checked: boolean) => {
|
const handleIs24HrsClick = (checked: boolean) => {
|
||||||
|
|
@ -84,6 +86,7 @@ const TemporalDateAttr: React.FC<TemporalDateAttrInt> = ({ subType, format, drop
|
||||||
val = val + " " + timeFormats[1].format;
|
val = val + " " + timeFormats[1].format;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
console.log('line 89' , val )
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={indx}
|
key={indx}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import DrawSignatureCanvas from './DrawSignatureCanvas';
|
||||||
import { FaSpinner } from "react-icons/fa";
|
import { FaSpinner } from "react-icons/fa";
|
||||||
import { GrCheckboxSelected } from "react-icons/gr";
|
import { GrCheckboxSelected } from "react-icons/gr";
|
||||||
import { Bounce, toast } from "react-toastify";
|
import { Bounce, toast } from "react-toastify";
|
||||||
|
import { FiCheck } from 'react-icons/fi';
|
||||||
|
|
||||||
interface Signature {
|
interface Signature {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
@ -54,7 +55,7 @@ const AddSignatureModal: React.FC<AddSignatureModalProps> = ({
|
||||||
getAllSignatures,
|
getAllSignatures,
|
||||||
editingSignature
|
editingSignature
|
||||||
}) => {
|
}) => {
|
||||||
const [activeTab, setActiveTab] = useState<'TYPE' | 'DRAW' | 'UPLOAD' | 'SELECT'>('TYPE');
|
const [activeTab, setActiveTab] = useState<'TYPE' | 'DRAW' | 'UPLOAD' >('TYPE');
|
||||||
const [fullName, setFullName] = useState('');
|
const [fullName, setFullName] = useState('');
|
||||||
const [initials, setInitials] = useState('');
|
const [initials, setInitials] = useState('');
|
||||||
const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
|
const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
|
||||||
|
|
@ -72,6 +73,10 @@ const AddSignatureModal: React.FC<AddSignatureModalProps> = ({
|
||||||
{ id: 6, name: 'classic', initials: 'LA', style: 'classic' },
|
{ id: 6, name: 'classic', initials: 'LA', style: 'classic' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const [checked, setChecked] = useState(false);
|
||||||
|
|
||||||
|
const toggleCheckbox = () => setChecked(!checked);
|
||||||
|
|
||||||
const [selectedSignature, setSelectedSignature] = useState<SelectStyle>(
|
const [selectedSignature, setSelectedSignature] = useState<SelectStyle>(
|
||||||
signatureOptions.length > 0 ? { id: signatureOptions[0].id, style: signatureOptions[0].style } : { id: 0, style: "" }
|
signatureOptions.length > 0 ? { id: signatureOptions[0].id, style: signatureOptions[0].style } : { id: 0, style: "" }
|
||||||
);
|
);
|
||||||
|
|
@ -105,7 +110,7 @@ const AddSignatureModal: React.FC<AddSignatureModalProps> = ({
|
||||||
{ id: 'TYPE', label: 'TYPE', icon: <GrCheckboxSelected className="w-4 h-4" /> },
|
{ id: 'TYPE', label: 'TYPE', icon: <GrCheckboxSelected className="w-4 h-4" /> },
|
||||||
{ id: 'DRAW', label: 'DRAW', icon: <AiOutlineEdit className="w-5 h-5" /> },
|
{ id: 'DRAW', label: 'DRAW', icon: <AiOutlineEdit className="w-5 h-5" /> },
|
||||||
{ id: 'UPLOAD', label: 'UPLOAD', icon: <AiOutlineUpload className="w-5 h-5" /> },
|
{ id: 'UPLOAD', label: 'UPLOAD', icon: <AiOutlineUpload className="w-5 h-5" /> },
|
||||||
{ id: 'SELECT', label: 'SELECT', icon: <GrCheckboxSelected className="w-4 h-4" /> },
|
// { id: 'SELECT', label: 'SELECT', icon: <GrCheckboxSelected className="w-4 h-4" /> },
|
||||||
];
|
];
|
||||||
|
|
||||||
// Initialize form with editing signature data
|
// Initialize form with editing signature data
|
||||||
|
|
@ -134,6 +139,10 @@ const AddSignatureModal: React.FC<AddSignatureModalProps> = ({
|
||||||
setPreview2(`data:image/png;base64,${editingSignature.initialsBlob}`);
|
setPreview2(`data:image/png;base64,${editingSignature.initialsBlob}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (editingSignature.default) {
|
||||||
|
setChecked(editingSignature.default)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, [editingSignature]);
|
}, [editingSignature]);
|
||||||
|
|
||||||
|
|
@ -197,7 +206,8 @@ const AddSignatureModal: React.FC<AddSignatureModalProps> = ({
|
||||||
initialsBase64: signatures.initials,
|
initialsBase64: signatures.initials,
|
||||||
firstName: fullName.split(' ')[0] || user.firstName,
|
firstName: fullName.split(' ')[0] || user.firstName,
|
||||||
lastName: fullName.split(' ')[1] || user.lastName,
|
lastName: fullName.split(' ')[1] || user.lastName,
|
||||||
font: selectedSignature.style
|
font: selectedSignature.style,
|
||||||
|
default:checked
|
||||||
};
|
};
|
||||||
|
|
||||||
let res;
|
let res;
|
||||||
|
|
@ -384,16 +394,14 @@ const AddSignatureModal: React.FC<AddSignatureModalProps> = ({
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// case 'SELECT':
|
||||||
|
// return (
|
||||||
case 'SELECT':
|
// <div className="h-full flex flex-col">
|
||||||
return (
|
// <div className="mb-6">
|
||||||
<div className="h-full flex flex-col">
|
// <h2 className="text-xl font-semibold text-gray-900 mb-2">Select Signature</h2>
|
||||||
<div className="mb-6">
|
// </div>
|
||||||
<h2 className="text-xl font-semibold text-gray-900 mb-2">Select Signature</h2>
|
// </div>
|
||||||
</div>
|
// );
|
||||||
</div>
|
|
||||||
);
|
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -430,7 +438,7 @@ const AddSignatureModal: React.FC<AddSignatureModalProps> = ({
|
||||||
<div className="px-4 py-4 border-b border-gray-200">
|
<div className="px-4 py-4 border-b border-gray-200">
|
||||||
<div className="flex items-center space-x-3">
|
<div className="flex items-center space-x-3">
|
||||||
<div className='px-1 py-1'>
|
<div className='px-1 py-1'>
|
||||||
<h3 className="text-md font-semibold text-gray-900">Add Signature</h3>
|
<h3 className="text-md font-semibold text-gray-900">Add Signature </h3>
|
||||||
<p className="text-xs text-gray-500">Create your digital signature</p>
|
<p className="text-xs text-gray-500">Create your digital signature</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -505,6 +513,35 @@ const AddSignatureModal: React.FC<AddSignatureModalProps> = ({
|
||||||
</button> */}
|
</button> */}
|
||||||
{renderContent()}
|
{renderContent()}
|
||||||
</div>
|
</div>
|
||||||
|
<div className="text-right px-6 py-1 text-white">
|
||||||
|
<label className="inline-flex items-center cursor-pointer group">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={checked}
|
||||||
|
onChange={toggleCheckbox}
|
||||||
|
className="sr-only"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Custom checkbox UI */}
|
||||||
|
<div
|
||||||
|
className={`w-4 h-4 border rounded transition-all duration-300 flex items-center justify-center
|
||||||
|
${checked ? 'bg-[var(--modalSubmitBG)] border-[var(--modalSubmitBG)] scale-110' : 'bg-white border-gray-400'}
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
{checked && (
|
||||||
|
<FiCheck className="text-white text-sm transform scale-100 transition-transform duration-300" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p className="text-sm text-gray-700 opacity-80 ms-1">
|
||||||
|
{checked
|
||||||
|
? 'Signature will be used by default.'
|
||||||
|
: 'Signature will not be used by default.'}
|
||||||
|
</p>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
{/* Caption text below */}
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Footer Buttons in Main Area */}
|
{/* Footer Buttons in Main Area */}
|
||||||
<div className="p-4 border-t border-gray-200 flex justify-end gap-3">
|
<div className="p-4 border-t border-gray-200 flex justify-end gap-3">
|
||||||
|
|
|
||||||
|
|
@ -232,7 +232,7 @@ const SignatureManager: React.FC = () => {
|
||||||
|
|
||||||
{/* Empty State (if no signatures) */}
|
{/* Empty State (if no signatures) */}
|
||||||
{signatures.length === 0 && (
|
{signatures.length === 0 && (
|
||||||
<div className="bg-white rounded-xl shadow-lg p-12 text-center mt-8">
|
<div className=" rounded-xl shadow-lg p-12 text-center mt-8">
|
||||||
<div className="text-gray-400 mb-4">
|
<div className="text-gray-400 mb-4">
|
||||||
<FiEdit3 className="w-16 h-16 mx-auto" />
|
<FiEdit3 className="w-16 h-16 mx-auto" />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -61,9 +61,28 @@ const Templates = () => {
|
||||||
return new Date(timestamp * 1000).toLocaleString();
|
return new Date(timestamp * 1000).toLocaleString();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUseFun = (id) => {
|
const handleUseClick = async (item: any) => {
|
||||||
alert(id)
|
try {
|
||||||
}
|
const payload = {
|
||||||
|
name: item?.name ?? "",
|
||||||
|
subject: item.subject,
|
||||||
|
message: item.message,
|
||||||
|
description: item.description,
|
||||||
|
expireAfter: item.expireAfter,
|
||||||
|
enableIdStamping: item.enableIdStamping,
|
||||||
|
allowViewAudit: item.allowViewAudit,
|
||||||
|
allowReassign: item.allowReassign,
|
||||||
|
enableSignatureIdStamping: item.enableSignatureIdStamping,
|
||||||
|
templateId: item.id,
|
||||||
|
};
|
||||||
|
let res = await api.post(`/api/accounts/${activeAccountId}/transactions`, payload)
|
||||||
|
console.log("handleUseClick", res.data)
|
||||||
|
// /process-step-one/:accountId/:transactionId
|
||||||
|
navigate(`/process-step-one/${activeAccountId}/${res?.data?.id}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -130,7 +149,7 @@ alert(id)
|
||||||
<td className="px-4 py-2 text-sm text-center">{item.name || 'Dummy'}</td>
|
<td className="px-4 py-2 text-sm text-center">{item.name || 'Dummy'}</td>
|
||||||
<td className="px-4 py-2 text-sm text-center">{formatDate(item.createdAt)}</td>
|
<td className="px-4 py-2 text-sm text-center">{formatDate(item.createdAt)}</td>
|
||||||
<td className="px-4 py-2 text-sm text-center">{formatDate(item.lastModifiedAt)}</td>
|
<td className="px-4 py-2 text-sm text-center">{formatDate(item.lastModifiedAt)}</td>
|
||||||
<td className="px-4 py-2 text-sm text-center" onClick={() => handleUseFun(item.id)}><span className="from-green-500 cursor-pointer to-blue-500 bg-gradient-to-br px-3 py-1 rounded-lg text-white font-semibold text-[12px]">Use</span></td>
|
<td className="px-4 py-2 text-sm text-center" onClick={() => handleUseClick(item)}><span className="bg-[var(--lightGreyCol)] cursor-pointer border-gray-300 text-gray-600 hover:bg-gray-100 px-3 py-1 rounded-lg font-semibold text-[12px]">Use</span></td>
|
||||||
{/* Dropdown Trigger + Tooltip */}
|
{/* Dropdown Trigger + Tooltip */}
|
||||||
<td className="px-4 py-2 text-center relative">
|
<td className="px-4 py-2 text-center relative">
|
||||||
<button
|
<button
|
||||||
|
|
|
||||||
|
|
@ -351,8 +351,12 @@ export interface Recipient {
|
||||||
hostEmail: string;
|
hostEmail: string;
|
||||||
type: recipientType;
|
type: recipientType;
|
||||||
color?: string;
|
color?: string;
|
||||||
roleName:string
|
allowSenderToEdit: boolean;
|
||||||
|
allowSenderToDelete: boolean;
|
||||||
|
roleName: string
|
||||||
provideOwnTags?: boolean;
|
provideOwnTags?: boolean;
|
||||||
|
uuid?: string;
|
||||||
|
newOne: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SelectedRecipientInt {
|
export interface SelectedRecipientInt {
|
||||||
|
|
@ -401,6 +405,8 @@ export const addRecipientAsync = createAsyncThunk<
|
||||||
const updateRecipientsData = recipientsData.filter(recipient => recipient.id !== null);
|
const updateRecipientsData = recipientsData.filter(recipient => recipient.id !== null);
|
||||||
const createRecipientsData = recipientsData.filter(recipient => recipient.id == null);
|
const createRecipientsData = recipientsData.filter(recipient => recipient.id == null);
|
||||||
|
|
||||||
|
console.log("createRecipientsData", createRecipientsData)
|
||||||
|
|
||||||
const basePath = `/api/accounts/${accountId}/${toggle}/${transactionId}/recipients`;
|
const basePath = `/api/accounts/${accountId}/${toggle}/${transactionId}/recipients`;
|
||||||
|
|
||||||
const resUpdate = updateRecipientsData.length
|
const resUpdate = updateRecipientsData.length
|
||||||
|
|
@ -516,7 +522,7 @@ const selectedRecipientsSlice = createSlice({
|
||||||
state.signingOrder = action.payload;
|
state.signingOrder = action.payload;
|
||||||
},
|
},
|
||||||
removeSelectedRecipient: (state, action: PayloadAction<Recipient>) => {
|
removeSelectedRecipient: (state, action: PayloadAction<Recipient>) => {
|
||||||
state.recipients = state.recipients.filter((recipient) => recipient.email !== action.payload.email);
|
state.recipients = state.recipients.filter((recipient) => recipient.uuid !== action.payload.uuid);
|
||||||
},
|
},
|
||||||
addColorsToRecipient: (state) => {
|
addColorsToRecipient: (state) => {
|
||||||
for (const [index, recipient] of state.recipients.entries()) {
|
for (const [index, recipient] of state.recipients.entries()) {
|
||||||
|
|
@ -538,6 +544,35 @@ const selectedRecipientsSlice = createSlice({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
updateRecipient(state, action: PayloadAction<Recipient>) {
|
||||||
|
const payloadUuid = String(action.payload.uuid);
|
||||||
|
|
||||||
|
// First try matching by id
|
||||||
|
let index = state.recipients.findIndex(
|
||||||
|
r => String(r.id) === payloadUuid
|
||||||
|
);
|
||||||
|
|
||||||
|
// If not found, try matching by uuid
|
||||||
|
if (index === -1) {
|
||||||
|
index = state.recipients.findIndex(
|
||||||
|
r => String(r.uuid) === payloadUuid
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index !== -1) {
|
||||||
|
// Merge existing recipient with new values
|
||||||
|
state.recipients[index] = {
|
||||||
|
...state.recipients[index],
|
||||||
|
...action.payload
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
console.warn('Recipient not found with uuid:', payloadUuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
,
|
||||||
|
|
||||||
resetSelRecipient: () => initialState
|
resetSelRecipient: () => initialState
|
||||||
},
|
},
|
||||||
extraReducers: (builder) => {
|
extraReducers: (builder) => {
|
||||||
|
|
@ -600,6 +635,7 @@ export const {
|
||||||
updateRecipientIds,
|
updateRecipientIds,
|
||||||
resetSelRecipient,
|
resetSelRecipient,
|
||||||
updateRecipientOrder,
|
updateRecipientOrder,
|
||||||
|
updateRecipient,
|
||||||
resetRecipients
|
resetRecipients
|
||||||
} = selectedRecipientsSlice.actions;
|
} = selectedRecipientsSlice.actions;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,8 @@ const handleGroupBorderPosition = (groupElements: NodeListOf<HTMLElement>, conta
|
||||||
const borderBottom: HTMLElement | null = document.querySelector("[border-group='" + groupElements[0].getAttribute("group") + "'][border-pos='bottom']");
|
const borderBottom: HTMLElement | null = document.querySelector("[border-group='" + groupElements[0].getAttribute("group") + "'][border-pos='bottom']");
|
||||||
const borderLeft: HTMLElement | null = document.querySelector("[border-group='" + groupElements[0].getAttribute("group") + "'][border-pos='left']");
|
const borderLeft: HTMLElement | null = document.querySelector("[border-group='" + groupElements[0].getAttribute("group") + "'][border-pos='left']");
|
||||||
|
|
||||||
|
console.log("handleGroupBorderPosition")
|
||||||
|
|
||||||
if (borderTop !== null && dimension.maxLeft !== null && dimension.minLeft !== null) {
|
if (borderTop !== null && dimension.maxLeft !== null && dimension.minLeft !== null) {
|
||||||
borderTop.style.width = (dimension.maxLeft - dimension.minLeft) + "px";
|
borderTop.style.width = (dimension.maxLeft - dimension.minLeft) + "px";
|
||||||
borderTop.style.height = "1px";
|
borderTop.style.height = "1px";
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue