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 b6bd5da93 fix(config-ui): some bugs (#4084)
b6bd5da93 is described below
commit b6bd5da93572f164e2e96546f921a41bb599edee
Author: 青湛 <[email protected]>
AuthorDate: Tue Jan 3 21:10:36 2023 +0800
fix(config-ui): some bugs (#4084)
* fix(config-ui): adjust the column count for gitlab and jenkins
* fix(config-ui): the multi-selector scroll to top when the selectedItems
changed
* fix(config-ui): the selector content not fill
* fix(config-ui): the connection default value not work
* fix(config-ui): updated tasks will refresh page
* fix(config-ui): unable to modify project name continuously
* fix(config-ui): bp detail not show all entities on change scope
* fix(config-ui): advacned mode bp cannot show
* fix(config-ui): pipeline rerun path error
* feat(config-ui): add github token real-time verification
* fix(config-ui): show jenkins scope tips condition error
* fix(config-ui): pipeline historical cannot auto refresh
---
.../components/selector/multi-selector/index.tsx | 7 +-
.../src/components/selector/selector/index.tsx | 10 +-
.../src/{pages/pipeline/detail => hooks}/index.ts | 2 +-
config-ui/src/hooks/use-auto-refresh.ts | 67 ++++++++++
config-ui/src/layouts/base/styled.ts | 1 -
.../blueprint/detail/blueprint-detail-page.tsx | 16 +--
.../pages/blueprint/detail/blueprint-detail.tsx | 63 ++++++----
.../src/pages/blueprint/detail/components/index.ts | 1 -
.../components/update-scope-dialog/index.tsx | 5 +-
.../pages/blueprint/detail/panel/configuration.tsx | 7 +-
.../src/pages/blueprint/detail/panel/status.tsx | 11 +-
config-ui/src/pages/blueprint/detail/styled.ts | 8 +-
config-ui/src/pages/blueprint/detail/types.ts | 1 +
config-ui/src/pages/blueprint/detail/use-detail.ts | 7 +-
.../form/components/github-token/index.tsx | 136 +++++++++++++++++++++
.../form/{ => components/github-token}/styled.ts | 66 +++-------
.../detail => connection/form/components}/index.ts | 2 +-
config-ui/src/pages/connection/form/index.tsx | 86 ++-----------
config-ui/src/pages/connection/form/styled.ts | 19 ---
.../components/pipeline-list => pipeline}/api.ts | 2 +
.../components/historical}/index.tsx | 79 ++++++------
.../components/historical/styled.ts} | 29 ++++-
.../pages/pipeline/{detail => components}/index.ts | 2 +-
config-ui/src/pages/pipeline/detail/api.ts | 4 +-
config-ui/src/pages/pipeline/detail/index.ts | 2 +-
.../src/pages/pipeline/detail/pipeline-detail.tsx | 48 ++++++--
.../types.ts => pipeline/detail/pipeline-info.tsx} | 23 ++--
config-ui/src/pages/pipeline/detail/use-detail.ts | 62 ++--------
config-ui/src/pages/pipeline/index.ts | 1 +
config-ui/src/pages/project/detail/use-project.ts | 2 +-
.../plugins/common/data-scope/use-data-scope.ts | 13 +-
.../gitlab/components/miller-columns/index.tsx | 2 +-
.../jenkins/components/miller-columns/index.tsx | 2 +-
33 files changed, 449 insertions(+), 337 deletions(-)
diff --git a/config-ui/src/components/selector/multi-selector/index.tsx
b/config-ui/src/components/selector/multi-selector/index.tsx
index 48fcda0c7..65a9f22d9 100644
--- a/config-ui/src/components/selector/multi-selector/index.tsx
+++ b/config-ui/src/components/selector/multi-selector/index.tsx
@@ -18,7 +18,7 @@
import React, { useState, useEffect } from 'react';
import { MenuItem, Checkbox, Intent } from '@blueprintjs/core';
-import { MultiSelect } from '@blueprintjs/select';
+import { MultiSelect2 } from '@blueprintjs/select';
interface Props<T> {
placeholder?: string;
@@ -98,11 +98,14 @@ export const MultiSelector = <T,>({
};
return (
- <MultiSelect
+ <MultiSelect2
fill
resetOnSelect
placeholder={placeholder ?? 'Select...'}
items={items}
+ // https://github.com/palantir/blueprint/issues/3596
+ // set activeItem to null will fixed the scrollBar to top when the
selectedItems changed
+ activeItem={null}
selectedItems={selectedItems}
itemRenderer={itemRenderer}
tagRenderer={tagRenderer}
diff --git a/config-ui/src/components/selector/selector/index.tsx
b/config-ui/src/components/selector/selector/index.tsx
index 2d284ee9c..0f334179d 100644
--- a/config-ui/src/components/selector/selector/index.tsx
+++ b/config-ui/src/components/selector/selector/index.tsx
@@ -17,8 +17,8 @@
*/
import React, { useState, useEffect, useMemo } from 'react';
-import { MenuItem, Button } from '@blueprintjs/core';
-import { Select } from '@blueprintjs/select';
+import { MenuItem, Button, Alignment } from '@blueprintjs/core';
+import { Select2 } from '@blueprintjs/select';
interface Props<T> {
items: T[];
@@ -67,14 +67,14 @@ export const Selector = <T,>({
};
return (
- <Select
+ <Select2
items={items}
activeItem={selectedItem}
itemPredicate={itemPredicate}
itemRenderer={itemRenderer}
onItemSelect={handleItemSelect}
>
- <Button outlined small fill rightIcon="double-caret-vertical"
text={btnText} />
- </Select>
+ <Button outlined small fill alignText={Alignment.LEFT}
rightIcon="double-caret-vertical" text={btnText} />
+ </Select2>
);
};
diff --git a/config-ui/src/pages/pipeline/detail/index.ts
b/config-ui/src/hooks/index.ts
similarity index 95%
copy from config-ui/src/pages/pipeline/detail/index.ts
copy to config-ui/src/hooks/index.ts
index 07d867746..bd3a94b28 100644
--- a/config-ui/src/pages/pipeline/detail/index.ts
+++ b/config-ui/src/hooks/index.ts
@@ -16,4 +16,4 @@
*
*/
-export * from './pipeline-detail';
+export * from './use-auto-refresh';
diff --git a/config-ui/src/hooks/use-auto-refresh.ts
b/config-ui/src/hooks/use-auto-refresh.ts
new file mode 100644
index 000000000..33059964c
--- /dev/null
+++ b/config-ui/src/hooks/use-auto-refresh.ts
@@ -0,0 +1,67 @@
+/*
+ * 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, useRef } from 'react';
+
+export const useAutoRefresh = <T>(
+ request: () => Promise<T>,
+ deps: React.DependencyList = [],
+ option?: {
+ cancel?: (data?: T) => boolean;
+ interval?: number;
+ },
+) => {
+ const [loading, setLoading] = useState(false);
+ const [data, setData] = useState<T>();
+
+ const timer = useRef<any>();
+
+ useEffect(() => {
+ setLoading(true);
+ request()
+ .then((data: T) => {
+ setData(data);
+ })
+ .finally(() => {
+ setLoading(false);
+ });
+ }, [...deps]);
+
+ useEffect(() => {
+ timer.current = setInterval(() => {
+ request().then((data: T) => {
+ setData(data);
+ });
+ }, option?.interval ?? 5000);
+ return () => clearInterval(timer.current);
+ }, [...deps]);
+
+ useEffect(() => {
+ if (option?.cancel?.(data)) {
+ clearInterval(timer.current);
+ }
+ }, [data]);
+
+ return useMemo(
+ () => ({
+ loading,
+ data,
+ }),
+ [loading, data],
+ );
+};
diff --git a/config-ui/src/layouts/base/styled.ts
b/config-ui/src/layouts/base/styled.ts
index 8ef7405d4..6fc945334 100644
--- a/config-ui/src/layouts/base/styled.ts
+++ b/config-ui/src/layouts/base/styled.ts
@@ -77,7 +77,6 @@ export const Sider = styled.div`
`;
export const Inner = styled.div`
- position: relative;
display: flex;
flex-direction: column;
flex: auto;
diff --git a/config-ui/src/pages/blueprint/detail/blueprint-detail-page.tsx
b/config-ui/src/pages/blueprint/detail/blueprint-detail-page.tsx
index 48a472a1e..bfbde9404 100644
--- a/config-ui/src/pages/blueprint/detail/blueprint-detail-page.tsx
+++ b/config-ui/src/pages/blueprint/detail/blueprint-detail-page.tsx
@@ -16,28 +16,19 @@
*
*/
-import React, { useMemo } from 'react';
+import React from 'react';
import { useParams } from 'react-router-dom';
import { PageHeader, PageLoading } from '@/components';
-import { Plugins } from '@/plugins';
import { useDetail } from './use-detail';
import { BlueprintDetail } from './blueprint-detail';
-import * as S from './styled';
-
export const BlueprintDetailPage = () => {
const { id } = useParams<{ id: string }>();
const { loading, blueprint } = useDetail({ id });
- const showJenkinsTips = useMemo(() => {
- const jenkins = blueprint && blueprint.settings.connections.find((cs) =>
cs.plugin === Plugins.Jenkins);
-
- return !jenkins?.scopes.length;
- }, [blueprint]);
-
if (loading || !blueprint) {
return <PageLoading />;
}
@@ -50,11 +41,6 @@ export const BlueprintDetailPage = () => {
]}
>
<BlueprintDetail id={blueprint.id} />
- {showJenkinsTips && (
- <S.JenkinsTips>
- <p>Please add the "Jenkins jobs" to collect before this Blueprint
can run again.</p>
- </S.JenkinsTips>
- )}
</PageHeader>
);
};
diff --git a/config-ui/src/pages/blueprint/detail/blueprint-detail.tsx
b/config-ui/src/pages/blueprint/detail/blueprint-detail.tsx
index cc558e0db..6f0edd139 100644
--- a/config-ui/src/pages/blueprint/detail/blueprint-detail.tsx
+++ b/config-ui/src/pages/blueprint/detail/blueprint-detail.tsx
@@ -16,52 +16,67 @@
*
*/
-import React, { useState } from 'react';
+import React, { useState, useMemo } from 'react';
import type { TabId } from '@blueprintjs/core';
import { Tabs, Tab } from '@blueprintjs/core';
import { PageLoading } from '@/components';
+import { Plugins } from '@/plugins';
import type { UseDetailProps } from './use-detail';
import { useDetail } from './use-detail';
import { Configuration } from './panel/configuration';
import { Status } from './panel/status';
+import * as S from './styled';
interface Props extends UseDetailProps {}
export const BlueprintDetail = ({ id }: Props) => {
const [activeTab, setActiveTab] = useState<TabId>('status');
- const { loading, blueprint, pipelines, pipelineId, operating, onRun,
onUpdate, onDelete, onRefresh } = useDetail({
+ const { loading, blueprint, pipelineId, operating, onRun, onUpdate,
onDelete, onRefresh } = useDetail({
id,
});
+ const showJenkinsTips = useMemo(() => {
+ const jenkins = blueprint && blueprint.settings?.connections.find((cs) =>
cs.plugin === Plugins.Jenkins);
+ return jenkins && !jenkins.scopes.length;
+ }, [blueprint]);
+
if (loading || !blueprint) {
return <PageLoading />;
}
return (
- <Tabs selectedTabId={activeTab} onChange={(at) => setActiveTab(at)}>
- <Tab
- id="status"
- title="Status"
- panel={
- <Status
- blueprint={blueprint}
- pipelines={pipelines}
- pipelineId={pipelineId}
- operating={operating}
- onRun={onRun}
- onUpdate={onUpdate}
- onDelete={onDelete}
- />
- }
- />
- <Tab
- id="configuration"
- title="Configuration"
- panel={<Configuration blueprint={blueprint} operating={operating}
onUpdate={onUpdate} onRefresh={onRefresh} />}
- />
- </Tabs>
+ <S.Wrapper>
+ <Tabs selectedTabId={activeTab} onChange={(at) => setActiveTab(at)}>
+ <Tab
+ id="status"
+ title="Status"
+ panel={
+ <Status
+ blueprint={blueprint}
+ pipelineId={pipelineId}
+ operating={operating}
+ onRun={onRun}
+ onUpdate={onUpdate}
+ onDelete={onDelete}
+ />
+ }
+ />
+ <Tab
+ id="configuration"
+ title="Configuration"
+ panel={
+ <Configuration blueprint={blueprint} operating={operating}
onUpdate={onUpdate} onRefresh={onRefresh} />
+ }
+ />
+ </Tabs>
+ {showJenkinsTips && (
+ <S.JenkinsTips>
+ <p>Please add the "Jenkins jobs" to collect before this Blueprint
can run again.</p>
+ </S.JenkinsTips>
+ )}
+ </S.Wrapper>
);
};
diff --git a/config-ui/src/pages/blueprint/detail/components/index.ts
b/config-ui/src/pages/blueprint/detail/components/index.ts
index a68cbba59..a78ec47ea 100644
--- a/config-ui/src/pages/blueprint/detail/components/index.ts
+++ b/config-ui/src/pages/blueprint/detail/components/index.ts
@@ -20,4 +20,3 @@ export * from './update-name-dialog';
export * from './update-policy-dialog';
export * from './update-scope-dialog';
export * from './update-transformation-dialog';
-export * from './pipeline-list';
diff --git
a/config-ui/src/pages/blueprint/detail/components/update-scope-dialog/index.tsx
b/config-ui/src/pages/blueprint/detail/components/update-scope-dialog/index.tsx
index 61e998a8e..1825e3ffc 100644
---
a/config-ui/src/pages/blueprint/detail/components/update-scope-dialog/index.tsx
+++
b/config-ui/src/pages/blueprint/detail/components/update-scope-dialog/index.tsx
@@ -32,7 +32,7 @@ interface Props {
export const UpdateScopeDialog = ({ connection, onCancel, onSubmit }: Props)
=> {
if (!connection) return null;
- const { plugin, connectionId, entities } = connection;
+ const { plugin, connectionId, entities, selectedEntites } = connection;
const handleSaveScope = (sc: any) => {
onSubmit({
@@ -51,6 +51,9 @@ export const UpdateScopeDialog = ({ connection, onCancel,
onSubmit }: Props) =>
plugin={plugin}
connectionId={connectionId}
entities={entities}
+ initialValues={{
+ entites: selectedEntites,
+ }}
onCancel={onCancel}
onSave={handleSaveScope}
/>
diff --git a/config-ui/src/pages/blueprint/detail/panel/configuration.tsx
b/config-ui/src/pages/blueprint/detail/panel/configuration.tsx
index 591f83500..73baede66 100644
--- a/config-ui/src/pages/blueprint/detail/panel/configuration.tsx
+++ b/config-ui/src/pages/blueprint/detail/panel/configuration.tsx
@@ -63,7 +63,8 @@ export const Configuration = ({ blueprint, operating,
onUpdate, onRefresh }: Pro
icon: plugin.icon,
name: plugin.name,
connectionId: cs.connectionId,
- entities: cs.scopes[0].entities,
+ entities: plugin.entities,
+ selectedEntites: cs.scopes[0].entities,
plugin: cs.plugin,
scopeIds: cs.scopes.map((sc: any) => sc.id),
};
@@ -117,8 +118,8 @@ export const Configuration = ({ blueprint, operating,
onUpdate, onRefresh }: Pro
},
{
title: 'Data Entities',
- dataIndex: 'entities',
- key: 'entities',
+ dataIndex: 'selectedEntites',
+ key: 'selectedEntites',
render: (val: string[]) => (
<>
{val.map((it) => (
diff --git a/config-ui/src/pages/blueprint/detail/panel/status.tsx
b/config-ui/src/pages/blueprint/detail/panel/status.tsx
index 2047cdb0e..f7401e1cc 100644
--- a/config-ui/src/pages/blueprint/detail/panel/status.tsx
+++ b/config-ui/src/pages/blueprint/detail/panel/status.tsx
@@ -21,17 +21,14 @@ import { Button, Switch, Intent } from '@blueprintjs/core';
import dayjs from 'dayjs';
import { getCron } from '@/config';
-import type { PipelineType } from '@/pages';
-import { PipelineDetail } from '@/pages';
+import { PipelineInfo, PipelineHistorical } from '@/pages';
import type { BlueprintType } from '../../types';
-import { PipelineList } from '../components';
import * as S from '../styled';
interface Props {
blueprint: BlueprintType;
- pipelines: PipelineType[];
pipelineId?: ID;
operating: boolean;
onRun: () => void;
@@ -39,7 +36,7 @@ interface Props {
onDelete: () => void;
}
-export const Status = ({ blueprint, pipelines, pipelineId, operating, onRun,
onUpdate, onDelete }: Props) => {
+export const Status = ({ blueprint, pipelineId, operating, onRun, onUpdate,
onDelete }: Props) => {
const cron = useMemo(() => getCron(blueprint.isManual,
blueprint.cronConfig), [blueprint]);
const handleRunNow = () => onRun();
@@ -84,11 +81,11 @@ export const Status = ({ blueprint, pipelines, pipelineId,
operating, onRun, onU
</div>
<div className="block">
<h3>Current Pipeline</h3>
- <PipelineDetail id={pipelineId} />
+ <PipelineInfo id={pipelineId} />
</div>
<div className="block">
<h3>Historical Pipelines</h3>
- <PipelineList pipelines={pipelines} />
+ <PipelineHistorical blueprintId={blueprint.id} />
</div>
</S.StatusPanel>
);
diff --git a/config-ui/src/pages/blueprint/detail/styled.ts
b/config-ui/src/pages/blueprint/detail/styled.ts
index 9b480e23d..0a772d8a1 100644
--- a/config-ui/src/pages/blueprint/detail/styled.ts
+++ b/config-ui/src/pages/blueprint/detail/styled.ts
@@ -18,6 +18,10 @@
import styled from 'styled-components';
+export const Wrapper = styled.div`
+ padding-bottom: 24px;
+`;
+
export const ConfigurationPanel = styled.div`
.top {
display: flex;
@@ -98,10 +102,10 @@ export const StatusPanel = styled.div`
`;
export const JenkinsTips = styled.div`
- position: absolute;
+ position: fixed;
right: 0;
bottom: 0;
- left: 0;
+ left: 200px;
background-color: #3c5088;
display: flex;
align-items: center;
diff --git a/config-ui/src/pages/blueprint/detail/types.ts
b/config-ui/src/pages/blueprint/detail/types.ts
index 174e43525..872ebb001 100644
--- a/config-ui/src/pages/blueprint/detail/types.ts
+++ b/config-ui/src/pages/blueprint/detail/types.ts
@@ -24,5 +24,6 @@ export type ConfigConnectionItemType = {
connectionId: ID;
plugin: Plugins;
entities: string[];
+ selectedEntites: string[];
scopeIds: ID[];
};
diff --git a/config-ui/src/pages/blueprint/detail/use-detail.ts
b/config-ui/src/pages/blueprint/detail/use-detail.ts
index f4803ce30..15a4e9f04 100644
--- a/config-ui/src/pages/blueprint/detail/use-detail.ts
+++ b/config-ui/src/pages/blueprint/detail/use-detail.ts
@@ -21,7 +21,7 @@ import { useState, useEffect, useMemo } from 'react';
import { Error } from '@/error';
import { operator } from '@/utils';
-import type { BlueprintType, PipelineType } from '@/pages';
+import type { BlueprintType } from '@/pages';
import * as API from './api';
export interface UseDetailProps {
@@ -32,7 +32,6 @@ export const useDetail = ({ id }: UseDetailProps) => {
const [loading, setLoading] = useState(false);
const [operating, setOperating] = useState(false);
const [blueprint, setBlueprint] = useState<BlueprintType>();
- const [pipelines, setPipelines] = useState<PipelineType[]>([]);
const [pipelineId, setPipelineId] = useState<ID>();
const [, setError] = useState();
@@ -49,7 +48,6 @@ export const useDetail = ({ id }: UseDetailProps) => {
}
setBlueprint(bpRes);
- setPipelines(plRes.pipelines);
setPipelineId(plRes.pipelines?.[0]?.id);
} finally {
setLoading(false);
@@ -102,13 +100,12 @@ export const useDetail = ({ id }: UseDetailProps) => {
loading,
operating,
blueprint,
- pipelines,
pipelineId,
onRun: handleRun,
onUpdate: handleUpdate,
onDelete: handleDelete,
onRefresh: getBlueprint,
}),
- [loading, operating, blueprint, pipelines, pipelineId],
+ [loading, operating, blueprint, pipelineId],
);
};
diff --git
a/config-ui/src/pages/connection/form/components/github-token/index.tsx
b/config-ui/src/pages/connection/form/components/github-token/index.tsx
new file mode 100644
index 000000000..82b5d7193
--- /dev/null
+++ b/config-ui/src/pages/connection/form/components/github-token/index.tsx
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import React, { useEffect, useState } from 'react';
+import { InputGroup, Button, Intent } from '@blueprintjs/core';
+import { pick } from 'lodash';
+
+import { Plugins } from '@/plugins';
+
+import * as API from '../../api';
+
+import * as S from './styled';
+
+type TokenItem = {
+ value: string;
+ status: 'idle' | 'valid' | 'invalid';
+ from?: string;
+};
+
+interface Props {
+ form: any;
+ value?: string;
+ onChange?: (value: string) => void;
+}
+
+export const GitHubToken = ({ form, value, onChange }: Props) => {
+ const [tokens, setTokens] = useState<TokenItem[]>([]);
+
+ const testToken = async (token: string): Promise<TokenItem> => {
+ try {
+ const res = await API.testConnection(Plugins.GitHub, {
+ ...pick(form, ['endpoint', 'proxy']),
+ token,
+ });
+ return {
+ value: token,
+ status: 'valid',
+ from: res.login,
+ };
+ } catch {
+ return {
+ value: token,
+ status: 'invalid',
+ };
+ }
+ };
+
+ const checkTokens = async (value: string) => {
+ const res = await Promise.all((value ?? '').split(',').map((it) =>
testToken(it)));
+ setTokens(res);
+ };
+
+ useEffect(() => {
+ if (value) {
+ checkTokens(value);
+ }
+ }, []);
+
+ useEffect(() => {
+ onChange?.(tokens.map((it) => it.value).join(','));
+ }, [tokens]);
+
+ const handleCreateToken = () => {
+ setTokens([...tokens, { value: '', status: 'idle' }]);
+ };
+
+ const handleRemoveToken = (key: number) => {
+ setTokens(tokens.filter((_, i) => (i === key ? false : true)));
+ };
+
+ const handleChangeToken = (key: number, value: string) => {
+ setTokens(tokens.map((it, i) => (i === key ? { value, status: 'idle' } :
it)));
+ };
+
+ const handleTestToken = async (key: number) => {
+ const token = tokens.find((_, i) => i === key) as TokenItem;
+
+ if (token.status === 'idle' && token.value) {
+ const res = await testToken(token.value);
+ setTokens((tokens) => tokens.map((it, i) => (i === key ? res : it)));
+ }
+ };
+
+ return (
+ <S.Wrapper>
+ <p>
+ Add one or more personal token(s) for authentication from you and your
organization members. Multiple tokens can
+ help speed up the data collection process.{' '}
+ </p>
+ <p>
+ <a
+
href="https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token"
+ target="_blank"
+ rel="noreferrer"
+ >
+ Learn about how to create a personal access token
+ </a>
+ </p>
+ <h3>Personal Access Token(s)</h3>
+ {tokens.map(({ value, status, from }, i) => (
+ <div className="token" key={i}>
+ <div className="input">
+ <InputGroup
+ placeholder="token"
+ type="password"
+ value={value ?? ''}
+ onChange={(e) => handleChangeToken(i, e.target.value)}
+ onBlur={() => handleTestToken(i)}
+ />
+ {status === 'invalid' && <span className="error">Invalid</span>}
+ {status === 'valid' && <span className="success">Valid From:
{from}</span>}
+ </div>
+ <Button minimal icon="cross" onClick={() => handleRemoveToken(i)} />
+ </div>
+ ))}
+ <div className="action">
+ <Button outlined small intent={Intent.PRIMARY} text="Another Token"
icon="plus" onClick={handleCreateToken} />
+ </div>
+ </S.Wrapper>
+ );
+};
diff --git a/config-ui/src/pages/connection/form/styled.ts
b/config-ui/src/pages/connection/form/components/github-token/styled.ts
similarity index 61%
copy from config-ui/src/pages/connection/form/styled.ts
copy to config-ui/src/pages/connection/form/components/github-token/styled.ts
index ba6584fe6..ffb01932d 100644
--- a/config-ui/src/pages/connection/form/styled.ts
+++ b/config-ui/src/pages/connection/form/components/github-token/styled.ts
@@ -20,55 +20,6 @@ import { Colors } from '@blueprintjs/core';
import styled from 'styled-components';
export const Wrapper = styled.div`
- .bp4-form-group {
- display: flex;
- align-items: center;
- justify-content: space-between;
-
- .bp4-label {
- flex: 0 0 200px;
- font-weight: 600;
-
- .bp4-popover2-target {
- display: inline;
- margin: 0;
- line-height: 1;
- margin-left: 4px;
- }
-
- .bp4-text-muted {
- color: ${Colors.RED3};
- }
- }
-
- .bp4-form-content {
- flex: auto;
- }
- }
-
- .footer {
- display: flex;
- align-items: center;
- justify-content: space-between;
- margin-top: 32px;
- }
-`;
-
-export const Label = styled.span`
- display: inline-flex;
- align-items: center;
-`;
-
-export const RateLimit = styled.div`
- display: flex;
- align-items: center;
-
- & > .bp4-numeric-input {
- margin-right: 8px;
- }
-`;
-
-export const GitHubToken = styled.div`
p {
margin: 0 0 8px;
}
@@ -84,5 +35,22 @@ export const GitHubToken = styled.div`
align-items: center;
justify-content: space-between;
margin-bottom: 8px;
+
+ .input {
+ display: flex;
+ align-items: center;
+
+ & > span {
+ margin-left: 4px;
+
+ &.error {
+ color: ${Colors.RED3};
+ }
+
+ &.success {
+ color: ${Colors.GREEN3};
+ }
+ }
+ }
}
`;
diff --git a/config-ui/src/pages/pipeline/detail/index.ts
b/config-ui/src/pages/connection/form/components/index.ts
similarity index 95%
copy from config-ui/src/pages/pipeline/detail/index.ts
copy to config-ui/src/pages/connection/form/components/index.ts
index 07d867746..d54071fb7 100644
--- a/config-ui/src/pages/pipeline/detail/index.ts
+++ b/config-ui/src/pages/connection/form/components/index.ts
@@ -16,4 +16,4 @@
*
*/
-export * from './pipeline-detail';
+export * from './github-token';
diff --git a/config-ui/src/pages/connection/form/index.tsx
b/config-ui/src/pages/connection/form/index.tsx
index 66c243c2a..0aa28c50f 100644
--- a/config-ui/src/pages/connection/form/index.tsx
+++ b/config-ui/src/pages/connection/form/index.tsx
@@ -18,7 +18,7 @@
import React, { useState, useEffect, useMemo } from 'react';
import { useParams, useHistory } from 'react-router-dom';
-import { omit, pick } from 'lodash';
+import { pick } from 'lodash';
import {
FormGroup,
InputGroup,
@@ -36,13 +36,13 @@ import { PageHeader, Card, PageLoading } from
'@/components';
import type { PluginConfigConnectionType } from '@/plugins';
import { Plugins, PluginConfig } from '@/plugins';
+import { GitHubToken } from './components';
import { useForm } from './use-form';
import * as S from './styled';
export const ConnectionFormPage = () => {
const [form, setForm] = useState<Record<string, any>>({});
const [showRateLimit, setShowRateLimit] = useState(false);
- const [githubTokens, setGitHubTokens] = useState<Record<string, string>>({});
const history = useHistory();
const { plugin, cid } = useParams<{ plugin: Plugins; cid?: string }>();
@@ -60,49 +60,14 @@ export const ConnectionFormPage = () => {
...(connection ?? {}),
});
- setGitHubTokens(
- (connection?.token ?? '').split(',').reduce((acc: any, cur: string,
index: number) => {
- acc[index] = cur;
- return acc;
- }, {} as any),
- );
-
setShowRateLimit(connection?.rateLimitPerHour ? true : false);
}, [initialValues, connection]);
- useEffect(() => {
- if (plugin === Plugins.GitHub) {
- setForm({
- ...form,
- token: Object.values(githubTokens).filter(Boolean).join(','),
- });
- }
- }, [githubTokens]);
-
const error = useMemo(
() => !!(fields.filter((field) => field.required) ?? []).find((field) =>
!form[field.key]),
[form, fields],
);
- const handleChangeGitHubToken = (key: string, token: string) => {
- setGitHubTokens({
- ...githubTokens,
- [key]: token,
- });
- };
-
- const handleCreateToken = () => {
- const keys = Object.keys(githubTokens);
- setGitHubTokens({
- ...githubTokens,
- [+keys[keys.length - 1] + 1]: '',
- });
- };
-
- const handleRemoveToken = (key: string) => {
- setGitHubTokens(omit(githubTokens, [key]));
- };
-
const handleTest = () =>
onTest(pick(form, ['endpoint', 'token', 'username', 'password', 'app_id',
'secret_key', 'proxy']));
@@ -182,43 +147,16 @@ export const ConnectionFormPage = () => {
/>
)}
{type === 'github-token' && (
- <S.GitHubToken>
- <p>
- Add one or more personal token(s) for authentication from you
and your organization members. Multiple
- tokens can help speed up the data collection process.{' '}
- </p>
- <p>
- <a
-
href="https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token"
- target="_blank"
- rel="noreferrer"
- >
- Learn about how to create a personal access token
- </a>
- </p>
- <h3>Personal Access Token(s)</h3>
- {Object.entries(githubTokens).map(([key, value]) => (
- <div className="token" key={key}>
- <InputGroup
- placeholder="token"
- type="password"
- value={value}
- onChange={(e) => handleChangeGitHubToken(key,
e.target.value)}
- />
- <Button minimal icon="cross" onClick={() =>
handleRemoveToken(key)} />
- </div>
- ))}
- <div className="action">
- <Button
- outlined
- small
- intent={Intent.PRIMARY}
- text="Another Token"
- icon="plus"
- onClick={handleCreateToken}
- />
- </div>
- </S.GitHubToken>
+ <GitHubToken
+ form={form}
+ value={form.token}
+ onChange={(value) =>
+ setForm({
+ ...form,
+ token: value,
+ })
+ }
+ />
)}
</FormGroup>
);
diff --git a/config-ui/src/pages/connection/form/styled.ts
b/config-ui/src/pages/connection/form/styled.ts
index ba6584fe6..564bc0961 100644
--- a/config-ui/src/pages/connection/form/styled.ts
+++ b/config-ui/src/pages/connection/form/styled.ts
@@ -67,22 +67,3 @@ export const RateLimit = styled.div`
margin-right: 8px;
}
`;
-
-export const GitHubToken = styled.div`
- p {
- margin: 0 0 8px;
- }
-
- h3 {
- margin: 0 0 8px;
- padding: 0;
- font-size: 14px;
- }
-
- .token {
- display: flex;
- align-items: center;
- justify-content: space-between;
- margin-bottom: 8px;
- }
-`;
diff --git
a/config-ui/src/pages/blueprint/detail/components/pipeline-list/api.ts
b/config-ui/src/pages/pipeline/api.ts
similarity index 91%
copy from config-ui/src/pages/blueprint/detail/components/pipeline-list/api.ts
copy to config-ui/src/pages/pipeline/api.ts
index 6d038c6a8..fc0fdaa03 100644
--- a/config-ui/src/pages/blueprint/detail/components/pipeline-list/api.ts
+++ b/config-ui/src/pages/pipeline/api.ts
@@ -18,4 +18,6 @@
import { request } from '@/utils';
+export const getPipelineHistorical = (id: ID) =>
request(`/blueprints/${id}/pipelines`);
+
export const getPipelineLog = (id: ID) =>
request(`/pipelines/${id}/logging.tar.gz`);
diff --git
a/config-ui/src/pages/blueprint/detail/components/pipeline-list/index.tsx
b/config-ui/src/pages/pipeline/components/historical/index.tsx
similarity index 74%
rename from
config-ui/src/pages/blueprint/detail/components/pipeline-list/index.tsx
rename to config-ui/src/pages/pipeline/components/historical/index.tsx
index 15637060f..b5df1e76e 100644
--- a/config-ui/src/pages/blueprint/detail/components/pipeline-list/index.tsx
+++ b/config-ui/src/pages/pipeline/components/historical/index.tsx
@@ -17,53 +17,46 @@
*/
import React, { useState, useMemo } from 'react';
-import { ButtonGroup, Button, Icon, Intent, Colors, Position, IconName } from
'@blueprintjs/core';
+import { Icon, ButtonGroup, Button, Position, Intent, IconName } from
'@blueprintjs/core';
import { Tooltip2 } from '@blueprintjs/popover2';
import { pick } from 'lodash';
import { saveAs } from 'file-saver';
-import styled from 'styled-components';
import { DEVLAKE_ENDPOINT } from '@/config';
-import { Card, Table, ColumnType, Loading, Inspector } from '@/components';
-import { PipelineType, StatusEnum, STATUS_ICON, STATUS_LABEL, STATUS_CLS }
from '@/pages';
+import { Card, Loading, Table, ColumnType, Inspector } from '@/components';
+import { useAutoRefresh } from '@/hooks';
import { formatTime, duration } from '@/utils';
-import * as API from './api';
+import type { PipelineType } from '../../types';
+import { StatusEnum } from '../../types';
+import { STATUS_ICON, STATUS_LABEL, STATUS_CLS } from '../../misc';
+import * as API from '../../api';
-const StatusColumn = styled.div`
- display: flex;
- align-items: center;
-
- .bp4-icon {
- margin-right: 4px;
- }
-
- &.ready,
- &.cancel {
- color: #94959f;
- }
-
- &.loading {
- color: #7497f7;
- }
-
- &.success {
- color: ${Colors.GREEN3};
- }
-
- &.error {
- color: ${Colors.RED3};
- }
-`;
+import * as S from './styled';
interface Props {
- pipelines: PipelineType[];
+ blueprintId: ID;
}
-export const PipelineList = ({ pipelines }: Props) => {
+export const PipelineHistorical = ({ blueprintId }: Props) => {
const [isOpen, setIsOpen] = useState(false);
const [json, setJson] = useState<any>({});
+ const { loading, data } = useAutoRefresh<PipelineType[]>(
+ async () => {
+ const res = await API.getPipelineHistorical(blueprintId);
+ return res.pipelines;
+ },
+ [],
+ {
+ cancel: (data) =>
+ !!(
+ data &&
+ data.every((it) => [StatusEnum.COMPLETED, StatusEnum.CANCELLED,
StatusEnum.FAILED].includes(it.status))
+ ),
+ },
+ );
+
const handleDownloadLog = async (id: ID) => {
const res = await API.getPipelineLog(id);
if (res) {
@@ -79,14 +72,14 @@ export const PipelineList = ({ pipelines }: Props) => {
dataIndex: 'status',
key: 'status',
render: (val: StatusEnum) => (
- <StatusColumn className={STATUS_CLS(val)}>
+ <S.StatusColumn className={STATUS_CLS(val)}>
{STATUS_ICON[val] === 'loading' ? (
<Loading style={{ marginRight: 4 }} size={14} />
) : (
<Icon style={{ marginRight: 4 }} icon={STATUS_ICON[val] as
IconName} />
)}
<span>{STATUS_LABEL[val]}</span>
- </StatusColumn>
+ </S.StatusColumn>
),
},
{
@@ -135,11 +128,21 @@ export const PipelineList = ({ pipelines }: Props) => {
[],
);
- return !pipelines.length ? (
- <Card>There are no historical runs associated with this blueprint.</Card>
- ) : (
+ if (loading) {
+ return (
+ <Card>
+ <Loading />
+ </Card>
+ );
+ }
+
+ if (!data) {
+ return <Card>There are no historical runs associated with this
blueprint.</Card>;
+ }
+
+ return (
<div>
- <Table columns={columns} dataSource={pipelines} />
+ <Table columns={columns} dataSource={data} />
<Inspector isOpen={isOpen} title={`Pipeline ${json?.id}`} data={json}
onClose={() => setIsOpen(false)} />
</div>
);
diff --git
a/config-ui/src/pages/blueprint/detail/components/pipeline-list/api.ts
b/config-ui/src/pages/pipeline/components/historical/styled.ts
similarity index 67%
rename from config-ui/src/pages/blueprint/detail/components/pipeline-list/api.ts
rename to config-ui/src/pages/pipeline/components/historical/styled.ts
index 6d038c6a8..21362c88b 100644
--- a/config-ui/src/pages/blueprint/detail/components/pipeline-list/api.ts
+++ b/config-ui/src/pages/pipeline/components/historical/styled.ts
@@ -16,6 +16,31 @@
*
*/
-import { request } from '@/utils';
+import { Colors } from '@blueprintjs/core';
+import styled from 'styled-components';
-export const getPipelineLog = (id: ID) =>
request(`/pipelines/${id}/logging.tar.gz`);
+export const StatusColumn = styled.div`
+ display: flex;
+ align-items: center;
+
+ .bp4-icon {
+ margin-right: 4px;
+ }
+
+ &.ready,
+ &.cancel {
+ color: #94959f;
+ }
+
+ &.loading {
+ color: #7497f7;
+ }
+
+ &.success {
+ color: ${Colors.GREEN3};
+ }
+
+ &.error {
+ color: ${Colors.RED3};
+ }
+`;
diff --git a/config-ui/src/pages/pipeline/detail/index.ts
b/config-ui/src/pages/pipeline/components/index.ts
similarity index 95%
copy from config-ui/src/pages/pipeline/detail/index.ts
copy to config-ui/src/pages/pipeline/components/index.ts
index 07d867746..484dfb785 100644
--- a/config-ui/src/pages/pipeline/detail/index.ts
+++ b/config-ui/src/pages/pipeline/components/index.ts
@@ -16,4 +16,4 @@
*
*/
-export * from './pipeline-detail';
+export * from './historical';
diff --git a/config-ui/src/pages/pipeline/detail/api.ts
b/config-ui/src/pages/pipeline/detail/api.ts
index 99cfbd75b..2b4a9bc25 100644
--- a/config-ui/src/pages/pipeline/detail/api.ts
+++ b/config-ui/src/pages/pipeline/detail/api.ts
@@ -27,8 +27,8 @@ export const deletePipeline = (id: ID) =>
method: 'delete',
});
-export const pipeLineRerun = (id: ID) =>
- request(`/pipeline/${id}/rerun`, {
+export const pipelineRerun = (id: ID) =>
+ request(`/pipelines/${id}/rerun`, {
method: 'post',
});
diff --git a/config-ui/src/pages/pipeline/detail/index.ts
b/config-ui/src/pages/pipeline/detail/index.ts
index 07d867746..d0223bac2 100644
--- a/config-ui/src/pages/pipeline/detail/index.ts
+++ b/config-ui/src/pages/pipeline/detail/index.ts
@@ -16,4 +16,4 @@
*
*/
-export * from './pipeline-detail';
+export * from './pipeline-info';
diff --git a/config-ui/src/pages/pipeline/detail/pipeline-detail.tsx
b/config-ui/src/pages/pipeline/detail/pipeline-detail.tsx
index 260437ab9..c280dd99a 100644
--- a/config-ui/src/pages/pipeline/detail/pipeline-detail.tsx
+++ b/config-ui/src/pages/pipeline/detail/pipeline-detail.tsx
@@ -16,40 +16,64 @@
*
*/
-import React, { useState, useMemo } from 'react';
-import { Icon, Button, Collapse, IconName, Intent } from '@blueprintjs/core';
+import React, { useState } from 'react';
+import { Icon, Button, Collapse, Intent, IconName } from '@blueprintjs/core';
import { groupBy } from 'lodash';
import classNames from 'classnames';
import { Card, Loading } from '@/components';
+import { useAutoRefresh } from '@/hooks';
import { formatTime, duration } from '@/utils';
+import type { PipelineType, TaskType } from '../types';
import { StatusEnum } from '../types';
import { STATUS_ICON, STATUS_LABEL, STATUS_CLS } from '../misc';
-import type { UseDetailProps } from './use-detail';
import { useDetail } from './use-detail';
import { Task } from './components';
+import * as API from './api';
import * as S from './styled';
-interface Props extends UseDetailProps {}
+interface Props {
+ id: ID;
+}
-export const PipelineDetail = ({ ...props }: Props) => {
+export const PipelineDetail = ({ id }: Props) => {
const [isOpen, setIsOpen] = useState(true);
- const { loading, operating, pipeline, tasks, onCancel, onRerun, onRerunTask
} = useDetail({ ...props });
-
- const stages = useMemo(() => groupBy(tasks, 'pipelineRow'), [tasks]);
+ const { version, operating, onCancel, onRerun, onRerunTask } = useDetail({
id });
+
+ const { loading, data } = useAutoRefresh<{
+ pipeline: PipelineType;
+ tasks: TaskType[];
+ }>(
+ async () => {
+ const [pipeRes, taskRes] = await Promise.all([API.getPipeline(id),
API.getPipelineTasks(id)]);
+
+ return {
+ pipeline: pipeRes,
+ tasks: taskRes.tasks,
+ };
+ },
+ [version],
+ {
+ cancel: (data) => {
+ const { pipeline } = data ?? {};
+ return !!(
+ pipeline && [StatusEnum.COMPLETED, StatusEnum.FAILED,
StatusEnum.CANCELLED].includes(pipeline.status)
+ );
+ },
+ },
+ );
- if (loading) {
+ if (loading || !data) {
return <Loading />;
}
- if (!pipeline) {
- return <Card>There is no current run for this blueprint.</Card>;
- }
+ const { pipeline, tasks } = data;
const { status, beganAt, finishedAt, stage, finishedTasks, totalTasks,
message } = pipeline;
+ const stages = groupBy(tasks, 'pipelineRow');
const handleToggleOpen = () => {
setIsOpen(!isOpen);
diff --git a/config-ui/src/pages/blueprint/detail/types.ts
b/config-ui/src/pages/pipeline/detail/pipeline-info.tsx
similarity index 71%
copy from config-ui/src/pages/blueprint/detail/types.ts
copy to config-ui/src/pages/pipeline/detail/pipeline-info.tsx
index 174e43525..13e4ced79 100644
--- a/config-ui/src/pages/blueprint/detail/types.ts
+++ b/config-ui/src/pages/pipeline/detail/pipeline-info.tsx
@@ -16,13 +16,20 @@
*
*/
-import { Plugins } from '@/plugins';
+import React from 'react';
-export type ConfigConnectionItemType = {
- icon: string;
- name: string;
- connectionId: ID;
- plugin: Plugins;
- entities: string[];
- scopeIds: ID[];
+import { Card } from '@/components';
+
+import { PipelineDetail } from './pipeline-detail';
+
+interface Props {
+ id?: ID;
+}
+
+export const PipelineInfo = ({ id }: Props) => {
+ if (!id) {
+ return <Card>There is no current run for this blueprint.</Card>;
+ }
+
+ return <PipelineDetail id={id} />;
};
diff --git a/config-ui/src/pages/pipeline/detail/use-detail.ts
b/config-ui/src/pages/pipeline/detail/use-detail.ts
index 96b16ce95..00f7eb582 100644
--- a/config-ui/src/pages/pipeline/detail/use-detail.ts
+++ b/config-ui/src/pages/pipeline/detail/use-detail.ts
@@ -16,106 +16,58 @@
*
*/
-import { useState, useEffect, useMemo, useRef } from 'react';
+import { useState, useMemo } from 'react';
import { operator } from '@/utils';
-import type { PipelineType, TaskType } from '../types';
-import { StatusEnum } from '../types';
-
import * as API from './api';
-const pollTimer = 5000;
-
-export interface UseDetailProps {
- id?: ID;
+export interface Props {
+ id: ID;
}
-export const useDetail = ({ id }: UseDetailProps) => {
+export const useDetail = ({ id }: Props) => {
const [version, setVersion] = useState(0);
- const [loading, setLoading] = useState(false);
const [operating, setOperating] = useState(false);
- const [pipeline, setPipeline] = useState<PipelineType>();
- const [tasks, setTasks] = useState<TaskType[]>([]);
-
- const timer = useRef<any>();
-
- const getPipeline = async () => {
- if (!id) return;
- setLoading(true);
- try {
- const [pipeRes, taskRes] = await Promise.all([API.getPipeline(id),
API.getPipelineTasks(id)]);
-
- setPipeline(pipeRes);
- setTasks(taskRes.tasks);
- } finally {
- setLoading(false);
- }
- };
-
- useEffect(() => {
- getPipeline();
- }, []);
-
- useEffect(() => {
- timer.current = setInterval(() => {
- getPipeline();
- }, pollTimer);
- return () => clearInterval(timer.current);
- }, [version]);
-
- useEffect(() => {
- if (pipeline && [StatusEnum.COMPLETED, StatusEnum.FAILED,
StatusEnum.CANCELLED].includes(pipeline.status)) {
- clearInterval(timer.current);
- }
- }, [pipeline]);
const handlePipelineCancel = async () => {
- if (!id) return;
const [success] = await operator(() => API.deletePipeline(id), {
setOperating,
});
if (success) {
- getPipeline();
setVersion(version + 1);
}
};
const handlePipelineRerun = async () => {
- if (!id) return;
- const [success] = await operator(() => API.pipeLineRerun(id), {
+ const [success] = await operator(() => API.pipelineRerun(id), {
setOperating,
});
if (success) {
- getPipeline();
setVersion(version + 1);
}
};
const handleTaskRertun = async (id: ID) => {
- if (!id) return;
const [success] = await operator(() => API.taskRerun(id), {
setOperating,
});
if (success) {
- getPipeline();
setVersion(version + 1);
}
};
return useMemo(
() => ({
- loading,
+ version,
operating,
- pipeline,
- tasks,
onCancel: handlePipelineCancel,
onRerun: handlePipelineRerun,
onRerunTask: handleTaskRertun,
}),
- [loading, operating, pipeline, tasks],
+ [version, operating],
);
};
diff --git a/config-ui/src/pages/pipeline/index.ts
b/config-ui/src/pages/pipeline/index.ts
index fb5ee63e4..5c45114f7 100644
--- a/config-ui/src/pages/pipeline/index.ts
+++ b/config-ui/src/pages/pipeline/index.ts
@@ -18,4 +18,5 @@
export * from './types';
export * from './misc';
+export * from './components';
export * from './detail';
diff --git a/config-ui/src/pages/project/detail/use-project.ts
b/config-ui/src/pages/project/detail/use-project.ts
index d95a7cd17..6332a4f9c 100644
--- a/config-ui/src/pages/project/detail/use-project.ts
+++ b/config-ui/src/pages/project/detail/use-project.ts
@@ -131,6 +131,6 @@ export const useProject = (name: string) => {
onSelectWebhook: handleSelectWebhook,
onCreateWebhook: handleCreateWebhook,
}),
- [loading, project, saving],
+ [loading, project, saving, name],
);
};
diff --git a/config-ui/src/plugins/common/data-scope/use-data-scope.ts
b/config-ui/src/plugins/common/data-scope/use-data-scope.ts
index 773ac968a..6f1b2033b 100644
--- a/config-ui/src/plugins/common/data-scope/use-data-scope.ts
+++ b/config-ui/src/plugins/common/data-scope/use-data-scope.ts
@@ -28,7 +28,10 @@ export interface UseDataScope {
plugin: string;
connectionId: ID;
entities: string[];
- initialValues?: any;
+ initialValues?: {
+ scope?: any;
+ entites?: string[];
+ };
onSave?: (scope: any) => void;
}
@@ -38,12 +41,12 @@ export const useDataScope = ({ plugin, connectionId,
entities, initialValues, on
const [selectedEntities, setSelectedEntities] = useState<string[]>([]);
useEffect(() => {
- setSelectedScope(initialValues ?? []);
- }, [initialValues]);
+ setSelectedScope(initialValues?.scope ?? []);
+ }, [initialValues?.scope]);
useEffect(() => {
- setSelectedEntities(entities ?? []);
- }, [entities]);
+ setSelectedEntities(initialValues?.entites ?? entities);
+ }, [entities, initialValues?.entites]);
const getPluginId = (scope: any) => {
switch (true) {
diff --git a/config-ui/src/plugins/gitlab/components/miller-columns/index.tsx
b/config-ui/src/plugins/gitlab/components/miller-columns/index.tsx
index a3fd05cb6..d98ee3234 100644
--- a/config-ui/src/plugins/gitlab/components/miller-columns/index.tsx
+++ b/config-ui/src/plugins/gitlab/components/miller-columns/index.tsx
@@ -76,7 +76,7 @@ export const MillerColumns = ({ connectionId, disabledItems,
selectedItems, onCh
return (
<MillerColumnsSelect
- columnCount={3}
+ columnCount={2.5}
columnHeight={300}
getCanExpand={(it) => it.type === 'group'}
getHasMore={getHasMore}
diff --git a/config-ui/src/plugins/jenkins/components/miller-columns/index.tsx
b/config-ui/src/plugins/jenkins/components/miller-columns/index.tsx
index 7b89e26ca..a2a3ddee0 100644
--- a/config-ui/src/plugins/jenkins/components/miller-columns/index.tsx
+++ b/config-ui/src/plugins/jenkins/components/miller-columns/index.tsx
@@ -66,7 +66,7 @@ export const MillerColumns = ({ connectionId, selectedItems,
onChangeItems }: Pr
return (
<MillerColumnsSelect
- columnCount={2}
+ columnCount={2.5}
columnHeight={300}
getCanExpand={(it) => it.type === 'folder'}
getHasMore={getHasMore}