Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: View PDF document preview when adding a document #689

Merged
merged 5 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"@testing-library/jest-dom": "6.6.2",
"@testing-library/react": "16.0.1",
"@testing-library/react-hooks": "8.0.1",
"@types/react-pdf": "^5.0.0",
"@typescript-eslint/eslint-plugin": "5.54.0",
"@typescript-eslint/parser": "5.54.0",
"babel-preset-cozy-app": "2.0.2",
Expand Down Expand Up @@ -105,6 +106,7 @@
"react-dom": "18.2.0",
"react-input-mask": "3.0.0-alpha.2",
"react-inspector": "5.1.1",
"react-pdf": "^5.7.2",
"react-router-dom": "6.23.1",
"terser-webpack-plugin": "1.4.5"
}
Expand Down
96 changes: 0 additions & 96 deletions src/components/ModelSteps/ScanResult/ScanResultCard.jsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import PropTypes from 'prop-types'
import React, { forwardRef } from 'react'
import { useFormData } from 'src/components/Contexts/FormDataProvider'
import { useStepperDialog } from 'src/components/Contexts/StepperDialogProvider'
import ScanResultCardImage from 'src/components/ModelSteps/ScanResult/ScanResultCard/ScanResultCardImage'
import ScanResultCardPDF from 'src/components/ModelSteps/ScanResult/ScanResultCard/ScanResultCardPDF'
import {
getLastFormDataFile,
isSameFile
} from 'src/components/ModelSteps/helpers'

const ScanResultCard = forwardRef((props, ref) => {
const { currentFile, setCurrentFile } = props
const { setFormData, formData } = useFormData()
const { currentStepIndex } = useStepperDialog()

const handleSelectedFile = () => {
const newData = formData.data.filter(
data => !isSameFile(currentFile, data.file)
)
setCurrentFile(
getLastFormDataFile({ formData: { data: newData }, currentStepIndex })
)

setFormData(prev => ({
...prev,
data: newData
}))
}

if (currentFile.type === 'application/pdf') {
return (
<ScanResultCardPDF {...props} handleSelectedFile={handleSelectedFile} />
)
}

return (
<ScanResultCardImage
{...props}
handleSelectedFile={handleSelectedFile}
ref={ref}
/>
)
})

ScanResultCard.displayName = 'ScanResultCard'

ScanResultCard.propTypes = {
currentFile: PropTypes.object.isRequired,
setCurrentFile: PropTypes.func.isRequired,
setRotationImage: PropTypes.func.isRequired,
rotationImage: PropTypes.number.isRequired
}

export default ScanResultCard
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,16 @@
width 100%
padding-top 100%
position relative

.image-container:before
content ""
display block
margin-top -100%

.image-container
display flex
flex-direction column
align-items center
justify-content center

&:before
content ""
display block
margin-top -100%

& > img
position absolute
top 0
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import PropTypes from 'prop-types'
import React, { useState, forwardRef } from 'react'
import styles from 'src/components/ModelSteps/ScanResult/ScanResultCard/ScanResultCard.styl'
import ScanResultCardImageActions from 'src/components/ModelSteps/ScanResult/ScanResultCard/ScanResultCardImageActions'
import RotateImage from 'src/components/ModelSteps/widgets/RotateImage'

import Box from 'cozy-ui/transpiled/react/Box'
import Card from 'cozy-ui/transpiled/react/Card'

const ScanResultCardImage = forwardRef((props, ref) => {
const { currentFile, handleSelectedFile, setRotationImage, rotationImage } =
props
const [imgWrapperMinHeight, setImgWrapperMinHeight] = useState(0)
const [isImageRotating, setIsImageRotating] = useState(false)

const handleRotate = () => {
setIsImageRotating(true)
setRotationImage(prev => prev - 90)
}

const handleImageLoaded = () => {
setIsImageRotating(false)
// We don't want to recalculate the size on every rotation
if (ref.current && imgWrapperMinHeight === 0) {
const maxSize = Math.max(
ref.current.offsetWidth,
ref.current.offsetHeight
)
setImgWrapperMinHeight(maxSize)
}
}

return (
<Card className="u-ta-center u-p-1 u-flex u-flex-column u-flex-justify-between">
<div className={styles['image-container']}>
<RotateImage
image={URL.createObjectURL(currentFile)}
onLoaded={handleImageLoaded}
rotation={rotationImage}
a11n={{ 'aria-hidden': true }}
ref={ref}
/>
</div>
<Box display="flex" gridGap="1rem" marginTop="1rem">
<ScanResultCardImageActions
onRotate={handleRotate}
onCancel={handleSelectedFile}
isImageRotating={isImageRotating}
/>
</Box>
</Card>
)
})
ScanResultCardImage.displayName = 'ScanResultCardImage'

ScanResultCardImage.propTypes = {
currentFile: PropTypes.object.isRequired,
handleSelectedFile: PropTypes.func.isRequired,
setRotationImage: PropTypes.func.isRequired,
rotationImage: PropTypes.number.isRequired
}

export default ScanResultCardImage
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ const useStyles = makeStyles(theme => ({
}
}))

const ScanResultCardActions = ({ onRotate, onCancel, isImageRotating }) => {
const ScanResultCardImageActions = ({
onRotate,
onCancel,
isImageRotating
}) => {
const classes = useStyles()
const { t } = useI18n()
const { isDesktop } = useBreakpoints()
Expand Down Expand Up @@ -49,10 +53,10 @@ const ScanResultCardActions = ({ onRotate, onCancel, isImageRotating }) => {
)
}

ScanResultCardActions.propTypes = {
ScanResultCardImageActions.propTypes = {
onCancel: PropTypes.func,
onRotate: PropTypes.func,
isImageRotating: PropTypes.bool
}

export default ScanResultCardActions
export default ScanResultCardImageActions
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import PropTypes from 'prop-types'
import React from 'react'
import styles from 'src/components/ModelSteps/ScanResult/ScanResultCard/ScanResultCard.styl'
import ScanResultCardPDFActions from 'src/components/ModelSteps/ScanResult/ScanResultCard/ScanResultCardPDFActions'
import { PdfOverview } from 'src/components/PdfOverview/PdfOverview'

import Box from 'cozy-ui/transpiled/react/Box'
import Card from 'cozy-ui/transpiled/react/Card'
import Typography from 'cozy-ui/transpiled/react/Typography'

const ScanResultCardPDF = props => {
const { currentFile, handleSelectedFile } = props

return (
<Card className="u-ta-center u-p-1 u-flex u-flex-column u-flex-justify-between">
<div className={styles['image-container']}>
<PdfOverview file={currentFile} />
<Typography className="u-mt-half">{currentFile.name}</Typography>
</div>
<Box display="flex" gridGap="1rem" marginTop="1rem">
<ScanResultCardPDFActions onCancel={handleSelectedFile} />
</Box>
</Card>
)
}

ScanResultCardPDF.propTypes = {
currentFile: PropTypes.object.isRequired,
handleSelectedFile: PropTypes.func.isRequired
}

export default ScanResultCardPDF
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import PropTypes from 'prop-types'
import React from 'react'

import Button from 'cozy-ui/transpiled/react/Buttons'
import useBreakpoints from 'cozy-ui/transpiled/react/providers/Breakpoints'
import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'

const ScanResultCardPDFActions = ({ onCancel }) => {
const { t } = useI18n()
const { isDesktop } = useBreakpoints()

const device = isDesktop ? 'desktop' : 'mobile'

return (
<Button
data-testid="retry-button"
label={t(`Acquisition.${device}.retry`)}
fullWidth
variant="secondary"
onClick={onCancel}
/>
)
}

ScanResultCardPDFActions.propTypes = {
onCancel: PropTypes.func
}

export default ScanResultCardPDFActions
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import CompositeHeaderImage from 'src/components/CompositeHeader/CompositeHeader
import { useFormData } from 'src/components/Contexts/FormDataProvider'
import { useStepperDialog } from 'src/components/Contexts/StepperDialogProvider'
import OcrProcessingDialog from 'src/components/ModelSteps/ScanResult/OcrProcessingDialog'
import ScanResultCard from 'src/components/ModelSteps/ScanResult/ScanResultCard'
import ScanResultCard from 'src/components/ModelSteps/ScanResult/ScanResultCard/ScanResultCard'
import ScanResultTitle from 'src/components/ModelSteps/ScanResult/ScanResultTitle'
import { makeFileFromBase64 } from 'src/components/ModelSteps/helpers'
import StepperDialogTitle from 'src/components/StepperDialog/StepperDialogTitle'
Expand Down
39 changes: 39 additions & 0 deletions src/components/PdfOverview/PdfOverview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React, { useEffect, useRef, useState } from 'react'
import { Document, Page } from 'react-pdf'

interface PdfOverviewProps {
file: File
}

const styles = {
container: {
width: '100%',
display: 'flex',
justifyContent: 'center'
}
}

export const PdfOverview: React.FC<PdfOverviewProps> = ({
file
}: PdfOverviewProps) => {
const parentRef = useRef<HTMLDivElement | null>(null)
const [parentWidth, setParentWidth] = useState(0)

useEffect(() => {
const updateSize = (): void => {
if (parentRef.current) {
const width = parentRef.current.getBoundingClientRect().width
setParentWidth(width)
}
}
updateSize()
}, [])
Merkur39 marked this conversation as resolved.
Show resolved Hide resolved

return (
<div style={styles.container} ref={parentRef}>
<Document file={file}>
<Page pageNumber={1} width={parentWidth} />
</Document>
</div>
)
}
Loading
Loading