From 0018fb1973fbc04ca0eaa311b3007bdc6c2ddd69 Mon Sep 17 00:00:00 2001 From: Rares Mardare Date: Tue, 4 Oct 2022 17:51:00 +0300 Subject: [PATCH] schedule changes --- .../ScheduleBorderedAvatar.tsx | 26 ++++++------ .../src/containers/Rotations/Rotations.tsx | 6 +-- .../containers/Rotations/ScheduleFinal.tsx | 22 ++++------ .../Rotations/ScheduleOverrides.tsx | 14 ++----- .../UsersTimezones/UsersTimezones.tsx | 27 +++++++------ .../src/models/schedule/schedule.helpers.ts | 40 ++++++++++++++++++- .../src/models/schedule/schedule.ts | 2 +- .../src/pages/schedule/Schedule.tsx | 10 ++--- .../src/pages/schedules/Schedules.tsx | 5 +-- 9 files changed, 86 insertions(+), 66 deletions(-) diff --git a/grafana-plugin/src/components/ScheduleBorderedAvatar/ScheduleBorderedAvatar.tsx b/grafana-plugin/src/components/ScheduleBorderedAvatar/ScheduleBorderedAvatar.tsx index 88b5ecb5..af2899dc 100644 --- a/grafana-plugin/src/components/ScheduleBorderedAvatar/ScheduleBorderedAvatar.tsx +++ b/grafana-plugin/src/components/ScheduleBorderedAvatar/ScheduleBorderedAvatar.tsx @@ -6,19 +6,21 @@ import styles from './ScheduleBorderedAvatar.module.scss'; const cx = cn.bind(styles); +interface ScheduleBorderedAvatarProps { + colors: string[]; + width: number; + height: number; + renderAvatar: () => JSX.Element; + renderIcon: () => JSX.Element; +} + export default function ScheduleBorderedAvatar({ colors, renderAvatar, renderIcon, width, height, -}: { - colors: string[]; - width: number; - height: number; - renderAvatar: () => JSX.Element; - renderIcon: () => JSX.Element; -}) { +}: ScheduleBorderedAvatarProps) { return
{colors?.length ? renderSVG() : renderAvatarIcon()}
; function renderAvatarIcon() { @@ -50,16 +52,16 @@ export default function ScheduleBorderedAvatar({ } const stepAngle = (2 * Math.PI) / colors.length; - const radius = 100; + const RADIUS = 100; let lastX = 0; - let lastY = -radius; + let lastY = -RADIUS; return colorSchemeList.map((_color, colorIndex) => { const angle = (colorIndex + 1) * stepAngle; - const x = radius * Math.sin(angle); - const y = -radius * Math.cos(angle); - const d = `M ${lastX.toFixed(3)},${lastY.toFixed(3)} A 100,100 0 0,1 ${x.toFixed(3)},${y.toFixed(3)}`; + const x = RADIUS * Math.sin(angle); + const y = -RADIUS * Math.cos(angle); + const d = `M ${lastX.toFixed(3)},${lastY.toFixed(3)} A ${RADIUS},${RADIUS} 0 0,1 ${x.toFixed(3)},${y.toFixed(3)}`; lastX = x; lastY = y; diff --git a/grafana-plugin/src/containers/Rotations/Rotations.tsx b/grafana-plugin/src/containers/Rotations/Rotations.tsx index 43ea3716..e1a8d51e 100644 --- a/grafana-plugin/src/containers/Rotations/Rotations.tsx +++ b/grafana-plugin/src/containers/Rotations/Rotations.tsx @@ -30,6 +30,7 @@ interface RotationsProps extends WithStoreProps { startMoment: dayjs.Dayjs; currentTimezone: Timezone; shiftIdToShowRotationForm?: Shift['id'] | 'new'; + scheduleId: Schedule['id']; onShowRotationForm: (shiftId: Shift['id'] | 'new') => void; onClick: (id: Shift['id'] | 'new') => void; onCreate: () => void; @@ -50,9 +51,8 @@ class Rotations extends Component { }; render() { - const { startMoment, currentTimezone, onCreate, onUpdate, onDelete, store, shiftIdToShowRotationForm } = this.props; + const { scheduleId, startMoment, currentTimezone, onCreate, onUpdate, onDelete, store, shiftIdToShowRotationForm } = this.props; const { layerPriority, shiftMomentToShowRotationForm } = this.state; - const { scheduleId } = store.scheduleStore; const base = 7 * 24 * 60; // in minutes const diff = dayjs().tz(currentTimezone).diff(startMoment, 'minutes'); @@ -239,8 +239,6 @@ class Rotations extends Component { }; hideRotationForm = () => { - const { store } = this.props; - this.setState( { layerPriority: undefined, diff --git a/grafana-plugin/src/containers/Rotations/ScheduleFinal.tsx b/grafana-plugin/src/containers/Rotations/ScheduleFinal.tsx index 5bac8b04..f5ed2945 100644 --- a/grafana-plugin/src/containers/Rotations/ScheduleFinal.tsx +++ b/grafana-plugin/src/containers/Rotations/ScheduleFinal.tsx @@ -8,7 +8,7 @@ import { CSSTransition, TransitionGroup } from 'react-transition-group'; import TimelineMarks from 'components/TimelineMarks/TimelineMarks'; import Rotation from 'containers/Rotation/Rotation'; -import { getColor, getFromString, getOverrideColor } from 'models/schedule/schedule.helpers'; +import { getColor, getFromString, getLayersFromStore, getOverrideColor, getOverridesFromStore, getShiftsFromStore } from 'models/schedule/schedule.helpers'; import { Event, Layer, Schedule, Shift } from 'models/schedule/schedule.types'; import { Timezone } from 'models/timezone/timezone.types'; import { WithStoreProps } from 'state/types'; @@ -24,6 +24,7 @@ const cx = cn.bind(styles); interface ScheduleFinalProps extends WithStoreProps { startMoment: dayjs.Dayjs; currentTimezone: Timezone; + scheduleId: Schedule['id']; hideHeader?: boolean; onClick: (shiftId: Shift['id']) => void; } @@ -39,28 +40,19 @@ class ScheduleFinal extends Component); + const shifts = getShiftsFromStore(store, scheduleId, startMoment, false); - const layers = store.scheduleStore.rotationPreview - ? store.scheduleStore.rotationPreview - : (store.scheduleStore.events[scheduleId]?.['rotation']?.[getFromString(startMoment)] as Layer[]); + const layers = getLayersFromStore(store, scheduleId, startMoment); + + const overrides = getOverridesFromStore(store, scheduleId, startMoment, true); - const overrides = store.scheduleStore.overridePreview - ? store.scheduleStore.overridePreview - : store.scheduleStore.events[scheduleId]?.['override']?.[getFromString(startMoment)]; const currentTimeHidden = currentTimeX < 0 || currentTimeX > 1; return ( diff --git a/grafana-plugin/src/containers/Rotations/ScheduleOverrides.tsx b/grafana-plugin/src/containers/Rotations/ScheduleOverrides.tsx index e03dc26f..1fdc5121 100644 --- a/grafana-plugin/src/containers/Rotations/ScheduleOverrides.tsx +++ b/grafana-plugin/src/containers/Rotations/ScheduleOverrides.tsx @@ -10,7 +10,7 @@ import TimelineMarks from 'components/TimelineMarks/TimelineMarks'; import Rotation from 'containers/Rotation/Rotation'; import { RotationCreateData } from 'containers/RotationForm/RotationForm.types'; import ScheduleOverrideForm from 'containers/RotationForm/ScheduleOverrideForm'; -import { getFromString, getOverrideColor } from 'models/schedule/schedule.helpers'; +import { getFromString, getOverrideColor, getShiftsFromStore } from 'models/schedule/schedule.helpers'; import { Event, Schedule, Shift } from 'models/schedule/schedule.types'; import { Timezone } from 'models/timezone/timezone.types'; import { WithStoreProps } from 'state/types'; @@ -26,6 +26,7 @@ const cx = cn.bind(styles); interface ScheduleOverridesProps extends WithStoreProps { startMoment: dayjs.Dayjs; currentTimezone: Timezone; + scheduleId: Schedule['id']; shiftIdToShowRotationForm?: Shift['id'] | 'new'; onShowRotationForm: (shiftId: Shift['id'] | 'new') => void; onCreate: () => void; @@ -44,18 +45,11 @@ class ScheduleOverrides extends Component); + const shifts = getShiftsFromStore(store, scheduleId, startMoment, true); const base = 7 * 24 * 60; // in minutes const diff = dayjs().tz(currentTimezone).diff(startMoment, 'minutes'); diff --git a/grafana-plugin/src/containers/UsersTimezones/UsersTimezones.tsx b/grafana-plugin/src/containers/UsersTimezones/UsersTimezones.tsx index 66e2e247..231673e2 100644 --- a/grafana-plugin/src/containers/UsersTimezones/UsersTimezones.tsx +++ b/grafana-plugin/src/containers/UsersTimezones/UsersTimezones.tsx @@ -12,8 +12,15 @@ import ScheduleUserDetails from 'components/ScheduleUserDetails/ScheduleUserDeta import Text from 'components/Text/Text'; import { findColor } from 'containers/Rotations/Rotations.helpers'; import { IsOncallIcon } from 'icons'; -import { getColor, getFromString, getOverrideColor } from 'models/schedule/schedule.helpers'; -import { Event, Layer } from 'models/schedule/schedule.types'; +import { + getColor, + getFromString, + getLayersFromStore, + getOverrideColor, + getOverridesFromStore, + getShiftsFromStore, +} from 'models/schedule/schedule.helpers'; +import { Event, Layer, Schedule } from 'models/schedule/schedule.types'; import { Timezone } from 'models/timezone/timezone.types'; import { User } from 'models/user/user.types'; import { getStartOfWeek } from 'pages/schedule/Schedule.helpers'; @@ -130,7 +137,7 @@ const UsersTimezones: FC = (props) => { interface UserAvatarsProps { users: User[]; currentMoment: dayjs.Dayjs; - scheduleId: string; + scheduleId: Schedule['id']; onTzChange: (timezone: Timezone) => void; onCallNow: Array>; } @@ -195,7 +202,7 @@ interface AvatarGroupProps { xPos: number; currentMoment: dayjs.Dayjs; utcOffset: number; - scheduleId: string; + scheduleId: Schedule['id']; onSetActiveUtcOffset: (utcOffset: number | undefined) => void; activeUtcOffset: number; onTzChange: (timezone: Timezone) => void; @@ -308,17 +315,11 @@ const AvatarGroup = (props: AvatarGroupProps) => { function getColorSchemeMappingForUsers(store: RootStore, scheduleId: string): { [userId: string]: Set } { const startMoment = getStartOfWeek(store.currentTimezone); - const shifts: Array<{ shiftId: string; events: Event[] }> = false - ? store.scheduleStore.finalPreview - : (store.scheduleStore.events[scheduleId]?.['final']?.[getFromString(startMoment)] as any); + const shifts = getShiftsFromStore(store, scheduleId, startMoment, false); - const layers = store.scheduleStore.rotationPreview - ? store.scheduleStore.rotationPreview - : (store.scheduleStore.events[scheduleId]?.['rotation']?.[getFromString(startMoment)] as Layer[]); + const layers = getLayersFromStore(store, scheduleId, startMoment); - const overrides = store.scheduleStore.overridePreview - ? store.scheduleStore.overridePreview - : store.scheduleStore.events[scheduleId]?.['override']?.[getFromString(startMoment)]; + const overrides = getOverridesFromStore(store, scheduleId, startMoment, false); const usersColorSchemeHash: { [userId: string]: Set } = {}; diff --git a/grafana-plugin/src/models/schedule/schedule.helpers.ts b/grafana-plugin/src/models/schedule/schedule.helpers.ts index d626d32e..b97aa545 100644 --- a/grafana-plugin/src/models/schedule/schedule.helpers.ts +++ b/grafana-plugin/src/models/schedule/schedule.helpers.ts @@ -1,6 +1,7 @@ import dayjs from 'dayjs'; +import { RootStore } from 'state'; -import { Event, Layer, ScheduleType, Shift } from './schedule.types'; +import { Event, Layer, Schedule, ScheduleType, Shift } from './schedule.types'; export const getFromString = (moment: dayjs.Dayjs) => { return moment.format('YYYY-MM-DD'); @@ -57,6 +58,43 @@ export const splitToShiftsAndFillGaps = (events: Event[]) => { return shifts; }; +export const getShiftsFromStore = ( + store: RootStore, + scheduleId: Schedule['id'], + startMoment: dayjs.Dayjs, + isOverridePreview: boolean, +): Array<{ shiftId: string; events: Event[], isPreview?: boolean; }> => { + const source = isOverridePreview ? store.scheduleStore.overridePreview : store.scheduleStore.finalPreview; + return source + ? store.scheduleStore.finalPreview + : (store.scheduleStore.events[scheduleId]?.['final']?.[getFromString(startMoment)] as any); +}; + +export const getLayersFromStore = (store: RootStore, scheduleId: Schedule['id'], startMoment: dayjs.Dayjs): Layer[] => { + return store.scheduleStore.rotationPreview + ? store.scheduleStore.rotationPreview + : (store.scheduleStore.events[scheduleId]?.['rotation']?.[getFromString(startMoment)] as Layer[]); +}; + +export const getOverridesFromStore = ( + store: RootStore, + scheduleId: Schedule['id'], + startMoment: dayjs.Dayjs, + isOverridePreview: boolean +): + | Layer[] + | { + shiftId: string; + events: Event[]; + isPreview?: boolean; + }[] => { + + const source = isOverridePreview ? store.scheduleStore.overridePreview : store.scheduleStore.rotationPreview; + return source + ? store.scheduleStore.rotationPreview + : (store.scheduleStore.events[scheduleId]?.['rotation']?.[getFromString(startMoment)] as Layer[]); +}; + export const splitToLayers = ( shifts: Array<{ shiftId: Shift['id']; priority: Shift['priority_level']; events: Event[] }> ) => { diff --git a/grafana-plugin/src/models/schedule/schedule.ts b/grafana-plugin/src/models/schedule/schedule.ts index 9bf6d6a2..cfd9a4ca 100644 --- a/grafana-plugin/src/models/schedule/schedule.ts +++ b/grafana-plugin/src/models/schedule/schedule.ts @@ -77,7 +77,7 @@ export class ScheduleStore extends BaseStore { byDayOptions: SelectOption[]; @observable - scheduleId: string; + scheduleId: Schedule['id']; constructor(rootStore: RootStore) { super(rootStore); diff --git a/grafana-plugin/src/pages/schedule/Schedule.tsx b/grafana-plugin/src/pages/schedule/Schedule.tsx index 11203db6..adf816bf 100644 --- a/grafana-plugin/src/pages/schedule/Schedule.tsx +++ b/grafana-plugin/src/pages/schedule/Schedule.tsx @@ -86,8 +86,6 @@ class SchedulePage extends React.Component this.updateEvents(), ]); - store.scheduleStore.scheduleId = id; - this.setState({ isLoading: false }); } @@ -95,19 +93,16 @@ class SchedulePage extends React.Component const { store } = this.props; store.scheduleStore.clearPreview(); - store.scheduleStore.scheduleId = undefined } render() { const { query: { id: scheduleId }, store } = this.props; - const { isLoading, startMoment, shiftIdToShowRotationForm, shiftIdToShowOverridesForm } = this.state; + const { startMoment, shiftIdToShowRotationForm, shiftIdToShowOverridesForm } = this.state; const { scheduleStore, currentTimezone } = store; const users = store.userStore.getSearchResult().results; const schedule = scheduleStore.items[scheduleId]; - if (isLoading) {return } - return (
@@ -173,6 +168,7 @@ class SchedulePage extends React.Component currentTimezone={currentTimezone} startMoment={startMoment} onClick={this.handleShowForm} + scheduleId={scheduleId} /> onDelete={this.handleDeleteRotation} shiftIdToShowRotationForm={shiftIdToShowRotationForm} onShowRotationForm={this.handleShowRotationForm} + scheduleId={scheduleId} /> onDelete={this.handleDeleteOverride} shiftIdToShowRotationForm={shiftIdToShowOverridesForm} onShowRotationForm={this.handleShowOverridesForm} + scheduleId={scheduleId} />
diff --git a/grafana-plugin/src/pages/schedules/Schedules.tsx b/grafana-plugin/src/pages/schedules/Schedules.tsx index 9b2e5e3a..d1df28ba 100644 --- a/grafana-plugin/src/pages/schedules/Schedules.tsx +++ b/grafana-plugin/src/pages/schedules/Schedules.tsx @@ -99,7 +99,7 @@ class SchedulesPage extends React.Component { - const { store } = this.props; - const { scheduleStore } = store; - this.setState({ filters }, () => { const { filters, expandedSchedulesKeys } = this.state;