Releasing new design #161

Merged
b merged 241 commits from staging into main 2024-08-21 11:38:25 +00:00
5 changed files with 245 additions and 124 deletions
Showing only changes of commit 19f7151db7 - Show all commits

View File

@ -1,11 +1,4 @@
import { import { Close } from '@mui/icons-material'
AccessTime,
CalendarMonth,
Gesture,
Badge,
Work,
Close
} from '@mui/icons-material'
import { import {
Box, Box,
CircularProgress, CircularProgress,
@ -22,11 +15,10 @@ import * as PDFJS from 'pdfjs-dist'
import { ProfileMetadata, User, UserRole } from '../../types' import { ProfileMetadata, User, UserRole } from '../../types'
import { import {
PdfFile, PdfFile,
DrawTool,
MouseState, MouseState,
PdfPage, PdfPage,
DrawnField, DrawnField,
MarkType DrawTool
} from '../../types/drawing' } from '../../types/drawing'
import { truncate } from 'lodash' import { truncate } from 'lodash'
import { hexToNpub } from '../../utils' import { hexToNpub } from '../../utils'
@ -41,48 +33,15 @@ interface Props {
users: User[] users: User[]
metadata: { [key: string]: ProfileMetadata } metadata: { [key: string]: ProfileMetadata }
onDrawFieldsChange: (pdfFiles: PdfFile[]) => void onDrawFieldsChange: (pdfFiles: PdfFile[]) => void
selectedTool?: DrawTool
} }
export const DrawPDFFields = (props: Props) => { export const DrawPDFFields = (props: Props) => {
const { selectedFiles } = props const { selectedFiles, selectedTool } = props
const [pdfFiles, setPdfFiles] = useState<PdfFile[]>([]) const [pdfFiles, setPdfFiles] = useState<PdfFile[]>([])
const [parsingPdf, setParsingPdf] = useState<boolean>(false) const [parsingPdf, setParsingPdf] = useState<boolean>(false)
const [selectedTool, setSelectedTool] = useState<DrawTool | null>()
const [toolbox] = useState<DrawTool[]>([
{
identifier: MarkType.SIGNATURE,
icon: <Gesture />,
label: 'Signature',
active: false
},
{
identifier: MarkType.FULLNAME,
icon: <Badge />,
label: 'Full Name',
active: true
},
{
identifier: MarkType.JOBTITLE,
icon: <Work />,
label: 'Job Title',
active: false
},
{
identifier: MarkType.DATE,
icon: <CalendarMonth />,
label: 'Date',
active: false
},
{
identifier: MarkType.DATETIME,
icon: <AccessTime />,
label: 'Datetime',
active: false
}
])
const [mouseState, setMouseState] = useState<MouseState>({ const [mouseState, setMouseState] = useState<MouseState>({
clicked: false clicked: false
}) })
@ -385,20 +344,6 @@ export const DrawPDFFields = (props: Props) => {
} }
} }
/**
* Changes the drawing tool
* @param drawTool to draw with
*/
const handleToolSelect = (drawTool: DrawTool) => {
// If clicked on the same tool, unselect
if (drawTool.identifier === selectedTool?.identifier) {
setSelectedTool(null)
return
}
setSelectedTool(drawTool)
}
/** /**
* Renders the pdf pages and drawing elements * Renders the pdf pages and drawing elements
*/ */
@ -555,27 +500,6 @@ export const DrawPDFFields = (props: Props) => {
</React.Fragment> </React.Fragment>
) )
})} })}
<Box className={styles.drawToolBoxContainer}>
<Box className={styles.drawToolBox}>
{toolbox
.filter((drawTool) => drawTool.active)
.map((drawTool: DrawTool, index: number) => {
return (
<div
key={index}
onClick={() => {
handleToolSelect(drawTool)
}}
className={`${styles.toolItem} ${selectedTool?.identifier === drawTool.identifier ? styles.selected : ''}`}
>
{drawTool.icon}
{drawTool.label}
</div>
)
})}
</Box>
</Box>
</div> </div>
) )
} }

View File

@ -7,48 +7,6 @@
cursor: pointer; cursor: pointer;
} }
.drawToolBoxContainer {
position: fixed;
bottom: 0;
left: 0;
right: 0;
display: flex;
justify-content: center;
z-index: 50;
.drawToolBox {
display: flex;
gap: 10px;
min-width: 100px;
background-color: white;
padding: 15px;
box-shadow: 0 0 10px 1px #0000003b;
border-radius: 4px;
.toolItem {
display: flex;
flex-direction: column;
align-items: center;
border: 1px solid rgba(0, 0, 0, 0.137);
padding: 5px;
cursor: pointer;
-webkit-user-select: none;
user-select: none;
&.selected {
border-color: #01aaad;
color: #01aaad;
}
&:not(.selected) {
&:hover {
border-color: #01aaad79;
}
}
}
}
}
.pdfImageWrapper { .pdfImageWrapper {
position: relative; position: relative;
-webkit-user-select: none; -webkit-user-select: none;

View File

@ -51,16 +51,35 @@ import {
import { Container } from '../../components/Container' import { Container } from '../../components/Container'
import styles from './style.module.scss' import styles from './style.module.scss'
import fileListStyles from '../../components/FileList/style.module.scss' import fileListStyles from '../../components/FileList/style.module.scss'
import { PdfFile } from '../../types/drawing' import { DrawTool, MarkType, PdfFile } from '../../types/drawing'
import { DrawPDFFields } from '../../components/DrawPDFFields' import { DrawPDFFields } from '../../components/DrawPDFFields'
import { Mark } from '../../types/mark.ts' import { Mark } from '../../types/mark.ts'
import { StickySideColumns } from '../../layouts/StickySideColumns.tsx' import { StickySideColumns } from '../../layouts/StickySideColumns.tsx'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { import {
fa1,
faBriefcase,
faCalendarDays,
faCheckDouble,
faCircleDot,
faClock,
faCreditCard,
faEllipsis,
faEye, faEye,
faGripLines, faGripLines,
faHeading,
faIdCard,
faImage,
faPaperclip,
faPen, faPen,
faPhone,
faPlus, faPlus,
faSignature,
faSquareCaretDown,
faSquareCheck,
faStamp,
faT,
faTableCellsLarge,
faTrash, faTrash,
faUpload faUpload
} from '@fortawesome/free-solid-svg-icons' } from '@fortawesome/free-solid-svg-icons'
@ -108,6 +127,132 @@ export const CreatePage = () => {
) )
const [drawnPdfs, setDrawnPdfs] = useState<PdfFile[]>([]) const [drawnPdfs, setDrawnPdfs] = useState<PdfFile[]>([])
const [selectedTool, setSelectedTool] = useState<DrawTool>()
const [toolbox] = useState<DrawTool[]>([
{
identifier: MarkType.TEXT,
icon: <FontAwesomeIcon icon={faT} />,
label: 'Text',
active: false
},
{
identifier: MarkType.SIGNATURE,
icon: <FontAwesomeIcon icon={faSignature} />,
label: 'Signature',
active: false
},
{
identifier: MarkType.JOBTITLE,
icon: <FontAwesomeIcon icon={faBriefcase} />,
label: 'Job Title',
active: false
},
{
identifier: MarkType.FULLNAME,
icon: <FontAwesomeIcon icon={faIdCard} />,
label: 'Full Name',
active: true
},
{
identifier: MarkType.INITIALS,
icon: <FontAwesomeIcon icon={faHeading} />,
label: 'Initials',
active: false
},
{
identifier: MarkType.DATETIME,
icon: <FontAwesomeIcon icon={faClock} />,
label: 'Date Time',
active: false
},
{
identifier: MarkType.DATE,
icon: <FontAwesomeIcon icon={faCalendarDays} />,
label: 'Date',
active: false
},
{
identifier: MarkType.NUMBER,
icon: <FontAwesomeIcon icon={fa1} />,
label: 'Number',
active: false
},
{
identifier: MarkType.IMAGES,
icon: <FontAwesomeIcon icon={faImage} />,
label: 'Images',
active: false
},
{
identifier: MarkType.CHECKBOX,
icon: <FontAwesomeIcon icon={faSquareCheck} />,
label: 'Checkbox',
active: false
},
{
identifier: MarkType.MULTIPLE,
icon: <FontAwesomeIcon icon={faCheckDouble} />,
label: 'Multiple',
active: false
},
{
identifier: MarkType.FILE,
icon: <FontAwesomeIcon icon={faPaperclip} />,
label: 'File',
active: false
},
{
identifier: MarkType.RADIO,
icon: <FontAwesomeIcon icon={faCircleDot} />,
label: 'Radio',
active: false
},
{
identifier: MarkType.SELECT,
icon: <FontAwesomeIcon icon={faSquareCaretDown} />,
label: 'Select',
active: false
},
{
identifier: MarkType.CELLS,
icon: <FontAwesomeIcon icon={faTableCellsLarge} />,
label: 'Cells',
active: false
},
{
identifier: MarkType.STAMP,
icon: <FontAwesomeIcon icon={faStamp} />,
label: 'Stamp',
active: false
},
{
identifier: MarkType.PAYMENT,
icon: <FontAwesomeIcon icon={faCreditCard} />,
label: 'Payment',
active: false
},
{
identifier: MarkType.PHONE,
icon: <FontAwesomeIcon icon={faPhone} />,
label: 'Phone',
active: false
}
])
/**
* Changes the drawing tool
* @param drawTool to draw with
*/
const handleToolSelect = (drawTool: DrawTool) => {
// If clicked on the same tool, unselect
if (drawTool.identifier === selectedTool?.identifier) {
setSelectedTool(undefined)
return
}
setSelectedTool(drawTool)
}
useEffect(() => { useEffect(() => {
users.forEach((user) => { users.forEach((user) => {
if (!(user.pubkey in metadata)) { if (!(user.pubkey in metadata)) {
@ -866,6 +1011,39 @@ export const CreatePage = () => {
Publish Publish
</Button> </Button>
<div className={`${styles.paperGroup} ${styles.toolbox}`}>
{toolbox.map((drawTool: DrawTool, index: number) => {
return (
<div
key={index}
onClick={
drawTool.active
? () => {
handleToolSelect(drawTool)
}
: () => null
}
className={`${styles.toolItem} ${selectedTool?.identifier === drawTool.identifier ? styles.selected : ''} ${!drawTool.active ? styles.comingSoon : ''}
`}
>
{drawTool.icon}
{drawTool.label}
{drawTool.active ? (
<FontAwesomeIcon icon={faEllipsis} />
) : (
<span
style={{
fontSize: '10px'
}}
>
Coming soon
</span>
)}
</div>
)
})}
</div>
{!!error && ( {!!error && (
<FormHelperText error={!!error}>{error}</FormHelperText> <FormHelperText error={!!error}>{error}</FormHelperText>
)} )}
@ -877,6 +1055,7 @@ export const CreatePage = () => {
users={users} users={users}
selectedFiles={selectedFiles} selectedFiles={selectedFiles}
onDrawFieldsChange={onDrawFieldsChange} onDrawFieldsChange={onDrawFieldsChange}
selectedTool={selectedTool}
/> />
</StickySideColumns> </StickySideColumns>
</Container> </Container>

View File

@ -123,3 +123,50 @@
overflow: hidden; overflow: hidden;
flex-grow: 1; flex-grow: 1;
} }
.toolbox {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 15px;
max-height: 450px;
overflow-x: hidden;
overflow-y: auto;
}
.toolItem {
width: 90px;
height: 90px;
transition: ease 0.2s;
display: inline-flex;
flex-direction: column;
gap: 5px;
border-radius: 4px;
padding: 10px 5px 5px 5px;
background: rgba(0, 0, 0, 0.05);
color: rgba(0, 0, 0, 0.5);
align-items: center;
justify-content: center;
font-size: 14px;
cursor: pointer;
-webkit-user-select: none;
user-select: none;
&.selected {
background: $primary-main;
color: white;
}
&:not(.selected) {
&:hover {
background: $primary-light;
color: white;
}
}
&.comingSoon {
opacity: 0.5;
cursor: not-allowed;
}
}

View File

@ -41,9 +41,22 @@ export interface DrawTool {
} }
export enum MarkType { export enum MarkType {
TEXT = 'TEXT',
SIGNATURE = 'SIGNATURE', SIGNATURE = 'SIGNATURE',
JOBTITLE = 'JOBTITLE', JOBTITLE = 'JOBTITLE',
FULLNAME = 'FULLNAME', FULLNAME = 'FULLNAME',
INITIALS = 'INITIALS',
DATETIME = 'DATETIME',
DATE = 'DATE', DATE = 'DATE',
DATETIME = 'DATETIME' NUMBER = 'NUMBER',
IMAGES = 'IMAGES',
CHECKBOX = 'CHECKBOX',
MULTIPLE = 'MULTIPLE',
FILE = 'FILE',
RADIO = 'RADIO',
SELECT = 'SELECT',
CELLS = 'CELLS',
STAMP = 'STAMP',
PAYMENT = 'PAYMENT',
PHONE = 'PHONE'
} }