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

Merge branch 'feat/growi-bot' into imprv/slack-notification-from-slackBot

zahmis 5 лет назад
Родитель
Сommit
202df26201

+ 10 - 0
resource/locales/en_US/admin/admin.json

@@ -252,6 +252,16 @@
     "download": "Download",
     "delete": "Delete"
   },
+  "slack_integration": {
+    "access_token_settings": {
+      "discard": "Discard",
+      "generate": "Generate"
+    },
+    "custom_bot_non_proxy_settings": "Custom bot (non-proxy) Settings",
+    "non_proxy": {
+      "create_bot": "Create Bot"
+    }
+  },
   "user_management": {
     "invite_users": "Invite new users",
     "click_twice_same_checkbox": "You should check at least one checkbox.",

+ 1 - 1
resource/locales/en_US/translation.json

@@ -111,7 +111,7 @@
   "Notification Settings": "Notification Settings",
   "slack_integration": "Slack Integration",
   "External_Notification": "External Notification",
-  "Legacy_External_Notification": "Legacy External Notification",
+  "Legacy_Slack_Integration": "Legacy Slack Integration",
   "User_Management": "User Management",
   "external_account_management": "External Account Management",
   "UserGroup Management": "UserGroup Management",

+ 10 - 0
resource/locales/ja_JP/admin/admin.json

@@ -250,6 +250,16 @@
     "page_skip": "既に GROWI 側に同名のページが存在する場合、そのページはスキップされます",
     "Directory_hierarchy_tag": "ディレクトリ階層タグ"
   },
+  "slack_integration": {
+    "access_token_settings": {
+      "discard": "破棄",
+      "generate": "発行"
+    },
+    "custom_bot_non_proxy_settings": "Custom bot (non-proxy) 設定",
+    "non_proxy": {
+      "create_bot": "Bot を作成する"
+    }
+  },
   "user_management": {
     "invite_users": "新規ユーザーの招待",
     "click_twice_same_checkbox": "少なくとも一つはチェックしてください。",

+ 1 - 1
resource/locales/ja_JP/translation.json

@@ -112,7 +112,7 @@
   "Notification Settings": "通知設定",
   "slack_integration": "Slack連携",
   "External_Notification": "外部ツールへの通知",
-  "Legacy_External_Notification": "外部ツールへの通知 (レガシー)",
+  "Legacy_Slack_Integration": "Slack連携 (レガシー)",
   "User_Management": "ユーザー管理",
   "external_account_management": "外部アカウント管理",
   "UserGroup Management": "グループ管理",

+ 10 - 0
resource/locales/zh_CN/admin/admin.json

@@ -259,6 +259,16 @@
 		"export_menu": "导出菜单",
 		"download": "下载",
 		"delete": "删除"
+  },
+  "slack_integration": {
+    "access_token_settings": {
+      "discard": "丢弃",
+      "generate": "生成"
+    },
+    "custom_bot_non_proxy_settings": "Custom bot (non-proxy) 设置",
+    "non_proxy": {
+      "create_bot": "创建 Bot"
+    }
   },
 	"user_management": {
 		"invite_users": "邀请新用户",

+ 1 - 1
resource/locales/zh_CN/translation.json

@@ -120,7 +120,7 @@
 	"Notification Settings": "通知设置",
   "slack_integration": "Slack一体化",
   "External_Notification": "外部通知",
-  "Legacy_External_Notification": "旧版外部通知",
+  "Legacy_Slack_Integration": "旧版Slack一体化",
 	"User_Management": "用户管理",
 	"external_account_management": "外部账户管理",
 	"UserGroup Management": "用户组管理",

+ 3 - 3
src/client/js/components/Admin/Common/AdminNavigation.jsx

@@ -21,8 +21,8 @@ const AdminNavigation = (props) => {
       case 'importer':          return <><i className="icon-fw icon-cloud-upload"></i>    { t('Import Data') }</>;
       case 'export':            return <><i className="icon-fw icon-cloud-download"></i>  { t('Export Archive Data') }</>;
       case 'notification':      return <><i className="icon-fw icon-bell"></i>            { t('External_Notification') }</>;
-      // TODO change icon for legacy-external-notification by GW-5466
-      case 'legacy-external-notification':  return <> <i className="icon-fw icon-bell"></i>{ t('Legacy_External_Notification') }</>;
+      // TODO change icon for legacy-slack-integration by GW-5466
+      case 'legacy-slack-integration':  return <> <i className="icon-fw icon-paper-plane"></i>    { t('Legacy_Slack_Integration') }</>;
       case 'slack-integration': return <><i className="icon-fw icon-paper-plane"></i>     { t('slack_integration') }</>;
       case 'users':             return <><i className="icon-fw icon-user"></i>            { t('User_Management') }</>;
       case 'user-groups':       return <><i className="icon-fw icon-people"></i>          { t('UserGroup Management') }</>;
@@ -64,8 +64,8 @@ const AdminNavigation = (props) => {
         <MenuLink menu="importer"     isListGroupItems isActive={isActiveMenu('/importer')} />
         <MenuLink menu="export"       isListGroupItems isActive={isActiveMenu('/export')} />
         <MenuLink menu="notification" isListGroupItems isActive={isActiveMenu('/notification') || isActiveMenu('/global-notification')} />
-        <MenuLink menu="legacy-external-notification" isListGroupItems isActive={isActiveMenu('/legacy-external-notification')} />
         <MenuLink menu="slack-integration" isListGroupItems isActive={isActiveMenu('/slack-integration')} />
+        <MenuLink menu="legacy-slack-integration" isListGroupItems isActive={isActiveMenu('/legacy-slack-integration')} />
         <MenuLink menu="users"        isListGroupItems isActive={isActiveMenu('/users')} />
         <MenuLink menu="user-groups"  isListGroupItems isActive={isActiveMenu('/user-groups')} />
         <MenuLink menu="search"       isListGroupItems isActive={isActiveMenu('/search')} />

+ 0 - 1
src/client/js/components/Admin/Common/AdminUpdateButtonRow.jsx

@@ -16,7 +16,6 @@ const AdminUpdateButtonRow = (props) => {
 
 AdminUpdateButtonRow.propTypes = {
   t: PropTypes.func.isRequired, // i18next
-
   onClick: PropTypes.func.isRequired,
   disabled: PropTypes.bool.isRequired,
 };

+ 39 - 0
src/client/js/components/Admin/SlackIntegration/AccessTokenSettings.jsx

@@ -0,0 +1,39 @@
+/* eslint-disable no-console */
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+
+function AccessTokenSettings() {
+
+  const { t } = useTranslation('admin');
+  function discardHandler() {
+    console.log('Discard button pressed');
+  }
+
+  function generateHandler() {
+    console.log('Generate button pressed');
+  }
+
+  return (
+    <>
+      <div className="form-group row my-5">
+        <label className="text-left text-md-right col-md-3 col-form-label">Access Token</label>
+        <div className="col-md-6">
+          <input className="form-control" type="text" placeholder="access-token" />
+        </div>
+      </div>
+
+      <div className="row">
+        <div className="mx-auto">
+          <button type="button" className="btn btn-outline-secondary text-nowrap mx-1" onClick={discardHandler}>
+            {t('slack_integration.access_token_settings.discard')}
+          </button>
+          <button type="button" className="btn btn-primary text-nowrap mx-1" onClick={generateHandler}>
+            {t('slack_integration.access_token_settings.generate')}
+          </button>
+        </div>
+      </div>
+    </>
+  );
+}
+
+export default AccessTokenSettings;

+ 54 - 0
src/client/js/components/Admin/SlackIntegration/CustomBotNonProxySettings.jsx

@@ -0,0 +1,54 @@
+/* eslint-disable no-console */
+import React, { useState } from 'react';
+import { useTranslation } from 'react-i18next';
+
+import AdminUpdateButtonRow from '../Common/AdminUpdateButtonRow';
+
+function CustomBotNonProxySettings() {
+
+  const { t } = useTranslation('admin');
+  const [secret, setSecret] = useState('');
+  const [token, setToken] = useState('');
+
+  function updateHandler() {
+    console.log(`Signing Secret: ${secret}, Bot User OAuth Token: ${token}`);
+  }
+
+  return (
+    <>
+      <div className="row my-5">
+        <div className="mx-auto">
+          <button type="button" className="btn btn-primary text-nowrap mx-1" onClick={() => window.open('https://api.slack.com/apps', '_blank')}>
+            {t('slack_integration.non_proxy.create_bot')}
+          </button>
+        </div>
+      </div>
+
+      <div className="form-group row">
+        <label className="text-left text-md-right col-md-3 col-form-label">Signing Secret</label>
+        <div className="col-md-6">
+          <input
+            className="form-control"
+            type="text"
+            onChange={e => setSecret(e.target.value)}
+          />
+        </div>
+      </div>
+
+      <div className="form-group row mb-5">
+        <label className="text-left text-md-right col-md-3 col-form-label">Bot User OAuth Token</label>
+        <div className="col-md-6">
+          <input
+            className="form-control"
+            type="text"
+            onChange={e => setToken(e.target.value)}
+          />
+        </div>
+      </div>
+
+      <AdminUpdateButtonRow onClick={updateHandler} disabled={false} />
+    </>
+  );
+}
+
+export default CustomBotNonProxySettings;

+ 21 - 34
src/client/js/components/Admin/SlackIntegration/SlackIntegration.jsx

@@ -1,42 +1,29 @@
-import React, { Fragment } from 'react';
-// import PropTypes from 'prop-types';
+import React from 'react';
+import { useTranslation } from 'react-i18next';
 
-// import { withUnstatedContainers } from '../../UnstatedUtils';
-// import AppContainer from '../../../services/AppContainer';
+import AccessTokenSettings from './AccessTokenSettings';
+import CustomBotNonProxySettings from './CustomBotNonProxySettings';
 
-class SlackIntegration extends React.Component {
+function SlackIntegration() {
 
-  render() {
-    // const { t } = this.props;
-
-    return (
-      <Fragment>
-        <div className="row">
-          <div className="col-lg-12">
-            {/* <h2 className="admin-setting-header">{t('Access Token')}</h2> */}
-            <h2 className="admin-setting-header">Access Token</h2>
-            <div className="form-group row">
-              {/* <label className="text-left text-md-right col-md-3 col-form-label">{t('admin:app_setting.site_name')}</label> */}
-              <label className="text-left text-md-right col-md-3 col-form-label">Access Token</label>
-
-              <div className="col-md-6">
-                <input className="form-control" type="text" placeholder="access-token" />
-              </div>
-            </div>
-          </div>
+  const { t } = useTranslation('admin');
+  return (
+    <>
+      <div className="row">
+        <div className="col-lg-12">
+          <h2 className="admin-setting-header">Access Token</h2>
+          <AccessTokenSettings />
         </div>
-      </Fragment>
-    );
-  }
+      </div>
 
+      <div className="row">
+        <div className="col-lg-12">
+          <h2 className="admin-setting-header">{t('slack_integration.custom_bot_non_proxy_settings')}</h2>
+          <CustomBotNonProxySettings />
+        </div>
+      </div>
+    </>
+  );
 }
 
-// const SlackIntegrationWrapper = withUnstatedContainers(SlackIntegration, [AppContainer]);
-
-// SlackIntegration.propTypes = {
-//   t: PropTypes.func.isRequired, // i18next
-//   appContainer: PropTypes.instanceOf(AppContainer).isRequired,
-// slackIntegrationContainer: PropTypes.instanceOf(SlackIntegrationContainer).isRequired,
-// };
-
 export default SlackIntegration;

+ 3 - 3
src/server/routes/admin.js

@@ -223,9 +223,9 @@ module.exports = function(crowi, app) {
     return res.render('admin/external-accounts');
   };
 
-  actions.legacyExternalNotification = {};
-  actions.legacyExternalNotification = function(req, res) {
-    return res.render('admin/legacy-external-notification');
+  actions.legacySlackIntegration = {};
+  actions.legacySlackIntegration = function(req, res) {
+    return res.render('admin/legacy-slack-integration');
   };
 
   actions.slackIntegration = {};

+ 1 - 1
src/server/routes/index.js

@@ -93,7 +93,7 @@ module.exports = function(crowi, app) {
   app.get('/admin/notification/slackSetting/disconnect' , loginRequiredStrictly , adminRequired , admin.notification.disconnectFromSlack);
   app.get('/admin/global-notification/new'              , loginRequiredStrictly , adminRequired , admin.globalNotification.detail);
   app.get('/admin/global-notification/:id'              , loginRequiredStrictly , adminRequired , admin.globalNotification.detail);
-  app.get('/admin/legacy-external-notification'         , loginRequiredStrictly , adminRequired,  admin.legacyExternalNotification);
+  app.get('/admin/legacy-slack-integration'         , loginRequiredStrictly , adminRequired,  admin.legacySlackIntegration);
   app.get('/admin/slack-integration'                    , loginRequiredStrictly , adminRequired,  admin.slackIntegration);
 
   app.get('/admin/users'                                , loginRequiredStrictly , adminRequired , admin.user.index);

+ 4 - 18
src/server/service/bolt.js

@@ -74,21 +74,6 @@ class BoltService {
   }
 
   init() {
-    // Example of listening for event
-    // See. https://github.com/slackapi/bolt-js#listening-for-events
-    // or https://slack.dev/bolt-js/concepts#basic
-    this.bolt.command('/growi-bot', async({ command, ack, say }) => { // demo
-      await say('Hello');
-    });
-
-    // The echo command simply echoes on command
-    this.bolt.command('/echo', async({ command, ack, say }) => {
-      // Acknowledge command request
-      await ack();
-
-      await say(`${command.text}`);
-    });
-
     this.bolt.command('/growi', async({
       command, client, body, ack,
     }) => {
@@ -204,7 +189,7 @@ class BoltService {
           this.generateMarkdownSectionBlock('`-tag:wiki` \n Exclude pages with wiki tag'),
         ],
       });
-      return;
+      return { resultPaths: [] };
     }
 
     const resultPaths = results.data.map((data) => {
@@ -223,9 +208,10 @@ class BoltService {
 
     const keywords = this.getKeywords(args);
 
-    if (resultPaths == null) {
+    if (resultPaths.length === 0) {
       return;
     }
+
     const base = this.crowi.appService.getSiteUrl();
 
     const urls = resultPaths.map((path) => {
@@ -271,7 +257,7 @@ class BoltService {
       };
       // show "Next" button if next page exists
       if (resultsTotal > offset + PAGINGLIMIT) {
-        actionBlocks.elements.push(
+        actionBlocks.elements.unshift(
           {
             type: 'button',
             text: {

+ 2 - 2
src/server/views/admin/legacy-external-notification.html → src/server/views/admin/legacy-slack-integration.html

@@ -1,9 +1,9 @@
 {% extends '../layout/admin.html' %}
 
-{% block html_title %}{{ customizeService.generateCustomTitleForFixedPageName(t('Legacy_External_Notification')) }}{% endblock %}
+{% block html_title %}{{ customizeService.generateCustomTitleForFixedPageName(t('Legacy_Slack_Integration')) }}{% endblock %}
 
 {% block content_header %}
-<h1 class="title">{{ t('Legacy_External_Notification') }}</h1>
+<h1 class="title">{{ t('Legacy_Slack_Integration') }}</h1>
 {% endblock %}
 
 {% block content_main %}