Sfoglia il codice sorgente

Merge branch 'feat/GW-6710-slackbot-togetter-command' into feat/GW-6710-slackbot-togetter-command-choose-growi

hakumizuki 4 anni fa
parent
commit
0108e9c096

+ 17 - 4
CHANGES.md

@@ -1,13 +1,24 @@
 # CHANGES
 # CHANGES
 
 
-## v4.3.0-RC
+## v4.3.2-RC
+
+* 
+
+## v4.3.1
+
+* Fix: Build script for production
+
 
 
-* Support: Upgrade libs
-    * striptags
+
+## v4.3.0-RC
 
 
 ### BREAKING CHANGES
 ### BREAKING CHANGES
 
 
-None.
+* GROWI manages dependencies with `lerna`
+    * Use `npx lerna bootstrap` instead of `yarn install`
+* GROWI includes some official plugins in default
+    * Users no longer need to install [growi-plugin-lsx](https://github.com/weseek/growi-plugin-lsx), [growi-plugin-pukiwiki-like-linker](https://github.com/weseek/growi-plugin-pukiwiki-like-linker) and [growi-plugin-attachment-refs](https://github.com/weseek/growi-plugin-attachment-refs) before build client.
+
 
 
 Upgrading Guide: <https://docs.growi.org/en/admin-guide/upgrading/43x.html>
 Upgrading Guide: <https://docs.growi.org/en/admin-guide/upgrading/43x.html>
 
 
@@ -22,6 +33,8 @@ Upgrading Guide: <https://docs.growi.org/en/admin-guide/upgrading/43x.html>
 * Improvement: Mark users who failed to send invitation emails
 * Improvement: Mark users who failed to send invitation emails
 * Fix: lsx plugin in the custom sidebar does not work when showing search result page
 * Fix: lsx plugin in the custom sidebar does not work when showing search result page
 * Support: Switch the official docker base image from Alpine based to Ubuntu based
 * Support: Switch the official docker base image from Alpine based to Ubuntu based
+* Support: Upgrade libs
+    * striptags
 
 
 ## v4.2.21
 ## v4.2.21
 
 

+ 1 - 0
config/webpack.common.js

@@ -45,6 +45,7 @@ module.exports = (options) => {
       'styles/theme-island':      './src/client/styles/scss/theme/island.scss',
       'styles/theme-island':      './src/client/styles/scss/theme/island.scss',
       'styles/theme-antarctic':      './src/client/styles/scss/theme/antarctic.scss',
       'styles/theme-antarctic':      './src/client/styles/scss/theme/antarctic.scss',
       'styles/theme-spring':         './src/client/styles/scss/theme/spring.scss',
       'styles/theme-spring':         './src/client/styles/scss/theme/spring.scss',
+      'styles/theme-hufflepuff':         './src/client/styles/scss/theme/hufflepuff.scss',
       // styles for external services
       // styles for external services
       'styles/style-hackmd':          './src/client/styles/hackmd/style.scss',
       'styles/style-hackmd':          './src/client/styles/hackmd/style.scss',
     }, options.entry || {}), // Merge with env dependent settings
     }, options.entry || {}), // Merge with env dependent settings

+ 2 - 1
package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "growi",
   "name": "growi",
-  "version": "4.3.0-RC",
+  "version": "4.3.2-RC",
   "description": "Team collaboration software using markdown",
   "description": "Team collaboration software using markdown",
   "tags": [
   "tags": [
     "wiki",
     "wiki",
@@ -34,6 +34,7 @@
     "build:dev:watch": "npm run build:dev:app:watch",
     "build:dev:watch": "npm run build:dev:app:watch",
     "build:dev:watch:poll": "npm run build:dev:app:watch:poll",
     "build:dev:watch:poll": "npm run build:dev:app:watch:poll",
     "build:dev": "yarn build:dev:app",
     "build:dev": "yarn build:dev:app",
+    "build:prod": "yarn lerna run build --scope @growi/app --scope @growi/slack",
     "build:slack": "lerna run build --scope @growi/slack",
     "build:slack": "lerna run build --scope @growi/slack",
     "build": "npm run build:dev:watch",
     "build": "npm run build:dev:watch",
     "build:poll": "npm run build:dev:watch:poll",
     "build:poll": "npm run build:dev:watch:poll",

+ 11 - 1
packages/slack/src/utils/block-kit-builder.ts

@@ -63,11 +63,20 @@ export function inputBlock(
   };
   };
 }
 }
 
 
+type ButtonElement = {
+  text: string,
+  actionId: string,
+  style?: string,
+  value?:string
+}
+
 /**
 /**
  * Button element
  * Button element
  * https://api.slack.com/reference/block-kit/block-elements#button
  * https://api.slack.com/reference/block-kit/block-elements#button
  */
  */
-export function buttonElement(text: string, actionId: string, style?: string): Button {
+export function buttonElement({
+  text, actionId, style, value,
+}:ButtonElement): Button {
   const button: Button = {
   const button: Button = {
     type: 'button',
     type: 'button',
     text: {
     text: {
@@ -75,6 +84,7 @@ export function buttonElement(text: string, actionId: string, style?: string): B
       text,
       text,
     },
     },
     action_id: actionId,
     action_id: actionId,
+    value,
   };
   };
   if (style === 'primary' || style === 'danger') {
   if (style === 'primary' || style === 'danger') {
     button.style = style;
     button.style = style;

BIN
public/images/themes/hufflepuff/badger-dark.jpg


BIN
public/images/themes/hufflepuff/badger-light.png


BIN
public/images/themes/hufflepuff/badger-light3.png


+ 2 - 0
src/client/js/components/Admin/Customize/CustomizeThemeOptions.jsx

@@ -20,6 +20,8 @@ class CustomizeThemeOptions extends React.Component {
       name: 'default',    bg: '#ffffff', topbar: '#2a2929', sidebar: '#122c55', theme: '#209fd8',
       name: 'default',    bg: '#ffffff', topbar: '#2a2929', sidebar: '#122c55', theme: '#209fd8',
     }, {
     }, {
       name: 'mono-blue',  bg: '#F7FBFD', topbar: '#2a2929', sidebar: '#00587A', theme: '#00587A',
       name: 'mono-blue',  bg: '#F7FBFD', topbar: '#2a2929', sidebar: '#00587A', theme: '#00587A',
+    }, {
+      name: 'hufflepuff',  bg: '#EFE2CF', topbar: '#2a2929', sidebar: '#EAAB20', theme: '#993439',
     }];
     }];
 
 
     const uniqueTheme = [{
     const uniqueTheme = [{

+ 1 - 1
src/client/js/components/Admin/Security/LdapAuthTest.jsx

@@ -114,7 +114,7 @@ class LdapAuthTest extends React.Component {
 
 
         <div className="form-group">
         <div className="form-group">
           <label><h5>Logs</h5></label>
           <label><h5>Logs</h5></label>
-          <textarea id="taLogs" className="col" rows="4" value={this.state.logs} readOnly />
+          <textarea id="taLogs" className="col form-control" rows="4" value={this.state.logs} readOnly />
         </div>
         </div>
 
 
         <div>
         <div>

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

@@ -28,6 +28,8 @@ const SlackIntegration = (props) => {
   const [slackAppIntegrations, setSlackAppIntegrations] = useState();
   const [slackAppIntegrations, setSlackAppIntegrations] = useState();
   const [proxyServerUri, setProxyServerUri] = useState();
   const [proxyServerUri, setProxyServerUri] = useState();
   const [connectionStatuses, setConnectionStatuses] = useState({});
   const [connectionStatuses, setConnectionStatuses] = useState({});
+  const [errorMsg, setErrorMsg] = useState(null);
+  const [errorCode, setErrorCode] = useState(null);
   const [isLoading, setIsLoading] = useState(true);
   const [isLoading, setIsLoading] = useState(true);
 
 
 
 
@@ -38,6 +40,8 @@ const SlackIntegration = (props) => {
         slackSigningSecret, slackBotToken, slackSigningSecretEnvVars, slackBotTokenEnvVars, slackAppIntegrations, proxyServerUri,
         slackSigningSecret, slackBotToken, slackSigningSecretEnvVars, slackBotTokenEnvVars, slackAppIntegrations, proxyServerUri,
       } = data.settings;
       } = data.settings;
 
 
+      setErrorMsg(data.errorMsg);
+      setErrorCode(data.errorCode);
       setConnectionStatuses(data.connectionStatuses);
       setConnectionStatuses(data.connectionStatuses);
       setCurrentBotType(data.currentBotType);
       setCurrentBotType(data.currentBotType);
       setSlackSigningSecret(slackSigningSecret);
       setSlackSigningSecret(slackSigningSecret);
@@ -194,6 +198,12 @@ const SlackIntegration = (props) => {
           </a> */}
           </a> */}
         </h2>
         </h2>
 
 
+        { errorCode && (
+          <div className="alert alert-warning">
+            <strong>ERROR: </strong>{errorMsg} ({errorCode})
+          </div>
+        ) }
+
         <div className="d-flex justify-content-end">
         <div className="d-flex justify-content-end">
           <button
           <button
             className="btn btn-outline-danger"
             className="btn btn-outline-danger"

+ 2 - 2
src/client/js/components/Me/AssociateModal.jsx

@@ -71,7 +71,7 @@ class AssociateModal extends React.Component {
 
 
     return (
     return (
       <Modal isOpen={this.props.isOpen} toggle={this.props.onClose} size="lg">
       <Modal isOpen={this.props.isOpen} toggle={this.props.onClose} size="lg">
-        <ModalHeader className="bg-info text-light" toggle={this.props.onClose}>
+        <ModalHeader className="bg-primary text-light" toggle={this.props.onClose}>
           { t('admin:user_management.create_external_account') }
           { t('admin:user_management.create_external_account') }
         </ModalHeader>
         </ModalHeader>
         <ModalBody>
         <ModalBody>
@@ -118,7 +118,7 @@ class AssociateModal extends React.Component {
           </div>
           </div>
         </ModalBody>
         </ModalBody>
         <ModalFooter className="border-top-0">
         <ModalFooter className="border-top-0">
-          <button type="button" className="btn btn-info mt-3" onClick={this.onClickAddBtn}>
+          <button type="button" className="btn btn-primary mt-3" onClick={this.onClickAddBtn}>
             <i className="fa fa-plus-circle" aria-hidden="true"></i>
             <i className="fa fa-plus-circle" aria-hidden="true"></i>
             {t('add')}
             {t('add')}
           </button>
           </button>

+ 310 - 0
src/client/styles/scss/theme/hufflepuff.scss

@@ -0,0 +1,310 @@
+@import '../variables';
+@import '../override-bootstrap-variables';
+
+// == Define Bootstrap theme colors
+//
+
+// colors for overriding bootstrap $theme-colors
+// $secondary: #;
+// $info: #;
+// $success: #;
+// $warning: #;
+// $danger: #;
+// $light: #;
+// $dark: #;
+
+// .grw-navbar {
+//   border-bottom: $accentcolor 4px solid;
+// }
+
+//== Light Mode
+//
+html[light] {
+  // Theme colors
+  $themecolor: #eaab20;
+  $themelight: #efe2cf;
+  $subthemecolor: #231e1d;
+  $third-main-color: #f0c05a;
+  $accentcolor: #993439;
+
+  $primary: $themecolor;
+  // $secondary: $subthemecolor;
+  $secondary: $third-main-color;
+
+  // Background colors
+  $bgcolor-global: lighten($themelight, 10%);
+  $bgcolor-inline-code: $gray-100; //optional
+  $bgcolor-card: $gray-100;
+  $bgcolor-highlighted: rgba($primary, 0.5);
+
+  // Font colors
+  $color-global: $subthemecolor;
+  $color-reversal: white;
+  $color-link: $accentcolor;
+  $color-link-hover: lighten($accentcolor, 10%);
+  $color-link-wiki: $accentcolor;
+  $color-link-wiki-hover: lighten($color-link-wiki, 10%);
+  $color-link-nabvar: $color-reversal;
+  $color-inline-code: #c7254e; // optional
+
+  // List Group colors
+  // $color-list: $color-global;
+  $bgcolor-list: transparent;
+  $color-list-hover: lighten($themecolor, 10%);
+  // $bgcolor-list-hover: darken($bgcolor-list, 2%);
+  // $color-list-active: $bgcolor-global;
+  // $bgcolor-list-active: $accentcolor;
+
+  // Navbar
+  $bgcolor-navbar: $third-main-color;
+  $bgcolor-search-top-dropdown: $themecolor;
+  $border-image-navbar: linear-gradient(to right, #90a555 0%, #a84be6 50%, #eaab20 100%);
+
+  // Logo colors
+  $bgcolor-logo: $bgcolor-navbar;
+  $fillcolor-logo-mark: lighten(desaturate($bgcolor-inline-code, 10%), 15%);
+
+  // Sidebar
+  $bgcolor-sidebar: $themecolor;
+  // Sidebar resize button
+  $color-resize-button: $color-reversal;
+  $bgcolor-resize-button: $subthemecolor;
+  $color-resize-button-hover: $color-reversal;
+  $bgcolor-resize-button-hover: lighten($bgcolor-resize-button, 10%);
+  // Sidebar contents
+  $color-sidebar-context: $accentcolor;
+  $bgcolor-sidebar-context: lighten($themelight, 8%);
+  // Sidebar list group
+  $bgcolor-sidebar-list-group: lighten($themelight, 10%);
+
+  // Icon colors
+  $color-editor-icons: $accentcolor;
+
+  // Border colors
+  $border-color-theme: lighten($subthemecolor, 40%);
+  $bordercolor-inline-code: #ccc8c8; // optional
+
+  // Dropdown colors
+  $bgcolor-dropdown-link-active: $growi-blue;
+  $color-dropdown-link-active: $color-reversal;
+  $color-dropdown-link-hover: $color-global;
+
+  // admin theme box
+  $color-theme-color-box: darken($primary, 5%);
+
+  @import 'apply-colors';
+  @import 'apply-colors-light';
+
+  //Button
+  .btn.btn-outline-primary {
+    @include btn-page-editor-mode-manager(darken($primary, 50%), darken($primary, 50%), lighten($primary, 20%));
+  }
+  .btn-group.grw-page-editor-mode-manager {
+    .btn.btn-outline-primary {
+      @include btn-page-editor-mode-manager(darken($primary, 70%), lighten($primary, 5%), lighten($primary, 20%));
+    }
+  }
+
+  .growi:not(.login-page) {
+    // add background-image
+    #page-wrapper,
+    .page-editor-preview-container {
+      background-image: url('/images/themes/hufflepuff/badger-light3.png');
+      background-attachment: fixed;
+      background-position: bottom;
+      background-size: cover;
+    }
+  }
+
+  // login and register
+  .nologin {
+    #page-wrapper {
+      background-color: $themelight;
+      background-image: url('/images/themes/hufflepuff/badger-light.png');
+      background-attachment: fixed;
+      background-position: bottom;
+      background-size: cover;
+    }
+
+    .login-header,
+    .login-dialog {
+      background-color: rgba(black, 0.1);
+    }
+
+    .link-switch {
+      color: $color-global;
+    }
+
+    .grw-external-auth-form {
+      border-color: $accentcolor !important;
+    }
+  }
+
+  .table {
+    background-color: $bgcolor-global;
+  }
+
+  .card-timeline > .card-header {
+    background-color: $third-main-color;
+  }
+
+  .nav.nav-tabs {
+    > .nav-item {
+      > .nav-link.active {
+        color: $subthemecolor;
+      }
+    }
+  }
+}
+
+html[dark] {
+  // Theme colors
+  $themecolor: #eaab20;
+  $themedark: #3d3f38;
+  $subthemecolor: #231e1d;
+  $third-main-color: #967224;
+  $accentcolor: #993439;
+
+  $primary: darken($themecolor, 10%);
+  $secondary: $third-main-color;
+  $dark: #031018;
+
+  // Background colors
+  $bgcolor-global: $themedark;
+  // $bgcolor-navbar: #27343b;
+  $bgcolor-inline-code: $subthemecolor;
+  $bgcolor-card: darken($themedark, 5%);
+  $bgcolor-highlighted: rgba($primary, 0.5);
+
+  // Font colors
+  $color-global: #efe2cf;
+  $color-reversal: $gray-100;
+  $color-link: lighten($themecolor, 20%);
+  $color-link-hover: lighten($color-link, 10%);
+  $color-link-wiki: lighten($primary, 20%);
+  $color-link-wiki-hover: lighten($color-link-wiki, 20%);
+  $color-link-nabvar: $color-reversal;
+  $color-inline-code: $themecolor;
+  // $color-inline-code: #c7254e; // optional
+  // $color-search: #000102;
+
+  // List Group colors
+  // $color-list: $color-global;
+  $bgcolor-list: transparent;
+  $color-list-hover: $accentcolor;
+  // $bgcolor-list-hover: lighten($bgcolor-global, 3%);
+  // $color-list-active: $color-reversal;
+  // $bgcolor-list-active: $primary;
+
+  // Navbar
+  $bgcolor-navbar: $third-main-color;
+  $bgcolor-search-top-dropdown: $themecolor;
+  $border-image-navbar: linear-gradient(to right, #90a555 0%, #3d98a3 50%, #eaab20 100%);
+
+  // Logo colors
+  $bgcolor-logo: #13191c;
+  $fillcolor-logo-mark: white;
+
+  // Sidebar
+  $bgcolor-sidebar: $themecolor;
+  // $bgcolor-sidebar-nav-item-active: rgba(#, 0.3); // optional
+  $text-shadow-sidebar-nav-item-active: 0px 0px 10px #cc951e; // optional
+  // Sidebar resize button
+  $color-resize-button: $color-global;
+  $bgcolor-resize-button: $accentcolor;
+  $color-resize-button-hover: $color-global;
+  $bgcolor-resize-button-hover: darken($bgcolor-resize-button, 7%);
+  // Sidebar contents
+  $color-sidebar-context: $color-global;
+  $bgcolor-sidebar-context: $subthemecolor;
+  // Sidebar list group
+  $bgcolor-sidebar-list-group: lighten($subthemecolor, 5%);
+
+  // Icon colors
+  $color-editor-icons: $themecolor;
+
+  // Border colors
+  $border-color-theme: darken($themecolor, 25%);
+  $bordercolor-inline-code: #4d4d4d; // optional
+
+  // Dropdown colors
+  $bgcolor-dropdown-link-active: $primary;
+  $color-dropdown-link-active: $color-global;
+  $color-dropdown-link-hover: $color-reversal;
+
+  // admin theme box
+  $color-theme-color-box: $primary;
+
+  @import 'apply-colors';
+  @import 'apply-colors-dark';
+
+  // Navs
+  .nav-tabs {
+    border-bottom: $border-color-theme 1px solid;
+    .nav-link {
+      &:hover {
+        border-color: lighten($border-color-theme, 10%);
+        border-bottom: none;
+      }
+      &.active {
+        color: $color-link;
+        background-color: transparent;
+        border-color: $border-color-theme;
+      }
+    }
+  }
+
+  // Table
+  .table {
+    color: white;
+  }
+
+  // Button
+  .btn.btn-outline-primary {
+    @include btn-page-editor-mode-manager(lighten($primary, 40%), lighten($primary, 15%), darken($primary, 10%), darken($primary, 30%));
+  }
+  .btn-group.grw-page-editor-mode-manager {
+    .btn.btn-outline-primary {
+      @include btn-page-editor-mode-manager(lighten($primary, 40%), lighten($primary, 15%), darken($primary, 0%), darken($primary, 30%));
+    }
+  }
+
+  .card-timeline > .card-header {
+    background-color: $accentcolor;
+  }
+
+  .growi:not(.login-page) {
+    // add background-image
+    #page-wrapper,
+    .page-editor-preview-container {
+      background-image: url('/images/themes/hufflepuff/badger-dark.jpg');
+      background-attachment: fixed;
+      background-position: bottom;
+      background-size: cover;
+    }
+  }
+
+  // login and register
+  .nologin {
+    #page-wrapper {
+      background-color: $themedark;
+      background-image: url('/images/themes/hufflepuff/badger-light.png');
+      background-attachment: fixed;
+      background-position: bottom;
+      background-size: cover;
+    }
+
+    .login-header,
+    .login-dialog {
+      background-color: rgba(black, 0.1);
+    }
+
+    .link-switch {
+      color: $color-global;
+    }
+
+    .grw-external-auth-form {
+      border-color: $accentcolor !important;
+    }
+  }
+}

+ 28 - 26
src/server/routes/apiv3/slack-integration-settings.js

@@ -153,8 +153,10 @@ module.exports = (crowi) => {
 
 
     // retrieve connection statuses
     // retrieve connection statuses
     let connectionStatuses = {};
     let connectionStatuses = {};
+    let errorMsg;
+    let errorCode;
     if (currentBotType == null) {
     if (currentBotType == null) {
-      // TODO imple null action
+      // no need to do anything
     }
     }
     else if (currentBotType === 'customBotWithoutProxy') {
     else if (currentBotType === 'customBotWithoutProxy') {
       const token = settings.slackBotToken;
       const token = settings.slackBotToken;
@@ -163,10 +165,10 @@ module.exports = (crowi) => {
         try {
         try {
           connectionStatuses = await getConnectionStatuses([token]);
           connectionStatuses = await getConnectionStatuses([token]);
         }
         }
-        catch (error) {
-          const msg = 'Error occured in getting connection statuses';
-          logger.error('Error', error);
-          return res.apiv3Err(new ErrorV3(msg, 'get-connection-failed'), 500);
+        catch (e) {
+          errorMsg = 'Error occured in getting connection statuses';
+          errorCode = 'get-connection-failed';
+          logger.error(errorMsg, e);
         }
         }
       }
       }
     }
     }
@@ -175,37 +177,37 @@ module.exports = (crowi) => {
         const slackAppIntegrations = await SlackAppIntegration.find();
         const slackAppIntegrations = await SlackAppIntegration.find();
         settings.slackAppIntegrations = slackAppIntegrations;
         settings.slackAppIntegrations = slackAppIntegrations;
       }
       }
-      catch (error) {
-        const msg = 'Error occured in getting connection statuses';
-        logger.error('Error', error);
-        return res.apiv3Err(new ErrorV3(msg, 'get-connection-failed'), 500);
+      catch (e) {
+        errorMsg = 'Error occured in finding SlackAppIntegration entities.';
+        errorCode = 'get-slackappintegration-failed';
+        logger.error(errorMsg, e);
       }
       }
 
 
       const proxyServerUri = settings.proxyServerUri;
       const proxyServerUri = settings.proxyServerUri;
 
 
-      if (proxyServerUri != null) {
+      if (proxyServerUri != null && settings.slackAppIntegrations != null && settings.slackAppIntegrations.length > 0) {
         try {
         try {
-          if (settings.slackAppIntegrations.length > 0) {
-            // key: slackAppIntegration.tokenGtoP, value: slackAppIntegration._id
-            const tokenGtoPToSlackAppIntegrationId = {};
-            settings.slackAppIntegrations.forEach((slackAppIntegration) => {
-              tokenGtoPToSlackAppIntegrationId[slackAppIntegration.tokenGtoP] = slackAppIntegration._id;
-            });
-            const result = (await getConnectionStatusesFromProxy(Object.keys(tokenGtoPToSlackAppIntegrationId)));
-            Object.entries(result.connectionStatuses).forEach(([tokenGtoP, connectionStatus]) => {
-              connectionStatuses[tokenGtoPToSlackAppIntegrationId[tokenGtoP]] = connectionStatus;
-            });
-          }
+          // key: slackAppIntegration.tokenGtoP, value: slackAppIntegration._id
+          const tokenGtoPToSlackAppIntegrationId = {};
+          settings.slackAppIntegrations.forEach((slackAppIntegration) => {
+            tokenGtoPToSlackAppIntegrationId[slackAppIntegration.tokenGtoP] = slackAppIntegration._id;
+          });
+          const result = (await getConnectionStatusesFromProxy(Object.keys(tokenGtoPToSlackAppIntegrationId)));
+          Object.entries(result.connectionStatuses).forEach(([tokenGtoP, connectionStatus]) => {
+            connectionStatuses[tokenGtoPToSlackAppIntegrationId[tokenGtoP]] = connectionStatus;
+          });
         }
         }
-        catch (error) {
-          const msg = 'Incorrect Proxy URL';
-          logger.error('Error', error);
-          return res.apiv3Err(new ErrorV3(msg, 'test-connection-failed'), 400);
+        catch (e) {
+          errorMsg = 'Incorrect Proxy URL';
+          errorCode = 'test-connection-failed';
+          logger.error(errorMsg, e);
         }
         }
       }
       }
     }
     }
 
 
-    return res.apiv3({ currentBotType, settings, connectionStatuses });
+    return res.apiv3({
+      currentBotType, settings, connectionStatuses, errorMsg, errorCode,
+    });
   });
   });
 
 
   /**
   /**

+ 9 - 8
src/server/routes/apiv3/slack-integration.js

@@ -148,6 +148,15 @@ module.exports = (crowi) => {
         await crowi.slackBotService.showEphemeralSearchResults(client, body, args, newOffset);
         await crowi.slackBotService.showEphemeralSearchResults(client, body, args, newOffset);
         break;
         break;
       }
       }
+      case 'togetterShowMore': {
+        const parsedValue = JSON.parse(payload.actions[0].value);
+        const togetterHandler = require('../../service/slack-command-handler/togetter')(crowi);
+
+        const { body, args, limit } = parsedValue;
+        const newLimit = limit + 1;
+        await togetterHandler.handleCommand(client, body, args, newLimit);
+        break;
+      }
       case 'togetterCreatePage': {
       case 'togetterCreatePage': {
         await crowi.slackBotService.togetterCreatePageInGrowi(client, payload);
         await crowi.slackBotService.togetterCreatePageInGrowi(client, payload);
         break;
         break;
@@ -156,14 +165,6 @@ module.exports = (crowi) => {
         console.log('Cancel here');
         console.log('Cancel here');
         break;
         break;
       }
       }
-      case 'showMoreTogetterResults': {
-        const parsedValue = JSON.parse(payload.actions[0].value);
-
-        const { body, args, limit } = parsedValue;
-        const newLimit = limit + 10;
-        await crowi.slackBotService.togetterCommand(client, body, args, newLimit);
-        break;
-      }
       default:
       default:
         break;
         break;
     }
     }

+ 20 - 18
src/server/service/slack-command-handler/togetter.js

@@ -1,6 +1,7 @@
 const {
 const {
   inputBlock, actionsBlock, buttonElement, checkboxesElementOption,
   inputBlock, actionsBlock, buttonElement, checkboxesElementOption,
 } = require('@growi/slack');
 } = require('@growi/slack');
+const { fromUnixTime, format } = require('date-fns');
 
 
 module.exports = () => {
 module.exports = () => {
   const BaseSlackCommandHandler = require('./slack-command-handler');
   const BaseSlackCommandHandler = require('./slack-command-handler');
@@ -8,46 +9,47 @@ module.exports = () => {
 
 
   handler.handleCommand = async function(client, body, args, limit = 10) {
   handler.handleCommand = async function(client, body, args, limit = 10) {
     // TODO GW-6721 Get the time from args
     // TODO GW-6721 Get the time from args
-    const reusult = await client.conversations.history({
+    const result = await client.conversations.history({
       channel: body.channel_id,
       channel: body.channel_id,
       limit,
       limit,
     });
     });
-    console.log(reusult);
-    // Return Checkbox Message
+      // Return Checkbox Message
     client.chat.postEphemeral({
     client.chat.postEphemeral({
       channel: body.channel_id,
       channel: body.channel_id,
       user: body.user_id,
       user: body.user_id,
       text: 'Select messages to use.',
       text: 'Select messages to use.',
-      blocks: this.togetterMessageBlocks(),
+      blocks: this.togetterMessageBlocks(result.messages, body, args, limit),
     });
     });
     return;
     return;
   };
   };
 
 
-  handler.togetterMessageBlocks = function() {
+  handler.togetterMessageBlocks = function(messages, body, args, limit) {
     return [
     return [
-      inputBlock(this.togetterCheckboxesElement(), 'selected_messages', 'Select massages to use.'),
-      actionsBlock(buttonElement('Show more', 'showMoreTogetterResults')),
+      inputBlock(this.togetterCheckboxesElement(messages), 'selected_messages', 'Select massages to use.'),
+      actionsBlock(buttonElement({ text: 'Show more', actionId: 'togetterShowMore', value: JSON.stringify({ body, args, limit }) })),
       inputBlock(this.togetterInputBlockElement('page_path', '/'), 'page_path', 'Page path'),
       inputBlock(this.togetterInputBlockElement('page_path', '/'), 'page_path', 'Page path'),
-      actionsBlock(buttonElement('Cancel', 'togetterCancelPageCreation'), buttonElement('Create page', 'togetterCreatePage', 'primary')),
+      actionsBlock(
+        buttonElement({ text: 'Cancel', actionId: 'togetterCancelPageCreation' }),
+        buttonElement({ text: 'Create page', actionId: 'togetterCreatePage', color: 'primary' }),
+      ),
     ];
     ];
   };
   };
 
 
-  handler.togetterCheckboxesElement = function() {
+  handler.togetterCheckboxesElement = function(messages) {
     return {
     return {
       type: 'checkboxes',
       type: 'checkboxes',
-      options: this.togetterCheckboxesElementOptions(),
+      options: this.togetterCheckboxesElementOptions(messages),
       action_id: 'checkboxes_changed',
       action_id: 'checkboxes_changed',
     };
     };
   };
   };
 
 
-  handler.togetterCheckboxesElementOptions = function() {
-    // increment options with results from conversations.history
-    const options = [];
-    // temporary code
-    for (let i = 0; i < 10; i++) {
-      const option = checkboxesElementOption('username  12:00 PM', 'sample slack messages ... :star:\nsample slack messages ... :star:\n', `selected-${i}`);
-      options.push(option);
-    }
+  handler.togetterCheckboxesElementOptions = function(messages) {
+    const options = messages
+      .sort((a, b) => { return a.ts - b.ts })
+      .map((message, index) => {
+        const date = fromUnixTime(message.ts);
+        return checkboxesElementOption(`*${message.user}*  ${format(new Date(date), 'yyyy/MM/dd HH:mm:ss')}`, message.text, `selected-${index}`);
+      });
     return options;
     return options;
   };
   };