123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- import React, { useEffect, useState } from 'react';
- import AnnotationWrapper from '../components/AnnotationWrapper';
- import Highlight from '../components/Highlight';
- import Ink from '../components/Ink';
- import FreeText from '../components/FreeText';
- import StickyNote from '../components/StickyNote';
- import Shape from '../components/Shape';
- import Line from '../components/Line';
- import Image from '../components/Image';
- import TextField from '../components/TextField';
- import DeleteDialog from '../components/DeleteDialog';
- import useCursorPosition from '../hooks/useCursorPosition';
- import ClickAwayListener from '../components/ClickAwayListener';
- import { appendUserIdAndDate } from '../helpers/annotation';
- import useStore from '../store';
- import useActions from '../actions';
- type Props = AnnotationType & {
- index: number;
- scale: number;
- };
- const Annotation: React.FC<Props> = ({
- id,
- obj_type,
- obj_attr,
- index,
- scale,
- }: Props) => {
- const [isCollapse, setCollapse] = useState(true);
- const [isEdit, setEdit] = useState(false);
- const [isCovered, setMouseOver] = useState(false);
- const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });
- const [openDialog, setDialog] = useState(false);
- const [cursorPosition, ref] = useCursorPosition();
- const [{ viewport, annotations }, dispatch] = useStore();
- const { updateAnnots } = useActions(dispatch);
- const handleClick = (): void => {
- if (isCollapse && !isEdit) {
- setCollapse(false);
- setMousePosition({
- x: cursorPosition.x || 0,
- y: cursorPosition.y || 0,
- });
- }
- };
- const handleMouseOver = (): void => {
- setMouseOver(true);
- };
- const handleMouseOut = (): void => {
- setMouseOver(false);
- };
- const handleUpdate: OnUpdateType = data => {
- const newAttributes = {
- ...annotations[index].obj_attr,
- ...data,
- isInit: false,
- };
- annotations[index].obj_attr = newAttributes;
- annotations[index] = appendUserIdAndDate(annotations[index]);
- updateAnnots(annotations);
- };
- const handleEdit = (): void => {
- setEdit(true);
- setCollapse(true);
- };
- const deleteDialogToggle = (): void => {
- setDialog(!openDialog);
- };
- const handleDelete = (): void => {
- annotations.splice(index, 1);
- setDialog(false);
- updateAnnots(annotations);
- };
- const handleBlur = (): void => {
- setCollapse(true);
- };
- const handleInputBlur = (): void => {
- setEdit(false);
- if (obj_type === 'FreeText' && !obj_attr.content) {
- handleDelete();
- }
- };
- const handleKeyDown = (e: React.KeyboardEvent): void => {
- if (e.key === 'Delete') {
- deleteDialogToggle();
- }
- };
- useEffect(() => {
- if (obj_type === 'FreeText' && !obj_attr.content) {
- setEdit(true);
- }
- }, [obj_type, obj_attr]);
- useEffect(() => {
- return () => {
- handleMouseOut();
- handleBlur();
- setEdit(false);
- };
- }, []);
- const childProps = {
- id,
- obj_type,
- obj_attr,
- scale,
- isCollapse,
- isCovered,
- mousePosition,
- onUpdate: handleUpdate,
- onDelete: deleteDialogToggle,
- viewport,
- onEdit: handleEdit,
- isEdit,
- onBlur: handleInputBlur,
- onMouseOver: handleMouseOver,
- onMouseOut: handleMouseOut,
- };
- const wrapperProps = {
- onMouseDown: handleClick,
- onKeyDown: handleKeyDown,
- };
- return (
- <ClickAwayListener onClick={handleBlur}>
- <AnnotationWrapper ref={ref} {...wrapperProps}>
- {((): React.ReactNode => {
- switch (obj_type) {
- case 'Ink':
- return <Ink {...childProps} />;
- case 'FreeText':
- return <FreeText {...childProps} />;
- case 'Text':
- return <StickyNote {...childProps} />;
- case 'Square':
- case 'Circle':
- return <Shape {...childProps} />;
- case 'Line':
- case 'Arrow':
- return <Line {...childProps} />;
- case 'Image':
- return <Image {...childProps} />;
- case 'textfield':
- case 'checkbox':
- return <TextField {...childProps} />;
- default:
- return <Highlight {...childProps} />;
- }
- })()}
- {openDialog && (
- <DeleteDialog onCancel={deleteDialogToggle} onDelete={handleDelete} />
- )}
- </AnnotationWrapper>
- </ClickAwayListener>
- );
- };
- export default Annotation;
|