diff --git a/grafana-plugin/src/components/SchedulesFilters_NEW/SchedulesFilters.tsx b/grafana-plugin/src/components/SchedulesFilters_NEW/SchedulesFilters.tsx
index b1fa8834..cc6ee209 100644
--- a/grafana-plugin/src/components/SchedulesFilters_NEW/SchedulesFilters.tsx
+++ b/grafana-plugin/src/components/SchedulesFilters_NEW/SchedulesFilters.tsx
@@ -42,7 +42,7 @@ const SchedulesFilters = (props: SchedulesFiltersProps) => {
return (
-
+
= (props) => {
return (
-
+
);
};
diff --git a/grafana-plugin/src/containers/RotationForm/RotationForm.module.css b/grafana-plugin/src/containers/RotationForm/RotationForm.module.css
index 26042e17..a37c588e 100644
--- a/grafana-plugin/src/containers/RotationForm/RotationForm.module.css
+++ b/grafana-plugin/src/containers/RotationForm/RotationForm.module.css
@@ -22,6 +22,9 @@
padding: 6px 10px;
z-index: 1;
color: #fff;
+ width: 330px;
+ overflow: hidden;
+ white-space: nowrap;
}
.working-hours {
diff --git a/grafana-plugin/src/containers/Rotations/Rotations.tsx b/grafana-plugin/src/containers/Rotations/Rotations.tsx
index a309cbc1..fe8eb348 100644
--- a/grafana-plugin/src/containers/Rotations/Rotations.tsx
+++ b/grafana-plugin/src/containers/Rotations/Rotations.tsx
@@ -1,7 +1,7 @@
import React, { Component } from 'react';
import { SelectableValue } from '@grafana/data';
-import { ValuePicker, HorizontalGroup, Button } from '@grafana/ui';
+import { ValuePicker, HorizontalGroup, Button, Tooltip } from '@grafana/ui';
import cn from 'classnames/bind';
import dayjs from 'dayjs';
import { observer } from 'mobx-react';
@@ -13,7 +13,7 @@ import Rotation from 'containers/Rotation/Rotation';
import RotationForm from 'containers/RotationForm/RotationForm';
import { WithPermissionControl } from 'containers/WithPermissionControl/WithPermissionControl';
import { getColor, getFromString } from 'models/schedule/schedule.helpers';
-import { Layer, Schedule, Shift } from 'models/schedule/schedule.types';
+import { Layer, Schedule, ScheduleType, Shift } from 'models/schedule/schedule.types';
import { Timezone } from 'models/timezone/timezone.types';
import { WithStoreProps } from 'state/types';
import { UserAction } from 'state/userAction';
@@ -87,6 +87,11 @@ class Rotations extends Component {
options.push({ label: 'New Layer', value: nextPriority });
+ const schedule = store.scheduleStore.items[scheduleId];
+
+ const isTypeReadOnly =
+ schedule && (schedule?.type === ScheduleType.Ical || schedule?.type === ScheduleType.Calendar);
+
return (
<>
@@ -98,11 +103,21 @@ class Rotations extends Component {
{disabled ? (
-
-
-
+ isTypeReadOnly ? (
+
+
+
+
+
+ ) : (
+
+
+
+ )
) : (
1;
+ const schedule = store.scheduleStore.items[scheduleId];
+
+ const isTypeReadOnly =
+ schedule && (schedule?.type === ScheduleType.Ical || schedule?.type === ScheduleType.Calendar);
+
return (
<>
@@ -80,11 +85,21 @@ class ScheduleOverrides extends Component
-
-
-
+ {isTypeReadOnly ? (
+
+
+
+
+
+ ) : (
+
+
+
+ )}
diff --git a/grafana-plugin/src/models/user/user.ts b/grafana-plugin/src/models/user/user.ts
index d790ed8e..3db546fc 100644
--- a/grafana-plugin/src/models/user/user.ts
+++ b/grafana-plugin/src/models/user/user.ts
@@ -19,6 +19,8 @@ export class UserStore extends BaseStore {
@observable.shallow
items: { [pk: string]: User } = {};
+ itemsCurrentlyUpdating = {};
+
@observable
notificationPolicies: any = {};
@@ -87,12 +89,20 @@ export class UserStore extends BaseStore {
@action
async updateItem(userPk: User['pk']) {
+ if (this.itemsCurrentlyUpdating[userPk]) {
+ return;
+ }
+
+ this.itemsCurrentlyUpdating[userPk] = true;
+
const user = await this.getById(userPk);
this.items = {
...this.items,
[user.pk]: { ...user, timezone: getTimezone(user) },
};
+
+ delete this.itemsCurrentlyUpdating[userPk];
}
@action
diff --git a/grafana-plugin/src/pages/schedule/Schedule.tsx b/grafana-plugin/src/pages/schedule/Schedule.tsx
index 8ac61496..1f155226 100644
--- a/grafana-plugin/src/pages/schedule/Schedule.tsx
+++ b/grafana-plugin/src/pages/schedule/Schedule.tsx
@@ -6,7 +6,6 @@ import { Button, HorizontalGroup, VerticalGroup, IconButton, ToolbarButton, Icon
import { PluginPage } from 'PluginPage';
import cn from 'classnames/bind';
import dayjs from 'dayjs';
-import { omit } from 'lodash-es';
import { observer } from 'mobx-react';
import PageErrorHandlingWrapper from 'components/PageErrorHandlingWrapper/PageErrorHandlingWrapper';
@@ -138,16 +137,16 @@ class SchedulePage extends React.Component
)}
- {schedule?.type === ScheduleType.Ical && (
-
-
+
+
+ {(schedule?.type === ScheduleType.Ical || schedule?.type === ScheduleType.Calendar) && (
-
- )}
+ )}
+
- {schedule?.type !== ScheduleType.API && (
-
- Ical and API/Terraform schedules are read-only
-
- )}
return async () => {
await scheduleStore.reloadIcal(scheduleId);
- scheduleStore.updateItem(scheduleId);
- this.updateEventsFor(scheduleId);
+ store.scheduleStore.updateOncallShifts(scheduleId);
+ this.updateEvents();
};
};
- updateEventsFor = async (scheduleId: Schedule['id'], withEmpty = true, with_gap = true) => {
- const { store } = this.props;
- const { id } = getQueryParams();
-
- const { scheduleStore } = store;
-
- store.scheduleStore.scheduleToScheduleEvents = omit(store.scheduleStore.scheduleToScheduleEvents, [scheduleId]);
-
- await scheduleStore.updateScheduleEvents(
- scheduleId,
- withEmpty,
- with_gap,
- dayjs().format('YYYY-MM-DD').toString(),
- dayjs.tz.guess()
- );
-
- await store.scheduleStore.updateOncallShifts(id);
- await this.updateEvents();
- };
-
handleDelete = () => {
const { store } = this.props;
const { id: scheduleId } = getQueryParams();
diff --git a/grafana-plugin/src/pages/schedules/Schedules.module.css b/grafana-plugin/src/pages/schedules/Schedules.module.css
index c1fce1b8..bb044563 100644
--- a/grafana-plugin/src/pages/schedules/Schedules.module.css
+++ b/grafana-plugin/src/pages/schedules/Schedules.module.css
@@ -1,6 +1,7 @@
.schedule {
position: relative;
margin: 20px 0;
+ max-width: calc(100vw - 104px);
}
.title {