schedule changes

This commit is contained in:
Rares Mardare 2022-10-04 17:51:00 +03:00
parent c7bc0248f4
commit 0018fb1973
9 changed files with 86 additions and 66 deletions

View file

@ -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 <div className={cx('root')}>{colors?.length ? renderSVG() : renderAvatarIcon()}</div>;
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;

View file

@ -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<RotationsProps, RotationsState> {
};
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<RotationsProps, RotationsState> {
};
hideRotationForm = () => {
const { store } = this.props;
this.setState(
{
layerPriority: undefined,

View file

@ -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<ScheduleFinalProps, ScheduleOverridesState
};
render() {
const { startMoment, currentTimezone, store, hideHeader } = this.props;
const { scheduleId } = store.scheduleStore;
const { startMoment, currentTimezone, store, hideHeader, scheduleId } = this.props;
const base = 7 * 24 * 60; // in minutes
const diff = dayjs().tz(currentTimezone).diff(startMoment, 'minutes');
const currentTimeX = diff / base;
const shifts = store.scheduleStore.finalPreview
? store.scheduleStore.finalPreview
: (store.scheduleStore.events[scheduleId]?.['final']?.[getFromString(startMoment)] as Array<{
shiftId: string;
events: Event[];
}>);
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 (

View file

@ -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<ScheduleOverridesProps, ScheduleOverri
};
render() {
const { startMoment, currentTimezone, onCreate, onUpdate, onDelete, store, shiftIdToShowRotationForm } =
const { startMoment, currentTimezone, onCreate, onUpdate, onDelete, store, shiftIdToShowRotationForm, scheduleId } =
this.props;
const { shiftMomentToShowOverrideForm } = this.state;
const { scheduleId } = store.scheduleStore;
const shifts = store.scheduleStore.overridePreview
? store.scheduleStore.overridePreview
: (store.scheduleStore.events[scheduleId]?.['override']?.[getFromString(startMoment)] as Array<{
shiftId: string;
events: Event[];
isPreview?: boolean;
}>);
const shifts = getShiftsFromStore(store, scheduleId, startMoment, true);
const base = 7 * 24 * 60; // in minutes
const diff = dayjs().tz(currentTimezone).diff(startMoment, 'minutes');

View file

@ -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<UsersTimezonesProps> = (props) => {
interface UserAvatarsProps {
users: User[];
currentMoment: dayjs.Dayjs;
scheduleId: string;
scheduleId: Schedule['id'];
onTzChange: (timezone: Timezone) => void;
onCallNow: Array<Partial<User>>;
}
@ -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<string> } {
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<string> } = {};

View file

@ -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[] }>
) => {

View file

@ -77,7 +77,7 @@ export class ScheduleStore extends BaseStore {
byDayOptions: SelectOption[];
@observable
scheduleId: string;
scheduleId: Schedule['id'];
constructor(rootStore: RootStore) {
super(rootStore);

View file

@ -86,8 +86,6 @@ class SchedulePage extends React.Component<SchedulePageProps, SchedulePageState>
this.updateEvents(),
]);
store.scheduleStore.scheduleId = id;
this.setState({ isLoading: false });
}
@ -95,19 +93,16 @@ class SchedulePage extends React.Component<SchedulePageProps, SchedulePageState>
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 <LoadingPlaceholder text="Loading..." />}
return (
<div className={cx('root')}>
<VerticalGroup spacing="lg">
@ -173,6 +168,7 @@ class SchedulePage extends React.Component<SchedulePageProps, SchedulePageState>
currentTimezone={currentTimezone}
startMoment={startMoment}
onClick={this.handleShowForm}
scheduleId={scheduleId}
/>
<Rotations
currentTimezone={currentTimezone}
@ -182,6 +178,7 @@ class SchedulePage extends React.Component<SchedulePageProps, SchedulePageState>
onDelete={this.handleDeleteRotation}
shiftIdToShowRotationForm={shiftIdToShowRotationForm}
onShowRotationForm={this.handleShowRotationForm}
scheduleId={scheduleId}
/>
<ScheduleOverrides
currentTimezone={currentTimezone}
@ -191,6 +188,7 @@ class SchedulePage extends React.Component<SchedulePageProps, SchedulePageState>
onDelete={this.handleDeleteOverride}
shiftIdToShowRotationForm={shiftIdToShowOverridesForm}
onShowRotationForm={this.handleShowOverridesForm}
scheduleId={scheduleId}
/>
</div>
</VerticalGroup>

View file

@ -99,7 +99,7 @@ class SchedulesPage extends React.Component<SchedulesPageProps, SchedulesPageSta
const { store } = this.props;
const { expandedSchedulesKeys, scheduleIdToDelete, scheduleIdToEdit, scheduleIdToExport } = this.state;
const { filters } = this.state;
const { scheduleStore, userStore } = store;
const { scheduleStore } = store;
const columns = [
{
@ -306,9 +306,6 @@ class SchedulesPage extends React.Component<SchedulesPageProps, SchedulesPageSta
};
handleChangeFilters = (filters: SchedulesFiltersType) => {
const { store } = this.props;
const { scheduleStore } = store;
this.setState({ filters }, () => {
const { filters, expandedSchedulesKeys } = this.state;