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

Merge branch 'feat/search-implement' into feat/77524-search-result-conent-page

* feat/search-implement:
  fix: Slack Integration 'note' command causes expired_trigger_id error (#4629)
  remove unnesessary one line
  add react multiline clamp and adjust code indent
  use react multiline clamp
  use resgular expression
  change col lg to xl
  use multi-line truncation css
  modify comment
  remove overflowhidden and change name of search item
  slice snippet successfully
  add comment
  adjust search result card but regex is not working
Mao 4 лет назад
Родитель
Сommit
f8fd0deed6

+ 1 - 0
packages/app/package.json

@@ -133,6 +133,7 @@
     "prom-client": "^13.0.0",
     "react-card-flip": "^1.0.10",
     "react-image-crop": "^8.3.0",
+    "react-multiline-clamp": "^2.0.0",
     "reconnecting-websocket": "^4.4.0",
     "redis": "^3.0.2",
     "rimraf": "^3.0.0",

+ 1 - 1
packages/app/src/components/SearchPage.jsx

@@ -34,7 +34,7 @@ class SearchPage extends React.Component {
       selectedPages: new Set(),
       searchResultCount: 0,
       activePage: 1,
-      pagingLimit: 3, // change to an appropriate limit number
+      pagingLimit: 10, // change to an appropriate limit number
       excludeUsersHome: true,
       excludeTrash: true,
     };

+ 2 - 2
packages/app/src/components/SearchPage/SearchPageLayout.tsx

@@ -19,7 +19,7 @@ const SearchPageLayout: FC<Props> = (props: Props) => {
   return (
     <div className="content-main">
       <div className="search-result row" id="search-result">
-        <div className="col-lg-6  page-list search-result-list pr-0" id="search-result-list">
+        <div className="col-xl-6  page-list search-result-list pr-0" id="search-result-list">
           <nav><SearchControl></SearchControl></nav>
           <div className="d-flex align-items-start justify-content-between mt-1">
             <div className="search-result-meta">
@@ -31,7 +31,7 @@ const SearchPageLayout: FC<Props> = (props: Props) => {
             <ul className="page-list-ul page-list-ul-flat nav nav-pills"><SearchResultList></SearchResultList></ul>
           </div>
         </div>
-        <div className="col-lg-6 d-none d-lg-block search-result-content">
+        <div className="col-xl-6 d-none d-lg-block search-result-content">
           <SearchResultContent></SearchResultContent>
         </div>
       </div>

+ 14 - 5
packages/app/src/components/SearchPage/SearchResultListItem.tsx

@@ -1,4 +1,7 @@
 import React, { FC } from 'react';
+
+import Clamp from 'react-multiline-clamp';
+
 import { useTranslation } from 'react-i18next';
 import { UserPicture, PageListMeta, PagePathLabel } from '@growi/ui';
 import { DevidedPagePath } from '@growi/core';
@@ -85,7 +88,7 @@ const SearchResultListItem: FC<Props> = (props:Props) => {
   };
 
   return (
-    <li key={page._id} className={`page-list-li w-100 border-bottom pr-4 list-group-item-action ${isSelected ? 'active' : ''}`}>
+    <li key={page._id} className={`page-list-li search-page-item w-100 border-bottom pr-4 list-group-item-action ${isSelected ? 'active' : ''}`}>
       <a
         className="d-block pt-3"
         href={pageId}
@@ -117,13 +120,19 @@ const SearchResultListItem: FC<Props> = (props:Props) => {
                 <PageItemControl page={page} />
               </div>
             </div>
+            <div className="my-2">
+              <Clamp
+                lines={2}
+              >
+                {page.snippet
+                  ? <div className="mt-1">page.snippet</div>
+                  : <div className="mt-1" dangerouslySetInnerHTML={{ __html: page.elasticSearchResult.snippet }}></div>
+                }
+              </Clamp>
+            </div>
           </div>
         </div>
         {/* TODO: adjust snippet position */}
-        {page.snippet
-          ? <div className="mt-1">page.snippet</div>
-          : <div className="mt-1" dangerouslySetInnerHTML={{ __html: page.elasticSearchResult.snippet }}></div>
-        }
       </a>
     </li>
   );

+ 23 - 38
packages/app/src/server/service/slack-command-handler/note.js

@@ -1,8 +1,9 @@
 import loggerFactory from '~/utils/logger';
 
 const {
-  markdownSectionBlock, inputSectionBlock, inputBlock,
+  markdownHeaderBlock, inputSectionBlock, inputBlock, actionsBlock, buttonElement,
 } = require('@growi/slack');
+const { SlackCommandHandlerError } = require('../../models/vo/slack-command-handler-error');
 
 const logger = loggerFactory('growi:service:SlackCommandHandler:note');
 
@@ -14,58 +15,42 @@ module.exports = (crowi) => {
   const conversationsSelectElement = {
     action_id: 'conversation',
     type: 'conversations_select',
-    response_url_enabled: true,
     default_to_current_conversation: true,
   };
 
   handler.handleCommand = async(growiCommand, client, body, respondUtil) => {
-    await client.views.open({
-      trigger_id: body.trigger_id,
-
-      view: {
-        type: 'modal',
-        callback_id: 'note:createPage',
-        title: {
-          type: 'plain_text',
-          text: 'Take a note',
-        },
-        submit: {
-          type: 'plain_text',
-          text: 'Submit',
-        },
-        close: {
-          type: 'plain_text',
-          text: 'Cancel',
-        },
-        blocks: [
-          markdownSectionBlock('Take a note on GROWI'),
-          inputBlock(conversationsSelectElement, 'conversation', 'Channel name to display in the page to be created'),
-          inputSectionBlock('path', 'Page path', 'path_input', false, '/path'),
-          inputSectionBlock('contents', 'Contents', 'contents_input', true, 'Input with Markdown...'),
-        ],
-        private_metadata: JSON.stringify({ channelId: body.channel_id, channelName: body.channel_name }),
-      },
+    await respondUtil.respond({
+      text: 'Take a note on GROWI',
+      blocks: [
+        markdownHeaderBlock('Take a note on GROWI'),
+        inputBlock(conversationsSelectElement, 'conversation', 'Channel name to display in the page to be created'),
+        inputSectionBlock('path', 'Page path', 'path_input', false, '/path'),
+        inputSectionBlock('contents', 'Contents', 'contents_input', true, 'Input with Markdown...'),
+        actionsBlock(
+          buttonElement({ text: 'Cancel', actionId: 'note:cancel' }),
+          buttonElement({ text: 'Create page', actionId: 'note:createPage', style: 'primary' }),
+        ),
+
+      ],
     });
   };
 
+  handler.cancel = async function(client, interactionPayload, interactionPayloadAccessor, respondUtil) {
+    await respondUtil.deleteOriginal();
+  };
+
   handler.handleInteractions = async function(client, interactionPayload, interactionPayloadAccessor, handlerMethodName, respondUtil) {
     await this[handlerMethodName](client, interactionPayload, interactionPayloadAccessor, respondUtil);
   };
 
   handler.createPage = async function(client, interactionPayload, interactionPayloadAccessor, respondUtil) {
     const path = interactionPayloadAccessor.getStateValues()?.path.path_input.value;
-    const privateMetadata = interactionPayloadAccessor.getViewPrivateMetaData();
-    if (privateMetadata == null) {
-      await respondUtil.respond({
-        text: 'Error occurred',
-        blocks: [
-          markdownSectionBlock('Failed to create a page.'),
-        ],
-      });
-      return;
-    }
     const contentsBody = interactionPayloadAccessor.getStateValues()?.contents.contents_input.value;
+    if (path == null || contentsBody == null) {
+      throw new SlackCommandHandlerError('All parameters are required.');
+    }
     await createPageService.createPageInGrowi(interactionPayloadAccessor, path, contentsBody, respondUtil);
+    await respondUtil.deleteOriginal();
   };
 
   return handler;

+ 4 - 0
packages/app/src/styles/_search.scss

@@ -245,6 +245,10 @@
   }
 }
 
+.search-page-item {
+  height: 130px;
+}
+
 @include media-breakpoint-down(sm) {
   .grw-search-table {
     th {

+ 5 - 0
yarn.lock

@@ -16860,6 +16860,11 @@ react-motion@^0.5.0, react-motion@^0.5.2:
     prop-types "^15.5.8"
     raf "^3.1.0"
 
+react-multiline-clamp@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/react-multiline-clamp/-/react-multiline-clamp-2.0.0.tgz#913a2092368ef1b52c1c79364d506ba4af27e019"
+  integrity sha512-iPm3HxFD6LO63lE5ZnThiqs+6A3c+LW3WbsEM0oa0iNTa0qN4SKx/LK/6ZToSmXundEcQXBFVNzKDvgmExawTw==
+
 react-node-resolver@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/react-node-resolver/-/react-node-resolver-1.0.1.tgz#1798a729c0e218bf2f0e8ddf79c550d4af61d83a"