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

Merge branch 'feat/growi-bot' into imprv/gw5856-be-able-to-copy-a-url

# Conflicts:
#	src/client/js/components/Admin/SlackIntegration/OfficialbotSettingsAccordion.jsx
kaori 4 лет назад
Родитель
Сommit
abaf8a81df

+ 8 - 0
packages/slackbot-proxy/src/Server.ts

@@ -75,6 +75,14 @@ export class Server {
   @Inject()
   injector: InjectorService;
 
+  $onInit(): Promise<any> | void {
+    const serverUri = process.env.SERVER_URI;
+
+    if (serverUri === undefined) {
+      throw new Error('The environment variable \'SERVER_URI\' must be defined.');
+    }
+  }
+
   $beforeRoutesInit(): void {
     this.app
       .use(cookieParser())

+ 1 - 1
packages/slackbot-proxy/src/controllers/slack.ts

@@ -155,7 +155,7 @@ export class SlackCtrl {
     // register
     if (type === 'view_submission' && payload.response_urls[0].action_id === 'submit_growi_url_and_access_tokens') {
       await this.registerService.upsertOrderRecord(this.orderRepository, installation, payload);
-      await this.registerService.showProxyUrl(authorizeResult, payload);
+      await this.registerService.notifyServerUriToSlack(authorizeResult, payload);
       return;
     }
 

+ 4 - 9
packages/slackbot-proxy/src/services/RegisterService.ts

@@ -6,7 +6,6 @@ import { GrowiCommandProcessor } from '~/interfaces/growi-command-processor';
 import { OrderRepository } from '~/repositories/order';
 import { Installation } from '~/entities/installation';
 
-
 const isProduction = process.env.NODE_ENV === 'production';
 
 @Service()
@@ -79,19 +78,15 @@ export class RegisterService implements GrowiCommandProcessor {
     }
   }
 
-  async showProxyUrl(
+  async notifyServerUriToSlack(
       // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
       authorizeResult:AuthorizeResult, payload: any,
   ): Promise<void> {
 
-    // TODO: implement for when proxy URL is undefined by GW-5834
-    let proxyURL;
-    if (process.env.PROXY_URL != null) {
-      proxyURL = process.env.PROXY_URL;
-    }
-
     const { botToken } = authorizeResult;
 
+    const serverUri = process.env.SERVER_URI;
+
     const client = new WebClient(botToken, { logLevel: isProduction ? LogLevel.DEBUG : LogLevel.INFO });
 
     await client.chat.postEphemeral({
@@ -102,7 +97,7 @@ export class RegisterService implements GrowiCommandProcessor {
       text: 'Proxy URL',
       blocks: [
         generateMarkdownSectionBlock('Please enter and update the following Proxy URL to slack bot setting form in your GROWI'),
-        generateMarkdownSectionBlock(`Proxy URL: ${proxyURL}`),
+        generateMarkdownSectionBlock(`Proxy URL: ${serverUri}`),
       ],
     });
     return;

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

@@ -288,6 +288,8 @@
       "discard": "Discard",
       "generate": "Generate"
     },
+    "delete": "Delete",
+    "cooperation_procedure": "Cooperation procedure",
     "official_bot_settings": "Official bot Settings",
     "custom_bot_without_proxy_settings": "Custom Bot without proxy Settings",
     "accordion": {
@@ -296,6 +298,13 @@
       "how_to_install": "How to install",
       "install_bot_to_slack": "Install Bot To Slack",
       "install_now": "Install now",
+      "generate_access_token": "Generate Access Token",
+      "register_for_growi_official_bot_proxy_service": "Register for GROWI Official Bot Proxy Service",
+      "enter_growi_register_on_slack": "Enter `/growi register` on slack",
+      "paste_growi_url": "Enter `http://localhost:3000` for <b>GROWI URL</b>",
+      "enter_access_token_for_growi_and_proxy": "Enter <b>Access Token for GROWI</b> and <b>Access Token for Proxy</b>",
+      "set_proxy_url_on_growi": "Set Proxy URL on GROWI",
+      "enter_proxy_url_and_update": "Enter <b>Proxy URL</b> shown on Slack and click Update",
       "select_install_your_app": "Select \"Install your app\".",
       "select_install_to_workspace": "Select \"Install to Workspace\".",
       "register_official_bot_proxy_service": "Issue Access Token / Register GROWI Official Bot Proxy Service",

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

@@ -286,6 +286,8 @@
       "discard": "破棄",
       "generate": "発行"
     },
+    "delete": "削除",
+    "cooperation_procedure": "連携手順",
     "custom_bot_without_proxy_settings": "Custom Bot (Without-Proxy) 設定",
     "accordion": {
       "create_bot": "Bot を作成する",
@@ -293,6 +295,13 @@
       "how_to_install": "インストール方法はこちら",
       "install_bot_to_slack": "Bot を Slack にインストールする",
       "install_now": "今すぐインストール",
+      "generate_access_token": "Access Tokenの発行",
+      "register_for_growi_official_bot_proxy_service": "GROWI Official Bot Proxy サービスへの登録",
+      "enter_growi_register_on_slack": "Slack上で `/growi register` と打つ",
+      "paste_growi_url": "<b>GROWI URL</b>には`http://localhost:3000`を貼り付ける",
+      "enter_access_token_for_growi_and_proxy": "上記で発行した<b>Access Token for GROWI</b> と <b>Access Token for Proxy</b>を入れる",
+      "set_proxy_url_on_growi": "ProxyのURLをGROWIに登録する",
+      "enter_proxy_url_and_update": "Slack上に通知された<b>Proxy URL</b>を入力し、更新してください。",
       "select_install_your_app": "Install your app をクリックします。",
       "select_install_to_workspace": "Install to Workspace をクリックします。",
       "register_official_bot_proxy_service": "アクセストークンの発行 / GROWI Official Bot Proxy サービスへの登録",

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

@@ -296,6 +296,8 @@
       "discard": "丢弃",
       "generate": "生成"
     },
+    "delete": "取消",
+    "cooperation_procedure": "协作程序",
     "custom_bot_without_proxy_settings": "Custom Bot (Without-Proxy) 设置",
     "accordion": {
       "create_bot": "创建 Bot",
@@ -303,6 +305,13 @@
       "how_to_install": "点击这里查看安装说明",
       "install_bot_to_slack": "将 Bot 安装到 Slack",
       "install_now": "现在安装",
+      "generate_access_token": "生成Access Token",
+      "register_for_growi_official_bot_proxy_service": "注册 GROWI Official Bot Proxy Service",
+      "enter_growi_register_on_slack": "在Slack中,输入`/growi register`。",
+      "paste_growi_url": "将`http://localhost:3000`粘贴到 <b>GROWI URL</b> 网址中",
+      "enter_access_token_for_growi_and_proxy": "插入上面发出的 <b>Access Token for GROWI</b> 和 <b>Access Token for Proxy</b>。",
+      "set_proxy_url_on_growi": "向GROWI注册Proxy的URL",
+      "enter_proxy_url_and_update": "按照Slack上的通知输入并更新你的 <b>Proxy URL</b>。",
       "select_install_your_app": "选择 \"Install your app\"。",
       "select_install_to_workspace": "选择 \"Install to Workspace\"。",
       "register_official_bot_proxy_service": "发行访问令牌 / 注册 GROWI 官方 Bot 代理服务",

+ 14 - 4
src/client/js/components/Admin/SlackIntegration/CustomBotWithProxySettings.jsx

@@ -15,7 +15,7 @@ const CustomBotWithProxySettings = (props) => {
   return (
     <>
 
-      <h2 className="admin-setting-header">{t('admin:slack_integration.custom_bot_with_proxy_integration')}</h2>
+      <h2 className="admin-setting-header mb-2">{t('admin:slack_integration.custom_bot_with_proxy_integration')}</h2>
 
       {/* TODO delete tmp props */}
       <CustomBotWithProxyIntegrationCard
@@ -23,9 +23,19 @@ const CustomBotWithProxySettings = (props) => {
         slackWSNameInWithProxy="SlackWorkSpaceName"
         isSlackScopeSet
       />
-
-      <div className="my-5 mx-3">
-        <CustomBotWithProxySettingsAccordion />
+      <h2 className="admin-setting-header">{t('admin:slack_integration.cooperation_procedure')}</h2>
+      <div className="mx-3">
+        <div className="d-flex flex-column pull-right">
+          <button
+            className="my-3 btn btn-outline-danger"
+            type="button"
+          ><i className="icon-trash mr-1" />{t('admin:slack_integration.delete')}
+          </button>
+        </div>
+
+        <div className="d-flex flex-column my-5 w-100">
+          <CustomBotWithProxySettingsAccordion />
+        </div>
       </div>
     </>
   );

+ 163 - 5
src/client/js/components/Admin/SlackIntegration/CustomBotWithProxySettingsAccordion.jsx

@@ -1,9 +1,38 @@
-import React from 'react';
+import React, { useState } from 'react';
 import { useTranslation } from 'react-i18next';
+import AdminUpdateButtonRow from '../Common/AdminUpdateButtonRow';
 import Accordion from '../Common/Accordion';
 
 const CustomBotWithProxySettingsAccordion = () => {
+  const [testChannel, setTestChannel] = useState('');
+  /* eslint-disable no-unused-vars */
+  // TODO: Add connection Logs
+  const [connectionErrorCode, setConnectionErrorCode] = useState(null);
+  const [connectionErrorMessage, setConnectionErrorMessage] = useState(null);
+  const [connectionSuccessMessage, setConnectionSuccessMessage] = useState(null);
+
   const { t } = useTranslation();
+
+  // TODO: Handle test button
+  const submitForm = (e) => {
+    e.preventDefault();
+    // eslint-disable-next-line no-console
+    console.log('Form Submitted');
+  };
+
+  const inputTestChannelHandler = (channel) => {
+    setTestChannel(channel);
+  };
+
+  // TODO: Show test logs
+  let value = '';
+  if (connectionErrorMessage != null) {
+    value = [connectionErrorCode, connectionErrorMessage];
+  }
+  if (connectionSuccessMessage != null) {
+    value = connectionSuccessMessage;
+  }
+
   return (
     <div className="card border-0 rounded-lg shadow overflow-hidden">
       <Accordion
@@ -46,14 +75,143 @@ const CustomBotWithProxySettingsAccordion = () => {
         </div>
       </Accordion>
       <Accordion
-        title={<><span className="mr-2">③</span>Third Accordion</>}
+        title={(
+          <>
+            <span className="mr-2">③</span>
+            {t('admin:slack_integration.accordion.generate_access_token')}
+            {' / '}
+            {t('admin:slack_integration.accordion.register_for_growi_official_bot_proxy_service')}
+          </>
+        )}
+      >
+        <div className="py-4 px-5">
+          <p className="font-weight-bold">1. {t('admin:slack_integration.accordion.generate_access_token')}</p>
+          <div className="form-group row">
+            <label className="text-left text-md-right col-md-3 col-form-label">Access Token for GROWI</label>
+            <div className="col-md-6">
+              <input
+                className="form-control"
+                type="text"
+              />
+            </div>
+          </div>
+          <div className="form-group row">
+            <label className="text-left text-md-right col-md-3 col-form-label">Access Token for Proxy</label>
+            <div className="col-md-6">
+              <input
+                className="form-control"
+                type="text"
+              />
+            </div>
+          </div>
+
+          <div className="row my-3">
+            <div className="mx-auto">
+              <button type="button" className="btn btn-outline-secondary mx-2">{ t('admin:slack_integration.access_token_settings.discard') }</button>
+              <button type="button" className="btn btn-primary mx-2">{ t('admin:slack_integration.access_token_settings.generate') }</button>
+            </div>
+          </div>
+          <p className="font-weight-bold">2. {t('admin:slack_integration.accordion.register_for_growi_official_bot_proxy_service')}</p>
+          <div className="d-flex flex-column align-items-center">
+            <ol className="p-0">
+              <li><p className="ml-2">{t('admin:slack_integration.accordion.enter_growi_register_on_slack')}</p></li>
+              <li>
+                <p
+                  className="ml-2"
+                  // TODO: Add dynamic link
+                  // TODO: Copy to clipboard on click
+                  // TODO: Add logo
+                  // eslint-disable-next-line react/no-danger
+                  dangerouslySetInnerHTML={{ __html: t('admin:slack_integration.accordion.paste_growi_url') }}
+                />
+              </li>
+              <li>
+                <p
+                  className="ml-2"
+                  // eslint-disable-next-line react/no-danger
+                  dangerouslySetInnerHTML={{ __html: t('admin:slack_integration.accordion.enter_access_token_for_growi_and_proxy') }}
+                />
+              </li>
+            </ol>
+            {/* TODO: Insert photo */}
+            <div className="rounded border w-50 d-flex justify-content-center align-items-center" style={{ height: '15rem' }}>
+              <h1 className="text-muted">参考画像</h1>
+            </div>
+          </div>
+        </div>
+      </Accordion>
+      <Accordion
+        title={<><span className="mr-2">④</span>{t('admin:slack_integration.accordion.set_proxy_url_on_growi')}</>}
       >
-        3
+        <div className="p-4">
+          <p
+            className="text-center"
+            // eslint-disable-next-line react/no-danger
+            dangerouslySetInnerHTML={{ __html: t('admin:slack_integration.accordion.enter_proxy_url_and_update') }}
+          />
+          <div className="form-group row my-4">
+            <label className="text-left text-md-right col-md-3 col-form-label">Proxy URL</label>
+            <div className="col-md-6">
+              <input
+                className="form-control"
+                type="text"
+              />
+            </div>
+          </div>
+          <AdminUpdateButtonRow
+            disabled={false}
+            // TODO: Add Proxy URL submit logic
+            // eslint-disable-next-line no-console
+            onClick={() => console.log('Update')}
+          />
+        </div>
       </Accordion>
       <Accordion
-        title={<><span className="mr-2">④</span>Fourth Accordion</>}
+        title={<><span className="mr-2">⑤</span>{t('admin:slack_integration.accordion.test_connection')}</>}
       >
-        4
+        {/* TODO: Responsive */}
+        <p className="text-center m-4">{t('admin:slack_integration.accordion.test_connection_by_pressing_button')}</p>
+        <div className="d-flex justify-content-center">
+          <form className="form-row justify-content-center" onSubmit={e => submitForm(e)}>
+            <div className="input-group col-8">
+              <div className="input-group-prepend">
+                <span className="input-group-text" id="slack-channel-addon"><i className="fa fa-hashtag" /></span>
+              </div>
+              <input
+                className="form-control"
+                type="text"
+                value={testChannel}
+                placeholder="Slack Channel"
+                // TODO: Handle test button
+                onChange={e => inputTestChannelHandler(e.target.value)}
+              />
+            </div>
+            <button
+              type="submit"
+              className="btn btn-info mx-3 font-weight-bold"
+              disabled={testChannel.trim() === ''}
+            >Test
+            </button>
+          </form>
+        </div>
+        {connectionErrorMessage != null
+          && <p className="text-danger text-center my-4">{t('admin:slack_integration.accordion.error_check_logs_below')}</p>}
+        {connectionSuccessMessage != null
+          && <p className="text-info text-center my-4">{t('admin:slack_integration.accordion.send_message_to_slack_work_space')}</p>}
+        <form>
+          <div className="row my-3 justify-content-center">
+            <div className="form-group slack-connection-log col-md-4">
+              <label className="mb-1"><p className="border-info slack-connection-log-title pl-2 m-0">Logs</p></label>
+              <textarea
+                className="form-control card border-info slack-connection-log-body rounded-lg"
+                rows="5"
+                // TODO: Show test logs
+                value={value}
+                readOnly
+              />
+            </div>
+          </div>
+        </form>
       </Accordion>
     </div>
   );

+ 15 - 14
src/client/js/components/Admin/SlackIntegration/CustomBotWithoutProxySettingsAccordion.jsx

@@ -160,25 +160,25 @@ const CustomBotWithoutProxySettingsAccordion = ({
       >
         <p className="text-center m-4">{t('admin:slack_integration.accordion.test_connection_by_pressing_button')}</p>
         <div className="d-flex justify-content-center">
-          <form className="form-row align-items-center w-25" onSubmit={e => submitForm(e)}>
-            <div className="col-8 input-group-prepend">
-              <span className="input-group-text" id="slack-channel-addon"><i className="fa fa-hashtag" /></span>
+          <form className="form-row align-items-center" onSubmit={e => submitForm(e)}>
+            <div className="input-group col-8">
+              <div className="input-group-prepend">
+                <span className="input-group-text" id="slack-channel-addon"><i className="fa fa-hashtag" /></span>
+              </div>
               <input
-                className="form-control w-100"
+                className="form-control"
                 type="text"
                 value={testChannel}
                 placeholder="Slack Channel"
                 onChange={e => inputTestChannelHandler(e.target.value)}
               />
             </div>
-            <div className="col-4">
-              <button
-                type="submit"
-                className="btn btn-info mx-3 font-weight-bold"
-                disabled={testChannel.trim() === ''}
-              >Test
-              </button>
-            </div>
+            <button
+              type="submit"
+              className="btn btn-info mx-3 font-weight-bold"
+              disabled={testChannel.trim() === ''}
+            >Test
+            </button>
           </form>
         </div>
         {connectionErrorMessage != null
@@ -187,10 +187,11 @@ const CustomBotWithoutProxySettingsAccordion = ({
           && <p className="text-info text-center my-4">{t('admin:slack_integration.accordion.send_message_to_slack_work_space')}</p>}
         <form>
           <div className="row my-3 justify-content-center">
-            <div className="form-group slack-connection-log w-25">
-              <label className="mb-1"><p className="border-info slack-connection-log-title pl-2">Logs</p></label>
+            <div className="form-group slack-connection-log col-md-4">
+              <label className="mb-1"><p className="border-info slack-connection-log-title pl-2 m-0">Logs</p></label>
               <textarea
                 className="form-control card border-info slack-connection-log-body rounded-lg"
+                rows="5"
                 value={value}
                 readOnly
               />

+ 17 - 3
src/client/js/components/Admin/SlackIntegration/OfficialbotSettingsAccordion.jsx

@@ -1,15 +1,19 @@
 import React from 'react';
+import PropTypes from 'prop-types';
 import { useTranslation } from 'react-i18next';
 import { CopyToClipboard } from 'react-copy-to-clipboard';
 import Accordion from '../Common/Accordion';
 import AdminUpdateButtonRow from '../Common/AdminUpdateButtonRow';
 import { toastSuccess } from '../../../util/apiNotification';
+import { withUnstatedContainers } from '../../UnstatedUtils';
+import AppContainer from '../../../services/AppContainer';
 
-const growiUrl = window.location.host;
 
-const OfficialBotSettingsAccordion = () => {
+const OfficialBotSettingsAccordion = (props) => {
   // TODO: apply i18n by GW-5878
   const { t } = useTranslation();
+  const { appContainer } = props;
+  const growiUrl = appContainer.config.crowi.url;
 
   return (
     <div className="card border-0 rounded-lg shadow overflow-hidden">
@@ -106,6 +110,7 @@ const OfficialBotSettingsAccordion = () => {
           <AdminUpdateButtonRow
             disabled={false}
             // TODO: Add Proxy URL submit logic
+            // eslint-disable-next-line no-console
             onClick={() => console.log('Update')}
           />
         </div>
@@ -149,4 +154,13 @@ const OfficialBotSettingsAccordion = () => {
   );
 };
 
-export default OfficialBotSettingsAccordion;
+/**
+ * Wrapper component for using unstated
+ */
+const OfficialBotSettingsAccordionWrapper = withUnstatedContainers(OfficialBotSettingsAccordion, [AppContainer]);
+
+OfficialBotSettingsAccordion.propTypes = {
+  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
+};
+
+export default OfficialBotSettingsAccordionWrapper;

+ 0 - 1
src/client/styles/scss/_admin.scss

@@ -114,7 +114,6 @@ $slack-work-space-name-card-border: #efc1f6;
       border-left: 2px solid;
     }
     .slack-connection-log-body {
-      min-height: 6rem;
       border: 2px solid;
     }
   }