feat(create-page): intial layout and page styling

Additional linting fixes
This commit is contained in:
enes 2024-08-15 18:57:40 +02:00
parent 18637bbbc1
commit 86c8cc00fd
4 changed files with 188 additions and 183 deletions

View File

@ -1,20 +1,15 @@
import { import {
AccessTime, AccessTime,
CalendarMonth, CalendarMonth,
ExpandMore,
Gesture, Gesture,
PictureAsPdf,
Badge, Badge,
Work, Work,
Close Close
} from '@mui/icons-material' } from '@mui/icons-material'
import { import {
Box, Box,
Typography,
Accordion,
AccordionDetails,
AccordionSummary,
CircularProgress, CircularProgress,
Divider,
FormControl, FormControl,
InputLabel, InputLabel,
MenuItem, MenuItem,
@ -53,7 +48,7 @@ export const DrawPDFFields = (props: Props) => {
const [pdfFiles, setPdfFiles] = useState<PdfFile[]>([]) const [pdfFiles, setPdfFiles] = useState<PdfFile[]>([])
const [parsingPdf, setParsingPdf] = useState<boolean>(false) const [parsingPdf, setParsingPdf] = useState<boolean>(false)
const [showDrawToolBox, setShowDrawToolBox] = useState<boolean>(false) const [showDrawToolBox] = useState<boolean>(true)
const [selectedTool, setSelectedTool] = useState<DrawTool | null>() const [selectedTool, setSelectedTool] = useState<DrawTool | null>()
const [toolbox] = useState<DrawTool[]>([ const [toolbox] = useState<DrawTool[]>([
@ -95,6 +90,16 @@ export const DrawPDFFields = (props: Props) => {
useEffect(() => { useEffect(() => {
if (selectedFiles) { 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) setParsingPdf(true)
parsePdfPages().finally(() => { parsePdfPages().finally(() => {
@ -105,7 +110,7 @@ export const DrawPDFFields = (props: Props) => {
useEffect(() => { useEffect(() => {
if (pdfFiles) props.onDrawFieldsChange(pdfFiles) if (pdfFiles) props.onDrawFieldsChange(pdfFiles)
}, [pdfFiles]) }, [pdfFiles, props])
/** /**
* Drawing events * Drawing events
@ -132,12 +137,15 @@ export const DrawPDFFields = (props: Props) => {
* @param event Mouse event * @param event Mouse event
* @param page PdfPage where press happened * @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 // Proceed only if left click
if (event.button !== 0) return if (event.button !== 0) return
// Only allow drawing if mouse is not over other drawn element // 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) { if (!selectedTool || !isOverPdfImageWrapper) {
return return
@ -185,7 +193,10 @@ export const DrawPDFFields = (props: Props) => {
* @param event Mouse event * @param event Mouse event
* @param page PdfPage where moving is happening * @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) { if (mouseState.clicked && selectedTool) {
const lastElementIndex = page.drawnFields.length - 1 const lastElementIndex = page.drawnFields.length - 1
const lastDrawnField = page.drawnFields[lastElementIndex] const lastDrawnField = page.drawnFields[lastElementIndex]
@ -216,7 +227,9 @@ export const DrawPDFFields = (props: Props) => {
* @param event Mouse event * @param event Mouse event
* @param drawnField Which we are moving * @param drawnField Which we are moving
*/ */
const onDrawnFieldMouseDown = (event: any) => { const onDrawnFieldMouseDown = (
event: React.MouseEvent<HTMLDivElement, MouseEvent>
) => {
event.stopPropagation() event.stopPropagation()
// Proceed only if left click // Proceed only if left click
@ -239,11 +252,14 @@ export const DrawPDFFields = (props: Props) => {
* @param event Mouse event * @param event Mouse event
* @param drawnField which we are moving * @param drawnField which we are moving
*/ */
const onDranwFieldMouseMove = (event: any, drawnField: DrawnField) => { const onDranwFieldMouseMove = (
event: React.MouseEvent<HTMLDivElement, MouseEvent>,
drawnField: DrawnField
) => {
if (mouseState.dragging) { if (mouseState.dragging) {
const { mouseX, mouseY, rect } = getMouseCoordinates( const { mouseX, mouseY, rect } = getMouseCoordinates(
event, event,
event.target.parentNode event.currentTarget.parentNode as HTMLElement
) )
const coordsOffset = mouseState.coordsInWrapper const coordsOffset = mouseState.coordsInWrapper
@ -272,7 +288,9 @@ export const DrawPDFFields = (props: Props) => {
* @param event Mouse event * @param event Mouse event
* @param drawnField which we are resizing * @param drawnField which we are resizing
*/ */
const onResizeHandleMouseDown = (event: any) => { const onResizeHandleMouseDown = (
event: React.MouseEvent<HTMLSpanElement, MouseEvent>
) => {
// Proceed only if left click // Proceed only if left click
if (event.button !== 0) return if (event.button !== 0) return
@ -288,11 +306,14 @@ export const DrawPDFFields = (props: Props) => {
* @param event Mouse event * @param event Mouse event
* @param drawnField which we are resizing * @param drawnField which we are resizing
*/ */
const onResizeHandleMouseMove = (event: any, drawnField: DrawnField) => { const onResizeHandleMouseMove = (
event: React.MouseEvent<HTMLSpanElement, MouseEvent>,
drawnField: DrawnField
) => {
if (mouseState.resizing) { if (mouseState.resizing) {
const { mouseX, mouseY } = getMouseCoordinates( const { mouseX, mouseY } = getMouseCoordinates(
event, event,
event.target.parentNode.parentNode event.currentTarget.parentNode as HTMLElement
) )
const width = mouseX - drawnField.left const width = mouseX - drawnField.left
@ -313,7 +334,7 @@ export const DrawPDFFields = (props: Props) => {
* @param drawnFileIndex drawn file index * @param drawnFileIndex drawn file index
*/ */
const onRemoveHandleMouseDown = ( const onRemoveHandleMouseDown = (
event: any, event: React.MouseEvent<HTMLSpanElement, MouseEvent>,
pdfFileIndex: number, pdfFileIndex: number,
pdfPageIndex: number, pdfPageIndex: number,
drawnFileIndex: number drawnFileIndex: number
@ -331,7 +352,9 @@ export const DrawPDFFields = (props: Props) => {
* so select can work properly * so select can work properly
* @param event Mouse event * @param event Mouse event
*/ */
const onUserSelectHandleMouseDown = (event: any) => { const onUserSelectHandleMouseDown = (
event: React.MouseEvent<HTMLDivElement, MouseEvent>
) => {
event.stopPropagation() event.stopPropagation()
} }
@ -341,8 +364,11 @@ export const DrawPDFFields = (props: Props) => {
* @param customTarget mouse coordinates relative to this element, if not provided * @param customTarget mouse coordinates relative to this element, if not provided
* event.target will be used * event.target will be used
*/ */
const getMouseCoordinates = (event: any, customTarget?: any) => { const getMouseCoordinates = (
const target = customTarget ? customTarget : event.target event: React.MouseEvent<HTMLElement, MouseEvent>,
customTarget?: HTMLElement
) => {
const target = customTarget ? customTarget : event.currentTarget
const rect = target.getBoundingClientRect() const rect = target.getBoundingClientRect()
const mouseX = event.clientX - rect.left //x position within the element. const mouseX = event.clientX - rect.left //x position within the element.
const mouseY = event.clientY - rect.top //y 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 * Changes the drawing tool
* @param drawTool to draw with * @param drawTool to draw with
@ -398,19 +399,11 @@ export const DrawPDFFields = (props: Props) => {
*/ */
const getPdfPages = (pdfFile: PdfFile, pdfFileIndex: number) => { const getPdfPages = (pdfFile: PdfFile, pdfFileIndex: number) => {
return ( return (
<Box <>
sx={{
width: '100%'
}}
>
{pdfFile.pages.map((page, pdfPageIndex: number) => { {pdfFile.pages.map((page, pdfPageIndex: number) => {
return ( return (
<div <div
key={pdfPageIndex} key={pdfPageIndex}
style={{
border: '1px solid #c4c4c4',
marginBottom: '10px'
}}
className={`${styles.pdfImageWrapper} ${selectedTool ? styles.drawing : ''}`} className={`${styles.pdfImageWrapper} ${selectedTool ? styles.drawing : ''}`}
onMouseMove={(event) => { onMouseMove={(event) => {
onMouseMove(event, page) onMouseMove(event, page)
@ -516,7 +509,7 @@ export const DrawPDFFields = (props: Props) => {
</div> </div>
) )
})} })}
</Box> </>
) )
} }
@ -533,34 +526,26 @@ export const DrawPDFFields = (props: Props) => {
} }
return ( return (
<Box> <div className={styles.view}>
<Box sx={{ mt: 1 }}> {pdfFiles.map((pdfFile, pdfFileIndex: number) => {
<Typography sx={{ mb: 1 }}>Draw fields on the PDFs:</Typography> return (
<>
{pdfFiles.map((pdfFile, pdfFileIndex: number) => { <div className={styles.fileWrapper}>
return ( {getPdfPages(pdfFile, pdfFileIndex)}
<Accordion </div>
key={pdfFileIndex} {pdfFileIndex < pdfFiles.length - 1 && (
expanded={pdfFile.expanded} <Divider
onChange={(_event, expanded) => { sx={{
handleAccordionExpandChange(expanded, pdfFile) fontSize: '12px',
}} color: 'rgba(0,0,0,0.15)'
> }}
<AccordionSummary
expandIcon={<ExpandMore />}
aria-controls={`panel${pdfFileIndex}-content`}
id={`panel${pdfFileIndex}header`}
> >
<PictureAsPdf sx={{ mr: 1 }} /> File Separator
{pdfFile.file.name} </Divider>
</AccordionSummary> )}
<AccordionDetails> </>
{getPdfPages(pdfFile, pdfFileIndex)} )
</AccordionDetails> })}
</Accordion>
)
})}
</Box>
{showDrawToolBox && ( {showDrawToolBox && (
<Box className={styles.drawToolBoxContainer}> <Box className={styles.drawToolBoxContainer}>
@ -569,7 +554,7 @@ export const DrawPDFFields = (props: Props) => {
.filter((drawTool) => drawTool.active) .filter((drawTool) => drawTool.active)
.map((drawTool: DrawTool, index: number) => { .map((drawTool: DrawTool, index: number) => {
return ( return (
<Box <div
key={index} key={index}
onClick={() => { onClick={() => {
handleToolSelect(drawTool) handleToolSelect(drawTool)
@ -578,12 +563,12 @@ export const DrawPDFFields = (props: Props) => {
> >
{drawTool.icon} {drawTool.icon}
{drawTool.label} {drawTool.label}
</Box> </div>
) )
})} })}
</Box> </Box>
</Box> </Box>
)} )}
</Box> </div>
) )
} }

View File

@ -51,7 +51,6 @@
position: relative; position: relative;
-webkit-user-select: none; -webkit-user-select: none;
user-select: none; user-select: none;
margin-bottom: 10px;
> img { > img {
display: block; display: block;
@ -81,7 +80,7 @@
} }
&.edited { &.edited {
border: 1px dotted #01aaad border: 1px dotted #01aaad;
} }
.resizeHandle { .resizeHandle {
@ -124,3 +123,15 @@
padding: 5px 0; padding: 5px 0;
} }
} }
.fileWrapper {
display: flex;
flex-direction: column;
gap: 15px;
}
.view {
display: flex;
flex-direction: column;
gap: 25px;
}

View File

@ -64,6 +64,7 @@ import styles from './style.module.scss'
import { PdfFile } from '../../types/drawing' import { 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'
export const CreatePage = () => { export const CreatePage = () => {
const navigate = useNavigate() const navigate = useNavigate()
@ -702,94 +703,110 @@ export const CreatePage = () => {
<> <>
{isLoading && <LoadingSpinner desc={loadingSpinnerDesc} />} {isLoading && <LoadingSpinner desc={loadingSpinnerDesc} />}
<Container className={styles.container}> <Container className={styles.container}>
<TextField <StickySideColumns
label="Title" left={
value={title} <>
onChange={(e) => setTitle(e.target.value)} <TextField
variant="outlined" label="Title"
/> value={title}
onChange={(e) => setTitle(e.target.value)}
variant="outlined"
/>
<Box> <Box>
<MuiFileInput <MuiFileInput
fullWidth fullWidth
multiple multiple
placeholder="Choose Files" placeholder="Choose Files"
value={selectedFiles} value={selectedFiles}
onChange={(value) => handleSelectFiles(value)} 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}
/> />
</StickySideColumns>
{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>
</Container> </Container>
</> </>
) )

View File

@ -1,14 +1,6 @@
@import '../../styles/colors.scss'; @import '../../styles/colors.scss';
.container { .container {
display: flex;
flex-direction: column;
color: $text-color;
margin-top: 10px;
gap: 10px;
width: 550px;
max-width: 550px;
.inputBlock { .inputBlock {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -38,4 +30,4 @@
cursor: pointer; cursor: pointer;
} }
} }
} }