diff --git a/grafana-plugin/src/components/UserGroups/UserGroups.module.css b/grafana-plugin/src/components/UserGroups/UserGroups.module.css index 9ff63c70..178e3412 100644 --- a/grafana-plugin/src/components/UserGroups/UserGroups.module.css +++ b/grafana-plugin/src/components/UserGroups/UserGroups.module.css @@ -54,9 +54,15 @@ .user { background: #22252b; border-radius: 2px; - padding: 6px 10px; display: flex; - justify-content: space-between; + position: relative; + overflow: hidden; +} + +.user-buttons { + position: absolute; + top: 8px; + right: 5px; } .user:hover { diff --git a/grafana-plugin/src/components/UserGroups/UserGroups.tsx b/grafana-plugin/src/components/UserGroups/UserGroups.tsx index d9d996ba..37ab4780 100644 --- a/grafana-plugin/src/components/UserGroups/UserGroups.tsx +++ b/grafana-plugin/src/components/UserGroups/UserGroups.tsx @@ -7,6 +7,7 @@ import cn from 'classnames/bind'; import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc'; import Text from 'components/Text/Text'; +import WorkingHours from 'components/WorkingHours/WorkingHours'; import GSelect from 'containers/GSelect/GSelect'; import UserTooltip from 'containers/UserTooltip/UserTooltip'; import { User } from 'models/user/user.types'; @@ -21,6 +22,7 @@ interface UserGroupsProps { onChange: (value: Array>) => void; isMultipleGroups: boolean; getItemData: (id: string) => ItemData; + renderUser: (id: string) => React.ReactElement; } const cx = cn.bind(styles); @@ -30,7 +32,7 @@ const DragHandle = () => ; const SortableHandleHoc = SortableHandle(DragHandle); const UserGroups = (props: UserGroupsProps) => { - const { value, onChange, isMultipleGroups, getItemData } = props; + const { value, onChange, isMultipleGroups, getItemData, renderUser } = props; const handleAddUserGroup = useCallback(() => { onChange([...value, []]); @@ -86,10 +88,29 @@ const UserGroups = (props: UserGroupsProps) => { [items] ); + const getDeleteItemHandler = (index: number) => { + return () => { + handleDeleteUser(index); + }; + }; + + const renderItem = (item: Item, index: number) => ( +
  • + {renderUser(item.item)} +
    + + + + +
    +
  • + ); + return (
    void; handleDeleteItem: (index: number) => void; isMultipleGroups: boolean; + renderItem: (item: Item, index: number) => React.ReactElement; } const SortableList = SortableContainer( - ({ items, handleAddGroup, handleDeleteItem, isMultipleGroups }: SortableListProps) => { - const getDeleteItemHandler = (index: number) => { - return () => { - handleDeleteItem(index); - }; - }; - + ({ items, handleAddGroup, handleDeleteItem, isMultipleGroups, renderItem }: SortableListProps) => { return (
      {items.map((item, index) => item.type === 'item' ? ( -
    • -
      - {item.data.name} ({item.data.desc}) -
      -
      - - - - -
      -
    • + {renderItem(item, index)}
      ) : isMultipleGroups ? ( diff --git a/grafana-plugin/src/components/UserGroups/UserGroups.types.ts b/grafana-plugin/src/components/UserGroups/UserGroups.types.ts index 0a4bd62c..b3b85942 100644 --- a/grafana-plugin/src/components/UserGroups/UserGroups.types.ts +++ b/grafana-plugin/src/components/UserGroups/UserGroups.types.ts @@ -1,11 +1,6 @@ export interface Item { key: string; type: string; - data: ItemData; + data: any; item?: string; } - -export interface ItemData { - name: string; - desc?: string; -} diff --git a/grafana-plugin/src/components/WorkingHours/WorkingHours.tsx b/grafana-plugin/src/components/WorkingHours/WorkingHours.tsx index 200c895a..cf25e5dd 100644 --- a/grafana-plugin/src/components/WorkingHours/WorkingHours.tsx +++ b/grafana-plugin/src/components/WorkingHours/WorkingHours.tsx @@ -19,12 +19,13 @@ interface WorkingHoursProps { startMoment: dayjs.Dayjs; duration: number; // in seconds className: string; + style?: React.CSSProperties; } const cx = cn.bind(styles); const WorkingHours: FC = (props) => { - const { timezone, workingHours, startMoment, duration, className } = props; + const { timezone, workingHours, startMoment, duration, className, style } = props; const endMoment = startMoment.add(duration, 'seconds'); @@ -61,7 +62,14 @@ const WorkingHours: FC = (props) => { );*/ return ( - + diff --git a/grafana-plugin/src/containers/Rotation/Rotation.module.css b/grafana-plugin/src/containers/Rotation/Rotation.module.css index b7690181..1d39055b 100644 --- a/grafana-plugin/src/containers/Rotation/Rotation.module.css +++ b/grafana-plugin/src/containers/Rotation/Rotation.module.css @@ -62,9 +62,8 @@ .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 719e0b69..d603e058 100644 --- a/grafana-plugin/src/containers/RotationForm/RotationForm.module.css +++ b/grafana-plugin/src/containers/RotationForm/RotationForm.module.css @@ -4,7 +4,7 @@ .draggable { top: 0; - transition: transform 500ms ease; + transition: transform 300ms ease; } .header { @@ -17,6 +17,20 @@ width: 195px; } +.user-title { + padding: 6px 10px; + z-index: 1; + color: #fff; +} + +.working-hours { + position: absolute; + top: 0; + left: 0; + height: 100%; + pointer-events: none; +} + .date-time-picker { display: block; } diff --git a/grafana-plugin/src/containers/RotationForm/RotationForm.tsx b/grafana-plugin/src/containers/RotationForm/RotationForm.tsx index 5fe37915..84fe1c81 100644 --- a/grafana-plugin/src/containers/RotationForm/RotationForm.tsx +++ b/grafana-plugin/src/containers/RotationForm/RotationForm.tsx @@ -18,9 +18,12 @@ import { observer } from 'mobx-react'; import Draggable from 'react-draggable'; import Modal from 'components/Modal/Modal'; +import ScheduleSlot from 'components/ScheduleSlot/ScheduleSlot'; import Text from 'components/Text/Text'; import UserGroups from 'components/UserGroups/UserGroups'; +import { Item } from 'components/UserGroups/UserGroups.types'; import WithConfirm from 'components/WithConfirm/WithConfirm'; +import WorkingHours from 'components/WorkingHours/WorkingHours'; import RemoteSelect from 'containers/RemoteSelect/RemoteSelect'; import { getFromString } from 'models/schedule/schedule.helpers'; import { Rotation, Schedule, Shift } from 'models/schedule/schedule.types'; @@ -49,6 +52,7 @@ interface RotationFormProps { onCreate: () => void; onUpdate: () => void; onDelete: () => void; + shiftColor?: string; } const cx = cn.bind(styles); @@ -65,8 +69,11 @@ const RotationForm: FC = observer((props) => { layerPriority, shiftId, shiftMoment = dayjs().startOf('day').add(1, 'day'), + shiftColor = '#3D71D9', } = props; + console.log('shiftColor', shiftColor); + const [isOpen, setIsOpen] = useState(false); const [repeatEveryValue, setRepeatEveryValue] = useState(1); @@ -109,6 +116,29 @@ const RotationForm: FC = observer((props) => { }; }; + const renderUser = (userPk: User['pk']) => { + const name = store.userStore.items[userPk]?.username; + const desc = store.userStore.items[userPk]?.timezone; + const workingHours = store.userStore.items[userPk]?.working_hours; + const timezone = store.userStore.items[userPk]?.timezone; + + return ( + <> +
      + {name} ({desc}) +
      + + + ); + }; + const handleDeleteClick = useCallback(() => { store.scheduleStore.deleteOncallShift(shiftId).then(() => { onDelete(); @@ -238,7 +268,13 @@ const RotationForm: FC = observer((props) => { - + {/*
      */} diff --git a/grafana-plugin/src/containers/RotationForm/ScheduleOverrideForm.tsx b/grafana-plugin/src/containers/RotationForm/ScheduleOverrideForm.tsx index 5d4b87c5..31fd7c51 100644 --- a/grafana-plugin/src/containers/RotationForm/ScheduleOverrideForm.tsx +++ b/grafana-plugin/src/containers/RotationForm/ScheduleOverrideForm.tsx @@ -20,6 +20,7 @@ import Modal from 'components/Modal/Modal'; import Text from 'components/Text/Text'; import UserGroups from 'components/UserGroups/UserGroups'; import WithConfirm from 'components/WithConfirm/WithConfirm'; +import WorkingHours from 'components/WorkingHours/WorkingHours'; import { getFromString } from 'models/schedule/schedule.helpers'; import { Rotation, Schedule, Shift } from 'models/schedule/schedule.types'; import { getTzOffsetString } from 'models/timezone/timezone.helpers'; @@ -40,6 +41,8 @@ interface RotationFormProps { startMoment: dayjs.Dayjs; currentTimezone: Timezone; scheduleId: Schedule['id']; + shiftMoment: dayjs.Dayjs; + shiftColor?: string; onCreate: () => void; onUpdate: () => void; onDelete: () => void; @@ -58,6 +61,7 @@ const ScheduleOverrideForm: FC = (props) => { shiftId, startMoment, shiftMoment = dayjs().startOf('day').add(1, 'day'), + shiftColor = '#C69B06', } = props; const store = useStore(); @@ -92,6 +96,29 @@ const ScheduleOverrideForm: FC = (props) => { }; }; + const renderUser = (userPk: User['pk']) => { + const name = store.userStore.items[userPk]?.username; + const desc = store.userStore.items[userPk]?.timezone; + const workingHours = store.userStore.items[userPk]?.working_hours; + const timezone = store.userStore.items[userPk]?.timezone; + + return ( + <> +
      + {name} ({desc}) +
      + + + ); + }; + const shift = store.scheduleStore.shifts[shiftId]; useEffect(() => { @@ -183,7 +210,13 @@ const ScheduleOverrideForm: FC = (props) => {
      - + {/*
      */} diff --git a/grafana-plugin/src/containers/Rotations/Rotations.helpers.ts b/grafana-plugin/src/containers/Rotations/Rotations.helpers.ts index 9326fe3b..b6b69c5e 100644 --- a/grafana-plugin/src/containers/Rotations/Rotations.helpers.ts +++ b/grafana-plugin/src/containers/Rotations/Rotations.helpers.ts @@ -1,6 +1,6 @@ import { getColor, getOverrideColor } from 'models/schedule/schedule.helpers'; -export const findColor = (shiftId, layers, overrides) => { +export const findColor = (shiftId, layers, overrides?) => { let color = undefined; const layerIndex = layers ? layers.findIndex((layer) => layer.shifts.some((shift) => shift.shiftId === shiftId)) : -1; @@ -10,7 +10,7 @@ export const findColor = (shiftId, layers, overrides) => { if (layerIndex > -1 && rotationIndex > -1) { color = getColor(layerIndex, rotationIndex); - } else { + } else if (overrides) { const overrideIndex = overrides ? overrides.findIndex((shift) => shift.shiftId === shiftId) : -1; if (overrideIndex > -1) { diff --git a/grafana-plugin/src/containers/Rotations/Rotations.tsx b/grafana-plugin/src/containers/Rotations/Rotations.tsx index 53e87569..86671f8d 100644 --- a/grafana-plugin/src/containers/Rotations/Rotations.tsx +++ b/grafana-plugin/src/containers/Rotations/Rotations.tsx @@ -17,6 +17,8 @@ import { Timezone } from 'models/timezone/timezone.types'; import { SelectOption, WithStoreProps } from 'state/types'; import { withMobXProviderContext } from 'state/withStore'; +import { findColor } from './Rotations.helpers'; + import styles from './Rotations.module.css'; const cx = cn.bind(styles); @@ -93,11 +95,11 @@ class Rotations extends Component {
      Layer {layer.priority} - + {/**/}
      - + {!currentTimeHidden && (
      )} @@ -127,12 +129,12 @@ class Rotations extends Component {
      Layer 1 - + {/* */}
      - +
      { @@ -164,6 +166,7 @@ class Rotations extends Component { {shiftIdToShowRotationForm && (