Refactor Stage Context to redux #7
@ -1,13 +1,14 @@
 | 
			
		||||
'use client'
 | 
			
		||||
 | 
			
		||||
import React, { useState } from 'react'
 | 
			
		||||
import { useSelector } from 'react-redux'
 | 
			
		||||
import Konva from 'konva'
 | 
			
		||||
import { Group, Rect } from 'react-konva'
 | 
			
		||||
import { KonvaEventObject } from 'konva/lib/Node'
 | 
			
		||||
import { entities } from '../../wailsjs/wailsjs/go/models'
 | 
			
		||||
import { useProject } from '../../context/Project/provider'
 | 
			
		||||
import AreaContextMenu from './AreaContextMenu'
 | 
			
		||||
import { useStage } from './context/provider'
 | 
			
		||||
import { RootState } from '../../redux/store'
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
  isActive: boolean,
 | 
			
		||||
@ -17,8 +18,8 @@ type Props = {
 | 
			
		||||
type coordinates = { x: number, y: number }
 | 
			
		||||
 | 
			
		||||
const Area = (props: Props) => {
 | 
			
		||||
  const { scale } = useSelector((state: RootState) => state.stage)
 | 
			
		||||
  const { selectedAreaId, setSelectedAreaId } = useProject()
 | 
			
		||||
  const { scale } = useStage()
 | 
			
		||||
  const shapeRef = React.useRef<Konva.Rect>(null)
 | 
			
		||||
  const [isAreaContextMenuOpen, setIsAreaContextMenuOpen] = useState(false)
 | 
			
		||||
  const [areaContextMenuPosition, setAreaContextMenuPosition] = useState<coordinates>()
 | 
			
		||||
 | 
			
		||||
@ -1,19 +1,20 @@
 | 
			
		||||
'use client'
 | 
			
		||||
 | 
			
		||||
import React, { useEffect, useState } from 'react'
 | 
			
		||||
import { useSelector } from 'react-redux'
 | 
			
		||||
import { Group } from 'react-konva'
 | 
			
		||||
import { useProject } from '../../context/Project/provider'
 | 
			
		||||
import { entities } from '../../wailsjs/wailsjs/go/models'
 | 
			
		||||
import Area from './Area'
 | 
			
		||||
import ProcessedWord from './ProcessedWord'
 | 
			
		||||
import EditingWord from './EditingWord'
 | 
			
		||||
import { useStage } from './context/provider'
 | 
			
		||||
import { RootState } from '../../redux/store'
 | 
			
		||||
 | 
			
		||||
type Props = { scale: number }
 | 
			
		||||
 | 
			
		||||
const Areas = ({ scale }: Props) => {
 | 
			
		||||
  const { areProcessedWordsVisible } = useSelector((state: RootState) => state.stage)
 | 
			
		||||
  const { getSelectedDocument, selectedAreaId, getProcessedAreaById } = useProject()
 | 
			
		||||
  const { isProcessedWordsVisible } = useStage()
 | 
			
		||||
  const areas = getSelectedDocument()?.areas || []
 | 
			
		||||
  const [editingWord, setEditingWord] = useState<entities.ProcessedWord | null>(null)
 | 
			
		||||
  const [selectedProcessedArea, setSelectedProcessedArea] = useState<entities.ProcessedArea | null>(null)
 | 
			
		||||
@ -59,8 +60,8 @@ const Areas = ({ scale }: Props) => {
 | 
			
		||||
 | 
			
		||||
  return <Group>
 | 
			
		||||
    {renderAreas(areas)}
 | 
			
		||||
    {isProcessedWordsVisible ? renderProcessedWords() : <></>}
 | 
			
		||||
    {isProcessedWordsVisible ? renderEditingWord() : <></>}
 | 
			
		||||
    {areProcessedWordsVisible ? renderProcessedWords() : <></>}
 | 
			
		||||
    {areProcessedWordsVisible ? renderEditingWord() : <></>}
 | 
			
		||||
  </Group>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,7 @@
 | 
			
		||||
'use client'
 | 
			
		||||
 | 
			
		||||
import React, { useRef, useState } from 'react'
 | 
			
		||||
import { useDispatch, useSelector } from 'react-redux'
 | 
			
		||||
import { Stage, Layer, Image, } from 'react-konva'
 | 
			
		||||
import { KonvaEventObject } from 'konva/lib/Node'
 | 
			
		||||
import Areas from './Areas'
 | 
			
		||||
@ -9,16 +10,25 @@ import useImage from 'use-image'
 | 
			
		||||
import { RectangleCoordinates } from './types'
 | 
			
		||||
import DrawingArea from './DrawingArea'
 | 
			
		||||
import getNormalizedRectToBounds from '../../utils/getNormalizedRectToBounds'
 | 
			
		||||
import { useStage } from './context/provider'
 | 
			
		||||
import ContextConnections from './ContextConnections'
 | 
			
		||||
import processImageRect from '../../useCases/processImageRect'
 | 
			
		||||
import { RootState } from '../../redux/store'
 | 
			
		||||
import { maxScale, scaleStep, setIsDrawingArea, setScale, setStartingContextConnectionPoint } from '../../redux/features/stage/stageSlice'
 | 
			
		||||
 | 
			
		||||
let downClickX: number
 | 
			
		||||
let downClickY: number
 | 
			
		||||
 | 
			
		||||
const CanvasStage = () => {
 | 
			
		||||
  const dispatch = useDispatch()
 | 
			
		||||
  const {
 | 
			
		||||
    scale, size,
 | 
			
		||||
    isDrawingArea,
 | 
			
		||||
    areAreasVisible,
 | 
			
		||||
    areLinkAreaContextsVisible,
 | 
			
		||||
    startingContextConnectionPoint
 | 
			
		||||
  } = useSelector((state: RootState) => state.stage)
 | 
			
		||||
 | 
			
		||||
  const { getSelectedDocument, updateDocuments, setSelectedAreaId } = useProject()
 | 
			
		||||
  const { scale, scaleStep, maxScale, size, setScale, isAreasVisible, isLinkAreaContextsVisible, isDrawingArea, setIsDrawingArea, startingContextConnection, setStartingContextConnection } = useStage()
 | 
			
		||||
  const [documentImage] = useImage(getSelectedDocument()?.path || '')
 | 
			
		||||
  const documentRef = useRef(null)
 | 
			
		||||
  const [drawingAreaRect, setDrawingAreaRect] = useState<RectangleCoordinates | null>(null)
 | 
			
		||||
@ -27,13 +37,13 @@ const CanvasStage = () => {
 | 
			
		||||
  const documentHeight = documentImage?.naturalHeight || 0
 | 
			
		||||
 | 
			
		||||
  const handleMouseDown = (e: KonvaEventObject<MouseEvent>) => {
 | 
			
		||||
    if (startingContextConnection) return setStartingContextConnection(null) // TODO: handle if clicking o connect
 | 
			
		||||
    if (startingContextConnectionPoint) return dispatch(setStartingContextConnectionPoint(null)) // TODO: handle if clicking o connect
 | 
			
		||||
    if (!e.evt.shiftKey) return e.currentTarget.startDrag()
 | 
			
		||||
 | 
			
		||||
    const position = e.currentTarget.getRelativePointerPosition()
 | 
			
		||||
    downClickX = position.x
 | 
			
		||||
    downClickY = position.y
 | 
			
		||||
    setIsDrawingArea(true)
 | 
			
		||||
    dispatch(setIsDrawingArea(true))
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const handleMouseMove = (e: KonvaEventObject<MouseEvent>) => {
 | 
			
		||||
@ -49,7 +59,7 @@ const CanvasStage = () => {
 | 
			
		||||
  const handleMouseUp = (e: KonvaEventObject<MouseEvent>) => {
 | 
			
		||||
    const stage = e.currentTarget
 | 
			
		||||
    if (stage.isDragging()) stage.stopDrag()
 | 
			
		||||
    else if (isDrawingArea) setIsDrawingArea(false)
 | 
			
		||||
    else if (isDrawingArea) dispatch(setIsDrawingArea(false))
 | 
			
		||||
 | 
			
		||||
    if (!drawingAreaRect) return
 | 
			
		||||
 | 
			
		||||
@ -70,8 +80,8 @@ const CanvasStage = () => {
 | 
			
		||||
    const wheelDelta = e.evt.deltaY
 | 
			
		||||
 | 
			
		||||
    const shouldAttemptScaleUp = (wheelDelta < 0) && scale < maxScale
 | 
			
		||||
    if (shouldAttemptScaleUp) setScale(scale + scaleStep)
 | 
			
		||||
    else if (scale > (scaleStep * 2)) setScale(scale - scaleStep)
 | 
			
		||||
    if (shouldAttemptScaleUp) dispatch(setScale(scale + scaleStep))
 | 
			
		||||
    else if (scale > (scaleStep * 2)) dispatch(setScale(scale - scaleStep))
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return <Stage width={size.width} height={size.height} scale={{ x: scale, y: scale }} onMouseDown={handleMouseDown} onMouseMove={handleMouseMove} onMouseUp={handleMouseUp} onWheel={handleWheel}>
 | 
			
		||||
@ -90,13 +100,13 @@ const CanvasStage = () => {
 | 
			
		||||
      />
 | 
			
		||||
      {(isDrawingArea && drawingAreaRect) ? <DrawingArea rect={drawingAreaRect} /> : <></>}
 | 
			
		||||
    </Layer>
 | 
			
		||||
    {isAreasVisible
 | 
			
		||||
    {areAreasVisible
 | 
			
		||||
      ? <Layer id='areaLayer'>
 | 
			
		||||
        <Areas scale={scale} />
 | 
			
		||||
      </Layer>
 | 
			
		||||
      : <></>
 | 
			
		||||
    }
 | 
			
		||||
    {isAreasVisible && isLinkAreaContextsVisible
 | 
			
		||||
    {areAreasVisible && areLinkAreaContextsVisible
 | 
			
		||||
      ? <Layer id='contextConnections'>
 | 
			
		||||
        <ContextConnections />
 | 
			
		||||
      </Layer>
 | 
			
		||||
 | 
			
		||||
@ -1,17 +1,17 @@
 | 
			
		||||
'use client'
 | 
			
		||||
 | 
			
		||||
import React from 'react'
 | 
			
		||||
import { useSelector } from 'react-redux'
 | 
			
		||||
import { Group, Line } from 'react-konva'
 | 
			
		||||
import { useProject } from '../../../context/Project/provider'
 | 
			
		||||
import { useStage } from '../context/provider'
 | 
			
		||||
import { RootState } from '../../../redux/store'
 | 
			
		||||
 | 
			
		||||
const ConnectionLines = () => {
 | 
			
		||||
  const { scale } = useStage()
 | 
			
		||||
  const { scale } = useSelector((state: RootState) => state.stage)
 | 
			
		||||
  const { getSelectedDocument, contextGroups } = useProject()
 | 
			
		||||
  const areas = getSelectedDocument()?.areas || []
 | 
			
		||||
 | 
			
		||||
  const renderLines = () => {
 | 
			
		||||
    console.log('contextGroups', contextGroups)
 | 
			
		||||
    if (!contextGroups?.length) return <></>
 | 
			
		||||
 | 
			
		||||
    const linesAlreadyRendered = new Set<string>()
 | 
			
		||||
 | 
			
		||||
@ -1,14 +1,18 @@
 | 
			
		||||
'use client'
 | 
			
		||||
 | 
			
		||||
import { Circle, Group } from 'react-konva'
 | 
			
		||||
import { useStage } from '../context/provider'
 | 
			
		||||
import { useDispatch, useSelector } from 'react-redux'
 | 
			
		||||
import { entities } from '../../../wailsjs/wailsjs/go/models'
 | 
			
		||||
import { KonvaEventObject } from 'konva/lib/Node'
 | 
			
		||||
import { useProject } from '../../../context/Project/provider'
 | 
			
		||||
import { RootState } from '../../../redux/store'
 | 
			
		||||
import { setStartingContextConnectionPoint } from '../../../redux/features/stage/stageSlice'
 | 
			
		||||
 | 
			
		||||
type Props = { areas: entities.Area[] }
 | 
			
		||||
const ConnectionPoints = (props: Props) => {
 | 
			
		||||
  const { isLinkAreaContextsVisible, scale, startingContextConnection, setStartingContextConnection } = useStage()
 | 
			
		||||
  const dispatch = useDispatch()
 | 
			
		||||
  const { scale, areLinkAreaContextsVisible, startingContextConnectionPoint } = useSelector((state: RootState) => state.stage)
 | 
			
		||||
 | 
			
		||||
  const { requestConnectProcessedAreas } = useProject()
 | 
			
		||||
 | 
			
		||||
  const handleContextAreaMouseDown = async (e: KonvaEventObject<MouseEvent>) => {
 | 
			
		||||
@ -18,15 +22,15 @@ const ConnectionPoints = (props: Props) => {
 | 
			
		||||
      areaId: e.currentTarget.attrs.id
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!startingContextConnection) return setStartingContextConnection(clickedConnectionPoint)
 | 
			
		||||
    if (!startingContextConnectionPoint) return dispatch(setStartingContextConnectionPoint(clickedConnectionPoint))
 | 
			
		||||
 | 
			
		||||
    if (clickedConnectionPoint.isHead === startingContextConnection.isHead
 | 
			
		||||
      || clickedConnectionPoint.areaId === startingContextConnection.areaId)
 | 
			
		||||
      return setStartingContextConnection(null)
 | 
			
		||||
    if (clickedConnectionPoint.isHead === startingContextConnectionPoint.isHead
 | 
			
		||||
      || clickedConnectionPoint.areaId === startingContextConnectionPoint.areaId)
 | 
			
		||||
      return dispatch(setStartingContextConnectionPoint(null))
 | 
			
		||||
 | 
			
		||||
    const headId = startingContextConnection.isHead ? startingContextConnection.areaId : clickedConnectionPoint.areaId
 | 
			
		||||
    const tailId = !startingContextConnection.isHead ? startingContextConnection.areaId : clickedConnectionPoint.areaId
 | 
			
		||||
    setStartingContextConnection(null)
 | 
			
		||||
    const headId = startingContextConnectionPoint.isHead ? startingContextConnectionPoint.areaId : clickedConnectionPoint.areaId
 | 
			
		||||
    const tailId = !startingContextConnectionPoint.isHead ? startingContextConnectionPoint.areaId : clickedConnectionPoint.areaId
 | 
			
		||||
    dispatch(setStartingContextConnectionPoint(null))
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      await requestConnectProcessedAreas(headId, tailId)
 | 
			
		||||
@ -36,7 +40,7 @@ const ConnectionPoints = (props: Props) => {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const renderConnectingPointsForArea = (a: entities.Area) => {
 | 
			
		||||
    if (!isLinkAreaContextsVisible) return <></>
 | 
			
		||||
    if (!areLinkAreaContextsVisible) return <></>
 | 
			
		||||
 | 
			
		||||
    const headConnector = <Circle
 | 
			
		||||
      key={`head-${a.id}`}
 | 
			
		||||
@ -68,12 +72,12 @@ const ConnectionPoints = (props: Props) => {
 | 
			
		||||
 | 
			
		||||
    let connectorsToRender = []
 | 
			
		||||
 | 
			
		||||
    if (!startingContextConnection) connectorsToRender = [headConnector, tailConnector]
 | 
			
		||||
    else if (startingContextConnection.isHead) connectorsToRender = [tailConnector]
 | 
			
		||||
    if (!startingContextConnectionPoint) connectorsToRender = [headConnector, tailConnector]
 | 
			
		||||
    else if (startingContextConnectionPoint.isHead) connectorsToRender = [tailConnector]
 | 
			
		||||
    else connectorsToRender = [headConnector]
 | 
			
		||||
 | 
			
		||||
    if (startingContextConnection?.areaId === a.id) {
 | 
			
		||||
      let y = (startingContextConnection.isHead ? a.startY : a.endY) * scale
 | 
			
		||||
    if (startingContextConnectionPoint?.areaId === a.id) {
 | 
			
		||||
      let y = (startingContextConnectionPoint.isHead ? a.startY : a.endY) * scale
 | 
			
		||||
      connectorsToRender.push(<Circle
 | 
			
		||||
        key={`active-${a.id}`}
 | 
			
		||||
        id={a.id}
 | 
			
		||||
@ -81,11 +85,11 @@ const ConnectionPoints = (props: Props) => {
 | 
			
		||||
        x={((a.startX + a.endX) * scale) / 2}
 | 
			
		||||
        y={y}
 | 
			
		||||
        strokeEnabled={false}
 | 
			
		||||
        fill={startingContextConnection.isHead ? '#dc8dec' : '#1e1e1e'}
 | 
			
		||||
        fill={startingContextConnectionPoint.isHead ? '#dc8dec' : '#1e1e1e'}
 | 
			
		||||
        strokeScaleEnabled={false}
 | 
			
		||||
        shadowForStrokeEnabled={false}
 | 
			
		||||
        isHead={startingContextConnection.isHead}
 | 
			
		||||
        onMouseDown={() => setStartingContextConnection(null)}
 | 
			
		||||
        isHead={startingContextConnectionPoint.isHead}
 | 
			
		||||
        onMouseDown={() => dispatch(setStartingContextConnectionPoint(null))}
 | 
			
		||||
      />)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,23 +1,24 @@
 | 
			
		||||
'use client'
 | 
			
		||||
 | 
			
		||||
import React from 'react'
 | 
			
		||||
import { useSelector } from 'react-redux'
 | 
			
		||||
import { Line } from 'react-konva'
 | 
			
		||||
import { Coordinates } from '../types'
 | 
			
		||||
import { useStage } from '../context/provider'
 | 
			
		||||
import { useProject } from '../../../context/Project/provider'
 | 
			
		||||
import { RootState } from '../../../redux/store'
 | 
			
		||||
 | 
			
		||||
type CurrentDrawingConnectionProps = {
 | 
			
		||||
  endDrawingPosition: Coordinates | null
 | 
			
		||||
}
 | 
			
		||||
const CurrentDrawingConnection = (props: CurrentDrawingConnectionProps) => {
 | 
			
		||||
  const { scale, startingContextConnectionPoint } = useSelector((state: RootState) => state.stage)
 | 
			
		||||
  const { endDrawingPosition } = props 
 | 
			
		||||
  const { startingContextConnection, scale } = useStage()
 | 
			
		||||
  const { getSelectedDocument } = useProject()
 | 
			
		||||
  const areas = getSelectedDocument()?.areas || []
 | 
			
		||||
 | 
			
		||||
  if (!startingContextConnection || !endDrawingPosition) return <></>
 | 
			
		||||
  if (!startingContextConnectionPoint || !endDrawingPosition) return <></>
 | 
			
		||||
 | 
			
		||||
  const { areaId, isHead } = startingContextConnection
 | 
			
		||||
  const { areaId, isHead } = startingContextConnectionPoint
 | 
			
		||||
 | 
			
		||||
  const area = areas.find(a => a.id === areaId)
 | 
			
		||||
  if (!area) return <></>
 | 
			
		||||
 | 
			
		||||
@ -1,24 +1,26 @@
 | 
			
		||||
'use client'
 | 
			
		||||
 | 
			
		||||
import React, { useEffect, useState } from 'react'
 | 
			
		||||
import { useSelector } from 'react-redux'
 | 
			
		||||
import { Group } from 'react-konva'
 | 
			
		||||
import { useStage } from '../context/provider'
 | 
			
		||||
import { useProject } from '../../../context/Project/provider'
 | 
			
		||||
import Konva from 'konva'
 | 
			
		||||
import { Coordinates } from '../types'
 | 
			
		||||
import CurrentDrawingConnection from './CurrentDrawingConnection'
 | 
			
		||||
import ConnectionPoints from './ConnectionPoints'
 | 
			
		||||
import ConnectionLines from './ConnectionLines'
 | 
			
		||||
import { RootState } from '../../../redux/store'
 | 
			
		||||
 | 
			
		||||
const ContextConnections = () => {
 | 
			
		||||
  const { startingContextConnectionPoint, areLinkAreaContextsVisible } = useSelector((state: RootState) => state.stage)
 | 
			
		||||
 | 
			
		||||
  const { getSelectedDocument } = useProject()
 | 
			
		||||
  const { isLinkAreaContextsVisible, startingContextConnection, scale } = useStage()
 | 
			
		||||
  const areas = getSelectedDocument()?.areas || []
 | 
			
		||||
 | 
			
		||||
  const [endDrawingPosition, setEndDrawingPosition] = useState<Coordinates | null>(null)
 | 
			
		||||
 | 
			
		||||
  const handleMouseMove = (e: MouseEvent) => {
 | 
			
		||||
    if (!isLinkAreaContextsVisible || !startingContextConnection) return
 | 
			
		||||
    if (!areLinkAreaContextsVisible || !startingContextConnectionPoint) return
 | 
			
		||||
    setEndDrawingPosition(Konva.stages[0].getRelativePointerPosition())
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -28,10 +30,10 @@ const ContextConnections = () => {
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    if (!startingContextConnection) setEndDrawingPosition(null)
 | 
			
		||||
  }, [startingContextConnection])
 | 
			
		||||
    if (!startingContextConnectionPoint) setEndDrawingPosition(null)
 | 
			
		||||
  }, [startingContextConnectionPoint])
 | 
			
		||||
 | 
			
		||||
  if (!isLinkAreaContextsVisible) return <></>
 | 
			
		||||
  if (!areLinkAreaContextsVisible) return <></>
 | 
			
		||||
 | 
			
		||||
  return <Group>
 | 
			
		||||
    <ConnectionPoints areas={areas} />
 | 
			
		||||
 | 
			
		||||
@ -1,27 +1,29 @@
 | 
			
		||||
'use client'
 | 
			
		||||
 | 
			
		||||
import React, { useEffect, useState } from 'react'
 | 
			
		||||
import { useDispatch } from 'react-redux'
 | 
			
		||||
import { useDispatch, useSelector } from 'react-redux'
 | 
			
		||||
import { DocumentTextIcon, LanguageIcon, LinkIcon, MagnifyingGlassMinusIcon, MagnifyingGlassPlusIcon, SquaresPlusIcon } from '@heroicons/react/24/outline'
 | 
			
		||||
import { useProject } from '../../../context/Project/provider'
 | 
			
		||||
import { entities } from '../../../wailsjs/wailsjs/go/models'
 | 
			
		||||
import LanguageSelect from '../../utils/LanguageSelect'
 | 
			
		||||
import { useStage } from '../context/provider'
 | 
			
		||||
import ToolToggleButton from './ToolToggleButton'
 | 
			
		||||
import processImageArea from '../../../useCases/processImageArea'
 | 
			
		||||
import { pushNotification } from '../../../redux/features/notifications/notificationQueueSlice'
 | 
			
		||||
import { RootState } from '../../../redux/store'
 | 
			
		||||
import { maxScale, scaleStep, setAreAreasVisible, setAreLinkAreaContextsVisible, setAreProcessedWordsVisible, setAreTranslatedWordsVisible, setScale } from '../../../redux/features/stage/stageSlice'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const ToolingOverlay = () => {
 | 
			
		||||
  const dispatch = useDispatch()
 | 
			
		||||
  const { getSelectedDocument, selectedAreaId, requestUpdateArea, requestUpdateDocument, updateDocuments } = useProject()
 | 
			
		||||
  const {
 | 
			
		||||
    scale, scaleStep, maxScale, setScale,
 | 
			
		||||
    isLinkAreaContextsVisible, setIsLinkAreaContextsVisible,
 | 
			
		||||
    isAreasVisible, setIsAreasVisible,
 | 
			
		||||
    isProcessedWordsVisible, setIsProcessedWordsVisible,
 | 
			
		||||
    isTranslatedWordsVisible, setIsTranslatedWordsVisible,
 | 
			
		||||
  } = useStage()
 | 
			
		||||
    scale,
 | 
			
		||||
    areAreasVisible,
 | 
			
		||||
    areLinkAreaContextsVisible,
 | 
			
		||||
    areProcessedWordsVisible,
 | 
			
		||||
    areTranslatedWordsVisible,
 | 
			
		||||
  } = useSelector((state: RootState) => state.stage)
 | 
			
		||||
 | 
			
		||||
  const { getSelectedDocument, selectedAreaId, requestUpdateArea, requestUpdateDocument, updateDocuments } = useProject()
 | 
			
		||||
 | 
			
		||||
  const selectedDocument = getSelectedDocument()
 | 
			
		||||
  const [selectedArea, setSelectedArea] = useState<entities.Area | undefined>()
 | 
			
		||||
@ -95,7 +97,7 @@ const ToolingOverlay = () => {
 | 
			
		||||
        <input
 | 
			
		||||
          id="zoomRange" type="range" min={scaleStep} max={maxScale} step={scaleStep}
 | 
			
		||||
          value={scale} className="w-[calc(100%-50px)] h-2 bg-indigo-200 rounded-lg appearance-none cursor-pointer p-0"
 | 
			
		||||
          onChange={(e) => { setScale(e.currentTarget.valueAsNumber) }}
 | 
			
		||||
          onChange={(e) => { dispatch(setScale(e.currentTarget.valueAsNumber)) }}
 | 
			
		||||
        />
 | 
			
		||||
        <MagnifyingGlassPlusIcon className='w-4 h-4' />
 | 
			
		||||
      </div>
 | 
			
		||||
@ -103,16 +105,16 @@ const ToolingOverlay = () => {
 | 
			
		||||
 | 
			
		||||
    {/* Right Buttons */}
 | 
			
		||||
    <div className='absolute bottom-6 right-3 pointer-events-none'>
 | 
			
		||||
      {isAreasVisible
 | 
			
		||||
      {areAreasVisible
 | 
			
		||||
        ? <>
 | 
			
		||||
          <ToolToggleButton icon={LinkIcon} hint='Link Area Contexts' isActive={isLinkAreaContextsVisible} onClick={() => setIsLinkAreaContextsVisible(!isLinkAreaContextsVisible)} />
 | 
			
		||||
          <ToolToggleButton icon={LanguageIcon} hint='Toggle Translations' isActive={isTranslatedWordsVisible} onClick={() => setIsTranslatedWordsVisible(!isTranslatedWordsVisible)} />
 | 
			
		||||
          <ToolToggleButton icon={DocumentTextIcon} hint='Toggle Processed' isActive={isProcessedWordsVisible} onClick={() => setIsProcessedWordsVisible(!isProcessedWordsVisible)} />
 | 
			
		||||
          <ToolToggleButton icon={LinkIcon} hint='Link Area Contexts' isActive={areLinkAreaContextsVisible} onClick={() => dispatch(setAreLinkAreaContextsVisible(!areLinkAreaContextsVisible))} />
 | 
			
		||||
          <ToolToggleButton icon={LanguageIcon} hint='Toggle Translations' isActive={areTranslatedWordsVisible} onClick={() => dispatch(setAreTranslatedWordsVisible(!areTranslatedWordsVisible))} />
 | 
			
		||||
          <ToolToggleButton icon={DocumentTextIcon} hint='Toggle Processed' isActive={areProcessedWordsVisible} onClick={() => dispatch(setAreProcessedWordsVisible(!areProcessedWordsVisible))} />
 | 
			
		||||
        </>
 | 
			
		||||
        : <></>
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      <ToolToggleButton icon={SquaresPlusIcon} hint='Toggle Areas' isActive={isAreasVisible} onClick={() => setIsAreasVisible(!isAreasVisible)} />
 | 
			
		||||
      <ToolToggleButton icon={SquaresPlusIcon} hint='Toggle Areas' isActive={areAreasVisible} onClick={() => dispatch(setAreAreasVisible(!areAreasVisible))} />
 | 
			
		||||
    </div>
 | 
			
		||||
  </>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,24 +0,0 @@
 | 
			
		||||
import { StageContextType } from './types'
 | 
			
		||||
 | 
			
		||||
const makeDefaultStage = (): StageContextType => ({
 | 
			
		||||
  scale: 1,
 | 
			
		||||
  maxScale: 4,
 | 
			
		||||
  scaleStep: 0.01,
 | 
			
		||||
  setScale: (_) => {},
 | 
			
		||||
  isAreasVisible: true,
 | 
			
		||||
  setIsAreasVisible: (_) => {},
 | 
			
		||||
  isProcessedWordsVisible: true,
 | 
			
		||||
  setIsProcessedWordsVisible: (_) => {},
 | 
			
		||||
  isTranslatedWordsVisible: true,
 | 
			
		||||
  setIsTranslatedWordsVisible: (_) => {},
 | 
			
		||||
  isLinkAreaContextsVisible: false,
 | 
			
		||||
  setIsLinkAreaContextsVisible: (_) => {},
 | 
			
		||||
  size: { width: 1, height: 1 },
 | 
			
		||||
  setSize: (_) => {},
 | 
			
		||||
  isDrawingArea: false,
 | 
			
		||||
  setIsDrawingArea: (_) => {},
 | 
			
		||||
  startingContextConnection: null,
 | 
			
		||||
  setStartingContextConnection: (_) => {},
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
export default makeDefaultStage
 | 
			
		||||
@ -1,51 +0,0 @@
 | 
			
		||||
'use client'
 | 
			
		||||
 | 
			
		||||
import { createContext, useContext, useState, ReactNode, } from 'react'
 | 
			
		||||
import makeDefaultStage from './makeDefaultStage'
 | 
			
		||||
import { StageContextType, StartingContextConnection } from './types'
 | 
			
		||||
 | 
			
		||||
const StageContext = createContext<StageContextType>(makeDefaultStage())
 | 
			
		||||
 | 
			
		||||
export function useStage() {
 | 
			
		||||
  return useContext(StageContext)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const maxScale = 4
 | 
			
		||||
const scaleStep = 0.01
 | 
			
		||||
 | 
			
		||||
type Props = { children: ReactNode }
 | 
			
		||||
export function StageProvider({ children }: Props) {
 | 
			
		||||
  const [size, setSize] = useState({width: 1, height: 1})
 | 
			
		||||
  const [scale, setScale] = useState(1)
 | 
			
		||||
  const [isAreasVisible, setIsAreasVisible] = useState(true)
 | 
			
		||||
  const [isProcessedWordsVisible, setIsProcessedWordsVisible] = useState(true)
 | 
			
		||||
  const [isTranslatedWordsVisible, setIsTranslatedWordsVisible] = useState(true)
 | 
			
		||||
  const [isLinkAreaContextsVisible, setIsLinkAreaContextsVisible] = useState(false)
 | 
			
		||||
  const [isDrawingArea, setIsDrawingArea] = useState(false)
 | 
			
		||||
  const [startingContextConnection, setStartingContextConnection] = useState<StartingContextConnection | null>(null)
 | 
			
		||||
 | 
			
		||||
  const value = {
 | 
			
		||||
    scale,
 | 
			
		||||
    maxScale,
 | 
			
		||||
    scaleStep,
 | 
			
		||||
    setScale,
 | 
			
		||||
    isAreasVisible,
 | 
			
		||||
    setIsAreasVisible,
 | 
			
		||||
    isProcessedWordsVisible,
 | 
			
		||||
    setIsProcessedWordsVisible,
 | 
			
		||||
    isTranslatedWordsVisible,
 | 
			
		||||
    setIsTranslatedWordsVisible,
 | 
			
		||||
    isLinkAreaContextsVisible,
 | 
			
		||||
    setIsLinkAreaContextsVisible,
 | 
			
		||||
    size,
 | 
			
		||||
    setSize,
 | 
			
		||||
    isDrawingArea,
 | 
			
		||||
    setIsDrawingArea,
 | 
			
		||||
    startingContextConnection,
 | 
			
		||||
    setStartingContextConnection,
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return <StageContext.Provider value={value}>
 | 
			
		||||
    { children }
 | 
			
		||||
  </StageContext.Provider>
 | 
			
		||||
}
 | 
			
		||||
@ -1,25 +0,0 @@
 | 
			
		||||
export type StartingContextConnection = {
 | 
			
		||||
  isHead: boolean,
 | 
			
		||||
  areaId: string,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type StageContextType = {
 | 
			
		||||
  scale: number,
 | 
			
		||||
  maxScale: number,
 | 
			
		||||
  scaleStep: number,
 | 
			
		||||
  setScale: (value: number) => void,
 | 
			
		||||
  isAreasVisible: boolean,
 | 
			
		||||
  setIsAreasVisible: (value: boolean) => void,
 | 
			
		||||
  isProcessedWordsVisible: boolean,
 | 
			
		||||
  setIsProcessedWordsVisible: (value: boolean) => void,
 | 
			
		||||
  isTranslatedWordsVisible: boolean,
 | 
			
		||||
  setIsTranslatedWordsVisible: (value: boolean) => void,
 | 
			
		||||
  isLinkAreaContextsVisible: boolean,
 | 
			
		||||
  setIsLinkAreaContextsVisible: (value: boolean) => void,
 | 
			
		||||
  size: { width: number, height: number }
 | 
			
		||||
  setSize: (size: {width: number, height: number}) => void,
 | 
			
		||||
  isDrawingArea: boolean,
 | 
			
		||||
  setIsDrawingArea: (value: boolean) => void,
 | 
			
		||||
  startingContextConnection: StartingContextConnection | null,
 | 
			
		||||
  setStartingContextConnection: (value: StartingContextConnection | null) => void,
 | 
			
		||||
}
 | 
			
		||||
@ -2,19 +2,21 @@
 | 
			
		||||
 | 
			
		||||
import dynamic from 'next/dynamic'
 | 
			
		||||
import React, { useEffect, useRef } from 'react'
 | 
			
		||||
import { useDispatch } from 'react-redux'
 | 
			
		||||
import ToolingOverlay from './ToolingOverlay'
 | 
			
		||||
import { useStage } from './context/provider'
 | 
			
		||||
import { setSize } from '../../redux/features/stage/stageSlice'
 | 
			
		||||
 | 
			
		||||
const CanvasStage = dynamic(() => import('./CanvasStage'), { ssr: false })
 | 
			
		||||
 | 
			
		||||
const DocumentCanvas = () => {
 | 
			
		||||
  const { setSize } = useStage()
 | 
			
		||||
  const dispatch = useDispatch()
 | 
			
		||||
 | 
			
		||||
  const thisRef = useRef<HTMLDivElement>(null)
 | 
			
		||||
 | 
			
		||||
  const handleWindowResize = () => {
 | 
			
		||||
    const width = thisRef?.current?.clientWidth || 0
 | 
			
		||||
    const height = thisRef?.current?.clientHeight || 0
 | 
			
		||||
    setSize({ width, height })
 | 
			
		||||
    dispatch(setSize({ width, height }))
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,6 @@ import { useNavigation } from '../../context/Navigation/provider'
 | 
			
		||||
import { workspaces } from '../../context/Navigation/types'
 | 
			
		||||
import { useProject } from '../../context/Project/provider'
 | 
			
		||||
import DocumentCanvas from '../DocumentCanvas'
 | 
			
		||||
import { StageProvider } from '../DocumentCanvas/context/provider'
 | 
			
		||||
import NoSelectedDocument from './NoSelectedDocument'
 | 
			
		||||
import TextEditor from './TextEditor'
 | 
			
		||||
 | 
			
		||||
@ -16,9 +15,7 @@ const MainWorkspace = () => {
 | 
			
		||||
    if (selectedWorkspace === workspaces.TEXTEDITOR) return <TextEditor />
 | 
			
		||||
    else return !selectedDocumentId
 | 
			
		||||
      ? <NoSelectedDocument />
 | 
			
		||||
      : <StageProvider>
 | 
			
		||||
        <DocumentCanvas />
 | 
			
		||||
      </StageProvider>
 | 
			
		||||
      : <DocumentCanvas />
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return <main className=" bg-gray-100 min-h-[calc(100vh-118px)] ml-64 overflow-y-scroll">
 | 
			
		||||
 | 
			
		||||
@ -2,8 +2,8 @@ import { createSlice } from '@reduxjs/toolkit'
 | 
			
		||||
import type { PayloadAction } from '@reduxjs/toolkit'
 | 
			
		||||
import { ContextConnectionPoint, StageState } from './types'
 | 
			
		||||
 | 
			
		||||
const maxScale = 4
 | 
			
		||||
const scaleStep = 0.01
 | 
			
		||||
export const maxScale = 4
 | 
			
		||||
export const scaleStep = 0.01
 | 
			
		||||
 | 
			
		||||
const initialState: StageState = {
 | 
			
		||||
  size: { width: 1, height: 1 },
 | 
			
		||||
@ -46,7 +46,7 @@ export const stageSlice = createSlice({
 | 
			
		||||
    setIsDrawingArea: (state, action: PayloadAction<boolean>) => {
 | 
			
		||||
      state.isDrawingArea = action.payload
 | 
			
		||||
    },
 | 
			
		||||
    setStartingContextConnectionPoint: (state, action: PayloadAction<ContextConnectionPoint>) => {
 | 
			
		||||
    setStartingContextConnectionPoint: (state, action: PayloadAction<ContextConnectionPoint | null>) => {
 | 
			
		||||
      state.startingContextConnectionPoint = action.payload
 | 
			
		||||
    },
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user