feat(pdf-marking): add pdf-view components
This commit is contained in:
parent
bf167d78f2
commit
b58ba625f9
@ -101,7 +101,7 @@ export const DrawPDFFields = (props: Props) => {
|
|||||||
* It is re rendered and visible right away
|
* It is re rendered and visible right away
|
||||||
*
|
*
|
||||||
* @param event Mouse event
|
* @param event Mouse event
|
||||||
* @param page PdfPage where press happened
|
* @param page PdfItem where press happened
|
||||||
*/
|
*/
|
||||||
const onMouseDown = (event: any, page: PdfPage) => {
|
const onMouseDown = (event: any, page: PdfPage) => {
|
||||||
// Proceed only if left click
|
// Proceed only if left click
|
||||||
@ -154,7 +154,7 @@ export const DrawPDFFields = (props: Props) => {
|
|||||||
* After {@link onMouseDown} create an drawing element, this function gets called on every pixel moved
|
* After {@link onMouseDown} create an drawing element, this function gets called on every pixel moved
|
||||||
* which alters the newly created drawing element, resizing it while mouse move
|
* which alters the newly created drawing element, resizing it while mouse move
|
||||||
* @param event Mouse event
|
* @param event Mouse event
|
||||||
* @param page PdfPage where moving is happening
|
* @param page PdfItem where moving is happening
|
||||||
*/
|
*/
|
||||||
const onMouseMove = (event: any, page: PdfPage) => {
|
const onMouseMove = (event: any, page: PdfPage) => {
|
||||||
if (mouseState.clicked && selectedTool) {
|
if (mouseState.clicked && selectedTool) {
|
||||||
|
0
src/components/PDFView/Mark.tsx
Normal file
0
src/components/PDFView/Mark.tsx
Normal file
28
src/components/PDFView/PdfItem.tsx
Normal file
28
src/components/PDFView/PdfItem.tsx
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { PdfFile } from '../../types/drawing.ts'
|
||||||
|
import { MarkConfigDetails} from '../../types/mark.ts'
|
||||||
|
import PdfPageItem from './PdfPageItem.tsx';
|
||||||
|
|
||||||
|
interface PdfItemProps {
|
||||||
|
pdfFile: PdfFile
|
||||||
|
markConfigDetails: MarkConfigDetails[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const PdfItem = ({ pdfFile, markConfigDetails }: PdfItemProps) => {
|
||||||
|
const filterMarkConfigDetails = (i: number) => {
|
||||||
|
return markConfigDetails.filter(
|
||||||
|
(details) => details.markLocation.page === i);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
pdfFile.pages.map((page, i) => {
|
||||||
|
console.log('page: ', page);
|
||||||
|
return (
|
||||||
|
<PdfPageItem
|
||||||
|
page={page}
|
||||||
|
key={i}
|
||||||
|
markConfigDetails={filterMarkConfigDetails(i)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PdfItem
|
23
src/components/PDFView/PdfMarkItem.tsx
Normal file
23
src/components/PDFView/PdfMarkItem.tsx
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { MarkLocation } from '../../types/mark.ts'
|
||||||
|
import styles from '../DrawPDFFields/style.module.scss'
|
||||||
|
import { inPx } from '../../utils/pdf.ts'
|
||||||
|
|
||||||
|
interface PdfMarkItemProps {
|
||||||
|
markLocation: MarkLocation
|
||||||
|
}
|
||||||
|
|
||||||
|
const PdfMarkItem = ({ markLocation }: PdfMarkItemProps) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={styles.drawingRectangle}
|
||||||
|
style={{
|
||||||
|
left: inPx(markLocation.left),
|
||||||
|
top: inPx(markLocation.top),
|
||||||
|
width: inPx(markLocation.width),
|
||||||
|
height: inPx(markLocation.height)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PdfMarkItem
|
30
src/components/PDFView/PdfPageItem.tsx
Normal file
30
src/components/PDFView/PdfPageItem.tsx
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import styles from '../DrawPDFFields/style.module.scss'
|
||||||
|
import { PdfPage } from '../../types/drawing.ts'
|
||||||
|
import { MarkConfigDetails, MarkLocation } from '../../types/mark.ts'
|
||||||
|
import PdfMarkItem from './PdfMarkItem.tsx'
|
||||||
|
import { useState } from 'react';
|
||||||
|
interface PdfPageProps {
|
||||||
|
page: PdfPage
|
||||||
|
markConfigDetails: MarkConfigDetails[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const PdfPageItem = ({ page, markConfigDetails }: PdfPageProps) => {
|
||||||
|
const [currentMark, setCurrentMark] = useState<MarkLocation | null>(null);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
border: '1px solid #c4c4c4',
|
||||||
|
marginBottom: '10px'
|
||||||
|
}}
|
||||||
|
className={styles.pdfImageWrapper}
|
||||||
|
>
|
||||||
|
<img draggable="false" style={{width: '100%'}} src={page.image} />
|
||||||
|
{markConfigDetails.map((detail, i) => (
|
||||||
|
<PdfMarkItem key={i} markLocation={detail.markLocation} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PdfPageItem
|
45
src/components/PDFView/index.tsx
Normal file
45
src/components/PDFView/index.tsx
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { PdfFile } from '../../types/drawing.ts'
|
||||||
|
import { Box } from '@mui/material'
|
||||||
|
import PdfItem from './PdfItem.tsx'
|
||||||
|
import { MarkConfig, MarkConfigDetails } from '../../types/mark.ts'
|
||||||
|
import { State } from '../../store/rootReducer'
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
import { hexToNpub, npubToHex } from '../../utils'
|
||||||
|
|
||||||
|
interface PdfViewProps {
|
||||||
|
files: { [filename: string]: PdfFile },
|
||||||
|
fileHashes: { [key: string]: string | null },
|
||||||
|
markConfig: MarkConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
const PdfView = (props: PdfViewProps) => {
|
||||||
|
console.log('current file hashes: ', props.fileHashes)
|
||||||
|
const usersPubkey = useSelector((state: State) => state.auth.usersPubkey);
|
||||||
|
if (!usersPubkey) return;
|
||||||
|
console.log(props.markConfig[hexToNpub(usersPubkey)]);
|
||||||
|
|
||||||
|
console.log('users pubkey: ', usersPubkey);
|
||||||
|
console.log('mark config: ', props.markConfig);
|
||||||
|
|
||||||
|
const getMarkConfigDetails = (fileName: string): MarkConfigDetails[] | undefined => {
|
||||||
|
const fileHash = props.fileHashes[fileName];
|
||||||
|
if (!fileHash) return;
|
||||||
|
return props.markConfig[hexToNpub(usersPubkey)][fileHash];
|
||||||
|
}
|
||||||
|
const { files } = props;
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
{Object.entries(files)
|
||||||
|
.filter(([name]) => !!getMarkConfigDetails(name))
|
||||||
|
.map(([name, file], i) => (
|
||||||
|
<PdfItem
|
||||||
|
pdfFile={file}
|
||||||
|
key={i}
|
||||||
|
markConfigDetails={getMarkConfigDetails(name) as MarkConfigDetails[]} />
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PdfView;
|
@ -350,9 +350,17 @@ export const CreatePage = () => {
|
|||||||
if (!markConfig[drawnField.counterpart]) markConfig[drawnField.counterpart] = {}
|
if (!markConfig[drawnField.counterpart]) markConfig[drawnField.counterpart] = {}
|
||||||
if (!markConfig[drawnField.counterpart][fileHash]) markConfig[drawnField.counterpart][fileHash] = []
|
if (!markConfig[drawnField.counterpart][fileHash]) markConfig[drawnField.counterpart][fileHash] = []
|
||||||
|
|
||||||
|
console.log('drawn field: ', drawnField);
|
||||||
|
|
||||||
markConfig[drawnField.counterpart][fileHash].push({
|
markConfig[drawnField.counterpart][fileHash].push({
|
||||||
markType: drawnField.type,
|
markType: drawnField.type,
|
||||||
markLocation: `P:${pageIndex};X:${drawnField.left};Y:${drawnField.top}`
|
markLocation: {
|
||||||
|
page: pageIndex,
|
||||||
|
top: drawnField.top,
|
||||||
|
left: drawnField.left,
|
||||||
|
height: drawnField.height,
|
||||||
|
width: drawnField.width,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -510,6 +518,8 @@ export const CreatePage = () => {
|
|||||||
const viewers = users.filter((user) => user.role === UserRole.viewer)
|
const viewers = users.filter((user) => user.role === UserRole.viewer)
|
||||||
const markConfig = createMarkConfig(fileHashes)
|
const markConfig = createMarkConfig(fileHashes)
|
||||||
|
|
||||||
|
console.log('mark config: ', markConfig)
|
||||||
|
|
||||||
const content: CreateSignatureEventContent = {
|
const content: CreateSignatureEventContent = {
|
||||||
signers: signers.map((signer) => hexToNpub(signer.pubkey)),
|
signers: signers.map((signer) => hexToNpub(signer.pubkey)),
|
||||||
viewers: viewers.map((viewer) => hexToNpub(viewer.pubkey)),
|
viewers: viewers.map((viewer) => hexToNpub(viewer.pubkey)),
|
||||||
@ -519,6 +529,8 @@ export const CreatePage = () => {
|
|||||||
title
|
title
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('content: ', content)
|
||||||
|
|
||||||
setLoadingSpinnerDesc('Signing nostr event for create signature')
|
setLoadingSpinnerDesc('Signing nostr event for create signature')
|
||||||
|
|
||||||
const createSignature = await signEventForMetaFile(
|
const createSignature = await signEventForMetaFile(
|
||||||
|
@ -22,7 +22,7 @@ import {
|
|||||||
generateKeysFile,
|
generateKeysFile,
|
||||||
getHash,
|
getHash,
|
||||||
hexToNpub,
|
hexToNpub,
|
||||||
isOnline,
|
isOnline, loadZip,
|
||||||
now,
|
now,
|
||||||
npubToHex,
|
npubToHex,
|
||||||
parseJson,
|
parseJson,
|
||||||
@ -33,6 +33,10 @@ import {
|
|||||||
} from '../../utils'
|
} from '../../utils'
|
||||||
import { DisplayMeta } from './internal/displayMeta'
|
import { DisplayMeta } from './internal/displayMeta'
|
||||||
import styles from './style.module.scss'
|
import styles from './style.module.scss'
|
||||||
|
import { PdfFile } from '../../types/drawing.ts'
|
||||||
|
import { toFile, toPdfFile } from '../../utils/pdf.ts'
|
||||||
|
import PdfView from '../../components/PDFView'
|
||||||
|
import { MarkConfig } from '../../types/mark.ts'
|
||||||
enum SignedStatus {
|
enum SignedStatus {
|
||||||
Fully_Signed,
|
Fully_Signed,
|
||||||
User_Is_Next_Signer,
|
User_Is_Next_Signer,
|
||||||
@ -58,7 +62,7 @@ export const SignPage = () => {
|
|||||||
|
|
||||||
const [selectedFile, setSelectedFile] = useState<File | null>(null)
|
const [selectedFile, setSelectedFile] = useState<File | null>(null)
|
||||||
|
|
||||||
const [files, setFiles] = useState<{ [filename: string]: ArrayBuffer }>({})
|
const [files, setFiles] = useState<{ [filename: string]: PdfFile }>({})
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(true)
|
const [isLoading, setIsLoading] = useState(true)
|
||||||
const [loadingSpinnerDesc, setLoadingSpinnerDesc] = useState('')
|
const [loadingSpinnerDesc, setLoadingSpinnerDesc] = useState('')
|
||||||
@ -70,6 +74,7 @@ export const SignPage = () => {
|
|||||||
|
|
||||||
const [signers, setSigners] = useState<`npub1${string}`[]>([])
|
const [signers, setSigners] = useState<`npub1${string}`[]>([])
|
||||||
const [viewers, setViewers] = useState<`npub1${string}`[]>([])
|
const [viewers, setViewers] = useState<`npub1${string}`[]>([])
|
||||||
|
const [markConfig, setMarkConfig] = useState<MarkConfig | null>(null)
|
||||||
const [creatorFileHashes, setCreatorFileHashes] = useState<{
|
const [creatorFileHashes, setCreatorFileHashes] = useState<{
|
||||||
[key: string]: string
|
[key: string]: string
|
||||||
}>({})
|
}>({})
|
||||||
@ -178,6 +183,9 @@ export const SignPage = () => {
|
|||||||
setViewers(createSignatureContent.viewers)
|
setViewers(createSignatureContent.viewers)
|
||||||
setCreatorFileHashes(createSignatureContent.fileHashes)
|
setCreatorFileHashes(createSignatureContent.fileHashes)
|
||||||
setSubmittedBy(createSignatureEvent.pubkey)
|
setSubmittedBy(createSignatureEvent.pubkey)
|
||||||
|
setMarkConfig(createSignatureContent.markConfig);
|
||||||
|
|
||||||
|
console.log('createSignatureContent', createSignatureContent)
|
||||||
|
|
||||||
setSignedBy(Object.keys(meta.docSignatures) as `npub1${string}`[])
|
setSignedBy(Object.keys(meta.docSignatures) as `npub1${string}`[])
|
||||||
}
|
}
|
||||||
@ -262,16 +270,13 @@ export const SignPage = () => {
|
|||||||
|
|
||||||
if (!decrypted) return
|
if (!decrypted) return
|
||||||
|
|
||||||
const zip = await JSZip.loadAsync(decrypted).catch((err) => {
|
const zip = await loadZip(decrypted)
|
||||||
console.log('err in loading zip file :>> ', err)
|
if (!zip) {
|
||||||
toast.error(err.message || 'An error occurred in loading zip file.')
|
|
||||||
setIsLoading(false)
|
setIsLoading(false)
|
||||||
return null
|
return
|
||||||
})
|
}
|
||||||
|
|
||||||
if (!zip) return
|
const files: { [filename: string]: PdfFile } = {}
|
||||||
|
|
||||||
const files: { [filename: string]: ArrayBuffer } = {}
|
|
||||||
const fileHashes: { [key: string]: string | null } = {}
|
const fileHashes: { [key: string]: string | null } = {}
|
||||||
const fileNames = Object.values(zip.files).map((entry) => entry.name)
|
const fileNames = Object.values(zip.files).map((entry) => entry.name)
|
||||||
|
|
||||||
@ -285,7 +290,7 @@ export const SignPage = () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (arrayBuffer) {
|
if (arrayBuffer) {
|
||||||
files[fileName] = arrayBuffer
|
files[fileName] = await convertToPdfFile(arrayBuffer, fileName);
|
||||||
|
|
||||||
const hash = await getHash(arrayBuffer)
|
const hash = await getHash(arrayBuffer)
|
||||||
if (hash) {
|
if (hash) {
|
||||||
@ -296,10 +301,17 @@ export const SignPage = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('processed files: ', files);
|
||||||
|
|
||||||
setFiles(files)
|
setFiles(files)
|
||||||
setCurrentFileHashes(fileHashes)
|
setCurrentFileHashes(fileHashes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const convertToPdfFile = async (arrayBuffer: ArrayBuffer, fileName: string) => {
|
||||||
|
const file = toFile(arrayBuffer, fileName);
|
||||||
|
return toPdfFile(file);
|
||||||
|
}
|
||||||
|
|
||||||
const parseKeysJson = async (zip: JSZip) => {
|
const parseKeysJson = async (zip: JSZip) => {
|
||||||
const keysFileContent = await readContentOfZipEntry(
|
const keysFileContent = await readContentOfZipEntry(
|
||||||
zip,
|
zip,
|
||||||
@ -323,11 +335,7 @@ export const SignPage = () => {
|
|||||||
const decrypt = async (file: File) => {
|
const decrypt = async (file: File) => {
|
||||||
setLoadingSpinnerDesc('Decrypting file')
|
setLoadingSpinnerDesc('Decrypting file')
|
||||||
|
|
||||||
const zip = await JSZip.loadAsync(file).catch((err) => {
|
const zip = await loadZip(file);
|
||||||
console.log('err in loading zip file :>> ', err)
|
|
||||||
toast.error(err.message || 'An error occurred in loading zip file.')
|
|
||||||
return null
|
|
||||||
})
|
|
||||||
if (!zip) return
|
if (!zip) return
|
||||||
|
|
||||||
const parsedKeysJson = await parseKeysJson(zip)
|
const parsedKeysJson = await parseKeysJson(zip)
|
||||||
@ -398,32 +406,27 @@ export const SignPage = () => {
|
|||||||
|
|
||||||
setLoadingSpinnerDesc('Parsing zip file')
|
setLoadingSpinnerDesc('Parsing zip file')
|
||||||
|
|
||||||
const zip = await JSZip.loadAsync(decryptedZipFile).catch((err) => {
|
const zip = await loadZip(decryptedZipFile)
|
||||||
console.log('err in loading zip file :>> ', err)
|
|
||||||
toast.error(err.message || 'An error occurred in loading zip file.')
|
|
||||||
return null
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!zip) return
|
if (!zip) return
|
||||||
|
|
||||||
const files: { [filename: string]: ArrayBuffer } = {}
|
const files: { [filename: string]: PdfFile } = {}
|
||||||
const fileHashes: { [key: string]: string | null } = {}
|
const fileHashes: { [key: string]: string | null } = {}
|
||||||
const fileNames = Object.values(zip.files)
|
const fileNames = Object.values(zip.files)
|
||||||
.filter((entry) => entry.name.startsWith('files/') && !entry.dir)
|
.filter((entry) => entry.name.startsWith('files/') && !entry.dir)
|
||||||
.map((entry) => entry.name)
|
.map((entry) => entry.name)
|
||||||
|
.map((entry) => entry.replace(/^files\//, ''))
|
||||||
|
|
||||||
// generate hashes for all entries in files folder of zipArchive
|
// generate hashes for all entries in files folder of zipArchive
|
||||||
// these hashes can be used to verify the originality of files
|
// these hashes can be used to verify the originality of files
|
||||||
for (let fileName of fileNames) {
|
for (const fileName of fileNames) {
|
||||||
const arrayBuffer = await readContentOfZipEntry(
|
const arrayBuffer = await readContentOfZipEntry(
|
||||||
zip,
|
zip,
|
||||||
fileName,
|
fileName,
|
||||||
'arraybuffer'
|
'arraybuffer'
|
||||||
)
|
)
|
||||||
|
|
||||||
fileName = fileName.replace(/^files\//, '')
|
|
||||||
if (arrayBuffer) {
|
if (arrayBuffer) {
|
||||||
files[fileName] = arrayBuffer
|
files[fileName] = await convertToPdfFile(arrayBuffer, fileName);
|
||||||
|
|
||||||
const hash = await getHash(arrayBuffer)
|
const hash = await getHash(arrayBuffer)
|
||||||
if (hash) {
|
if (hash) {
|
||||||
@ -434,6 +437,8 @@ export const SignPage = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('processed files: ', files);
|
||||||
|
|
||||||
setFiles(files)
|
setFiles(files)
|
||||||
setCurrentFileHashes(fileHashes)
|
setCurrentFileHashes(fileHashes)
|
||||||
|
|
||||||
@ -916,6 +921,17 @@ export const SignPage = () => {
|
|||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
{markConfig && (<PdfView
|
||||||
|
files={files}
|
||||||
|
markConfig={markConfig}
|
||||||
|
fileHashes={currentFileHashes}/>)}
|
||||||
|
|
||||||
|
<div
|
||||||
|
className={styles.fixedBottomForm}>
|
||||||
|
<input type="text" placeholder="type here..." />
|
||||||
|
<button>Next</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
@ -34,10 +34,11 @@ import { UserComponent } from '../../../components/username'
|
|||||||
import { MetadataController } from '../../../controllers'
|
import { MetadataController } from '../../../controllers'
|
||||||
import { npubToHex, shorten, hexToNpub, parseJson } from '../../../utils'
|
import { npubToHex, shorten, hexToNpub, parseJson } from '../../../utils'
|
||||||
import styles from '../style.module.scss'
|
import styles from '../style.module.scss'
|
||||||
|
import { PdfFile } from '../../../types/drawing.ts'
|
||||||
|
|
||||||
type DisplayMetaProps = {
|
type DisplayMetaProps = {
|
||||||
meta: Meta
|
meta: Meta
|
||||||
files: { [filename: string]: ArrayBuffer }
|
files: { [filename: string]: PdfFile }
|
||||||
submittedBy: string
|
submittedBy: string
|
||||||
signers: `npub1${string}`[]
|
signers: `npub1${string}`[]
|
||||||
viewers: `npub1${string}`[]
|
viewers: `npub1${string}`[]
|
||||||
@ -143,7 +144,7 @@ export const DisplayMeta = ({
|
|||||||
}, [users, submittedBy])
|
}, [users, submittedBy])
|
||||||
|
|
||||||
const downloadFile = async (filename: string) => {
|
const downloadFile = async (filename: string) => {
|
||||||
const arrayBuffer = files[filename]
|
const arrayBuffer = await files[filename].file.arrayBuffer()
|
||||||
if (!arrayBuffer) return
|
if (!arrayBuffer) return
|
||||||
|
|
||||||
const blob = new Blob([arrayBuffer])
|
const blob = new Blob([arrayBuffer])
|
||||||
|
@ -47,4 +47,36 @@
|
|||||||
@extend .user;
|
@extend .user;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fixedBottomForm {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
width: 50%;
|
||||||
|
border-top: 1px solid #ccc;
|
||||||
|
box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.1);
|
||||||
|
padding: 10px 20px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fixedBottomForm input[type="text"] {
|
||||||
|
width: 80%;
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 16px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fixedBottomForm button {
|
||||||
|
background-color: #3f3d56;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
padding: 10px 20px;
|
||||||
|
font-size: 16px;
|
||||||
|
margin-left: 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,15 @@ export interface MarkConfigDetails {
|
|||||||
/**
|
/**
|
||||||
* Coordinates in format: X:10;Y:50
|
* Coordinates in format: X:10;Y:50
|
||||||
*/
|
*/
|
||||||
markLocation: string;
|
markLocation: MarkLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarkLocation {
|
||||||
|
top: number;
|
||||||
|
left: number;
|
||||||
|
height: number;
|
||||||
|
width: number;
|
||||||
|
page: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creator Meta Object Example
|
// Creator Meta Object Example
|
||||||
|
@ -10,4 +10,17 @@ export interface OutputByType {
|
|||||||
nodebuffer: Buffer
|
nodebuffer: Buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface InputByType {
|
||||||
|
base64: string;
|
||||||
|
string: string;
|
||||||
|
text: string;
|
||||||
|
binarystring: string;
|
||||||
|
array: number[];
|
||||||
|
uint8array: Uint8Array;
|
||||||
|
arraybuffer: ArrayBuffer;
|
||||||
|
blob: Blob;
|
||||||
|
stream: NodeJS.ReadableStream;
|
||||||
|
}
|
||||||
|
|
||||||
export type OutputType = keyof OutputByType
|
export type OutputType = keyof OutputByType
|
||||||
|
export type InputFileFormat = InputByType[keyof InputByType] | Promise<InputByType[keyof InputByType]>;
|
@ -20,6 +20,8 @@ const toPdfFiles = async (selectedFiles: File[]): Promise<PdfFile[]> => {
|
|||||||
.map(toPdfFile));
|
.map(toPdfFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const inPx = (coordinate: number): string => `${coordinate}px`;
|
||||||
|
|
||||||
const isPdf = (file: File) => file.type.toLowerCase().includes('pdf');
|
const isPdf = (file: File) => file.type.toLowerCase().includes('pdf');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -74,5 +76,6 @@ const pdfToImages = async (data: any): Promise<PdfPage[]> => {
|
|||||||
export {
|
export {
|
||||||
toFile,
|
toFile,
|
||||||
toPdfFile,
|
toPdfFile,
|
||||||
toPdfFiles
|
toPdfFiles,
|
||||||
|
inPx
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
import JSZip from 'jszip'
|
import JSZip from 'jszip'
|
||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
import { OutputByType, OutputType } from '../types'
|
import { InputFileFormat, OutputByType, OutputType } from '../types'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the content of a file within a zip archive.
|
* Read the content of a file within a zip archive.
|
||||||
@ -9,7 +9,7 @@ import { OutputByType, OutputType } from '../types'
|
|||||||
* @param outputType The type of output to return (e.g., 'string', 'arraybuffer', 'uint8array', etc.).
|
* @param outputType The type of output to return (e.g., 'string', 'arraybuffer', 'uint8array', etc.).
|
||||||
* @returns A Promise resolving to the content of the file, or null if an error occurs.
|
* @returns A Promise resolving to the content of the file, or null if an error occurs.
|
||||||
*/
|
*/
|
||||||
export const readContentOfZipEntry = async <T extends OutputType>(
|
const readContentOfZipEntry = async <T extends OutputType>(
|
||||||
zip: JSZip,
|
zip: JSZip,
|
||||||
filePath: string,
|
filePath: string,
|
||||||
outputType: T
|
outputType: T
|
||||||
@ -35,3 +35,20 @@ export const readContentOfZipEntry = async <T extends OutputType>(
|
|||||||
// Return the file content or null if an error occurred
|
// Return the file content or null if an error occurred
|
||||||
return fileContent
|
return fileContent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const loadZip = async (data: InputFileFormat): Promise<JSZip | null> => {
|
||||||
|
try {
|
||||||
|
return await JSZip.loadAsync(data);
|
||||||
|
} catch (err: any) {
|
||||||
|
console.log('err in loading zip file :>> ', err)
|
||||||
|
toast.error(err.message || 'An error occurred in loading zip file.')
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
readContentOfZipEntry,
|
||||||
|
loadZip
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user