From f8a4480994085b56bbda28b72f2a6d75b0c555d7 Mon Sep 17 00:00:00 2001 From: enes Date: Tue, 17 Sep 2024 15:04:54 +0200 Subject: [PATCH 01/10] refactor(toolbox): reduce number of mark types Closes #201 --- src/utils/mark.ts | 178 +++++++++++++++++++++------------------------- 1 file changed, 83 insertions(+), 95 deletions(-) diff --git a/src/utils/mark.ts b/src/utils/mark.ts index ac80623..258dc51 100644 --- a/src/utils/mark.ts +++ b/src/utils/mark.ts @@ -9,20 +9,8 @@ import { faSignature, faBriefcase, faIdCard, - faHeading, faClock, - faCalendarDays, - fa1, - faImage, - faSquareCheck, - faCheckDouble, - faPaperclip, - faCircleDot, - faSquareCaretDown, - faTableCellsLarge, - faStamp, - faCreditCard, - faPhone + fa1 } from '@fortawesome/free-solid-svg-icons' /** @@ -154,15 +142,9 @@ const findOtherUserMarks = (marks: Mark[], pubkey: string): Mark[] => { export const DEFAULT_TOOLBOX = [ { - identifier: MarkType.TEXT, - icon: faT, - label: 'Text', - active: true - }, - { - identifier: MarkType.SIGNATURE, - icon: faSignature, - label: 'Signature', + identifier: MarkType.FULLNAME, + icon: faIdCard, + label: 'Full Name', active: false }, { @@ -172,15 +154,9 @@ export const DEFAULT_TOOLBOX = [ active: false }, { - identifier: MarkType.FULLNAME, - icon: faIdCard, - label: 'Full Name', - active: false - }, - { - identifier: MarkType.INITIALS, - icon: faHeading, - label: 'Initials', + identifier: MarkType.SIGNATURE, + icon: faSignature, + label: 'Signature', active: false }, { @@ -190,77 +166,89 @@ export const DEFAULT_TOOLBOX = [ active: false }, { - identifier: MarkType.DATE, - icon: faCalendarDays, - label: 'Date', - active: false + identifier: MarkType.TEXT, + icon: faT, + label: 'Text', + active: true }, { identifier: MarkType.NUMBER, icon: fa1, label: 'Number', active: false - }, - { - identifier: MarkType.IMAGES, - icon: faImage, - label: 'Images', - active: false - }, - { - identifier: MarkType.CHECKBOX, - icon: faSquareCheck, - label: 'Checkbox', - active: false - }, - { - identifier: MarkType.MULTIPLE, - icon: faCheckDouble, - label: 'Multiple', - active: false - }, - { - identifier: MarkType.FILE, - icon: faPaperclip, - label: 'File', - active: false - }, - { - identifier: MarkType.RADIO, - icon: faCircleDot, - label: 'Radio', - active: false - }, - { - identifier: MarkType.SELECT, - icon: faSquareCaretDown, - label: 'Select', - active: false - }, - { - identifier: MarkType.CELLS, - icon: faTableCellsLarge, - label: 'Cells', - active: false - }, - { - identifier: MarkType.STAMP, - icon: faStamp, - label: 'Stamp', - active: false - }, - { - identifier: MarkType.PAYMENT, - icon: faCreditCard, - label: 'Payment', - active: false - }, - { - identifier: MarkType.PHONE, - icon: faPhone, - label: 'Phone', - active: false } + // { + // identifier: MarkType.INITIALS, + // icon: faHeading, + // label: 'Initials', + // active: false + // }, + // { + // identifier: MarkType.DATE, + // icon: faCalendarDays, + // label: 'Date', + // active: false + // }, + // { + // identifier: MarkType.IMAGES, + // icon: faImage, + // label: 'Images', + // active: false + // }, + // { + // identifier: MarkType.CHECKBOX, + // icon: faSquareCheck, + // label: 'Checkbox', + // active: false + // }, + // { + // identifier: MarkType.MULTIPLE, + // icon: faCheckDouble, + // label: 'Multiple', + // active: false + // }, + // { + // identifier: MarkType.FILE, + // icon: faPaperclip, + // label: 'File', + // active: false + // }, + // { + // identifier: MarkType.RADIO, + // icon: faCircleDot, + // label: 'Radio', + // active: false + // }, + // { + // identifier: MarkType.SELECT, + // icon: faSquareCaretDown, + // label: 'Select', + // active: false + // }, + // { + // identifier: MarkType.CELLS, + // icon: faTableCellsLarge, + // label: 'Cells', + // active: false + // }, + // { + // identifier: MarkType.STAMP, + // icon: faStamp, + // label: 'Stamp', + // active: false + // }, + // { + // identifier: MarkType.PAYMENT, + // icon: faCreditCard, + // label: 'Payment', + // active: false + // }, + // { + // identifier: MarkType.PHONE, + // icon: faPhone, + // label: 'Phone', + // active: false + // } ] export const getToolboxLabelByMarkType = (markType: MarkType) => { From dfdcb8419d5b3c8ca34c6f9590107ce120a53174 Mon Sep 17 00:00:00 2001 From: enes Date: Tue, 17 Sep 2024 17:21:30 +0200 Subject: [PATCH 02/10] fix(marks): add default signer --- src/components/DrawPDFFields/index.tsx | 113 ++++++++++++------------- 1 file changed, 56 insertions(+), 57 deletions(-) diff --git a/src/components/DrawPDFFields/index.tsx b/src/components/DrawPDFFields/index.tsx index 7c1227d..aa6b0e5 100644 --- a/src/components/DrawPDFFields/index.tsx +++ b/src/components/DrawPDFFields/index.tsx @@ -37,6 +37,8 @@ interface Props { export const DrawPDFFields = (props: Props) => { const { selectedFiles, selectedTool, onDrawFieldsChange, users } = props + const signers = users.filter((u) => u.role === UserRole.signer) + const defaultSignerNpub = signers.length ? hexToNpub(signers[0].pubkey) : '' const { to, from } = useScale() const [sigitFiles, setSigitFiles] = useState([]) @@ -115,7 +117,7 @@ export const DrawPDFFields = (props: Props) => { top: to(page.width, y), width: event.pointerType === 'mouse' ? 0 : DEFAULT_START_SIZE.width, height: event.pointerType === 'mouse' ? 0 : DEFAULT_START_SIZE.height, - counterpart: '', + counterpart: defaultSignerNpub, type: selectedTool.identifier } @@ -453,7 +455,9 @@ export const DrawPDFFields = (props: Props) => { Counterpart @@ -524,28 +523,28 @@ export const DrawPDFFields = (props: Props) => { ) } - const renderCounterpartValue = (value: string) => { - const user = users.find((u) => u.pubkey === npubToHex(value)) - if (user) { - let displayValue = truncate(value, { - length: 16 - }) - - const metadata = props.metadata[user.pubkey] + const renderCounterpartValue = (npub: string) => { + let displayValue = truncate(npub, { + length: 16 + }) + const signer = signers.find((u) => u.pubkey === npubToHex(npub)) + if (signer) { + const metadata = props.metadata[signer.pubkey] if (metadata) { displayValue = truncate( - metadata.name || metadata.display_name || metadata.username || value, + metadata.display_name || metadata.name || npub, { length: 16 } ) } + return ( <> { ) } - return value + return displayValue } if (parsingPdf) { From 39934f59c375d774f1fb4f7a97676304f5e9fd41 Mon Sep 17 00:00:00 2001 From: enes Date: Thu, 19 Sep 2024 11:46:34 +0200 Subject: [PATCH 03/10] fix: last signer as default next --- src/components/DrawPDFFields/index.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/components/DrawPDFFields/index.tsx b/src/components/DrawPDFFields/index.tsx index aa6b0e5..194291f 100644 --- a/src/components/DrawPDFFields/index.tsx +++ b/src/components/DrawPDFFields/index.tsx @@ -39,6 +39,7 @@ export const DrawPDFFields = (props: Props) => { const { selectedFiles, selectedTool, onDrawFieldsChange, users } = props const signers = users.filter((u) => u.role === UserRole.signer) const defaultSignerNpub = signers.length ? hexToNpub(signers[0].pubkey) : '' + const [lastSigner, setLastSigner] = useState(defaultSignerNpub) const { to, from } = useScale() const [sigitFiles, setSigitFiles] = useState([]) @@ -117,7 +118,7 @@ export const DrawPDFFields = (props: Props) => { top: to(page.width, y), width: event.pointerType === 'mouse' ? 0 : DEFAULT_START_SIZE.width, height: event.pointerType === 'mouse' ? 0 : DEFAULT_START_SIZE.height, - counterpart: defaultSignerNpub, + counterpart: lastSigner, type: selectedTool.identifier } @@ -456,10 +457,14 @@ export const DrawPDFFields = (props: Props) => { Counterpart { - drawnField.counterpart = event.target.value - setLastSigner(event.target.value) - refreshPdfFiles() - }} - labelId="counterparts" - label="Counterparts" - sx={{ - background: 'white' - }} - renderValue={(value) => renderCounterpartValue(value)} - > - {signers.map((signer, index) => { - const npub = hexToNpub(signer.pubkey) - let displayValue = truncate(npub, { - length: 16 - }) - - const metadata = props.metadata[signer.pubkey] - - if (metadata) { - displayValue = truncate( - metadata.name || - metadata.display_name || - metadata.username || - npub, - { - length: 16 - } - ) + {isActiveDrawnField( + fileIndex, + pageIndex, + drawnFieldIndex + ) && ( +
+ + Counterpart + - -
+ const metadata = props.metadata[signer.pubkey] + + if (metadata) { + displayValue = truncate( + metadata.name || + metadata.display_name || + metadata.username || + npub, + { + length: 16 + } + ) + } + + return ( + + + img': { + width: '30px', + height: '30px' + } + }} + /> + + {displayValue} + + ) + })} + + + + )} ) })} From d8d51be603a9817ffc449eb2ffd81382cba47ec8 Mon Sep 17 00:00:00 2001 From: enes Date: Thu, 19 Sep 2024 15:05:03 +0200 Subject: [PATCH 07/10] fix: add small avatar when select is not showing --- src/components/DrawPDFFields/index.tsx | 13 +++++++++++++ src/components/DrawPDFFields/style.module.scss | 11 +++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/components/DrawPDFFields/index.tsx b/src/components/DrawPDFFields/index.tsx index f2e962e..bad5d3a 100644 --- a/src/components/DrawPDFFields/index.tsx +++ b/src/components/DrawPDFFields/index.tsx @@ -21,6 +21,7 @@ import { FONT_SIZE, FONT_TYPE, inPx } from '../../utils/pdf' import { useScale } from '../../hooks/useScale' import { AvatarIconButton } from '../UserAvatarIconButton' import { LoadingSpinner } from '../LoadingSpinner' +import { UserAvatar } from '../UserAvatar' const DEFAULT_START_SIZE = { width: 140, @@ -493,6 +494,18 @@ export const DrawPDFFields = (props: Props) => { > + {!isActiveDrawnField( + fileIndex, + pageIndex, + drawnFieldIndex + ) && + !!drawnField.counterpart && ( +
+ +
+ )} {isActiveDrawnField( fileIndex, pageIndex, diff --git a/src/components/DrawPDFFields/style.module.scss b/src/components/DrawPDFFields/style.module.scss index 13afb9f..8c0b3b8 100644 --- a/src/components/DrawPDFFields/style.module.scss +++ b/src/components/DrawPDFFields/style.module.scss @@ -84,3 +84,14 @@ padding: 5px 0; } } + +.counterpartSelectValue { + display: flex; +} + +.counterpartAvatar { + img { + width: 21px; + height: 21px; + } +} From e05d3e53a2b663973adf2e02296b3a5bbfa8ee78 Mon Sep 17 00:00:00 2001 From: enes Date: Fri, 20 Sep 2024 10:26:32 +0200 Subject: [PATCH 08/10] fix: remove duplicate states and fix default signer --- src/components/DrawPDFFields/index.tsx | 107 +++++++------------------ src/pages/create/index.tsx | 64 ++++++++++++--- 2 files changed, 81 insertions(+), 90 deletions(-) diff --git a/src/components/DrawPDFFields/index.tsx b/src/components/DrawPDFFields/index.tsx index bad5d3a..076c6fb 100644 --- a/src/components/DrawPDFFields/index.tsx +++ b/src/components/DrawPDFFields/index.tsx @@ -11,17 +11,16 @@ import styles from './style.module.scss' import React, { useEffect, useState } from 'react' import { ProfileMetadata, User, UserRole } from '../../types' import { MouseState, PdfPage, DrawnField, DrawTool } from '../../types/drawing' -import { truncate } from 'lodash' -import { settleAllFullfilfedPromises, hexToNpub, npubToHex } from '../../utils' -import { getSigitFile, SigitFile } from '../../utils/file' +import { hexToNpub, npubToHex, getProfileUsername } from '../../utils' +import { SigitFile } from '../../utils/file' import { getToolboxLabelByMarkType } from '../../utils/mark' import { FileDivider } from '../FileDivider' import { ExtensionFileBox } from '../ExtensionFileBox' import { FONT_SIZE, FONT_TYPE, inPx } from '../../utils/pdf' import { useScale } from '../../hooks/useScale' import { AvatarIconButton } from '../UserAvatarIconButton' -import { LoadingSpinner } from '../LoadingSpinner' import { UserAvatar } from '../UserAvatar' +import _ from 'lodash' const DEFAULT_START_SIZE = { width: 140, @@ -29,22 +28,32 @@ const DEFAULT_START_SIZE = { } as const interface Props { - selectedFiles: File[] users: User[] metadata: { [key: string]: ProfileMetadata } - onDrawFieldsChange: (sigitFiles: SigitFile[]) => void + sigitFiles: SigitFile[] + setSigitFiles: React.Dispatch> selectedTool?: DrawTool } export const DrawPDFFields = (props: Props) => { - const { selectedFiles, selectedTool, onDrawFieldsChange, users } = props + const { selectedTool, sigitFiles, setSigitFiles, users } = props + const signers = users.filter((u) => u.role === UserRole.signer) const defaultSignerNpub = signers.length ? hexToNpub(signers[0].pubkey) : '' const [lastSigner, setLastSigner] = useState(defaultSignerNpub) - const { to, from } = useScale() + /** + * Return first pubkey that is present in the signers list + * @param pubkeys + * @returns available pubkey or empty string + */ + const getAvailableSigner = (...pubkeys: string[]) => { + const availableSigner: string | undefined = pubkeys.find((pubkey) => + signers.some((s) => s.pubkey === npubToHex(pubkey)) + ) + return availableSigner || '' + } - const [sigitFiles, setSigitFiles] = useState([]) - const [parsingPdf, setIsParsing] = useState(false) + const { to, from } = useScale() const [mouseState, setMouseState] = useState({ clicked: false @@ -64,33 +73,6 @@ export const DrawPDFFields = (props: Props) => { activeDrawnField?.pageIndex === pageIndex && activeDrawnField?.drawnFieldIndex === drawnFieldIndex - useEffect(() => { - if (selectedFiles) { - /** - * Reads the binary files and converts to internal file type - * and sets to a state (adds images if it's a PDF) - */ - const parsePages = async () => { - const files = await settleAllFullfilfedPromises( - selectedFiles, - getSigitFile - ) - - setSigitFiles(files) - } - - setIsParsing(true) - - parsePages().finally(() => { - setIsParsing(false) - }) - } - }, [selectedFiles]) - - useEffect(() => { - if (sigitFiles) onDrawFieldsChange(sigitFiles) - }, [onDrawFieldsChange, sigitFiles]) - /** * Drawing events */ @@ -136,7 +118,7 @@ export const DrawPDFFields = (props: Props) => { top: to(page.width, y), width: event.pointerType === 'mouse' ? 0 : DEFAULT_START_SIZE.width, height: event.pointerType === 'mouse' ? 0 : DEFAULT_START_SIZE.height, - counterpart: lastSigner, + counterpart: getAvailableSigner(lastSigner, defaultSignerNpub), type: selectedTool.identifier } @@ -518,7 +500,7 @@ export const DrawPDFFields = (props: Props) => { Counterpart