feat(create-page): intial layout and page styling
Additional linting fixes
This commit is contained in:
parent
18637bbbc1
commit
86c8cc00fd
@ -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 }}>
|
|
||||||
<Typography sx={{ mb: 1 }}>Draw fields on the PDFs:</Typography>
|
|
||||||
|
|
||||||
{pdfFiles.map((pdfFile, pdfFileIndex: number) => {
|
{pdfFiles.map((pdfFile, pdfFileIndex: number) => {
|
||||||
return (
|
return (
|
||||||
<Accordion
|
<>
|
||||||
key={pdfFileIndex}
|
<div className={styles.fileWrapper}>
|
||||||
expanded={pdfFile.expanded}
|
{getPdfPages(pdfFile, pdfFileIndex)}
|
||||||
onChange={(_event, expanded) => {
|
</div>
|
||||||
handleAccordionExpandChange(expanded, pdfFile)
|
{pdfFileIndex < pdfFiles.length - 1 && (
|
||||||
|
<Divider
|
||||||
|
sx={{
|
||||||
|
fontSize: '12px',
|
||||||
|
color: 'rgba(0,0,0,0.15)'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<AccordionSummary
|
File Separator
|
||||||
expandIcon={<ExpandMore />}
|
</Divider>
|
||||||
aria-controls={`panel${pdfFileIndex}-content`}
|
)}
|
||||||
id={`panel${pdfFileIndex}header`}
|
</>
|
||||||
>
|
|
||||||
<PictureAsPdf sx={{ mr: 1 }} />
|
|
||||||
{pdfFile.file.name}
|
|
||||||
</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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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,6 +703,9 @@ export const CreatePage = () => {
|
|||||||
<>
|
<>
|
||||||
{isLoading && <LoadingSpinner desc={loadingSpinnerDesc} />}
|
{isLoading && <LoadingSpinner desc={loadingSpinnerDesc} />}
|
||||||
<Container className={styles.container}>
|
<Container className={styles.container}>
|
||||||
|
<StickySideColumns
|
||||||
|
left={
|
||||||
|
<>
|
||||||
<TextField
|
<TextField
|
||||||
label="Title"
|
label="Title"
|
||||||
value={title}
|
value={title}
|
||||||
@ -731,7 +735,10 @@ export const CreatePage = () => {
|
|||||||
</ul>
|
</ul>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
right={
|
||||||
|
<>
|
||||||
<Typography component="label" variant="h6">
|
<Typography component="label" variant="h6">
|
||||||
Add Counterparts
|
Add Counterparts
|
||||||
</Typography>
|
</Typography>
|
||||||
@ -753,12 +760,18 @@ export const CreatePage = () => {
|
|||||||
label="Role"
|
label="Role"
|
||||||
onChange={(e) => setUserRole(e.target.value as UserRole)}
|
onChange={(e) => setUserRole(e.target.value as UserRole)}
|
||||||
>
|
>
|
||||||
<MenuItem value={UserRole.signer}>{UserRole.signer}</MenuItem>
|
<MenuItem value={UserRole.signer}>
|
||||||
<MenuItem value={UserRole.viewer}>{UserRole.viewer}</MenuItem>
|
{UserRole.signer}
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem value={UserRole.viewer}>
|
||||||
|
{UserRole.viewer}
|
||||||
|
</MenuItem>
|
||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}>
|
<Box
|
||||||
|
sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
disabled={!userInput}
|
disabled={!userInput}
|
||||||
onClick={handleAddUser}
|
onClick={handleAddUser}
|
||||||
@ -777,19 +790,23 @@ export const CreatePage = () => {
|
|||||||
handleRemoveUser={handleRemoveUser}
|
handleRemoveUser={handleRemoveUser}
|
||||||
moveSigner={moveSigner}
|
moveSigner={moveSigner}
|
||||||
/>
|
/>
|
||||||
|
<Box
|
||||||
|
sx={{ mt: 1, mb: 5, display: 'flex', justifyContent: 'center' }}
|
||||||
|
>
|
||||||
|
<Button onClick={handleCreate} variant="contained">
|
||||||
|
Create
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
>
|
||||||
<DrawPDFFields
|
<DrawPDFFields
|
||||||
metadata={metadata}
|
metadata={metadata}
|
||||||
users={users}
|
users={users}
|
||||||
selectedFiles={selectedFiles}
|
selectedFiles={selectedFiles}
|
||||||
onDrawFieldsChange={onDrawFieldsChange}
|
onDrawFieldsChange={onDrawFieldsChange}
|
||||||
/>
|
/>
|
||||||
|
</StickySideColumns>
|
||||||
<Box sx={{ mt: 1, mb: 5, display: 'flex', justifyContent: 'center' }}>
|
|
||||||
<Button onClick={handleCreate} variant="contained">
|
|
||||||
Create
|
|
||||||
</Button>
|
|
||||||
</Box>
|
|
||||||
</Container>
|
</Container>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user