This is an automated email from the ASF dual-hosted git repository. mintsweet pushed a commit to branch feat-dora-config in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git
commit 899310b819b5ae065d001d2679a37e6f04ac9d48 Author: mintsweet <0x1304...@gmail.com> AuthorDate: Wed Sep 11 16:41:02 2024 +1200 feat: adjust the part of github scope config cicd --- config-ui/src/api/scope-config/index.ts | 18 +++- config-ui/src/api/scope-config/types.ts | 5 + .../components/check-matched-items/index.tsx | 93 +++++++++++++++++++ .../src/plugins/components/deployments/index.tsx | 102 +++++++++++++++++++++ config-ui/src/plugins/components/index.ts | 2 + .../plugins/components/scope-config-form/index.tsx | 2 + .../src/plugins/register/github/transformation.tsx | 34 ++++--- 7 files changed, 244 insertions(+), 12 deletions(-) diff --git a/config-ui/src/api/scope-config/index.ts b/config-ui/src/api/scope-config/index.ts index 41547d9c0..f29786b56 100644 --- a/config-ui/src/api/scope-config/index.ts +++ b/config-ui/src/api/scope-config/index.ts @@ -18,7 +18,7 @@ import { request } from '@/utils'; -import { ICheck } from './types'; +import { ICheck, ITransform2deployments } from './types'; export const list = (plugin: string, connectionId: ID) => request(`/plugins/${plugin}/connections/${connectionId}/scope-configs`); @@ -40,3 +40,19 @@ export const update = (plugin: string, connectionId: ID, id: ID, data: any) => export const check = (plugin: string, id: ID): Promise<ICheck> => request(`/plugins/${plugin}/scope-config/${id}/projects`); + +export const deployments = (plugin: string, connectionId: ID): Promise<string[]> => + request(`/plugins/${plugin}/connections/${connectionId}/deployments`); + +export const transform2deployments = ( + plugin: string, + connectionId: ID, + data: { + deploymentPattern: string; + productionPattern: string; + } & Pagination, +): Promise<{ total: number; data: ITransform2deployments[] }> => + request(`/plugins/${plugin}/connections/${connectionId}/transform-to-deployments`, { + method: 'post', + data, + }); diff --git a/config-ui/src/api/scope-config/types.ts b/config-ui/src/api/scope-config/types.ts index 4c779c658..e61992aca 100644 --- a/config-ui/src/api/scope-config/types.ts +++ b/config-ui/src/api/scope-config/types.ts @@ -22,3 +22,8 @@ export type ICheck = { name: string; }>; }; + +export type ITransform2deployments = { + name: string; + url: string; +}; diff --git a/config-ui/src/plugins/components/check-matched-items/index.tsx b/config-ui/src/plugins/components/check-matched-items/index.tsx new file mode 100644 index 000000000..ce9c2b12b --- /dev/null +++ b/config-ui/src/plugins/components/check-matched-items/index.tsx @@ -0,0 +1,93 @@ +/* + * 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, useReducer } from 'react'; +import { SearchOutlined, PlusOutlined } from '@ant-design/icons'; +import { Flex, Button, Tag } from 'antd'; + +import API from '@/api'; +import type { ITransform2deployments } from '@/api/scope-config/types'; +import { ExternalLink } from '@/components'; + +const reducer = (state: ITransform2deployments[], action: { type: string; payload: ITransform2deployments[] }) => { + switch (action.type) { + case 'APPEND': + return [...state, ...action.payload]; + default: + return state; + } +}; + +interface Props { + plugin: string; + connectionId: ID; + transformation: any; +} + +export const CheckMatchedItems = ({ plugin, connectionId, transformation }: Props) => { + const [page, setPage] = useState(1); + const [total, setTotal] = useState(0); + const [loading, setLoading] = useState(false); + + const [state, dispatch] = useReducer(reducer, []); + + const handleLoadItems = async () => { + setLoading(true); + const res = await API.scopeConfig.transform2deployments(plugin, connectionId, { + deploymentPattern: transformation.deploymentPattern, + productionPattern: transformation.productionPattern, + page, + pageSize: 10, + }); + + dispatch({ type: 'APPEND', payload: res.data }); + + setPage(page + 1); + setTotal(res.total); + setLoading(false); + }; + + return ( + <Flex vertical gap="small"> + <div> + <Button ghost type="primary" loading={loading} icon={<SearchOutlined />} onClick={handleLoadItems}> + Check Matched Items + </Button> + </div> + {!!state.length && ( + <Flex vertical gap="small"> + <h3>Matched Items</h3> + <Flex wrap="wrap" gap="small"> + {state.map((it) => ( + <Tag key={it.url} color="blue"> + <ExternalLink link={it.url}>{it.name}</ExternalLink> + </Tag> + ))} + </Flex> + {total > state.length && ( + <div> + <Button type="link" size="small" loading={loading} icon={<PlusOutlined />} onClick={handleLoadItems}> + See More + </Button> + </div> + )} + </Flex> + )} + </Flex> + ); +}; diff --git a/config-ui/src/plugins/components/deployments/index.tsx b/config-ui/src/plugins/components/deployments/index.tsx new file mode 100644 index 000000000..b3b0d6a58 --- /dev/null +++ b/config-ui/src/plugins/components/deployments/index.tsx @@ -0,0 +1,102 @@ +/* + * 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 } from 'react'; +import { Space, Select, Input } from 'antd'; +import { useRequest } from '@mints/hooks'; + +import API from '@/api'; +import { PageLoading } from '@/components'; + +interface Props { + plugin: string; + connectionId: ID; + transformation: any; + setTransformation: React.Dispatch<React.SetStateAction<any>>; +} + +export const Deployments = ({ plugin, connectionId, transformation, setTransformation }: Props) => { + const [type, setType] = useState('regex'); + + const { loading, data } = useRequest(() => API.scopeConfig.deployments(plugin, connectionId), [plugin, connectionId]); + + useEffect(() => { + if (transformation.envNamePattern) { + setType('regex'); + } + }, [transformation]); + + const handleChangeType = (t: string) => { + if (t === 'regex') { + setTransformation({ + ...transformation, + envNameList: [], + }); + } + + if (t === 'select') { + setTransformation({ + ...transformation, + envNamePattern: '', + }); + } + + setType(t); + }; + + const handleChangeRegex = (e: React.ChangeEvent<HTMLInputElement>) => { + const envNamePattern = e.target.value; + setTransformation({ + ...transformation, + envNamePattern, + envNameList: [], + }); + }; + + const handleChangeSelect = (value: string[]) => { + setTransformation({ + ...transformation, + envNamePattern: '', + envNameList: value, + }); + }; + + if (loading || !data) { + return <PageLoading />; + } + + return ( + <Space> + <Select value={type} onChange={handleChangeType}> + <Select.Option value="select">is one of</Select.Option> + <Select.Option value="regex">matches</Select.Option> + </Select> + {type === 'regex' ? ( + <Input placeholder="(?i)prod(.*)" onChange={handleChangeRegex} /> + ) : ( + <Select mode="tags" style={{ width: 180 }} maxTagCount={2} onChange={handleChangeSelect}> + {data.map((d) => ( + <Select.Option key={d} value={d}> + {d} + </Select.Option> + ))} + </Select> + )} + </Space> + ); +}; diff --git a/config-ui/src/plugins/components/index.ts b/config-ui/src/plugins/components/index.ts index 337e446fe..4cbfa01e5 100644 --- a/config-ui/src/plugins/components/index.ts +++ b/config-ui/src/plugins/components/index.ts @@ -16,12 +16,14 @@ * */ +export * from './check-matched-items'; export * from './connection-form'; export * from './connection-list'; export * from './connection-select'; export * from './connection-status'; export * from './data-scope-remote'; export * from './data-scope-select'; +export * from './deployments'; export * from './plugin-name'; export * from './scope-config'; export * from './scope-config-form'; 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 5c27d84d4..06b4e27c6 100644 --- a/config-ui/src/plugins/components/scope-config-form/index.tsx +++ b/config-ui/src/plugins/components/scope-config-form/index.tsx @@ -243,6 +243,8 @@ export const ScopeConfigForm = ({ {plugin === 'github' && ( <GitHubTransformation + plugin={plugin} + connectionId={connectionId} entities={entities} transformation={transformation} setTransformation={setTransformation} diff --git a/config-ui/src/plugins/register/github/transformation.tsx b/config-ui/src/plugins/register/github/transformation.tsx index 0d6473c4d..9114e72eb 100644 --- a/config-ui/src/plugins/register/github/transformation.tsx +++ b/config-ui/src/plugins/register/github/transformation.tsx @@ -23,15 +23,25 @@ import { theme, Form, Collapse, Input, Tag, Checkbox } from 'antd'; import { HelpTooltip, ExternalLink } from '@/components'; import { DOC_URL } from '@/release'; +import { CheckMatchedItems, Deployments } from '@/plugins'; interface Props { + plugin: string; + connectionId: ID; entities: string[]; transformation: any; setTransformation: React.Dispatch<React.SetStateAction<any>>; setHasError: React.Dispatch<React.SetStateAction<boolean>>; } -export const GitHubTransformation = ({ entities, transformation, setTransformation, setHasError }: Props) => { +export const GitHubTransformation = ({ + plugin, + connectionId, + entities, + transformation, + setTransformation, + setHasError, +}: Props) => { const [useCustom, setUseCustom] = useState(false); useEffect(() => { @@ -77,6 +87,8 @@ export const GitHubTransformation = ({ entities, transformation, setTransformati style={{ background: token.colorBgContainer }} size="large" items={renderCollapseItems({ + plugin, + connectionId, entities, panelStyle, transformation, @@ -89,6 +101,8 @@ export const GitHubTransformation = ({ entities, transformation, setTransformati }; const renderCollapseItems = ({ + plugin, + connectionId, entities, panelStyle, transformation, @@ -96,6 +110,8 @@ const renderCollapseItems = ({ useCustom, onChangeUseCustom, }: { + plugin: string; + connectionId: ID; entities: string[]; panelStyle: React.CSSProperties; transformation: any; @@ -245,16 +261,11 @@ const renderCollapseItems = ({ </Checkbox> <div style={{ margin: '8px 0', paddingLeft: 28 }}> <span>If its environment name matches</span> - <Input - style={{ width: 180, margin: '0 8px' }} - placeholder="(?i)prod(.*)" - value={transformation.envNamePattern} - onChange={(e) => - onChangeTransformation({ - ...transformation, - envNamePattern: e.target.value, - }) - } + <Deployments + plugin={plugin} + connectionId={connectionId} + transformation={transformation} + setTransformation={onChangeTransformation} /> <span>, this deployment is a ‘Production Deployment’</span> </div> @@ -296,6 +307,7 @@ const renderCollapseItems = ({ <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> + <CheckMatchedItems plugin={plugin} connectionId={connectionId} transformation={transformation} /> </> ), },