Skip to content

Commit

Permalink
feat/canvas-trackpad on move (#120)
Browse files Browse the repository at this point in the history
* feat(drawer): adding wheel

* feat(drawer): adding wheel

* feat(drawer): adding types

* feat(drawer): adding zoom logic

* feat(drawer): adding zoom logic

* feat(drawer): adding move logic

* feat(drawer): removing zoom

* feat(drawer): adding emitter types

* fix(docker): revert

* fix(linter): imports
  • Loading branch information
JyTosTT authored Sep 14, 2023
1 parent 568e1a7 commit ffc0d03
Show file tree
Hide file tree
Showing 22 changed files with 247 additions and 70 deletions.
58 changes: 41 additions & 17 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,23 +1,47 @@
version: "3"
version: '3'

services:
front:
container_name: front
build:
context: ./front
dockerfile: Dockerfile
volumes:
- ./front/:/app
- /app/node_modules
- ./.env:/app/.env
ports:
- "${FRONT_PORT}:3000"
entrypoint: ["yarn", "start"]

api:
container_name: api
image: go:1.18
build:
context: ./api
dockerfile: Dockerfile
volumes:
- ./api/:/app
- ./.env:/app/.env
ports:
- 3030:8080
environment:
ENV: prod
networks:
- private
entrypoint: go build -t ./src/server.go
- "${API_PORT}:3000"
depends_on:
database:
condition: service_healthy

database:
container_name: database
networks:
- private
front:
container_name: front
networks:
private:
external: false
volumes:
data: {}
image: postgres:15
restart: always
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
ports:
- "${POSTGRES_PORT}:5432"
volumes:
- ./tmp/database:/var/lib/postgresql/data
healthcheck:
test: ["CMD", "pg_isready", "-U", "${POSTGRES_USER}"]
interval: 5s
timeout: 5s
retries: 10
2 changes: 1 addition & 1 deletion front/src/enums/eventEmitters.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export enum EventEmitters {
ON_MOVED_SCROLL_CLICK_MOUSE = 'onMovedScrollClickMouse',
ON_MOVED_DRAWERS = 'onMovedDrawers',
ON_MOVED_DRAWER = 'onDrawerMoved',
ON_SELECTED_DRAWER = 'onDrawerSelected',
ON_UNSELECTED_DRAWER = 'onDrawerUnselected',
Expand Down
1 change: 1 addition & 0 deletions front/src/enums/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ export enum Events {
ON_MOUSE_OUT = 'handleMouseOut',
ON_KEY_DOWN = 'keydown',
ON_RESIZE = 'resize',
WHEEL = 'wheel',
}
30 changes: 15 additions & 15 deletions front/src/hooks/useBoard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import { type TLinkBody, type TLinkEntity, type TLinker, type TLinkerOrNullify }
import BoardEntity from '../services/entities/Board.entity'
import UtilsDrawer from '../services/board/Utils.drawer'
import { type AxiosResponse } from 'axios'
import type drawerManager from '../services/entities/Drawer.manager'
import DrawerManager from '../services/entities/Drawer.manager'
import { Errors } from '../enums/errors'
import type drawerManager from '../services/entities/Drawer.manager'

const useBoard = (board: TBoardOrNullify): {
canvasRef: MutableRefObject<HTMLCanvasElement | null>
Expand All @@ -24,27 +24,27 @@ const useBoard = (board: TBoardOrNullify): {
const [selectedDrawer, setSelectedDrawer] = useState<TDrawerOrNullify>(undefined)
const [selectedLinker, setSelectedLinker] = useState<TLinkerOrNullify>(undefined)

const onSelectedDrawer: EventListenerCallback = async (drawer: TDrawer) => {
const onSelectedDrawer: EventListenerCallback<TDrawer> = async (drawer: TDrawer) => {
await onSelectDrawer(drawer, DrawerManager.get)
}

const onMovedDrawer: EventListenerCallback = async (drawer: TDrawer) => {
const onMovedDrawer: EventListenerCallback<{ drawer: TDrawer, selectDrawer?: boolean }> = async ({ drawer, selectDrawer }): Promise<void> => {
drawer.updateEntityPosition()
await onSelectDrawer(drawer, DrawerManager.update)
await onSelectDrawer(drawer, DrawerManager.update, selectDrawer)
}

const onSelectDrawer = async (drawer: TDrawer, method: typeof drawerManager['update' | 'get']): Promise<void> => {
const onSelectDrawer = async (drawer: TDrawer, method: typeof drawerManager['update' | 'get'], selectDrawer: boolean = true): Promise<void> => {
const { data: entity } = await method(drawer.entity!, drawer.type!)
drawer.update(entity)

setSelectedDrawer(drawer)
if (selectDrawer) setSelectedDrawer(drawer)
}

const onMovedScrollClickMouse: EventListenerCallback = async () => {
EventsCanvas.drawers.forEach(onMovedDrawer)
const onMovedDrawers: EventListenerCallback<any> = async () => {
EventsCanvas.drawers.forEach((drawer: TDrawer) => { onMovedDrawer({ drawer, selectDrawer: false }) })
}

const onCreatedLinker: EventListenerCallback = async (linker: TLinker) => {
const onCreatedLinker: EventListenerCallback<TLinker> = async (linker: TLinker) => {
const response = await createLink(linker)
if ((response?.data) != null) {
linker.entity = response?.data
Expand All @@ -63,7 +63,7 @@ const useBoard = (board: TBoardOrNullify): {
throw new Error(Errors.NOT_IMPLEMENTED)
}

const onDeletedLinker: EventListenerCallback = async (linker: TLinker) => {
const onDeletedLinker: EventListenerCallback<TLinker> = async (linker: TLinker) => {
if (UtilsDrawer.isServiceNetworkLink(linker)) {
await BoardEntity.deleteServiceNetworkLink(linker.entity!.id)
} else if (UtilsDrawer.isServiceVolumeLink(linker)) {
Expand All @@ -73,15 +73,15 @@ const useBoard = (board: TBoardOrNullify): {
throw new Error(Errors.NOT_IMPLEMENTED)
}

const onUnselectedDrawer: EventListenerCallback = (_) => {
const onUnselectedDrawer: EventListenerCallback<any> = () => {
setSelectedDrawer(undefined)
}

const onSelectedLinker: EventListenerCallback = (linker: TLinker) => {
const onSelectedLinker: EventListenerCallback<TLinker> = (linker: TLinker) => {
setSelectedLinker(linker)
}

const onUnselectedLinker: EventListenerCallback = (_) => {
const onUnselectedLinker: EventListenerCallback<any> = () => {
setSelectedLinker(undefined)
}

Expand All @@ -97,7 +97,7 @@ const useBoard = (board: TBoardOrNullify): {
{ name: EventEmitters.ON_DELETED_LINKER, action: onDeletedLinker },
{ name: EventEmitters.ON_SELECTED_DRAWER, action: onSelectedDrawer },
{ name: EventEmitters.ON_UNSELECTED_DRAWER, action: onUnselectedDrawer },
{ name: EventEmitters.ON_MOVED_SCROLL_CLICK_MOUSE, action: onMovedScrollClickMouse },
{ name: EventEmitters.ON_MOVED_DRAWERS, action: onMovedDrawers },
{ name: EventEmitters.ON_SELECTED_LINKER, action: onSelectedLinker },
{ name: EventEmitters.ON_UNSELECTED_LINKER, action: onUnselectedLinker }
]
Expand All @@ -115,7 +115,7 @@ const useBoard = (board: TBoardOrNullify): {

useEffect(() => {
events.forEach(({ name, action }) => {
eventEmitter.on(name, action)
eventEmitter.on<any>(name, action)
})

return () => {
Expand Down
4 changes: 2 additions & 2 deletions front/src/interfaces/EventListener.interface.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export type EventListenerCallback = (data?: any) => void
export type EventListenerCallback<T> = (arg: T) => void

export type EventListeners = Record<string, EventListenerCallback[]>
export type EventListeners<T> = Record<string, Array<EventListenerCallback<T>>>
2 changes: 1 addition & 1 deletion front/src/interfaces/Stack.interface.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { type EditorForm, TypeList } from '../forms/editor.structure'
import Input from '../views/atoms/forms/Input.atom'
import { object, string } from 'yup'
import { string } from 'yup'

export interface IStack {
id: number
Expand Down
8 changes: 4 additions & 4 deletions front/src/services/apps/Event.emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import { type EventEmitters } from '../../enums/eventEmitters'
import { type EventListenerCallback, type EventListeners } from '../../interfaces/EventListener.interface'

class EventEmitter {
private listeners: EventListeners = {}
private listeners: EventListeners<any> = {}

public on (event: EventEmitters, ...callbacks: EventListenerCallback[]): void {
public on<T> (event: EventEmitters, ...callbacks: Array<EventListenerCallback<T>>): void {
this.listeners[event] = callbacks
}

public emit (event: EventEmitters, data?: any): void {
this.listeners[event].forEach((callback: EventListenerCallback) => { callback(data) })
public emit<T>(event: EventEmitters, data?: any): void {
this.listeners[event].forEach((callback: EventListenerCallback<T>) => { callback(data) })
}

public removeListener (event: EventEmitters): void {
Expand Down
22 changes: 19 additions & 3 deletions front/src/services/canvas/Base.canvas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,24 @@ import { type ISize } from '../../interfaces/Window.interface'
import { Contexts } from '../../enums/contexts'
import { type TBaseCanvas } from '../../types/canvas/Base.canvas'
import { CursorTypes } from '../../enums/CursorTypes'
import { type IPosition } from '../../interfaces/Position.interface'

const BaseCanvas: TBaseCanvas = {
scale: 1,
position: { x: 0, y: 0 },

create (canvas: HTMLCanvasElement): void {
this.canvas = canvas
this.context = canvas.getContext(Contexts.ID_2D) as CanvasRenderingContext2D

this.sizeCanvas()
},

sizeCanvas () {
scaleCanvas (): void {

},

sizeCanvas (): void {
const dimensions: ISize = { width: this.context!.canvas.offsetWidth, height: this.context!.canvas.offsetHeight }

this.setCanvasDimensions(dimensions)
Expand All @@ -26,8 +34,10 @@ const BaseCanvas: TBaseCanvas = {
},

clearArea (): void {
this.context?.setTransform(1, 0, 0, 1, 0, 0)
this.context?.clearRect(0, 0, this.canvas!.width, this.canvas!.height)
this.context!.setTransform(1, 0, 0, 1, 0, 0)
this.context!.clearRect(0, 0, this.canvas!.width, this.canvas!.height)
this.context!.scale(this.scale, this.scale)
this.context!.translate(this.position.x, this.position.y)
},

updateContext (): void {
Expand All @@ -43,6 +53,12 @@ const BaseCanvas: TBaseCanvas = {
add
? this.canvas!.classList.add(CursorTypes.GRAB)
: this.canvas!.classList.remove(CursorTypes.GRAB)
},

boundingClientPosition (event: MouseEvent | WheelEvent): IPosition {
const rect: DOMRect = this.context!.canvas.getBoundingClientRect()

return { x: event.clientX - rect.left, y: event.clientY - rect.top }
}
}

Expand Down
3 changes: 2 additions & 1 deletion front/src/services/canvas/Base.manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import eventEmitter from '../apps/Event.emitter'
import { EventEmitters } from '../../enums/eventEmitters'
import { type IPosition } from '../../interfaces/Position.interface'
import { type ISize } from '../../interfaces/Window.interface'
import { type EventListenerCallback } from '../../interfaces/EventListener.interface'

const BaseManager: TBaseManager = {
...BaseCanvas,
Expand Down Expand Up @@ -35,7 +36,7 @@ const BaseManager: TBaseManager = {
this.selectDrawer(drawer)
this.updateScreen()

eventEmitter.emit(EventEmitters.ON_SELECTED_DRAWER, drawer)
eventEmitter.emit<EventListenerCallback<TDrawer>>(EventEmitters.ON_SELECTED_DRAWER, drawer)
},

emptyPosition (size: ISize, offset: number = 20): IPosition {
Expand Down
14 changes: 13 additions & 1 deletion front/src/services/canvas/Drawer.manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import StateCanvas from './State.canvas'
import { type TDrawer, type TDrawerOrNullify } from '../../types/Drawer'
import eventEmitter from '../apps/Event.emitter'
import { EventEmitters } from '../../enums/eventEmitters'
import { type EventListenerCallback } from '../../interfaces/EventListener.interface'

export const DrawerManager: TDrawerManager = {
...StateCanvas,
Expand All @@ -19,7 +20,7 @@ export const DrawerManager: TDrawerManager = {
}
this.selectedDrawer = undefined

eventEmitter.emit(EventEmitters.ON_UNSELECTED_DRAWER)
eventEmitter.emit<EventListenerCallback<any>>(EventEmitters.ON_UNSELECTED_DRAWER)
},

clearOnHoverDrawer (): void {
Expand Down Expand Up @@ -48,5 +49,16 @@ export const DrawerManager: TDrawerManager = {
} else {
this.clearOnHoverDrawer()
}
},

moveDrawersByPosition (deltaPosition: IPosition): void {
this.drawers.forEach((drawer: TDrawer) => {
const drawerPosition: IPosition = {
x: drawer.factory!.positionX + deltaPosition.x,
y: drawer.factory!.positionY + deltaPosition.y
}

drawer.factory?.updatePosition(drawerPosition)
})
}
}
3 changes: 3 additions & 0 deletions front/src/services/canvas/Events.canvas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import LinkerManager from './Linker.manager'
import { ConnectorManager } from './Connector.manager'
import KeyboardEventManager from './KeyboardEvent.manager'
import ScreenEventManager from './ScreenEvent.manager'
import WheelEventManager from './WheelEvent.manager'

const EventsCanvas: TEventsCanvas = {
...StateCanvas,
Expand All @@ -16,13 +17,15 @@ const EventsCanvas: TEventsCanvas = {
...LinkerManager,
...ConnectorManager,
...MouseEventManager,
...WheelEventManager,
...ScreenEventManager,
...KeyboardEventManager,

startup (): void {
this.draw()
this.screenStartup()
this.mouseStartup()
this.wheelStartup()
this.keyboardStartup()
},

Expand Down
9 changes: 5 additions & 4 deletions front/src/services/canvas/Linker.manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { type TBaseLinker } from '../../types/board/drawer/linkers/Base.linker'
import { CanvasColor } from '../../enums/CanvasColor'
import eventEmitter from '../apps/Event.emitter'
import { EventEmitters } from '../../enums/eventEmitters'
import { type EventListenerCallback } from '../../interfaces/EventListener.interface'

const LinkerManager: TLinkerManager = {
...BaseManager,
Expand Down Expand Up @@ -38,7 +39,7 @@ const LinkerManager: TLinkerManager = {

deleteLinker (drawer: TDrawer, linkerToRemove: TLinker): void {
const index = drawer.linkers.findIndex((linker: TBaseLinker) => linkerToRemove === linker)
eventEmitter.emit(EventEmitters.ON_DELETED_LINKER, drawer.linkers[index])
eventEmitter.emit<EventListenerCallback<TDrawer>>(EventEmitters.ON_DELETED_LINKER, drawer.linkers[index])
drawer.linkers.splice(index, 1)
this.clearSelectedLinker()
},
Expand All @@ -53,7 +54,7 @@ const LinkerManager: TLinkerManager = {
this.clearSelectedLinker()
this.selectedLinker = linker
this.selectedLinker.selected = true
eventEmitter.emit(EventEmitters.ON_SELECTED_LINKER, linker)
eventEmitter.emit<EventListenerCallback<TLinker>>(EventEmitters.ON_SELECTED_LINKER, linker)
},

createLinker (position: IPosition): void {
Expand All @@ -62,7 +63,7 @@ const LinkerManager: TLinkerManager = {
if ((this.selectedConnector != null) && (connector != null) && (this.selectedDrawer != null) && (this.onHoverDrawer != null)) {
const link = connector.drawer!.createLink(connector, this.selectedConnector)

eventEmitter.emit(EventEmitters.ON_CREATED_LINKER, link)
eventEmitter.emit<EventListenerCallback<TLinker>>(EventEmitters.ON_CREATED_LINKER, link)

this.clearOnHoverDrawer()
this.onSelectDrawer(false)
Expand All @@ -80,7 +81,7 @@ const LinkerManager: TLinkerManager = {
this.selectedLinker.selected = false
}
this.selectedLinker = undefined
eventEmitter.emit(EventEmitters.ON_UNSELECTED_LINKER)
eventEmitter.emit<EventListenerCallback<null>>(EventEmitters.ON_UNSELECTED_LINKER)
}
}

Expand Down
Loading

0 comments on commit ffc0d03

Please sign in to comment.