This is an automated email from the ASF dual-hosted git repository.

warren pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git


The following commit(s) were added to refs/heads/main by this push:
     new 998d84a1 feat(frontend): add tapd config-ui
998d84a1 is described below

commit 998d84a1a1ccf9c7838b0c73a4149680b77f69de
Author: Yingchu Chen <[email protected]>
AuthorDate: Thu Aug 4 02:36:23 2022 +0800

    feat(frontend): add tapd config-ui
    
    Signed-off-by: Yingchu Chen <[email protected]>
---
 .../src/components/Sidebar/MenuConfiguration.jsx   |  8 +++
 .../src/components/blueprints/ConnectionDialog.jsx |  6 ++
 .../blueprints/ProviderTransformationSettings.jsx  | 12 ++++
 .../src/components/pipelines/StageTaskName.jsx     |  1 +
 config-ui/src/data/Providers.js                    | 21 ++++++-
 config-ui/src/data/availablePlugins.js             |  2 +-
 config-ui/src/data/integrations.jsx                | 20 +++++++
 config-ui/src/hooks/useConnectionManager.jsx       | 10 ++++
 config-ui/src/hooks/usePipelineManager.jsx         |  3 +-
 config-ui/src/hooks/usePipelineValidation.jsx      |  3 +-
 config-ui/src/images/integrations/tapd.svg         |  6 ++
 .../src/pages/blueprints/create-blueprint.jsx      |  9 +++
 .../pages/configure/connections/AddConnection.jsx  |  3 +-
 .../configure/connections/ConfigureConnection.jsx  |  6 +-
 .../pages/configure/connections/ConnectionForm.jsx |  2 +-
 .../pages/configure/connections/EditConnection.jsx |  3 +-
 config-ui/src/pages/configure/settings/tapd.jsx    | 65 ++++++++++++++++++++++
 config-ui/src/pages/pipelines/activity.jsx         | 19 +++++++
 plugins/tapd/api/connection.go                     | 17 +++---
 plugins/tapd/models/connection.go                  |  6 +-
 plugins/tapd/tasks/company_extractor.go            |  2 +-
 21 files changed, 201 insertions(+), 23 deletions(-)

diff --git a/config-ui/src/components/Sidebar/MenuConfiguration.jsx 
b/config-ui/src/components/Sidebar/MenuConfiguration.jsx
index c6fad4d4..a291c472 100644
--- a/config-ui/src/components/Sidebar/MenuConfiguration.jsx
+++ b/config-ui/src/components/Sidebar/MenuConfiguration.jsx
@@ -59,6 +59,14 @@ const MenuConfiguration = (activeRoute) => {
           active: activeRoute.url.endsWith('/integrations/jenkins') || 
activeRoute.url.endsWith('/jenkins'),
           icon: 'layers',
           classNames: [],
+        },
+        {
+          id: 4,
+          label: ProviderLabels.TAPD,
+          route: '/integrations/tapd',
+          active: activeRoute.url.endsWith('/integrations/tapd') || 
activeRoute.url.endsWith('/tapd'),
+          icon: 'layers',
+          classNames: [],
         }
       ]
     },
diff --git a/config-ui/src/components/blueprints/ConnectionDialog.jsx 
b/config-ui/src/components/blueprints/ConnectionDialog.jsx
index 05079dcd..04245623 100644
--- a/config-ui/src/components/blueprints/ConnectionDialog.jsx
+++ b/config-ui/src/components/blueprints/ConnectionDialog.jsx
@@ -75,6 +75,12 @@ const DATA_SOURCES_LIST = [
     title: ProviderLabels[Providers.JENKINS.toUpperCase()],
     value: Providers.JENKINS,
   },
+  {
+    id: 5,
+    name: Providers.TAPD,
+    title: ProviderLabels[Providers.TAPD.toUpperCase()],
+    value: Providers.TAPD,
+  },
 ]
 
 const ConnectionDialog = (props) => {
diff --git 
a/config-ui/src/components/blueprints/ProviderTransformationSettings.jsx 
b/config-ui/src/components/blueprints/ProviderTransformationSettings.jsx
index d92dbaa0..a86281e5 100644
--- a/config-ui/src/components/blueprints/ProviderTransformationSettings.jsx
+++ b/config-ui/src/components/blueprints/ProviderTransformationSettings.jsx
@@ -27,6 +27,7 @@ import { DataEntities, DataEntityTypes } from 
'@/data/DataEntities'
 import JiraSettings from '@/pages/configure/settings/jira'
 import GitlabSettings from '@/pages/configure/settings/gitlab'
 import JenkinsSettings from '@/pages/configure/settings/jenkins'
+import TapdSettings from '@/pages/configure/settings/tapd'
 import GithubSettings from '@/pages/configure/settings/github'
 
 const ProviderTransformationSettings = (props) => {
@@ -107,6 +108,17 @@ const ProviderTransformationSettings = (props) => {
           isSavingConnection={isSavingConnection}
         />
       )}
+      {provider?.id === Providers.TAPD && (
+        <TapdSettings
+          provider={provider}
+          connection={connection}
+          transformation={transformation}
+          onSettingsChange={onSettingsChange}
+          entities={entities[connection?.id]}
+          isSaving={isSaving}
+          isSavingConnection={isSavingConnection}
+        />
+      )}
     </div>
   )
 }
diff --git a/config-ui/src/components/pipelines/StageTaskName.jsx 
b/config-ui/src/components/pipelines/StageTaskName.jsx
index 80610392..cb84f881 100644
--- a/config-ui/src/components/pipelines/StageTaskName.jsx
+++ b/config-ui/src/components/pipelines/StageTaskName.jsx
@@ -92,6 +92,7 @@ const StageTaskName = (props) => {
                   {task.plugin === Providers.GITEXTRACTOR && 
(<>{ProviderLabels.GITEXTRACTOR}</>)}
                   {task.plugin === Providers.FEISHU && 
(<>{ProviderLabels.FEISHU}</>)}
                   {task.plugin === Providers.JENKINS && 
(<>{ProviderLabels.JENKINS}</>)}
+                  {task.plugin === Providers.TAPD && 
(<>{ProviderLabels.TAPD}</>)}
                   {task.plugin === Providers.JIRA && (<>Board ID 
{task.options.boardId}</>)}
                   {task.plugin === Providers.GITLAB && (<>Project ID 
{task.options.projectId}</>)}
                   {task.plugin === Providers.GITHUB && task.plugin !== 
Providers.JENKINS && (<>@{task.options.owner}/{task.options.repo}</>)}
diff --git a/config-ui/src/data/Providers.js b/config-ui/src/data/Providers.js
index e7db3131..caa94c93 100644
--- a/config-ui/src/data/Providers.js
+++ b/config-ui/src/data/Providers.js
@@ -21,6 +21,7 @@ import { ReactComponent as GitlabProviderIcon } from 
'@/images/integrations/gitl
 import { ReactComponent as JenkinsProviderIcon } from 
'@/images/integrations/jenkins.svg'
 import { ReactComponent as JiraProviderIcon } from 
'@/images/integrations/jira.svg'
 import { ReactComponent as GitHubProviderIcon } from 
'@/images/integrations/github.svg'
+import { ReactComponent as TapdProviderIcon } from 
'@/images/integrations/tapd.svg'
 // import GitExtractorIcon from '@/images/git.png'
 // import RefDiffIcon from '@/images/git-diff.png'
 import FeishuIcon from '@/images/feishu.png'
@@ -39,6 +40,7 @@ const Providers = {
   AE: 'ae',
   DBT: 'dbt',
   STARROCKS: 'starrocks',
+  TAPD: 'tapd',
 }
 
 const ProviderTypes = {
@@ -59,6 +61,7 @@ const ProviderLabels = {
   AE: 'Analysis Engine (AE)',
   DBT: 'Data Build Tool (DBT)',
   STARROCKS: 'StarRocks',
+  TAPD: 'TAPD',
 }
 
 const ProviderConnectionLimits = {
@@ -96,11 +99,18 @@ const ProviderFormLabels = {
     username: 'Username',
     password: 'Password'
   },
-  jira: {
+  tapd: {
     name: 'Connection Name',
     endpoint: 'Endpoint URL',
     proxy: 'Proxy URL',
     token: 'Basic Auth Token',
+    username: 'Username',
+    password: 'Password',
+  },
+  jira: {
+    name: 'Connection Name',
+    endpoint: 'Endpoint URL',
+    token: 'Basic Auth Token',
     username: 'Username / E-mail',
     // password; 'Password',
     password: (
@@ -181,6 +191,14 @@ const ProviderFormPlaceholders = {
     username: 'eg. admin',
     password: 'eg. ************'
   },
+  tapd: {
+    name: 'eg. Tapd',
+    endpoint: 'URL eg. https://api.tapd.cn/',
+    proxy: 'eg. http://proxy.localhost:8080',
+    token: 'eg. 6b057ffe68464c93a057',
+    username: 'eg. admin',
+    password: 'eg. ************'
+  },
   jira: {
     name: 'eg. JIRA',
     endpoint: 'eg. https://your-domain.atlassian.net/rest/',
@@ -202,6 +220,7 @@ const ProviderFormPlaceholders = {
 const ProviderIcons = {
   [Providers.GITLAB]: (w, h) => <GitlabProviderIcon width={w || 24} height={h 
|| 24} />,
   [Providers.JENKINS]: (w, h) => <JenkinsProviderIcon width={w || 24} 
height={h || 24} />,
+  [Providers.TAPD]: (w, h) => <TapdProviderIcon width={w || 24} height={h || 
24} />,
   [Providers.JIRA]: (w, h) => <JiraProviderIcon width={w || 24} height={h || 
24} />,
   [Providers.GITHUB]: (w, h) => <GitHubProviderIcon width={w || 24} height={h 
|| 24} />,
   [Providers.REFDIFF]: (w, h) => <Icon icon='box' size={w || 24} />,
diff --git a/config-ui/src/data/availablePlugins.js 
b/config-ui/src/data/availablePlugins.js
index 6827c54f..4433f79c 100644
--- a/config-ui/src/data/availablePlugins.js
+++ b/config-ui/src/data/availablePlugins.js
@@ -15,6 +15,6 @@
  * limitations under the License.
  *
  */
-const AVAILABLE_PLUGINS = ['gitlab', 'jira', 'jenkins', 'github']
+const AVAILABLE_PLUGINS = ['gitlab', 'jira', 'jenkins', 'github', 'tapd']
 
 module.exports = AVAILABLE_PLUGINS
diff --git a/config-ui/src/data/integrations.jsx 
b/config-ui/src/data/integrations.jsx
index a63a0ae1..6a947747 100644
--- a/config-ui/src/data/integrations.jsx
+++ b/config-ui/src/data/integrations.jsx
@@ -22,12 +22,14 @@ import { Providers, ProviderLabels, ProviderTypes } from 
'@/data/Providers'
 import JiraSettings from '@/pages/configure/settings/jira'
 import GitlabSettings from '@/pages/configure/settings/gitlab'
 import JenkinsSettings from '@/pages/configure/settings/jenkins'
+import TapdSettings from '@/pages/configure/settings/tapd'
 import GithubSettings from '@/pages/configure/settings/github'
 
 import { ReactComponent as GitlabProvider } from 
'@/images/integrations/gitlab.svg'
 import { ReactComponent as JenkinsProvider } from 
'@/images/integrations/jenkins.svg'
 import { ReactComponent as JiraProvider } from '@/images/integrations/jira.svg'
 import { ReactComponent as GitHubProvider } from 
'@/images/integrations/github.svg'
+import { ReactComponent as TapdProvider } from '@/images/integrations/tapd.svg'
 // import GitExtractorProvider from '@/images/git.png'
 // import RefDiffProvider from '@/images/git-diff.png'
 // import { ReactComponent as NullProvider } from 
'@/images/integrations/null.svg'
@@ -69,6 +71,24 @@ const integrationsData = [
       />
     )
   },
+  {
+    id: Providers.TAPD,
+    type: ProviderTypes.INTEGRATION,
+    enabled: true,
+    multiConnection: true,
+    name: ProviderLabels.TAPD,
+    icon: <TapdProvider className='providerIconSvg' width='30' height='30' 
style={{ float: 'left', marginTop: '5px' }} />,
+    iconDashboard: <TapdProvider className='providerIconSvg' width='40' 
height='40' />,
+    settings: ({ activeProvider, activeConnection, isSaving, 
isSavingConnection, setSettings }) => (
+      <TapdSettings
+        provider={activeProvider}
+        connection={activeConnection}
+        isSaving={isSaving}
+        isSavingConnection={isSavingConnection}
+        onSettingsChange={setSettings}
+      />
+    )
+  },
   {
     id: Providers.JIRA,
     type: ProviderTypes.INTEGRATION,
diff --git a/config-ui/src/hooks/useConnectionManager.jsx 
b/config-ui/src/hooks/useConnectionManager.jsx
index aa762d6d..37e2c03a 100644
--- a/config-ui/src/hooks/useConnectionManager.jsx
+++ b/config-ui/src/hooks/useConnectionManager.jsx
@@ -149,6 +149,16 @@ function useConnectionManager (
           ...connectionPayload,
         }
         break
+      case Providers.TAPD:
+        connectionPayload = {
+          name: name,
+          endpoint: endpointUrl,
+          username: username,
+          password: password,
+          proxy: proxy,
+          ...connectionPayload,
+        }
+        break
       case Providers.GITHUB:
         connectionPayload = {
           name: name,
diff --git a/config-ui/src/hooks/usePipelineManager.jsx 
b/config-ui/src/hooks/usePipelineManager.jsx
index b2d7f8e0..5f29e417 100644
--- a/config-ui/src/hooks/usePipelineManager.jsx
+++ b/config-ui/src/hooks/usePipelineManager.jsx
@@ -53,7 +53,8 @@ function usePipelineManager (myPipelineName = `COLLECTION 
${Date.now()}`, initia
     Providers.GITEXTRACTOR,
     Providers.FEISHU,
     Providers.AE,
-    Providers.DBT
+    Providers.DBT,
+    Providers.TAPD
   ])
 
   const PIPELINES_ENDPOINT = useMemo(() => `${DEVLAKE_ENDPOINT}/pipelines`, 
[DEVLAKE_ENDPOINT])
diff --git a/config-ui/src/hooks/usePipelineValidation.jsx 
b/config-ui/src/hooks/usePipelineValidation.jsx
index 43e86092..a8e10d77 100644
--- a/config-ui/src/hooks/usePipelineValidation.jsx
+++ b/config-ui/src/hooks/usePipelineValidation.jsx
@@ -56,7 +56,8 @@ function usePipelineValidation ({
     Providers.FEISHU,
     Providers.AE,
     Providers.DBT,
-    Providers.STARROCKS
+    Providers.STARROCKS,
+    Providers.TAPD
   ])
 
   const clear = () => {
diff --git a/config-ui/src/images/integrations/tapd.svg 
b/config-ui/src/images/integrations/tapd.svg
new file mode 100644
index 00000000..b228e608
--- /dev/null
+++ b/config-ui/src/images/integrations/tapd.svg
@@ -0,0 +1,6 @@
+<svg width="100" height="100" viewBox="0 0 36 36" fill="none" 
xmlns="http://www.w3.org/2000/svg";>
+<path d="M30.1151 10.3491L27.9087 3.35706L4.95635 10.3491L6.96429 
17.3253L15.0198 15.0396L19.4008 29.492L26.5992 27.246L22.1389 12.8491L30.1151 
10.3491Z" fill="#7497F7"/>
+<path d="M2.25 33.6666H15.2659L2.25 12.0317V33.6666Z" fill="#7497F7"/>
+<path d="M33.0119 2.33325L27.2103 33.6666H33.75V2.33325H33.0119Z" 
fill="#7497F7"/>
+<path d="M2.25 2.33325V8.6904L23.6944 2.33325H2.25Z" fill="#7497F7"/>
+</svg>
diff --git a/config-ui/src/pages/blueprints/create-blueprint.jsx 
b/config-ui/src/pages/blueprints/create-blueprint.jsx
index df0aad25..560da912 100644
--- a/config-ui/src/pages/blueprints/create-blueprint.jsx
+++ b/config-ui/src/pages/blueprints/create-blueprint.jsx
@@ -494,6 +494,7 @@ const CreateBlueprint = (props) => {
     switch (configuredConnection.provider) {
       case Providers.GITLAB:
       case Providers.JIRA:
+      case Providers.TAPD:
       case Providers.GITHUB:
         items = dataEntitiesList.filter((d) => d.name !== 'ci-cd')
         break
@@ -550,6 +551,11 @@ const CreateBlueprint = (props) => {
             ...newScope,
           }
           break
+        case Providers.TAPD:
+          newScope = {
+            ...newScope,
+          }
+          break
         case Providers.GITHUB:
           newScope = projects[connection.id]?.map((p) => ({
             ...newScope,
@@ -905,6 +911,9 @@ const CreateBlueprint = (props) => {
         case Providers.JENKINS:
           // No Transform Settings...
           break
+        case Providers.TAPD:
+          // No Transform Settings...
+          break
         case Providers.GITLAB:
           // No Transform Settings...
           break
diff --git a/config-ui/src/pages/configure/connections/AddConnection.jsx 
b/config-ui/src/pages/configure/connections/AddConnection.jsx
index 7013609b..4ad749bf 100644
--- a/config-ui/src/pages/configure/connections/AddConnection.jsx
+++ b/config-ui/src/pages/configure/connections/AddConnection.jsx
@@ -112,6 +112,7 @@ export default function AddConnection () {
         case Providers.GITHUB:
         case Providers.GITLAB:
         case Providers.JIRA:
+        case Providers.TAPD:
         default:
           setName('')
           break
@@ -184,7 +185,7 @@ export default function AddConnection () {
                   allTestResponses={allTestResponses}
                   errors={errors}
                   showError={showError}
-                  authType={[Providers.JENKINS, 
Providers.JIRA].includes(activeProvider.id) ? 'plain' : 'token'}
+                  authType={[Providers.JENKINS, Providers.JIRA, 
Providers.TAPD].includes(activeProvider.id) ? 'plain' : 'token'}
                   sourceLimits={ProviderConnectionLimits}
                   labels={ProviderFormLabels[activeProvider.id]}
                   placeholders={ProviderFormPlaceholders[activeProvider.id]}
diff --git a/config-ui/src/pages/configure/connections/ConfigureConnection.jsx 
b/config-ui/src/pages/configure/connections/ConfigureConnection.jsx
index 5234f5c2..bbc60ba6 100644
--- a/config-ui/src/pages/configure/connections/ConfigureConnection.jsx
+++ b/config-ui/src/pages/configure/connections/ConfigureConnection.jsx
@@ -216,7 +216,7 @@ export default function ConfigureConnection () {
                     </div>
                     {activeConnection && (
                       <>
-                        {[Providers.GITLAB, 
Providers.JIRA].includes(activeProvider.id) &&
+                        {[Providers.GITLAB, Providers.JIRA, 
Providers.TAPD].includes(activeProvider.id) &&
                         (<h2 style={{ margin: 0 }}>#{activeConnection.ID} 
{activeConnection.name}</h2>)}
                         <p className='page-description'>Manage settings and 
options for this connection.</p>
                       </>
@@ -255,7 +255,7 @@ export default function ConfigureConnection () {
                             username={username}
                             password={password}
                             // JIRA and GITLAB are multi-connection plugins, 
for now we intentially won't include additional settings during save...
-                            onSave={() => saveConnection(![Providers.GITLAB, 
Providers.JIRA].includes(activeProvider.id) ? settings : {})}
+                            onSave={() => saveConnection(![Providers.GITLAB, 
Providers.JIRA,Providers.TAPD].includes(activeProvider.id) ? settings : {})}
                             onTest={testConnection}
                             onCancel={cancel}
                             onValidate={validate}
@@ -272,7 +272,7 @@ export default function ConfigureConnection () {
                             allTestResponses={allTestResponses}
                             errors={errors}
                             showError={showConnectionError}
-                            authType={[Providers.JENKINS, 
Providers.JIRA].includes(activeProvider.id) ? 'plain' : 'token'}
+                            authType={[Providers.JENKINS, Providers.JIRA, 
Providers.TAPD].includes(activeProvider.id) ? 'plain' : 'token'}
                             showLimitWarning={false}
                             sourceLimits={ProviderConnectionLimits}
                             labels={ProviderFormLabels[activeProvider.id]}
diff --git a/config-ui/src/pages/configure/connections/ConnectionForm.jsx 
b/config-ui/src/pages/configure/connections/ConnectionForm.jsx
index dc9cf9a6..c929fa54 100644
--- a/config-ui/src/pages/configure/connections/ConnectionForm.jsx
+++ b/config-ui/src/pages/configure/connections/ConnectionForm.jsx
@@ -702,7 +702,7 @@ export default function ConnectionForm (props) {
             </div>
           </>
         )}
-        {[Providers.GITHUB, Providers.GITLAB, Providers.JIRA].includes(
+        {[Providers.GITHUB, Providers.GITLAB, Providers.JIRA, 
Providers.TAPD].includes(
           activeProvider.id
         ) && (
           <div className='formContainer'>
diff --git a/config-ui/src/pages/configure/connections/EditConnection.jsx 
b/config-ui/src/pages/configure/connections/EditConnection.jsx
index 2631170a..d1bfc377 100644
--- a/config-ui/src/pages/configure/connections/EditConnection.jsx
+++ b/config-ui/src/pages/configure/connections/EditConnection.jsx
@@ -76,6 +76,7 @@ export default function EditConnection () {
     setEndpointUrl(activeConnection.endpoint)
     switch (activeProvider.id) {
       case Providers.JENKINS:
+      case Providers.TAPD:
       case Providers.JIRA:
         setUsername(activeConnection.username)
         setPassword(activeConnection.password)
@@ -155,7 +156,7 @@ export default function EditConnection () {
                   testStatus={testStatus}
                   errors={errors}
                   showError={showError}
-                  authType={[Providers.JENKINS, 
Providers.JIRA].includes(activeProvider.id) ? 'plain' : 'token'}
+                  authType={[Providers.JENKINS, Providers.JIRA, 
Providers.TAPD].includes(activeProvider.id) ? 'plain' : 'token'}
                   sourceLimits={ProviderConnectionLimits}
                   labels={ProviderFormLabels[activeProvider.id]}
                   placeholders={ProviderFormPlaceholders[activeProvider.id]}
diff --git a/config-ui/src/pages/configure/settings/tapd.jsx 
b/config-ui/src/pages/configure/settings/tapd.jsx
new file mode 100644
index 00000000..cf8aa021
--- /dev/null
+++ b/config-ui/src/pages/configure/settings/tapd.jsx
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+import React, { useEffect, useState } from 'react'
+import {
+  useParams,
+  useHistory
+} from 'react-router-dom'
+import { DataEntityTypes } from '@/data/DataEntities'
+
+import '@/styles/integration.scss'
+import '@/styles/connections.scss'
+
+export default function TapdSettings (props) {
+  const { provider, connection, entities = [], onSettingsChange = () => {} } = 
props
+  const history = useHistory()
+  const { providerId, connectionId } = useParams()
+
+  // eslint-disable-next-line max-len
+  const [errors, setErrors] = useState([])
+
+  const cancel = () => {
+    history.push(`/integrations/${provider.id}`)
+  }
+
+  // useEffect(() => {
+  //   setErrors(['This integration doesn’t require any configuration.'])
+  // }, [])
+
+  useEffect(() => {
+    onSettingsChange({
+      errors,
+      providerId,
+      connectionId
+    })
+  }, [errors, onSettingsChange, connectionId, providerId])
+
+  return (
+    <>
+      <div className='headlineContainer'>
+        <h3 className='headline'>No Additional Settings</h3>
+        <p className='description'>
+          This integration doesn’t require any configuration.
+          You can continue to&nbsp;
+          <a href='#' style={{ textDecoration: 'underline' }} 
onClick={cancel}>add other data connections</a>&nbsp;
+          or trigger collection at the <a href='#' style={{ textDecoration: 
'underline' }} onClick={cancel}>previous page</a>.
+        </p>
+      </div>
+    </>
+  )
+}
diff --git a/config-ui/src/pages/pipelines/activity.jsx 
b/config-ui/src/pages/pipelines/activity.jsx
index c127e941..015244f8 100644
--- a/config-ui/src/pages/pipelines/activity.jsx
+++ b/config-ui/src/pages/pipelines/activity.jsx
@@ -44,6 +44,7 @@ import TaskActivity from '@/components/pipelines/TaskActivity'
 import CodeInspector from '@/components/pipelines/CodeInspector'
 import { ReactComponent as GitlabProviderIcon } from 
'@/images/integrations/gitlab.svg'
 import { ReactComponent as JenkinsProviderIcon } from 
'@/images/integrations/jenkins.svg'
+import { ReactComponent as TapdProviderIcon } from 
'@/images/integrations/tapd.svg'
 import { ReactComponent as JiraProviderIcon } from 
'@/images/integrations/jira.svg'
 import { ReactComponent as GitHubProviderIcon } from 
'@/images/integrations/github.svg'
 import { ReactComponent as HelpIcon } from '@/images/help.svg'
@@ -507,6 +508,24 @@ const PipelineActivity = (props) => {
                         </div>
                       </div>
                     )}
+                    {pipelineHasProvider(Providers.TAPD) && (
+                      <div className='jenkins-settings' style={{ display: 
'flex' }}>
+                        <div style={{ display: 'flex', padding: '2px 6px' }}>
+                          <TapdProviderIcon width={24} height={24} />
+                        </div>
+                        <div>
+                          <label style={{ lineHeight: '100%', display: 
'block', fontSize: '10px', marginTop: '2px', marginBottom: '10px' }}>
+                            <strong style={{
+                              fontSize: '16px',
+                              fontWeight: 800
+                            }}
+                            >{ProviderLabels.TAPD}
+                            </strong><br />Auto-configured
+                          </label>
+                          <span style={{ color: Colors.GRAY3 }}>(No 
Settings)</span>
+                        </div>
+                      </div>
+                    )}
                     {pipelineHasProvider(Providers.JIRA) && (
                       <div className='jira-settings' style={{ display: 'flex', 
paddingLeft: '20px' }}>
                         <div style={{ display: 'flex', padding: '2px 6px' }}>
diff --git a/plugins/tapd/api/connection.go b/plugins/tapd/api/connection.go
index 9bc71985..a6cb97dd 100644
--- a/plugins/tapd/api/connection.go
+++ b/plugins/tapd/api/connection.go
@@ -41,38 +41,37 @@ import (
 // @Router /plugins/tapd/test [POST]
 func TestConnection(input *core.ApiResourceInput) (*core.ApiResourceOutput, 
error) {
        // process input
-       var params models.TestConnectionRequest
-       err := mapstructure.Decode(input.Body, &params)
+       var connection models.TestConnectionRequest
+       err := mapstructure.Decode(input.Body, &connection)
        if err != nil {
                return nil, err
        }
-       err = vld.Struct(params)
+       err = vld.Struct(connection)
        if err != nil {
                return nil, err
        }
 
        // verify multiple token in parallel
        // PLEASE NOTE: This works because GitHub API Client rotates tokens on 
each request
-       token := params.Auth
        apiClient, err := helper.NewApiClient(
                context.TODO(),
-               params.Endpoint,
+               connection.Endpoint,
                map[string]string{
-                       "Authorization": fmt.Sprintf("Basic %s", token),
+                       "Authorization": fmt.Sprintf("Basic %s", 
connection.GetEncodedToken()),
                },
                3*time.Second,
-               params.Proxy,
+               connection.Proxy,
                basicRes,
        )
        if err != nil {
-               return nil, fmt.Errorf("verify token failed for %s %w", token, 
err)
+               return nil, fmt.Errorf("verify token failed for %s %w", 
connection.Username, err)
        }
        res, err := apiClient.Get("/quickstart/testauth", nil, nil)
        if err != nil {
                return nil, err
        }
        if res.StatusCode == http.StatusUnauthorized {
-               return nil, fmt.Errorf("verify token failed for %s", token)
+               return nil, fmt.Errorf("verify token failed for %s", 
connection.Username)
        }
        if res.StatusCode != http.StatusOK {
                return nil, fmt.Errorf("unexpected status code: %d", 
res.StatusCode)
diff --git a/plugins/tapd/models/connection.go 
b/plugins/tapd/models/connection.go
index 50739886..c10f116b 100644
--- a/plugins/tapd/models/connection.go
+++ b/plugins/tapd/models/connection.go
@@ -25,9 +25,9 @@ import (
 )
 
 type TestConnectionRequest struct {
-       Endpoint string `json:"endpoint" validate:"required,url"`
-       Auth     string `json:"auth" validate:"required"`
-       Proxy    string `json:"proxy" gorm:"type:varchar(255)"`
+       Endpoint         string `json:"endpoint"`
+       Proxy            string `json:"proxy"`
+       helper.BasicAuth `mapstructure:",squash"`
 }
 
 type WorkspaceResponse struct {
diff --git a/plugins/tapd/tasks/company_extractor.go 
b/plugins/tapd/tasks/company_extractor.go
index 97bdc670..be7b6fb8 100644
--- a/plugins/tapd/tasks/company_extractor.go
+++ b/plugins/tapd/tasks/company_extractor.go
@@ -36,7 +36,7 @@ var ExtractCompanyMeta = core.SubTaskMeta{
 }
 
 func ExtractCompanies(taskCtx core.SubTaskContext) error {
-       rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, 
RAW_COMPANY_TABLE, false)
+       rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, 
RAW_COMPANY_TABLE, true)
        extractor, err := helper.NewApiExtractor(helper.ApiExtractorArgs{
                RawDataSubTaskArgs: *rawDataSubTaskArgs,
                Extract: func(row *helper.RawData) ([]interface{}, error) {

Reply via email to