Releasing new design #161
@ -1,20 +1,15 @@
|
||||
import {
|
||||
AccessTime,
|
||||
CalendarMonth,
|
||||
ExpandMore,
|
||||
Gesture,
|
||||
PictureAsPdf,
|
||||
Badge,
|
||||
Work,
|
||||
Close
|
||||
} from '@mui/icons-material'
|
||||
import {
|
||||
Box,
|
||||
Typography,
|
||||
Accordion,
|
||||
AccordionDetails,
|
||||
AccordionSummary,
|
||||
CircularProgress,
|
||||
Divider,
|
||||
FormControl,
|
||||
InputLabel,
|
||||
MenuItem,
|
||||
@ -53,7 +48,7 @@ export const DrawPDFFields = (props: Props) => {
|
||||
|
||||
const [pdfFiles, setPdfFiles] = useState<PdfFile[]>([])
|
||||
const [parsingPdf, setParsingPdf] = useState<boolean>(false)
|
||||
const [showDrawToolBox, setShowDrawToolBox] = useState<boolean>(false)
|
||||
const [showDrawToolBox] = useState<boolean>(true)
|
||||
|
||||
const [selectedTool, setSelectedTool] = useState<DrawTool | null>()
|
||||
const [toolbox] = useState<DrawTool[]>([
|
||||
@ -95,6 +90,16 @@ export const DrawPDFFields = (props: Props) => {
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedFiles) {
|
||||
/**
|
||||
* Reads the pdf binary files and converts it's pages to images
|
||||
* creates the pdfFiles object and sets to a state
|
||||
*/
|
||||
const parsePdfPages = async () => {
|
||||
const pdfFiles: PdfFile[] = await toPdfFiles(selectedFiles)
|
||||
|
||||
setPdfFiles(pdfFiles)
|
||||
}
|
||||
|
||||
setParsingPdf(true)
|
||||
|
||||
parsePdfPages().finally(() => {
|
||||
@ -105,7 +110,7 @@ export const DrawPDFFields = (props: Props) => {
|
||||
|
||||
useEffect(() => {
|
||||
if (pdfFiles) props.onDrawFieldsChange(pdfFiles)
|
||||
}, [pdfFiles])
|
||||
}, [pdfFiles, props])
|
||||
|
||||
/**
|
||||
* Drawing events
|
||||
@ -132,12 +137,15 @@ export const DrawPDFFields = (props: Props) => {
|
||||
* @param event Mouse event
|
||||
* @param page PdfPage where press happened
|
||||
*/
|
||||
const onMouseDown = (event: any, page: PdfPage) => {
|
||||
const onMouseDown = (
|
||||
event: React.MouseEvent<HTMLDivElement, MouseEvent>,
|
||||
page: PdfPage
|
||||
) => {
|
||||
// Proceed only if left click
|
||||
if (event.button !== 0) return
|
||||
|
||||
// Only allow drawing if mouse is not over other drawn element
|
||||
const isOverPdfImageWrapper = event.target.tagName === 'IMG'
|
||||
const isOverPdfImageWrapper = event.currentTarget.tagName === 'IMG'
|
||||
|
||||
if (!selectedTool || !isOverPdfImageWrapper) {
|
||||
return
|
||||
@ -185,7 +193,10 @@ export const DrawPDFFields = (props: Props) => {
|
||||
* @param event Mouse event
|
||||
* @param page PdfPage where moving is happening
|
||||
*/
|
||||
const onMouseMove = (event: any, page: PdfPage) => {
|
||||
const onMouseMove = (
|
||||
event: React.MouseEvent<HTMLDivElement, MouseEvent>,
|
||||
page: PdfPage
|
||||
) => {
|
||||
if (mouseState.clicked && selectedTool) {
|
||||
const lastElementIndex = page.drawnFields.length - 1
|
||||
const lastDrawnField = page.drawnFields[lastElementIndex]
|
||||
@ -216,7 +227,9 @@ export const DrawPDFFields = (props: Props) => {
|
||||
* @param event Mouse event
|
||||
* @param drawnField Which we are moving
|
||||
*/
|
||||
const onDrawnFieldMouseDown = (event: any) => {
|
||||
const onDrawnFieldMouseDown = (
|
||||
event: React.MouseEvent<HTMLDivElement, MouseEvent>
|
||||
) => {
|
||||
event.stopPropagation()
|
||||
|
||||
// Proceed only if left click
|
||||
@ -239,11 +252,14 @@ export const DrawPDFFields = (props: Props) => {
|
||||
* @param event Mouse event
|
||||
* @param drawnField which we are moving
|
||||
*/
|
||||
const onDranwFieldMouseMove = (event: any, drawnField: DrawnField) => {
|
||||
const onDranwFieldMouseMove = (
|
||||
event: React.MouseEvent<HTMLDivElement, MouseEvent>,
|
||||
drawnField: DrawnField
|
||||
) => {
|
||||
if (mouseState.dragging) {
|
||||
const { mouseX, mouseY, rect } = getMouseCoordinates(
|
||||
event,
|
||||
event.target.parentNode
|
||||
event.currentTarget.parentNode as HTMLElement
|
||||
)
|
||||
const coordsOffset = mouseState.coordsInWrapper
|
||||
|
||||
@ -272,7 +288,9 @@ export const DrawPDFFields = (props: Props) => {
|
||||
* @param event Mouse event
|
||||
* @param drawnField which we are resizing
|
||||
*/
|
||||
const onResizeHandleMouseDown = (event: any) => {
|
||||
const onResizeHandleMouseDown = (
|
||||
event: React.MouseEvent<HTMLSpanElement, MouseEvent>
|
||||
) => {
|
||||
// Proceed only if left click
|
||||
if (event.button !== 0) return
|
||||
|
||||
@ -288,11 +306,14 @@ export const DrawPDFFields = (props: Props) => {
|
||||
* @param event Mouse event
|
||||
* @param drawnField which we are resizing
|
||||
*/
|
||||
const onResizeHandleMouseMove = (event: any, drawnField: DrawnField) => {
|
||||
const onResizeHandleMouseMove = (
|
||||
event: React.MouseEvent<HTMLSpanElement, MouseEvent>,
|
||||
drawnField: DrawnField
|
||||
) => {
|
||||
if (mouseState.resizing) {
|
||||
const { mouseX, mouseY } = getMouseCoordinates(
|
||||
event,
|
||||
event.target.parentNode.parentNode
|
||||
event.currentTarget.parentNode as HTMLElement
|
||||
)
|
||||
|
||||
const width = mouseX - drawnField.left
|
||||
@ -313,7 +334,7 @@ export const DrawPDFFields = (props: Props) => {
|
||||
* @param drawnFileIndex drawn file index
|
||||
*/
|
||||
const onRemoveHandleMouseDown = (
|
||||
event: any,
|
||||
event: React.MouseEvent<HTMLSpanElement, MouseEvent>,
|
||||
pdfFileIndex: number,
|
||||
pdfPageIndex: number,
|
||||
drawnFileIndex: number
|
||||
@ -331,7 +352,9 @@ export const DrawPDFFields = (props: Props) => {
|
||||
* so select can work properly
|
||||
* @param event Mouse event
|
||||
*/
|
||||
const onUserSelectHandleMouseDown = (event: any) => {
|
||||
const onUserSelectHandleMouseDown = (
|
||||
event: React.MouseEvent<HTMLDivElement, MouseEvent>
|
||||
) => {
|
||||
event.stopPropagation()
|
||||
}
|
||||
|
||||
@ -341,8 +364,11 @@ export const DrawPDFFields = (props: Props) => {
|
||||
* @param customTarget mouse coordinates relative to this element, if not provided
|
||||
* event.target will be used
|
||||
*/
|
||||
const getMouseCoordinates = (event: any, customTarget?: any) => {
|
||||
const target = customTarget ? customTarget : event.target
|
||||
const getMouseCoordinates = (
|
||||
event: React.MouseEvent<HTMLElement, MouseEvent>,
|
||||
customTarget?: HTMLElement
|
||||
) => {
|
||||
const target = customTarget ? customTarget : event.currentTarget
|
||||
const rect = target.getBoundingClientRect()
|
||||
const mouseX = event.clientX - rect.left //x position within the element.
|
||||
const mouseY = event.clientY - rect.top //y position within the element.
|
||||
@ -354,31 +380,6 @@ export const DrawPDFFields = (props: Props) => {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the pdf binary files and converts it's pages to images
|
||||
* creates the pdfFiles object and sets to a state
|
||||
*/
|
||||
const parsePdfPages = async () => {
|
||||
const pdfFiles: PdfFile[] = await toPdfFiles(selectedFiles)
|
||||
|
||||
setPdfFiles(pdfFiles)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns if expanded pdf accordion is present
|
||||
*/
|
||||
const hasExpandedPdf = () => {
|
||||
return !!pdfFiles.filter((pdfFile) => !!pdfFile.expanded).length
|
||||
}
|
||||
|
||||
const handleAccordionExpandChange = (expanded: boolean, pdfFile: PdfFile) => {
|
||||
pdfFile.expanded = expanded
|
||||
|
||||
refreshPdfFiles()
|
||||
setShowDrawToolBox(hasExpandedPdf())
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the drawing tool
|
||||
* @param drawTool to draw with
|
||||
@ -398,19 +399,11 @@ export const DrawPDFFields = (props: Props) => {
|
||||
*/
|
||||
const getPdfPages = (pdfFile: PdfFile, pdfFileIndex: number) => {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
width: '100%'
|
||||
}}
|
||||
>
|
||||
<>
|
||||
{pdfFile.pages.map((page, pdfPageIndex: number) => {
|
||||
return (
|
||||
<div
|
||||
key={pdfPageIndex}
|
||||
style={{
|
||||
border: '1px solid #c4c4c4',
|
||||
marginBottom: '10px'
|
||||
}}
|
||||
className={`${styles.pdfImageWrapper} ${selectedTool ? styles.drawing : ''}`}
|
||||
onMouseMove={(event) => {
|
||||
onMouseMove(event, page)
|
||||
@ -516,7 +509,7 @@ export const DrawPDFFields = (props: Props) => {
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</Box>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@ -533,34 +526,26 @@ export const DrawPDFFields = (props: Props) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Box sx={{ mt: 1 }}>
|
||||
<Typography sx={{ mb: 1 }}>Draw fields on the PDFs:</Typography>
|
||||
|
||||
{pdfFiles.map((pdfFile, pdfFileIndex: number) => {
|
||||
return (
|
||||
<Accordion
|
||||
key={pdfFileIndex}
|
||||
expanded={pdfFile.expanded}
|
||||
onChange={(_event, expanded) => {
|
||||
handleAccordionExpandChange(expanded, pdfFile)
|
||||
}}
|
||||
>
|
||||
<AccordionSummary
|
||||
expandIcon={<ExpandMore />}
|
||||
aria-controls={`panel${pdfFileIndex}-content`}
|
||||
id={`panel${pdfFileIndex}header`}
|
||||
<div className={styles.view}>
|
||||
{pdfFiles.map((pdfFile, pdfFileIndex: number) => {
|
||||
return (
|
||||
<>
|
||||
<div className={styles.fileWrapper}>
|
||||
{getPdfPages(pdfFile, pdfFileIndex)}
|
||||
</div>
|
||||
{pdfFileIndex < pdfFiles.length - 1 && (
|
||||
<Divider
|
||||
sx={{
|
||||
fontSize: '12px',
|
||||
color: 'rgba(0,0,0,0.15)'
|
||||
}}
|
||||
>
|
||||
<PictureAsPdf sx={{ mr: 1 }} />
|
||||
{pdfFile.file.name}
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
{getPdfPages(pdfFile, pdfFileIndex)}
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
)
|
||||
})}
|
||||
</Box>
|
||||
File Separator
|
||||
</Divider>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
})}
|
||||
|
||||
{showDrawToolBox && (
|
||||
<Box className={styles.drawToolBoxContainer}>
|
||||
@ -569,7 +554,7 @@ export const DrawPDFFields = (props: Props) => {
|
||||
.filter((drawTool) => drawTool.active)
|
||||
.map((drawTool: DrawTool, index: number) => {
|
||||
return (
|
||||
<Box
|
||||
<div
|
||||
key={index}
|
||||
onClick={() => {
|
||||
handleToolSelect(drawTool)
|
||||
@ -578,12 +563,12 @@ export const DrawPDFFields = (props: Props) => {
|
||||
>
|
||||
{drawTool.icon}
|
||||
{drawTool.label}
|
||||
</Box>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -51,7 +51,6 @@
|
||||
position: relative;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
margin-bottom: 10px;
|
||||
|
||||
> img {
|
||||
display: block;
|
||||
@ -81,7 +80,7 @@
|
||||
}
|
||||
|
||||
&.edited {
|
||||
border: 1px dotted #01aaad
|
||||
border: 1px dotted #01aaad;
|
||||
}
|
||||
|
||||
.resizeHandle {
|
||||
@ -124,3 +123,15 @@
|
||||
padding: 5px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.fileWrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.view {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 25px;
|
||||
}
|
||||
|
@ -64,6 +64,7 @@ import styles from './style.module.scss'
|
||||
import { PdfFile } from '../../types/drawing'
|
||||
import { DrawPDFFields } from '../../components/DrawPDFFields'
|
||||
import { Mark } from '../../types/mark.ts'
|
||||
import { StickySideColumns } from '../../layouts/StickySideColumns.tsx'
|
||||
|
||||
export const CreatePage = () => {
|
||||
const navigate = useNavigate()
|
||||
@ -702,94 +703,110 @@ export const CreatePage = () => {
|
||||
<>
|
||||
{isLoading && <LoadingSpinner desc={loadingSpinnerDesc} />}
|
||||
<Container className={styles.container}>
|
||||
<TextField
|
||||
label="Title"
|
||||
value={title}
|
||||
onChange={(e) => setTitle(e.target.value)}
|
||||
variant="outlined"
|
||||
/>
|
||||
<StickySideColumns
|
||||
left={
|
||||
<>
|
||||
<TextField
|
||||
label="Title"
|
||||
value={title}
|
||||
onChange={(e) => setTitle(e.target.value)}
|
||||
variant="outlined"
|
||||
/>
|
||||
|
||||
<Box>
|
||||
<MuiFileInput
|
||||
fullWidth
|
||||
multiple
|
||||
placeholder="Choose Files"
|
||||
value={selectedFiles}
|
||||
onChange={(value) => handleSelectFiles(value)}
|
||||
<Box>
|
||||
<MuiFileInput
|
||||
fullWidth
|
||||
multiple
|
||||
placeholder="Choose Files"
|
||||
value={selectedFiles}
|
||||
onChange={(value) => handleSelectFiles(value)}
|
||||
/>
|
||||
|
||||
{selectedFiles.length > 0 && (
|
||||
<ul>
|
||||
{selectedFiles.map((file, index) => (
|
||||
<li key={index}>
|
||||
<Typography component="label">{file.name}</Typography>
|
||||
<IconButton onClick={() => handleRemoveFile(file)}>
|
||||
<Clear style={{ color: 'red' }} />{' '}
|
||||
</IconButton>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</Box>
|
||||
</>
|
||||
}
|
||||
right={
|
||||
<>
|
||||
<Typography component="label" variant="h6">
|
||||
Add Counterparts
|
||||
</Typography>
|
||||
<Box className={styles.inputBlock}>
|
||||
<Box className={styles.inputBlock}>
|
||||
<TextField
|
||||
label="nip05 / npub"
|
||||
value={userInput}
|
||||
onChange={(e) => setUserInput(e.target.value)}
|
||||
helperText={error}
|
||||
error={!!error}
|
||||
/>
|
||||
<FormControl fullWidth>
|
||||
<InputLabel id="select-role-label">Role</InputLabel>
|
||||
<Select
|
||||
labelId="select-role-label"
|
||||
id="demo-simple-select"
|
||||
value={userRole}
|
||||
label="Role"
|
||||
onChange={(e) => setUserRole(e.target.value as UserRole)}
|
||||
>
|
||||
<MenuItem value={UserRole.signer}>
|
||||
{UserRole.signer}
|
||||
</MenuItem>
|
||||
<MenuItem value={UserRole.viewer}>
|
||||
{UserRole.viewer}
|
||||
</MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<Box
|
||||
sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}
|
||||
>
|
||||
<Button
|
||||
disabled={!userInput}
|
||||
onClick={handleAddUser}
|
||||
variant="contained"
|
||||
>
|
||||
Add
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<DisplayUser
|
||||
metadata={metadata}
|
||||
users={users}
|
||||
handleUserRoleChange={handleUserRoleChange}
|
||||
handleRemoveUser={handleRemoveUser}
|
||||
moveSigner={moveSigner}
|
||||
/>
|
||||
<Box
|
||||
sx={{ mt: 1, mb: 5, display: 'flex', justifyContent: 'center' }}
|
||||
>
|
||||
<Button onClick={handleCreate} variant="contained">
|
||||
Create
|
||||
</Button>
|
||||
</Box>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<DrawPDFFields
|
||||
metadata={metadata}
|
||||
users={users}
|
||||
selectedFiles={selectedFiles}
|
||||
onDrawFieldsChange={onDrawFieldsChange}
|
||||
/>
|
||||
|
||||
{selectedFiles.length > 0 && (
|
||||
<ul>
|
||||
{selectedFiles.map((file, index) => (
|
||||
<li key={index}>
|
||||
<Typography component="label">{file.name}</Typography>
|
||||
<IconButton onClick={() => handleRemoveFile(file)}>
|
||||
<Clear style={{ color: 'red' }} />{' '}
|
||||
</IconButton>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
<Typography component="label" variant="h6">
|
||||
Add Counterparts
|
||||
</Typography>
|
||||
<Box className={styles.inputBlock}>
|
||||
<Box className={styles.inputBlock}>
|
||||
<TextField
|
||||
label="nip05 / npub"
|
||||
value={userInput}
|
||||
onChange={(e) => setUserInput(e.target.value)}
|
||||
helperText={error}
|
||||
error={!!error}
|
||||
/>
|
||||
<FormControl fullWidth>
|
||||
<InputLabel id="select-role-label">Role</InputLabel>
|
||||
<Select
|
||||
labelId="select-role-label"
|
||||
id="demo-simple-select"
|
||||
value={userRole}
|
||||
label="Role"
|
||||
onChange={(e) => setUserRole(e.target.value as UserRole)}
|
||||
>
|
||||
<MenuItem value={UserRole.signer}>{UserRole.signer}</MenuItem>
|
||||
<MenuItem value={UserRole.viewer}>{UserRole.viewer}</MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}>
|
||||
<Button
|
||||
disabled={!userInput}
|
||||
onClick={handleAddUser}
|
||||
variant="contained"
|
||||
>
|
||||
Add
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<DisplayUser
|
||||
metadata={metadata}
|
||||
users={users}
|
||||
handleUserRoleChange={handleUserRoleChange}
|
||||
handleRemoveUser={handleRemoveUser}
|
||||
moveSigner={moveSigner}
|
||||
/>
|
||||
|
||||
<DrawPDFFields
|
||||
metadata={metadata}
|
||||
users={users}
|
||||
selectedFiles={selectedFiles}
|
||||
onDrawFieldsChange={onDrawFieldsChange}
|
||||
/>
|
||||
|
||||
<Box sx={{ mt: 1, mb: 5, display: 'flex', justifyContent: 'center' }}>
|
||||
<Button onClick={handleCreate} variant="contained">
|
||||
Create
|
||||
</Button>
|
||||
</Box>
|
||||
</StickySideColumns>
|
||||
</Container>
|
||||
</>
|
||||
)
|
||||
|
@ -1,14 +1,6 @@
|
||||
@import '../../styles/colors.scss';
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
color: $text-color;
|
||||
margin-top: 10px;
|
||||
gap: 10px;
|
||||
width: 550px;
|
||||
max-width: 550px;
|
||||
|
||||
.inputBlock {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
Loading…
Reference in New Issue
Block a user