feat: zoom doc and delete area
This commit is contained in:
parent
f0d0c609b3
commit
49db0aff66
@ -1,19 +1,26 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import React, { useEffect, useRef } from 'react'
|
import { MagnifyingGlassMinusIcon, MagnifyingGlassPlusIcon } from '@heroicons/react/24/outline'
|
||||||
|
import React, { useEffect, useRef, useState, WheelEvent } from 'react'
|
||||||
import { useProject } from '../../context/Project/provider'
|
import { useProject } from '../../context/Project/provider'
|
||||||
import loadImage from '../../useCases/loadImage'
|
import loadImage from '../../useCases/loadImage'
|
||||||
import processImageArea from '../../useCases/processImageArea'
|
import processImageArea from '../../useCases/processImageArea'
|
||||||
|
import classNames from '../../utils/classNames'
|
||||||
import LanguageSelect from './LanguageSelect'
|
import LanguageSelect from './LanguageSelect'
|
||||||
|
|
||||||
|
const zoomStep = 0.05
|
||||||
|
const maxZoomLevel = 4
|
||||||
|
|
||||||
const DocumentRenderer = () => {
|
const DocumentRenderer = () => {
|
||||||
const { getSelectedDocument, requestAddArea } = useProject()
|
const { getSelectedDocument, requestAddArea, selectedAreaId, setSelectedAreaId } = useProject()
|
||||||
const selectedDocument = getSelectedDocument()
|
const selectedDocument = getSelectedDocument()
|
||||||
const areas = selectedDocument?.areas
|
const areas = selectedDocument?.areas
|
||||||
const documentCanvas = useRef<HTMLCanvasElement>(null)
|
const documentCanvas = useRef<HTMLCanvasElement>(null)
|
||||||
const areaCanvas = useRef<HTMLCanvasElement>(null)
|
const areaCanvas = useRef<HTMLCanvasElement>(null)
|
||||||
const drawingCanvas = useRef<HTMLCanvasElement>(null)
|
const drawingCanvas = useRef<HTMLCanvasElement>(null)
|
||||||
|
|
||||||
|
const [zoomLevel, setZoomLevel] = useState(1)
|
||||||
|
|
||||||
let downClickX = 0
|
let downClickX = 0
|
||||||
let downClickY = 0
|
let downClickY = 0
|
||||||
let isMouseDown = false
|
let isMouseDown = false
|
||||||
@ -43,14 +50,17 @@ const DocumentRenderer = () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
applyCanvasSizes({ width: image.naturalWidth, height: image.naturalHeight })
|
const width = image.naturalWidth * zoomLevel
|
||||||
|
const height = image.naturalHeight * zoomLevel
|
||||||
|
|
||||||
|
applyCanvasSizes({ width, height })
|
||||||
|
|
||||||
const documentCanvasInstance = documentCanvas.current
|
const documentCanvasInstance = documentCanvas.current
|
||||||
if (!documentCanvasInstance) return
|
if (!documentCanvasInstance) return
|
||||||
|
|
||||||
const context = documentCanvasInstance.getContext('2d')
|
const context = documentCanvasInstance.getContext('2d')
|
||||||
if (!context) return
|
if (!context) return
|
||||||
context.drawImage(image, 0, 0, image.width, image.height)
|
context.drawImage(image, 0, 0, width, height)
|
||||||
|
|
||||||
if (areas) applyAreasToCanvas()
|
if (areas) applyAreasToCanvas()
|
||||||
}
|
}
|
||||||
@ -58,7 +68,7 @@ const DocumentRenderer = () => {
|
|||||||
const applyAreasToCanvas = () => {
|
const applyAreasToCanvas = () => {
|
||||||
const areaCanvasInstance = areaCanvas.current
|
const areaCanvasInstance = areaCanvas.current
|
||||||
if (!areaCanvasInstance) return
|
if (!areaCanvasInstance) return
|
||||||
const context = areaCanvasInstance.getContext('2d')
|
const context = areaCanvasInstance.getContext('2d')!
|
||||||
if (!context) return
|
if (!context) return
|
||||||
|
|
||||||
context.clearRect(0, 0, areaCanvasInstance.width, areaCanvasInstance.height)
|
context.clearRect(0, 0, areaCanvasInstance.width, areaCanvasInstance.height)
|
||||||
@ -66,14 +76,23 @@ const DocumentRenderer = () => {
|
|||||||
if (!areas || !areas.length) return
|
if (!areas || !areas.length) return
|
||||||
|
|
||||||
areas.forEach(a => {
|
areas.forEach(a => {
|
||||||
const width = a.endX - a.startX
|
context.beginPath()
|
||||||
const height = a.endY - a.startY
|
if (a.id !== selectedAreaId) {
|
||||||
const x = a.startX
|
context.setLineDash([4])
|
||||||
const y = a.startY
|
context.lineWidth = 2
|
||||||
context.rect(x, y, width, height)
|
context.strokeStyle = '#010101'
|
||||||
context.lineWidth = 2
|
} else {
|
||||||
context.strokeStyle = '#dc8dec'
|
context.setLineDash([])
|
||||||
|
context.lineWidth = 3
|
||||||
|
context.strokeStyle = '#dc8dec'
|
||||||
|
}
|
||||||
|
const width = (a.endX - a.startX) * zoomLevel
|
||||||
|
const height = (a.endY - a.startY) * zoomLevel
|
||||||
|
const x = a.startX * zoomLevel
|
||||||
|
const y = a.startY * zoomLevel
|
||||||
|
context.roundRect(x, y, width, height, 4)
|
||||||
context.stroke()
|
context.stroke()
|
||||||
|
context.closePath()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,25 +114,26 @@ const DocumentRenderer = () => {
|
|||||||
|
|
||||||
let startX: number, endX: number
|
let startX: number, endX: number
|
||||||
if (downClickX < mouseX) {
|
if (downClickX < mouseX) {
|
||||||
startX = downClickX
|
startX = Math.floor(downClickX / zoomLevel)
|
||||||
endX = mouseX
|
endX = Math.floor(mouseX / zoomLevel)
|
||||||
} else {
|
} else {
|
||||||
startX = mouseX
|
startX = Math.floor(mouseX / zoomLevel)
|
||||||
endX = downClickX
|
endX = Math.floor(downClickX / zoomLevel)
|
||||||
}
|
}
|
||||||
|
|
||||||
let startY: number, endY: number
|
let startY: number, endY: number
|
||||||
if (downClickY < mouseY) {
|
if (downClickY < mouseY) {
|
||||||
startY = downClickY
|
startY = Math.floor(downClickY / zoomLevel)
|
||||||
endY = mouseY
|
endY = Math.floor(mouseY / zoomLevel)
|
||||||
} else {
|
} else {
|
||||||
startY = mouseY
|
startY = Math.floor(mouseY / zoomLevel)
|
||||||
endY = downClickY
|
endY = Math.floor(downClickY / zoomLevel)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedDocument?.id) {
|
if (selectedDocument?.id) {
|
||||||
const addedArea = await requestAddArea(selectedDocument.id, { startX, startY, endX, endY })
|
const addedArea = await requestAddArea(selectedDocument.id, { startX, startY, endX, endY })
|
||||||
processImageArea(selectedDocument.id, addedArea)
|
setSelectedAreaId(addedArea.id)
|
||||||
|
processImageArea(selectedDocument.id, addedArea.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
const context = drawingCanvasInstance.getContext('2d')
|
const context = drawingCanvasInstance.getContext('2d')
|
||||||
@ -145,9 +165,16 @@ const DocumentRenderer = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleWheelEvent = (e: WheelEvent<HTMLDivElement>) => {
|
||||||
|
if (!e.ctrlKey) return
|
||||||
|
|
||||||
|
const shouldAttemptToZoomIn = (e.deltaY < 0) && zoomLevel < maxZoomLevel
|
||||||
|
if (shouldAttemptToZoomIn) setZoomLevel(zoomLevel + zoomStep)
|
||||||
|
else if (zoomLevel > (zoomStep * 2)) setZoomLevel(zoomLevel - zoomStep)
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedDocument?.path) applyDocumentToCanvas(selectedDocument.path)
|
if (selectedDocument?.path) applyDocumentToCanvas(selectedDocument.path)
|
||||||
applyAreasToCanvas()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return <div className='relative'>
|
return <div className='relative'>
|
||||||
@ -155,26 +182,42 @@ const DocumentRenderer = () => {
|
|||||||
<h1 className="text-2xl font-semibold text-gray-900">
|
<h1 className="text-2xl font-semibold text-gray-900">
|
||||||
{getSelectedDocument()?.name}
|
{getSelectedDocument()?.name}
|
||||||
</h1>
|
</h1>
|
||||||
<LanguageSelect shouldUpdateDocument defaultLanguage={selectedDocument?.defaultLanguage} />
|
<div>
|
||||||
|
<LanguageSelect shouldUpdateDocument defaultLanguage={selectedDocument?.defaultLanguage} />
|
||||||
|
<div className='flex justify-evenly items-center mt-2 mb-0'>
|
||||||
|
<MagnifyingGlassMinusIcon className='w-4 h-4' />
|
||||||
|
<input
|
||||||
|
id="zoomRange" type="range" min={zoomStep} max={maxZoomLevel} step={zoomStep}
|
||||||
|
value={zoomLevel} className="w-[calc(100%-50px)] h-2 bg-indigo-200 rounded-lg appearance-none cursor-pointer p-0"
|
||||||
|
onChange={(e) => { setZoomLevel(e.currentTarget.valueAsNumber) }}
|
||||||
|
/>
|
||||||
|
<MagnifyingGlassPlusIcon className='w-4 h-4' />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative mt-2">
|
<div
|
||||||
|
onWheelCapture={handleWheelEvent}
|
||||||
|
className={classNames('relative mt-2 overflow-scroll',
|
||||||
|
'w-[calc(100vw-320px)] h-[calc(100vh-240px)] border-4',
|
||||||
|
'border-dashed border-gray-200')}>
|
||||||
<canvas
|
<canvas
|
||||||
className="absolute border-4 border-dashed border-gray-200"
|
className="absolute"
|
||||||
ref={documentCanvas}
|
ref={documentCanvas}
|
||||||
/>
|
/>
|
||||||
<canvas
|
<canvas
|
||||||
className="absolute border-4 border-transparent"
|
className="absolute "
|
||||||
ref={areaCanvas}
|
ref={areaCanvas}
|
||||||
/>
|
/>
|
||||||
<canvas
|
<canvas
|
||||||
className="absolute border-4 border-transparent"
|
className="absolute"
|
||||||
ref={drawingCanvas}
|
ref={drawingCanvas}
|
||||||
onMouseDown={handleMouseDown}
|
onMouseDown={handleMouseDown}
|
||||||
onMouseUp={handleMouseUp}
|
onMouseUp={handleMouseUp}
|
||||||
onMouseMove={handleMouseMove}
|
onMouseMove={handleMouseMove}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div >
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DocumentRenderer
|
export default DocumentRenderer
|
||||||
|
|||||||
@ -70,6 +70,7 @@ function Sidebar() {
|
|||||||
getSelectedDocument,
|
getSelectedDocument,
|
||||||
getAreaById,
|
getAreaById,
|
||||||
requestUpdateArea,
|
requestUpdateArea,
|
||||||
|
requestDeleteAreaById,
|
||||||
requestAddDocument,
|
requestAddDocument,
|
||||||
requestAddDocumentGroup,
|
requestAddDocumentGroup,
|
||||||
selectedAreaId,
|
selectedAreaId,
|
||||||
@ -128,34 +129,24 @@ function Sidebar() {
|
|||||||
setIsEditAreaNameInputShowing(false)
|
setIsEditAreaNameInputShowing(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ________________
|
|
||||||
|
|
||||||
const onAreaDragOver = (areaId: string) => {
|
const onAreaDragOver = (areaId: string) => {
|
||||||
setDragOverAreaId(areaId)
|
setDragOverAreaId(areaId)
|
||||||
}
|
}
|
||||||
|
|
||||||
const onAreaDragStart = (areaId: string) => {
|
const onAreaDragStart = (areaId: string) => {
|
||||||
// setDragStartAreaId(areaId)
|
setSelectedAreaId(areaId)
|
||||||
}
|
}
|
||||||
|
|
||||||
const onAreaDropEnd = (areaId: string) => {
|
const onAreaDropEnd = (areaId: string) => {
|
||||||
const areaDroppedOn = navigation.map(n => n.documents).flat().map(d => d.areas).flat().find(a => a.id === dragOverAreaId)
|
const areaDroppedOn = navigation.map(n => n.documents).flat().map(d => d.areas).flat().find(a => a.id === dragOverAreaId)
|
||||||
if (!areaDroppedOn) return
|
if (!areaDroppedOn) return
|
||||||
requestChangeAreaOrder(areaId, areaDroppedOn.order)
|
requestChangeAreaOrder(areaId, areaDroppedOn.order)
|
||||||
setDragOverAreaId('')
|
setDragOverAreaId('')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ________________
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const handleAreaDeleteButtonClick = (areaId: string) => {
|
||||||
|
requestDeleteAreaById(areaId)
|
||||||
|
}
|
||||||
|
|
||||||
const onDocumentClickHandler = (itemId: string) => {
|
const onDocumentClickHandler = (itemId: string) => {
|
||||||
setSelectedDocumentId(itemId)
|
setSelectedDocumentId(itemId)
|
||||||
@ -362,7 +353,7 @@ function Sidebar() {
|
|||||||
name="documentName"
|
name="documentName"
|
||||||
id="documentName"
|
id="documentName"
|
||||||
autoFocus
|
autoFocus
|
||||||
className="h-8 text-white placeholder-gray-400 bg-gray-900 bg-opacity-5 block w-full rounded-none rounded-l-md border-late-700 focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
|
className="h-8 w-[calc(100%-18px)] text-white placeholder-gray-400 bg-gray-900 bg-opacity-5 inline-block rounded-none rounded-l-md border-late-700 focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
|
||||||
defaultValue={d.name}
|
defaultValue={d.name}
|
||||||
onBlur={onDocumentInputBlur}
|
onBlur={onDocumentInputBlur}
|
||||||
onKeyDown={(event) => {
|
onKeyDown={(event) => {
|
||||||
@ -397,12 +388,12 @@ function Sidebar() {
|
|||||||
|
|
||||||
)}>
|
)}>
|
||||||
{selectedDocumentId === d.id && isEditDocumentNameInputShowing
|
{selectedDocumentId === d.id && isEditDocumentNameInputShowing
|
||||||
? <input // TODO: this
|
? <input
|
||||||
type="text"
|
type="text"
|
||||||
name="documentName"
|
name="documentName"
|
||||||
id="documentName"
|
id="documentName"
|
||||||
autoFocus
|
autoFocus
|
||||||
className="h-8 text-white placeholder-gray-400 bg-gray-900 bg-opacity-5 block w-full rounded-none rounded-l-md border-late-700 focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
|
className="h-8 w-[calc(100%-18px)] text-white placeholder-gray-400 bg-gray-900 bg-opacity-5 inline-block rounded-none rounded-l-md border-late-700 focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
|
||||||
defaultValue={d.name}
|
defaultValue={d.name}
|
||||||
onBlur={onDocumentInputBlur}
|
onBlur={onDocumentInputBlur}
|
||||||
onKeyDown={(event) => {
|
onKeyDown={(event) => {
|
||||||
@ -434,7 +425,7 @@ function Sidebar() {
|
|||||||
id="areaName"
|
id="areaName"
|
||||||
autoFocus
|
autoFocus
|
||||||
className="h-8 text-white placeholder-gray-400 bg-gray-900 bg-opacity-5 block w-full rounded-none rounded-l-md border-late-700 focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
|
className="h-8 text-white placeholder-gray-400 bg-gray-900 bg-opacity-5 block w-full rounded-none rounded-l-md border-late-700 focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
|
||||||
placeholder={a.name || `Area ${index + 1}`}
|
placeholder={a.name || `Area ${index}`}
|
||||||
onBlur={onAreaInputBlur}
|
onBlur={onAreaInputBlur}
|
||||||
onKeyDown={(event) => {
|
onKeyDown={(event) => {
|
||||||
onEnterHandler(event,
|
onEnterHandler(event,
|
||||||
@ -442,23 +433,29 @@ function Sidebar() {
|
|||||||
}}
|
}}
|
||||||
ref={editAreaNameTextInput}
|
ref={editAreaNameTextInput}
|
||||||
/>
|
/>
|
||||||
: <a
|
: <div
|
||||||
role='button'
|
|
||||||
onClick={() => onAreaClick(a.id)}
|
|
||||||
onDoubleClick={() => onAreaDoubleClick(a.id)}
|
|
||||||
draggable
|
draggable
|
||||||
onDragOver={() => onAreaDragOver(a.id)}
|
onDragOver={() => onAreaDragOver(a.id)}
|
||||||
onDragStart={() => onAreaDragStart(a.id)}
|
onDragStart={() => onAreaDragStart(a.id)}
|
||||||
onDragEnd={() => onAreaDropEnd(a.id)}
|
onDragEnd={() => onAreaDropEnd(a.id)}
|
||||||
className={classNames('text-gray-300 hover:bg-gray-700 hover:text-white',
|
className={classNames('flex justify-between items-center cursor-pointer',
|
||||||
'group w-full flex items-center pr-2 py-2 text-left font-medium pl-8 text-xs',
|
selectedAreaId === a.id ? 'bg-indigo-500 text-gray-200' : 'text-gray-300 hover:bg-gray-700 hover:text-white',
|
||||||
'rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 py-2 select-none',
|
dragOverAreaId === a.id ? 'bg-gray-300 text-gray-700' : '',
|
||||||
selectedAreaId === a.id ? 'underline' : '',
|
selectedAreaId === a.id && dragOverAreaId === a.id ? 'bg-indigo-300' : '',
|
||||||
dragOverAreaId === a.id ? 'bg-gray-300 text-gray-700' : ''
|
)}>
|
||||||
)}
|
<a
|
||||||
>
|
role='button'
|
||||||
{a.name || `Area ${a.order}`}
|
onClick={() => onAreaClick(a.id)}
|
||||||
</a>
|
onDoubleClick={() => onAreaDoubleClick(a.id)}
|
||||||
|
className={classNames('group w-full pr-2 py-2 text-left font-medium pl-8 text-xs',
|
||||||
|
'rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 py-2 select-none',
|
||||||
|
)}>
|
||||||
|
{a.name || `Area ${a.order}`}
|
||||||
|
</a>
|
||||||
|
<XMarkIcon
|
||||||
|
className='w-5 h-5 mr-2 text-white hover:bg-white hover:text-gray-700 rounded-full p-0.5'
|
||||||
|
onClick={() => handleAreaDeleteButtonClick(a.id)} />
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@ -13,6 +13,7 @@ const makeDefaultProject = (): ProjectContextType => ({
|
|||||||
requestAddProcessedArea: (processesArea) => Promise.resolve(new ipc.ProcessedArea()),
|
requestAddProcessedArea: (processesArea) => Promise.resolve(new ipc.ProcessedArea()),
|
||||||
requestAddArea: (documentId, area) => Promise.resolve(new ipc.Area()),
|
requestAddArea: (documentId, area) => Promise.resolve(new ipc.Area()),
|
||||||
requestUpdateArea: (updatedArea) => Promise.resolve(new ipc.Area()),
|
requestUpdateArea: (updatedArea) => Promise.resolve(new ipc.Area()),
|
||||||
|
requestDeleteAreaById: (areaId) => Promise.resolve(false),
|
||||||
requestAddDocument: (groupId, documentName) => Promise.resolve(new ipc.Document()),
|
requestAddDocument: (groupId, documentName) => Promise.resolve(new ipc.Document()),
|
||||||
requestAddDocumentGroup: (groupName: string) => Promise.resolve(new ipc.Group()),
|
requestAddDocumentGroup: (groupName: string) => Promise.resolve(new ipc.Group()),
|
||||||
requestUpdateDocumentUserMarkdown: (documentId: string, markdown: string) => Promise.resolve(new ipc.UserMarkdown()),
|
requestUpdateDocumentUserMarkdown: (documentId: string, markdown: string) => Promise.resolve(new ipc.UserMarkdown()),
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import {
|
|||||||
RequestChooseUserAvatar,
|
RequestChooseUserAvatar,
|
||||||
RequestUpdateDocument,
|
RequestUpdateDocument,
|
||||||
RequestChangeAreaOrder,
|
RequestChangeAreaOrder,
|
||||||
|
RequestDeleteAreaById,
|
||||||
} from '../../wailsjs/wailsjs/go/ipc/Channel'
|
} from '../../wailsjs/wailsjs/go/ipc/Channel'
|
||||||
import { ipc } from '../../wailsjs/wailsjs/go/models'
|
import { ipc } from '../../wailsjs/wailsjs/go/models'
|
||||||
import { AddAreaProps, AreaProps, ProjectContextType, ProjectProps, UpdateDocumentRequest, UserProps } from './types'
|
import { AddAreaProps, AreaProps, ProjectContextType, ProjectProps, UpdateDocumentRequest, UserProps } from './types'
|
||||||
@ -30,7 +31,6 @@ export function ProjectProvider({ children, projectProps }: Props) {
|
|||||||
|
|
||||||
const updateDocuments = async () => {
|
const updateDocuments = async () => {
|
||||||
GetDocuments().then(response => {
|
GetDocuments().then(response => {
|
||||||
console.log(response)
|
|
||||||
if (response.documents.length) setDocuments(response.documents)
|
if (response.documents.length) setDocuments(response.documents)
|
||||||
if (response.groups.length) setGroups(response.groups)
|
if (response.groups.length) setGroups(response.groups)
|
||||||
Promise.resolve(response)
|
Promise.resolve(response)
|
||||||
@ -66,6 +66,12 @@ export function ProjectProvider({ children, projectProps }: Props) {
|
|||||||
documents.map(d => d.areas).flat().find(a => a.id === areaId)
|
documents.map(d => d.areas).flat().find(a => a.id === areaId)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const requestDeleteAreaById = async (areaId: string): Promise<boolean> => {
|
||||||
|
const wasSuccessfulDeletion = await RequestDeleteAreaById(areaId)
|
||||||
|
if (wasSuccessfulDeletion) updateDocuments()
|
||||||
|
return wasSuccessfulDeletion
|
||||||
|
}
|
||||||
|
|
||||||
const getSelectedDocument = () => documents.find(d => d.id === selectedDocumentId)
|
const getSelectedDocument = () => documents.find(d => d.id === selectedDocumentId)
|
||||||
|
|
||||||
const getProcessedAreasByDocumentId = async (documentId: string) => {
|
const getProcessedAreasByDocumentId = async (documentId: string) => {
|
||||||
@ -132,7 +138,6 @@ export function ProjectProvider({ children, projectProps }: Props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const requestChangeAreaOrder = async (areaId: string, newOrder: number) => {
|
const requestChangeAreaOrder = async (areaId: string, newOrder: number) => {
|
||||||
console.log('requestChangeAreaOrder')
|
|
||||||
const response = await RequestChangeAreaOrder(areaId, newOrder)
|
const response = await RequestChangeAreaOrder(areaId, newOrder)
|
||||||
await updateDocuments()
|
await updateDocuments()
|
||||||
return response
|
return response
|
||||||
@ -152,6 +157,7 @@ export function ProjectProvider({ children, projectProps }: Props) {
|
|||||||
requestAddDocument,
|
requestAddDocument,
|
||||||
requestAddDocumentGroup,
|
requestAddDocumentGroup,
|
||||||
requestUpdateArea,
|
requestUpdateArea,
|
||||||
|
requestDeleteAreaById,
|
||||||
selectedAreaId,
|
selectedAreaId,
|
||||||
setSelectedAreaId,
|
setSelectedAreaId,
|
||||||
selectedDocumentId,
|
selectedDocumentId,
|
||||||
|
|||||||
@ -43,6 +43,7 @@ export type ProjectContextType = {
|
|||||||
requestAddProcessedArea: (processedArea: ipc.ProcessedArea) => Promise<ipc.ProcessedArea>
|
requestAddProcessedArea: (processedArea: ipc.ProcessedArea) => Promise<ipc.ProcessedArea>
|
||||||
requestAddArea: (documentId: string, area: AddAreaProps) => Promise<ipc.Area>
|
requestAddArea: (documentId: string, area: AddAreaProps) => Promise<ipc.Area>
|
||||||
requestUpdateArea: (area: AreaProps) => Promise<ipc.Area>
|
requestUpdateArea: (area: AreaProps) => Promise<ipc.Area>
|
||||||
|
requestDeleteAreaById: (areaId: string) => Promise<boolean>
|
||||||
requestAddDocument: (groupId: string, documentName: string) => Promise<ipc.Document>
|
requestAddDocument: (groupId: string, documentName: string) => Promise<ipc.Document>
|
||||||
requestAddDocumentGroup: (groupName: string) => Promise<ipc.Group>
|
requestAddDocumentGroup: (groupName: string) => Promise<ipc.Group>
|
||||||
requestUpdateDocumentUserMarkdown: (documentId: string, markdown: string) => Promise<ipc.UserMarkdown>
|
requestUpdateDocumentUserMarkdown: (documentId: string, markdown: string) => Promise<ipc.UserMarkdown>
|
||||||
|
|||||||
@ -1,32 +1,35 @@
|
|||||||
import { createScheduler, createWorker } from 'tesseract.js'
|
import { createScheduler, createWorker } from 'tesseract.js'
|
||||||
import { GetDocumentById, RequestAddProcessedArea } from '../wailsjs/wailsjs/go/ipc/Channel'
|
import { GetAreaById, GetDocumentById, RequestAddProcessedArea } from '../wailsjs/wailsjs/go/ipc/Channel'
|
||||||
import { ipc } from '../wailsjs/wailsjs/go/models'
|
import { ipc } from '../wailsjs/wailsjs/go/models'
|
||||||
import loadImage from './loadImage'
|
import loadImage from './loadImage'
|
||||||
|
|
||||||
const processImageArea = async (documentId: string, area: ipc.Area) => {
|
const processImageArea = async (documentId: string, areaId: string) => {
|
||||||
const foundDocument = await GetDocumentById(documentId)
|
const foundDocument = await GetDocumentById(documentId)
|
||||||
if (!foundDocument.path || !foundDocument.areas?.length) return
|
const foundArea = await GetAreaById(areaId)
|
||||||
|
if (!foundDocument.path || !foundDocument.areas?.length || !foundArea.id) return
|
||||||
|
|
||||||
|
const processLanguage = foundDocument.defaultLanguage.processCode
|
||||||
|
|
||||||
const { path } = foundDocument
|
const { path } = foundDocument
|
||||||
const imageData = await loadImage(path)
|
const imageData = await loadImage(path)
|
||||||
|
|
||||||
const scheduler = createScheduler()
|
const scheduler = createScheduler()
|
||||||
const worker = await createWorker()
|
const worker = await createWorker()
|
||||||
await worker.loadLanguage('eng') // TODO: change this when multilangiage system is implementd
|
await worker.loadLanguage(processLanguage)
|
||||||
await worker.initialize('eng') // TODO: same here
|
await worker.initialize(processLanguage)
|
||||||
scheduler.addWorker(worker)
|
scheduler.addWorker(worker)
|
||||||
|
|
||||||
const result = await scheduler.addJob('recognize', imageData, {
|
const result = await scheduler.addJob('recognize', imageData, {
|
||||||
rectangle: {
|
rectangle: {
|
||||||
left: area.startX,
|
left: foundArea.startX,
|
||||||
top: area.startY,
|
top: foundArea.startY,
|
||||||
width: area.endX - area.startX,
|
width: foundArea.endX - foundArea.startX,
|
||||||
height: area.endY - area.startY,
|
height: foundArea.endY - foundArea.startY,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const addProcessesAreaRequest = await RequestAddProcessedArea(new ipc.ProcessedArea({
|
const addProcessesAreaRequest = await RequestAddProcessedArea(new ipc.ProcessedArea({
|
||||||
id: area.id,
|
id: foundArea.id,
|
||||||
documentId,
|
documentId,
|
||||||
fullText: result.data.text,
|
fullText: result.data.text,
|
||||||
lines: result.data.lines.map((l: any) => new ipc.ProcessedLine({
|
lines: result.data.lines.map((l: any) => new ipc.ProcessedLine({
|
||||||
|
|||||||
4
frontend/wailsjs/wailsjs/go/ipc/Channel.d.ts
vendored
4
frontend/wailsjs/wailsjs/go/ipc/Channel.d.ts
vendored
@ -4,6 +4,8 @@ import {ipc} from '../models';
|
|||||||
|
|
||||||
export function CreateNewProject(arg1:string):Promise<ipc.Session>;
|
export function CreateNewProject(arg1:string):Promise<ipc.Session>;
|
||||||
|
|
||||||
|
export function GetAreaById(arg1:string):Promise<ipc.Area>;
|
||||||
|
|
||||||
export function GetCurrentSession():Promise<ipc.Session>;
|
export function GetCurrentSession():Promise<ipc.Session>;
|
||||||
|
|
||||||
export function GetCurrentUser():Promise<ipc.User>;
|
export function GetCurrentUser():Promise<ipc.User>;
|
||||||
@ -30,6 +32,8 @@ export function RequestChangeAreaOrder(arg1:string,arg2:number):Promise<ipc.Docu
|
|||||||
|
|
||||||
export function RequestChooseUserAvatar():Promise<string>;
|
export function RequestChooseUserAvatar():Promise<string>;
|
||||||
|
|
||||||
|
export function RequestDeleteAreaById(arg1:string):Promise<boolean>;
|
||||||
|
|
||||||
export function RequestUpdateArea(arg1:ipc.Area):Promise<ipc.Area>;
|
export function RequestUpdateArea(arg1:ipc.Area):Promise<ipc.Area>;
|
||||||
|
|
||||||
export function RequestUpdateCurrentUser(arg1:ipc.User):Promise<ipc.User>;
|
export function RequestUpdateCurrentUser(arg1:ipc.User):Promise<ipc.User>;
|
||||||
|
|||||||
@ -6,6 +6,10 @@ export function CreateNewProject(arg1) {
|
|||||||
return window['go']['ipc']['Channel']['CreateNewProject'](arg1);
|
return window['go']['ipc']['Channel']['CreateNewProject'](arg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function GetAreaById(arg1) {
|
||||||
|
return window['go']['ipc']['Channel']['GetAreaById'](arg1);
|
||||||
|
}
|
||||||
|
|
||||||
export function GetCurrentSession() {
|
export function GetCurrentSession() {
|
||||||
return window['go']['ipc']['Channel']['GetCurrentSession']();
|
return window['go']['ipc']['Channel']['GetCurrentSession']();
|
||||||
}
|
}
|
||||||
@ -58,6 +62,10 @@ export function RequestChooseUserAvatar() {
|
|||||||
return window['go']['ipc']['Channel']['RequestChooseUserAvatar']();
|
return window['go']['ipc']['Channel']['RequestChooseUserAvatar']();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function RequestDeleteAreaById(arg1) {
|
||||||
|
return window['go']['ipc']['Channel']['RequestDeleteAreaById'](arg1);
|
||||||
|
}
|
||||||
|
|
||||||
export function RequestUpdateArea(arg1) {
|
export function RequestUpdateArea(arg1) {
|
||||||
return window['go']['ipc']['Channel']['RequestUpdateArea'](arg1);
|
return window['go']['ipc']['Channel']['RequestUpdateArea'](arg1);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,12 +32,13 @@ func (c *Channel) GetDocumentById(id string) Document {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
response := Document{
|
response := Document{
|
||||||
Id: foundDocument.Id,
|
Id: foundDocument.Id,
|
||||||
Name: foundDocument.Name,
|
Name: foundDocument.Name,
|
||||||
GroupId: foundDocument.GroupId,
|
GroupId: foundDocument.GroupId,
|
||||||
Path: foundDocument.Path,
|
Path: foundDocument.Path,
|
||||||
ProjectId: foundDocument.ProjectId,
|
ProjectId: foundDocument.ProjectId,
|
||||||
Areas: jsonAreas,
|
Areas: jsonAreas,
|
||||||
|
DefaultLanguage: Language(foundDocument.DefaultLanguage),
|
||||||
}
|
}
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
@ -193,6 +194,32 @@ func (c *Channel) RequestAddDocumentGroup(name string) Group {
|
|||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Channel) GetAreaById(areaId string) Area {
|
||||||
|
foundDocument := document.GetDocumentCollection().GetDocumentByAreaId(areaId)
|
||||||
|
|
||||||
|
if len(foundDocument.Areas) == 0 {
|
||||||
|
return Area{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var foundArea document.Area
|
||||||
|
for i, a := range foundDocument.Areas {
|
||||||
|
if a.Id == areaId {
|
||||||
|
foundArea = foundDocument.Areas[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Area{
|
||||||
|
Id: foundArea.Id,
|
||||||
|
Name: foundArea.Name,
|
||||||
|
StartX: foundArea.StartX,
|
||||||
|
EndX: foundArea.EndX,
|
||||||
|
StartY: foundArea.StartY,
|
||||||
|
EndY: foundArea.EndY,
|
||||||
|
Order: foundArea.Order,
|
||||||
|
Language: Language(foundArea.Language),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Channel) RequestAddArea(documentId string, area Area) Area {
|
func (c *Channel) RequestAddArea(documentId string, area Area) Area {
|
||||||
foundDocument := document.GetDocumentCollection().GetDocumentById(documentId)
|
foundDocument := document.GetDocumentCollection().GetDocumentById(documentId)
|
||||||
|
|
||||||
@ -233,7 +260,7 @@ func (c *Channel) RequestUpdateArea(updatedArea Area) Area {
|
|||||||
return Area{}
|
return Area{}
|
||||||
}
|
}
|
||||||
|
|
||||||
areaToUpdate := documentOfArea.GetAreaById((updatedArea.Id))
|
areaToUpdate := documentOfArea.GetAreaById(updatedArea.Id)
|
||||||
|
|
||||||
if areaToUpdate.Id == "" {
|
if areaToUpdate.Id == "" {
|
||||||
return Area{}
|
return Area{}
|
||||||
@ -259,6 +286,37 @@ func (c *Channel) RequestUpdateArea(updatedArea Area) Area {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Channel) RequestDeleteAreaById(areaId string) bool {
|
||||||
|
documentOfArea := document.GetDocumentCollection().GetDocumentByAreaId(areaId)
|
||||||
|
|
||||||
|
if documentOfArea.Id == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
areaToDeleteIndex := -1
|
||||||
|
|
||||||
|
for i, a := range documentOfArea.Areas {
|
||||||
|
if a.Id == areaId {
|
||||||
|
areaToDeleteIndex = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if areaToDeleteIndex < 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// func remove(s []int, i int) []int {
|
||||||
|
// s[i] = s[len(s)-1]
|
||||||
|
// return s[:len(s)-1]
|
||||||
|
// }
|
||||||
|
|
||||||
|
documentOfArea.Areas[areaToDeleteIndex] = documentOfArea.Areas[len(documentOfArea.Areas)-1]
|
||||||
|
documentOfArea.Areas = documentOfArea.Areas[:len(documentOfArea.Areas)-1]
|
||||||
|
return true
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Channel) RequestUpdateDocument(updatedDocument Document) Document {
|
func (c *Channel) RequestUpdateDocument(updatedDocument Document) Document {
|
||||||
documentToUpdate := document.GetDocumentCollection().GetDocumentById(updatedDocument.Id)
|
documentToUpdate := document.GetDocumentCollection().GetDocumentById(updatedDocument.Id)
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user