From 751ee980e04e1bdab1351f40ad46ca23e5127e08 Mon Sep 17 00:00:00 2001 From: Maxim Date: Tue, 23 Aug 2022 16:36:20 +0300 Subject: [PATCH] add rotation form positionning --- grafana-plugin/src/components/Modal/Modal.tsx | 2 + .../containers/Rotation/Rotation.module.css | 5 ++- .../RotationForm/RotationForm.module.css | 5 +++ .../containers/RotationForm/RotationForm.tsx | 31 ++++++++++----- .../RotationForm/ScheduleOverrideForm.tsx | 18 ++++++++- .../src/containers/Rotations/Rotations.tsx | 12 +++--- .../Rotations/ScheduleOverrides.tsx | 8 ++-- grafana-plugin/src/utils/DOM.ts | 38 +++++++++++++++++++ 8 files changed, 97 insertions(+), 22 deletions(-) create mode 100644 grafana-plugin/src/utils/DOM.ts diff --git a/grafana-plugin/src/components/Modal/Modal.tsx b/grafana-plugin/src/components/Modal/Modal.tsx index b26cafaa..4cff1595 100644 --- a/grafana-plugin/src/components/Modal/Modal.tsx +++ b/grafana-plugin/src/components/Modal/Modal.tsx @@ -3,6 +3,8 @@ import React, { FC, PropsWithChildren } from 'react'; import cn from 'classnames/bind'; import ReactModal from 'react-modal'; +ReactModal.setAppElement('#reactRoot'); + import styles from './Modal.module.css'; export interface ModalProps { diff --git a/grafana-plugin/src/containers/Rotation/Rotation.module.css b/grafana-plugin/src/containers/Rotation/Rotation.module.css index a8edd3bf..be9dadd3 100644 --- a/grafana-plugin/src/containers/Rotation/Rotation.module.css +++ b/grafana-plugin/src/containers/Rotation/Rotation.module.css @@ -62,8 +62,9 @@ .empty { height: 28px; - background: #5f505633; + + /* background: #5f505633; border: 1px dashed #5c474d; - color: rgba(209, 14, 92, 0.5); + color: rgba(209, 14, 92, 0.5); */ margin: 0 2px; } diff --git a/grafana-plugin/src/containers/RotationForm/RotationForm.module.css b/grafana-plugin/src/containers/RotationForm/RotationForm.module.css index 1928ede4..719e0b69 100644 --- a/grafana-plugin/src/containers/RotationForm/RotationForm.module.css +++ b/grafana-plugin/src/containers/RotationForm/RotationForm.module.css @@ -2,6 +2,11 @@ display: block; } +.draggable { + top: 0; + transition: transform 500ms ease; +} + .header { width: 100%; display: flex; diff --git a/grafana-plugin/src/containers/RotationForm/RotationForm.tsx b/grafana-plugin/src/containers/RotationForm/RotationForm.tsx index 15aa59ea..853c8f4e 100644 --- a/grafana-plugin/src/containers/RotationForm/RotationForm.tsx +++ b/grafana-plugin/src/containers/RotationForm/RotationForm.tsx @@ -31,6 +31,7 @@ import { makeRequest } from 'network'; import { getDateTime, getUTCString } from 'pages/schedule/Schedule.helpers'; import { SelectOption } from 'state/types'; import { useStore } from 'state/useStore'; +import { getCoords, waitForElement } from 'utils/DOM'; import { useDebouncedCallback } from 'utils/hooks'; import { RotationCreateData } from './RotationForm.types'; @@ -57,8 +58,6 @@ const RotationForm: FC = observer((props) => { const { onHide, onCreate, startMoment, currentTimezone, scheduleId, onUpdate, onDelete, layerPriority, shiftId } = props; - const [isOpen, setIsOpen] = useState(true); - const [repeatEveryValue, setRepeatEveryValue] = useState(1); const [repeatEveryPeriod, setRepeatEveryPeriod] = useState(0); const [selectedDays, setSelectedDays] = useState([]); @@ -70,6 +69,24 @@ const RotationForm: FC = observer((props) => { dateTime(startOfDay.add(1, 'month').format('YYYY-MM-DD HH:mm:ss')) ); + const store = useStore(); + + const shift = store.scheduleStore.shifts[shiftId]; + + const [offsetTop, setOffsetTop] = useState(0); + + useEffect(() => { + waitForElement(`#layer${shiftId === 'new' ? layerPriority : shift?.priority_level}`).then((elm) => { + const modal = document.querySelector(`.${cx('draggable')}`) as HTMLDivElement; + + const coords = getCoords(elm); + + // setOffsetTop(Math.max(coords.top + elm.offsetHeight, 0)); + + setOffsetTop(coords.top - modal?.offsetHeight - 70); + }); + }, []); + const [userGroups, setUserGroups] = useState([[]]); const getUser = (pk: User['pk']) => { @@ -85,10 +102,6 @@ const RotationForm: FC = observer((props) => { }); }, []); - const store = useStore(); - - const shift = store.scheduleStore.shifts[shiftId]; - useEffect(() => { if (shiftId !== 'new') { store.scheduleStore.updateOncallShift(shiftId); @@ -137,7 +150,7 @@ const RotationForm: FC = observer((props) => { const handleChange = useDebouncedCallback(() => { store.scheduleStore.updateRotationPreview(scheduleId, shiftId, getFromString(startMoment), false, params); - }, 1000); + }, 500); useEffect(handleChange, [params]); @@ -172,11 +185,11 @@ const RotationForm: FC = observer((props) => { return ( ( - +
{children}
)} diff --git a/grafana-plugin/src/containers/RotationForm/ScheduleOverrideForm.tsx b/grafana-plugin/src/containers/RotationForm/ScheduleOverrideForm.tsx index 62204844..6c83d0b4 100644 --- a/grafana-plugin/src/containers/RotationForm/ScheduleOverrideForm.tsx +++ b/grafana-plugin/src/containers/RotationForm/ScheduleOverrideForm.tsx @@ -27,6 +27,7 @@ import { Timezone } from 'models/timezone/timezone.types'; import { User } from 'models/user/user.types'; import { getDateTime, getUTCString } from 'pages/schedule/Schedule.helpers'; import { useStore } from 'state/useStore'; +import { getCoords, waitForElement } from 'utils/DOM'; import { useDebouncedCallback } from 'utils/hooks'; import { RotationCreateData } from './RotationForm.types'; @@ -53,6 +54,18 @@ const ScheduleOverrideForm: FC = (props) => { const store = useStore(); + const [offsetTop, setOffsetTop] = useState(0); + + useEffect(() => { + waitForElement('#overrides-list').then((elm) => { + const modal = document.querySelector(`.${cx('draggable')}`) as HTMLDivElement; + + const coords = getCoords(elm); + + setOffsetTop(coords.top - modal?.offsetHeight - 10); + }); + }, []); + const [shiftStart, setShiftStart] = useState(dateTime(startOfDay.format('YYYY-MM-DD HH:mm:ss'))); const [shiftEnd, setShiftEnd] = useState( dateTime(startOfDay.add(12, 'hours').format('YYYY-MM-DD HH:mm:ss')) @@ -117,16 +130,17 @@ const ScheduleOverrideForm: FC = (props) => { const handleChange = useDebouncedCallback(() => { store.scheduleStore.updateRotationPreview(scheduleId, shiftId, getFromString(startMoment), true, params); - }, 1000); + }, 500); useEffect(handleChange, [params]); return ( ( - +
{children}
)} diff --git a/grafana-plugin/src/containers/Rotations/Rotations.tsx b/grafana-plugin/src/containers/Rotations/Rotations.tsx index d0cb61c5..dce39f50 100644 --- a/grafana-plugin/src/containers/Rotations/Rotations.tsx +++ b/grafana-plugin/src/containers/Rotations/Rotations.tsx @@ -87,10 +87,11 @@ class Rotations extends Component { {layers && layers.length ? ( layers.map((layer, layerIndex) => (
-
+
- Layer {layer.priority} + Layer {layer.priority} +
@@ -119,10 +120,11 @@ class Rotations extends Component { )) ) : (
-
+
- Layer 1 + Layer 1 +
@@ -151,7 +153,7 @@ class Rotations extends Component { this.handleAddLayer(nextPriority); }} > - Add rotations layer + + + Add rotations layer
diff --git a/grafana-plugin/src/containers/Rotations/ScheduleOverrides.tsx b/grafana-plugin/src/containers/Rotations/ScheduleOverrides.tsx index 4eb8aa33..bfbf9df9 100644 --- a/grafana-plugin/src/containers/Rotations/ScheduleOverrides.tsx +++ b/grafana-plugin/src/containers/Rotations/ScheduleOverrides.tsx @@ -55,7 +55,7 @@ class ScheduleOverrides extends Component -
+
Overrides
@@ -93,9 +93,9 @@ class ScheduleOverrides extends Component
-
- Add override + -
+ {/*
+ + Add override +
*/}
{shiftIdToShowOverrideForm && ( { + return new Promise((resolve) => { + if (document.querySelector(selector)) { + return resolve(document.querySelector(selector)); + } + + const observer = new MutationObserver((mutations) => { + if (document.querySelector(selector)) { + resolve(document.querySelector(selector)); + observer.disconnect(); + } + }); + + observer.observe(document.body, { + childList: true, + subtree: true, + }); + }); +}; + +export const getCoords = (elem) => { + // crossbrowser version + var box = elem.getBoundingClientRect(); + + var body = document.body; + var docEl = document.documentElement; + + var scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop; + var scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft; + + var clientTop = docEl.clientTop || body.clientTop || 0; + var clientLeft = docEl.clientLeft || body.clientLeft || 0; + + var top = box.top + scrollTop - clientTop; + var left = box.left + scrollLeft - clientLeft; + + return { top: Math.round(top), left: Math.round(left) }; +};