From 405e7c0a237e03a9cb1fda33788be3c62102c243 Mon Sep 17 00:00:00 2001 From: Joshua Shoemaker Date: Wed, 22 Feb 2023 21:18:48 -0600 Subject: [PATCH] feat: reorder areas --- core/Document/Document.go | 5 +- core/Document/ProcessedText.go | 14 +++++ frontend/components/workspace/Sidebar.tsx | 50 ++++++++++++--- .../context/Project/makeDefaultProject.ts | 1 + frontend/context/Project/provider.tsx | 11 +++- frontend/context/Project/types.ts | 1 + frontend/wailsjs/wailsjs/go/ipc/Channel.d.ts | 2 + frontend/wailsjs/wailsjs/go/ipc/Channel.js | 4 ++ frontend/wailsjs/wailsjs/go/models.ts | 4 ++ ipc/Documents.go | 61 +++++++++++++++++-- ipc/JsonEntities.go | 2 + ipc/ProcessedDocument.go | 15 ++++- 12 files changed, 155 insertions(+), 15 deletions(-) diff --git a/core/Document/Document.go b/core/Document/Document.go index 2cc13ee..aba446d 100644 --- a/core/Document/Document.go +++ b/core/Document/Document.go @@ -1,6 +1,8 @@ package document -import app "textualize/core/App" +import ( + app "textualize/core/App" +) type Entity struct { Id string @@ -20,6 +22,7 @@ type Area struct { EndX int EndY int Language app.Language + Order int } func (e *Entity) AddArea(a Area) { diff --git a/core/Document/ProcessedText.go b/core/Document/ProcessedText.go index 0ae9f62..56a8f32 100644 --- a/core/Document/ProcessedText.go +++ b/core/Document/ProcessedText.go @@ -30,6 +30,7 @@ type ProcessedArea struct { Id string DocumentId string FullText string + Order int // TODO: make reorder feature Lines []ProcessedLine } @@ -61,3 +62,16 @@ func (collection *ProcessedAreaCollection) GetAreasByDocumentId(id string) []*Pr 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 +} diff --git a/frontend/components/workspace/Sidebar.tsx b/frontend/components/workspace/Sidebar.tsx index 8d7e294..e7aa5e3 100644 --- a/frontend/components/workspace/Sidebar.tsx +++ b/frontend/components/workspace/Sidebar.tsx @@ -12,7 +12,7 @@ type GroupNavigationItem = { documents: { id: 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 => ({ id: d.id, 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 { @@ -38,7 +38,7 @@ const getNavigationProps = (documents: ipc.Document[], groups: ipc.Group[]): Gro .map(d => ({ id: d.id, 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 [ @@ -57,6 +57,8 @@ function Sidebar() { const [isEditDocumentNameInputShowing, setIsEditDocumentNameInputShowing] = useState(false) const [isAddNewGroupInputShowing, setIsAddNewGroupInputShowing] = useState(false) const [isEditAreaNameInputShowing, setIsEditAreaNameInputShowing] = useState(false) + const [dragOverAreaId, setDragOverAreaId] = useState('') + const addDocumentTextInput = useRef(null) const addGroupTextInput = useRef(null) const editAreaNameTextInput = useRef(null) @@ -76,6 +78,7 @@ function Sidebar() { setSelectedDocumentId, currentSession, requestUpdateDocument, + requestChangeAreaOrder, } = useProject() const navigation = getNavigationProps(documents, groups) @@ -117,15 +120,43 @@ function Sidebar() { } const onAreaDoubleClick = (areaId: string) => { - const documentIdOfArea = getDocumentIdFromAreaId(areaId) + setSelectedDocumentId(getDocumentIdFromAreaId(areaId) || '') setIsEditAreaNameInputShowing(true) - console.log('double click') } const onAreaInputBlur = () => { 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) => { setSelectedDocumentId(itemId) setSelectedGroupId(getGroupIdFromDocumentId(itemId)) @@ -415,13 +446,18 @@ function Sidebar() { role='button' onClick={() => onAreaClick(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', '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', - 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}`} } diff --git a/frontend/context/Project/makeDefaultProject.ts b/frontend/context/Project/makeDefaultProject.ts index 06e433f..fe1b198 100644 --- a/frontend/context/Project/makeDefaultProject.ts +++ b/frontend/context/Project/makeDefaultProject.ts @@ -24,6 +24,7 @@ const makeDefaultProject = (): ProjectContextType => ({ requestUpdateCurrentUser: (updatedUserProps: UserProps) => Promise.resolve(new ipc.User()), requestChooseUserAvatar: () => Promise.resolve(''), requestUpdateDocument: ({}) => Promise.resolve(new ipc.Document), + requestChangeAreaOrder: (areaId: string, newOrder: number) => Promise.resolve(new ipc.Document()), }) export default makeDefaultProject diff --git a/frontend/context/Project/provider.tsx b/frontend/context/Project/provider.tsx index a1b860c..9066812 100644 --- a/frontend/context/Project/provider.tsx +++ b/frontend/context/Project/provider.tsx @@ -8,6 +8,7 @@ import { RequestUpdateArea, RequestUpdateCurrentUser, RequestUpdateDocumentUserMarkdown, RequestChooseUserAvatar, RequestUpdateDocument, + RequestChangeAreaOrder, } from '../../wailsjs/wailsjs/go/ipc/Channel' import { ipc } from '../../wailsjs/wailsjs/go/models' import { AddAreaProps, AreaProps, ProjectContextType, ProjectProps, UpdateDocumentRequest, UserProps } from './types' @@ -29,6 +30,7 @@ export function ProjectProvider({ children, projectProps }: Props) { const updateDocuments = async () => { GetDocuments().then(response => { + console.log(response) if (response.documents.length) setDocuments(response.documents) if (response.groups.length) setGroups(response.groups) Promise.resolve(response) @@ -124,12 +126,18 @@ export function ProjectProvider({ children, projectProps }: Props) { } const requestUpdateDocument = async (docuemntProps: UpdateDocumentRequest) => { - console.log('request: ', docuemntProps) const response = await RequestUpdateDocument(new ipc.Document(docuemntProps)) await updateDocuments() return response } + const requestChangeAreaOrder = async (areaId: string, newOrder: number) => { + console.log('requestChangeAreaOrder') + const response = await RequestChangeAreaOrder(areaId, newOrder) + await updateDocuments() + return response + } + useEffect(() => { if (!documents.length && !groups.length) updateDocuments() }, [documents.length, groups.length]) @@ -157,6 +165,7 @@ export function ProjectProvider({ children, projectProps }: Props) { requestUpdateCurrentUser, requestChooseUserAvatar, requestUpdateDocument, + requestChangeAreaOrder, } return diff --git a/frontend/context/Project/types.ts b/frontend/context/Project/types.ts index 27fe656..cb0c60d 100644 --- a/frontend/context/Project/types.ts +++ b/frontend/context/Project/types.ts @@ -56,4 +56,5 @@ export type ProjectContextType = { requestUpdateCurrentUser: (updatedUserProps: UserProps) => Promise requestChooseUserAvatar: () => Promise requestUpdateDocument: (request: UpdateDocumentRequest) => Promise + requestChangeAreaOrder: (areaId: string, newOrder: number) => Promise } & ProjectProps \ No newline at end of file diff --git a/frontend/wailsjs/wailsjs/go/ipc/Channel.d.ts b/frontend/wailsjs/wailsjs/go/ipc/Channel.d.ts index a3cc3e8..4f0f41e 100755 --- a/frontend/wailsjs/wailsjs/go/ipc/Channel.d.ts +++ b/frontend/wailsjs/wailsjs/go/ipc/Channel.d.ts @@ -26,6 +26,8 @@ export function RequestAddDocumentGroup(arg1:string):Promise; export function RequestAddProcessedArea(arg1:ipc.ProcessedArea):Promise; +export function RequestChangeAreaOrder(arg1:string,arg2:number):Promise; + export function RequestChooseUserAvatar():Promise; export function RequestUpdateArea(arg1:ipc.Area):Promise; diff --git a/frontend/wailsjs/wailsjs/go/ipc/Channel.js b/frontend/wailsjs/wailsjs/go/ipc/Channel.js index 3bf7230..43a9d7d 100755 --- a/frontend/wailsjs/wailsjs/go/ipc/Channel.js +++ b/frontend/wailsjs/wailsjs/go/ipc/Channel.js @@ -50,6 +50,10 @@ export function 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() { return window['go']['ipc']['Channel']['RequestChooseUserAvatar'](); } diff --git a/frontend/wailsjs/wailsjs/go/models.ts b/frontend/wailsjs/wailsjs/go/models.ts index 3199f2e..275fd44 100755 --- a/frontend/wailsjs/wailsjs/go/models.ts +++ b/frontend/wailsjs/wailsjs/go/models.ts @@ -24,6 +24,7 @@ export namespace ipc { endX: number; endY: number; language: Language; + order: number; static createFrom(source: any = {}) { return new Area(source); @@ -38,6 +39,7 @@ export namespace ipc { this.endX = source["endX"]; this.endY = source["endY"]; this.language = this.convertValues(source["language"], Language); + this.order = source["order"]; } convertValues(a: any, classs: any, asMap: boolean = false): any { @@ -338,6 +340,7 @@ export namespace ipc { id: string; documentId: string; fullText: string; + order: number; lines: ProcessedLine[]; static createFrom(source: any = {}) { @@ -349,6 +352,7 @@ export namespace ipc { this.id = source["id"]; this.documentId = source["documentId"]; this.fullText = source["fullText"]; + this.order = source["order"]; this.lines = this.convertValues(source["lines"], ProcessedLine); } diff --git a/ipc/Documents.go b/ipc/Documents.go index 642f857..e151f71 100644 --- a/ipc/Documents.go +++ b/ipc/Documents.go @@ -1,7 +1,7 @@ package ipc import ( - "fmt" + "sort" app "textualize/core/App" document "textualize/core/Document" session "textualize/core/Session" @@ -27,6 +27,7 @@ func (c *Channel) GetDocumentById(id string) Document { StartY: a.StartY, EndX: a.EndX, EndY: a.EndY, + Order: a.Order, Language: Language(a.Language), }) } @@ -60,10 +61,19 @@ func (c *Channel) GetDocuments() GetDocumentsResponse { StartY: a.StartY, EndX: a.EndX, EndY: a.EndY, + Order: a.Order, 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{ Id: d.Id, GroupId: d.GroupId, @@ -193,6 +203,11 @@ func (c *Channel) RequestAddArea(documentId string, area Area) Area { id = area.Id } + order := area.Order + if order < 1 { + order = len(foundDocument.Areas) + } + newArea := document.Area{ Id: id, Name: area.Name, @@ -200,6 +215,7 @@ func (c *Channel) RequestAddArea(documentId string, area Area) Area { EndX: area.EndX, StartY: area.StartY, EndY: area.EndY, + Order: order, Language: app.Language(area.Language), } foundDocument.AddArea(newArea) @@ -227,6 +243,9 @@ func (c *Channel) RequestUpdateArea(updatedArea Area) Area { if updatedArea.Name != "" { areaToUpdate.Name = updatedArea.Name } + if updatedArea.Order != areaToUpdate.Order { + areaToUpdate.Order = updatedArea.Order + } return Area{ Id: areaToUpdate.Id, @@ -235,6 +254,7 @@ func (c *Channel) RequestUpdateArea(updatedArea Area) Area { StartY: areaToUpdate.StartY, EndX: areaToUpdate.EndX, EndY: areaToUpdate.EndY, + Order: areaToUpdate.Order, Language: Language(areaToUpdate.Language), } } @@ -262,8 +282,41 @@ func (c *Channel) RequestUpdateDocument(updatedDocument Document) Document { documentToUpdate.DefaultLanguage = app.Language(updatedDocument.DefaultLanguage) } - fmt.Println("updated doc") - fmt.Println(document.GetDocumentCollection().GetDocumentById(updatedDocument.Id)) - 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) +} diff --git a/ipc/JsonEntities.go b/ipc/JsonEntities.go index ab6dc10..eab8413 100644 --- a/ipc/JsonEntities.go +++ b/ipc/JsonEntities.go @@ -36,6 +36,7 @@ type Area struct { EndX int `json:"endX"` EndY int `json:"endY"` Language Language `json:"language"` + Order int `json:"order"` } type ProcessedBoundingBox struct { @@ -68,6 +69,7 @@ type ProcessedArea struct { Id string `json:"id"` DocumentId string `json:"documentId"` FullText string `json:"fullText"` + Order int `json:"order"` Lines []ProcessedLine `json:"lines"` } diff --git a/ipc/ProcessedDocument.go b/ipc/ProcessedDocument.go index dbabc51..bd00e2e 100644 --- a/ipc/ProcessedDocument.go +++ b/ipc/ProcessedDocument.go @@ -1,6 +1,7 @@ package ipc import ( + "sort" document "textualize/core/Document" ) @@ -61,6 +62,7 @@ func serializeProcessedArea(area document.ProcessedArea) ProcessedArea { Id: area.Id, DocumentId: area.DocumentId, FullText: area.FullText, + Order: area.Order, Lines: lines, } } @@ -74,6 +76,10 @@ func (c *Channel) GetProcessedAreasByDocumentId(id string) []ProcessedArea { response = append(response, serializeProcessedArea(*a)) } + sort.Slice(response, func(i, j int) bool { + return response[i].Order < response[j].Order + }) + return response } @@ -141,7 +147,9 @@ func deserializeProcessedArea(area ProcessedArea) document.ProcessedArea { func (c *Channel) RequestAddProcessedArea(area ProcessedArea) ProcessedArea { var currentAreaIds []string - for _, a := range document.GetProcessedAreaCollection().Areas { + processedAreasCollection := document.GetProcessedAreaCollection() + + for _, a := range processedAreasCollection.Areas { currentAreaIds = append(currentAreaIds, a.Id) } @@ -153,7 +161,10 @@ func (c *Channel) RequestAddProcessedArea(area ProcessedArea) ProcessedArea { } 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 }