From 4454501721aac53fc2fd187435a7d82a234acff1 Mon Sep 17 00:00:00 2001 From: Matej Vavrek Date: Sun, 29 Mar 2020 16:37:18 +0200 Subject: [PATCH 1/4] #211 made report form resizable --- js/components/common/Modal/index.js | 53 ++++++++----- js/components/userFeedback/reportForm.js | 98 +++++++++++++++++++----- js/utils/useResizeObserver.js | 28 +++++++ package.json | 1 + yarn.lock | 2 +- 5 files changed, 140 insertions(+), 42 deletions(-) create mode 100644 js/utils/useResizeObserver.js diff --git a/js/components/common/Modal/index.js b/js/components/common/Modal/index.js index 48c32f11d..004fa7d7d 100644 --- a/js/components/common/Modal/index.js +++ b/js/components/common/Modal/index.js @@ -1,6 +1,7 @@ import { CircularProgress, makeStyles, Modal as MaterialModal } from '@material-ui/core'; import React, { memo } from 'react'; import classNames from 'classnames'; +import useResizeObserver from '../../../utils/useResizeObserver'; const useStyles = makeStyles(theme => ({ paper: { @@ -18,30 +19,40 @@ const useStyles = makeStyles(theme => ({ }, resizable: { resize: 'both', - overflow: 'auto' + overflow: 'hidden' } })); -export const Modal = memo(({ children, open, loading, onClose, noPadding, resizable, ...rest }) => { - const classes = useStyles(); - const content = loading ? : children; - return ( - -
{ + const classes = useStyles(); + const content = loading ? : children; + + const [containerDiv] = useResizeObserver(onResize); + + return ( + -
{content}
-
-
- ); -}); +
+
{content}
+
+ + ); + } +); export default Modal; diff --git a/js/components/userFeedback/reportForm.js b/js/components/userFeedback/reportForm.js index c4fd57088..068a5ba1d 100644 --- a/js/components/userFeedback/reportForm.js +++ b/js/components/userFeedback/reportForm.js @@ -19,6 +19,9 @@ import { snackbarColors } from '../header/constants'; import CanvasDraw from 'react-canvas-draw'; import { SketchPicker } from 'react-color'; +/* Min resolution is 960 x 540 */ +const FORM_MIN_WIDTH = 960; +const FORM_MIN_HEIGHT = 540; const CANVAS_MAX_WIDTH = 605; const CANVAS_MAX_HEIGHT = 400; @@ -64,13 +67,21 @@ const useStyles = makeStyles(theme => ({ marginBottom: '2px' }, formMinWidth: { - minWidth: '900px' + // 60 is padding (64 actually) + minWidth: FORM_MIN_WIDTH - 60 + 'px' + }, + formModal: { + minWidth: FORM_MIN_WIDTH + 'px', + minHeight: FORM_MIN_HEIGHT + 'px' }, canvasDrawWrapper: { overflow: 'auto', - maxWidth: CANVAS_MAX_WIDTH + 'px', - maxHeight: CANVAS_MAX_HEIGHT + 'px', + width: CANVAS_MAX_WIDTH + 'px', + height: CANVAS_MAX_HEIGHT + 'px', position: 'absolute' + }, + canvasNoImage: { + paddingTop: '200px' } })); @@ -164,12 +175,48 @@ export const ReportForm = memo(({ formType }) => { /* Modal handlers */ const [openForm, setOpenForm] = useState(false); const [openDialog, setOpenDialog] = useState(false); + const [modalWidth, setModalWidth] = useState(0); + const [modalHeight, setModalHeight] = useState(0); + const canvasWrapperGridItem = useRef(); + const canvasWrapper = useRef(); const canvasDraw = useRef(); const colorPicker = useRef(); + const [wrapperWidth, setWrapperWidth] = useState(CANVAS_MAX_WIDTH); + const [wrapperHeight, setWrapperHeight] = useState(CANVAS_MAX_HEIGHT); const [openBrushColor, setOpenBrushColor] = useState(false); const [brushRadius, setBrushRadius] = useState(2); const [brushColor, setBrushColor] = useState('#444'); + const modalOnResize = (entry, node) => { + // initialize modal width and height + if (node && !modalWidth && !modalHeight) { + setModalWidth(node.offsetWidth); + setModalHeight(node.offsetHeight); + } + if (canvasWrapper && canvasWrapper.current) { + const changedWidth = entry.target.offsetWidth; + if (modalWidth && modalWidth < changedWidth) { + // set new width from its flex div container + let newWidth = canvasWrapperGridItem.current.offsetWidth; + if (newWidth > formState.imageSource.width) { + // 17 is for scroll + newWidth = formState.imageSource.width + 17; + } + canvasWrapper.current.style.width = newWidth + 'px'; + } + const changedHeight = entry.target.offsetHeight; + if (modalHeight && modalHeight < changedHeight) { + // compute new height + let newHeight = wrapperHeight + changedHeight - modalHeight; + if (newHeight > formState.imageSource.height) { + newHeight = formState.imageSource.height; + } + canvasWrapperGridItem.current.style.flexBasis = newHeight + 'px'; + canvasWrapper.current.style.height = canvasWrapperGridItem.current.offsetHeight + 'px'; + } + } + }; + const handleColorChange = color => { setBrushColor(color.hex); }; @@ -279,7 +326,7 @@ export const ReportForm = memo(({ formType }) => { - + { - + + {/* Canvas options */} { - -
- {/* lazyRadius - how far is cursor from drawing point */} - -
+ {/* Canvas */} + + {formState.imageSource ? ( +
+ {/* lazyRadius - how far is cursor from drawing point */} + +
+ ) : ( + No image source. + )}
diff --git a/js/utils/useResizeObserver.js b/js/utils/useResizeObserver.js new file mode 100644 index 000000000..d1c2756e5 --- /dev/null +++ b/js/utils/useResizeObserver.js @@ -0,0 +1,28 @@ +import { useRef, useLayoutEffect, useState, useCallback } from 'react'; +import ResizeObserver from 'resize-observer-polyfill'; + +// https://tobbelindstrom.com/blog/resize-observer-hook/ + +const useResizeObserver = observerCallback => { + const [node, setNode] = useState(null); + const observer = useRef(null); + + const disconnect = useCallback(() => { + const { current } = observer; + current && current.disconnect(); + }, []); + + const observe = useCallback(() => { + observer.current = new ResizeObserver(([entry]) => observerCallback(entry, node)); + node && observer.current.observe(node); + }, [node, observerCallback]); + + useLayoutEffect(() => { + observe(); + return () => disconnect(); + }, [disconnect, observe]); + + return [setNode]; +}; + +export default useResizeObserver; diff --git a/package.json b/package.json index 74e21c384..7758d5703 100644 --- a/package.json +++ b/package.json @@ -110,6 +110,7 @@ "lint-staged": "^9.5.0", "prettier": "^1.19.1", "redux-mock-store": "^1.5.4", + "resize-observer-polyfill": "^1.5.1", "terser-webpack-plugin": "^2.2.1", "typescript": "^3.7.2", "webpack": "^4.41.5", diff --git a/yarn.lock b/yarn.lock index 600c87736..2ae36882e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7935,7 +7935,7 @@ reselect@^4.0.0: resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.0.0.tgz#f2529830e5d3d0e021408b246a206ef4ea4437f7" integrity sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA== -resize-observer-polyfill@^1.5.0: +resize-observer-polyfill@^1.5.0, resize-observer-polyfill@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464" integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg== From 5ed0238c8e8fd54f67044ffba33b872732be871a Mon Sep 17 00:00:00 2001 From: Matej Vavrek Date: Sun, 29 Mar 2020 16:41:14 +0200 Subject: [PATCH 2/4] #211 updated version From 80ce59849642d893d5f3e94b7f3b656a8891a761 Mon Sep 17 00:00:00 2001 From: Matej Vavrek Date: Sun, 29 Mar 2020 17:03:01 +0200 Subject: [PATCH 3/4] #211 added check for undefined callback --- js/utils/useResizeObserver.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/js/utils/useResizeObserver.js b/js/utils/useResizeObserver.js index d1c2756e5..3c4b3dbef 100644 --- a/js/utils/useResizeObserver.js +++ b/js/utils/useResizeObserver.js @@ -13,7 +13,9 @@ const useResizeObserver = observerCallback => { }, []); const observe = useCallback(() => { - observer.current = new ResizeObserver(([entry]) => observerCallback(entry, node)); + observer.current = new ResizeObserver(([entry]) => + observerCallback !== undefined ? observerCallback(entry, node) : null + ); node && observer.current.observe(node); }, [node, observerCallback]); From c9c52119a9be8bb143e9ecfc9e0af2ac6220482f Mon Sep 17 00:00:00 2001 From: Matej Vavrek Date: Tue, 31 Mar 2020 19:33:00 +0200 Subject: [PATCH 4/4] #211 updated version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7758d5703..e01044f6a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fragalysis-frontend", - "version": "0.5.0", + "version": "0.5.1", "description": "Frontend for fragalysis", "main": "webpack.config.js", "scripts": {