|
|
@@ -1,16 +1,18 @@
|
|
|
-import React, { useCallback, useState } from 'react';
|
|
|
+import React, {
|
|
|
+ useCallback, useMemo, useEffect, useState,
|
|
|
+} from 'react';
|
|
|
|
|
|
import { useTranslation } from 'next-i18next';
|
|
|
-import PropTypes from 'prop-types';
|
|
|
+import { useRouter } from 'next/router';
|
|
|
|
|
|
-import AdminNotificationContainer from '~/client/services/AdminNotificationContainer';
|
|
|
+import { NotifyType, TriggerEventType } from '~/client/interfaces/global-notification';
|
|
|
import { toastError } from '~/client/util/apiNotification';
|
|
|
-import { apiv3Post, apiv3Put } from '~/client/util/apiv3-client';
|
|
|
+import { apiv3Post } from '~/client/util/apiv3-client';
|
|
|
import { useIsMailerSetup } from '~/stores/context';
|
|
|
+import { useSWRxGlobalNotification } from '~/stores/global-notification';
|
|
|
import loggerFactory from '~/utils/logger';
|
|
|
|
|
|
|
|
|
-import { withUnstatedContainers } from '../../UnstatedUtils';
|
|
|
import AdminUpdateButtonRow from '../Common/AdminUpdateButtonRow';
|
|
|
|
|
|
import TriggerEventCheckBox from './TriggerEventCheckBox';
|
|
|
@@ -18,18 +20,50 @@ import TriggerEventCheckBox from './TriggerEventCheckBox';
|
|
|
|
|
|
const logger = loggerFactory('growi:manageGlobalNotification');
|
|
|
|
|
|
-const ManageGlobalNotification = (props) => {
|
|
|
|
|
|
- let globalNotification;
|
|
|
- // TODO: securely fetch the data of globalNotification variable without using swig. URL https://redmine.weseek.co.jp/issues/103901
|
|
|
- // globalNotification = JSON.parse(document.getElementById('admin-global-notification-setting').getAttribute('data-global-notification'));
|
|
|
+type Props = {
|
|
|
+ globalNotificationId?: string,
|
|
|
+}
|
|
|
+
|
|
|
+const ManageGlobalNotification = (props: Props): JSX.Element => {
|
|
|
|
|
|
- const [globalNotificationId, setGlobalNotificationId] = useState(null);
|
|
|
const [triggerPath, setTriggerPath] = useState('');
|
|
|
- const [notifyToType, setNotifyToType] = useState('mail');
|
|
|
+ const [notifyType, setNotifyType] = useState<NotifyType>(NotifyType.Email);
|
|
|
const [emailToSend, setEmailToSend] = useState('');
|
|
|
const [slackChannelToSend, setSlackChannelToSend] = useState('');
|
|
|
- const [triggerEvents, setTriggerEvents] = useState(new Set(globalNotification?.triggerEvents));
|
|
|
+ const [triggerEvents, setTriggerEvents] = useState(new Set());
|
|
|
+ const { data: globalNotificationData, update: updateGlobalNotification } = useSWRxGlobalNotification(props.globalNotificationId || '');
|
|
|
+ const globalNotification = useMemo(() => globalNotificationData?.globalNotification, [globalNotificationData?.globalNotification]);
|
|
|
+
|
|
|
+ const router = useRouter();
|
|
|
+
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ if (globalNotification != null) {
|
|
|
+ const notifyType = globalNotification.__t;
|
|
|
+ setNotifyType(notifyType);
|
|
|
+
|
|
|
+ setTriggerPath(globalNotification.triggerPath);
|
|
|
+ setTriggerEvents(new Set(globalNotification.triggerEvents));
|
|
|
+
|
|
|
+ if (notifyType === NotifyType.Email) {
|
|
|
+ setEmailToSend(globalNotification.toEmail);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ setSlackChannelToSend(globalNotification.slackChannels);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, [globalNotification]);
|
|
|
+
|
|
|
+ const isLoading = globalNotificationData === undefined;
|
|
|
+ const notExistsGlobalNotification = !isLoading && globalNotificationData == null;
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ if (notExistsGlobalNotification) {
|
|
|
+ router.push('/admin/notification');
|
|
|
+ }
|
|
|
+ }, [notExistsGlobalNotification, router]);
|
|
|
+
|
|
|
|
|
|
const onChangeTriggerEvents = useCallback((triggerEvent) => {
|
|
|
let newTriggerEvents;
|
|
|
@@ -44,32 +78,34 @@ const ManageGlobalNotification = (props) => {
|
|
|
}
|
|
|
}, [triggerEvents]);
|
|
|
|
|
|
- const updateButtonClickedHandler = useCallback(async() => {
|
|
|
|
|
|
+ const updateButtonClickedHandler = useCallback(async() => {
|
|
|
const requestParams = {
|
|
|
triggerPath,
|
|
|
- notifyToType,
|
|
|
+ notifyType,
|
|
|
toEmail: emailToSend,
|
|
|
slackChannels: slackChannelToSend,
|
|
|
triggerEvents: [...triggerEvents],
|
|
|
};
|
|
|
|
|
|
try {
|
|
|
- if (globalNotificationId != null) {
|
|
|
- await apiv3Put(`/notification-setting/global-notification/${globalNotificationId}`, requestParams);
|
|
|
+ if (props.globalNotificationId != null) {
|
|
|
+ await updateGlobalNotification(requestParams);
|
|
|
+ router.push('/admin/notification');
|
|
|
}
|
|
|
else {
|
|
|
await apiv3Post('/notification-setting/global-notification', requestParams);
|
|
|
+ router.push('/admin/notification');
|
|
|
}
|
|
|
}
|
|
|
catch (err) {
|
|
|
toastError(err);
|
|
|
logger.error(err);
|
|
|
}
|
|
|
- }, [emailToSend, globalNotificationId, notifyToType, slackChannelToSend, triggerEvents, triggerPath]);
|
|
|
+ }, [emailToSend, notifyType, props.globalNotificationId, router, slackChannelToSend, triggerEvents, triggerPath, updateGlobalNotification]);
|
|
|
+
|
|
|
|
|
|
const { data: isMailerSetup } = useIsMailerSetup();
|
|
|
- const { adminNotificationContainer } = props;
|
|
|
const { t } = useTranslation('admin');
|
|
|
|
|
|
return (
|
|
|
@@ -88,9 +124,11 @@ const ManageGlobalNotification = (props) => {
|
|
|
</div>
|
|
|
|
|
|
<div className="col-sm-4">
|
|
|
- <h3 htmlFor="triggerPath">{t('notification_settings.trigger_path')}
|
|
|
- {/* eslint-disable-next-line react/no-danger */}
|
|
|
- <small dangerouslySetInnerHTML={{ __html: t('notification_settings.trigger_path_help', '<code>*</code>') }} />
|
|
|
+ <h3>
|
|
|
+ <label htmlFor="triggerPath">{t('notification_settings.trigger_path')}
|
|
|
+ {/* eslint-disable-next-line react/no-danger */}
|
|
|
+ <small dangerouslySetInnerHTML={{ __html: t('notification_settings.trigger_path_help', '<code>*</code>') }} />
|
|
|
+ </label>
|
|
|
</h3>
|
|
|
<div className="form-group">
|
|
|
<input
|
|
|
@@ -110,10 +148,10 @@ const ManageGlobalNotification = (props) => {
|
|
|
className="custom-control-input"
|
|
|
type="radio"
|
|
|
id="mail"
|
|
|
- name="notifyToType"
|
|
|
+ name="notifyType"
|
|
|
value="mail"
|
|
|
- checked={notifyToType === 'mail'}
|
|
|
- onChange={() => { setNotifyToType('mail') }}
|
|
|
+ checked={notifyType === NotifyType.Email}
|
|
|
+ onChange={() => { setNotifyType(NotifyType.Email) }}
|
|
|
/>
|
|
|
<label className="custom-control-label" htmlFor="mail">
|
|
|
<p className="font-weight-bold">Email</p>
|
|
|
@@ -124,10 +162,10 @@ const ManageGlobalNotification = (props) => {
|
|
|
className="custom-control-input"
|
|
|
type="radio"
|
|
|
id="slack"
|
|
|
- name="notifyToType"
|
|
|
+ name="notifyType"
|
|
|
value="slack"
|
|
|
- checked={notifyToType === 'slack'}
|
|
|
- onChange={() => { setNotifyToType('slack') }}
|
|
|
+ checked={notifyType === NotifyType.SLACK}
|
|
|
+ onChange={() => { setNotifyType(NotifyType.SLACK) }}
|
|
|
/>
|
|
|
<label className="custom-control-label" htmlFor="slack">
|
|
|
<p className="font-weight-bold">Slack</p>
|
|
|
@@ -135,7 +173,7 @@ const ManageGlobalNotification = (props) => {
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- {notifyToType === 'mail'
|
|
|
+ {notifyType === NotifyType.Email
|
|
|
? (
|
|
|
<>
|
|
|
<div className="input-group notify-to-option" id="mail-input">
|
|
|
@@ -194,9 +232,9 @@ const ManageGlobalNotification = (props) => {
|
|
|
<div className="my-1">
|
|
|
<TriggerEventCheckBox
|
|
|
checkbox="success"
|
|
|
- event="pageCreate"
|
|
|
- checked={triggerEvents.has('pageCreate')}
|
|
|
- onChange={() => onChangeTriggerEvents('pageCreate')}
|
|
|
+ event={TriggerEventType.CREATE}
|
|
|
+ checked={triggerEvents.has(TriggerEventType.CREATE)}
|
|
|
+ onChange={() => onChangeTriggerEvents(TriggerEventType.CREATE)}
|
|
|
>
|
|
|
<span className="badge badge-pill badge-success">
|
|
|
<i className="icon-doc mr-1" /> CREATE
|
|
|
@@ -206,9 +244,9 @@ const ManageGlobalNotification = (props) => {
|
|
|
<div className="my-1">
|
|
|
<TriggerEventCheckBox
|
|
|
checkbox="warning"
|
|
|
- event="pageEdit"
|
|
|
- checked={triggerEvents.has('pageEdit')}
|
|
|
- onChange={() => onChangeTriggerEvents('pageEdit')}
|
|
|
+ event={TriggerEventType.EDIT}
|
|
|
+ checked={triggerEvents.has(TriggerEventType.EDIT)}
|
|
|
+ onChange={() => onChangeTriggerEvents(TriggerEventType.EDIT)}
|
|
|
>
|
|
|
<span className="badge badge-pill badge-warning">
|
|
|
<i className="icon-pencil mr-1" />EDIT
|
|
|
@@ -218,9 +256,9 @@ const ManageGlobalNotification = (props) => {
|
|
|
<div className="my-1">
|
|
|
<TriggerEventCheckBox
|
|
|
checkbox="pink"
|
|
|
- event="pageMove"
|
|
|
- checked={triggerEvents.has('pageMove')}
|
|
|
- onChange={() => onChangeTriggerEvents('pageMove')}
|
|
|
+ event={TriggerEventType.MOVE}
|
|
|
+ checked={triggerEvents.has(TriggerEventType.MOVE)}
|
|
|
+ onChange={() => onChangeTriggerEvents(TriggerEventType.MOVE)}
|
|
|
>
|
|
|
<span className="badge badge-pill badge-pink">
|
|
|
<i className="icon-action-redo mr-1" />MOVE
|
|
|
@@ -231,8 +269,8 @@ const ManageGlobalNotification = (props) => {
|
|
|
<TriggerEventCheckBox
|
|
|
checkbox="danger"
|
|
|
event="pageDelete"
|
|
|
- checked={triggerEvents.has('pageDelete')}
|
|
|
- onChange={() => onChangeTriggerEvents('pageDelete')}
|
|
|
+ checked={triggerEvents.has(TriggerEventType.DELETE)}
|
|
|
+ onChange={() => onChangeTriggerEvents(TriggerEventType.DELETE)}
|
|
|
>
|
|
|
<span className="badge badge-pill badge-danger">
|
|
|
<i className="icon-fire mr-1" />DELETE
|
|
|
@@ -242,9 +280,9 @@ const ManageGlobalNotification = (props) => {
|
|
|
<div className="my-1">
|
|
|
<TriggerEventCheckBox
|
|
|
checkbox="info"
|
|
|
- event="pageLike"
|
|
|
- checked={triggerEvents.has('pageLike')}
|
|
|
- onChange={() => onChangeTriggerEvents('pageLike')}
|
|
|
+ event={TriggerEventType.LIKE}
|
|
|
+ checked={triggerEvents.has(TriggerEventType.LIKE)}
|
|
|
+ onChange={() => onChangeTriggerEvents(TriggerEventType.LIKE)}
|
|
|
>
|
|
|
<span className="badge badge-pill badge-info">
|
|
|
<i className="fa fa-heart-o mr-1" />LIKE
|
|
|
@@ -254,9 +292,9 @@ const ManageGlobalNotification = (props) => {
|
|
|
<div className="my-1">
|
|
|
<TriggerEventCheckBox
|
|
|
checkbox="secondary"
|
|
|
- event="comment"
|
|
|
- checked={triggerEvents.has('comment')}
|
|
|
- onChange={() => onChangeTriggerEvents('comment')}
|
|
|
+ event={TriggerEventType.POST}
|
|
|
+ checked={triggerEvents.has(TriggerEventType.POST)}
|
|
|
+ onChange={() => onChangeTriggerEvents(TriggerEventType.POST)}
|
|
|
>
|
|
|
<span className="badge badge-pill badge-secondary">
|
|
|
<i className="icon-bubble mr-1" />POST
|
|
|
@@ -270,17 +308,10 @@ const ManageGlobalNotification = (props) => {
|
|
|
|
|
|
<AdminUpdateButtonRow
|
|
|
onClick={updateButtonClickedHandler}
|
|
|
- disabled={adminNotificationContainer.state.retrieveError != null}
|
|
|
+ disabled={false}
|
|
|
/>
|
|
|
</>
|
|
|
);
|
|
|
};
|
|
|
|
|
|
-ManageGlobalNotification.propTypes = {
|
|
|
- adminNotificationContainer: PropTypes.instanceOf(AdminNotificationContainer).isRequired,
|
|
|
-};
|
|
|
-
|
|
|
-const ManageGlobalNotificationWrapper = withUnstatedContainers(ManageGlobalNotification, [AdminNotificationContainer]);
|
|
|
-
|
|
|
-
|
|
|
-export default ManageGlobalNotificationWrapper;
|
|
|
+export default ManageGlobalNotification;
|