feat: edit area names
This commit is contained in:
parent
fe25bc1c2e
commit
f01cd74a88
BIN
build/bin/textualize.app/Contents/MacOS/Textualize
Executable file
BIN
build/bin/textualize.app/Contents/MacOS/Textualize
Executable file
Binary file not shown.
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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<HTMLInputElement>(null)
|
||||
const addGroupTextInput = useRef<HTMLInputElement>(null)
|
||||
const editAreaNameTextInput = useRef<HTMLInputElement>(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,7 +195,7 @@ 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,
|
||||
@ -178,7 +242,7 @@ 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) => {
|
||||
@ -222,35 +286,81 @@ function Sidebar() {
|
||||
|
||||
{renderAddGroupInput()}
|
||||
|
||||
{navigation.map((item) =>
|
||||
<details key={item.name} open={item.id === selectedGroupId}>
|
||||
{navigation.map((group) =>
|
||||
<details key={group.name} open={group.id === selectedGroupId}>
|
||||
<summary className={classNames(
|
||||
item.id === selectedGroupId
|
||||
group.id === selectedGroupId
|
||||
? 'bg-gray-900 text-white'
|
||||
: 'text-gray-300 hover:bg-gray-700 hover:text-white',
|
||||
'group items-center px-2 py-2 text-base font-medium rounded-md'
|
||||
'group items-center px-2 py-2 text-base font-medium rounded-t-md'
|
||||
)}>
|
||||
<a role='button'>{item.name}</a>
|
||||
<a role='button'>{group.name}</a>
|
||||
</summary>
|
||||
<ul>
|
||||
{item.children.map(child => (
|
||||
<li key={child.id}>
|
||||
<a
|
||||
role='button'
|
||||
onClick={() => onItemClickHandler(child.id)}
|
||||
{group.documents.map((d, index) => (
|
||||
<li className='p-0 m-0' key={d.id}>
|
||||
<details>
|
||||
<summary
|
||||
onClick={() => onDocumentClickHandler(d.id)}
|
||||
className={classNames(
|
||||
child.id === selectedDocumentId
|
||||
d.id === selectedDocumentId
|
||||
? 'bg-gray-900 text-white'
|
||||
: 'text-gray-300 hover:bg-gray-700 hover:text-white',
|
||||
'group w-full flex items-center pr-2 py-2 text-left font-medium text-sm rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 p-2'
|
||||
'group items-center py-2 text-base font-medium rounded-b-md pl-6',
|
||||
index !== 0
|
||||
? 'rounded-t-md'
|
||||
: ''
|
||||
)}>
|
||||
<a
|
||||
role='button'
|
||||
className={classNames(
|
||||
d.id === selectedDocumentId
|
||||
? 'bg-gray-900 text-white'
|
||||
: 'text-gray-300 hover:bg-gray-700 hover:text-white',
|
||||
'text-left font-medium text-sm rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 '
|
||||
)}
|
||||
>
|
||||
{child.name}
|
||||
{d.name}
|
||||
</a>
|
||||
</summary>
|
||||
<ul>
|
||||
{d.areas.map((a, index) => (
|
||||
<li key={a.id}>
|
||||
{selectedAreaId === a.id && isEditAreaNameInputShowing
|
||||
? <input
|
||||
type="text"
|
||||
name="areaName"
|
||||
id="areaName"
|
||||
autoFocus
|
||||
className="h-8 text-white placeholder-gray-400 bg-gray-900 bg-opacity-5 block w-full rounded-none rounded-l-md border-late-700 focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
|
||||
placeholder={a.name || `Area ${index + 1}`}
|
||||
onBlur={onAreaInputBlur}
|
||||
onKeyDown={(event) => {
|
||||
onEnterHandler(event,
|
||||
() => onConfirmAreaNameChangeHandler({ areaId: a.id, areaName: event.currentTarget.value }))
|
||||
}}
|
||||
ref={editAreaNameTextInput}
|
||||
/>
|
||||
: <a
|
||||
role='button'
|
||||
onClick={() => onAreaClick(a.id)}
|
||||
onDoubleClick={() => onAreaDoubleclick(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'
|
||||
)}
|
||||
>
|
||||
{a.name || `Area ${index + 1}`}
|
||||
</a>
|
||||
}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</details>
|
||||
</li>
|
||||
))}
|
||||
|
||||
{renderAddNewDocument(item.id)}
|
||||
{renderAddNewDocument(group.id)}
|
||||
</ul>
|
||||
</details>
|
||||
)}
|
||||
|
||||
@ -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) => {}
|
||||
|
||||
@ -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<ProjectContextType>(makeDefaultProject())
|
||||
@ -45,6 +45,17 @@ export function ProjectProvider({ children, projectProps }: Props) {
|
||||
return response
|
||||
}
|
||||
|
||||
const requestUpdateArea = async (updatedArea: AreaProps): Promise<ipc.Area> => {
|
||||
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,
|
||||
}
|
||||
|
||||
@ -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<ipc.Area>
|
||||
requestUpdateArea: (area: AreaProps) => Promise<ipc.Area>
|
||||
requestAddDocument: (groupId: string, documentName: string) => Promise<ipc.Document>
|
||||
requestAddDocumentGroup: (groupName: string) => Promise<ipc.Group>
|
||||
selectedDocumentId: string
|
||||
|
||||
2
frontend/wailsjs/wailsjs/go/ipc/Channel.d.ts
vendored
2
frontend/wailsjs/wailsjs/go/ipc/Channel.d.ts
vendored
@ -11,3 +11,5 @@ export function RequestAddArea(arg1:string,arg2:ipc.Area):Promise<ipc.Area>;
|
||||
export function RequestAddDocument(arg1:string,arg2:string):Promise<ipc.Document>;
|
||||
|
||||
export function RequestAddDocumentGroup(arg1:string):Promise<ipc.Group>;
|
||||
|
||||
export function RequestUpdateArea(arg1:ipc.Area):Promise<ipc.Area>;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user