You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@devlake.apache.org by li...@apache.org on 2023/05/31 01:57:07 UTC
[incubator-devlake] branch main updated: feat(config-ui): improve the content about scope config (#5320)
This is an automated email from the ASF dual-hosted git repository.
likyh 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 eda853733 feat(config-ui): improve the content about scope config (#5320)
eda853733 is described below
commit eda8537334e836295406bbde041abda06feaf668
Author: 青湛 <0x...@gmail.com>
AuthorDate: Wed May 31 09:57:03 2023 +0800
feat(config-ui): improve the content about scope config (#5320)
* feat(config-ui): support params position in buttons component
* feat(config-ui): improve the style for card component
* refactor(config-ui): adjust the type for table rowKey
* fix(config-ui): depends error in github miller columns
* refactor(config-ui): some code format
* refactor(config-ui): remove plugin component about transformation
* refactor(config-ui): remove content about transformation type
* feat(config-ui): add plugin component about scope config
* feat(config-ui): improve the content about scope config
---
config-ui/src/components/buttons/index.tsx | 22 ++-
config-ui/src/components/card/index.tsx | 4 +
.../components/table/hooks/use-row-selection.ts | 10 +-
config-ui/src/global.d.ts | 10 --
.../pages/blueprint/connection-detail/index.tsx | 43 ++---
.../pages/blueprint/detail/panel/configuration.tsx | 8 +-
config-ui/src/pages/connection/detail/api.ts | 11 +-
config-ui/src/pages/connection/detail/index.tsx | 111 +++++++++++-
config-ui/src/pages/connection/detail/styled.ts | 9 -
config-ui/src/plugins/components/index.ts | 5 +-
.../{transformation => scope-config-form}/api.ts | 14 +-
.../fields/additional-settings.tsx | 0
.../fields/index.ts | 0
.../fields/styled.ts | 0
.../plugins/components/scope-config-form/index.tsx | 198 +++++++++++++++++++++
.../misc.ts | 0
.../api.ts => scope-config-form/styled.ts} | 5 +-
.../api.ts | 19 +-
.../components/scope-config-select/index.tsx | 106 +++++++++++
.../index.ts => scope-config-select/styled.ts} | 6 +-
.../components/transformation-form/index.tsx | 154 ----------------
.../components/transformation-form/styled.ts | 39 ----
.../components/transformation-select/index.tsx | 145 ---------------
.../components/transformation-select/styled.ts | 36 ----
.../plugins/components/transformation/index.tsx | 180 -------------------
.../plugins/components/transformation/styled.ts | 52 ------
config-ui/src/plugins/config.ts | 5 +-
.../github/components/miller-columns/index.tsx | 2 +-
.../miller-columns/use-miller-columns.ts | 4 +-
config-ui/src/plugins/register/github/config.tsx | 5 +-
.../github/connection-fields/authentication.tsx | 15 +-
.../github/connection-fields/githubapp.tsx | 28 +--
.../register/github/connection-fields/index.ts | 2 +-
.../register/github/connection-fields/token.tsx | 2 +-
.../register/jira/connection-fields/styled.ts | 1 -
config-ui/src/plugins/register/tapd/config.tsx | 1 -
config-ui/src/plugins/types.ts | 1 -
config-ui/src/store/connections/context.tsx | 2 -
config-ui/src/utils/operator.ts | 2 -
39 files changed, 525 insertions(+), 732 deletions(-)
diff --git a/config-ui/src/components/buttons/index.tsx b/config-ui/src/components/buttons/index.tsx
index ac5dd647e..1c411f2d3 100644
--- a/config-ui/src/components/buttons/index.tsx
+++ b/config-ui/src/components/buttons/index.tsx
@@ -18,10 +18,19 @@
import styled from 'styled-components';
-const Wrapper = styled.div<{ align: 'left' | 'right' | 'center' }>`
+const Wrapper = styled.div<{ position: 'top' | 'bottom'; align: 'left' | 'right' | 'center' }>`
display: flex;
align-items: center;
- margin-top: 24px;
+
+ ${({ position }) => {
+ if (position === 'top') {
+ return 'margin-bottom: 24px;';
+ }
+
+ if (position === 'bottom') {
+ return 'margin-top: 24px;';
+ }
+ }}
${({ align }) => {
if (align === 'left') {
@@ -43,10 +52,15 @@ const Wrapper = styled.div<{ align: 'left' | 'right' | 'center' }>`
`;
interface Props {
+ position?: 'top' | 'bottom';
align?: 'left' | 'right' | 'center';
children: React.ReactNode;
}
-export const Buttons = ({ align = 'right', children }: Props) => {
- return <Wrapper align={align}>{children}</Wrapper>;
+export const Buttons = ({ position = 'bottom', align = 'right', children }: Props) => {
+ return (
+ <Wrapper position={position} align={align}>
+ {children}
+ </Wrapper>
+ );
};
diff --git a/config-ui/src/components/card/index.tsx b/config-ui/src/components/card/index.tsx
index 2aa84c8a0..418b1f065 100644
--- a/config-ui/src/components/card/index.tsx
+++ b/config-ui/src/components/card/index.tsx
@@ -23,4 +23,8 @@ export const Card = styled.div`
background-color: #fff;
box-shadow: 0px 2.4px 4.8px -0.8px rgba(0, 0, 0, 0.1), 0px 1.6px 8px rgba(0, 0, 0, 0.07);
border-radius: 8px;
+
+ & + & {
+ margin-top: 24px;
+ }
`;
diff --git a/config-ui/src/components/table/hooks/use-row-selection.ts b/config-ui/src/components/table/hooks/use-row-selection.ts
index 358122e48..ab56bdd81 100644
--- a/config-ui/src/components/table/hooks/use-row-selection.ts
+++ b/config-ui/src/components/table/hooks/use-row-selection.ts
@@ -21,15 +21,15 @@ import { useState, useEffect, useMemo } from 'react';
export interface UseRowSelectionProps<T> {
dataSource: T[];
rowSelection?: {
- rowKey: string;
+ rowKey: ID;
type?: 'checkbox' | 'radio';
- selectedRowKeys?: string[];
- onChange?: (selectedRowKeys: string[]) => void;
+ selectedRowKeys?: ID[];
+ onChange?: (selectedRowKeys: ID[]) => void;
};
}
export const useRowSelection = <T>({ dataSource, rowSelection }: UseRowSelectionProps<T>) => {
- const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
+ const [selectedKeys, setSelectedKeys] = useState<ID[]>([]);
const {
rowKey = 'key',
@@ -48,7 +48,7 @@ export const useRowSelection = <T>({ dataSource, rowSelection }: UseRowSelection
const handleChecked = (data: T) => {
const key = (data as any)[rowKey];
- let result: string[] = selectedKeys;
+ let result: ID[] = selectedKeys;
switch (true) {
case !selectedKeys.includes(key) && type === 'radio':
diff --git a/config-ui/src/global.d.ts b/config-ui/src/global.d.ts
index a1c271815..0f3a050aa 100644
--- a/config-ui/src/global.d.ts
+++ b/config-ui/src/global.d.ts
@@ -18,16 +18,6 @@
type ID = string | number;
-type MixConnection = {
- unique: string;
- plugin: string;
- connectionId: ID;
- name: string;
- icon: string;
- scope: Array<any>;
- transformationType?: 'none' | 'for-connection' | 'for-scope';
-};
-
declare module '*.svg' {
const content: any;
export default content;
diff --git a/config-ui/src/pages/blueprint/connection-detail/index.tsx b/config-ui/src/pages/blueprint/connection-detail/index.tsx
index 01929b4d6..657fd570c 100644
--- a/config-ui/src/pages/blueprint/connection-detail/index.tsx
+++ b/config-ui/src/pages/blueprint/connection-detail/index.tsx
@@ -24,7 +24,7 @@ import { Popover2 } from '@blueprintjs/popover2';
import { Dialog, PageHeader, PageLoading } from '@/components';
import { EntitiesLabel } from '@/config';
import { useRefreshData } from '@/hooks';
-import { DataScopeSelect, getPluginConfig, Transformation } from '@/plugins';
+import { DataScopeSelect, getPluginConfig } from '@/plugins';
import * as API from './api';
import * as S from './styled';
@@ -59,7 +59,6 @@ export const BlueprintConnectionDetailPage = () => {
icon: config.icon,
scope,
origin,
- transformationType: config.transformationType,
},
};
}, [version]);
@@ -73,33 +72,6 @@ export const BlueprintConnectionDetailPage = () => {
const handleShowDataScope = () => setIsOpen(true);
const handleHideDataScope = () => setIsOpen(false);
- const handleChangeDataScope = async (connections: MixConnection[]) => {
- const [connection] = connections;
- await API.updateBlueprint(blueprint.id, {
- ...blueprint,
- settings: {
- ...blueprint.settings,
- connections: blueprint.settings.connections.map((cs: any) => {
- if (cs.plugin === connection.plugin && cs.connectionId === connection.connectionId) {
- return {
- ...cs,
- scopes: connection.scope.map((sc: any) => ({
- id: `${sc.id}`,
- entities: sc.entities,
- })),
- };
- }
- return cs;
- }),
- },
- });
- setVersion((v) => v + 1);
- };
-
- const handleChangeTransformation = () => {
- setVersion((v) => v + 1);
- };
-
const handleRemoveConnection = async () => {
await API.updateBlueprint(blueprint.id, {
...blueprint,
@@ -113,6 +85,11 @@ export const BlueprintConnectionDetailPage = () => {
history.push(pname ? `/projects/:${pname}` : `/blueprints/${blueprint.id}`);
};
+ const handleChangeDataScope = (scope: any) => {
+ console.log(scope);
+ setVersion((v) => v + 1);
+ };
+
return (
<PageHeader
breadcrumbs={[
@@ -161,7 +138,6 @@ export const BlueprintConnectionDetailPage = () => {
))}
</ul>
</S.Entities>
- <Transformation connections={[connection]} noFooter onSubmit={handleChangeTransformation} />
<Dialog
isOpen={isOpen}
title="Change Data Scope"
@@ -169,7 +145,12 @@ export const BlueprintConnectionDetailPage = () => {
style={{ width: 820 }}
onCancel={handleHideDataScope}
>
- <DataScopeSelect plugin={connection.plugin} connectionId={connection.connectionId} />
+ <DataScopeSelect
+ plugin={connection.plugin}
+ connectionId={connection.connectionId}
+ onCancel={handleHideDataScope}
+ onSubmit={handleChangeDataScope}
+ />
</Dialog>
</PageHeader>
);
diff --git a/config-ui/src/pages/blueprint/detail/panel/configuration.tsx b/config-ui/src/pages/blueprint/detail/panel/configuration.tsx
index 32c1b78c7..8d7b88220 100644
--- a/config-ui/src/pages/blueprint/detail/panel/configuration.tsx
+++ b/config-ui/src/pages/blueprint/detail/panel/configuration.tsx
@@ -83,6 +83,10 @@ export const Configuration = ({ blueprint, operating, onUpdate }: Props) => {
setType('add-connection');
};
+ const handleAddConnection = (value: any) => {
+ console.log(value);
+ };
+
return (
<S.ConfigurationPanel>
<div className="block">
@@ -201,9 +205,7 @@ export const Configuration = ({ blueprint, operating, onUpdate }: Props) => {
onSubmit={(payload) => onUpdate(payload, handleCancel)}
/>
)}
- {type === 'add-connection' && (
- <AddConnectionDialog onCancel={handleCancel} onSubmit={(value) => console.log(value)} />
- )}
+ {type === 'add-connection' && <AddConnectionDialog onCancel={handleCancel} onSubmit={handleAddConnection} />}
</S.ConfigurationPanel>
);
};
diff --git a/config-ui/src/pages/connection/detail/api.ts b/config-ui/src/pages/connection/detail/api.ts
index 055719883..60a50e4d8 100644
--- a/config-ui/src/pages/connection/detail/api.ts
+++ b/config-ui/src/pages/connection/detail/api.ts
@@ -21,7 +21,16 @@ import { request } from '@/utils';
export const deleteConnection = (plugin: string, id: ID) =>
request(`/plugins/${plugin}/connections/${id}`, { method: 'delete' });
-export const getDataScope = (plugin: string, id: ID) => request(`/plugins/${plugin}/connections/${id}/scopes`);
+export const getDataScopes = (plugin: string, id: ID) => request(`/plugins/${plugin}/connections/${id}/scopes`);
+
+export const getDataScope = (plugin: string, id: ID, scopeId: ID) =>
+ request(`/plugins/${plugin}/connections/${id}/scopes/${scopeId}`);
+
+export const updateDataScope = (plugin: string, id: ID, scopeId: ID, payload: any) =>
+ request(`/plugins/${plugin}/connections/${id}/scopes/${scopeId}`, {
+ method: 'patch',
+ data: payload,
+ });
export const deleteDataScope = (plugin: string, id: ID, scopeId: ID, onlyData: boolean) =>
request(`/plugins/${plugin}/connections/${id}/scopes/${scopeId}`, {
diff --git a/config-ui/src/pages/connection/detail/index.tsx b/config-ui/src/pages/connection/detail/index.tsx
index a82eba8c4..0d7945497 100644
--- a/config-ui/src/pages/connection/detail/index.tsx
+++ b/config-ui/src/pages/connection/detail/index.tsx
@@ -20,9 +20,16 @@ import { useState } from 'react';
import { useParams, useHistory } from 'react-router-dom';
import { Button, Icon, Intent } from '@blueprintjs/core';
-import { PageHeader, Dialog, IconButton, Table } from '@/components';
+import { PageHeader, Buttons, Dialog, IconButton, Table } from '@/components';
import { useTips, useConnections, useRefreshData } from '@/hooks';
-import { ConnectionForm, ConnectionStatus, DataScopeSelectRemote, getPluginId } from '@/plugins';
+import {
+ ConnectionForm,
+ ConnectionStatus,
+ DataScopeSelectRemote,
+ getPluginId,
+ ScopeConfigForm,
+ ScopeConfigSelect,
+} from '@/plugins';
import { operator } from '@/utils';
import * as API from './api';
@@ -35,16 +42,23 @@ interface Props {
const ConnectionDetail = ({ plugin, id }: Props) => {
const [type, setType] = useState<
- 'deleteConnection' | 'updateConnection' | 'createDataScope' | 'clearDataScope' | 'deleteDataScope'
+ | 'deleteConnection'
+ | 'updateConnection'
+ | 'createDataScope'
+ | 'clearDataScope'
+ | 'deleteDataScope'
+ | 'associateScopeConfig'
>();
const [operating, setOperating] = useState(false);
const [version, setVersion] = useState(1);
const [scopeId, setScopeId] = useState<ID>();
+ const [scopeIds, setScopeIds] = useState<ID[]>([]);
+ const [scopeConfigId, setScopeConfigId] = useState<ID>();
const history = useHistory();
const { onGet, onTest, onRefresh } = useConnections();
const { setTips } = useTips();
- const { ready, data } = useRefreshData(() => API.getDataScope(plugin, id), [version]);
+ const { ready, data } = useRefreshData(() => API.getDataScopes(plugin, id), [version]);
const { unique, status, name, icon } = onGet(`${plugin}-${id}`);
@@ -123,6 +137,36 @@ const ConnectionDetail = ({ plugin, id }: Props) => {
}
};
+ const handleShowScopeConfigSelectDialog = (scopeIds: ID[]) => {
+ setType('associateScopeConfig');
+ setScopeIds(scopeIds);
+ };
+
+ const handleAssociateScopeConfig = async (trId: ID) => {
+ const [success] = await operator(
+ () =>
+ Promise.all(
+ scopeIds.map(async (scopeId) => {
+ const scope = await API.getDataScope(plugin, id, scopeId);
+ return API.updateDataScope(plugin, id, scopeId, {
+ ...scope,
+ scopeConfigId: +trId,
+ });
+ }),
+ ),
+ {
+ setOperating,
+ formatMessage: () => `Associate scope config successful.`,
+ },
+ );
+
+ if (success) {
+ setVersion((v) => v + 1);
+ handleShowTips();
+ handleHideDialog();
+ }
+ };
+
return (
<PageHeader
breadcrumbs={[
@@ -137,9 +181,17 @@ const ConnectionDetail = ({ plugin, id }: Props) => {
<ConnectionStatus status={status} unique={unique} onTest={onTest} />
<IconButton icon="annotation" tooltip="Edit Connection" onClick={handleShowUpdateDialog} />
</div>
- <div className="action">
+ <Buttons position="top" align="left">
<Button intent={Intent.PRIMARY} icon="add" text="Add Data Scope" onClick={handleShowCreateDataScopeDialog} />
- </div>
+ {plugin !== 'tapd' && (
+ <Button
+ intent={Intent.PRIMARY}
+ icon="many-to-one"
+ text="Associate Scope Config"
+ onClick={() => handleShowScopeConfigSelectDialog(scopeIds)}
+ />
+ )}
+ </Buttons>
<Table
loading={!ready}
columns={[
@@ -148,6 +200,27 @@ const ConnectionDetail = ({ plugin, id }: Props) => {
dataIndex: 'name',
key: 'name',
},
+ {
+ title: 'Scope Config',
+ dataIndex: 'scopeConfigName',
+ key: 'scopeConfig',
+ width: 400,
+ render: (val, row) => (
+ <>
+ <span>{val ?? 'No Scope Config'}</span>
+ <IconButton
+ icon="link"
+ tooltip="Associate Scope Config"
+ onClick={() => {
+ handleShowScopeConfigSelectDialog([row[getPluginId(plugin)]]);
+ if (plugin === 'tapd') {
+ setScopeConfigId(row.scopeConfigId);
+ }
+ }}
+ />
+ </>
+ ),
+ },
{
title: '',
dataIndex: getPluginId(plugin),
@@ -175,6 +248,11 @@ const ConnectionDetail = ({ plugin, id }: Props) => {
btnText: 'Add Data Scope',
onCreate: handleShowCreateDataScopeDialog,
}}
+ rowSelection={{
+ rowKey: getPluginId(plugin),
+ selectedRowKeys: scopeIds,
+ onChange: (selectedRowKeys) => setScopeIds(selectedRowKeys),
+ }}
/>
</S.Wrapper>
{type === 'deleteConnection' && (
@@ -269,6 +347,27 @@ const ConnectionDetail = ({ plugin, id }: Props) => {
</S.DialogBody>
</Dialog>
)}
+ {type === 'associateScopeConfig' && (
+ <Dialog isOpen style={{ width: 820 }} footer={null} title="Associate Scope Config" onCancel={handleHideDialog}>
+ {plugin === 'tapd' ? (
+ <ScopeConfigForm
+ plugin={plugin}
+ connectionId={id}
+ scopeId={scopeIds[0]}
+ scopeConfigId={scopeConfigId}
+ onCancel={handleHideDialog}
+ onSubmit={handleAssociateScopeConfig}
+ />
+ ) : (
+ <ScopeConfigSelect
+ plugin={plugin}
+ connectionId={id}
+ onCancel={handleHideDialog}
+ onSubmit={handleAssociateScopeConfig}
+ />
+ )}
+ </Dialog>
+ )}
</PageHeader>
);
};
diff --git a/config-ui/src/pages/connection/detail/styled.ts b/config-ui/src/pages/connection/detail/styled.ts
index ce2815f10..8a166f523 100644
--- a/config-ui/src/pages/connection/detail/styled.ts
+++ b/config-ui/src/pages/connection/detail/styled.ts
@@ -23,15 +23,6 @@ export const Wrapper = styled.div`
display: flex;
align-items: center;
justify-content: flex-end;
-
- & > .bp4-popover2-target {
- margin-left: 8px;
- }
- }
-
- .action {
- margin-top: 36px;
- margin-bottom: 24px;
}
`;
diff --git a/config-ui/src/plugins/components/index.ts b/config-ui/src/plugins/components/index.ts
index b7fc05447..194f390e3 100644
--- a/config-ui/src/plugins/components/index.ts
+++ b/config-ui/src/plugins/components/index.ts
@@ -23,6 +23,5 @@ export * from './data-scope-miller-columns';
export * from './data-scope-search';
export * from './data-scope-select';
export * from './data-scope-select-remote';
-export * from './transformation';
-export * from './transformation-form';
-export * from './transformation-select';
+export * from './scope-config-form';
+export * from './scope-config-select';
diff --git a/config-ui/src/plugins/components/transformation/api.ts b/config-ui/src/plugins/components/scope-config-form/api.ts
similarity index 62%
rename from config-ui/src/plugins/components/transformation/api.ts
rename to config-ui/src/plugins/components/scope-config-form/api.ts
index ef0f79387..0e13fd9f2 100644
--- a/config-ui/src/plugins/components/transformation/api.ts
+++ b/config-ui/src/plugins/components/scope-config-form/api.ts
@@ -18,11 +18,17 @@
import { request } from '@/utils';
-export const getDataScope = (plugin: string, connectionId: ID, scopeId: ID) =>
- request(`/plugins/${plugin}/connections/${connectionId}/scopes/${scopeId}`);
+export const getScopeConfig = (plugin: string, connectionId: ID, id: ID) =>
+ request(`/plugins/${plugin}/connections/${connectionId}/scope_configs/${id}`);
-export const updateDataScope = (plugin: string, connectionId: ID, scopeId: ID, payload: any) =>
- request(`/plugins/${plugin}/connections/${connectionId}/scopes/${scopeId}`, {
+export const createScopeConfig = (plugin: string, connectionId: ID, payload: any) =>
+ request(`/plugins/${plugin}/connections/${connectionId}/scope_configs`, {
+ method: 'post',
+ data: payload,
+ });
+
+export const updateScopeConfig = (plugin: string, connectionId: ID, id: ID, payload: any) =>
+ request(`/plugins/${plugin}/connections/${connectionId}/scope_configs/${id}`, {
method: 'patch',
data: payload,
});
diff --git a/config-ui/src/plugins/components/transformation-form/fields/additional-settings.tsx b/config-ui/src/plugins/components/scope-config-form/fields/additional-settings.tsx
similarity index 100%
rename from config-ui/src/plugins/components/transformation-form/fields/additional-settings.tsx
rename to config-ui/src/plugins/components/scope-config-form/fields/additional-settings.tsx
diff --git a/config-ui/src/plugins/components/transformation-form/fields/index.ts b/config-ui/src/plugins/components/scope-config-form/fields/index.ts
similarity index 100%
copy from config-ui/src/plugins/components/transformation-form/fields/index.ts
copy to config-ui/src/plugins/components/scope-config-form/fields/index.ts
diff --git a/config-ui/src/plugins/components/transformation-form/fields/styled.ts b/config-ui/src/plugins/components/scope-config-form/fields/styled.ts
similarity index 100%
rename from config-ui/src/plugins/components/transformation-form/fields/styled.ts
rename to config-ui/src/plugins/components/scope-config-form/fields/styled.ts
diff --git a/config-ui/src/plugins/components/scope-config-form/index.tsx b/config-ui/src/plugins/components/scope-config-form/index.tsx
new file mode 100644
index 000000000..0637d2ee9
--- /dev/null
+++ b/config-ui/src/plugins/components/scope-config-form/index.tsx
@@ -0,0 +1,198 @@
+/*
+ * 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, useEffect, useMemo } from 'react';
+import { omit } from 'lodash';
+import { InputGroup, Button, Intent } from '@blueprintjs/core';
+
+import { Alert, ExternalLink, Card, FormItem, MultiSelector, Buttons, Divider } from '@/components';
+import { transformEntities, EntitiesLabel } from '@/config';
+import { getPluginConfig } from '@/plugins';
+import { GitHubTransformation } from '@/plugins/register/github';
+import { JiraTransformation } from '@/plugins/register/jira';
+import { GitLabTransformation } from '@/plugins/register/gitlab';
+import { JenkinsTransformation } from '@/plugins/register/jenkins';
+import { BitbucketTransformation } from '@/plugins/register/bitbucket';
+import { AzureTransformation } from '@/plugins/register/azure';
+import { TapdTransformation } from '@/plugins/register/tapd';
+import { operator } from '@/utils';
+
+import { AdditionalSettings } from './fields';
+import { TIPS_MAP } from './misc';
+import * as API from './api';
+import * as S from './styled';
+
+interface Props {
+ plugin: string;
+ connectionId: ID;
+ scopeId?: ID;
+ scopeConfigId?: ID;
+ onCancel?: () => void;
+ onSubmit?: (trId: string) => void;
+}
+
+export const ScopeConfigForm = ({ plugin, connectionId, scopeId, scopeConfigId, onCancel, onSubmit }: Props) => {
+ const [step, setStep] = useState(1);
+ const [name, setName] = useState('');
+ const [entities, setEntities] = useState<string[]>([]);
+ const [transformation, setTransformation] = useState<any>({});
+ const [hasRefDiff, setHasRefDiff] = useState(false);
+ const [operating, setOperating] = useState(false);
+
+ const config = useMemo(() => getPluginConfig(plugin), []);
+
+ useEffect(() => {
+ setHasRefDiff(!!config.transformation.refdiff);
+ }, [config.transformation]);
+
+ useEffect(() => {
+ if (!scopeConfigId) return;
+
+ (async () => {
+ try {
+ const res = await API.getScopeConfig(plugin, connectionId, scopeConfigId);
+ setName(res.name);
+ setEntities(res.entities);
+ setTransformation(omit(res, ['id', 'connectionId', 'name', 'entities', 'createdAt', 'updatedAt']));
+ } catch {}
+ })();
+ }, [scopeConfigId]);
+
+ const handleNextStep = () => {
+ setStep(2);
+ };
+
+ const handleSubmit = async () => {
+ const [success, res] = await operator(
+ () =>
+ !scopeConfigId
+ ? API.createScopeConfig(plugin, connectionId, { name, entities, ...transformation })
+ : API.updateScopeConfig(plugin, connectionId, scopeConfigId, { name, entities, ...transformation }),
+ {
+ setOperating,
+ formatMessage: () => (!scopeConfigId ? 'Create scope config successful.' : 'Update scope config successful'),
+ },
+ );
+
+ if (success) {
+ onCancel?.();
+ onSubmit?.(res.id);
+ }
+ };
+
+ return (
+ <S.Wrapper>
+ {TIPS_MAP[plugin] && (
+ <Alert style={{ marginBottom: 24 }}>
+ To learn about how {TIPS_MAP[plugin].name} transformation is used in DevLake,{' '}
+ <ExternalLink link={TIPS_MAP[plugin].link}>check out this doc</ExternalLink>.
+ </Alert>
+ )}
+ {step === 1 && (
+ <>
+ <Card>
+ <FormItem
+ label="Scope Config Name"
+ subLabel="Give this Scope Config a unique name so that you can identify it in the future."
+ required
+ >
+ <InputGroup placeholder="My Scope Config 1" value={name} onChange={(e) => setName(e.target.value)} />
+ </FormItem>
+ </Card>
+ <Card>
+ <FormItem
+ label="Data Entities"
+ subLabel={
+ <>
+ Select the data entities you wish to collect for the Data Scope.
+ <ExternalLink link="">Learn about data entities</ExternalLink>
+ </>
+ }
+ required
+ >
+ <MultiSelector
+ items={transformEntities(config.entities)}
+ getKey={(it) => it.value}
+ getName={(it) => it.label}
+ selectedItems={entities.map((it) => ({ label: EntitiesLabel[it], value: it }))}
+ onChangeItems={(its) => setEntities(its.map((it) => it.value))}
+ />
+ </FormItem>
+ </Card>
+ <Buttons>
+ <Button outlined intent={Intent.PRIMARY} text="Cancel" onClick={onCancel} />
+ <Button disabled={!name || !entities.length} intent={Intent.PRIMARY} text="Next" onClick={handleNextStep} />
+ </Buttons>
+ </>
+ )}
+ {step === 2 && (
+ <>
+ <Card>
+ {plugin === 'github' && (
+ <GitHubTransformation transformation={transformation} setTransformation={setTransformation} />
+ )}
+
+ {plugin === 'jira' && (
+ <JiraTransformation
+ connectionId={connectionId}
+ transformation={transformation}
+ setTransformation={setTransformation}
+ />
+ )}
+
+ {plugin === 'gitlab' && (
+ <GitLabTransformation transformation={transformation} setTransformation={setTransformation} />
+ )}
+
+ {plugin === 'jenkins' && (
+ <JenkinsTransformation transformation={transformation} setTransformation={setTransformation} />
+ )}
+
+ {plugin === 'bitbucket' && (
+ <BitbucketTransformation transformation={transformation} setTransformation={setTransformation} />
+ )}
+
+ {plugin === 'azuredevops' && (
+ <AzureTransformation transformation={transformation} setTransformation={setTransformation} />
+ )}
+
+ {plugin === 'tapd' && scopeId && (
+ <TapdTransformation
+ connectionId={connectionId}
+ scopeId={scopeId}
+ transformation={transformation}
+ setTransformation={setTransformation}
+ />
+ )}
+
+ {hasRefDiff && (
+ <>
+ <Divider />
+ <AdditionalSettings transformation={transformation} setTransformation={setTransformation} />
+ </>
+ )}
+ </Card>
+ <Buttons>
+ <Button outlined intent={Intent.PRIMARY} text="Cancel" onClick={onCancel} />
+ <Button loading={operating} intent={Intent.PRIMARY} text="Save" onClick={handleSubmit} />
+ </Buttons>
+ </>
+ )}
+ </S.Wrapper>
+ );
+};
diff --git a/config-ui/src/plugins/components/transformation-form/misc.ts b/config-ui/src/plugins/components/scope-config-form/misc.ts
similarity index 100%
rename from config-ui/src/plugins/components/transformation-form/misc.ts
rename to config-ui/src/plugins/components/scope-config-form/misc.ts
diff --git a/config-ui/src/plugins/components/transformation-select/api.ts b/config-ui/src/plugins/components/scope-config-form/styled.ts
similarity index 81%
rename from config-ui/src/plugins/components/transformation-select/api.ts
rename to config-ui/src/plugins/components/scope-config-form/styled.ts
index e1d6c5cc6..4bf74a53c 100644
--- a/config-ui/src/plugins/components/transformation-select/api.ts
+++ b/config-ui/src/plugins/components/scope-config-form/styled.ts
@@ -16,7 +16,6 @@
*
*/
-import { request } from '@/utils';
+import styled from 'styled-components';
-export const getTransformations = (plugin: string, connectionId: ID) =>
- request(`/plugins/${plugin}/connections/${connectionId}/transformation_rules`);
+export const Wrapper = styled.div``;
diff --git a/config-ui/src/plugins/components/transformation-form/api.ts b/config-ui/src/plugins/components/scope-config-select/api.ts
similarity index 58%
rename from config-ui/src/plugins/components/transformation-form/api.ts
rename to config-ui/src/plugins/components/scope-config-select/api.ts
index 9bfc6c4c3..8d35d854a 100644
--- a/config-ui/src/plugins/components/transformation-form/api.ts
+++ b/config-ui/src/plugins/components/scope-config-select/api.ts
@@ -18,19 +18,20 @@
import { request } from '@/utils';
-export const getTransformation = (plugin: string, connectionId: ID, tid: ID) =>
- request(`/plugins/${plugin}/connections/${connectionId}/transformation_rules/${tid}`, {
- method: 'get',
- });
+export const getScopeConfigs = (plugin: string, connectionId: ID) =>
+ request(`/plugins/${plugin}/connections/${connectionId}/scope_configs`);
+
+export const getScopeConfig = (plugin: string, connectionId: ID, id: ID) =>
+ request(`/plugins/${plugin}/connections/${connectionId}/scope_configs/${id}`);
-export const createTransformation = (plugin: string, connectionId: ID, paylod: any) =>
- request(`/plugins/${plugin}/connections/${connectionId}/transformation_rules`, {
+export const createScopeConfig = (plugin: string, connectionId: ID, payload: any) =>
+ request(`/plugins/${plugin}/connections/${connectionId}/scope_configs`, {
method: 'post',
- data: paylod,
+ data: payload,
});
-export const updateTransformation = (plugin: string, connectionId: ID, tid: ID, payload: any) =>
- request(`/plugins/${plugin}/connections/${connectionId}/transformation_rules/${tid}`, {
+export const updateScopeConfig = (plugin: string, connectionId: ID, id: ID, payload: any) =>
+ request(`/plugins/${plugin}/connections/${connectionId}/scope_configs/${id}`, {
method: 'patch',
data: payload,
});
diff --git a/config-ui/src/plugins/components/scope-config-select/index.tsx b/config-ui/src/plugins/components/scope-config-select/index.tsx
new file mode 100644
index 000000000..18fbcb6bd
--- /dev/null
+++ b/config-ui/src/plugins/components/scope-config-select/index.tsx
@@ -0,0 +1,106 @@
+/*
+ * 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, useMemo } from 'react';
+import { Button, Intent } from '@blueprintjs/core';
+
+import { Buttons, Table, IconButton, Dialog } from '@/components';
+import { useRefreshData } from '@/hooks';
+
+import { ScopeConfigForm } from '../scope-config-form';
+
+import * as API from './api';
+import * as S from './styled';
+
+interface Props {
+ plugin: string;
+ connectionId: ID;
+ onCancel?: () => void;
+ onSubmit?: (trId: string) => void;
+}
+
+export const ScopeConfigSelect = ({ plugin, connectionId, onCancel, onSubmit }: Props) => {
+ const [version, setVersion] = useState(1);
+ const [trId, setTrId] = useState<string>();
+ const [isOpen, setIsOpen] = useState(false);
+ const [updatedId, setUpdatedId] = useState<ID>();
+
+ const { ready, data } = useRefreshData(() => API.getScopeConfigs(plugin, connectionId), [version]);
+
+ const dataSource = useMemo(() => (data ? data : []), [data]);
+
+ const handleShowDialog = () => {
+ setIsOpen(true);
+ };
+
+ const handleHideDialog = () => {
+ setIsOpen(false);
+ };
+
+ const handleUpdate = async (id: ID) => {
+ setUpdatedId(id);
+ handleShowDialog();
+ };
+
+ const handleSubmit = async () => {
+ handleHideDialog();
+ setVersion((v) => v + 1);
+ };
+
+ return (
+ <S.Wrapper>
+ <Buttons position="top" align="left">
+ <Button icon="add" intent={Intent.PRIMARY} text="Add New Scope Config" onClick={handleShowDialog} />
+ </Buttons>
+ <Table
+ loading={!ready}
+ columns={[
+ { title: 'Name', dataIndex: 'name', key: 'name' },
+ {
+ title: '',
+ dataIndex: 'id',
+ key: 'id',
+ width: 100,
+ render: (id) => <IconButton icon="annotation" tooltip="Edit" onClick={() => handleUpdate(id)} />,
+ },
+ ]}
+ dataSource={dataSource}
+ rowSelection={{
+ rowKey: 'id',
+ type: 'radio',
+ selectedRowKeys: trId ? [`${trId}`] : [],
+ onChange: (selectedRowKeys) => setTrId(`${selectedRowKeys[0]}`),
+ }}
+ noShadow
+ />
+ <Buttons>
+ <Button outlined intent={Intent.PRIMARY} text="Cancel" onClick={onCancel} />
+ <Button disabled={!trId} intent={Intent.PRIMARY} text="Save" onClick={() => trId && onSubmit?.(trId)} />
+ </Buttons>
+ <Dialog style={{ width: 820 }} footer={null} isOpen={isOpen} title="Add Scope Config" onCancel={handleHideDialog}>
+ <ScopeConfigForm
+ plugin={plugin}
+ connectionId={connectionId}
+ scopeConfigId={updatedId}
+ onCancel={onCancel}
+ onSubmit={handleSubmit}
+ />
+ </Dialog>
+ </S.Wrapper>
+ );
+};
diff --git a/config-ui/src/plugins/components/transformation-form/fields/index.ts b/config-ui/src/plugins/components/scope-config-select/styled.ts
similarity index 87%
rename from config-ui/src/plugins/components/transformation-form/fields/index.ts
rename to config-ui/src/plugins/components/scope-config-select/styled.ts
index f4a5a16e6..7ccc32dbe 100644
--- a/config-ui/src/plugins/components/transformation-form/fields/index.ts
+++ b/config-ui/src/plugins/components/scope-config-select/styled.ts
@@ -16,4 +16,8 @@
*
*/
-export * from './additional-settings';
+import styled from 'styled-components';
+
+export const Wrapper = styled.div``;
+
+export const DialogBody = styled.div``;
diff --git a/config-ui/src/plugins/components/transformation-form/index.tsx b/config-ui/src/plugins/components/transformation-form/index.tsx
deleted file mode 100644
index 4b20f9394..000000000
--- a/config-ui/src/plugins/components/transformation-form/index.tsx
+++ /dev/null
@@ -1,154 +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 { useEffect, useMemo, useState } from 'react';
-import { Button, InputGroup, Intent } from '@blueprintjs/core';
-
-import { Card, ExternalLink, PageLoading, Divider } from '@/components';
-import { useRefreshData } from '@/hooks';
-import { operator } from '@/utils';
-import { getPluginConfig } from '@/plugins';
-import { GitHubTransformation } from '@/plugins/register/github';
-import { JiraTransformation } from '@/plugins/register/jira';
-import { GitLabTransformation } from '@/plugins/register/gitlab';
-import { JenkinsTransformation } from '@/plugins/register/jenkins';
-import { BitbucketTransformation } from '@/plugins/register/bitbucket';
-import { AzureTransformation } from '@/plugins/register/azure';
-import { TapdTransformation } from '@/plugins/register/tapd';
-
-import { TIPS_MAP } from './misc';
-import { AdditionalSettings } from './fields';
-import * as API from './api';
-import * as S from './styled';
-
-interface Props {
- plugin: string;
- connectionId: ID;
- scopeId: ID;
- id?: ID;
- onCancel?: (transformationRule?: any) => void;
-}
-
-export const TransformationForm = ({ plugin, connectionId, scopeId, id, onCancel }: Props) => {
- const [saving, setSaving] = useState(false);
- const [name, setName] = useState('');
- const [transformation, setTransformation] = useState({});
- const [hasRefDiff, setHasRefDiff] = useState(false);
-
- const config = useMemo(() => getPluginConfig(plugin), []);
-
- const { ready, data } = useRefreshData(async () => {
- if (!id) return null;
- return API.getTransformation(plugin, connectionId, id);
- }, [id]);
-
- useEffect(() => {
- setTransformation(data ?? config.transformation);
- setHasRefDiff(!!config.transformation.refdiff);
- setName(data?.name ?? '');
- }, [data, config.transformation]);
-
- const handleSubmit = async () => {
- const [success, res] = await operator(
- () =>
- id
- ? API.updateTransformation(plugin, connectionId, id, { ...transformation, name })
- : API.createTransformation(plugin, connectionId, { ...transformation, name }),
- {
- setOperating: setSaving,
- formatMessage: () => 'Transformation created successfully',
- },
- );
-
- if (success) {
- onCancel?.(res);
- }
- };
-
- if (!ready) {
- return <PageLoading />;
- }
-
- return (
- <S.Wrapper>
- {TIPS_MAP[plugin] && (
- <S.Tips>
- To learn about how {TIPS_MAP[plugin].name} transformation is used in DevLake,{' '}
- <ExternalLink link={TIPS_MAP[plugin].link}>check out this doc</ExternalLink>.
- </S.Tips>
- )}
-
- <Card style={{ marginTop: 24 }}>
- <h3>Transformation Name *</h3>
- <p>Give this set of transformation rules a unique name so that you can identify it in the future.</p>
- <InputGroup placeholder="Enter Transformation Name" value={name} onChange={(e) => setName(e.target.value)} />
- </Card>
-
- <Card style={{ marginTop: 24 }}>
- {plugin === 'github' && (
- <GitHubTransformation transformation={transformation} setTransformation={setTransformation} />
- )}
-
- {plugin === 'jira' && (
- <JiraTransformation
- connectionId={connectionId}
- transformation={transformation}
- setTransformation={setTransformation}
- />
- )}
-
- {plugin === 'gitlab' && (
- <GitLabTransformation transformation={transformation} setTransformation={setTransformation} />
- )}
-
- {plugin === 'jenkins' && (
- <JenkinsTransformation transformation={transformation} setTransformation={setTransformation} />
- )}
-
- {plugin === 'bitbucket' && (
- <BitbucketTransformation transformation={transformation} setTransformation={setTransformation} />
- )}
-
- {plugin === 'azuredevops' && (
- <AzureTransformation transformation={transformation} setTransformation={setTransformation} />
- )}
-
- {plugin === 'tapd' && (
- <TapdTransformation
- connectionId={connectionId}
- scopeId={scopeId}
- transformation={transformation}
- setTransformation={setTransformation}
- />
- )}
-
- {hasRefDiff && (
- <>
- <Divider />
- <AdditionalSettings transformation={transformation} setTransformation={setTransformation} />
- </>
- )}
- </Card>
-
- <S.Btns>
- <Button outlined intent={Intent.PRIMARY} text="Cancel" onClick={() => onCancel?.(undefined)} />
- <Button intent={Intent.PRIMARY} disabled={!name} loading={saving} text="Save" onClick={handleSubmit} />
- </S.Btns>
- </S.Wrapper>
- );
-};
diff --git a/config-ui/src/plugins/components/transformation-form/styled.ts b/config-ui/src/plugins/components/transformation-form/styled.ts
deleted file mode 100644
index cc7bea2fe..000000000
--- a/config-ui/src/plugins/components/transformation-form/styled.ts
+++ /dev/null
@@ -1,39 +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 Wrapper = styled.div``;
-
-export const Tips = styled.div`
- padding: 24px;
- background: #f0f4fe;
- border: 1px solid #bdcefb;
- border-radius: 4px;
-`;
-
-export const Btns = styled.div`
- display: flex;
- align-items: center;
- justify-content: end;
- margin-top: 24px;
-
- .bp4-button + .bp4-button {
- margin-left: 4px;
- }
-`;
diff --git a/config-ui/src/plugins/components/transformation-select/index.tsx b/config-ui/src/plugins/components/transformation-select/index.tsx
deleted file mode 100644
index ac1440fd6..000000000
--- a/config-ui/src/plugins/components/transformation-select/index.tsx
+++ /dev/null
@@ -1,145 +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, useEffect, useMemo } from 'react';
-import { Button, Intent } from '@blueprintjs/core';
-
-import { Dialog, PageLoading, Table, IconButton } from '@/components';
-import { useRefreshData } from '@/hooks';
-import { TransformationForm } from '@/plugins';
-
-import * as API from './api';
-import * as S from './styled';
-
-interface Props {
- plugin: string;
- connectionId: ID;
- scopeId: ID;
- transformationId?: ID;
- transformationType: MixConnection['transformationType'];
- onCancel: () => void;
- onSubmit: (tid: ID) => void;
-}
-
-export const TransformationSelect = ({
- plugin,
- connectionId,
- scopeId,
- transformationId,
- transformationType,
- onCancel,
- onSubmit,
-}: Props) => {
- const [step, setStep] = useState(1);
- const [type, setType] = useState<'add' | 'edit'>('add');
- const [selectedId, setSelectedId] = useState<ID>();
- const [updatedId, setUpdatedId] = useState<ID>();
-
- useEffect(() => setSelectedId(transformationId), [transformationId]);
-
- useEffect(() => {
- setStep(transformationType === 'for-scope' ? 2 : 1);
- setType(transformationType === 'for-scope' && transformationId ? 'edit' : 'add');
- setUpdatedId(transformationType === 'for-scope' && transformationId ? transformationId : undefined);
- }, [transformationId, transformationType]);
-
- const { ready, data } = useRefreshData(() => API.getTransformations(plugin, connectionId), [step]);
-
- const title = useMemo(() => {
- switch (true) {
- case step === 1:
- return 'Associate Transformation';
- case type === 'add':
- return 'Add New Transformation';
- case type === 'edit':
- return 'Edit Transformation';
- }
- }, [step, type]);
-
- const handleNewTransformation = () => {
- setStep(2);
- setType('add');
- };
-
- const handleEditTransformation = (id: ID) => {
- setStep(2);
- setType('edit');
- setUpdatedId(id);
- };
-
- const handleReset = (tr?: any) => {
- if (transformationType === 'for-scope') {
- return tr ? onSubmit(tr.id) : onCancel();
- }
- setStep(1);
- setUpdatedId('');
- };
-
- const handleSubmit = () => !!selectedId && onSubmit(selectedId);
-
- return (
- <Dialog isOpen title={title} footer={null} style={{ width: 960 }} onCancel={onCancel}>
- {!ready || !data ? (
- <PageLoading />
- ) : step === 1 ? (
- <S.Wrapper>
- <S.Aciton>
- <Button intent={Intent.PRIMARY} icon="add" onClick={handleNewTransformation}>
- Add New Transformation
- </Button>
- </S.Aciton>
- <Table
- columns={[
- { title: 'Transformation', dataIndex: 'name', key: 'name' },
- {
- title: '',
- dataIndex: 'id',
- key: 'id',
- width: 100,
- align: 'right',
- render: (id) => (
- <IconButton icon="annotation" tooltip="Edit" onClick={() => handleEditTransformation(id)} />
- ),
- },
- ]}
- dataSource={data}
- rowSelection={{
- rowKey: 'id',
- type: 'radio',
- selectedRowKeys: selectedId ? [`${selectedId}`] : [],
- onChange: (selectedRowKeys) => setSelectedId(selectedRowKeys[0]),
- }}
- noShadow
- />
- <S.Btns>
- <Button outlined intent={Intent.PRIMARY} text="Cancel" onClick={onCancel} />
- <Button disabled={!selectedId} intent={Intent.PRIMARY} text="Save" onClick={handleSubmit} />
- </S.Btns>
- </S.Wrapper>
- ) : (
- <TransformationForm
- plugin={plugin}
- connectionId={connectionId}
- scopeId={scopeId}
- id={updatedId}
- onCancel={handleReset}
- />
- )}
- </Dialog>
- );
-};
diff --git a/config-ui/src/plugins/components/transformation-select/styled.ts b/config-ui/src/plugins/components/transformation-select/styled.ts
deleted file mode 100644
index c4c1bee23..000000000
--- a/config-ui/src/plugins/components/transformation-select/styled.ts
+++ /dev/null
@@ -1,36 +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 Wrapper = styled.div``;
-
-export const Aciton = styled.div`
- margin-bottom: 16px;
-`;
-
-export const Btns = styled.div`
- display: flex;
- align-items: center;
- justify-content: end;
- margin-top: 24px;
-
- .bp4-button + .bp4-button {
- margin-left: 4px;
- }
-`;
diff --git a/config-ui/src/plugins/components/transformation/index.tsx b/config-ui/src/plugins/components/transformation/index.tsx
deleted file mode 100644
index 407cc275d..000000000
--- a/config-ui/src/plugins/components/transformation/index.tsx
+++ /dev/null
@@ -1,180 +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 { Button, Intent } from '@blueprintjs/core';
-
-import { IconButton, Table } from '@/components';
-import { getPluginId, TransformationSelect } from '@/plugins';
-
-import * as API from './api';
-import * as S from './styled';
-
-interface Props {
- connections: MixConnection[];
- cancelBtnProps?: {
- text?: string;
- };
- submitBtnProps?: {
- text?: string;
- loading?: boolean;
- };
- noFooter?: boolean;
- onCancel?: () => void;
- onSubmit?: (connections: MixConnection[]) => void;
- onNext?: () => void;
-}
-
-export const Transformation = ({
- connections,
- cancelBtnProps,
- submitBtnProps,
- noFooter,
- onCancel,
- onSubmit,
- onNext,
-}: Props) => {
- const [selected, setSelected] = useState<Record<string, string[]>>({});
- const [connection, setConnection] = useState<MixConnection>();
- const [tid, setTid] = useState<ID>();
-
- const handleCancel = () => {
- setConnection(undefined);
- setTid(undefined);
- };
-
- const handleSubmit = async (tid: ID, connection: MixConnection, connections: MixConnection[]) => {
- const { unique, plugin, connectionId } = connection;
- const scopeIds = selected[unique];
- const scopes = await Promise.all(
- scopeIds.map(async (scopeId) => {
- const scope = await API.getDataScope(plugin, connectionId, scopeId);
- return await API.updateDataScope(plugin, connectionId, scopeId, {
- ...scope,
- transformationRuleId: tid,
- });
- }),
- );
- onSubmit?.(
- connections.map((cs) => {
- if (cs.unique !== unique) {
- return cs;
- }
-
- const scope = cs.scope.map((sc) => {
- if (!scopeIds.includes(sc[getPluginId(cs.plugin)])) {
- return sc;
- }
- return scopes.find((it) => it[getPluginId(cs.plugin)] === sc[getPluginId(cs.plugin)]);
- });
-
- return { ...cs, scope };
- }),
- );
- setSelected({
- ...selected,
- [`${unique}`]: [],
- });
- handleCancel();
- };
-
- return (
- <S.List>
- {connections.map((cs) => (
- <S.Item key={cs.unique}>
- {connections.length !== 1 && (
- <S.Title>
- <img src={cs.icon} alt="" />
- <span>{cs.name}</span>
- </S.Title>
- )}
- {cs.transformationType === 'for-connection' && (
- <S.Action>
- <Button
- intent={Intent.PRIMARY}
- icon="many-to-one"
- disabled={!selected[cs.unique] || !selected[cs.unique].length}
- onClick={() => setConnection(cs)}
- >
- Associate Transformation
- </Button>
- </S.Action>
- )}
- <Table
- columns={[
- { title: 'Data Scope', dataIndex: 'name', key: 'name' },
- {
- title: 'Transformation',
- dataIndex: 'transformationRuleName',
- key: 'transformation',
- align: 'center',
- render: (val, row) =>
- cs.transformationType === 'none' ? (
- 'N/A'
- ) : (
- <div>
- <span>{val ?? 'N/A'}</span>
- <IconButton
- icon="one-to-one"
- tooltip="Associate Transformation"
- onClick={() => {
- setSelected({
- ...selected,
- [`${cs.unique}`]: [row[getPluginId(cs.plugin)]],
- });
- setConnection(cs);
- setTid(row.transformationRuleId);
- }}
- />
- </div>
- ),
- },
- ]}
- dataSource={cs.scope}
- rowSelection={
- cs.transformationType === 'for-connection'
- ? {
- rowKey: getPluginId(cs.plugin),
- selectedRowKeys: selected[cs.unique],
- onChange: (selectedRowKeys) => setSelected({ ...selected, [`${cs.unique}`]: selectedRowKeys }),
- }
- : undefined
- }
- />
- </S.Item>
- ))}
- {!noFooter && (
- <S.Btns>
- <Button outlined intent={Intent.PRIMARY} text="Previous Step" onClick={onCancel} {...cancelBtnProps} />
- <Button intent={Intent.PRIMARY} text="Next Step" onClick={onNext} {...submitBtnProps} />
- </S.Btns>
- )}
- {connection && (
- <TransformationSelect
- plugin={connection.plugin}
- connectionId={connection.connectionId}
- scopeId={selected[connection.unique][0]}
- transformationId={tid}
- transformationType={connection.transformationType}
- onCancel={handleCancel}
- onSubmit={(tid) => handleSubmit(tid, connection, connections)}
- />
- )}
- </S.List>
- );
-};
diff --git a/config-ui/src/plugins/components/transformation/styled.ts b/config-ui/src/plugins/components/transformation/styled.ts
deleted file mode 100644
index 7062ec37e..000000000
--- a/config-ui/src/plugins/components/transformation/styled.ts
+++ /dev/null
@@ -1,52 +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 List = styled.div``;
-
-export const Item = styled.div`
- margin-bottom: 36px;
-
- &:last-child {
- margin-bottom: 0;
- }
-`;
-
-export const Title = styled.div`
- display: flex;
- align-items: center;
- margin-bottom: 16px;
-
- img {
- margin-right: 4px;
- width: 24px;
- height: 24px;
- }
-`;
-
-export const Action = styled.div`
- margin-bottom: 16px;
-`;
-
-export const Btns = styled.div`
- display: flex;
- align-items: center;
- justify-content: space-between;
- margin-top: 36px;
-`;
diff --git a/config-ui/src/plugins/config.ts b/config-ui/src/plugins/config.ts
index 29fefa6c4..1f907f71b 100644
--- a/config-ui/src/plugins/config.ts
+++ b/config-ui/src/plugins/config.ts
@@ -78,8 +78,5 @@ export function getPluginConfig(pluginName: string): PluginConfigType {
name: pluginName,
} as PluginConfigType;
}
- return {
- ...pluginConfig,
- transformationType: pluginConfig.transformationType || (pluginConfig.transformation ? 'for-connection' : 'none'),
- };
+ return pluginConfig;
}
diff --git a/config-ui/src/plugins/register/github/components/miller-columns/index.tsx b/config-ui/src/plugins/register/github/components/miller-columns/index.tsx
index 842de51c9..316eb52f4 100644
--- a/config-ui/src/plugins/register/github/components/miller-columns/index.tsx
+++ b/config-ui/src/plugins/register/github/components/miller-columns/index.tsx
@@ -48,7 +48,7 @@ export const MillerColumns = ({ connectionId, disabledItems, selectedItems, onCh
useEffect(() => {
setDisabledIds((disabledItems ?? []).map((it) => it.githubId));
- }, [disabledIds]);
+ }, [disabledItems]);
const handleChangeItems = (selectedIds: McsID[]) => {
const result = selectedIds.map((id) => {
diff --git a/config-ui/src/plugins/register/github/components/miller-columns/use-miller-columns.ts b/config-ui/src/plugins/register/github/components/miller-columns/use-miller-columns.ts
index 04f003218..6625e63c2 100644
--- a/config-ui/src/plugins/register/github/components/miller-columns/use-miller-columns.ts
+++ b/config-ui/src/plugins/register/github/components/miller-columns/use-miller-columns.ts
@@ -105,7 +105,7 @@ export const useMillerColumns = ({ connectionId }: UseMillerColumnsProps) => {
title: appInstallationRepos.repositories[0].owner.login,
type: 'org',
} as any,
- ])
+ ]);
}
} else {
const user = await API.getUser(prefix);
@@ -127,7 +127,7 @@ export const useMillerColumns = ({ connectionId }: UseMillerColumnsProps) => {
},
...formatOrgs(orgs),
]);
- }
+ }
})();
}, [prefix]);
diff --git a/config-ui/src/plugins/register/github/config.tsx b/config-ui/src/plugins/register/github/config.tsx
index 43a9db085..c488355ff 100644
--- a/config-ui/src/plugins/register/github/config.tsx
+++ b/config-ui/src/plugins/register/github/config.tsx
@@ -45,7 +45,7 @@ export const GitHubConfig: PluginConfigType = {
server: ' ',
},
},
- ({ initialValues, values, errors, setValues, setErrors }: any) => (
+ ({ initialValues, values, setValues }: any) => (
<Authentication
key="authMethod"
initialValue={initialValues.authMethod ?? ''}
@@ -54,8 +54,9 @@ export const GitHubConfig: PluginConfigType = {
/>
),
({ initialValues, values, errors, setValues, setErrors }: any) =>
- (values.authMethod || initialValues.authMethod) == 'AccessToken' ? (
+ (values.authMethod || initialValues.authMethod) === 'AccessToken' ? (
<Token
+ key="token"
endpoint={values.endpoint}
proxy={values.proxy}
initialValue={initialValues.token ?? ''}
diff --git a/config-ui/src/plugins/register/github/connection-fields/authentication.tsx b/config-ui/src/plugins/register/github/connection-fields/authentication.tsx
index 8ddb6547d..9cb6e3d0b 100644
--- a/config-ui/src/plugins/register/github/connection-fields/authentication.tsx
+++ b/config-ui/src/plugins/register/github/connection-fields/authentication.tsx
@@ -28,20 +28,21 @@ interface Props {
}
export const Authentication = ({ initialValue, value, setValue }: Props) => {
-
useEffect(() => {
setValue(initialValue);
}, [initialValue]);
return (
<FormGroup label={<S.Label>Authentication type</S.Label>} labelInfo={<S.LabelInfo>*</S.LabelInfo>}>
- <RadioGroup inline selectedValue={value || initialValue} onChange={(e) => {
- setValue((e.target as any).value);
- }}>
+ <RadioGroup
+ inline
+ selectedValue={value || initialValue}
+ onChange={(e) => {
+ setValue((e.target as any).value);
+ }}
+ >
<Radio value="AccessToken">Github Access Token</Radio>
- <Radio value="AppKey">
- Github App
- </Radio>
+ <Radio value="AppKey">Github App</Radio>
</RadioGroup>
</FormGroup>
);
diff --git a/config-ui/src/plugins/register/github/connection-fields/githubapp.tsx b/config-ui/src/plugins/register/github/connection-fields/githubapp.tsx
index 6691c9025..5637ad73e 100644
--- a/config-ui/src/plugins/register/github/connection-fields/githubapp.tsx
+++ b/config-ui/src/plugins/register/github/connection-fields/githubapp.tsx
@@ -69,10 +69,14 @@ export const GithubApp = ({ endpoint, proxy, initialValue, value, error, setValu
secretKey: '',
installationId: '',
});
- }
+ };
}, [value.appId, value.secretKey, value.installationId]);
- const testConfiguration = async (appId?: string, secretKey?: string, installationId?: number): Promise<GithubAppSettings> => {
+ const testConfiguration = async (
+ appId?: string,
+ secretKey?: string,
+ installationId?: number,
+ ): Promise<GithubAppSettings> => {
if (!endpoint || !appId || !secretKey) {
return {
appId,
@@ -110,7 +114,7 @@ export const GithubApp = ({ endpoint, proxy, initialValue, value, error, setValu
};
const handleChangeAppId = (value: string) => {
- setSettings({ ...settings, appId: value });;
+ setSettings({ ...settings, appId: value });
};
const handleChangeClientSecret = (value: string) => {
@@ -127,7 +131,6 @@ export const GithubApp = ({ endpoint, proxy, initialValue, value, error, setValu
setSettings(res);
};
-
useEffect(() => {
checkConfig(initialValue.appId, initialValue.secretKey, initialValue.installationId);
}, [initialValue.appId, initialValue.secretKey, initialValue.installationId, endpoint]);
@@ -136,7 +139,6 @@ export const GithubApp = ({ endpoint, proxy, initialValue, value, error, setValu
setValue({ appId: settings.appId, secretKey: settings.secretKey, installationId: settings.installationId });
}, [settings.appId, settings.secretKey, settings.installationId]);
-
return (
<FormGroup
label={<S.Label>Github App settings</S.Label>}
@@ -144,9 +146,7 @@ export const GithubApp = ({ endpoint, proxy, initialValue, value, error, setValu
subLabel={
<S.LabelDescription>
Input information about your Github App{' '}
- <ExternalLink link="https://TODO">
- Learn how to create a github app
- </ExternalLink>
+ <ExternalLink link="https://TODO">Learn how to create a github app</ExternalLink>
</S.LabelDescription>
}
>
@@ -184,7 +184,7 @@ export const GithubApp = ({ endpoint, proxy, initialValue, value, error, setValu
<S.Input>
<Select2
items={settings.installations ?? []}
- activeItem={settings.installations?.find(e => e.id === settings.installationId)}
+ activeItem={settings.installations?.find((e) => e.id === settings.installationId)}
itemPredicate={(query, item) => item.account.login.toLowerCase().includes(query.toLowerCase())}
itemRenderer={(item, { handleClick, handleFocus, modifiers }) => {
return (
@@ -197,7 +197,7 @@ export const GithubApp = ({ endpoint, proxy, initialValue, value, error, setValu
onFocus={handleFocus}
roleStructure="listoption"
text={item.account.login}
- />
+ />
);
}}
onItemSelect={(item) => {
@@ -207,9 +207,13 @@ export const GithubApp = ({ endpoint, proxy, initialValue, value, error, setValu
popoverProps={{ minimal: true }}
>
<Button
- text={settings.installations?.find(e => e.id === settings.installationId)?.account.login ?? 'Select App installation'}
+ text={
+ settings.installations?.find((e) => e.id === settings.installationId)?.account.login ??
+ 'Select App installation'
+ }
rightIcon="double-caret-vertical"
- placeholder="Select App installation" />
+ placeholder="Select App installation"
+ />
</Select2>
</S.Input>
</FormGroup>
diff --git a/config-ui/src/plugins/register/github/connection-fields/index.ts b/config-ui/src/plugins/register/github/connection-fields/index.ts
index 8e0a150a7..1775eec52 100644
--- a/config-ui/src/plugins/register/github/connection-fields/index.ts
+++ b/config-ui/src/plugins/register/github/connection-fields/index.ts
@@ -19,4 +19,4 @@
export * from './token';
export * from './graphql';
export * from './githubapp';
-export * from './authentication';
\ No newline at end of file
+export * from './authentication';
diff --git a/config-ui/src/plugins/register/github/connection-fields/token.tsx b/config-ui/src/plugins/register/github/connection-fields/token.tsx
index b811a072d..38dd31ba4 100644
--- a/config-ui/src/plugins/register/github/connection-fields/token.tsx
+++ b/config-ui/src/plugins/register/github/connection-fields/token.tsx
@@ -88,7 +88,7 @@ export const Token = ({ endpoint, proxy, initialValue, value, error, setValue, s
return () => {
setError('');
- }
+ };
}, [value]);
useEffect(() => {
diff --git a/config-ui/src/plugins/register/jira/connection-fields/styled.ts b/config-ui/src/plugins/register/jira/connection-fields/styled.ts
index 7833a8536..11e47a3d0 100644
--- a/config-ui/src/plugins/register/jira/connection-fields/styled.ts
+++ b/config-ui/src/plugins/register/jira/connection-fields/styled.ts
@@ -16,7 +16,6 @@
*
*/
-import { Colors } from '@blueprintjs/core';
import styled from 'styled-components';
export const Label = styled.label`
diff --git a/config-ui/src/plugins/register/tapd/config.tsx b/config-ui/src/plugins/register/tapd/config.tsx
index 1c36f8a8e..8be01df61 100644
--- a/config-ui/src/plugins/register/tapd/config.tsx
+++ b/config-ui/src/plugins/register/tapd/config.tsx
@@ -72,7 +72,6 @@ export const TAPDConfig: PluginConfigType = {
],
},
entities: ['TICKET', 'CROSS'],
- transformationType: 'for-scope',
transformation: {
typeMappings: {},
statusMappings: {},
diff --git a/config-ui/src/plugins/types.ts b/config-ui/src/plugins/types.ts
index 4dbe61edc..772368d46 100644
--- a/config-ui/src/plugins/types.ts
+++ b/config-ui/src/plugins/types.ts
@@ -35,5 +35,4 @@ export type PluginConfigType = {
};
entities: string[];
transformation: any;
- transformationType?: 'none' | 'for-connection' | 'for-scope';
};
diff --git a/config-ui/src/store/connections/context.tsx b/config-ui/src/store/connections/context.tsx
index b9a1fcea0..caec3a22a 100644
--- a/config-ui/src/store/connections/context.tsx
+++ b/config-ui/src/store/connections/context.tsx
@@ -112,8 +112,6 @@ export const ConnectionContextProvider = ({ children, ...props }: Props) => {
}));
};
-
-
const handleGet = (unique: string) => {
return connections.find((cs) => cs.unique === unique) as ConnectionItemType;
};
diff --git a/config-ui/src/utils/operator.ts b/config-ui/src/utils/operator.ts
index e144179f9..d1aeb1d4c 100644
--- a/config-ui/src/utils/operator.ts
+++ b/config-ui/src/utils/operator.ts
@@ -16,8 +16,6 @@
*
*/
-import { Intent } from '@blueprintjs/core';
-
import { toast } from '@/components';
export type OperateConfig = {