feat: reorder areas

This commit is contained in:
Joshua Shoemaker 2023-02-22 21:18:48 -06:00
parent 8eada10e87
commit 405e7c0a23
12 changed files with 155 additions and 15 deletions

View File

@ -1,6 +1,8 @@
package document package document
import app "textualize/core/App" import (
app "textualize/core/App"
)
type Entity struct { type Entity struct {
Id string Id string
@ -20,6 +22,7 @@ type Area struct {
EndX int EndX int
EndY int EndY int
Language app.Language Language app.Language
Order int
} }
func (e *Entity) AddArea(a Area) { func (e *Entity) AddArea(a Area) {

View File

@ -30,6 +30,7 @@ type ProcessedArea struct {
Id string Id string
DocumentId string DocumentId string
FullText string FullText string
Order int // TODO: make reorder feature
Lines []ProcessedLine Lines []ProcessedLine
} }
@ -61,3 +62,16 @@ func (collection *ProcessedAreaCollection) GetAreasByDocumentId(id string) []*Pr
return foundAreas return foundAreas
} }
func (collection *ProcessedAreaCollection) GetAreaById(areaId string) *ProcessedArea {
var foundArea *ProcessedArea
for index, a := range collection.Areas {
if a.Id == areaId {
foundArea = &collection.Areas[index]
break
}
}
return foundArea
}

View File

@ -12,7 +12,7 @@ type GroupNavigationItem = {
documents: { documents: {
id: string, id: string,
name: string, name: string,
areas: { id: string, name: string }[] areas: { id: string, name: string, order: number }[]
}[] }[]
} }
@ -23,7 +23,7 @@ const getNavigationProps = (documents: ipc.Document[], groups: ipc.Group[]): Gro
.map(d => ({ .map(d => ({
id: d.id, id: d.id,
name: d.name, name: d.name,
areas: d.areas.map(a => ({ id: a.id, name: a.name })) areas: d.areas.map(a => ({ id: a.id, name: a.name, order: a.order }))//.sort((a, b) => a.order - b.order)
})) }))
return { return {
@ -38,7 +38,7 @@ const getNavigationProps = (documents: ipc.Document[], groups: ipc.Group[]): Gro
.map(d => ({ .map(d => ({
id: d.id, id: d.id,
name: d.name, name: d.name,
areas: d.areas.map(a => ({ id: a.id, name: a.name })) areas: d.areas.map(a => ({ id: a.id, name: a.name, order: a.order }))//.sort((a, b) => a.order - b.order)
})) }))
return [ return [
@ -57,6 +57,8 @@ function Sidebar() {
const [isEditDocumentNameInputShowing, setIsEditDocumentNameInputShowing] = useState(false) const [isEditDocumentNameInputShowing, setIsEditDocumentNameInputShowing] = useState(false)
const [isAddNewGroupInputShowing, setIsAddNewGroupInputShowing] = useState(false) const [isAddNewGroupInputShowing, setIsAddNewGroupInputShowing] = useState(false)
const [isEditAreaNameInputShowing, setIsEditAreaNameInputShowing] = useState(false) const [isEditAreaNameInputShowing, setIsEditAreaNameInputShowing] = useState(false)
const [dragOverAreaId, setDragOverAreaId] = useState('')
const addDocumentTextInput = useRef<HTMLInputElement>(null) const addDocumentTextInput = useRef<HTMLInputElement>(null)
const addGroupTextInput = useRef<HTMLInputElement>(null) const addGroupTextInput = useRef<HTMLInputElement>(null)
const editAreaNameTextInput = useRef<HTMLInputElement>(null) const editAreaNameTextInput = useRef<HTMLInputElement>(null)
@ -76,6 +78,7 @@ function Sidebar() {
setSelectedDocumentId, setSelectedDocumentId,
currentSession, currentSession,
requestUpdateDocument, requestUpdateDocument,
requestChangeAreaOrder,
} = useProject() } = useProject()
const navigation = getNavigationProps(documents, groups) const navigation = getNavigationProps(documents, groups)
@ -117,15 +120,43 @@ function Sidebar() {
} }
const onAreaDoubleClick = (areaId: string) => { const onAreaDoubleClick = (areaId: string) => {
const documentIdOfArea = getDocumentIdFromAreaId(areaId) setSelectedDocumentId(getDocumentIdFromAreaId(areaId) || '')
setIsEditAreaNameInputShowing(true) setIsEditAreaNameInputShowing(true)
console.log('double click')
} }
const onAreaInputBlur = () => { const onAreaInputBlur = () => {
setIsEditAreaNameInputShowing(false) setIsEditAreaNameInputShowing(false)
} }
// ________________
const onAreaDragOver = (areaId: string) => {
setDragOverAreaId(areaId)
}
const onAreaDragStart = (areaId: string) => {
// setDragStartAreaId(areaId)
}
const onAreaDropEnd = (areaId: string) => {
const areaDroppedOn = navigation.map(n => n.documents).flat().map(d => d.areas).flat().find(a => a.id === dragOverAreaId)
if (!areaDroppedOn) return
requestChangeAreaOrder(areaId, areaDroppedOn.order)
setDragOverAreaId('')
}
// ________________
const onDocumentClickHandler = (itemId: string) => { const onDocumentClickHandler = (itemId: string) => {
setSelectedDocumentId(itemId) setSelectedDocumentId(itemId)
setSelectedGroupId(getGroupIdFromDocumentId(itemId)) setSelectedGroupId(getGroupIdFromDocumentId(itemId))
@ -415,13 +446,18 @@ function Sidebar() {
role='button' role='button'
onClick={() => onAreaClick(a.id)} onClick={() => onAreaClick(a.id)}
onDoubleClick={() => onAreaDoubleClick(a.id)} onDoubleClick={() => onAreaDoubleClick(a.id)}
draggable
onDragOver={() => onAreaDragOver(a.id)}
onDragStart={() => onAreaDragStart(a.id)}
onDragEnd={() => onAreaDropEnd(a.id)}
className={classNames('text-gray-300 hover:bg-gray-700 hover:text-white', className={classNames('text-gray-300 hover:bg-gray-700 hover:text-white',
'group w-full flex items-center pr-2 py-2 text-left font-medium pl-8 text-xs', 'group w-full flex items-center 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', 'rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 py-2 select-none',
selectedAreaId === a.id ? 'underline' : '' selectedAreaId === a.id ? 'underline' : '',
dragOverAreaId === a.id ? 'bg-gray-300 text-gray-700' : ''
)} )}
> >
{a.name || `Area ${index + 1}`} {a.name || `Area ${a.order}`}
</a> </a>
} }
</li> </li>

View File

@ -24,6 +24,7 @@ const makeDefaultProject = (): ProjectContextType => ({
requestUpdateCurrentUser: (updatedUserProps: UserProps) => Promise.resolve(new ipc.User()), requestUpdateCurrentUser: (updatedUserProps: UserProps) => Promise.resolve(new ipc.User()),
requestChooseUserAvatar: () => Promise.resolve(''), requestChooseUserAvatar: () => Promise.resolve(''),
requestUpdateDocument: ({}) => Promise.resolve(new ipc.Document), requestUpdateDocument: ({}) => Promise.resolve(new ipc.Document),
requestChangeAreaOrder: (areaId: string, newOrder: number) => Promise.resolve(new ipc.Document()),
}) })
export default makeDefaultProject export default makeDefaultProject

View File

@ -8,6 +8,7 @@ import {
RequestUpdateArea, RequestUpdateCurrentUser, RequestUpdateDocumentUserMarkdown, RequestUpdateArea, RequestUpdateCurrentUser, RequestUpdateDocumentUserMarkdown,
RequestChooseUserAvatar, RequestChooseUserAvatar,
RequestUpdateDocument, RequestUpdateDocument,
RequestChangeAreaOrder,
} 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'
@ -29,6 +30,7 @@ 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)
@ -124,12 +126,18 @@ export function ProjectProvider({ children, projectProps }: Props) {
} }
const requestUpdateDocument = async (docuemntProps: UpdateDocumentRequest) => { const requestUpdateDocument = async (docuemntProps: UpdateDocumentRequest) => {
console.log('request: ', docuemntProps)
const response = await RequestUpdateDocument(new ipc.Document(docuemntProps)) const response = await RequestUpdateDocument(new ipc.Document(docuemntProps))
await updateDocuments() await updateDocuments()
return response return response
} }
const requestChangeAreaOrder = async (areaId: string, newOrder: number) => {
console.log('requestChangeAreaOrder')
const response = await RequestChangeAreaOrder(areaId, newOrder)
await updateDocuments()
return response
}
useEffect(() => { useEffect(() => {
if (!documents.length && !groups.length) updateDocuments() if (!documents.length && !groups.length) updateDocuments()
}, [documents.length, groups.length]) }, [documents.length, groups.length])
@ -157,6 +165,7 @@ export function ProjectProvider({ children, projectProps }: Props) {
requestUpdateCurrentUser, requestUpdateCurrentUser,
requestChooseUserAvatar, requestChooseUserAvatar,
requestUpdateDocument, requestUpdateDocument,
requestChangeAreaOrder,
} }
return <ProjectContext.Provider value={value}> return <ProjectContext.Provider value={value}>

View File

@ -56,4 +56,5 @@ export type ProjectContextType = {
requestUpdateCurrentUser: (updatedUserProps: UserProps) => Promise<ipc.User> requestUpdateCurrentUser: (updatedUserProps: UserProps) => Promise<ipc.User>
requestChooseUserAvatar: () => Promise<string> requestChooseUserAvatar: () => Promise<string>
requestUpdateDocument: (request: UpdateDocumentRequest) => Promise<ipc.Document> requestUpdateDocument: (request: UpdateDocumentRequest) => Promise<ipc.Document>
requestChangeAreaOrder: (areaId: string, newOrder: number) => Promise<ipc.Document>
} & ProjectProps } & ProjectProps

View File

@ -26,6 +26,8 @@ export function RequestAddDocumentGroup(arg1:string):Promise<ipc.Group>;
export function RequestAddProcessedArea(arg1:ipc.ProcessedArea):Promise<ipc.ProcessedArea>; export function RequestAddProcessedArea(arg1:ipc.ProcessedArea):Promise<ipc.ProcessedArea>;
export function RequestChangeAreaOrder(arg1:string,arg2:number):Promise<ipc.Document>;
export function RequestChooseUserAvatar():Promise<string>; export function RequestChooseUserAvatar():Promise<string>;
export function RequestUpdateArea(arg1:ipc.Area):Promise<ipc.Area>; export function RequestUpdateArea(arg1:ipc.Area):Promise<ipc.Area>;

View File

@ -50,6 +50,10 @@ export function RequestAddProcessedArea(arg1) {
return window['go']['ipc']['Channel']['RequestAddProcessedArea'](arg1); return window['go']['ipc']['Channel']['RequestAddProcessedArea'](arg1);
} }
export function RequestChangeAreaOrder(arg1, arg2) {
return window['go']['ipc']['Channel']['RequestChangeAreaOrder'](arg1, arg2);
}
export function RequestChooseUserAvatar() { export function RequestChooseUserAvatar() {
return window['go']['ipc']['Channel']['RequestChooseUserAvatar'](); return window['go']['ipc']['Channel']['RequestChooseUserAvatar']();
} }

View File

@ -24,6 +24,7 @@ export namespace ipc {
endX: number; endX: number;
endY: number; endY: number;
language: Language; language: Language;
order: number;
static createFrom(source: any = {}) { static createFrom(source: any = {}) {
return new Area(source); return new Area(source);
@ -38,6 +39,7 @@ export namespace ipc {
this.endX = source["endX"]; this.endX = source["endX"];
this.endY = source["endY"]; this.endY = source["endY"];
this.language = this.convertValues(source["language"], Language); this.language = this.convertValues(source["language"], Language);
this.order = source["order"];
} }
convertValues(a: any, classs: any, asMap: boolean = false): any { convertValues(a: any, classs: any, asMap: boolean = false): any {
@ -338,6 +340,7 @@ export namespace ipc {
id: string; id: string;
documentId: string; documentId: string;
fullText: string; fullText: string;
order: number;
lines: ProcessedLine[]; lines: ProcessedLine[];
static createFrom(source: any = {}) { static createFrom(source: any = {}) {
@ -349,6 +352,7 @@ export namespace ipc {
this.id = source["id"]; this.id = source["id"];
this.documentId = source["documentId"]; this.documentId = source["documentId"];
this.fullText = source["fullText"]; this.fullText = source["fullText"];
this.order = source["order"];
this.lines = this.convertValues(source["lines"], ProcessedLine); this.lines = this.convertValues(source["lines"], ProcessedLine);
} }

View File

@ -1,7 +1,7 @@
package ipc package ipc
import ( import (
"fmt" "sort"
app "textualize/core/App" app "textualize/core/App"
document "textualize/core/Document" document "textualize/core/Document"
session "textualize/core/Session" session "textualize/core/Session"
@ -27,6 +27,7 @@ func (c *Channel) GetDocumentById(id string) Document {
StartY: a.StartY, StartY: a.StartY,
EndX: a.EndX, EndX: a.EndX,
EndY: a.EndY, EndY: a.EndY,
Order: a.Order,
Language: Language(a.Language), Language: Language(a.Language),
}) })
} }
@ -60,10 +61,19 @@ func (c *Channel) GetDocuments() GetDocumentsResponse {
StartY: a.StartY, StartY: a.StartY,
EndX: a.EndX, EndX: a.EndX,
EndY: a.EndY, EndY: a.EndY,
Order: a.Order,
Language: Language(a.Language), Language: Language(a.Language),
}) })
} }
// sort.Slice(jsonAreas, func(i, j int) bool {
// return jsonAreas[i].Order < jsonAreas[j].Order
// })
sort.Slice(jsonAreas, func(i, j int) bool {
return jsonAreas[i].Order < jsonAreas[j].Order
})
jsonDocument := Document{ jsonDocument := Document{
Id: d.Id, Id: d.Id,
GroupId: d.GroupId, GroupId: d.GroupId,
@ -193,6 +203,11 @@ func (c *Channel) RequestAddArea(documentId string, area Area) Area {
id = area.Id id = area.Id
} }
order := area.Order
if order < 1 {
order = len(foundDocument.Areas)
}
newArea := document.Area{ newArea := document.Area{
Id: id, Id: id,
Name: area.Name, Name: area.Name,
@ -200,6 +215,7 @@ func (c *Channel) RequestAddArea(documentId string, area Area) Area {
EndX: area.EndX, EndX: area.EndX,
StartY: area.StartY, StartY: area.StartY,
EndY: area.EndY, EndY: area.EndY,
Order: order,
Language: app.Language(area.Language), Language: app.Language(area.Language),
} }
foundDocument.AddArea(newArea) foundDocument.AddArea(newArea)
@ -227,6 +243,9 @@ func (c *Channel) RequestUpdateArea(updatedArea Area) Area {
if updatedArea.Name != "" { if updatedArea.Name != "" {
areaToUpdate.Name = updatedArea.Name areaToUpdate.Name = updatedArea.Name
} }
if updatedArea.Order != areaToUpdate.Order {
areaToUpdate.Order = updatedArea.Order
}
return Area{ return Area{
Id: areaToUpdate.Id, Id: areaToUpdate.Id,
@ -235,6 +254,7 @@ func (c *Channel) RequestUpdateArea(updatedArea Area) Area {
StartY: areaToUpdate.StartY, StartY: areaToUpdate.StartY,
EndX: areaToUpdate.EndX, EndX: areaToUpdate.EndX,
EndY: areaToUpdate.EndY, EndY: areaToUpdate.EndY,
Order: areaToUpdate.Order,
Language: Language(areaToUpdate.Language), Language: Language(areaToUpdate.Language),
} }
} }
@ -262,8 +282,41 @@ func (c *Channel) RequestUpdateDocument(updatedDocument Document) Document {
documentToUpdate.DefaultLanguage = app.Language(updatedDocument.DefaultLanguage) documentToUpdate.DefaultLanguage = app.Language(updatedDocument.DefaultLanguage)
} }
fmt.Println("updated doc")
fmt.Println(document.GetDocumentCollection().GetDocumentById(updatedDocument.Id))
return updatedDocument return updatedDocument
} }
func (c *Channel) RequestChangeAreaOrder(areaId string, newOrder int) Document {
documentOfArea := document.GetDocumentCollection().GetDocumentByAreaId((areaId))
if documentOfArea == nil {
return Document{}
}
var foundArea document.Area
for _, a := range documentOfArea.Areas {
if a.Id == areaId {
foundArea = a
break
}
}
if foundArea.Id == "" {
return Document{}
}
processedAreasCollection := document.GetProcessedAreaCollection()
for index, a := range documentOfArea.Areas {
if a.Order < newOrder {
continue
} else if a.Id == areaId {
documentOfArea.Areas[index].Order = newOrder
processedAreasCollection.GetAreaById(a.Id).Order = newOrder
} else {
documentOfArea.Areas[index].Order = a.Order + 1
processedAreasCollection.GetAreaById(a.Id).Order = a.Order + 1
}
}
return c.GetDocumentById(documentOfArea.Id)
}

View File

@ -36,6 +36,7 @@ type Area struct {
EndX int `json:"endX"` EndX int `json:"endX"`
EndY int `json:"endY"` EndY int `json:"endY"`
Language Language `json:"language"` Language Language `json:"language"`
Order int `json:"order"`
} }
type ProcessedBoundingBox struct { type ProcessedBoundingBox struct {
@ -68,6 +69,7 @@ type ProcessedArea struct {
Id string `json:"id"` Id string `json:"id"`
DocumentId string `json:"documentId"` DocumentId string `json:"documentId"`
FullText string `json:"fullText"` FullText string `json:"fullText"`
Order int `json:"order"`
Lines []ProcessedLine `json:"lines"` Lines []ProcessedLine `json:"lines"`
} }

View File

@ -1,6 +1,7 @@
package ipc package ipc
import ( import (
"sort"
document "textualize/core/Document" document "textualize/core/Document"
) )
@ -61,6 +62,7 @@ func serializeProcessedArea(area document.ProcessedArea) ProcessedArea {
Id: area.Id, Id: area.Id,
DocumentId: area.DocumentId, DocumentId: area.DocumentId,
FullText: area.FullText, FullText: area.FullText,
Order: area.Order,
Lines: lines, Lines: lines,
} }
} }
@ -74,6 +76,10 @@ func (c *Channel) GetProcessedAreasByDocumentId(id string) []ProcessedArea {
response = append(response, serializeProcessedArea(*a)) response = append(response, serializeProcessedArea(*a))
} }
sort.Slice(response, func(i, j int) bool {
return response[i].Order < response[j].Order
})
return response return response
} }
@ -141,7 +147,9 @@ func deserializeProcessedArea(area ProcessedArea) document.ProcessedArea {
func (c *Channel) RequestAddProcessedArea(area ProcessedArea) ProcessedArea { func (c *Channel) RequestAddProcessedArea(area ProcessedArea) ProcessedArea {
var currentAreaIds []string var currentAreaIds []string
for _, a := range document.GetProcessedAreaCollection().Areas { processedAreasCollection := document.GetProcessedAreaCollection()
for _, a := range processedAreasCollection.Areas {
currentAreaIds = append(currentAreaIds, a.Id) currentAreaIds = append(currentAreaIds, a.Id)
} }
@ -153,7 +161,10 @@ func (c *Channel) RequestAddProcessedArea(area ProcessedArea) ProcessedArea {
} }
if !areaAlreadyExists { if !areaAlreadyExists {
document.GetProcessedAreaCollection().AddProcessedArea((deserializeProcessedArea(area))) processedArea := deserializeProcessedArea(area)
currentAreasOfDocument := processedAreasCollection.GetAreasByDocumentId(area.DocumentId)
processedArea.Order = len(currentAreasOfDocument)
document.GetProcessedAreaCollection().AddProcessedArea(processedArea)
} }
return area return area
} }