You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@devlake.apache.org by kl...@apache.org on 2023/11/24 02:16:04 UTC
(incubator-devlake) branch main updated: feat(config-ui): unify the scope config style of the plug-in (#6503)
This is an automated email from the ASF dual-hosted git repository.
klesh 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 8965ceee7 feat(config-ui): unify the scope config style of the plug-in (#6503)
8965ceee7 is described below
commit 8965ceee787d1a98951642925f8470c74948826b
Author: 青湛 <0x...@gmail.com>
AuthorDate: Fri Nov 24 15:15:59 2023 +1300
feat(config-ui): unify the scope config style of the plug-in (#6503)
---
.../fields/additional-settings.tsx | 98 -----
.../components/scope-config-form/fields/index.ts | 19 -
.../components/scope-config-form/fields/styled.ts | 53 ---
.../plugins/components/scope-config-form/index.tsx | 130 ++++---
config-ui/src/plugins/register/azure/styled.ts | 63 ----
.../src/plugins/register/azure/transformation.tsx | 218 ++++++-----
.../src/plugins/register/bamboo/transformation.tsx | 105 ++++--
config-ui/src/plugins/register/bitbucket/styled.ts | 75 ----
.../plugins/register/bitbucket/transformation.tsx | 282 +++++++++-----
.../src/plugins/register/github/transformation.tsx | 128 ++++---
config-ui/src/plugins/register/gitlab/styled.ts | 38 --
.../src/plugins/register/gitlab/transformation.tsx | 103 ++++--
config-ui/src/plugins/register/jenkins/styled.ts | 62 ----
.../plugins/register/jenkins/transformation.tsx | 172 ++++-----
config-ui/src/plugins/register/jira/styled.ts | 46 ---
.../src/plugins/register/jira/transformation.tsx | 273 ++++++++------
config-ui/src/plugins/register/tapd/styled.ts | 47 ---
.../src/plugins/register/tapd/transformation.tsx | 406 ++++++++++++---------
18 files changed, 1088 insertions(+), 1230 deletions(-)
diff --git a/config-ui/src/plugins/components/scope-config-form/fields/additional-settings.tsx b/config-ui/src/plugins/components/scope-config-form/fields/additional-settings.tsx
deleted file mode 100644
index 79d831f39..000000000
--- a/config-ui/src/plugins/components/scope-config-form/fields/additional-settings.tsx
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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 { useState } from 'react';
-import { Switch, InputGroup } from '@blueprintjs/core';
-
-import { ExternalLink, HelpTooltip } from '@/components';
-import { DOC_URL } from '@/release';
-
-import * as S from './styled';
-
-interface Props {
- transformation: any;
- setTransformation: React.Dispatch<React.SetStateAction<any>>;
-}
-
-export const AdditionalSettings = ({ transformation, setTransformation }: Props) => {
- const [enable, setEnable] = useState(false);
-
- const handleChange = (e: React.FormEvent<HTMLInputElement>) => {
- const checked = (e.target as HTMLInputElement).checked;
-
- if (!checked) {
- setTransformation({
- ...transformation,
- refdiff: null,
- });
- }
-
- setEnable(checked);
- };
-
- return (
- <S.AdditionalSettings>
- <h2>
- <span>Additional Settings</span>
- <Switch alignIndicator="right" inline checked={enable} onChange={handleChange} />
- </h2>
- {enable && (
- <>
- <p>
- Enable the <ExternalLink link={DOC_URL.PLUGIN.REFDIFF}>RefDiff</ExternalLink> plugin to pre-calculate
- version-based metrics
- <HelpTooltip content="Calculate the commits diff between two consecutive tags that match the following RegEx. Issues closed by PRs which contain these commits will also be calculated. The result will be shown in table.refs_commits_diffs and table.refs_issues_diffs." />
- </p>
- <div className="refdiff">
- Compare the last
- <InputGroup
- style={{ width: 60 }}
- placeholder="10"
- value={transformation.refdiff?.tagsLimit ?? ''}
- onChange={(e) =>
- setTransformation({
- ...transformation,
- refdiff: {
- ...transformation?.refdiff,
- tagsLimit: +e.target.value,
- },
- })
- }
- />
- tags that match the
- <InputGroup
- style={{ width: 200 }}
- placeholder="(regex)$"
- value={transformation.refdiff?.tagsPattern ?? ''}
- onChange={(e) =>
- setTransformation({
- ...transformation,
- refdiff: {
- ...transformation?.refdiff,
- tagsPattern: e.target.value,
- },
- })
- }
- />
- for calculation
- </div>
- </>
- )}
- </S.AdditionalSettings>
- );
-};
diff --git a/config-ui/src/plugins/components/scope-config-form/fields/index.ts b/config-ui/src/plugins/components/scope-config-form/fields/index.ts
deleted file mode 100644
index f4a5a16e6..000000000
--- a/config-ui/src/plugins/components/scope-config-form/fields/index.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * 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.
- *
- */
-
-export * from './additional-settings';
diff --git a/config-ui/src/plugins/components/scope-config-form/fields/styled.ts b/config-ui/src/plugins/components/scope-config-form/fields/styled.ts
deleted file mode 100644
index bfdf077a4..000000000
--- a/config-ui/src/plugins/components/scope-config-form/fields/styled.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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 styled from 'styled-components';
-
-export const AdditionalSettings = styled.div`
- h2 {
- display: flex;
- align-items: center;
-
- .bp5-switch {
- margin: 0;
- }
- }
-
- .radio {
- display: flex;
- align-items: center;
- margin: 8px 0 16px;
-
- p {
- margin: 0;
- }
-
- .bp5-control {
- margin: 0;
- }
- }
-
- .refdiff {
- display: flex;
- align-items: center;
- padding-left: 20px;
-
- .bp5-input-group {
- margin: 0 8px;
- }
- }
-`;
diff --git a/config-ui/src/plugins/components/scope-config-form/index.tsx b/config-ui/src/plugins/components/scope-config-form/index.tsx
index 757d3eac0..613222f54 100644
--- a/config-ui/src/plugins/components/scope-config-form/index.tsx
+++ b/config-ui/src/plugins/components/scope-config-form/index.tsx
@@ -18,6 +18,7 @@
import { useState, useEffect, useMemo } from 'react';
import { omit } from 'lodash';
+import { Form } from 'antd';
import { InputGroup, Button, Intent } from '@blueprintjs/core';
import API from '@/api';
@@ -34,7 +35,6 @@ import { TapdTransformation } from '@/plugins/register/tapd';
import { BambooTransformation } from '@/plugins/register/bamboo';
import { operator } from '@/utils';
-import { AdditionalSettings } from './fields';
import { TIPS_MAP } from './misc';
import * as S from './styled';
@@ -61,14 +61,12 @@ export const ScopeConfigForm = ({
const [name, setName] = useState('');
const [entities, setEntities] = useState<string[]>([]);
const [transformation, setTransformation] = useState<any>({});
- const [hasRefDiff, setHasRefDiff] = useState(false);
const [hasError, setHasError] = useState(false);
const [operating, setOperating] = useState(false);
const config = useMemo(() => getPluginConfig(plugin), []);
useEffect(() => {
- setHasRefDiff(!!config.scopeConfig?.transformation.refdiff);
setTransformation(config.scopeConfig?.transformation ?? {});
}, [config.scopeConfig?.transformation]);
@@ -183,76 +181,76 @@ export const ScopeConfigForm = ({
/>
)}
- {plugin === 'github' && (
- <GitHubTransformation
- entities={entities}
- transformation={transformation}
- setTransformation={setTransformation}
- setHasError={setHasError}
- />
- )}
+ <Form labelCol={{ span: 4 }} wrapperCol={{ span: 16 }}>
+ {plugin === 'azuredevops' && (
+ <AzureTransformation
+ entities={entities}
+ transformation={transformation}
+ setTransformation={setTransformation}
+ />
+ )}
- {plugin === 'jira' && (
- <JiraTransformation
- entities={entities}
- connectionId={connectionId}
- transformation={transformation}
- setTransformation={setTransformation}
- />
- )}
+ {plugin === 'bamboo' && (
+ <BambooTransformation
+ entities={entities}
+ transformation={transformation}
+ setTransformation={setTransformation}
+ />
+ )}
- {plugin === 'gitlab' && (
- <GitLabTransformation
- entities={entities}
- transformation={transformation}
- setTransformation={setTransformation}
- setHasError={setHasError}
- />
- )}
+ {plugin === 'bitbucket' && (
+ <BitbucketTransformation
+ entities={entities}
+ transformation={transformation}
+ setTransformation={setTransformation}
+ />
+ )}
- {plugin === 'jenkins' && (
- <JenkinsTransformation
- entities={entities}
- transformation={transformation}
- setTransformation={setTransformation}
- />
- )}
+ {plugin === 'github' && (
+ <GitHubTransformation
+ entities={entities}
+ transformation={transformation}
+ setTransformation={setTransformation}
+ setHasError={setHasError}
+ />
+ )}
- {plugin === 'bitbucket' && (
- <BitbucketTransformation
- entities={entities}
- transformation={transformation}
- setTransformation={setTransformation}
- />
- )}
-
- {plugin === 'azuredevops' && (
- <AzureTransformation
- entities={entities}
- transformation={transformation}
- setTransformation={setTransformation}
- />
- )}
+ {plugin === 'gitlab' && (
+ <GitLabTransformation
+ entities={entities}
+ transformation={transformation}
+ setTransformation={setTransformation}
+ setHasError={setHasError}
+ />
+ )}
- {plugin === 'tapd' && scopeId && (
- <TapdTransformation
- entities={entities}
- connectionId={connectionId}
- scopeId={scopeId}
- transformation={transformation}
- setTransformation={setTransformation}
- />
- )}
+ {plugin === 'jenkins' && (
+ <JenkinsTransformation
+ entities={entities}
+ transformation={transformation}
+ setTransformation={setTransformation}
+ />
+ )}
- {plugin === 'bamboo' && (
- <BambooTransformation
- entities={entities}
- transformation={transformation}
- setTransformation={setTransformation}
- />
- )}
+ {plugin === 'jira' && (
+ <JiraTransformation
+ entities={entities}
+ connectionId={connectionId}
+ transformation={transformation}
+ setTransformation={setTransformation}
+ />
+ )}
- {hasRefDiff && <AdditionalSettings transformation={transformation} setTransformation={setTransformation} />}
+ {plugin === 'tapd' && scopeId && (
+ <TapdTransformation
+ entities={entities}
+ connectionId={connectionId}
+ scopeId={scopeId}
+ transformation={transformation}
+ setTransformation={setTransformation}
+ />
+ )}
+ </Form>
</Card>
<Buttons position="bottom" align="right">
<Button outlined intent={Intent.PRIMARY} text="Prev" onClick={handlePrevStep} />
diff --git a/config-ui/src/plugins/register/azure/styled.ts b/config-ui/src/plugins/register/azure/styled.ts
deleted file mode 100644
index 2502260e9..000000000
--- a/config-ui/src/plugins/register/azure/styled.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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 styled from 'styled-components';
-
-export const Transfromation = styled.div`
- .bp5-form-group {
- display: flex;
- align-items: center;
-
- .bp5-label {
- flex: 0 0 140px;
- }
-
- .bp5-form-content {
- flex: auto;
- }
- }
-`;
-
-export const CICD = styled.div`
- h3 {
- margin-top: 16px;
-
- .switch {
- display: inline-flex;
- align-items: center;
- margin-left: 16px;
- font-size: 14px;
- font-weight: 400;
-
- .bp5-switch {
- margin-bottom: 0;
- }
- }
- }
-
- .text {
- display: flex;
- align-items: baseline;
- margin-top: 16px;
- padding-left: 24px;
-
- .bp5-radio {
- margin-right: 0;
- }
- }
-`;
diff --git a/config-ui/src/plugins/register/azure/transformation.tsx b/config-ui/src/plugins/register/azure/transformation.tsx
index ece4ac960..df57ceb04 100644
--- a/config-ui/src/plugins/register/azure/transformation.tsx
+++ b/config-ui/src/plugins/register/azure/transformation.tsx
@@ -16,14 +16,12 @@
*
*/
-import { useState, useEffect } from 'react';
-import { Tag, Switch, InputGroup, Intent } from '@blueprintjs/core';
+import { CaretRightOutlined } from '@ant-design/icons';
+import { theme, Collapse, Tag, Input } from 'antd';
import { ExternalLink, HelpTooltip } from '@/components';
import { DOC_URL } from '@/release';
-import * as S from './styled';
-
interface Props {
entities: string[];
transformation: any;
@@ -31,90 +29,144 @@ interface Props {
}
export const AzureTransformation = ({ entities, transformation, setTransformation }: Props) => {
- const [enableCICD, setEnableCICD] = useState(true);
-
- useEffect(() => {
- if (!transformation.deploymentPattern) {
- setEnableCICD(false);
- }
- }, []);
-
- const handleChangeCICDEnable = (e: React.FormEvent<HTMLInputElement>) => {
- const checked = (e.target as HTMLInputElement).checked;
+ const { token } = theme.useToken();
- if (!checked) {
- setTransformation({
- ...transformation,
- deploymentPattern: undefined,
- productionPattern: undefined,
- });
- }
-
- setEnableCICD(checked);
+ const panelStyle: React.CSSProperties = {
+ marginBottom: 24,
+ background: token.colorFillAlter,
+ borderRadius: token.borderRadiusLG,
+ border: 'none',
};
return (
- <S.Transfromation>
- {entities.includes('CICD') && (
- <S.CICD>
- <h2>CI/CD</h2>
- <h3>
+ <Collapse
+ bordered={false}
+ defaultActiveKey={['CICD']}
+ expandIcon={({ isActive }) => <CaretRightOutlined rotate={isActive ? 90 : 0} rev="" />}
+ style={{ background: token.colorBgContainer }}
+ size="large"
+ items={renderCollapseItems({
+ entities,
+ panelStyle,
+ transformation,
+ onChangeTransformation: setTransformation,
+ })}
+ />
+ );
+};
+
+const renderCollapseItems = ({
+ entities,
+ panelStyle,
+ transformation,
+ onChangeTransformation,
+}: {
+ entities: string[];
+ panelStyle: React.CSSProperties;
+ transformation: any;
+ onChangeTransformation: any;
+}) =>
+ [
+ {
+ key: 'CICD',
+ label: 'CI/CD',
+ style: panelStyle,
+ children: (
+ <>
+ <h3 style={{ marginBottom: 16 }}>
<span>Deployment</span>
- <Tag minimal intent={Intent.PRIMARY} style={{ marginLeft: 8 }}>
+ <Tag style={{ marginLeft: 4 }} color="blue">
DORA
</Tag>
- <div className="switch">
- <span>Enable</span>
- <Switch alignIndicator="right" inline checked={enableCICD} onChange={handleChangeCICDEnable} />
- </div>
</h3>
- {enableCICD && (
- <>
- <p>
- Use Regular Expression to define Deployments in DevLake in order to measure DORA metrics.{' '}
- <ExternalLink link={DOC_URL.PLUGIN.AZUREDEVOPS.TRANSFORMATION}>Learn more</ExternalLink>
- </p>
- <div style={{ marginTop: 16 }}>Convert a Azure Pipeline Run as a DevLake Deployment when: </div>
- <div className="text">
- <span>
- The name of the <strong>Azure pipeline</strong> or <strong>one of its jobs</strong> matches
- </span>
- <InputGroup
- style={{ width: 200, margin: '0 8px' }}
- placeholder="(deploy|push-image)"
- value={transformation.deploymentPattern ?? ''}
- onChange={(e) =>
- setTransformation({
- ...transformation,
- deploymentPattern: e.target.value,
- productionPattern: !e.target.value ? '' : transformation.productionPattern,
- })
- }
- />
- <i style={{ color: '#E34040' }}>*</i>
- <HelpTooltip content="Azure Pipelines: https://learn.microsoft.com/en-us/azure/devops/pipelines/get-started/what-is-azure-pipelines?view=azure-devops#continuous-testing" />
- </div>
- <div className="text">
- <span>If the name also matches</span>
- <InputGroup
- style={{ width: 200, margin: '0 8px' }}
- disabled={!transformation.deploymentPattern}
- placeholder="prod(.*)"
- value={transformation.productionPattern ?? ''}
- onChange={(e) =>
- setTransformation({
- ...transformation,
- productionPattern: e.target.value,
- })
- }
- />
- <span>, this Deployment is a ‘Production Deployment’</span>
- <HelpTooltip content="If you leave this field empty, all DevLake Deployments will be tagged as in the Production environment. " />
- </div>
- </>
- )}
- </S.CICD>
- )}
- </S.Transfromation>
- );
-};
+ <p style={{ marginBottom: 16 }}>
+ Use Regular Expression to define Deployments in DevLake in order to measure DORA metrics.{' '}
+ <ExternalLink link={DOC_URL.PLUGIN.AZUREDEVOPS.TRANSFORMATION}>Learn more</ExternalLink>
+ </p>
+ <div>Convert a Azure Pipeline Run as a DevLake Deployment when: </div>
+ <div style={{ margin: '8px 0', paddingLeft: 28 }}>
+ <span>
+ The name of the <strong>Azure pipeline</strong> or <strong>one of its jobs</strong> matches
+ </span>
+ <Input
+ style={{ width: 200, margin: '0 8px' }}
+ placeholder="(deploy|push-image)"
+ value={transformation.deploymentPattern ?? ''}
+ onChange={(e) =>
+ onChangeTransformation({
+ ...transformation,
+ deploymentPattern: e.target.value,
+ productionPattern: !e.target.value ? '' : transformation.productionPattern,
+ })
+ }
+ />
+ <i style={{ color: '#E34040' }}>*</i>
+ <HelpTooltip content="Azure Pipelines: https://learn.microsoft.com/en-us/azure/devops/pipelines/get-started/what-is-azure-pipelines?view=azure-devops#continuous-testing" />
+ </div>
+ <div style={{ margin: '8px 0', paddingLeft: 28 }}>
+ <span>If the name also matches</span>
+ <Input
+ style={{ width: 200, margin: '0 8px' }}
+ placeholder="prod(.*)"
+ value={transformation.productionPattern ?? ''}
+ onChange={(e) =>
+ onChangeTransformation({
+ ...transformation,
+ productionPattern: e.target.value,
+ })
+ }
+ />
+ <span>, this Deployment is a ‘Production Deployment’</span>
+ <HelpTooltip content="If you leave this field empty, all DevLake Deployments will be tagged as in the Production environment. " />
+ </div>
+ </>
+ ),
+ },
+ {
+ key: 'ADDITIONAL',
+ label: 'Additional Settings',
+ style: panelStyle,
+ children: (
+ <>
+ <p>
+ Enable the <ExternalLink link={DOC_URL.PLUGIN.REFDIFF}>RefDiff</ExternalLink> plugin to pre-calculate
+ version-based metrics
+ <HelpTooltip content="Calculate the commits diff between two consecutive tags that match the following RegEx. Issues closed by PRs which contain these commits will also be calculated. The result will be shown in table.refs_commits_diffs and table.refs_issues_diffs." />
+ </p>
+ <div className="refdiff">
+ Compare the last
+ <Input
+ style={{ margin: '0 8px', width: 60 }}
+ placeholder="10"
+ value={transformation.refdiff?.tagsLimit ?? ''}
+ onChange={(e) =>
+ onChangeTransformation({
+ ...transformation,
+ refdiff: {
+ ...transformation?.refdiff,
+ tagsLimit: +e.target.value,
+ },
+ })
+ }
+ />
+ tags that match the
+ <Input
+ style={{ margin: '0 8px', width: 200 }}
+ placeholder="(regex)$"
+ value={transformation.refdiff?.tagsPattern ?? ''}
+ onChange={(e) =>
+ onChangeTransformation({
+ ...transformation,
+ refdiff: {
+ ...transformation?.refdiff,
+ tagsPattern: e.target.value,
+ },
+ })
+ }
+ />
+ for calculation
+ </div>
+ </>
+ ),
+ },
+ ].filter((it) => entities.includes(it.key) || it.key === 'ADDITIONAL');
diff --git a/config-ui/src/plugins/register/bamboo/transformation.tsx b/config-ui/src/plugins/register/bamboo/transformation.tsx
index fc04d528e..07c1fb35a 100644
--- a/config-ui/src/plugins/register/bamboo/transformation.tsx
+++ b/config-ui/src/plugins/register/bamboo/transformation.tsx
@@ -17,13 +17,12 @@
*/
import { useState, useEffect } from 'react';
-import { InputGroup, Tag, Intent, Checkbox } from '@blueprintjs/core';
+import { CaretRightOutlined } from '@ant-design/icons';
+import { theme, Collapse, Tag, Input, Checkbox } from 'antd';
import { ExternalLink, HelpTooltip } from '@/components';
import { DOC_URL } from '@/release';
-import * as S from './styled';
-
interface Props {
entities: string[];
transformation: any;
@@ -55,14 +54,59 @@ export const BambooTransformation = ({ entities, transformation, setTransformati
setUseCustom(checked);
};
+ const { token } = theme.useToken();
+
+ const panelStyle: React.CSSProperties = {
+ marginBottom: 24,
+ background: token.colorFillAlter,
+ borderRadius: token.borderRadiusLG,
+ border: 'none',
+ };
+
return (
- <S.Transformation>
- {entities.includes('CICD') && (
- <S.CICD>
- <h2>CI/CD</h2>
- <h3>
+ <Collapse
+ bordered={false}
+ defaultActiveKey={['TICKET', 'CICD']}
+ expandIcon={({ isActive }) => <CaretRightOutlined rotate={isActive ? 90 : 0} rev="" />}
+ style={{ background: token.colorBgContainer }}
+ size="large"
+ items={renderCollapseItems({
+ entities,
+ panelStyle,
+ transformation,
+ onChangeTransformation: setTransformation,
+ useCustom,
+ onChangeUseCustom: handleChangeUseCustom,
+ })}
+ />
+ );
+};
+
+const renderCollapseItems = ({
+ entities,
+ panelStyle,
+ transformation,
+ onChangeTransformation,
+ useCustom,
+ onChangeUseCustom,
+}: {
+ entities: string[];
+ panelStyle: React.CSSProperties;
+ transformation: any;
+ onChangeTransformation: any;
+ useCustom: boolean;
+ onChangeUseCustom: any;
+}) =>
+ [
+ {
+ key: 'CICD',
+ label: 'CI/CD',
+ style: panelStyle,
+ children: (
+ <>
+ <h3 style={{ marginBottom: 16 }}>
<span>Deployment</span>
- <Tag minimal intent={Intent.PRIMARY} style={{ marginLeft: 8 }}>
+ <Tag style={{ marginLeft: 4 }} color="blue">
DORA
</Tag>
</h3>
@@ -70,18 +114,17 @@ export const BambooTransformation = ({ entities, transformation, setTransformati
Use Regular Expression to define Deployments in DevLake in order to measure DORA metrics.{' '}
<ExternalLink link={DOC_URL.PLUGIN.BAMBOO.TRANSFORMATION}>Learn more</ExternalLink>
</p>
- <div className="text">
- <Checkbox disabled checked />
- <span>Convert a Bamboo Deployment to a DevLake Deployment </span>
- </div>
- <div className="sub-text">
+ <Checkbox disabled checked>
+ Convert a Bamboo Deployment to a DevLake Deployment
+ </Checkbox>
+ <div style={{ margin: '8px 0', paddingLeft: 28 }}>
<span>If its environment name matches</span>
- <InputGroup
+ <Input
style={{ width: 180, margin: '0 8px' }}
placeholder="(?i)prod(.*)"
value={transformation.envNamePattern}
onChange={(e) =>
- setTransformation({
+ onChangeTransformation({
...transformation,
envNamePattern: e.target.value,
})
@@ -89,20 +132,17 @@ export const BambooTransformation = ({ entities, transformation, setTransformati
/>
<span>, this deployment is a ‘Production Deployment’</span>
</div>
- <div className="text">
- <Checkbox checked={useCustom} onChange={handleChangeUseCustom} />
- <span>
- Convert a Bamboo Plan Build to a DevLake Deployment when its name or one of its job builds’ names
- </span>
- </div>
- <div className="sub-text">
+ <Checkbox checked={useCustom} onChange={onChangeUseCustom}>
+ Convert a Bamboo Plan Build to a DevLake Deployment when its name or one of its job builds’ names
+ </Checkbox>
+ <div style={{ margin: '8px 0', paddingLeft: 28 }}>
<span>matches</span>
- <InputGroup
+ <Input
style={{ width: 180, margin: '0 8px' }}
placeholder="(deploy|push-image)"
value={transformation.deploymentPattern ?? ''}
onChange={(e) =>
- setTransformation({
+ onChangeTransformation({
...transformation,
deploymentPattern: e.target.value,
productionPattern: !e.target.value ? '' : transformation.productionPattern,
@@ -112,14 +152,14 @@ export const BambooTransformation = ({ entities, transformation, setTransformati
<span>.</span>
<HelpTooltip content="View your Bamboo Builds: https://confluence.atlassian.com/bamboo/viewing-a-plan-s-build-information-289276861.html" />
</div>
- <div className="sub-text">
+ <div style={{ margin: '8px 0', paddingLeft: 28 }}>
<span>If the name also matches</span>
- <InputGroup
+ <Input
style={{ width: 180, margin: '0 8px' }}
placeholder="prod(.*)"
value={transformation.productionPattern ?? ''}
onChange={(e) =>
- setTransformation({
+ onChangeTransformation({
...transformation,
productionPattern: e.target.value,
})
@@ -128,8 +168,7 @@ export const BambooTransformation = ({ entities, transformation, setTransformati
<span>, this Deployment is a ‘Production Deployment’</span>
<HelpTooltip content="If you leave this field empty, all Deployments will be tagged as in the Production environment. " />
</div>
- </S.CICD>
- )}
- </S.Transformation>
- );
-};
+ </>
+ ),
+ },
+ ].filter((it) => entities.includes(it.key));
diff --git a/config-ui/src/plugins/register/bitbucket/styled.ts b/config-ui/src/plugins/register/bitbucket/styled.ts
deleted file mode 100644
index 2a60f6e6f..000000000
--- a/config-ui/src/plugins/register/bitbucket/styled.ts
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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 styled from 'styled-components';
-
-export const Transformation = styled.div`
- .issue-tracking {
- .issue-type {
- .title {
- margin-bottom: 8px;
- }
-
- .list {
- padding-left: 40px;
- }
- }
- }
-
- .bp5-form-group {
- display: flex;
- align-items: center;
-
- .bp5-label {
- flex: 0 0 140px;
- }
-
- .bp5-form-content {
- flex: auto;
- }
- }
-`;
-
-export const CICD = styled.div`
- h3 {
- margin-top: 16px;
-
- .switch {
- display: inline-flex;
- align-items: center;
- margin-left: 16px;
- font-size: 14px;
- font-weight: 400;
-
- .bp5-switch {
- margin-bottom: 0;
- }
- }
- }
-
- .text,
- .sub-text {
- display: flex;
- align-items: baseline;
- margin-bottom: 8px;
- }
-
- .sub-text {
- padding-left: 28px;
- }
-`;
diff --git a/config-ui/src/plugins/register/bitbucket/transformation.tsx b/config-ui/src/plugins/register/bitbucket/transformation.tsx
index 5124c65fd..f0562a538 100644
--- a/config-ui/src/plugins/register/bitbucket/transformation.tsx
+++ b/config-ui/src/plugins/register/bitbucket/transformation.tsx
@@ -17,13 +17,13 @@
*/
import { useMemo, useState, useEffect } from 'react';
-import { FormGroup, InputGroup, Tag, Intent, Checkbox } from '@blueprintjs/core';
+import { CaretRightOutlined } from '@ant-design/icons';
+import { theme, Collapse, Tag, Form, Input, Checkbox } from 'antd';
-import { ExternalLink, HelpTooltip, Divider, MultiSelector } from '@/components';
+import { ExternalLink, HelpTooltip, MultiSelector } from '@/components';
import { DOC_URL } from '@/release';
import ExampleJpg from './assets/bitbucket-example.jpg';
-import * as S from './styled';
interface Props {
entities: string[];
@@ -68,82 +68,130 @@ export const BitbucketTransformation = ({ entities, transformation, setTransform
setUseCustom(checked);
};
+ const { token } = theme.useToken();
+
+ const panelStyle: React.CSSProperties = {
+ marginBottom: 24,
+ background: token.colorFillAlter,
+ borderRadius: token.borderRadiusLG,
+ border: 'none',
+ };
+
return (
- <S.Transformation>
- {entities.includes('TICKET') && (
- <div className="issue-tracking">
- <h2>Issue Tracking</h2>
- <div className="issue-type">
- <div className="title">
- <span>Issue Status Mapping</span>
- <HelpTooltip content="Standardize your issue statuses to the following issue statuses to view metrics such as `Requirement Delivery Rate` in built-in dashboards." />
- </div>
- <div className="list">
- <FormGroup inline label="TODO">
- <MultiSelector
- items={ALL_STATES}
- disabledItems={selectedStates}
- selectedItems={transformation.issueStatusTodo ? transformation.issueStatusTodo.split(',') : []}
- onChangeItems={(selectedItems) =>
- setTransformation({
- ...transformation,
- issueStatusTodo: selectedItems.join(','),
- })
- }
- />
- </FormGroup>
- <FormGroup inline label="IN-PROGRESS">
- <MultiSelector
- items={ALL_STATES}
- disabledItems={selectedStates}
- selectedItems={
- transformation.issueStatusInProgress ? transformation.issueStatusInProgress.split(',') : []
- }
- onChangeItems={(selectedItems) =>
- setTransformation({
- ...transformation,
- issueStatusInProgress: selectedItems.join(','),
- })
- }
- />
- </FormGroup>
- <FormGroup inline label="DONE">
- <MultiSelector
- items={ALL_STATES}
- disabledItems={selectedStates}
- selectedItems={transformation.issueStatusDone ? transformation.issueStatusDone.split(',') : []}
- onChangeItems={(selectedItems) =>
- setTransformation({
- ...transformation,
- issueStatusDone: selectedItems.join(','),
- })
- }
- />
- </FormGroup>
- <FormGroup inline label="OTHER">
- <MultiSelector
- items={ALL_STATES}
- disabledItems={selectedStates}
- selectedItems={transformation.issueStatusOther ? transformation.issueStatusOther.split(',') : []}
- onChangeItems={(selectedItems) =>
- setTransformation({
- ...transformation,
- issueStatusOther: selectedItems.join(','),
- })
- }
- />
- </FormGroup>
- </div>
- </div>
- <Divider />
+ <Collapse
+ bordered={false}
+ defaultActiveKey={['TICKET', 'CICD']}
+ expandIcon={({ isActive }) => <CaretRightOutlined rotate={isActive ? 90 : 0} rev="" />}
+ style={{ background: token.colorBgContainer }}
+ size="large"
+ items={renderCollapseItems({
+ entities,
+ panelStyle,
+ selectedStates,
+ transformation,
+ onChangeTransformation: setTransformation,
+ useCustom,
+ onChangeUseCustom: handleChangeUseCustom,
+ })}
+ />
+ );
+};
+
+const renderCollapseItems = ({
+ entities,
+ panelStyle,
+ selectedStates,
+ transformation,
+ onChangeTransformation,
+ useCustom,
+ onChangeUseCustom,
+}: {
+ entities: string[];
+ panelStyle: React.CSSProperties;
+ selectedStates: any;
+ transformation: any;
+ onChangeTransformation: any;
+ useCustom: boolean;
+ onChangeUseCustom: any;
+}) =>
+ [
+ {
+ key: 'TICKET',
+ label: (
+ <>
+ <span>Issue Status Mapping</span>
+ <HelpTooltip content="Standardize your issue statuses to the following issue statuses to view metrics such as `Requirement Delivery Rate` in built-in dashboards." />
+ </>
+ ),
+ style: panelStyle,
+ children: (
+ <div className="list">
+ <Form.Item label="TODO">
+ <MultiSelector
+ items={ALL_STATES}
+ disabledItems={selectedStates}
+ selectedItems={transformation.issueStatusTodo ? transformation.issueStatusTodo.split(',') : []}
+ onChangeItems={(selectedItems) =>
+ onChangeTransformation({
+ ...transformation,
+ issueStatusTodo: selectedItems.join(','),
+ })
+ }
+ />
+ </Form.Item>
+ <Form.Item label="IN-PROGRESS">
+ <MultiSelector
+ items={ALL_STATES}
+ disabledItems={selectedStates}
+ selectedItems={
+ transformation.issueStatusInProgress ? transformation.issueStatusInProgress.split(',') : []
+ }
+ onChangeItems={(selectedItems) =>
+ onChangeTransformation({
+ ...transformation,
+ issueStatusInProgress: selectedItems.join(','),
+ })
+ }
+ />
+ </Form.Item>
+ <Form.Item label="DONE">
+ <MultiSelector
+ items={ALL_STATES}
+ disabledItems={selectedStates}
+ selectedItems={transformation.issueStatusDone ? transformation.issueStatusDone.split(',') : []}
+ onChangeItems={(selectedItems) =>
+ onChangeTransformation({
+ ...transformation,
+ issueStatusDone: selectedItems.join(','),
+ })
+ }
+ />
+ </Form.Item>
+ <Form.Item label="OTHER">
+ <MultiSelector
+ items={ALL_STATES}
+ disabledItems={selectedStates}
+ selectedItems={transformation.issueStatusOther ? transformation.issueStatusOther.split(',') : []}
+ onChangeItems={(selectedItems) =>
+ onChangeTransformation({
+ ...transformation,
+ issueStatusOther: selectedItems.join(','),
+ })
+ }
+ />
+ </Form.Item>
</div>
- )}
- {entities.includes('CICD') && (
- <S.CICD>
- <h2>CI/CD</h2>
- <h3>
+ ),
+ },
+ {
+ key: 'CICD',
+ label: 'CI/CD',
+ style: panelStyle,
+ children: (
+ <>
+ <h3 style={{ marginBottom: 16 }}>
<span>Deployment</span>
- <Tag minimal intent={Intent.PRIMARY} style={{ marginLeft: 8 }}>
+ <Tag style={{ marginLeft: 4 }} color="blue">
DORA
</Tag>
</h3>
@@ -151,23 +199,21 @@ export const BitbucketTransformation = ({ entities, transformation, setTransform
Use Regular Expression to define Deployments in DevLake in order to measure DORA metrics.{' '}
<ExternalLink link={DOC_URL.PLUGIN.BITBUCKET.TRANSFORMATION}>Learn more</ExternalLink>
</p>
- <div className="text">
- <Checkbox disabled checked />
- <span>Convert a BitBucket Deployment to a DevLake Deployment </span>
+ <Checkbox disabled checked>
+ <span>Convert a BitBucket Deployment to a DevLake Deployment</span>
<HelpTooltip content={<img src={ExampleJpg} alt="" width={400} />} />
- </div>
- <div className="text">
- <Checkbox checked={useCustom} onChange={handleChangeUseCustom} />
- <span>Convert a BitBucket Pipeline to a DevLake Deployment when its branch/tag name</span>
- </div>
- <div className="sub-text">
+ </Checkbox>
+ <Checkbox checked={useCustom} onChange={onChangeUseCustom}>
+ Convert a BitBucket Pipeline to a DevLake Deployment when its branch/tag name
+ </Checkbox>
+ <div style={{ margin: '8px 0', paddingLeft: 28 }}>
<span>matches</span>
- <InputGroup
+ <Input
style={{ width: 200, margin: '0 8px' }}
placeholder="(deploy|push-image)"
value={transformation.deploymentPattern ?? ''}
onChange={(e) =>
- setTransformation({
+ onChangeTransformation({
...transformation,
deploymentPattern: e.target.value,
productionPattern: !e.target.value ? '' : transformation.productionPattern,
@@ -177,14 +223,14 @@ export const BitbucketTransformation = ({ entities, transformation, setTransform
<span>.</span>
<HelpTooltip content="View your BitBucket Pipelines: https://support.atlassian.com/bitbucket-cloud/docs/view-your-pipeline/" />
</div>
- <div className="sub-text">
+ <div style={{ margin: '8px 0', paddingLeft: 28 }}>
<span>If the name also matches</span>
- <InputGroup
+ <Input
style={{ width: 200, margin: '0 8px' }}
placeholder="prod(.*)"
value={transformation.productionPattern ?? ''}
onChange={(e) =>
- setTransformation({
+ onChangeTransformation({
...transformation,
productionPattern: e.target.value,
})
@@ -193,8 +239,54 @@ export const BitbucketTransformation = ({ entities, transformation, setTransform
<span>, this Deployment is a ‘Production Deployment’</span>
<HelpTooltip content="If you leave this field empty, all Deployments will be tagged as in the Production environment. " />
</div>
- </S.CICD>
- )}
- </S.Transformation>
- );
-};
+ </>
+ ),
+ },
+ {
+ key: 'ADDITIONAL',
+ label: 'Additional Settings',
+ style: panelStyle,
+ children: (
+ <>
+ <p>
+ Enable the <ExternalLink link={DOC_URL.PLUGIN.REFDIFF}>RefDiff</ExternalLink> plugin to pre-calculate
+ version-based metrics
+ <HelpTooltip content="Calculate the commits diff between two consecutive tags that match the following RegEx. Issues closed by PRs which contain these commits will also be calculated. The result will be shown in table.refs_commits_diffs and table.refs_issues_diffs." />
+ </p>
+ <div className="refdiff">
+ Compare the last
+ <Input
+ style={{ margin: '0 8px', width: 60 }}
+ placeholder="10"
+ value={transformation.refdiff?.tagsLimit ?? ''}
+ onChange={(e) =>
+ onChangeTransformation({
+ ...transformation,
+ refdiff: {
+ ...transformation?.refdiff,
+ tagsLimit: +e.target.value,
+ },
+ })
+ }
+ />
+ tags that match the
+ <Input
+ style={{ margin: '0 8px', width: 200 }}
+ placeholder="(regex)$"
+ value={transformation.refdiff?.tagsPattern ?? ''}
+ onChange={(e) =>
+ onChangeTransformation({
+ ...transformation,
+ refdiff: {
+ ...transformation?.refdiff,
+ tagsPattern: e.target.value,
+ },
+ })
+ }
+ />
+ for calculation
+ </div>
+ </>
+ ),
+ },
+ ].filter((it) => entities.includes(it.key) || it.key === 'ADDITIONAL');
diff --git a/config-ui/src/plugins/register/github/transformation.tsx b/config-ui/src/plugins/register/github/transformation.tsx
index f82dce8ee..1ddf8245a 100644
--- a/config-ui/src/plugins/register/github/transformation.tsx
+++ b/config-ui/src/plugins/register/github/transformation.tsx
@@ -17,16 +17,11 @@
*/
import { useState, useEffect } from 'react';
-import {
- QuestionCircleOutlined,
- CheckCircleOutlined,
- CloseCircleOutlined,
- CaretRightOutlined,
-} from '@ant-design/icons';
+import { CheckCircleOutlined, CloseCircleOutlined, CaretRightOutlined } from '@ant-design/icons';
import type { CheckboxChangeEvent } from 'antd/lib/checkbox';
-import { theme, Form, Collapse as AntdCollapse, Input, Tooltip, Tag, Checkbox } from 'antd';
+import { theme, Form, Collapse, Input, Tag, Checkbox } from 'antd';
-import { ExternalLink } from '@/components';
+import { HelpTooltip, ExternalLink } from '@/components';
import { DOC_URL } from '@/release';
interface Props {
@@ -75,23 +70,21 @@ export const GitHubTransformation = ({ entities, transformation, setTransformati
};
return (
- <Form labelCol={{ span: 4 }} wrapperCol={{ span: 16 }}>
- <AntdCollapse
- bordered={false}
- defaultActiveKey={['TICKET', 'CICD']}
- expandIcon={({ isActive }) => <CaretRightOutlined rotate={isActive ? 90 : 0} rev="" />}
- style={{ background: token.colorBgContainer }}
- size="large"
- items={renderCollapseItems({
- entities,
- panelStyle,
- transformation,
- onChangeTransformation: setTransformation,
- useCustom,
- onChangeUseCustom: handleChangeUseCustom,
- })}
- />
- </Form>
+ <Collapse
+ bordered={false}
+ defaultActiveKey={['TICKET', 'CICD']}
+ expandIcon={({ isActive }) => <CaretRightOutlined rotate={isActive ? 90 : 0} rev="" />}
+ style={{ background: token.colorBgContainer }}
+ size="large"
+ items={renderCollapseItems({
+ entities,
+ panelStyle,
+ transformation,
+ onChangeTransformation: setTransformation,
+ useCustom,
+ onChangeUseCustom: handleChangeUseCustom,
+ })}
+ />
);
};
@@ -175,9 +168,7 @@ const renderCollapseItems = ({
label={
<>
<span style={{ marginRight: 4 }}>Issue Priority</span>
- <Tooltip title="Labels that match the RegEx will be set as the priority of an issue.">
- <QuestionCircleOutlined rev="" />
- </Tooltip>
+ <HelpTooltip content="Labels that match the RegEx will be set as the priority of an issue." />
</>
}
>
@@ -196,9 +187,7 @@ const renderCollapseItems = ({
label={
<>
<span style={{ marginRight: 4 }}>Issue Component</span>
- <Tooltip title="Labels that match the RegEx will be set as the component of an issue.">
- <QuestionCircleOutlined rev="" />
- </Tooltip>
+ <HelpTooltip content="Labels that match the RegEx will be set as the component of an issue." />
</>
}
>
@@ -217,9 +206,7 @@ const renderCollapseItems = ({
label={
<>
<span style={{ marginRight: 4 }}>Issue Severity</span>
- <Tooltip title="Labels that match the RegEx will be set as the serverity of an issue.">
- <QuestionCircleOutlined rev="" />
- </Tooltip>
+ <HelpTooltip content="Labels that match the RegEx will be set as the serverity of an issue." />
</>
}
>
@@ -291,9 +278,7 @@ const renderCollapseItems = ({
}
/>
<i style={{ marginRight: 4, color: '#E34040' }}>*</i>
- <Tooltip title="GitHub Workflow Runs: https://docs.github.com/en/actions/managing-workflow-runs/manually-running-a-workflow">
- <QuestionCircleOutlined rev="" />
- </Tooltip>
+ <HelpTooltip content="GitHub Workflow Runs: https://docs.github.com/en/actions/managing-workflow-runs/manually-running-a-workflow" />
</div>
<div style={{ margin: '8px 0', paddingLeft: 28 }}>
<span>If the name or its branch’s name also matches</span>
@@ -309,9 +294,7 @@ const renderCollapseItems = ({
}
/>
<span>, this deployment is a ‘Production Deployment’</span>
- <Tooltip title="If you leave this field empty, all Deployments will be tagged as in the Production environment. ">
- <QuestionCircleOutlined rev="" />
- </Tooltip>
+ <HelpTooltip content="If you leave this field empty, all Deployments will be tagged as in the Production environment. " />
</div>
</>
),
@@ -331,9 +314,7 @@ const renderCollapseItems = ({
label={
<>
<span style={{ marginRight: 4 }}>PR Type</span>
- <Tooltip title="Labels that match the RegEx will be set as the type of a pull request.">
- <QuestionCircleOutlined rev="" />
- </Tooltip>
+ <HelpTooltip content="Labels that match the RegEx will be set as the type of a pull request." />
</>
}
>
@@ -347,9 +328,7 @@ const renderCollapseItems = ({
label={
<>
<span style={{ marginRight: 4 }}>PR Component</span>
- <Tooltip title="Labels that match the RegEx will be set as the component of a pull request.">
- <QuestionCircleOutlined rev="" />
- </Tooltip>
+ <HelpTooltip content="Labels that match the RegEx will be set as the component of a pull request." />
</>
}
>
@@ -385,8 +364,8 @@ const renderCollapseItems = ({
label={
<div className="label">
<span style={{ marginRight: 4 }}>Connect PRs and Issues</span>
- <Tooltip
- title={
+ <HelpTooltip
+ content={
<>
<div>
<CheckCircleOutlined rev="" style={{ marginRight: 4, color: '#4DB764' }} />
@@ -400,9 +379,7 @@ const renderCollapseItems = ({
</div>
</>
}
- >
- <QuestionCircleOutlined rev="" />
- </Tooltip>
+ />
</div>
}
>
@@ -421,4 +398,51 @@ const renderCollapseItems = ({
</>
),
},
- ].filter((it) => entities.includes(it.key));
+ {
+ key: 'ADDITIONAL',
+ label: 'Additional Settings',
+ style: panelStyle,
+ children: (
+ <>
+ <p>
+ Enable the <ExternalLink link={DOC_URL.PLUGIN.REFDIFF}>RefDiff</ExternalLink> plugin to pre-calculate
+ version-based metrics
+ <HelpTooltip content="Calculate the commits diff between two consecutive tags that match the following RegEx. Issues closed by PRs which contain these commits will also be calculated. The result will be shown in table.refs_commits_diffs and table.refs_issues_diffs." />
+ </p>
+ <div className="refdiff">
+ Compare the last
+ <Input
+ style={{ margin: '0 8px', width: 60 }}
+ placeholder="10"
+ value={transformation.refdiff?.tagsLimit ?? ''}
+ onChange={(e) =>
+ onChangeTransformation({
+ ...transformation,
+ refdiff: {
+ ...transformation?.refdiff,
+ tagsLimit: +e.target.value,
+ },
+ })
+ }
+ />
+ tags that match the
+ <Input
+ style={{ margin: '0 8px', width: 200 }}
+ placeholder="(regex)$"
+ value={transformation.refdiff?.tagsPattern ?? ''}
+ onChange={(e) =>
+ onChangeTransformation({
+ ...transformation,
+ refdiff: {
+ ...transformation?.refdiff,
+ tagsPattern: e.target.value,
+ },
+ })
+ }
+ />
+ for calculation
+ </div>
+ </>
+ ),
+ },
+ ].filter((it) => entities.includes(it.key) || it.key === 'ADDITIONAL');
diff --git a/config-ui/src/plugins/register/gitlab/styled.ts b/config-ui/src/plugins/register/gitlab/styled.ts
deleted file mode 100644
index 88bf19ae1..000000000
--- a/config-ui/src/plugins/register/gitlab/styled.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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 styled from 'styled-components';
-
-export const Transformation = styled.div``;
-
-export const CICD = styled.div`
- h3 {
- margin-top: 16px;
- }
-
- .text,
- .sub-text {
- display: flex;
- align-items: baseline;
- margin-bottom: 8px;
- }
-
- .sub-text {
- padding-left: 28px;
- }
-`;
diff --git a/config-ui/src/plugins/register/gitlab/transformation.tsx b/config-ui/src/plugins/register/gitlab/transformation.tsx
index 217d1853d..3ad9b97c6 100644
--- a/config-ui/src/plugins/register/gitlab/transformation.tsx
+++ b/config-ui/src/plugins/register/gitlab/transformation.tsx
@@ -17,13 +17,12 @@
*/
import { useState, useEffect } from 'react';
-import { Tag, Intent, Checkbox, InputGroup } from '@blueprintjs/core';
+import { CaretRightOutlined } from '@ant-design/icons';
+import { theme, Collapse, Tag, Input, Checkbox } from 'antd';
import { ExternalLink, HelpTooltip } from '@/components';
import { DOC_URL } from '@/release';
-import * as S from './styled';
-
interface Props {
entities: string[];
transformation: any;
@@ -60,14 +59,59 @@ export const GitLabTransformation = ({ entities, transformation, setTransformati
setUseCustom(checked);
};
+ const { token } = theme.useToken();
+
+ const panelStyle: React.CSSProperties = {
+ marginBottom: 24,
+ background: token.colorFillAlter,
+ borderRadius: token.borderRadiusLG,
+ border: 'none',
+ };
+
return (
- <S.Transformation>
- {entities.includes('CICD') && (
- <S.CICD>
- <h2>CI/CD</h2>
- <h3>
+ <Collapse
+ bordered={false}
+ defaultActiveKey={['TICKET', 'CICD']}
+ expandIcon={({ isActive }) => <CaretRightOutlined rotate={isActive ? 90 : 0} rev="" />}
+ style={{ background: token.colorBgContainer }}
+ size="large"
+ items={renderCollapseItems({
+ entities,
+ panelStyle,
+ transformation,
+ onChangeTransformation: setTransformation,
+ useCustom,
+ onChangeUseCustom: handleChangeUseCustom,
+ })}
+ />
+ );
+};
+
+const renderCollapseItems = ({
+ entities,
+ panelStyle,
+ transformation,
+ onChangeTransformation,
+ useCustom,
+ onChangeUseCustom,
+}: {
+ entities: string[];
+ panelStyle: React.CSSProperties;
+ transformation: any;
+ onChangeTransformation: any;
+ useCustom: boolean;
+ onChangeUseCustom: any;
+}) =>
+ [
+ {
+ key: 'CICD',
+ label: 'CI/CD',
+ style: panelStyle,
+ children: (
+ <>
+ <h3 style={{ marginBottom: 16 }}>
<span>Deployment</span>
- <Tag minimal intent={Intent.PRIMARY} style={{ marginLeft: 8 }}>
+ <Tag style={{ marginLeft: 4 }} color="blue">
DORA
</Tag>
</h3>
@@ -75,18 +119,17 @@ export const GitLabTransformation = ({ entities, transformation, setTransformati
Use Regular Expression to define Deployments in DevLake in order to measure DORA metrics.{' '}
<ExternalLink link={DOC_URL.PLUGIN.GITLAB.TRANSFORMATION}>Learn more</ExternalLink>
</p>
- <div className="text">
- <Checkbox disabled checked />
- <span>Convert a GitLab Deployment to a DevLake Deployment </span>
- </div>
- <div className="sub-text">
+ <Checkbox disabled checked>
+ Convert a GitLab Deployment to a DevLake Deployment
+ </Checkbox>
+ <div style={{ margin: '8px 0', paddingLeft: 28 }}>
<span>If its environment name matches</span>
- <InputGroup
+ <Input
style={{ width: 180, margin: '0 8px' }}
placeholder="(?i)prod(.*)"
value={transformation.envNamePattern}
onChange={(e) =>
- setTransformation({
+ onChangeTransformation({
...transformation,
envNamePattern: e.target.value,
})
@@ -94,20 +137,19 @@ export const GitLabTransformation = ({ entities, transformation, setTransformati
/>
<span>, this deployment is a ‘Production Deployment’</span>
</div>
- <div className="text">
- <Checkbox checked={useCustom} onChange={handleChangeUseCustom} />
- <span>Convert a GitLab Pipeline as a DevLake Deployment when: </span>
- </div>
- <div className="sub-text">
+ <Checkbox checked={useCustom} onChange={onChangeUseCustom}>
+ Convert a GitLab Pipeline as a DevLake Deployment when:
+ </Checkbox>
+ <div style={{ margin: '8px 0', paddingLeft: 28 }}>
<span>
Its branch/tag name or <strong>one of its jobs</strong> matches
</span>
- <InputGroup
+ <Input
style={{ width: 180, margin: '0 8px' }}
placeholder="(deploy|push-image)"
value={transformation.deploymentPattern ?? ''}
onChange={(e) =>
- setTransformation({
+ onChangeTransformation({
...transformation,
deploymentPattern: e.target.value,
productionPattern: !e.target.value ? '' : transformation.productionPattern,
@@ -117,14 +159,14 @@ export const GitLabTransformation = ({ entities, transformation, setTransformati
<i style={{ color: '#E34040' }}>*</i>
<HelpTooltip content="GitLab Pipelines: https://docs.gitlab.com/ee/ci/pipelines/" />
</div>
- <div className="sub-text">
+ <div style={{ margin: '8px 0', paddingLeft: 28 }}>
<span>If the name also matches</span>
- <InputGroup
+ <Input
style={{ width: 180, margin: '0 8px' }}
placeholder="prod(.*)"
value={transformation.productionPattern ?? ''}
onChange={(e) =>
- setTransformation({
+ onChangeTransformation({
...transformation,
productionPattern: e.target.value,
})
@@ -133,8 +175,7 @@ export const GitLabTransformation = ({ entities, transformation, setTransformati
<span>, this deployment is a ‘Production Deployment’</span>
<HelpTooltip content="If you leave this field empty, all Deployments will be tagged as in the Production environment. " />
</div>
- </S.CICD>
- )}
- </S.Transformation>
- );
-};
+ </>
+ ),
+ },
+ ].filter((it) => entities.includes(it.key));
diff --git a/config-ui/src/plugins/register/jenkins/styled.ts b/config-ui/src/plugins/register/jenkins/styled.ts
deleted file mode 100644
index 5b1ce515c..000000000
--- a/config-ui/src/plugins/register/jenkins/styled.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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 styled from 'styled-components';
-
-export const Transformation = styled.div``;
-
-export const CICD = styled.div`
- h3 {
- margin-top: 16px;
-
- .switch {
- display: inline-flex;
- align-items: center;
- margin-left: 16px;
- font-size: 14px;
- font-weight: 400;
-
- .bp5-switch {
- margin-bottom: 0;
- }
- }
- }
-
- .text {
- display: flex;
- align-items: baseline;
- margin-top: 16px;
- padding-left: 24px;
-
- .bp5-radio {
- margin-right: 0;
- }
- }
-`;
-
-export const DataScope = styled.div``;
-
-export const JobLoad = styled.div`
- display: flex;
- align-items: center;
-
- & > span.count {
- margin: 0 8px;
- color: #7497f7;
- }
-`;
diff --git a/config-ui/src/plugins/register/jenkins/transformation.tsx b/config-ui/src/plugins/register/jenkins/transformation.tsx
index 9246d5b14..0a44f1dbd 100644
--- a/config-ui/src/plugins/register/jenkins/transformation.tsx
+++ b/config-ui/src/plugins/register/jenkins/transformation.tsx
@@ -16,14 +16,12 @@
*
*/
-import { useState, useEffect } from 'react';
-import { Tag, Intent, Switch, InputGroup } from '@blueprintjs/core';
+import { CaretRightOutlined } from '@ant-design/icons';
+import { theme, Collapse, Tag, Input } from 'antd';
import { ExternalLink, HelpTooltip } from '@/components';
import { DOC_URL } from '@/release';
-import * as S from './styled';
-
interface Props {
entities: string[];
transformation: any;
@@ -31,90 +29,98 @@ interface Props {
}
export const JenkinsTransformation = ({ entities, transformation, setTransformation }: Props) => {
- const [enableCICD, setEnableCICD] = useState(true);
-
- useEffect(() => {
- if (!transformation.deploymentPattern) {
- setEnableCICD(false);
- }
- }, []);
-
- const handleChangeCICDEnable = (e: React.FormEvent<HTMLInputElement>) => {
- const checked = (e.target as HTMLInputElement).checked;
+ const { token } = theme.useToken();
- if (!checked) {
- setTransformation({
- ...transformation,
- deploymentPattern: undefined,
- productionPattern: undefined,
- });
- }
-
- setEnableCICD(checked);
+ const panelStyle: React.CSSProperties = {
+ marginBottom: 24,
+ background: token.colorFillAlter,
+ borderRadius: token.borderRadiusLG,
+ border: 'none',
};
return (
- <S.Transformation>
- {entities.includes('CICD') && (
- <S.CICD>
- <h2>CI/CD</h2>
- <h3>
+ <Collapse
+ bordered={false}
+ defaultActiveKey={['TICKET', 'CICD']}
+ expandIcon={({ isActive }) => <CaretRightOutlined rotate={isActive ? 90 : 0} rev="" />}
+ style={{ background: token.colorBgContainer }}
+ size="large"
+ items={renderCollapseItems({
+ entities,
+ panelStyle,
+ transformation,
+ onChangeTransformation: setTransformation,
+ })}
+ />
+ );
+};
+
+const renderCollapseItems = ({
+ entities,
+ panelStyle,
+ transformation,
+ onChangeTransformation,
+}: {
+ entities: string[];
+ panelStyle: React.CSSProperties;
+ transformation: any;
+ onChangeTransformation: any;
+}) =>
+ [
+ {
+ key: 'CICD',
+ label: 'CI/CD',
+ style: panelStyle,
+ children: (
+ <>
+ <h3 style={{ marginBottom: 16 }}>
<span>Deployment</span>
- <Tag minimal intent={Intent.PRIMARY} style={{ marginLeft: 8 }}>
+ <Tag style={{ marginLeft: 4 }} color="blue">
DORA
</Tag>
- <div className="switch">
- <span>Enable</span>
- <Switch alignIndicator="right" inline checked={enableCICD} onChange={handleChangeCICDEnable} />
- </div>
</h3>
- {enableCICD && (
- <>
- <p>
- Use Regular Expression to define Deployments in DevLake in order to measure DORA metrics.{' '}
- <ExternalLink link={DOC_URL.PLUGIN.JENKINS.TRANSFORMATION}>Learn more</ExternalLink>
- </p>
- <div style={{ marginTop: 16 }}>Convert a Jenkins Build as a DevLake Deployment when: </div>
- <div className="text">
- <span>
- The name of the <strong>Jenkins job</strong> or <strong>one of its stages</strong> matches
- </span>
- <InputGroup
- style={{ width: 200, margin: '0 8px' }}
- placeholder="(deploy|push-image)"
- value={transformation.deploymentPattern ?? ''}
- onChange={(e) =>
- setTransformation({
- ...transformation,
- deploymentPattern: e.target.value,
- productionPattern: !e.target.value ? '' : transformation.productionPattern,
- })
- }
- />
- <i style={{ color: '#E34040' }}>*</i>
- <HelpTooltip content="Jenkins Builds: https://www.jenkins.io/doc/pipeline/steps/pipeline-build-step/" />
- </div>
- <div className="text">
- <span>If the name also matches</span>
- <InputGroup
- style={{ width: 120, margin: '0 8px' }}
- disabled={!transformation.deploymentPattern}
- placeholder="prod(.*)"
- value={transformation.productionPattern ?? ''}
- onChange={(e) =>
- setTransformation({
- ...transformation,
- productionPattern: e.target.value,
- })
- }
- />
- <span>, this Deployment is a ‘Production Deployment’</span>
- <HelpTooltip content="If you leave this field empty, all DevLake Deployments will be tagged as in the Production environment. " />
- </div>
- </>
- )}
- </S.CICD>
- )}
- </S.Transformation>
- );
-};
+ <p style={{ marginBottom: 16 }}>
+ Use Regular Expression to define Deployments in DevLake in order to measure DORA metrics.{' '}
+ <ExternalLink link={DOC_URL.PLUGIN.JENKINS.TRANSFORMATION}>Learn more</ExternalLink>
+ </p>
+ <div style={{ marginTop: 16 }}>Convert a Jenkins Build as a DevLake Deployment when: </div>
+ <div style={{ margin: '8px 0', paddingLeft: 28 }}>
+ <span>
+ The name of the <strong>Jenkins job</strong> or <strong>one of its stages</strong> matches
+ </span>
+ <Input
+ style={{ width: 200, margin: '0 8px' }}
+ placeholder="(deploy|push-image)"
+ value={transformation.deploymentPattern ?? ''}
+ onChange={(e) =>
+ onChangeTransformation({
+ ...transformation,
+ deploymentPattern: e.target.value,
+ productionPattern: !e.target.value ? '' : transformation.productionPattern,
+ })
+ }
+ />
+ <i style={{ color: '#E34040' }}>*</i>
+ <HelpTooltip content="Jenkins Builds: https://www.jenkins.io/doc/pipeline/steps/pipeline-build-step/" />
+ </div>
+ <div style={{ margin: '8px 0', paddingLeft: 28 }}>
+ <span>If the name also matches</span>
+ <Input
+ style={{ width: 120, margin: '0 8px' }}
+ disabled={!transformation.deploymentPattern}
+ placeholder="prod(.*)"
+ value={transformation.productionPattern ?? ''}
+ onChange={(e) =>
+ onChangeTransformation({
+ ...transformation,
+ productionPattern: e.target.value,
+ })
+ }
+ />
+ <span>, this Deployment is a ‘Production Deployment’</span>
+ <HelpTooltip content="If you leave this field empty, all DevLake Deployments will be tagged as in the Production environment. " />
+ </div>
+ </>
+ ),
+ },
+ ].filter((it) => entities.includes(it.key));
diff --git a/config-ui/src/plugins/register/jira/styled.ts b/config-ui/src/plugins/register/jira/styled.ts
deleted file mode 100644
index 5503cb802..000000000
--- a/config-ui/src/plugins/register/jira/styled.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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 styled from 'styled-components';
-
-export const TransformationWrapper = styled.div`
- .issue-tracking {
- .issue-type {
- .title {
- margin-bottom: 8px;
- }
-
- .list {
- padding-left: 40px;
- }
- }
- }
-
- .bp5-form-group {
- display: flex;
- align-items: center;
-
- .bp5-label {
- flex: 0 0 140px;
- }
-
- .bp5-form-content {
- flex: auto;
- }
- }
-`;
diff --git a/config-ui/src/plugins/register/jira/transformation.tsx b/config-ui/src/plugins/register/jira/transformation.tsx
index c893ac0f6..7964674e5 100644
--- a/config-ui/src/plugins/register/jira/transformation.tsx
+++ b/config-ui/src/plugins/register/jira/transformation.tsx
@@ -17,17 +17,16 @@
*/
import { useState, useEffect, useMemo } from 'react';
-import { FormGroup, Tag, Icon, Intent } from '@blueprintjs/core';
-import { Popover2 } from '@blueprintjs/popover2';
import { uniqWith } from 'lodash';
+import { CaretRightOutlined } from '@ant-design/icons';
+import { theme, Collapse, Tag, Form } from 'antd';
import API from '@/api';
-import { PageLoading, HelpTooltip, ExternalLink, MultiSelector, Selector, Divider } from '@/components';
+import { PageLoading, HelpTooltip, ExternalLink, MultiSelector, Selector } from '@/components';
import { useProxyPrefix, useRefreshData } from '@/hooks';
import { DOC_URL } from '@/release';
import { CrossDomain } from './transformation-fields';
-import * as S from './styled';
enum StandardType {
Requirement = 'REQUIREMENT',
@@ -93,6 +92,8 @@ export const JiraTransformation = ({ entities, connectionId, transformation, set
];
}, [requirements, bugs, incidents, data?.issueTypes]);
+ const { token } = theme.useToken();
+
if (!ready || !data) {
return <PageLoading />;
}
@@ -115,108 +116,153 @@ export const JiraTransformation = ({ entities, connectionId, transformation, set
}, {} as any);
};
+ const panelStyle: React.CSSProperties = {
+ marginBottom: 24,
+ background: token.colorFillAlter,
+ borderRadius: token.borderRadiusLG,
+ border: 'none',
+ };
+
return (
- <S.TransformationWrapper>
- {entities.includes('TICKET') && (
- <div className="issue-tracking">
- <h2>Issue Tracking</h2>
+ <Collapse
+ bordered={false}
+ defaultActiveKey={['TICKET', 'CROSS']}
+ expandIcon={({ isActive }) => <CaretRightOutlined rotate={isActive ? 90 : 0} rev={undefined} />}
+ style={{ background: token.colorBgContainer }}
+ size="large"
+ items={renderCollapseItems({
+ entities,
+ panelStyle,
+ transformation,
+ onChangeTransformation: setTransformation,
+ connectionId,
+ issueTypes,
+ fields,
+ requirementItems,
+ bugItems,
+ incidentItems,
+ transformaType,
+ })}
+ />
+ );
+};
+
+const renderCollapseItems = ({
+ entities,
+ panelStyle,
+ transformation,
+ onChangeTransformation,
+ connectionId,
+ issueTypes,
+ fields,
+ bugItems,
+ incidentItems,
+ requirementItems,
+ transformaType,
+}: {
+ entities: string[];
+ panelStyle: React.CSSProperties;
+ transformation: any;
+ onChangeTransformation: any;
+ connectionId: ID;
+ issueTypes: any;
+ fields: Array<{
+ id: string;
+ name: string;
+ }>;
+ requirementItems: any;
+ bugItems: any;
+ incidentItems: any;
+ transformaType: any;
+}) =>
+ [
+ {
+ key: 'TICKET',
+ label: 'Issue Tracking',
+ style: panelStyle,
+ children: (
+ <>
<p>
Tell DevLake what types of Jira issues you are using as features, bugs and incidents, and what field as
`Epic Link` or `Story Points`.
</p>
- <div className="issue-type">
- <div className="title">
- <span>Issue Type</span>
- <Popover2
- position="top"
- content={
- <div style={{ padding: '8px 12px', color: '#ffffff', backgroundColor: 'rgba(0,0,0,.8)' }}>
- DevLake defines three standard types of issues: FEATURE, BUG and INCIDENT. Standardize your Jira
- issue types to these three types so that DevLake can calculate metrics such as{' '}
- <ExternalLink link={DOC_URL.METRICS.REQUIREMENT_LEAD_TIME}>Requirement Lead Time</ExternalLink>,{' '}
- <ExternalLink link={DOC_URL.METRICS.BUG_AGE}>Bug Age</ExternalLink>,
- <ExternalLink link={DOC_URL.METRICS.MTTR}>DORA - Median Time to Restore Service</ExternalLink>, etc.
- </div>
- }
- >
- <Icon icon="help" size={12} color="#94959f" style={{ marginLeft: 4, cursor: 'pointer' }} />
- </Popover2>
- </div>
- <div className="list">
- <FormGroup inline label="Requirement">
- <MultiSelector
- items={issueTypes}
- disabledItems={[...bugItems, ...incidentItems]}
- getKey={(it) => it.id}
- getName={(it) => it.name}
- getIcon={(it) => it.iconUrl}
- selectedItems={requirementItems}
- onChangeItems={(selectedItems) =>
- setTransformation({
- ...transformation,
- typeMappings: {
- ...transformaType(selectedItems, StandardType.Requirement),
- ...transformaType(bugItems, StandardType.Bug),
- ...transformaType(incidentItems, StandardType.Incident),
- },
- })
- }
- />
- </FormGroup>
- <FormGroup inline label="Bug">
- <MultiSelector
- items={issueTypes}
- disabledItems={[...requirementItems, ...incidentItems]}
- getKey={(it) => it.id}
- getName={(it) => it.name}
- getIcon={(it) => it.iconUrl}
- selectedItems={bugItems}
- onChangeItems={(selectedItems) =>
- setTransformation({
- ...transformation,
- typeMappings: {
- ...transformaType(requirementItems, StandardType.Requirement),
- ...transformaType(selectedItems, StandardType.Bug),
- ...transformaType(incidentItems, StandardType.Incident),
- },
- })
- }
- />
- </FormGroup>
- <FormGroup
- inline
- label={
- <>
- <span>Incident</span>
- <Tag intent={Intent.PRIMARY} style={{ marginLeft: 4 }}>
- DORA
- </Tag>
- </>
- }
- >
- <MultiSelector
- items={issueTypes}
- disabledItems={[...requirementItems, ...bugItems]}
- getKey={(it) => it.id}
- getName={(it) => it.name}
- getIcon={(it) => it.iconUrl}
- selectedItems={incidentItems}
- onChangeItems={(selectedItems) =>
- setTransformation({
- ...transformation,
- typeMappings: {
- ...transformaType(requirementItems, StandardType.Requirement),
- ...transformaType(bugItems, StandardType.Bug),
- ...transformaType(selectedItems, StandardType.Incident),
- },
- })
- }
- />
- </FormGroup>
- </div>
- </div>
- <FormGroup
- inline
+ <p>
+ DevLake defines three standard types of issues: FEATURE, BUG and INCIDENT. Standardize your Jira issue types
+ to these three types so that DevLake can calculate metrics such as{' '}
+ <ExternalLink link={DOC_URL.METRICS.REQUIREMENT_LEAD_TIME}>Requirement Lead Time</ExternalLink>,{' '}
+ <ExternalLink link={DOC_URL.METRICS.BUG_AGE}>Bug Age</ExternalLink>,
+ <ExternalLink link={DOC_URL.METRICS.MTTR}>DORA - Median Time to Restore Service</ExternalLink>, etc.
+ </p>
+ <Form.Item label="Requirement">
+ <MultiSelector
+ items={issueTypes}
+ disabledItems={[...bugItems, ...incidentItems]}
+ getKey={(it) => it.id}
+ getName={(it) => it.name}
+ getIcon={(it) => it.iconUrl}
+ selectedItems={requirementItems}
+ onChangeItems={(selectedItems) =>
+ onChangeTransformation({
+ ...transformation,
+ typeMappings: {
+ ...transformaType(selectedItems, StandardType.Requirement),
+ ...transformaType(bugItems, StandardType.Bug),
+ ...transformaType(incidentItems, StandardType.Incident),
+ },
+ })
+ }
+ />
+ </Form.Item>
+ <Form.Item label="Bug">
+ <MultiSelector
+ items={issueTypes}
+ disabledItems={[...requirementItems, ...incidentItems]}
+ getKey={(it) => it.id}
+ getName={(it) => it.name}
+ getIcon={(it) => it.iconUrl}
+ selectedItems={bugItems}
+ onChangeItems={(selectedItems) =>
+ onChangeTransformation({
+ ...transformation,
+ typeMappings: {
+ ...transformaType(requirementItems, StandardType.Requirement),
+ ...transformaType(selectedItems, StandardType.Bug),
+ ...transformaType(incidentItems, StandardType.Incident),
+ },
+ })
+ }
+ />
+ </Form.Item>
+ <Form.Item
+ label={
+ <>
+ <span>Incident</span>
+ <Tag style={{ marginLeft: 4 }} color="blue">
+ DORA
+ </Tag>
+ </>
+ }
+ >
+ <MultiSelector
+ items={issueTypes}
+ disabledItems={[...requirementItems, ...bugItems]}
+ getKey={(it) => it.id}
+ getName={(it) => it.name}
+ getIcon={(it) => it.iconUrl}
+ selectedItems={incidentItems}
+ onChangeItems={(selectedItems) =>
+ onChangeTransformation({
+ ...transformation,
+ typeMappings: {
+ ...transformaType(requirementItems, StandardType.Requirement),
+ ...transformaType(bugItems, StandardType.Bug),
+ ...transformaType(selectedItems, StandardType.Incident),
+ },
+ })
+ }
+ />
+ </Form.Item>
+ <Form.Item
label={
<>
<span>Story Points</span>
@@ -230,23 +276,26 @@ export const JiraTransformation = ({ entities, connectionId, transformation, set
getName={(it) => it.name}
selectedItem={fields.find((it) => it.id === transformation.storyPointField)}
onChangeItem={(selectedItem) =>
- setTransformation({
+ onChangeTransformation({
...transformation,
storyPointField: selectedItem.id,
})
}
/>
- </FormGroup>
- <Divider />
- </div>
- )}
- {entities.includes('CROSS') && (
+ </Form.Item>
+ </>
+ ),
+ },
+ {
+ key: 'CROSS',
+ label: 'Cross Domain',
+ style: panelStyle,
+ children: (
<CrossDomain
connectionId={connectionId}
transformation={transformation}
- setTransformation={setTransformation}
+ setTransformation={onChangeTransformation}
/>
- )}
- </S.TransformationWrapper>
- );
-};
+ ),
+ },
+ ].filter((it) => entities.includes(it.key));
diff --git a/config-ui/src/plugins/register/tapd/styled.ts b/config-ui/src/plugins/register/tapd/styled.ts
deleted file mode 100644
index 7b4be7872..000000000
--- a/config-ui/src/plugins/register/tapd/styled.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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 styled from 'styled-components';
-
-export const TransformationWrapper = styled.div`
- .issue-tracking {
- .issue-type,
- .issue-status {
- .title {
- margin-bottom: 8px;
- }
-
- .list {
- padding-left: 40px;
- }
- }
- }
-
- .bp5-form-group {
- display: flex;
- align-items: center;
-
- .bp5-label {
- flex: 0 0 140px;
- }
-
- .bp5-form-content {
- flex: auto;
- }
- }
-`;
diff --git a/config-ui/src/plugins/register/tapd/transformation.tsx b/config-ui/src/plugins/register/tapd/transformation.tsx
index 86b841046..cb4d9e624 100644
--- a/config-ui/src/plugins/register/tapd/transformation.tsx
+++ b/config-ui/src/plugins/register/tapd/transformation.tsx
@@ -17,15 +17,14 @@
*/
import { useEffect, useState } from 'react';
-import { FormGroup, Intent, Tag } from '@blueprintjs/core';
+import { uniqWith } from 'lodash';
+import { CaretRightOutlined } from '@ant-design/icons';
+import { theme, Collapse, Tag, Form } from 'antd';
import API from '@/api';
-import { HelpTooltip, MultiSelector, PageLoading } from '@/components';
+import { MultiSelector, PageLoading } from '@/components';
import { useProxyPrefix, useRefreshData } from '@/hooks';
-import * as S from './styled';
-import { uniqWith } from 'lodash';
-
enum StandardType {
Requirement = 'Requirement',
Bug = 'BUG',
@@ -129,175 +128,234 @@ export const TapdTransformation = ({ entities, connectionId, scopeId, transforma
return acc;
}, {} as Record<string, string>);
};
+
+ const { token } = theme.useToken();
+
+ const panelStyle: React.CSSProperties = {
+ marginBottom: 24,
+ background: token.colorFillAlter,
+ borderRadius: token.borderRadiusLG,
+ border: 'none',
+ };
+
return (
- <S.TransformationWrapper>
- {entities.includes('TICKET') && (
- <div className="issue-tracking">
- <h2>Issue Tracking</h2>
- <div className="issue-type">
- <div className="title">
- <span>Issue Type Mapping</span>
- <HelpTooltip content="Standardize your issue types to the following issue types to view metrics such as `Requirement lead time` and `Bug age` in built-in dashboards." />
- </div>
- <div className="list">
- <FormGroup inline label="Requirement">
- <MultiSelector
- items={typeList}
- disabledItems={typeList.filter((v) => [...bugTypeList, ...incidentTypeList].includes(v.id))}
- getKey={(it) => it.id}
- getName={(it) => it.name}
- selectedItems={typeList.filter((v) => featureTypeList.includes(v.id))}
- onChangeItems={(selectedItems) =>
- setTransformation({
- ...transformation,
- typeMappings: {
- ...transformaType(
- selectedItems.map((v) => v.id),
- StandardType.Requirement,
- ),
- ...transformaType(bugTypeList, StandardType.Bug),
- ...transformaType(incidentTypeList, StandardType.Incident),
- },
- })
- }
- />
- </FormGroup>
- <FormGroup inline label="Bug">
- <MultiSelector
- items={typeList}
- disabledItems={typeList.filter((v) => [...featureTypeList, ...incidentTypeList].includes(v.id))}
- getKey={(it) => it.id}
- getName={(it) => it.name}
- selectedItems={typeList.filter((v) => bugTypeList.includes(v.id))}
- onChangeItems={(selectedItems) =>
- setTransformation({
- ...transformation,
- typeMappings: {
- ...transformaType(featureTypeList, StandardType.Requirement),
- ...transformaType(
- selectedItems.map((v) => v.id),
- StandardType.Bug,
- ),
- ...transformaType(incidentTypeList, StandardType.Incident),
- },
- })
- }
- />
- </FormGroup>
- <FormGroup
- inline
- label={
- <>
- <span>Incident</span>
- <Tag intent={Intent.PRIMARY} style={{ marginLeft: 4 }}>
- DORA
- </Tag>
- </>
- }
- >
- <MultiSelector
- items={typeList}
- disabledItems={typeList.filter((v) => [...featureTypeList, ...bugTypeList].includes(v.id))}
- getKey={(it) => it.id}
- getName={(it) => it.name}
- selectedItems={typeList.filter((v) => incidentTypeList.includes(v.id))}
- onChangeItems={(selectedItems) =>
- setTransformation({
- ...transformation,
- typeMappings: {
- ...transformaType(featureTypeList, StandardType.Requirement),
- ...transformaType(bugTypeList, StandardType.Bug),
- ...transformaType(
- selectedItems.map((v) => v.id),
- StandardType.Incident,
- ),
- },
- })
- }
- />
- </FormGroup>
- </div>
- </div>
- <div className="issue-status">
- <div className="title">
- <span>Issue Status Mapping</span>
- <HelpTooltip content="Standardize your issue statuses to the following issue statuses to view metrics such as `Requirement Delivery Rate` in built-in dashboards." />
- </div>
- <div className="list">
- <FormGroup inline label="TODO">
- <MultiSelector
- items={statusList}
- disabledItems={statusList.filter((v) =>
- [...inProgressStatusList, ...doneStatusList].includes(v.name),
- )}
- getKey={(it) => it.id}
- getName={(it) => it.name}
- selectedItems={statusList.filter((v) => todoStatusList.includes(v.name))}
- onChangeItems={(selectedItems) =>
- setTransformation({
- ...transformation,
- statusMappings: {
- ...transformaType(
- selectedItems.map((v) => v.name),
- StandardStatus.Todo,
- ),
- ...transformaType(inProgressStatusList, StandardStatus.InProgress),
- ...transformaType(doneStatusList, StandardStatus.Done),
- },
- })
- }
- />
- </FormGroup>
- <FormGroup inline label="IN-PROGRESS">
- <MultiSelector
- items={statusList}
- disabledItems={statusList.filter((v) => [...todoStatusList, ...doneStatusList].includes(v.name))}
- getKey={(it) => it.id}
- getName={(it) => it.name}
- selectedItems={statusList.filter((v) => inProgressStatusList.includes(v.name))}
- onChangeItems={(selectedItems) =>
- setTransformation({
- ...transformation,
- statusMappings: {
- ...transformaType(todoStatusList, StandardStatus.Todo),
- ...transformaType(
- selectedItems.map((v) => v.name),
- StandardStatus.InProgress,
- ),
- ...transformaType(doneStatusList, StandardStatus.Done),
- },
- })
- }
- />
- </FormGroup>
- <FormGroup inline label="DONE">
- <MultiSelector
- items={statusList}
- disabledItems={statusList.filter((v) =>
- [...todoStatusList, ...inProgressStatusList].includes(v.name),
- )}
- getKey={(it) => it.id}
- getName={(it) => it.name}
- selectedItems={statusList.filter((v) => doneStatusList.includes(v.name))}
- onChangeItems={(selectedItems) =>
- setTransformation({
- ...transformation,
- statusMappings: {
- ...transformaType(todoStatusList, StandardStatus.Todo),
- ...transformaType(inProgressStatusList, StandardStatus.InProgress),
- ...transformaType(
- selectedItems.map((v) => v.name),
- StandardStatus.Done,
- ),
- },
- })
- }
- />
- </FormGroup>
- </div>
- </div>
- </div>
- )}
- </S.TransformationWrapper>
+ <Collapse
+ bordered={false}
+ defaultActiveKey={['TICKET', 'CROSS']}
+ expandIcon={({ isActive }) => <CaretRightOutlined rotate={isActive ? 90 : 0} rev={undefined} />}
+ style={{ background: token.colorBgContainer }}
+ size="large"
+ items={renderCollapseItems({
+ entities,
+ panelStyle,
+ transformation,
+ onChangeTransformation: setTransformation,
+ typeList,
+ featureTypeList,
+ bugTypeList,
+ incidentTypeList,
+ statusList,
+ todoStatusList,
+ inProgressStatusList,
+ doneStatusList,
+ transformaType,
+ })}
+ />
);
};
+
+const renderCollapseItems = ({
+ entities,
+ panelStyle,
+ transformation,
+ onChangeTransformation,
+ typeList,
+ featureTypeList,
+ bugTypeList,
+ incidentTypeList,
+ statusList,
+ todoStatusList,
+ inProgressStatusList,
+ doneStatusList,
+ transformaType,
+}: {
+ entities: string[];
+ panelStyle: React.CSSProperties;
+ transformation: any;
+ onChangeTransformation: any;
+ typeList: Array<{
+ id: string;
+ name: string;
+ }>;
+ featureTypeList: any;
+ bugTypeList: any;
+ incidentTypeList: any;
+ statusList: Array<{
+ id: string;
+ name: string;
+ }>;
+ todoStatusList: any;
+ inProgressStatusList: any;
+ doneStatusList: any;
+ transformaType: any;
+}) =>
+ [
+ {
+ key: 'TICKET',
+ label: 'Issue Tracking',
+ style: panelStyle,
+ children: (
+ <>
+ <p>
+ Standardize your issue types to the following issue types to view metrics such as `Requirement lead time`
+ and `Bug age` in built-in dashboards.
+ </p>
+ <Form.Item label="Requirement">
+ <MultiSelector
+ items={typeList}
+ disabledItems={typeList.filter((v) => [...bugTypeList, ...incidentTypeList].includes(v.id))}
+ getKey={(it) => it.id}
+ getName={(it) => it.name}
+ selectedItems={typeList.filter((v) => featureTypeList.includes(v.id))}
+ onChangeItems={(selectedItems) =>
+ onChangeTransformation({
+ ...transformation,
+ typeMappings: {
+ ...transformaType(
+ selectedItems.map((v) => v.id),
+ StandardType.Requirement,
+ ),
+ ...transformaType(bugTypeList, StandardType.Bug),
+ ...transformaType(incidentTypeList, StandardType.Incident),
+ },
+ })
+ }
+ />
+ </Form.Item>
+ <Form.Item label="Bug">
+ <MultiSelector
+ items={typeList}
+ disabledItems={typeList.filter((v) => [...featureTypeList, ...incidentTypeList].includes(v.id))}
+ getKey={(it) => it.id}
+ getName={(it) => it.name}
+ selectedItems={typeList.filter((v) => bugTypeList.includes(v.id))}
+ onChangeItems={(selectedItems) =>
+ onChangeTransformation({
+ ...transformation,
+ typeMappings: {
+ ...transformaType(featureTypeList, StandardType.Requirement),
+ ...transformaType(
+ selectedItems.map((v) => v.id),
+ StandardType.Bug,
+ ),
+ ...transformaType(incidentTypeList, StandardType.Incident),
+ },
+ })
+ }
+ />
+ </Form.Item>
+ <Form.Item
+ label={
+ <>
+ <span>Incident</span>
+ <Tag style={{ marginLeft: 4 }} color="blue">
+ DORA
+ </Tag>
+ </>
+ }
+ >
+ <MultiSelector
+ items={typeList}
+ disabledItems={typeList.filter((v) => [...featureTypeList, ...bugTypeList].includes(v.id))}
+ getKey={(it) => it.id}
+ getName={(it) => it.name}
+ selectedItems={typeList.filter((v) => incidentTypeList.includes(v.id))}
+ onChangeItems={(selectedItems) =>
+ onChangeTransformation({
+ ...transformation,
+ typeMappings: {
+ ...transformaType(featureTypeList, StandardType.Requirement),
+ ...transformaType(bugTypeList, StandardType.Bug),
+ ...transformaType(
+ selectedItems.map((v) => v.id),
+ StandardType.Incident,
+ ),
+ },
+ })
+ }
+ />
+ </Form.Item>
+ <p>
+ Standardize your issue statuses to the following issue statuses to view metrics such as `Requirement
+ Delivery Rate` in built-in dashboards.
+ </p>
+ <Form.Item label="TODO">
+ <MultiSelector
+ items={statusList}
+ disabledItems={statusList.filter((v) => [...inProgressStatusList, ...doneStatusList].includes(v.name))}
+ getKey={(it) => it.id}
+ getName={(it) => it.name}
+ selectedItems={statusList.filter((v) => todoStatusList.includes(v.name))}
+ onChangeItems={(selectedItems) =>
+ onChangeTransformation({
+ ...transformation,
+ statusMappings: {
+ ...transformaType(
+ selectedItems.map((v) => v.name),
+ StandardStatus.Todo,
+ ),
+ ...transformaType(inProgressStatusList, StandardStatus.InProgress),
+ ...transformaType(doneStatusList, StandardStatus.Done),
+ },
+ })
+ }
+ />
+ </Form.Item>
+ <Form.Item label="IN-PROGRESS">
+ <MultiSelector
+ items={statusList}
+ disabledItems={statusList.filter((v) => [...todoStatusList, ...doneStatusList].includes(v.name))}
+ getKey={(it) => it.id}
+ getName={(it) => it.name}
+ selectedItems={statusList.filter((v) => inProgressStatusList.includes(v.name))}
+ onChangeItems={(selectedItems) =>
+ onChangeTransformation({
+ ...transformation,
+ statusMappings: {
+ ...transformaType(todoStatusList, StandardStatus.Todo),
+ ...transformaType(
+ selectedItems.map((v) => v.name),
+ StandardStatus.InProgress,
+ ),
+ ...transformaType(doneStatusList, StandardStatus.Done),
+ },
+ })
+ }
+ />
+ </Form.Item>
+ <Form.Item label="DONE">
+ <MultiSelector
+ items={statusList}
+ disabledItems={statusList.filter((v) => [...todoStatusList, ...inProgressStatusList].includes(v.name))}
+ getKey={(it) => it.id}
+ getName={(it) => it.name}
+ selectedItems={statusList.filter((v) => doneStatusList.includes(v.name))}
+ onChangeItems={(selectedItems) =>
+ onChangeTransformation({
+ ...transformation,
+ statusMappings: {
+ ...transformaType(todoStatusList, StandardStatus.Todo),
+ ...transformaType(inProgressStatusList, StandardStatus.InProgress),
+ ...transformaType(
+ selectedItems.map((v) => v.name),
+ StandardStatus.Done,
+ ),
+ },
+ })
+ }
+ />
+ </Form.Item>
+ </>
+ ),
+ },
+ ].filter((it) => entities.includes(it.key));