feat: text editor & stored processed docs
This commit is contained in:
parent
c1ad2132ac
commit
c58e021b5a
63
core/Document/ProcessedText.go
Normal file
63
core/Document/ProcessedText.go
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
package document
|
||||||
|
|
||||||
|
type ProcessedBoundingBox struct {
|
||||||
|
X0 int32
|
||||||
|
Y0 int32
|
||||||
|
X1 int32
|
||||||
|
Y1 int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProcessedSymbol struct {
|
||||||
|
Text string
|
||||||
|
Confidence float32
|
||||||
|
BoundingBox ProcessedBoundingBox
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProcessedWord struct {
|
||||||
|
FullText string
|
||||||
|
Symbols []ProcessedSymbol
|
||||||
|
Confidence float32
|
||||||
|
Direction string
|
||||||
|
BoundingBox ProcessedBoundingBox
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProcessedLine struct {
|
||||||
|
FullText string
|
||||||
|
Words []ProcessedWord
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProcessedArea struct {
|
||||||
|
Id string
|
||||||
|
DocumentId string
|
||||||
|
FullText string
|
||||||
|
Lines []ProcessedLine
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProcessedAreaCollection struct {
|
||||||
|
Areas []ProcessedArea
|
||||||
|
}
|
||||||
|
|
||||||
|
var processedAreaCollectionInstnace *ProcessedAreaCollection
|
||||||
|
|
||||||
|
func GetProcessedAreaCollection() *ProcessedAreaCollection {
|
||||||
|
if processedAreaCollectionInstnace == nil {
|
||||||
|
processedAreaCollectionInstnace = &ProcessedAreaCollection{}
|
||||||
|
}
|
||||||
|
return processedAreaCollectionInstnace
|
||||||
|
}
|
||||||
|
|
||||||
|
func (collection *ProcessedAreaCollection) AddProcessedArea(area ProcessedArea) {
|
||||||
|
collection.Areas = append(collection.Areas, area)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (collection *ProcessedAreaCollection) GetAreasByDocumentId(id string) []*ProcessedArea {
|
||||||
|
var foundAreas []*ProcessedArea
|
||||||
|
|
||||||
|
for index, a := range collection.Areas {
|
||||||
|
if a.DocumentId == id {
|
||||||
|
foundAreas = append(foundAreas, &collection.Areas[index])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return foundAreas
|
||||||
|
}
|
||||||
@ -3,7 +3,7 @@
|
|||||||
import React, { useEffect, useRef } from 'react'
|
import React, { useEffect, useRef } 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 processImageData from '../../useCases/processImageData'
|
import processImageArea from '../../useCases/processImageArea'
|
||||||
|
|
||||||
const DocumentRenderer = () => {
|
const DocumentRenderer = () => {
|
||||||
const { getSelectedDocument, requestAddArea } = useProject()
|
const { getSelectedDocument, requestAddArea } = useProject()
|
||||||
@ -111,10 +111,8 @@ const DocumentRenderer = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (selectedDocument?.id) {
|
if (selectedDocument?.id) {
|
||||||
await requestAddArea(selectedDocument.id, { startX, startY, endX, endY })
|
const addedArea = await requestAddArea(selectedDocument.id, { startX, startY, endX, endY })
|
||||||
processImageData(selectedDocument.id).then(results => {
|
processImageArea(selectedDocument.id, addedArea)
|
||||||
console.log(results)
|
|
||||||
}).catch(err => console.log(err))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const context = drawingCanvasInstance.getContext('2d')
|
const context = drawingCanvasInstance.getContext('2d')
|
||||||
|
|||||||
@ -1,12 +1,20 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
|
import { useNavigation } from '../../context/Navigation/provider'
|
||||||
|
import { workspaces } from '../../context/Navigation/types'
|
||||||
import { useProject } from '../../context/Project/provider'
|
import { useProject } from '../../context/Project/provider'
|
||||||
import DocumentRenderer from './DocumentRenderer'
|
import DocumentRenderer from './DocumentRenderer'
|
||||||
import NoSelectedDocument from './NoSelectedDocument'
|
import NoSelectedDocument from './NoSelectedDocument'
|
||||||
|
import TextEditor from './TextEditor'
|
||||||
|
|
||||||
const MainWorkspace = () => {
|
const MainWorkspace = () => {
|
||||||
const { getSelectedDocument, selectedDocumentId } = useProject()
|
const { getSelectedDocument, selectedDocumentId } = useProject()
|
||||||
|
const { selectedWorkspace } = useNavigation()
|
||||||
|
|
||||||
|
const renderSelectedWorkSpace = () => {
|
||||||
|
if (selectedWorkspace === workspaces.TEXTEDITOR) return <TextEditor />
|
||||||
|
else return !selectedDocumentId ? <NoSelectedDocument /> : <DocumentRenderer />
|
||||||
|
}
|
||||||
|
|
||||||
return <main className=" bg-gray-100 min-h-[calc(100vh-118px)] ml-64 overflow-y-scroll">
|
return <main className=" bg-gray-100 min-h-[calc(100vh-118px)] ml-64 overflow-y-scroll">
|
||||||
<div className='flex-1'>
|
<div className='flex-1'>
|
||||||
@ -18,10 +26,7 @@ const MainWorkspace = () => {
|
|||||||
{getSelectedDocument()?.name || 'Image Processor'}
|
{getSelectedDocument()?.name || 'Image Processor'}
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
{!selectedDocumentId
|
{ renderSelectedWorkSpace() }
|
||||||
? <NoSelectedDocument />
|
|
||||||
: <DocumentRenderer />
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -117,8 +117,6 @@ function Sidebar() {
|
|||||||
const onAreaDoubleclick = (areaId: string) => {
|
const onAreaDoubleclick = (areaId: string) => {
|
||||||
const documentIdOfArea = getDocumentIdFromAreaId(areaId)
|
const documentIdOfArea = getDocumentIdFromAreaId(areaId)
|
||||||
setIsEditAreaNameInputShowing(true)
|
setIsEditAreaNameInputShowing(true)
|
||||||
// const groupIdOfArea = getGroupIdFromAreaId(areaId)
|
|
||||||
console.log(documentIdOfArea, selectedDocumentId)
|
|
||||||
console.log('double click')
|
console.log('double click')
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +140,6 @@ function Sidebar() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const onConfirmAreaNameChangeHandler = async (areaDetails: { areaId: string, areaName: string }) => {
|
const onConfirmAreaNameChangeHandler = async (areaDetails: { areaId: string, areaName: string }) => {
|
||||||
console.log(areaDetails)
|
|
||||||
const { areaId, areaName } = areaDetails
|
const { areaId, areaName } = areaDetails
|
||||||
|
|
||||||
const areaToUpdate = getAreaById(areaId)
|
const areaToUpdate = getAreaById(areaId)
|
||||||
|
|||||||
50
frontend/components/workspace/TextEditor.tsx
Normal file
50
frontend/components/workspace/TextEditor.tsx
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import Editor, { DiffEditor, useMonaco } from '@monaco-editor/react'
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
import { useProject } from '../../context/Project/provider'
|
||||||
|
|
||||||
|
const TextEditor = () => {
|
||||||
|
const monaco = useMonaco()
|
||||||
|
const { selectedDocumentId, getProcessedAreasByDocumentId } = useProject()
|
||||||
|
const [editorHeight, setEditorHeight] = useState(window.innerHeight - 200)
|
||||||
|
const [editorValue, setEditorValue] = useState('')
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// if (monaco) {
|
||||||
|
// console.log("here is the monaco instance:", monaco);
|
||||||
|
// }
|
||||||
|
// }, [monaco])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!selectedDocumentId) {
|
||||||
|
setEditorValue('# No Document Selected')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
getProcessedAreasByDocumentId(selectedDocumentId)
|
||||||
|
.then(response => {
|
||||||
|
if (!response || response.length === 0) return
|
||||||
|
|
||||||
|
const fullTextOfAreas = response
|
||||||
|
.map(area => area.fullText + '\n')
|
||||||
|
.join('\n')
|
||||||
|
|
||||||
|
setEditorValue(fullTextOfAreas)
|
||||||
|
})
|
||||||
|
.catch(console.error)
|
||||||
|
|
||||||
|
}, [selectedDocumentId])
|
||||||
|
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
setEditorHeight(window.innerHeight - 200)
|
||||||
|
})
|
||||||
|
|
||||||
|
return <div>
|
||||||
|
<Editor
|
||||||
|
value={editorValue}
|
||||||
|
defaultLanguage='markdown'
|
||||||
|
height={`${editorHeight}px`}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TextEditor
|
||||||
@ -1,10 +1,11 @@
|
|||||||
import { useState } from 'react'
|
import { useNavigation } from '../../context/Navigation/provider'
|
||||||
|
import { workspaces } from '../../context/Navigation/types'
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{ name: 'Processor', id: 0 },
|
{ displayName: 'Processor', type: workspaces.PROCESSOR },
|
||||||
{ name: 'Text Editor', id: 1 },
|
{ displayName: 'Text Editor', type: workspaces.TEXTEDITOR },
|
||||||
{ name: 'Translator', id: 2 },
|
{ displayName: 'Translator', type: workspaces.TRANSLATOR },
|
||||||
{ name: 'Details', id: 3 },
|
{ displayName: 'Details', type: workspaces.DETAILS },
|
||||||
]
|
]
|
||||||
|
|
||||||
function classNames(...classes: string[]) {
|
function classNames(...classes: string[]) {
|
||||||
@ -12,9 +13,9 @@ function classNames(...classes: string[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function ToolTabs() {
|
export default function ToolTabs() {
|
||||||
const [selectedTabId, setSelectedTabId] = useState(0)
|
const { selectedWorkspace, setSelectedWorkspace } = useNavigation()
|
||||||
|
|
||||||
const getIsSelectedTab = (tabId: number) => tabId === selectedTabId
|
const getIsSelectedTab = (type: workspaces) => type === selectedWorkspace
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-white shadow">
|
<div className="bg-white shadow">
|
||||||
@ -23,17 +24,17 @@ export default function ToolTabs() {
|
|||||||
<nav className="-mb-px flex" aria-label="Tabs">
|
<nav className="-mb-px flex" aria-label="Tabs">
|
||||||
{tabs.map((tab) => (
|
{tabs.map((tab) => (
|
||||||
<a
|
<a
|
||||||
key={tab.name}
|
key={tab.displayName}
|
||||||
onClick={_ => setSelectedTabId(tab.id)}
|
onClick={_ => setSelectedWorkspace(tab.type)}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
getIsSelectedTab(tab.id)
|
getIsSelectedTab(tab.type)
|
||||||
? 'border-indigo-500 text-indigo-600'
|
? 'border-indigo-500 text-indigo-600'
|
||||||
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300',
|
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300',
|
||||||
'cursor-pointer w-1/4 py-4 px-1 text-center border-b-2 font-medium text-sm'
|
'cursor-pointer w-1/4 py-4 px-1 text-center border-b-2 font-medium text-sm'
|
||||||
)}
|
)}
|
||||||
aria-current={getIsSelectedTab(tab.id) ? 'page' : undefined}
|
aria-current={getIsSelectedTab(tab.type) ? 'page' : undefined}
|
||||||
>
|
>
|
||||||
{tab.name}
|
{tab.displayName}
|
||||||
</a>
|
</a>
|
||||||
))}
|
))}
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
8
frontend/context/Navigation/makeDefaultNavigation.ts
Normal file
8
frontend/context/Navigation/makeDefaultNavigation.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { NavigationContextType, workspaces } from './types'
|
||||||
|
|
||||||
|
const makeDefaultNavigation = (): NavigationContextType => ({
|
||||||
|
selectedWorkspace: workspaces.PROCESSOR,
|
||||||
|
setSelectedWorkspace: (workspace) => {}
|
||||||
|
})
|
||||||
|
|
||||||
|
export default makeDefaultNavigation
|
||||||
25
frontend/context/Navigation/provider.tsx
Normal file
25
frontend/context/Navigation/provider.tsx
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { createContext, ReactNode, useContext, useState } from 'react'
|
||||||
|
import makeDefaultNavigation from './makeDefaultNavigation'
|
||||||
|
import { NavigationContextType, NavigationProps, workspaces } from './types'
|
||||||
|
|
||||||
|
const NavigationContext = createContext<NavigationContextType>(makeDefaultNavigation())
|
||||||
|
|
||||||
|
export function useNavigation() {
|
||||||
|
return useContext(NavigationContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Props = { children: ReactNode, navigationProps: NavigationProps }
|
||||||
|
export function NavigationProvidor({ children, navigationProps }: Props) {
|
||||||
|
const [selectedWorkspace, setSelectedWorkspace] = useState<workspaces>(navigationProps.selectedWorkspace)
|
||||||
|
|
||||||
|
const value = {
|
||||||
|
selectedWorkspace,
|
||||||
|
setSelectedWorkspace
|
||||||
|
}
|
||||||
|
|
||||||
|
return <NavigationContext.Provider value={value}>
|
||||||
|
{ children }
|
||||||
|
</NavigationContext.Provider>
|
||||||
|
}
|
||||||
17
frontend/context/Navigation/types.ts
Normal file
17
frontend/context/Navigation/types.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
enum workspaces {
|
||||||
|
PROCESSOR = 'PROCESSOR',
|
||||||
|
TEXTEDITOR = 'TEXTEDITOR',
|
||||||
|
TRANSLATOR = 'TRANSLATOR',
|
||||||
|
DETAILS = 'DETAILS',
|
||||||
|
}
|
||||||
|
|
||||||
|
export { workspaces }
|
||||||
|
|
||||||
|
export type NavigationContextType = {
|
||||||
|
selectedWorkspace: workspaces,
|
||||||
|
setSelectedWorkspace: (workspace: workspaces) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export type NavigationProps = {
|
||||||
|
selectedWorkspace: workspaces
|
||||||
|
}
|
||||||
@ -9,6 +9,8 @@ const makeDefaultProject = (): ProjectContextType => ({
|
|||||||
selectedDocumentId: '',
|
selectedDocumentId: '',
|
||||||
getSelectedDocument: () => new ipc.Document(),
|
getSelectedDocument: () => new ipc.Document(),
|
||||||
getAreaById: (areaId) => undefined,
|
getAreaById: (areaId) => undefined,
|
||||||
|
getProcessedAreasByDocumentId: (documentId) => 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()),
|
||||||
requestAddDocument: (groupId, documentName) => Promise.resolve(new ipc.Document()),
|
requestAddDocument: (groupId, documentName) => Promise.resolve(new ipc.Document()),
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { createContext, ReactNode, useContext, useEffect, useState } from 'react'
|
import { createContext, ReactNode, useContext, useEffect, useState } from 'react'
|
||||||
import { GetDocuments, RequestAddArea, RequestAddDocument, RequestAddDocumentGroup, RequestUpdateArea } from '../../wailsjs/wailsjs/go/ipc/Channel'
|
import { GetDocuments, GetProcessedAreasByDocumentId, RequestAddArea, RequestAddDocument, RequestAddDocumentGroup, RequestAddProcessedArea, RequestUpdateArea } 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 } from './types'
|
import { AddAreaProps, AreaProps, ProjectContextType, ProjectProps } from './types'
|
||||||
import makeDefaultProject from './makeDefaultProject'
|
import makeDefaultProject from './makeDefaultProject'
|
||||||
@ -41,7 +41,6 @@ export function ProjectProvider({ children, projectProps }: Props) {
|
|||||||
|
|
||||||
const requestAddArea = async (documentId: string, area: AddAreaProps): Promise<ipc.Area> => {
|
const requestAddArea = async (documentId: string, area: AddAreaProps): Promise<ipc.Area> => {
|
||||||
const response = await RequestAddArea(documentId, new ipc.Area(area))
|
const response = await RequestAddArea(documentId, new ipc.Area(area))
|
||||||
|
|
||||||
if (response.id) await updateDocuments()
|
if (response.id) await updateDocuments()
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
@ -59,6 +58,18 @@ export function ProjectProvider({ children, projectProps }: Props) {
|
|||||||
|
|
||||||
const getSelectedDocument = () => documents.find(d => d.id === selectedDocumentId)
|
const getSelectedDocument = () => documents.find(d => d.id === selectedDocumentId)
|
||||||
|
|
||||||
|
const getProcessedAreasByDocumentId = async (documentId: string) => {
|
||||||
|
let response: ipc.ProcessedArea[] = []
|
||||||
|
try {
|
||||||
|
response = await GetProcessedAreasByDocumentId(documentId)
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
}
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
const requestAddProcessedArea = async (processedArea: ipc.ProcessedArea) => await RequestAddProcessedArea(processedArea)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!documents.length && !groups.length) updateDocuments()
|
if (!documents.length && !groups.length) updateDocuments()
|
||||||
}, [documents.length, groups.length])
|
}, [documents.length, groups.length])
|
||||||
@ -77,6 +88,8 @@ export function ProjectProvider({ children, projectProps }: Props) {
|
|||||||
setSelectedAreaId,
|
setSelectedAreaId,
|
||||||
selectedDocumentId,
|
selectedDocumentId,
|
||||||
setSelectedDocumentId,
|
setSelectedDocumentId,
|
||||||
|
getProcessedAreasByDocumentId,
|
||||||
|
requestAddProcessedArea,
|
||||||
}
|
}
|
||||||
|
|
||||||
return <ProjectContext.Provider value={value}>
|
return <ProjectContext.Provider value={value}>
|
||||||
|
|||||||
@ -19,6 +19,8 @@ export type AreaProps = { id: string } & AddAreaProps
|
|||||||
export type ProjectContextType = {
|
export type ProjectContextType = {
|
||||||
getSelectedDocument: () => ipc.Document | undefined
|
getSelectedDocument: () => ipc.Document | undefined
|
||||||
getAreaById: (areaId: string) => ipc.Area | undefined
|
getAreaById: (areaId: string) => ipc.Area | undefined
|
||||||
|
getProcessedAreasByDocumentId: (documentId: string) => 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>
|
||||||
requestAddDocument: (groupId: string, documentName: string) => Promise<ipc.Document>
|
requestAddDocument: (groupId: string, documentName: string) => Promise<ipc.Document>
|
||||||
|
|||||||
76
frontend/package-lock.json
generated
76
frontend/package-lock.json
generated
@ -10,7 +10,9 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@headlessui/react": "^1.7.4",
|
"@headlessui/react": "^1.7.4",
|
||||||
"@heroicons/react": "^2.0.13",
|
"@heroicons/react": "^2.0.13",
|
||||||
|
"@monaco-editor/react": "^4.4.6",
|
||||||
"@tailwindcss/forms": "^0.5.3",
|
"@tailwindcss/forms": "^0.5.3",
|
||||||
|
"monaco-editor": "^0.34.1",
|
||||||
"next": "^13.1.1",
|
"next": "^13.1.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
@ -399,6 +401,31 @@
|
|||||||
"@jridgewell/sourcemap-codec": "1.4.14"
|
"@jridgewell/sourcemap-codec": "1.4.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@monaco-editor/loader": {
|
||||||
|
"version": "1.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.3.2.tgz",
|
||||||
|
"integrity": "sha512-BTDbpHl3e47r3AAtpfVFTlAi7WXv4UQ/xZmz8atKl4q7epQV5e7+JbigFDViWF71VBi4IIBdcWP57Hj+OWuc9g==",
|
||||||
|
"dependencies": {
|
||||||
|
"state-local": "^1.0.6"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"monaco-editor": ">= 0.21.0 < 1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@monaco-editor/react": {
|
||||||
|
"version": "4.4.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.4.6.tgz",
|
||||||
|
"integrity": "sha512-Gr3uz3LYf33wlFE3eRnta4RxP5FSNxiIV9ENn2D2/rN8KgGAD8ecvcITRtsbbyuOuNkwbuHYxfeaz2Vr+CtyFA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@monaco-editor/loader": "^1.3.2",
|
||||||
|
"prop-types": "^15.7.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"monaco-editor": ">= 0.25.0 < 1",
|
||||||
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
||||||
|
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@next/env": {
|
"node_modules/@next/env": {
|
||||||
"version": "13.1.1",
|
"version": "13.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@next/env/-/env-13.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@next/env/-/env-13.1.1.tgz",
|
||||||
@ -2923,6 +2950,11 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/monaco-editor": {
|
||||||
|
"version": "0.34.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.34.1.tgz",
|
||||||
|
"integrity": "sha512-FKc80TyiMaruhJKKPz5SpJPIjL+dflGvz4CpuThaPMc94AyN7SeC9HQ8hrvaxX7EyHdJcUY5i4D0gNyJj1vSZQ=="
|
||||||
|
},
|
||||||
"node_modules/ms": {
|
"node_modules/ms": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
@ -3064,7 +3096,6 @@
|
|||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@ -3456,7 +3487,6 @@
|
|||||||
"version": "15.8.1",
|
"version": "15.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.4.0",
|
"loose-envify": "^1.4.0",
|
||||||
"object-assign": "^4.1.1",
|
"object-assign": "^4.1.1",
|
||||||
@ -3527,8 +3557,7 @@
|
|||||||
"node_modules/react-is": {
|
"node_modules/react-is": {
|
||||||
"version": "16.13.1",
|
"version": "16.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/read-cache": {
|
"node_modules/read-cache": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
@ -3756,6 +3785,11 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/state-local": {
|
||||||
|
"version": "1.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz",
|
||||||
|
"integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w=="
|
||||||
|
},
|
||||||
"node_modules/string.prototype.matchall": {
|
"node_modules/string.prototype.matchall": {
|
||||||
"version": "4.0.8",
|
"version": "4.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz",
|
||||||
@ -4519,6 +4553,23 @@
|
|||||||
"@jridgewell/sourcemap-codec": "1.4.14"
|
"@jridgewell/sourcemap-codec": "1.4.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@monaco-editor/loader": {
|
||||||
|
"version": "1.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.3.2.tgz",
|
||||||
|
"integrity": "sha512-BTDbpHl3e47r3AAtpfVFTlAi7WXv4UQ/xZmz8atKl4q7epQV5e7+JbigFDViWF71VBi4IIBdcWP57Hj+OWuc9g==",
|
||||||
|
"requires": {
|
||||||
|
"state-local": "^1.0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@monaco-editor/react": {
|
||||||
|
"version": "4.4.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.4.6.tgz",
|
||||||
|
"integrity": "sha512-Gr3uz3LYf33wlFE3eRnta4RxP5FSNxiIV9ENn2D2/rN8KgGAD8ecvcITRtsbbyuOuNkwbuHYxfeaz2Vr+CtyFA==",
|
||||||
|
"requires": {
|
||||||
|
"@monaco-editor/loader": "^1.3.2",
|
||||||
|
"prop-types": "^15.7.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@next/env": {
|
"@next/env": {
|
||||||
"version": "13.1.1",
|
"version": "13.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@next/env/-/env-13.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@next/env/-/env-13.1.1.tgz",
|
||||||
@ -6270,6 +6321,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz",
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz",
|
||||||
"integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g=="
|
"integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g=="
|
||||||
},
|
},
|
||||||
|
"monaco-editor": {
|
||||||
|
"version": "0.34.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.34.1.tgz",
|
||||||
|
"integrity": "sha512-FKc80TyiMaruhJKKPz5SpJPIjL+dflGvz4CpuThaPMc94AyN7SeC9HQ8hrvaxX7EyHdJcUY5i4D0gNyJj1vSZQ=="
|
||||||
|
},
|
||||||
"ms": {
|
"ms": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
@ -6350,8 +6406,7 @@
|
|||||||
"object-assign": {
|
"object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"object-hash": {
|
"object-hash": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
@ -6595,7 +6650,6 @@
|
|||||||
"version": "15.8.1",
|
"version": "15.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"loose-envify": "^1.4.0",
|
"loose-envify": "^1.4.0",
|
||||||
"object-assign": "^4.1.1",
|
"object-assign": "^4.1.1",
|
||||||
@ -6637,8 +6691,7 @@
|
|||||||
"react-is": {
|
"react-is": {
|
||||||
"version": "16.13.1",
|
"version": "16.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"read-cache": {
|
"read-cache": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
@ -6793,6 +6846,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
||||||
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw=="
|
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw=="
|
||||||
},
|
},
|
||||||
|
"state-local": {
|
||||||
|
"version": "1.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz",
|
||||||
|
"integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w=="
|
||||||
|
},
|
||||||
"string.prototype.matchall": {
|
"string.prototype.matchall": {
|
||||||
"version": "4.0.8",
|
"version": "4.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz",
|
||||||
|
|||||||
@ -15,7 +15,9 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@headlessui/react": "^1.7.4",
|
"@headlessui/react": "^1.7.4",
|
||||||
"@heroicons/react": "^2.0.13",
|
"@heroicons/react": "^2.0.13",
|
||||||
|
"@monaco-editor/react": "^4.4.6",
|
||||||
"@tailwindcss/forms": "^0.5.3",
|
"@tailwindcss/forms": "^0.5.3",
|
||||||
|
"monaco-editor": "^0.34.1",
|
||||||
"next": "^13.1.1",
|
"next": "^13.1.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
181c6c1e8f906e05414ee1ebe8117fcb
|
6ae330b5487329c78105faea78224dd4
|
||||||
@ -5,6 +5,8 @@ import { ProjectProvider } from '../context/Project/provider'
|
|||||||
import '../styles/globals.css'
|
import '../styles/globals.css'
|
||||||
import { ipc } from '../wailsjs/wailsjs/go/models'
|
import { ipc } from '../wailsjs/wailsjs/go/models'
|
||||||
import '../styles/globals.css'
|
import '../styles/globals.css'
|
||||||
|
import { NavigationProvidor } from '../context/Navigation/provider'
|
||||||
|
import { workspaces } from '../context/Navigation/types'
|
||||||
|
|
||||||
const initialProjectProps = {
|
const initialProjectProps = {
|
||||||
id: '',
|
id: '',
|
||||||
@ -12,10 +14,16 @@ const initialProjectProps = {
|
|||||||
groups: [] as ipc.Group[]
|
groups: [] as ipc.Group[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const initialNavigationProps = {
|
||||||
|
selectedWorkspace: workspaces.PROCESSOR
|
||||||
|
}
|
||||||
|
|
||||||
export default function MainAppLayout({ Component, pageProps }: AppProps) {
|
export default function MainAppLayout({ Component, pageProps }: AppProps) {
|
||||||
return <div className='min-h-screen' >
|
return <div className='min-h-screen' >
|
||||||
<ProjectProvider projectProps={initialProjectProps}>
|
<NavigationProvidor navigationProps={initialNavigationProps}>
|
||||||
<Component {...pageProps} />
|
<ProjectProvider projectProps={initialProjectProps}>
|
||||||
</ProjectProvider>
|
<Component {...pageProps} />
|
||||||
|
</ProjectProvider>
|
||||||
|
</NavigationProvidor>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,22 @@
|
|||||||
import { NextPage } from 'next'
|
import { NextPage } from 'next'
|
||||||
|
import { useState } from 'react'
|
||||||
import MainHead from '../components/head'
|
import MainHead from '../components/head'
|
||||||
import MainWorkspace from '../components/workspace/Main'
|
import MainWorkspace from '../components/workspace/Main'
|
||||||
import Navigation from '../components/workspace/Navigation'
|
import Navigation from '../components/workspace/Navigation'
|
||||||
|
|
||||||
|
enum workspaces {
|
||||||
|
PROCESSOR = 'PROCESSOR',
|
||||||
|
TEXTEDITOR = 'TEXTEDITOR'
|
||||||
|
}
|
||||||
|
|
||||||
const Home: NextPage = () => {
|
const Home: NextPage = () => {
|
||||||
|
const [ selectedWorkSpace, setSelectedWorkSpace ] = useState(workspaces.PROCESSOR)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<MainHead />
|
<MainHead />
|
||||||
<Navigation />
|
<Navigation />
|
||||||
<MainWorkspace />
|
<MainWorkspace selectedWorkSpace={selectedWorkSpace} />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
61
frontend/useCases/processImageArea.ts
Normal file
61
frontend/useCases/processImageArea.ts
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import { createScheduler, createWorker } from 'tesseract.js'
|
||||||
|
import { GetDocumentById, RequestAddProcessedArea } from '../wailsjs/wailsjs/go/ipc/Channel'
|
||||||
|
import { ipc } from '../wailsjs/wailsjs/go/models'
|
||||||
|
import loadImage from './loadImage'
|
||||||
|
|
||||||
|
const processImageArea = async (documentId: string, area: ipc.Area) => {
|
||||||
|
const foundDocument = await GetDocumentById(documentId)
|
||||||
|
if (!foundDocument.path || !foundDocument.areas?.length) return
|
||||||
|
|
||||||
|
const { path } = foundDocument
|
||||||
|
const imageData = await loadImage(path)
|
||||||
|
|
||||||
|
const scheduler = createScheduler()
|
||||||
|
const worker = await createWorker()
|
||||||
|
await worker.loadLanguage('eng') // TODO: change this when multilangiage system is implementd
|
||||||
|
await worker.initialize('eng') // TODO: same here
|
||||||
|
scheduler.addWorker(worker)
|
||||||
|
|
||||||
|
const result = await scheduler.addJob('recognize', imageData, {
|
||||||
|
rectangle: {
|
||||||
|
left: area.startX,
|
||||||
|
top: area.startY,
|
||||||
|
width: area.endX - area.startX,
|
||||||
|
height: area.endY - area.startY,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const addProcessesAreaRequest = await RequestAddProcessedArea(new ipc.ProcessedArea({
|
||||||
|
id: area.id,
|
||||||
|
documentId,
|
||||||
|
fullText: result.data.text,
|
||||||
|
lines: result.data.lines.map((l: any) => new ipc.ProcessedLine({
|
||||||
|
fullText: l.text,
|
||||||
|
words: l.words.map((w: any) => new ipc.ProcessedWord({
|
||||||
|
fullText: w.text,
|
||||||
|
direction: w.direction,
|
||||||
|
confidence: w.confidence,
|
||||||
|
boundingBox: new ipc.ProcessedBoundingBox({
|
||||||
|
x0: w.bbox.x0,
|
||||||
|
y0: w.bbox.y0,
|
||||||
|
x1: w.bbox.x1,
|
||||||
|
y1: w.bbox.y1,
|
||||||
|
}),
|
||||||
|
symbols: w.symbols.map((s: any) => new ipc.ProcessedSymbol({
|
||||||
|
fullText: s.text,
|
||||||
|
confidence: s.confidence,
|
||||||
|
boundingBox: new ipc.ProcessedBoundingBox({
|
||||||
|
x0: s.bbox.x0,
|
||||||
|
y0: s.bbox.y0,
|
||||||
|
x1: s.bbox.x1,
|
||||||
|
y1: s.bbox.y1,
|
||||||
|
})
|
||||||
|
}))
|
||||||
|
}))
|
||||||
|
}))
|
||||||
|
}))
|
||||||
|
|
||||||
|
return addProcessesAreaRequest
|
||||||
|
}
|
||||||
|
|
||||||
|
export default processImageArea
|
||||||
@ -17,16 +17,11 @@ const processImageData = async (documentId: string) => {
|
|||||||
if (!foundDocument.path || !foundDocument.areas?.length) return
|
if (!foundDocument.path || !foundDocument.areas?.length) return
|
||||||
|
|
||||||
const { areas, path } = foundDocument
|
const { areas, path } = foundDocument
|
||||||
|
|
||||||
console.log(`about to load: ${path}`)
|
|
||||||
|
|
||||||
const imageData = await loadImage(path)
|
const imageData = await loadImage(path)
|
||||||
|
|
||||||
const scheduler = createScheduler()
|
const scheduler = createScheduler()
|
||||||
|
|
||||||
const workerCount = getImageWorkerCount(areas.length)
|
const workerCount = getImageWorkerCount(areas.length)
|
||||||
for (let index = 0; index < workerCount; index++) {
|
for (let index = 0; index < workerCount; index++) {
|
||||||
console.log('add worker stuff')
|
|
||||||
const worker = await createWorker()
|
const worker = await createWorker()
|
||||||
await worker.loadLanguage('eng') // TODO: change this when multilangiage system is implementd
|
await worker.loadLanguage('eng') // TODO: change this when multilangiage system is implementd
|
||||||
await worker.initialize('eng') // TODO: same here
|
await worker.initialize('eng') // TODO: same here
|
||||||
@ -34,7 +29,6 @@ const processImageData = async (documentId: string) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const results = await Promise.allSettled(areas.map(a => {
|
const results = await Promise.allSettled(areas.map(a => {
|
||||||
console.log('adding job')
|
|
||||||
return scheduler.addJob('recognize', imageData, { rectangle: {
|
return scheduler.addJob('recognize', imageData, { rectangle: {
|
||||||
left: a.startX,
|
left: a.startX,
|
||||||
top: a.startY,
|
top: a.startY,
|
||||||
|
|||||||
4
frontend/wailsjs/wailsjs/go/ipc/Channel.d.ts
vendored
4
frontend/wailsjs/wailsjs/go/ipc/Channel.d.ts
vendored
@ -6,10 +6,14 @@ export function GetDocumentById(arg1:string):Promise<ipc.Document>;
|
|||||||
|
|
||||||
export function GetDocuments():Promise<ipc.GetDocumentsResponse>;
|
export function GetDocuments():Promise<ipc.GetDocumentsResponse>;
|
||||||
|
|
||||||
|
export function GetProcessedAreasByDocumentId(arg1:string):Promise<Array<ipc.ProcessedArea>>;
|
||||||
|
|
||||||
export function RequestAddArea(arg1:string,arg2:ipc.Area):Promise<ipc.Area>;
|
export function RequestAddArea(arg1:string,arg2:ipc.Area):Promise<ipc.Area>;
|
||||||
|
|
||||||
export function RequestAddDocument(arg1:string,arg2:string):Promise<ipc.Document>;
|
export function RequestAddDocument(arg1:string,arg2:string):Promise<ipc.Document>;
|
||||||
|
|
||||||
export function RequestAddDocumentGroup(arg1:string):Promise<ipc.Group>;
|
export function RequestAddDocumentGroup(arg1:string):Promise<ipc.Group>;
|
||||||
|
|
||||||
|
export function RequestAddProcessedArea(arg1:ipc.ProcessedArea):Promise<ipc.ProcessedArea>;
|
||||||
|
|
||||||
export function RequestUpdateArea(arg1:ipc.Area):Promise<ipc.Area>;
|
export function RequestUpdateArea(arg1:ipc.Area):Promise<ipc.Area>;
|
||||||
|
|||||||
@ -10,6 +10,10 @@ export function GetDocuments() {
|
|||||||
return window['go']['ipc']['Channel']['GetDocuments']();
|
return window['go']['ipc']['Channel']['GetDocuments']();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function GetProcessedAreasByDocumentId(arg1) {
|
||||||
|
return window['go']['ipc']['Channel']['GetProcessedAreasByDocumentId'](arg1);
|
||||||
|
}
|
||||||
|
|
||||||
export function RequestAddArea(arg1, arg2) {
|
export function RequestAddArea(arg1, arg2) {
|
||||||
return window['go']['ipc']['Channel']['RequestAddArea'](arg1, arg2);
|
return window['go']['ipc']['Channel']['RequestAddArea'](arg1, arg2);
|
||||||
}
|
}
|
||||||
@ -22,6 +26,10 @@ export function RequestAddDocumentGroup(arg1) {
|
|||||||
return window['go']['ipc']['Channel']['RequestAddDocumentGroup'](arg1);
|
return window['go']['ipc']['Channel']['RequestAddDocumentGroup'](arg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function RequestAddProcessedArea(arg1) {
|
||||||
|
return window['go']['ipc']['Channel']['RequestAddProcessedArea'](arg1);
|
||||||
|
}
|
||||||
|
|
||||||
export function RequestUpdateArea(arg1) {
|
export function RequestUpdateArea(arg1) {
|
||||||
return window['go']['ipc']['Channel']['RequestUpdateArea'](arg1);
|
return window['go']['ipc']['Channel']['RequestUpdateArea'](arg1);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -112,6 +112,168 @@ export namespace ipc {
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class ProcessedBoundingBox {
|
||||||
|
x0: number;
|
||||||
|
y0: number;
|
||||||
|
x1: number;
|
||||||
|
y1: number;
|
||||||
|
|
||||||
|
static createFrom(source: any = {}) {
|
||||||
|
return new ProcessedBoundingBox(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(source: any = {}) {
|
||||||
|
if ('string' === typeof source) source = JSON.parse(source);
|
||||||
|
this.x0 = source["x0"];
|
||||||
|
this.y0 = source["y0"];
|
||||||
|
this.x1 = source["x1"];
|
||||||
|
this.y1 = source["y1"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export class ProcessedSymbol {
|
||||||
|
text: string;
|
||||||
|
confidence: number;
|
||||||
|
boundingBox: ProcessedBoundingBox;
|
||||||
|
|
||||||
|
static createFrom(source: any = {}) {
|
||||||
|
return new ProcessedSymbol(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(source: any = {}) {
|
||||||
|
if ('string' === typeof source) source = JSON.parse(source);
|
||||||
|
this.text = source["text"];
|
||||||
|
this.confidence = source["confidence"];
|
||||||
|
this.boundingBox = this.convertValues(source["boundingBox"], ProcessedBoundingBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
convertValues(a: any, classs: any, asMap: boolean = false): any {
|
||||||
|
if (!a) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
if (a.slice) {
|
||||||
|
return (a as any[]).map(elem => this.convertValues(elem, classs));
|
||||||
|
} else if ("object" === typeof a) {
|
||||||
|
if (asMap) {
|
||||||
|
for (const key of Object.keys(a)) {
|
||||||
|
a[key] = new classs(a[key]);
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
return new classs(a);
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export class ProcessedWord {
|
||||||
|
fullText: string;
|
||||||
|
symbols: ProcessedSymbol[];
|
||||||
|
confidence: number;
|
||||||
|
direction: string;
|
||||||
|
boundingBox: ProcessedBoundingBox;
|
||||||
|
|
||||||
|
static createFrom(source: any = {}) {
|
||||||
|
return new ProcessedWord(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(source: any = {}) {
|
||||||
|
if ('string' === typeof source) source = JSON.parse(source);
|
||||||
|
this.fullText = source["fullText"];
|
||||||
|
this.symbols = this.convertValues(source["symbols"], ProcessedSymbol);
|
||||||
|
this.confidence = source["confidence"];
|
||||||
|
this.direction = source["direction"];
|
||||||
|
this.boundingBox = this.convertValues(source["boundingBox"], ProcessedBoundingBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
convertValues(a: any, classs: any, asMap: boolean = false): any {
|
||||||
|
if (!a) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
if (a.slice) {
|
||||||
|
return (a as any[]).map(elem => this.convertValues(elem, classs));
|
||||||
|
} else if ("object" === typeof a) {
|
||||||
|
if (asMap) {
|
||||||
|
for (const key of Object.keys(a)) {
|
||||||
|
a[key] = new classs(a[key]);
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
return new classs(a);
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export class ProcessedLine {
|
||||||
|
fullText: string;
|
||||||
|
words: ProcessedWord[];
|
||||||
|
|
||||||
|
static createFrom(source: any = {}) {
|
||||||
|
return new ProcessedLine(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(source: any = {}) {
|
||||||
|
if ('string' === typeof source) source = JSON.parse(source);
|
||||||
|
this.fullText = source["fullText"];
|
||||||
|
this.words = this.convertValues(source["words"], ProcessedWord);
|
||||||
|
}
|
||||||
|
|
||||||
|
convertValues(a: any, classs: any, asMap: boolean = false): any {
|
||||||
|
if (!a) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
if (a.slice) {
|
||||||
|
return (a as any[]).map(elem => this.convertValues(elem, classs));
|
||||||
|
} else if ("object" === typeof a) {
|
||||||
|
if (asMap) {
|
||||||
|
for (const key of Object.keys(a)) {
|
||||||
|
a[key] = new classs(a[key]);
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
return new classs(a);
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export class ProcessedArea {
|
||||||
|
id: string;
|
||||||
|
documentId: string;
|
||||||
|
fullText: string;
|
||||||
|
lines: ProcessedLine[];
|
||||||
|
|
||||||
|
static createFrom(source: any = {}) {
|
||||||
|
return new ProcessedArea(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(source: any = {}) {
|
||||||
|
if ('string' === typeof source) source = JSON.parse(source);
|
||||||
|
this.id = source["id"];
|
||||||
|
this.documentId = source["documentId"];
|
||||||
|
this.fullText = source["fullText"];
|
||||||
|
this.lines = this.convertValues(source["lines"], ProcessedLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
convertValues(a: any, classs: any, asMap: boolean = false): any {
|
||||||
|
if (!a) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
if (a.slice) {
|
||||||
|
return (a as any[]).map(elem => this.convertValues(elem, classs));
|
||||||
|
} else if ("object" === typeof a) {
|
||||||
|
if (asMap) {
|
||||||
|
for (const key of Object.keys(a)) {
|
||||||
|
a[key] = new classs(a[key]);
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
return new classs(a);
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -35,3 +35,36 @@ type Area struct {
|
|||||||
EndX int `json:"endX"`
|
EndX int `json:"endX"`
|
||||||
EndY int `json:"endY"`
|
EndY int `json:"endY"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ProcessedBoundingBox struct {
|
||||||
|
X0 int32 `json:"x0"`
|
||||||
|
Y0 int32 `json:"y0"`
|
||||||
|
X1 int32 `json:"x1"`
|
||||||
|
Y1 int32 `json:"y1"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProcessedSymbol struct {
|
||||||
|
Text string `json:"text"`
|
||||||
|
Confidence float32 `json:"confidence"`
|
||||||
|
BoundingBox ProcessedBoundingBox `json:"boundingBox"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProcessedWord struct {
|
||||||
|
FullText string `json:"fullText"`
|
||||||
|
Symbols []ProcessedSymbol `json:"symbols"`
|
||||||
|
Confidence float32 `json:"confidence"`
|
||||||
|
Direction string `json:"direction"`
|
||||||
|
BoundingBox ProcessedBoundingBox `json:"boundingBox"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProcessedLine struct {
|
||||||
|
FullText string `json:"fullText"`
|
||||||
|
Words []ProcessedWord `json:"words"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProcessedArea struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
DocumentId string `json:"documentId"`
|
||||||
|
FullText string `json:"fullText"`
|
||||||
|
Lines []ProcessedLine `json:"lines"`
|
||||||
|
}
|
||||||
|
|||||||
159
ipc/ProcessedDocument.go
Normal file
159
ipc/ProcessedDocument.go
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
package ipc
|
||||||
|
|
||||||
|
import (
|
||||||
|
document "textualize/core/Document"
|
||||||
|
)
|
||||||
|
|
||||||
|
func serializeBoundingBox(bbox document.ProcessedBoundingBox) ProcessedBoundingBox {
|
||||||
|
return ProcessedBoundingBox{
|
||||||
|
X0: bbox.X0,
|
||||||
|
Y0: bbox.Y0,
|
||||||
|
X1: bbox.X1,
|
||||||
|
Y1: bbox.Y1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func serializeSymbol(symbol document.ProcessedSymbol) ProcessedSymbol {
|
||||||
|
return ProcessedSymbol{
|
||||||
|
Text: symbol.Text,
|
||||||
|
Confidence: symbol.Confidence,
|
||||||
|
BoundingBox: serializeBoundingBox(symbol.BoundingBox),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func serialzeWord(word document.ProcessedWord) ProcessedWord {
|
||||||
|
var symbols []ProcessedSymbol
|
||||||
|
|
||||||
|
for _, symbol := range word.Symbols {
|
||||||
|
symbols = append(symbols, serializeSymbol(symbol))
|
||||||
|
}
|
||||||
|
|
||||||
|
return ProcessedWord{
|
||||||
|
FullText: word.FullText,
|
||||||
|
Symbols: symbols,
|
||||||
|
Confidence: word.Confidence,
|
||||||
|
Direction: word.Direction,
|
||||||
|
BoundingBox: serializeBoundingBox(word.BoundingBox),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func serializeLine(line document.ProcessedLine) ProcessedLine {
|
||||||
|
var words []ProcessedWord
|
||||||
|
|
||||||
|
for _, word := range line.Words {
|
||||||
|
words = append(words, serialzeWord((word)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return ProcessedLine{
|
||||||
|
FullText: line.FullText,
|
||||||
|
Words: words,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func serializeProcessedArea(area document.ProcessedArea) ProcessedArea {
|
||||||
|
var lines []ProcessedLine
|
||||||
|
|
||||||
|
for _, line := range area.Lines {
|
||||||
|
lines = append(lines, serializeLine(line))
|
||||||
|
}
|
||||||
|
|
||||||
|
return ProcessedArea{
|
||||||
|
Id: area.Id,
|
||||||
|
DocumentId: area.DocumentId,
|
||||||
|
FullText: area.FullText,
|
||||||
|
Lines: lines,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Channel) GetProcessedAreasByDocumentId(id string) []ProcessedArea {
|
||||||
|
areas := document.GetProcessedAreaCollection().GetAreasByDocumentId(id)
|
||||||
|
|
||||||
|
var response []ProcessedArea
|
||||||
|
|
||||||
|
for _, a := range areas {
|
||||||
|
response = append(response, serializeProcessedArea(*a))
|
||||||
|
}
|
||||||
|
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
func deserializeBoundingBox(bbox ProcessedBoundingBox) document.ProcessedBoundingBox {
|
||||||
|
return document.ProcessedBoundingBox{
|
||||||
|
X0: bbox.X0,
|
||||||
|
Y0: bbox.Y0,
|
||||||
|
X1: bbox.X1,
|
||||||
|
Y1: bbox.Y1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func deserializeSymbol(symbol ProcessedSymbol) document.ProcessedSymbol {
|
||||||
|
return document.ProcessedSymbol{
|
||||||
|
Text: symbol.Text,
|
||||||
|
Confidence: symbol.Confidence,
|
||||||
|
BoundingBox: deserializeBoundingBox(symbol.BoundingBox),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func deserialzeWord(word ProcessedWord) document.ProcessedWord {
|
||||||
|
var symbols []document.ProcessedSymbol
|
||||||
|
|
||||||
|
for _, symbol := range word.Symbols {
|
||||||
|
symbols = append(symbols, deserializeSymbol(symbol))
|
||||||
|
}
|
||||||
|
|
||||||
|
return document.ProcessedWord{
|
||||||
|
FullText: word.FullText,
|
||||||
|
Symbols: symbols,
|
||||||
|
Confidence: word.Confidence,
|
||||||
|
Direction: word.Direction,
|
||||||
|
BoundingBox: deserializeBoundingBox(word.BoundingBox),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func deserializeLine(line ProcessedLine) document.ProcessedLine {
|
||||||
|
var words []document.ProcessedWord
|
||||||
|
|
||||||
|
for _, word := range line.Words {
|
||||||
|
words = append(words, deserialzeWord((word)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return document.ProcessedLine{
|
||||||
|
FullText: line.FullText,
|
||||||
|
Words: words,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func deserializeProcessedArea(area ProcessedArea) document.ProcessedArea {
|
||||||
|
var lines []document.ProcessedLine
|
||||||
|
|
||||||
|
for _, line := range area.Lines {
|
||||||
|
lines = append(lines, deserializeLine(line))
|
||||||
|
}
|
||||||
|
|
||||||
|
return document.ProcessedArea{
|
||||||
|
Id: area.Id,
|
||||||
|
DocumentId: area.DocumentId,
|
||||||
|
FullText: area.FullText,
|
||||||
|
Lines: lines,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Channel) RequestAddProcessedArea(area ProcessedArea) ProcessedArea {
|
||||||
|
var currentAreaIds []string
|
||||||
|
|
||||||
|
for _, a := range document.GetProcessedAreaCollection().Areas {
|
||||||
|
currentAreaIds = append(currentAreaIds, a.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
areaAlreadyExists := false
|
||||||
|
for _, areaId := range currentAreaIds {
|
||||||
|
if area.Id == areaId {
|
||||||
|
areaAlreadyExists = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !areaAlreadyExists {
|
||||||
|
document.GetProcessedAreaCollection().AddProcessedArea((deserializeProcessedArea(area)))
|
||||||
|
}
|
||||||
|
return area
|
||||||
|
}
|
||||||
3
main.go
3
main.go
@ -32,10 +32,7 @@ func ClientFileLoader() *FileLoader {
|
|||||||
|
|
||||||
func (h *FileLoader) ServeHTTP(res http.ResponseWriter, req *http.Request) {
|
func (h *FileLoader) ServeHTTP(res http.ResponseWriter, req *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
// Make sure to prefix all local files with this in renderer
|
|
||||||
// requestedFilename := strings.TrimPrefix(req.URL.Path, "/textualizeFileAssets")
|
|
||||||
requestedFilename := req.URL.Path
|
requestedFilename := req.URL.Path
|
||||||
fmt.Println(requestedFilename)
|
|
||||||
fileData, err := os.ReadFile(requestedFilename)
|
fileData, err := os.ReadFile(requestedFilename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("was eror: ")
|
fmt.Println("was eror: ")
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user