Jelajahi Sumber

Merge pull request #3830 from weseek/feat/5907-6185-imprv-accordion-header

Feat/5907 6185 imprv accordion header
Yuki Takei 4 tahun lalu
induk
melakukan
81a7b9097c

+ 10 - 5
packages/slack/src/utils/check-communicable.ts

@@ -92,16 +92,21 @@ export const getConnectionStatus = async(token:string): Promise<ConnectionStatus
 
 /**
  * Get token string to ConnectionStatus map
- * @param tokens Array of bot OAuth token
+ * @param keys Array of bot OAuth token or specific key
+ * @param botTokenResolver function to convert from key to token
  * @returns
  */
-export const getConnectionStatuses = async(tokens: string[]): Promise<{[key: string]: ConnectionStatus}> => {
-  const map = tokens
+export const getConnectionStatuses = async(keys: string[], botTokenResolver?: (key: string) => string): Promise<{[key: string]: ConnectionStatus}> => {
+  const map = keys
     .reduce<Promise<Map<string, ConnectionStatus>>>(
-      async(acc, token) => {
+      async(acc, key) => {
+        let token = key;
+        if (botTokenResolver != null) {
+          token = botTokenResolver(key);
+        }
         const status: ConnectionStatus = await getConnectionStatus(token);
 
-        (await acc).set(token, status);
+        (await acc).set(key, status);
         return acc;
       },
       // define initial accumulator

+ 9 - 5
packages/slackbot-proxy/src/controllers/growi-to-slack.ts

@@ -63,13 +63,17 @@ export class GrowiToSlackCtrl {
 
     logger.debug(`${relations.length} relations found`, relations);
 
-    // extract bot token
-    const tokens: string[] = relations
-      .map(relation => relation.installation?.data?.bot?.token)
-      .filter((v): v is string => v != null); // filter out null values
+    // key: tokenGtoP, value: botToken
+    const botTokenResolverMapping: {[tokenGtoP:string]:string} = {};
 
-    const connectionStatuses = await getConnectionStatuses(tokens);
+    relations.forEach((relation) => {
+      const botToken = relation.installation?.data?.bot?.token;
+      if (botToken != null) {
+        botTokenResolverMapping[relation.tokenGtoP] = botToken;
+      }
+    });
 
+    const connectionStatuses = await getConnectionStatuses(Object.keys(botTokenResolverMapping), (tokenGtoP:string) => botTokenResolverMapping[tokenGtoP]);
     return res.send({ connectionStatuses });
   }
 

+ 7 - 3
src/client/js/components/Admin/SlackIntegration/CustomBotWithProxySettings.jsx

@@ -105,12 +105,16 @@ const CustomBotWithProxySettings = (props) => {
 
       <div className="mx-3">
         {slackAppIntegrations.map((slackAppIntegration, i) => {
-          const { tokenGtoP, tokenPtoG } = slackAppIntegration;
+          const { tokenGtoP, tokenPtoG, _id } = slackAppIntegration;
+          const workspaceName = connectionStatuses[_id]?.workspaceName;
           return (
             <React.Fragment key={slackAppIntegration._id}>
-              <div className="d-flex justify-content-end">
+              <div className="my-3 d-flex align-items-center justify-content-between">
+                <h2 id={_id || `settings-accordions-${i}`}>
+                  {(workspaceName != null) ? `${workspaceName} Work Space` : `Settings #${i}`}
+                </h2>
                 <button
-                  className="my-3 btn btn-outline-danger"
+                  className="btn btn-outline-danger"
                   type="button"
                   onClick={() => setIntegrationIdToDelete(slackAppIntegration._id)}
                 >

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

@@ -48,7 +48,10 @@ const CustomBotWithoutProxySettings = (props) => {
     setSiteName(siteName);
   }, [appContainer]);
 
+  const workspaceName = connectionStatuses[props.slackBotToken]?.workspaceName;
+
   return (
+
     <>
       <h2 className="admin-setting-header">{t('admin:slack_integration.custom_bot_without_proxy_integration')}
         {/* TODO: add an appropriate links by GW-5614 */}
@@ -61,18 +64,21 @@ const CustomBotWithoutProxySettings = (props) => {
       />
 
       <h2 className="admin-setting-header">{t('admin:slack_integration.integration_procedure')}</h2>
-      <div className={(props.slackSigningSecret != null || props.slackBotToken != null) ? 'px-3 mb-5' : 'px-3 my-5'}>
-        <div className="d-flex justify-content-end">
+
+      <div className="px-3">
+        <div className="my-3 d-flex align-items-center justify-content-between">
+          <h2 id={props.slackBotToken || 'settings-accordions'}>
+            {(workspaceName != null) ? `${workspaceName} Work Space` : 'Settings'}
+          </h2>
           {(props.slackSigningSecret != null || props.slackBotToken != null) && (
             <button
-              className="btn text-danger border-danger my-4"
+              className="btn btn-outline-danger"
               type="button"
               onClick={() => setIsDeleteConfirmModalShown(true)}
             >{t('admin:slack_integration.reset')}
             </button>
           )}
         </div>
-        {/* {isConnectedFailed && (<>Settings #1 <span className="text-danger">{t('admin:slack_integration.integration_failed')}</span></>)} */}
         <CustomBotWithoutProxySettingsAccordion
           {...props}
           activeStep={botInstallationStep.CREATE_BOT}

+ 8 - 4
src/client/js/components/Admin/SlackIntegration/OfficialBotSettings.jsx

@@ -105,13 +105,17 @@ const OfficialBotSettings = (props) => {
       <h2 className="admin-setting-header">{t('admin:slack_integration.integration_procedure')}</h2>
 
       <div className="mx-3">
-        {slackAppIntegrations.map((slackAppIntegration) => {
-          const { tokenGtoP, tokenPtoG } = slackAppIntegration;
+        {slackAppIntegrations.map((slackAppIntegration, i) => {
+          const { tokenGtoP, tokenPtoG, _id } = slackAppIntegration;
+          const workspaceName = connectionStatuses[_id]?.workspaceName;
           return (
             <React.Fragment key={slackAppIntegration._id}>
-              <div className="d-flex justify-content-end">
+              <div className="my-3 d-flex align-items-center justify-content-between">
+                <h2 id={_id || `settings-accordions-${i}`}>
+                  {(workspaceName != null) ? `${workspaceName} Work Space` : `Settings #${i}`}
+                </h2>
                 <button
-                  className="my-3 btn btn-outline-danger"
+                  className="btn btn-outline-danger"
                   type="button"
                   onClick={() => setIsDeleteConfirmModalShown(true)}
                 >

+ 10 - 3
src/server/routes/apiv3/slack-integration-settings.js

@@ -149,7 +149,7 @@ module.exports = (crowi) => {
     }
 
     // retrieve connection statuses
-    let connectionStatuses;
+    let connectionStatuses = {};
     if (currentBotType == null) {
       // TODO imple null action
     }
@@ -183,8 +183,15 @@ module.exports = (crowi) => {
       if (proxyServerUri != null) {
         try {
           if (settings.slackAppIntegrations.length > 0) {
-            const tokenGtoPs = settings.slackAppIntegrations.map(slackAppIntegration => slackAppIntegration.tokenGtoP);
-            connectionStatuses = (await getConnectionStatusesFromProxy(tokenGtoPs)).connectionStatuses;
+            // 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) {