Просмотр исходного кода

Merge pull request #5911 from weseek/fix/slack-channels-are-not-automatically-filled-after-setting-user-trigger-notification

fix: Slack channels are not automatically filled after setting up user trigger notification on v5.0.x
cao 3 лет назад
Родитель
Сommit
80e9069d82

+ 0 - 4
packages/app/src/client/services/CommentContainer.js

@@ -30,10 +30,6 @@ export default class CommentContainer extends Container {
 
     this.state = {
       comments: [],
-
-      // settings shared among all of CommentEditor
-      isSlackEnabled: false,
-      slackChannels: mainContent.getAttribute('data-slack-channels') || '',
     };
 
     this.retrieveComments = this.retrieveComments.bind(this);

+ 1 - 3
packages/app/src/client/services/ContextExtractor.tsx

@@ -16,7 +16,7 @@ import {
   useIsDeleted, useIsNotCreatable, useIsTrashPage, useIsUserPage, useLastUpdateUsername,
   useCurrentPageId, usePageIdOnHackmd, usePageUser, useCurrentPagePath, useRevisionCreatedAt, useRevisionId, useRevisionIdHackmdSynced,
   useShareLinkId, useShareLinksNumber, useTemplateTagData, useCurrentUpdatedAt, useCreator, useRevisionAuthor, useCurrentUser, useTargetAndAncestors,
-  useSlackChannels, useNotFoundTargetPathOrId, useIsSearchPage, useIsForbidden, useIsIdenticalPath, useHasParent,
+  useNotFoundTargetPathOrId, useIsSearchPage, useIsForbidden, useIsIdenticalPath, useHasParent,
   useIsAclEnabled, useIsSearchServiceConfigured, useIsSearchServiceReachable, useIsEnabledAttachTitleHeader, useIsNotFoundPermalink,
   useDefaultIndentSize, useIsIndentSizeForced,
 } from '../../stores/context';
@@ -85,7 +85,6 @@ const ContextExtractorOnce: FC = () => {
   const targetAndAncestors = JSON.parse(document.getElementById('growi-pagetree-target-and-ancestors')?.textContent || jsonNull);
   const notFoundTargetPathOrId = JSON.parse(notFoundContentForPt?.getAttribute('data-not-found-target-path-or-id') || jsonNull);
   const isNotFoundPermalink = JSON.parse(notFoundContent?.getAttribute('data-is-not-found-permalink') || jsonNull);
-  const slackChannels = mainContent?.getAttribute('data-slack-channels') || '';
   const isSearchPage = document.getElementById('search-page') != null;
 
   const grant = +(mainContent?.getAttribute('data-page-grant') || 1);
@@ -158,7 +157,6 @@ const ContextExtractorOnce: FC = () => {
   useIsDeviceSmallerThanMd();
 
   // Editor
-  useSlackChannels(slackChannels);
   useSelectedGrant(grant);
   useSelectedGrantGroupId(grantGroupId);
   useSelectedGrantGroupName(grantGroupName);

+ 5 - 4
packages/app/src/components/Page.jsx

@@ -9,9 +9,9 @@ import EditorContainer from '~/client/services/EditorContainer';
 import PageContainer from '~/client/services/PageContainer';
 import { getOptionsToSave } from '~/client/util/editor';
 import {
-  useCurrentPagePath, useIsGuestUser, useSlackChannels,
+  useCurrentPagePath, useIsGuestUser,
 } from '~/stores/context';
-import { useIsSlackEnabled } from '~/stores/editor';
+import { useSWRxSlackChannels, useIsSlackEnabled } from '~/stores/editor';
 import {
   useEditorMode, useIsMobile, useSelectedGrant, useSelectedGrantGroupId, useSelectedGrantGroupName,
 } from '~/stores/ui';
@@ -187,8 +187,8 @@ const PageWrapper = (props) => {
   const { data: editorMode } = useEditorMode();
   const { data: isGuestUser } = useIsGuestUser();
   const { data: isMobile } = useIsMobile();
+  const { data: slackChannelsData } = useSWRxSlackChannels(currentPagePath);
   const { data: isSlackEnabled } = useIsSlackEnabled();
-  const { data: slackChannels } = useSlackChannels();
   const { data: grant } = useSelectedGrant();
   const { data: grantGroupId } = useSelectedGrantGroupId();
   const { data: grantGroupName } = useSelectedGrantGroupName();
@@ -227,6 +227,7 @@ const PageWrapper = (props) => {
     return null;
   }
 
+
   return (
     <Page
       {...props}
@@ -236,7 +237,7 @@ const PageWrapper = (props) => {
       isGuestUser={isGuestUser}
       isMobile={isMobile}
       isSlackEnabled={isSlackEnabled}
-      slackChannels={slackChannels}
+      slackChannels={slackChannelsData.toString()}
       grant={grant}
       grantGroupId={grantGroupId}
       grantGroupName={grantGroupName}

+ 4 - 5
packages/app/src/components/Page/DisplaySwitcher.tsx

@@ -33,13 +33,12 @@ const { isTopPage } = pagePathUtils;
 const DisplaySwitcher = (): JSX.Element => {
   const { t } = useTranslation();
 
-
   // get element for smoothScroll
   const getCommentListDom = useMemo(() => { return document.getElementById('page-comments-list') }, []);
 
 
   const { data: currentPageId } = useCurrentPageId();
-  const { data: currentPath } = useCurrentPagePath();
+  const { data: currentPagePath } = useCurrentPagePath();
   const { data: isSharedUser } = useIsSharedUser();
   const { data: shareLinkId } = useShareLinkId();
   const { data: isUserPage } = useIsUserPage();
@@ -53,7 +52,7 @@ const DisplaySwitcher = (): JSX.Element => {
 
   const isPageExist = currentPageId != null;
   const isViewMode = editorMode === EditorMode.View;
-  const isTopPagePath = isTopPage(currentPath ?? '');
+  const isTopPagePath = isTopPage(currentPagePath ?? '');
 
   return (
     <>
@@ -67,11 +66,11 @@ const DisplaySwitcher = (): JSX.Element => {
 
                   {/* Page list */}
                   <div className="grw-page-accessories-control">
-                    { currentPath != null && !isSharedUser && (
+                    { currentPagePath != null && !isSharedUser && (
                       <button
                         type="button"
                         className="btn btn-block btn-outline-secondary grw-btn-page-accessories rounded-pill d-flex justify-content-between align-items-center"
-                        onClick={() => openDescendantPageListModal(currentPath)}
+                        onClick={() => openDescendantPageListModal(currentPagePath)}
                       >
                         <div className="grw-page-accessories-control-icon">
                           <PageListIcon />

+ 31 - 10
packages/app/src/components/PageComment/CommentEditor.jsx

@@ -13,7 +13,8 @@ import CommentContainer from '~/client/services/CommentContainer';
 import EditorContainer from '~/client/services/EditorContainer';
 import PageContainer from '~/client/services/PageContainer';
 import GrowiRenderer from '~/client/util/GrowiRenderer';
-import { useCurrentUser } from '~/stores/context';
+import { useCurrentPagePath, useCurrentUser } from '~/stores/context';
+import { useSWRxSlackChannels, useIsSlackEnabled } from '~/stores/editor';
 import { useIsMobile } from '~/stores/ui';
 
 import { CustomNavTab } from '../CustomNavigation/CustomNav';
@@ -64,6 +65,7 @@ class CommentEditor extends React.Component {
       isUploadableFile,
       errorMessage: undefined,
       isSlackConfigured: config.isSlackConfigured,
+      slackChannels: this.props.slackChannels,
     };
 
     this.updateState = this.updateState.bind(this);
@@ -77,8 +79,8 @@ class CommentEditor extends React.Component {
 
     this.renderHtml = this.renderHtml.bind(this);
     this.handleSelect = this.handleSelect.bind(this);
-    this.onSlackEnabledFlagChange = this.onSlackEnabledFlagChange.bind(this);
     this.onSlackChannelsChange = this.onSlackChannelsChange.bind(this);
+    this.fetchSlackChannels = this.fetchSlackChannels.bind(this);
   }
 
   updateState(value) {
@@ -97,12 +99,18 @@ class CommentEditor extends React.Component {
     this.renderHtml(this.state.comment);
   }
 
-  onSlackEnabledFlagChange(isSlackEnabled) {
-    this.props.commentContainer.setState({ isSlackEnabled });
+  fetchSlackChannels(slackChannels) {
+    this.setState({ slackChannels });
+  }
+
+  componentDidUpdate(prevProps) {
+    if (this.props.slackChannels !== prevProps.slackChannels) {
+      this.fetchSlackChannels(this.props.slackChannels);
+    }
   }
 
   onSlackChannelsChange(slackChannels) {
-    this.props.commentContainer.setState({ slackChannels });
+    this.setState({ slackChannels });
   }
 
   initializeEditor() {
@@ -165,8 +173,8 @@ class CommentEditor extends React.Component {
           this.state.comment,
           this.state.isMarkdown,
           replyTo,
-          commentContainer.state.isSlackEnabled,
-          commentContainer.state.slackChannels,
+          this.props.isSlackEnabled,
+          this.state.slackChannels,
         );
       }
       this.initializeEditor();
@@ -358,9 +366,9 @@ class CommentEditor extends React.Component {
               && (
                 <div className="form-inline align-self-center mr-md-2">
                   <SlackNotification
-                    isSlackEnabled={commentContainer.state.isSlackEnabled}
-                    slackChannels={commentContainer.state.slackChannels}
-                    onEnabledFlagChange={this.onSlackEnabledFlagChange}
+                    isSlackEnabled={this.props.isSlackEnabled}
+                    slackChannels={this.state.slackChannels}
+                    onEnabledFlagChange={this.props.onSlackEnabledFlagChange}
                     onChannelChange={this.onSlackChannelsChange}
                     id="idForComment"
                   />
@@ -416,6 +424,8 @@ CommentEditor.propTypes = {
   editorContainer: PropTypes.instanceOf(EditorContainer).isRequired,
   commentContainer: PropTypes.instanceOf(CommentContainer).isRequired,
 
+  slackChannels: PropTypes.string.isRequired,
+  isSlackEnabled: PropTypes.bool.isRequired,
   growiRenderer: PropTypes.instanceOf(GrowiRenderer).isRequired,
   currentUser: PropTypes.instanceOf(Object),
   isMobile: PropTypes.bool,
@@ -426,15 +436,26 @@ CommentEditor.propTypes = {
   commentCreator: PropTypes.string,
   onCancelButtonClicked: PropTypes.func,
   onCommentButtonClicked: PropTypes.func,
+  onSlackEnabledFlagChange: PropTypes.func,
 };
 
 const CommentEditorWrapper = (props) => {
   const { data: isMobile } = useIsMobile();
   const { data: currentUser } = useCurrentUser();
+  const { data: isSlackEnabled, mutate: mutateIsSlackEnabled } = useIsSlackEnabled();
+  const { data: currentPagePath } = useCurrentPagePath();
+  const { data: slackChannelsData } = useSWRxSlackChannels(currentPagePath);
+
+  const onSlackEnabledFlagChange = (isSlackEnabled) => {
+    mutateIsSlackEnabled(isSlackEnabled, false);
+  };
 
   return (
     <CommentEditorHOCWrapper
       {...props}
+      onSlackEnabledFlagChange={onSlackEnabledFlagChange}
+      slackChannels={slackChannelsData.toString()}
+      isSlackEnabled={isSlackEnabled}
       currentUser={currentUser}
       isMobile={isMobile}
     />

+ 9 - 4
packages/app/src/components/PageEditor.tsx

@@ -13,8 +13,10 @@ import EditorContainer from '~/client/services/EditorContainer';
 import PageContainer from '~/client/services/PageContainer';
 import { apiGet, apiPost } from '~/client/util/apiv1-client';
 import { getOptionsToSave } from '~/client/util/editor';
-import { useIsEditable, useIsIndentSizeForced, useSlackChannels } from '~/stores/context';
-import { useCurrentIndentSize, useIsSlackEnabled, useIsTextlintEnabled } from '~/stores/editor';
+import { useIsEditable, useIsIndentSizeForced, useCurrentPagePath } from '~/stores/context';
+import {
+  useCurrentIndentSize, useSWRxSlackChannels, useIsSlackEnabled, useIsTextlintEnabled,
+} from '~/stores/editor';
 import {
   EditorMode,
   useEditorMode, useIsMobile, useSelectedGrant, useSelectedGrantGroupId, useSelectedGrantGroupName,
@@ -83,7 +85,8 @@ const PageEditor = (props: Props): JSX.Element => {
   const { data: editorMode } = useEditorMode();
   const { data: isMobile } = useIsMobile();
   const { data: isSlackEnabled } = useIsSlackEnabled();
-  const { data: slackChannels } = useSlackChannels();
+  const { data: currentPagePath } = useCurrentPagePath();
+  const { data: slackChannelsData } = useSWRxSlackChannels(currentPagePath);
   const { data: grant, mutate: mutateGrant } = useSelectedGrant();
   const { data: grantGroupId } = useSelectedGrantGroupId();
   const { data: grantGroupName } = useSelectedGrantGroupName();
@@ -117,6 +120,8 @@ const PageEditor = (props: Props): JSX.Element => {
       return;
     }
 
+    const slackChannels = slackChannelsData ? slackChannelsData.toString() : '';
+
     const optionsToSave = getOptionsToSave(isSlackEnabled ?? false, slackChannels, grant, grantGroupId, grantGroupName, editorContainer);
 
     try {
@@ -136,7 +141,7 @@ const PageEditor = (props: Props): JSX.Element => {
       logger.error('failed to save', error);
       pageContainer.showErrorToastr(error);
     }
-  }, [editorContainer, editorMode, grant, grantGroupId, grantGroupName, isSlackEnabled, markdown, pageContainer, slackChannels]);
+  }, [editorContainer, editorMode, grant, grantGroupId, grantGroupName, isSlackEnabled, slackChannelsData, markdown, pageContainer]);
 
 
   /**

+ 49 - 30
packages/app/src/components/PageEditor/EditorNavbarBottom.tsx

@@ -1,23 +1,24 @@
-import React, { useCallback, useState } from 'react';
-import PropTypes from 'prop-types';
+import React, { useCallback, useState, useEffect } from 'react';
 
+import PropTypes from 'prop-types';
 import { Collapse, Button } from 'reactstrap';
 
-import EditorContainer from '~/client/services/EditorContainer';
+
 import AppContainer from '~/client/services/AppContainer';
+import EditorContainer from '~/client/services/EditorContainer';
+import { useCurrentPagePath } from '~/stores/context';
+import { useSWRxSlackChannels, useIsSlackEnabled } from '~/stores/editor';
 import {
   EditorMode, useDrawerOpened, useEditorMode, useIsDeviceSmallerThanMd,
 } from '~/stores/ui';
 
-import { SlackNotification } from '../SlackNotification';
+import SavePageControls from '../SavePageControls';
 import SlackLogo from '../SlackLogo';
+import { SlackNotification } from '../SlackNotification';
 import { withUnstatedContainers } from '../UnstatedUtils';
 
-import SavePageControls from '../SavePageControls';
 
 import OptionsSelector from './OptionsSelector';
-import { useIsSlackEnabled } from '~/stores/editor';
-import { useSlackChannels } from '~/stores/context';
 
 const EditorNavbarBottom = (props) => {
 
@@ -30,17 +31,28 @@ const EditorNavbarBottom = (props) => {
 
   const { mutate: mutateDrawerOpened } = useDrawerOpened();
   const { data: isDeviceSmallerThanMd } = useIsDeviceSmallerThanMd();
-  const { data: isSlackEnabled, mutate: mutateIsSlackEnabled } = useIsSlackEnabled();
-  const { data: slackChannels, mutate: mutateSlackChannels } = useSlackChannels();
   const additionalClasses = ['grw-editor-navbar-bottom'];
+  const { data: currentPagePath } = useCurrentPagePath();
+  const { data: slackChannelsData } = useSWRxSlackChannels(currentPagePath);
+  const { data: isSlackEnabled, mutate: mutateIsSlackEnabled } = useIsSlackEnabled();
 
-  const isSlackEnabledToggleHandler = useCallback(
-    (bool: boolean) => mutateIsSlackEnabled(bool), [mutateIsSlackEnabled],
-  );
+  const [slackChannelsStr, setSlackChannelsStr] = useState<string>('');
+
+  useEffect(() => {
+    if (slackChannelsData != null) {
+      setSlackChannelsStr(slackChannelsData.toString());
+      mutateIsSlackEnabled(false);
+    }
+  }, [mutateIsSlackEnabled, slackChannelsData]);
+
+  const isSlackEnabledToggleHandler = (bool: boolean) => {
+    mutateIsSlackEnabled(bool, false);
+  };
+
+  const slackChannelsChangedHandler = useCallback((slackChannels: string) => {
+    setSlackChannelsStr(slackChannels);
+  }, []);
 
-  const slackChannelsChangedHandler = useCallback(
-    (slackChannels: string) => mutateSlackChannels(slackChannels), [mutateSlackChannels],
-  );
 
   const renderDrawerButton = () => (
     <button
@@ -73,13 +85,17 @@ const EditorNavbarBottom = (props) => {
       {isSlackConfigured && (
         <Collapse isOpen={isSlackExpanded && isDeviceSmallerThanMd === true}>
           <nav className={`navbar navbar-expand-lg border-top ${additionalClasses.join(' ')}`}>
-            <SlackNotification
-              isSlackEnabled={isSlackEnabled ?? false}
-              slackChannels={slackChannels}
-              onEnabledFlagChange={isSlackEnabledToggleHandler}
-              onChannelChange={slackChannelsChangedHandler}
-              id="idForEditorNavbarBottomForMobile"
-            />
+            {isSlackEnabled != null
+            && (
+              <SlackNotification
+                isSlackEnabled={isSlackEnabled}
+                slackChannels={slackChannelsStr}
+                onEnabledFlagChange={isSlackEnabledToggleHandler}
+                onChannelChange={slackChannelsChangedHandler}
+                id="idForEditorNavbarBottomForMobile"
+              />
+            )
+            }
           </nav>
         </Collapse>
       )
@@ -104,16 +120,19 @@ const EditorNavbarBottom = (props) => {
             </Button>
           ) : (
             <div className="mr-2">
-              <SlackNotification
-                isSlackEnabled={isSlackEnabled ?? false}
-                slackChannels={slackChannels}
-                onEnabledFlagChange={isSlackEnabledToggleHandler}
-                onChannelChange={slackChannelsChangedHandler}
-                id="idForEditorNavbarBottom"
-              />
+              {isSlackEnabled != null
+              && (
+                <SlackNotification
+                  isSlackEnabled={isSlackEnabled}
+                  slackChannels={slackChannelsStr}
+                  onEnabledFlagChange={isSlackEnabledToggleHandler}
+                  onChannelChange={slackChannelsChangedHandler}
+                  id="idForEditorNavbarBottom"
+                />
+              )}
             </div>
           ))}
-          <SavePageControls />
+          <SavePageControls slackChannels={slackChannelsStr} isSlackEnabled={isSlackEnabled || false} />
           { isCollapsedOptionsSelectorEnabled && renderExpandButton() }
         </form>
       </div>

+ 6 - 5
packages/app/src/components/PageEditorByHackmd.jsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { useState, useEffect } from 'react';
 
 import PropTypes from 'prop-types';
 import { withTranslation } from 'react-i18next';
@@ -9,8 +9,8 @@ import EditorContainer from '~/client/services/EditorContainer';
 import PageContainer from '~/client/services/PageContainer';
 import { apiPost } from '~/client/util/apiv1-client';
 import { getOptionsToSave } from '~/client/util/editor';
-import { useSlackChannels } from '~/stores/context';
-import { useIsSlackEnabled } from '~/stores/editor';
+import { useCurrentPagePath } from '~/stores/context';
+import { useSWRxSlackChannels, useIsSlackEnabled } from '~/stores/editor';
 import {
   useEditorMode, useSelectedGrant, useSelectedGrantGroupId, useSelectedGrantGroupName,
 } from '~/stores/ui';
@@ -431,8 +431,9 @@ const PageEditorByHackmdHOCWrapper = withUnstatedContainers(PageEditorByHackmd,
 
 const PageEditorByHackmdWrapper = (props) => {
   const { data: editorMode } = useEditorMode();
+  const { data: currentPagePath } = useCurrentPagePath();
+  const { data: slackChannelsData } = useSWRxSlackChannels(currentPagePath);
   const { data: isSlackEnabled } = useIsSlackEnabled();
-  const { data: slackChannels } = useSlackChannels();
   const { data: grant } = useSelectedGrant();
   const { data: grantGroupId } = useSelectedGrantGroupId();
   const { data: grantGroupName } = useSelectedGrantGroupName();
@@ -446,7 +447,7 @@ const PageEditorByHackmdWrapper = (props) => {
       {...props}
       editorMode={editorMode}
       isSlackEnabled={isSlackEnabled}
-      slackChannels={slackChannels}
+      slackChannels={slackChannelsData.toString()}
       grant={grant}
       grantGroupId={grantGroupId}
       grantGroupName={grantGroupName}

+ 7 - 14
packages/app/src/components/SavePageControls.jsx

@@ -1,30 +1,27 @@
 import React from 'react';
-import PropTypes from 'prop-types';
 
+import PropTypes from 'prop-types';
 import { withTranslation } from 'react-i18next';
-
 import {
   UncontrolledButtonDropdown, Button,
   DropdownToggle, DropdownMenu, DropdownItem,
 } from 'reactstrap';
 
-import loggerFactory from '~/utils/logger';
 
-import PageContainer from '~/client/services/PageContainer';
 import AppContainer from '~/client/services/AppContainer';
 import EditorContainer from '~/client/services/EditorContainer';
-
-import { withUnstatedContainers } from './UnstatedUtils';
-import GrantSelector from './SavePageControls/GrantSelector';
-
+import PageContainer from '~/client/services/PageContainer';
 import { getOptionsToSave } from '~/client/util/editor';
 
 // TODO: remove this when omitting unstated is completed
+import { useIsEditable } from '~/stores/context';
 import {
   useEditorMode, useSelectedGrant, useSelectedGrantGroupId, useSelectedGrantGroupName,
 } from '~/stores/ui';
-import { useIsEditable, useSlackChannels } from '~/stores/context';
-import { useIsSlackEnabled } from '~/stores/editor';
+import loggerFactory from '~/utils/logger';
+
+import GrantSelector from './SavePageControls/GrantSelector';
+import { withUnstatedContainers } from './UnstatedUtils';
 
 const logger = loggerFactory('growi:SavePageControls');
 
@@ -142,8 +139,6 @@ const SavePageControlsHOCWrapper = withUnstatedContainers(SavePageControls, [App
 const SavePageControlsWrapper = (props) => {
   const { data: isEditable } = useIsEditable();
   const { data: editorMode } = useEditorMode();
-  const { data: isSlackEnabled } = useIsSlackEnabled();
-  const { data: slackChannels } = useSlackChannels();
   const { data: grant, mutate: mutateGrant } = useSelectedGrant();
   const { data: grantGroupId, mutate: mutateGrantGroupId } = useSelectedGrantGroupId();
   const { data: grantGroupName, mutate: mutateGrantGroupName } = useSelectedGrantGroupName();
@@ -161,8 +156,6 @@ const SavePageControlsWrapper = (props) => {
     <SavePageControlsHOCWrapper
       {...props}
       editorMode={editorMode}
-      isSlackEnabled={isSlackEnabled}
-      slackChannels={slackChannels}
       grant={grant}
       grantGroupId={grantGroupId}
       grantGroupName={grantGroupName}

+ 1 - 0
packages/app/src/components/SlackNotification.tsx

@@ -1,5 +1,6 @@
 /* eslint-disable react/prop-types */
 import React, { FC } from 'react';
+
 import { useTranslation } from 'react-i18next';
 import { PopoverBody, PopoverHeader, UncontrolledPopover } from 'reactstrap';
 

+ 3 - 0
packages/app/src/interfaces/user-trigger-notification.ts

@@ -0,0 +1,3 @@
+
+type SlackChannel = string;
+export type SlackChannels = {[updatePost: string]: SlackChannel[]}

+ 0 - 1
packages/app/src/server/models/page.ts

@@ -99,7 +99,6 @@ const schema = new Schema<PageDocument, PageModel>({
   liker: [{ type: ObjectId, ref: 'User' }],
   seenUsers: [{ type: ObjectId, ref: 'User' }],
   commentCount: { type: Number, default: 0 },
-  slackChannels: { type: String },
   pageIdOnHackmd: { type: String },
   revisionHackmdSynced: { type: ObjectId, ref: 'Revision' }, // the revision that is synced to HackMD
   hasDraftOnHackmd: { type: Boolean }, // set true if revision and revisionHackmdSynced are same but HackMD document has modified

+ 0 - 11
packages/app/src/server/service/user-notification/index.ts

@@ -49,7 +49,6 @@ export class UserNotificationService {
 
     // "dev,slacktest" => [dev,slacktest]
     const slackChannels: (string|null)[] = toArrayFromCsv(slackChannelsStr);
-    await this.putDefaultChannelIfEmpty(page.path, slackChannels);
 
     const appTitle = appService.getAppTitle();
     const siteUrl = appService.getSiteUrl();
@@ -69,14 +68,4 @@ export class UserNotificationService {
     return Promise.allSettled(promises);
   }
 
-  private async putDefaultChannelIfEmpty(pagePath:string, slackChannels: (string|null)[]): Promise<void> {
-    const updatePosts = await UpdatePost.findSettingsByPath(pagePath);
-    slackChannels.push(...(updatePosts).map(up => up.channel));
-
-    // insert null if empty to notify once
-    if (slackChannels.length === 0) {
-      slackChannels.push(null);
-    }
-  }
-
 }

+ 0 - 1
packages/app/src/server/views/layout-growi/identical-path-page.html

@@ -10,7 +10,6 @@
     <div id="content-main" class="content-main d-flex"
       data-path="{{ encodeURI(path) }}"
       data-current-user="{% if user %}{{ user._id.toString() }}{% endif %}"
-      data-slack-channels="{% if page %}{{ page.slackChannels }}{% endif %}"
       data-page-is-not-creatable="true"
       data-page-is-deleted="{% if page.isDeleted() %}true{% else %}false{% endif %}"
       data-identical-path="true"

+ 0 - 2
packages/app/src/server/views/widget/page_content.html

@@ -14,7 +14,6 @@
   data-page-grant-group-name="{{ grantedGroupName }}"
   data-page-is-deleted="{% if page.isDeleted() %}true{% else %}false{% endif %}"
   data-page-is-not-creatable="false"
-  data-slack-channels="{% if page %}{{ page.slackChannels }}{% endif %}"
   data-page-created-at="{{ page.createdAt|datetz('Y/m/d H:i:s') }}"
   data-page-creator="{% if page && page.creator %}{{ page.creator|json }}{% endif %}"
   data-page-last-update-username="{% if page && page.lastUpdateUser %}{{ page.lastUpdateUser.name }}{% endif %}"
@@ -31,7 +30,6 @@
 <div id="content-main" class="content-main d-flex"
   data-path="{{ encodeURI(path) }}"
   data-current-user="{% if user %}{{ user._id.toString() }}{% endif %}"
-  data-slack-channels="{% if page %}{{ page.slackChannels }}{% endif %}"
   data-page-is-deleted="{% if page.isDeleted() %}true{% else %}false{% endif %}"
   data-page-has-children="{% if pages.length > 0 %}true{% else %}false{% endif %}"
   >

+ 0 - 4
packages/app/src/stores/context.tsx

@@ -120,10 +120,6 @@ export const useRevisionAuthor = (initialData?: Nullable<any>): SWRResponse<Null
   return useStaticSWR<Nullable<any>, Error>('revisionAuthor', initialData);
 };
 
-export const useSlackChannels = (initialData?: Nullable<any>): SWRResponse<Nullable<any>, Error> => {
-  return useStaticSWR<Nullable<any>, Error>('slackChannels', initialData);
-};
-
 export const useIsSearchPage = (initialData?: Nullable<any>) : SWRResponse<Nullable<any>, Error> => {
   return useStaticSWR<Nullable<any>, Error>('isSearchPage', initialData);
 };

+ 27 - 6
packages/app/src/stores/editor.tsx

@@ -1,17 +1,18 @@
-import { SWRResponse } from 'swr';
+import useSWR, { SWRResponse } from 'swr';
 import useSWRImmutable from 'swr/immutable';
 
+import { apiGet } from '~/client/util/apiv1-client';
 import { apiv3Get, apiv3Put } from '~/client/util/apiv3-client';
+import { Nullable } from '~/interfaces/common';
 import { IEditorSettings } from '~/interfaces/editor-settings';
+import { SlackChannels } from '~/interfaces/user-trigger-notification';
 
-import { useCurrentUser, useDefaultIndentSize, useIsGuestUser } from './context';
+import {
+  useCurrentUser, useDefaultIndentSize, useIsGuestUser,
+} from './context';
 import { localStorageMiddleware } from './middlewares/sync-to-storage';
 import { useStaticSWR } from './use-static-swr';
 
-export const useIsSlackEnabled = (isEnabled?: boolean): SWRResponse<boolean, Error> => {
-  return useStaticSWR('isSlackEnabled', isEnabled, { fallbackData: false });
-};
-
 
 type EditorSettingsOperation = {
   update: (updateData: Partial<IEditorSettings>) => void,
@@ -69,3 +70,23 @@ export const useCurrentIndentSize = (): SWRResponse<number, Error> => {
     { fallbackData: defaultIndentSize },
   );
 };
+
+/*
+* Slack Notification
+*/
+export const useSWRxSlackChannels = (currentPagePath: Nullable<string>): SWRResponse<string[], Error> => {
+  const shouldFetch: boolean = currentPagePath != null;
+  return useSWR(
+    shouldFetch ? ['/pages.updatePost', currentPagePath] : null,
+    (endpoint, path) => apiGet(endpoint, { path }).then((response: SlackChannels) => response.updatePost),
+    { fallbackData: [''] },
+  );
+};
+
+export const useIsSlackEnabled = (): SWRResponse<boolean, Error> => {
+  return useStaticSWR(
+    'isSlackEnabled',
+    undefined,
+    { fallbackData: false },
+  );
+};

+ 1 - 14
packages/app/test/integration/models/update-post.test.js

@@ -1,19 +1,6 @@
-const mongoose = require('mongoose');
-
-const { getInstance } = require('../setup-crowi');
+import UpdatePost from '../../../src/server/models/update-post';
 
 describe('UpdatePost', () => {
-  // eslint-disable-next-line no-unused-vars
-  let crowi;
-  let UpdatePost;
-
-  beforeAll(async() => {
-    crowi = await getInstance();
-  });
-
-  beforeEach(async() => {
-    UpdatePost = mongoose.model('UpdatePost');
-  });
 
   describe('.createPrefixesByPathPattern', () => {
     describe('with a path', () => {