mirror of
https://github.com/mattermost/mattermost.git
synced 2026-05-28 04:35:04 -04:00
Merge c7bea46ce2 into 7e75035cb6
This commit is contained in:
commit
c369bb7ff6
4 changed files with 557 additions and 2 deletions
|
|
@ -192,6 +192,42 @@ Object {
|
|||
<div
|
||||
class="divider-light"
|
||||
/>
|
||||
<div
|
||||
class="section-min"
|
||||
>
|
||||
<div
|
||||
class="section-min__header"
|
||||
>
|
||||
<h4
|
||||
class="section-min__title"
|
||||
id="do_not_disturb_scheduleTitle"
|
||||
>
|
||||
Do not disturb schedule
|
||||
</h4>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-labelledby="do_not_disturb_scheduleTitle do_not_disturb_scheduleEdit"
|
||||
class="color--link style--none section-min__edit"
|
||||
id="do_not_disturb_scheduleEdit"
|
||||
>
|
||||
<i
|
||||
aria-hidden="true"
|
||||
class="icon-pencil-outline"
|
||||
title="Edit Icon"
|
||||
/>
|
||||
Edit
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="section-min__describe"
|
||||
id="do_not_disturb_scheduleDesc"
|
||||
>
|
||||
Disabled
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="divider-light"
|
||||
/>
|
||||
<div
|
||||
class="section-min"
|
||||
>
|
||||
|
|
@ -503,6 +539,42 @@ Object {
|
|||
<div
|
||||
class="divider-light"
|
||||
/>
|
||||
<div
|
||||
class="section-min"
|
||||
>
|
||||
<div
|
||||
class="section-min__header"
|
||||
>
|
||||
<h4
|
||||
class="section-min__title"
|
||||
id="do_not_disturb_scheduleTitle"
|
||||
>
|
||||
Do not disturb schedule
|
||||
</h4>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-labelledby="do_not_disturb_scheduleTitle do_not_disturb_scheduleEdit"
|
||||
class="color--link style--none section-min__edit"
|
||||
id="do_not_disturb_scheduleEdit"
|
||||
>
|
||||
<i
|
||||
aria-hidden="true"
|
||||
class="icon-pencil-outline"
|
||||
title="Edit Icon"
|
||||
/>
|
||||
Edit
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="section-min__describe"
|
||||
id="do_not_disturb_scheduleDesc"
|
||||
>
|
||||
Disabled
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="divider-light"
|
||||
/>
|
||||
<div
|
||||
class="section-min"
|
||||
>
|
||||
|
|
@ -880,6 +952,42 @@ Object {
|
|||
<div
|
||||
class="divider-light"
|
||||
/>
|
||||
<div
|
||||
class="section-min"
|
||||
>
|
||||
<div
|
||||
class="section-min__header"
|
||||
>
|
||||
<h4
|
||||
class="section-min__title"
|
||||
id="do_not_disturb_scheduleTitle"
|
||||
>
|
||||
Do not disturb schedule
|
||||
</h4>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-labelledby="do_not_disturb_scheduleTitle do_not_disturb_scheduleEdit"
|
||||
class="color--link style--none section-min__edit"
|
||||
id="do_not_disturb_scheduleEdit"
|
||||
>
|
||||
<i
|
||||
aria-hidden="true"
|
||||
class="icon-pencil-outline"
|
||||
title="Edit Icon"
|
||||
/>
|
||||
Edit
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="section-min__describe"
|
||||
id="do_not_disturb_scheduleDesc"
|
||||
>
|
||||
Disabled
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="divider-light"
|
||||
/>
|
||||
<div
|
||||
class="section-min"
|
||||
>
|
||||
|
|
@ -1193,6 +1301,42 @@ Object {
|
|||
<div
|
||||
class="divider-light"
|
||||
/>
|
||||
<div
|
||||
class="section-min"
|
||||
>
|
||||
<div
|
||||
class="section-min__header"
|
||||
>
|
||||
<h4
|
||||
class="section-min__title"
|
||||
id="do_not_disturb_scheduleTitle"
|
||||
>
|
||||
Do not disturb schedule
|
||||
</h4>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-labelledby="do_not_disturb_scheduleTitle do_not_disturb_scheduleEdit"
|
||||
class="color--link style--none section-min__edit"
|
||||
id="do_not_disturb_scheduleEdit"
|
||||
>
|
||||
<i
|
||||
aria-hidden="true"
|
||||
class="icon-pencil-outline"
|
||||
title="Edit Icon"
|
||||
/>
|
||||
Edit
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="section-min__describe"
|
||||
id="do_not_disturb_scheduleDesc"
|
||||
>
|
||||
Disabled
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="divider-light"
|
||||
/>
|
||||
<div
|
||||
class="section-min"
|
||||
>
|
||||
|
|
@ -1572,6 +1716,42 @@ Object {
|
|||
<div
|
||||
class="divider-light"
|
||||
/>
|
||||
<div
|
||||
class="section-min"
|
||||
>
|
||||
<div
|
||||
class="section-min__header"
|
||||
>
|
||||
<h4
|
||||
class="section-min__title"
|
||||
id="do_not_disturb_scheduleTitle"
|
||||
>
|
||||
Do not disturb schedule
|
||||
</h4>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-labelledby="do_not_disturb_scheduleTitle do_not_disturb_scheduleEdit"
|
||||
class="color--link style--none section-min__edit"
|
||||
id="do_not_disturb_scheduleEdit"
|
||||
>
|
||||
<i
|
||||
aria-hidden="true"
|
||||
class="icon-pencil-outline"
|
||||
title="Edit Icon"
|
||||
/>
|
||||
Edit
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="section-min__describe"
|
||||
id="do_not_disturb_scheduleDesc"
|
||||
>
|
||||
Disabled
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="divider-light"
|
||||
/>
|
||||
<div
|
||||
class="section-min"
|
||||
>
|
||||
|
|
@ -1847,6 +2027,42 @@ Object {
|
|||
<div
|
||||
class="divider-light"
|
||||
/>
|
||||
<div
|
||||
class="section-min"
|
||||
>
|
||||
<div
|
||||
class="section-min__header"
|
||||
>
|
||||
<h4
|
||||
class="section-min__title"
|
||||
id="do_not_disturb_scheduleTitle"
|
||||
>
|
||||
Do not disturb schedule
|
||||
</h4>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-labelledby="do_not_disturb_scheduleTitle do_not_disturb_scheduleEdit"
|
||||
class="color--link style--none section-min__edit"
|
||||
id="do_not_disturb_scheduleEdit"
|
||||
>
|
||||
<i
|
||||
aria-hidden="true"
|
||||
class="icon-pencil-outline"
|
||||
title="Edit Icon"
|
||||
/>
|
||||
Edit
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="section-min__describe"
|
||||
id="do_not_disturb_scheduleDesc"
|
||||
>
|
||||
Disabled
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="divider-light"
|
||||
/>
|
||||
<div
|
||||
class="section-min"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import {connect, type ConnectedProps} from 'react-redux';
|
|||
import type {PreferencesType} from '@mattermost/types/preferences';
|
||||
import type {UserProfile} from '@mattermost/types/users';
|
||||
|
||||
import {patchUser, updateMe} from 'mattermost-redux/actions/users';
|
||||
import {patchUser, setStatus, updateMe} from 'mattermost-redux/actions/users';
|
||||
import {getSubscriptionProduct} from 'mattermost-redux/selectors/entities/cloud';
|
||||
import {getConfig, getLicense} from 'mattermost-redux/selectors/entities/general';
|
||||
import {
|
||||
|
|
@ -57,6 +57,7 @@ const mapStateToProps = (state: GlobalState, props: OwnProps) => {
|
|||
const mapDispatchToProps = {
|
||||
updateMe,
|
||||
patchUser,
|
||||
setStatus,
|
||||
};
|
||||
|
||||
const connector = connect(mapStateToProps, mapDispatchToProps);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import {renderWithContext, screen} from 'tests/react_testing_utils';
|
|||
import {NotificationLevels} from 'utils/constants';
|
||||
import {TestHelper} from 'utils/test_helper';
|
||||
|
||||
import UserSettingsNotifications, {areDesktopAndMobileSettingsDifferent} from './user_settings_notifications';
|
||||
import UserSettingsNotifications, {areDesktopAndMobileSettingsDifferent, shouldSilenceForDndSchedule} from './user_settings_notifications';
|
||||
|
||||
jest.mock('components/user_settings/notifications/desktop_and_mobile_notification_setting/notification_permission_section_notice', () => () => <div/>);
|
||||
jest.mock('components/user_settings/notifications/desktop_and_mobile_notification_setting/notification_permission_title_tag', () => () => <div/>);
|
||||
|
|
@ -22,6 +22,7 @@ describe('components/user_settings/display/UserSettingsDisplay', () => {
|
|||
collapseModal: jest.fn(),
|
||||
updateMe: jest.fn(() => Promise.resolve({})),
|
||||
patchUser: jest.fn(() => Promise.resolve({})),
|
||||
setStatus: jest.fn(() => Promise.resolve({})),
|
||||
isCollapsedThreadsEnabled: true,
|
||||
sendPushNotifications: false,
|
||||
enableAutoResponder: false,
|
||||
|
|
@ -91,3 +92,65 @@ describe('areDesktopAndMobileSettingsDifferent', () => {
|
|||
expect(areDesktopAndMobileSettingsDifferent(NotificationLevels.ALL, NotificationLevels.ALL, NotificationLevels.ALL, undefined as any, true)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('shouldSilenceForDndSchedule', () => {
|
||||
test('notifies when schedule is deactivated', () => {
|
||||
const shouldSilence = shouldSilenceForDndSchedule({
|
||||
isScheduleEnabled: false,
|
||||
allowNotificationsOnWeekends: false,
|
||||
fromTime: '09:00',
|
||||
toTime: '17:00',
|
||||
now: new Date('2026-04-20T20:00:00'),
|
||||
});
|
||||
|
||||
expect(shouldSilence).toBe(false);
|
||||
});
|
||||
|
||||
test('silences when schedule is activated and current time is outside schedule window', () => {
|
||||
const shouldSilence = shouldSilenceForDndSchedule({
|
||||
isScheduleEnabled: true,
|
||||
allowNotificationsOnWeekends: false,
|
||||
fromTime: '09:00',
|
||||
toTime: '17:00',
|
||||
now: new Date('2026-04-20T20:00:00'),
|
||||
});
|
||||
|
||||
expect(shouldSilence).toBe(true);
|
||||
});
|
||||
|
||||
test('notifies when schedule is activated and current time is inside schedule window', () => {
|
||||
const shouldSilence = shouldSilenceForDndSchedule({
|
||||
isScheduleEnabled: true,
|
||||
allowNotificationsOnWeekends: false,
|
||||
fromTime: '09:00',
|
||||
toTime: '17:00',
|
||||
now: new Date('2026-04-20T10:00:00'),
|
||||
});
|
||||
|
||||
expect(shouldSilence).toBe(false);
|
||||
});
|
||||
|
||||
test('notifies on weekends when weekend notifications are allowed', () => {
|
||||
const shouldSilence = shouldSilenceForDndSchedule({
|
||||
isScheduleEnabled: true,
|
||||
allowNotificationsOnWeekends: true,
|
||||
fromTime: '09:00',
|
||||
toTime: '17:00',
|
||||
now: new Date('2026-04-19T20:00:00'),
|
||||
});
|
||||
|
||||
expect(shouldSilence).toBe(false);
|
||||
});
|
||||
|
||||
test('silences on weekends when weekend notifications are not allowed and time is outside schedule window', () => {
|
||||
const shouldSilence = shouldSilenceForDndSchedule({
|
||||
isScheduleEnabled: true,
|
||||
allowNotificationsOnWeekends: false,
|
||||
fromTime: '09:00',
|
||||
toTime: '17:00',
|
||||
now: new Date('2026-04-19T20:00:00'),
|
||||
});
|
||||
|
||||
expect(shouldSilence).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import SettingItemMax from 'components/setting_item_max';
|
|||
import RestrictedIndicator from 'components/widgets/menu/menu_items/restricted_indicator';
|
||||
|
||||
import Constants, {NotificationLevels, MattermostFeatures, LicenseSkus, UserSettingsNotificationSections} from 'utils/constants';
|
||||
import {toUTCUnixInSeconds} from 'utils/datetime';
|
||||
import {notificationSoundKeys, stopTryNotificationRing} from 'utils/notification_sounds';
|
||||
import {a11yFocus} from 'utils/utils';
|
||||
|
||||
|
|
@ -36,6 +37,67 @@ import type {OwnProps, PropsFromRedux} from './index';
|
|||
|
||||
const WHITE_SPACE_REGEX = /\s+/g;
|
||||
const COMMA_REGEX = /,/g;
|
||||
const DO_NOT_DISTURB_SCHEDULE_SECTION = 'do_not_disturb_schedule';
|
||||
const DND_SCHEDULE_ENABLED_KEY = 'dnd_schedule_enabled';
|
||||
const DND_SCHEDULE_FROM_TIME_KEY = 'dnd_schedule_from_time';
|
||||
const DND_SCHEDULE_TO_TIME_KEY = 'dnd_schedule_to_time';
|
||||
const DND_SCHEDULE_ALLOW_WEEKENDS_KEY = 'dnd_schedule_allow_weekends';
|
||||
|
||||
export function parseMinutesFromTimeValue(value: string): number {
|
||||
const [hoursString = '0', minutesString = '0'] = value.split(':');
|
||||
const hours = Number.parseInt(hoursString, 10);
|
||||
const minutes = Number.parseInt(minutesString, 10);
|
||||
|
||||
if (Number.isNaN(hours) || Number.isNaN(minutes)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (hours * 60) + minutes;
|
||||
}
|
||||
|
||||
export function isTimeInsideScheduleWindow(now: Date, fromMinutes: number, toMinutes: number): boolean {
|
||||
const currentMinutes = (now.getHours() * 60) + now.getMinutes();
|
||||
|
||||
if (fromMinutes === toMinutes) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (fromMinutes < toMinutes) {
|
||||
return currentMinutes >= fromMinutes && currentMinutes < toMinutes;
|
||||
}
|
||||
|
||||
return currentMinutes >= fromMinutes || currentMinutes < toMinutes;
|
||||
}
|
||||
|
||||
export function shouldSilenceForDndSchedule({
|
||||
isScheduleEnabled,
|
||||
allowNotificationsOnWeekends,
|
||||
fromTime,
|
||||
toTime,
|
||||
now,
|
||||
}: {
|
||||
isScheduleEnabled: boolean;
|
||||
allowNotificationsOnWeekends: boolean;
|
||||
fromTime: string;
|
||||
toTime: string;
|
||||
now: Date;
|
||||
}): boolean {
|
||||
if (!isScheduleEnabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const dayOfWeek = now.getDay();
|
||||
const isWeekend = dayOfWeek === 0 || dayOfWeek === 6;
|
||||
if (allowNotificationsOnWeekends && isWeekend) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const fromMinutes = parseMinutesFromTimeValue(fromTime);
|
||||
const toMinutes = parseMinutesFromTimeValue(toTime);
|
||||
const isInsideWindow = isTimeInsideScheduleWindow(now, fromMinutes, toMinutes);
|
||||
|
||||
return !isInsideWindow;
|
||||
}
|
||||
|
||||
type MultiInputValue = {
|
||||
label: string;
|
||||
|
|
@ -67,6 +129,10 @@ type State = {
|
|||
autoResponderActive: boolean;
|
||||
autoResponderMessage: UserNotifyProps['auto_responder_message'];
|
||||
notifyCommentsLevel: UserNotifyProps['comments'];
|
||||
dndScheduleEnabled: boolean;
|
||||
dndScheduleFromTime: string;
|
||||
dndScheduleToTime: string;
|
||||
dndAllowNotificationsOnWeekends: boolean;
|
||||
isSaving: boolean;
|
||||
serverError: string;
|
||||
desktopAndMobileSettingsDifferent: boolean;
|
||||
|
|
@ -90,6 +156,10 @@ function getDefaultStateFromProps(props: Props): State {
|
|||
id: 'user.settings.notifications.autoResponderDefault',
|
||||
defaultMessage: 'Hello, I am out of office and unable to respond to messages.',
|
||||
});
|
||||
let dndScheduleEnabled = false;
|
||||
let dndScheduleFromTime = '09:00';
|
||||
let dndScheduleToTime = '17:00';
|
||||
let dndAllowNotificationsOnWeekends = false;
|
||||
let desktopAndMobileSettingsDifferent = true;
|
||||
|
||||
if (props.user.notify_props) {
|
||||
|
|
@ -138,6 +208,13 @@ function getDefaultStateFromProps(props: Props): State {
|
|||
autoResponderMessage = props.user.notify_props.auto_responder_message;
|
||||
}
|
||||
|
||||
const notifyProps = props.user.notify_props as UserNotifyProps & Record<string, string | undefined>;
|
||||
|
||||
dndScheduleEnabled = notifyProps[DND_SCHEDULE_ENABLED_KEY] === 'true';
|
||||
dndScheduleFromTime = notifyProps[DND_SCHEDULE_FROM_TIME_KEY] || dndScheduleFromTime;
|
||||
dndScheduleToTime = notifyProps[DND_SCHEDULE_TO_TIME_KEY] || dndScheduleToTime;
|
||||
dndAllowNotificationsOnWeekends = notifyProps[DND_SCHEDULE_ALLOW_WEEKENDS_KEY] === 'true';
|
||||
|
||||
if (props.user.notify_props.desktop && props.user.notify_props.push) {
|
||||
desktopAndMobileSettingsDifferent = areDesktopAndMobileSettingsDifferent(props.user.notify_props.desktop, props.user.notify_props.push, props.user.notify_props?.desktop_threads, props.user.notify_props?.push_threads, props.isCollapsedThreadsEnabled);
|
||||
}
|
||||
|
|
@ -207,6 +284,10 @@ function getDefaultStateFromProps(props: Props): State {
|
|||
autoResponderActive,
|
||||
autoResponderMessage,
|
||||
notifyCommentsLevel: comments,
|
||||
dndScheduleEnabled,
|
||||
dndScheduleFromTime,
|
||||
dndScheduleToTime,
|
||||
dndAllowNotificationsOnWeekends,
|
||||
isSaving: false,
|
||||
serverError: '',
|
||||
desktopAndMobileSettingsDifferent,
|
||||
|
|
@ -253,6 +334,12 @@ class NotificationsTab extends React.PureComponent<Props, State> {
|
|||
data.first_name = this.state.firstNameKey ? 'true' : 'false';
|
||||
data.channel = this.state.channelKey ? 'true' : 'false';
|
||||
|
||||
const notifyData = data as UserNotifyProps & Record<string, string>;
|
||||
notifyData[DND_SCHEDULE_ENABLED_KEY] = this.state.dndScheduleEnabled ? 'true' : 'false';
|
||||
notifyData[DND_SCHEDULE_FROM_TIME_KEY] = this.state.dndScheduleFromTime;
|
||||
notifyData[DND_SCHEDULE_TO_TIME_KEY] = this.state.dndScheduleToTime;
|
||||
notifyData[DND_SCHEDULE_ALLOW_WEEKENDS_KEY] = this.state.dndAllowNotificationsOnWeekends ? 'true' : 'false';
|
||||
|
||||
if (this.state.desktopAndMobileSettingsDifferent) {
|
||||
data.push = this.state.pushActivity;
|
||||
data.push_threads = this.state.pushThreads;
|
||||
|
|
@ -487,6 +574,71 @@ class NotificationsTab extends React.PureComponent<Props, State> {
|
|||
this.props.closeModal();
|
||||
};
|
||||
|
||||
handleChangeForDndScheduleEnabled = async (event: ChangeEvent<HTMLInputElement>) => {
|
||||
const {target: {checked}} = event;
|
||||
this.setState({dndScheduleEnabled: checked});
|
||||
|
||||
if (checked) {
|
||||
await this.applyTimedDndFromSchedule();
|
||||
}
|
||||
};
|
||||
|
||||
handleChangeForDndScheduleFromTime = (event: ChangeEvent<HTMLInputElement>) => {
|
||||
this.setState({dndScheduleFromTime: event.target.value});
|
||||
};
|
||||
|
||||
handleChangeForDndScheduleToTime = (event: ChangeEvent<HTMLInputElement>) => {
|
||||
this.setState({dndScheduleToTime: event.target.value});
|
||||
};
|
||||
|
||||
handleChangeForDndAllowNotificationsOnWeekends = (event: ChangeEvent<HTMLInputElement>) => {
|
||||
const {target: {checked}} = event;
|
||||
this.setState({dndAllowNotificationsOnWeekends: checked});
|
||||
};
|
||||
|
||||
getNextDndEndDate = (now: Date, toMinutes: number): Date => {
|
||||
const endDate = new Date(now);
|
||||
endDate.setSeconds(0, 0);
|
||||
endDate.setHours(Math.floor(toMinutes / 60), toMinutes % 60, 0, 0);
|
||||
|
||||
if (endDate <= now) {
|
||||
endDate.setDate(endDate.getDate() + 1);
|
||||
}
|
||||
|
||||
return endDate;
|
||||
};
|
||||
|
||||
applyTimedDndFromSchedule = async () => {
|
||||
const now = new Date();
|
||||
const shouldSilence = shouldSilenceForDndSchedule({
|
||||
isScheduleEnabled: this.state.dndScheduleEnabled,
|
||||
allowNotificationsOnWeekends: this.state.dndAllowNotificationsOnWeekends,
|
||||
fromTime: this.state.dndScheduleFromTime,
|
||||
toTime: this.state.dndScheduleToTime,
|
||||
now,
|
||||
});
|
||||
|
||||
if (!shouldSilence) {
|
||||
return;
|
||||
}
|
||||
|
||||
const fromMinutes = parseMinutesFromTimeValue(this.state.dndScheduleFromTime);
|
||||
|
||||
const endDate = this.getNextDndEndDate(now, fromMinutes);
|
||||
|
||||
const result = await this.props.setStatus({
|
||||
user_id: this.props.user.id,
|
||||
status: Constants.UserStatuses.DND,
|
||||
dnd_end_time: toUTCUnixInSeconds(endDate),
|
||||
manual: true,
|
||||
last_activity_at: toUTCUnixInSeconds(now),
|
||||
});
|
||||
|
||||
if (result.error) {
|
||||
this.setState({serverError: result.error.message});
|
||||
}
|
||||
};
|
||||
|
||||
createKeywordsWithNotificationSection = () => {
|
||||
const serverError = this.state.serverError;
|
||||
const user = this.props.user;
|
||||
|
|
@ -975,11 +1127,132 @@ class NotificationsTab extends React.PureComponent<Props, State> {
|
|||
);
|
||||
};
|
||||
|
||||
createDoNotDisturbScheduleSection = () => {
|
||||
const isSectionExpanded = this.props.activeSection === DO_NOT_DISTURB_SCHEDULE_SECTION;
|
||||
const serverError = this.state.serverError;
|
||||
|
||||
let max = null;
|
||||
if (isSectionExpanded) {
|
||||
const inputs = (
|
||||
<fieldset>
|
||||
<legend className='form-legend hidden-label'>
|
||||
<FormattedMessage
|
||||
id='user.settings.notifications.dndSchedule.title'
|
||||
defaultMessage='Do not disturb schedule'
|
||||
/>
|
||||
</legend>
|
||||
<div className='setting-list__hint pb-3'>
|
||||
<FormattedMessage
|
||||
id='user.settings.notifications.dndSchedule.description'
|
||||
defaultMessage='Configure when notifications are silenced outside your working hours. (Skeleton only)'
|
||||
/>
|
||||
</div>
|
||||
<div className='checkbox'>
|
||||
<label>
|
||||
<input
|
||||
id='notificationDndScheduleAllowNotifications'
|
||||
type='checkbox'
|
||||
checked={this.state.dndScheduleEnabled}
|
||||
onChange={this.handleChangeForDndScheduleEnabled}
|
||||
/>
|
||||
<FormattedMessage
|
||||
id='user.settings.notifications.dndSchedule.allowNotifications'
|
||||
defaultMessage='Allow notifications'
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div className='mt-4'>
|
||||
<label htmlFor='notificationDndScheduleFromTime'>
|
||||
<FormattedMessage
|
||||
id='user.settings.notifications.dndSchedule.fromTime'
|
||||
defaultMessage='From'
|
||||
/>
|
||||
</label>
|
||||
<input
|
||||
id='notificationDndScheduleFromTime'
|
||||
type='time'
|
||||
className='form-control'
|
||||
value={this.state.dndScheduleFromTime}
|
||||
onChange={this.handleChangeForDndScheduleFromTime}
|
||||
disabled={!this.state.dndScheduleEnabled}
|
||||
/>
|
||||
</div>
|
||||
<div className='mt-4'>
|
||||
<label htmlFor='notificationDndScheduleToTime'>
|
||||
<FormattedMessage
|
||||
id='user.settings.notifications.dndSchedule.toTime'
|
||||
defaultMessage='To'
|
||||
/>
|
||||
</label>
|
||||
<input
|
||||
id='notificationDndScheduleToTime'
|
||||
type='time'
|
||||
className='form-control'
|
||||
value={this.state.dndScheduleToTime}
|
||||
onChange={this.handleChangeForDndScheduleToTime}
|
||||
disabled={!this.state.dndScheduleEnabled}
|
||||
/>
|
||||
</div>
|
||||
<div className='checkbox mt-4'>
|
||||
<label>
|
||||
<input
|
||||
id='notificationDndScheduleAllowNotificationsOnWeekends'
|
||||
type='checkbox'
|
||||
checked={this.state.dndAllowNotificationsOnWeekends}
|
||||
onChange={this.handleChangeForDndAllowNotificationsOnWeekends}
|
||||
disabled={!this.state.dndScheduleEnabled}
|
||||
/>
|
||||
<FormattedMessage
|
||||
id='user.settings.notifications.dndSchedule.allowNotificationsOnWeekends'
|
||||
defaultMessage='Allow notifications on weekends'
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</fieldset>
|
||||
);
|
||||
|
||||
max = (
|
||||
<SettingItemMax
|
||||
title={this.props.intl.formatMessage({
|
||||
id: 'user.settings.notifications.dndSchedule.title',
|
||||
defaultMessage: 'Do not disturb schedule',
|
||||
})}
|
||||
inputs={inputs}
|
||||
submit={this.handleSubmit}
|
||||
saving={this.state.isSaving}
|
||||
serverError={serverError}
|
||||
updateSection={this.handleUpdateSection}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<SettingItem
|
||||
title={this.props.intl.formatMessage({
|
||||
id: 'user.settings.notifications.dndSchedule.title',
|
||||
defaultMessage: 'Do not disturb schedule',
|
||||
})}
|
||||
active={isSectionExpanded}
|
||||
describe={this.props.intl.formatMessage({
|
||||
id: this.state.dndScheduleEnabled ?
|
||||
'user.settings.notifications.dndSchedule.enabled' :
|
||||
'user.settings.notifications.dndSchedule.disabled',
|
||||
defaultMessage: this.state.dndScheduleEnabled ? 'Enabled' : 'Disabled',
|
||||
})}
|
||||
section={DO_NOT_DISTURB_SCHEDULE_SECTION}
|
||||
updateSection={this.handleUpdateSection}
|
||||
max={max}
|
||||
areAllSectionsInactive={this.props.activeSection === ''}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const keywordsWithNotificationSection = this.createKeywordsWithNotificationSection();
|
||||
const keywordsWithHighlightSection = this.createKeywordsWithHighlightSection();
|
||||
const commentsSection = this.createCommentsSection();
|
||||
const autoResponderSection = this.createAutoResponderSection();
|
||||
const doNotDisturbScheduleSection = this.createDoNotDisturbScheduleSection();
|
||||
|
||||
const areAllSectionsInactive = this.props.activeSection === '';
|
||||
|
||||
|
|
@ -1080,6 +1353,8 @@ class NotificationsTab extends React.PureComponent<Props, State> {
|
|||
threads={this.state.emailThreads || ''}
|
||||
/>
|
||||
<div className='divider-light'/>
|
||||
{doNotDisturbScheduleSection}
|
||||
<div className='divider-light'/>
|
||||
{keywordsWithNotificationSection}
|
||||
{(!this.props.isEnterpriseOrCloudOrSKUStarterFree && this.props.isEnterpriseReady) && (
|
||||
<>
|
||||
|
|
|
|||
Loading…
Reference in a new issue