diff --git a/build/bin/textualize.app/Contents/MacOS/Textualize b/build/bin/textualize.app/Contents/MacOS/Textualize new file mode 100755 index 0000000..34868eb Binary files /dev/null and b/build/bin/textualize.app/Contents/MacOS/Textualize differ diff --git a/core/Document/Document.go b/core/Document/Document.go index be21ea5..1d746f6 100644 --- a/core/Document/Document.go +++ b/core/Document/Document.go @@ -21,3 +21,14 @@ type Area struct { func (e *Entity) AddArea(a Area) { e.Areas = append(e.Areas, a) } + +func (e *Entity) GetAreaById(areaId string) *Area { + var foundArea *Area + + for index, a := range e.Areas { + if a.Id == areaId { + foundArea = &e.Areas[index] + } + } + return foundArea +} diff --git a/core/Document/DocumentCollection.go b/core/Document/DocumentCollection.go index 5d7af9d..4419c72 100644 --- a/core/Document/DocumentCollection.go +++ b/core/Document/DocumentCollection.go @@ -31,3 +31,17 @@ func (collection *DocumentCollection) GetDocumentById(id string) *Entity { return foundDocument } + +func (collection *DocumentCollection) GetDocumentByAreaId(areaId string) *Entity { + var foundDocument *Entity + + for dIndex, d := range collection.Documents { + for _, a := range d.Areas { + if a.Id == areaId { + foundDocument = &collection.Documents[dIndex] + } + } + } + + return foundDocument +} diff --git a/frontend/components/workspace/Sidebar.tsx b/frontend/components/workspace/Sidebar.tsx index b90630c..8cf480a 100644 --- a/frontend/components/workspace/Sidebar.tsx +++ b/frontend/components/workspace/Sidebar.tsx @@ -5,35 +5,47 @@ import { PlusIcon, XMarkIcon } from '@heroicons/react/20/solid' import { ipc } from '../../wailsjs/wailsjs/go/models' import { useProject } from '../../context/Project/provider' -type NavigationItem = { +type GroupNavigationItem = { id: string, name: string, - children: { id: string, name: string }[] + documents: { + id: string, + name: string, + areas: { id: string, name: string }[] + }[] } -const getNavigationProps = (documents: ipc.Document[], groups: ipc.Group[]): NavigationItem[] => { +const getNavigationProps = (documents: ipc.Document[], groups: ipc.Group[]): GroupNavigationItem[] => { const groupsWithDocuments = groups.map(g => { const childrenDocuments = documents .filter(d => d.groupId === g.id) - .map(d => ({ id: d.id, name: d.name })) + .map(d => ({ + id: d.id, + name: d.name, + areas: d.areas.map(a => ({ id: a.id, name: a.name })) + })) return { id: g.id, name: g.name, - children: childrenDocuments + documents: childrenDocuments } }) const documentsWithoutGroup = documents .filter(d => !d.groupId || d.groupId === 'Uncategorized') - .map(d => ({ id: d.id, name: d.name })) + .map(d => ({ + id: d.id, + name: d.name, + areas: d.areas.map(a => ({ id: a.id, name: a.name })) + })) return [ ...groupsWithDocuments, { id: 'Uncategorized', name: 'Uncategorized', - children: documentsWithoutGroup + documents: documentsWithoutGroup } ] } @@ -44,29 +56,48 @@ function classNames(...classes: any[]) { function Sidebar() { const [selectedGroupId, setSelectedGroupId] = useState('') + const [selectedAreaId, setSelectedAreaId] = useState('') const [isAddNewDocumentInputShowing, setIsAddNewDocumentInputShowing] = useState(false) const [isAddNewGroupInputShowing, setIsAddNewGroupInputShowing] = useState(false) + const [isEditAreaNameInputShowing, setIsEditAreaNameInputShowing] = useState(false) const addDocumentTextInput = useRef(null) const addGroupTextInput = useRef(null) + const editAreaNameTextInput = useRef(null) const { documents, groups, + getAreaById, + requestUpdateArea, requestAddDocument, requestAddDocumentGroup, selectedDocumentId, - setSelectedDocumentId + setSelectedDocumentId, } = useProject() const navigation = getNavigationProps(documents, groups) - const getParentGroupIdFromItemId = (itemId: string) => { - let parentGroupId = '' - navigation.forEach(n => { - const foundItem = n.children.find(c => c.id === itemId) - if (foundItem) parentGroupId = n.id + const getGroupIdFromDocumentId = (itemId: string) => { + let groupId = '' + navigation.forEach(g => { + const foundDocument = g.documents.find(d => d.id === itemId) + if (foundDocument) groupId = g.id }) - return parentGroupId + return groupId + } + + // const getGroupIdFromAreaId = (areaId: string) => { + // return navigation.find(g => g.documents.map(d => d.areas.map(a => a.id)).flat().includes(areaId))?.id + // } + + const getDocumentIdFromAreaId = (areaId: string) => { + let documentId = '' + navigation.map(g => g.documents).flat().forEach(d => { + const doesDocumentIncludeArea = d.areas.map(a => a.id).includes(areaId) + if (doesDocumentIncludeArea) documentId = d.id + }) + + return documentId } const onAddNewDocumentLineItemClickHandler = (groupId: string) => { @@ -80,9 +111,28 @@ function Sidebar() { setIsAddNewDocumentInputShowing(false) } - const onItemClickHandler = (itemId: string) => { + const onAreaClick = (areaId: string) => { + getDocumentIdFromAreaId(areaId) + setSelectedDocumentId(getDocumentIdFromAreaId(areaId) || '') + setSelectedAreaId(areaId) + console.log('single click') + } + + const onAreaDoubleclick = (areaId: string) => { + const documentIdOfArea = getDocumentIdFromAreaId(areaId) + setIsEditAreaNameInputShowing(true) + // const groupIdOfArea = getGroupIdFromAreaId(areaId) + console.log(documentIdOfArea, selectedDocumentId) + console.log('double click') + } + + const onAreaInputBlur = () => { + setIsEditAreaNameInputShowing(false) + } + + const onDocumentClickHandler = (itemId: string) => { setSelectedDocumentId(itemId) - setSelectedGroupId(getParentGroupIdFromItemId(itemId)) + setSelectedGroupId(getGroupIdFromDocumentId(itemId)) setIsAddNewDocumentInputShowing(false) setIsAddNewGroupInputShowing(false) } @@ -95,6 +145,20 @@ function Sidebar() { setIsAddNewDocumentInputShowing(false) } + const onConfirmAreaNameChangeHandler = async (areaDetails: { areaId: string, areaName: string }) => { + console.log(areaDetails) + const { areaId, areaName } = areaDetails + + const areaToUpdate = getAreaById(areaId) + if (areaToUpdate) { + areaToUpdate.name = areaName + requestUpdateArea(areaToUpdate) + .then(response => console.log(response)) + .catch(console.error) + } + setIsEditAreaNameInputShowing(false) + } + const onConfirmAddDocumentClickHandler = async (groupId: string) => { const documentName = addDocumentTextInput.current?.value if (!documentName) return @@ -131,11 +195,11 @@ function Sidebar() { name="groupName" id="groupName" autoFocus - className="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="Add Group" onKeyDown={(event) => { onEnterHandler(event, - onConfirmAddGroupClickHandler) + onConfirmAddGroupClickHandler) }} ref={addGroupTextInput} /> @@ -178,12 +242,12 @@ function Sidebar() { type="text" name="documentName" id="documentName" - className="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="Add Document" autoFocus onKeyDown={(event) => { onEnterHandler(event, - () => onConfirmAddDocumentClickHandler(groupId)) + () => onConfirmAddDocumentClickHandler(groupId)) }} ref={addDocumentTextInput} /> @@ -222,35 +286,81 @@ function Sidebar() { {renderAddGroupInput()} - {navigation.map((item) => -
+ {navigation.map((group) => +
- {item.name} + {group.name}
)} diff --git a/frontend/context/Project/makeDefaultProject.ts b/frontend/context/Project/makeDefaultProject.ts index a6db341..d20b2d4 100644 --- a/frontend/context/Project/makeDefaultProject.ts +++ b/frontend/context/Project/makeDefaultProject.ts @@ -7,7 +7,9 @@ const makeDefaultProject = (): ProjectContextType => ({ groups: [] as ipc.Group[], selectedDocumentId: '', getSelectedDocument: () => new ipc.Document(), + getAreaById: (areaId) => undefined, requestAddArea: (documentId, area) => Promise.resolve(new ipc.Area()), + requestUpdateArea: (updatedArea) => Promise.resolve(new ipc.Area()), requestAddDocument: (groupId, documentName) => Promise.resolve(new ipc.Document()), requestAddDocumentGroup: (groupName: string) => Promise.resolve(new ipc.Group()), setSelectedDocumentId: (id) => {} diff --git a/frontend/context/Project/provider.tsx b/frontend/context/Project/provider.tsx index 13c9c5c..5940878 100644 --- a/frontend/context/Project/provider.tsx +++ b/frontend/context/Project/provider.tsx @@ -1,9 +1,9 @@ 'use client' import { createContext, ReactNode, useContext, useEffect, useState } from 'react' -import { GetDocuments, RequestAddArea, RequestAddDocument, RequestAddDocumentGroup } from '../../wailsjs/wailsjs/go/ipc/Channel' +import { GetDocuments, RequestAddArea, RequestAddDocument, RequestAddDocumentGroup, RequestUpdateArea } from '../../wailsjs/wailsjs/go/ipc/Channel' import { ipc } from '../../wailsjs/wailsjs/go/models' -import { AddAreaProps, ProjectContextType, ProjectProps } from './types' +import { AddAreaProps, AreaProps, ProjectContextType, ProjectProps } from './types' import makeDefaultProject from './makeDefaultProject' const ProjectContext = createContext(makeDefaultProject()) @@ -45,6 +45,17 @@ export function ProjectProvider({ children, projectProps }: Props) { return response } + const requestUpdateArea = async (updatedArea: AreaProps): Promise => { + const response = await RequestUpdateArea(new ipc.Area(updatedArea)) + + if (response.id) await updateDocuments() + return response + } + + const getAreaById = (areaId: string): ipc.Area | undefined => ( + documents.map(d => d.areas).flat().find(a => a.id ===areaId) + ) + const getSelectedDocument = () => documents.find(d => d.id === selectedDocumentId) useEffect(() => { @@ -56,9 +67,11 @@ export function ProjectProvider({ children, projectProps }: Props) { documents, groups, getSelectedDocument, + getAreaById, requestAddArea, requestAddDocument, requestAddDocumentGroup, + requestUpdateArea, selectedDocumentId, setSelectedDocumentId, } diff --git a/frontend/context/Project/types.ts b/frontend/context/Project/types.ts index 8414d9d..408cfbc 100644 --- a/frontend/context/Project/types.ts +++ b/frontend/context/Project/types.ts @@ -14,9 +14,13 @@ export type AddAreaProps = { endY: number } +export type AreaProps = { id: string } & AddAreaProps + export type ProjectContextType = { getSelectedDocument: () => ipc.Document | undefined + getAreaById: (areaId: string) => ipc.Area | undefined requestAddArea: (documentId: string, area: AddAreaProps) => Promise + requestUpdateArea: (area: AreaProps) => Promise requestAddDocument: (groupId: string, documentName: string) => Promise requestAddDocumentGroup: (groupName: string) => Promise selectedDocumentId: string diff --git a/frontend/wailsjs/wailsjs/go/ipc/Channel.d.ts b/frontend/wailsjs/wailsjs/go/ipc/Channel.d.ts index 78a7dd9..0e42200 100755 --- a/frontend/wailsjs/wailsjs/go/ipc/Channel.d.ts +++ b/frontend/wailsjs/wailsjs/go/ipc/Channel.d.ts @@ -11,3 +11,5 @@ export function RequestAddArea(arg1:string,arg2:ipc.Area):Promise; export function RequestAddDocument(arg1:string,arg2:string):Promise; export function RequestAddDocumentGroup(arg1:string):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 ef00a42..6b21989 100755 --- a/frontend/wailsjs/wailsjs/go/ipc/Channel.js +++ b/frontend/wailsjs/wailsjs/go/ipc/Channel.js @@ -21,3 +21,7 @@ export function RequestAddDocument(arg1, arg2) { export function RequestAddDocumentGroup(arg1) { return window['go']['ipc']['Channel']['RequestAddDocumentGroup'](arg1); } + +export function RequestUpdateArea(arg1) { + return window['go']['ipc']['Channel']['RequestUpdateArea'](arg1); +} diff --git a/ipc/Documents.go b/ipc/Documents.go index 384d472..25db65d 100644 --- a/ipc/Documents.go +++ b/ipc/Documents.go @@ -161,3 +161,31 @@ func (c *Channel) RequestAddArea(documentId string, area Area) Area { foundDocument.AddArea(newArea) return Area(newArea) } + +func (c *Channel) RequestUpdateArea(updatedArea Area) Area { + documentOfArea := document.GetDocumentCollection().GetDocumentByAreaId(updatedArea.Id) + + if documentOfArea.Id == "" { + return Area{} + } + + areaToUpdate := documentOfArea.GetAreaById((updatedArea.Id)) + + if areaToUpdate.Id == "" { + return Area{} + } + + // TODO: add more prop changes when needed + if updatedArea.Name != "" { + areaToUpdate.Name = updatedArea.Name + } + + return Area{ + Id: updatedArea.Id, + Name: updatedArea.Name, + StartX: updatedArea.StartX, + StartY: updatedArea.StartY, + EndX: updatedArea.EndX, + EndY: updatedArea.EndY, + } +}