This is an automated email from the ASF dual-hosted git repository.
klesh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git
The following commit(s) were added to refs/heads/main by this push:
new 4cc741d12 refactor(config-ui): use new ui select to replace selector
(#6631)
4cc741d12 is described below
commit 4cc741d1270d57656d81f2c0c18e47baac6fcc98
Author: 青湛 <[email protected]>
AuthorDate: Thu Dec 14 20:48:30 2023 +1300
refactor(config-ui): use new ui select to replace selector (#6631)
---
config-ui/src/components/index.ts | 1 -
config-ui/src/components/selector/index.ts | 20 ---
.../components/selector/multi-selector/index.tsx | 147 ---------------------
.../src/components/selector/selector/index.tsx | 91 -------------
.../plugins/components/data-scope-select/index.tsx | 19 ++-
.../plugins/components/scope-config-form/index.tsx | 16 +--
.../plugins/register/bitbucket/transformation.tsx | 54 ++++----
.../src/plugins/register/jira/transformation.tsx | 91 +++++++------
.../src/plugins/register/tapd/transformation.tsx | 106 ++++++---------
config-ui/src/routes/api-keys/api-keys.tsx | 23 ++--
10 files changed, 142 insertions(+), 426 deletions(-)
diff --git a/config-ui/src/components/index.ts
b/config-ui/src/components/index.ts
index 707c3506d..143c30b7f 100644
--- a/config-ui/src/components/index.ts
+++ b/config-ui/src/components/index.ts
@@ -24,5 +24,4 @@ export * from './logo';
export * from './message';
export * from './no-data';
export * from './page-header';
-export * from './selector';
export * from './tooltip';
diff --git a/config-ui/src/components/selector/index.ts
b/config-ui/src/components/selector/index.ts
deleted file mode 100644
index eb2f71e3d..000000000
--- a/config-ui/src/components/selector/index.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-export * from './selector';
-export * from './multi-selector';
diff --git a/config-ui/src/components/selector/multi-selector/index.tsx
b/config-ui/src/components/selector/multi-selector/index.tsx
deleted file mode 100644
index 4d48c6c4b..000000000
--- a/config-ui/src/components/selector/multi-selector/index.tsx
+++ /dev/null
@@ -1,147 +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 { MenuItem, Checkbox, Intent } from '@blueprintjs/core';
-import { MultiSelect2 } from '@blueprintjs/select';
-import { useDebounce } from 'ahooks';
-
-interface Props<T> {
- placeholder?: string;
- loading?: boolean;
- disabled?: boolean;
- items: T[];
- disabledItems?: T[];
- getKey?: (item: T) => string | number;
- getName?: (item: T) => string;
- getIcon?: (item: T) => string;
- selectedItems?: T[];
- onChangeItems?: (selectedItems: T[]) => void;
- noResult?: string;
- onQueryChange?: (query: string) => void;
-}
-
-export const MultiSelector = <T,>({
- placeholder,
- loading = false,
- disabled = false,
- items,
- disabledItems = [],
- getKey = (it) => it as string,
- getName = (it) => it as string,
- getIcon,
- onChangeItems,
- noResult = 'No results found.',
- onQueryChange,
- ...props
-}: Props<T>) => {
- const [selectedItems, setSelectedItems] = useState<T[]>([]);
- const [query, setQuery] = useState('');
- const search = useDebounce(query, { wait: 500 });
-
- const filteredItems = useMemo(
- () =>
- items.filter((it) => {
- const name = getName(it);
- return name.toLocaleLowerCase().includes(search.toLocaleLowerCase());
- }),
- [items, search],
- );
-
- useEffect(() => {
- setSelectedItems(props.selectedItems ?? []);
- }, [props.selectedItems]);
-
- const tagRenderer = (item: T) => {
- const name = getName(item);
- return <span>{name}</span>;
- };
-
- const itemRenderer = (item: T, { handleClick }: any) => {
- const key = getKey(item);
- const name = getName(item);
- const icon = getIcon?.(item);
- const selected = !!selectedItems.find((it) => getKey(it) === key);
- const disabled = !!disabledItems.find((it) => getKey(it) === key);
-
- return (
- <MenuItem
- key={key}
- disabled={selected || disabled}
- onClick={(e) => {
- e.preventDefault();
- handleClick();
- }}
- labelElement={icon ? <img src={icon} width={16} alt="" /> : null}
- text={<Checkbox disabled={selected || disabled} checked={selected ||
disabled} readOnly label={name} />}
- />
- );
- };
-
- const handleItemSelect = (item: T) => {
- const newSelectedItems = [...selectedItems, item];
- if (onChangeItems) {
- onChangeItems(newSelectedItems);
- } else {
- setSelectedItems(newSelectedItems);
- }
- };
-
- const handleItemRemove = (item: T) => {
- const newSelectedItems = selectedItems.filter((it) => getKey(it) !==
getKey(item));
- if (onChangeItems) {
- onChangeItems(newSelectedItems);
- } else {
- setSelectedItems(newSelectedItems);
- }
- };
-
- const handleQueryChange = (query: string) => {
- if (onQueryChange && query) {
- onQueryChange(query);
- } else {
- setQuery(query);
- }
- };
-
- return (
- <MultiSelect2
- disabled={disabled}
- resetOnSelect
- fill
- placeholder={placeholder ?? 'Select...'}
- items={filteredItems}
- // 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}
- tagInputProps={{
- tagProps: {
- intent: Intent.PRIMARY,
- minimal: true,
- },
- }}
- onItemSelect={handleItemSelect}
- onRemove={handleItemRemove}
- onQueryChange={handleQueryChange}
- noResults={<MenuItem disabled={true} text={loading ? 'Fetching...' :
noResult} />}
- />
- );
-};
diff --git a/config-ui/src/components/selector/selector/index.tsx
b/config-ui/src/components/selector/selector/index.tsx
deleted file mode 100644
index e425c5139..000000000
--- a/config-ui/src/components/selector/selector/index.tsx
+++ /dev/null
@@ -1,91 +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 { MenuItem, Button, Alignment } from '@blueprintjs/core';
-import { Select2 } from '@blueprintjs/select';
-
-interface Props<T> {
- items: T[];
- disabledItems?: T[];
- getKey?: (item: T) => ID;
- getName?: (item: T) => string;
- getIcon?: (item: T) => string;
- selectedItem?: T;
- onChangeItem?: (selectedItem: T) => void;
-}
-
-export const Selector = <T,>({
- items,
- disabledItems = [],
- getKey = (it) => it as string,
- getName = (it) => it as string,
- getIcon,
- onChangeItem,
- ...props
-}: Props<T>) => {
- const [selectedItem, setSelectedItem] = useState<T>();
-
- useEffect(() => {
- setSelectedItem(props.selectedItem);
- }, [props.selectedItem]);
-
- const btnText = useMemo(() => (selectedItem ? getName(selectedItem) :
'Select...'), [selectedItem]);
-
- const itemPredicate = (query: string, item: T) => {
- const name = getName(item);
- return name.toLowerCase().indexOf(query.toLowerCase()) >= 0;
- };
-
- const itemRenderer = (item: T, { handleClick }: any) => {
- const key = getKey(item);
- const name = getName(item);
- const icon = getIcon?.(item) ?? null;
- const disabled = !!disabledItems.find((it) => getKey(it) === getKey(item))
|| selectedItem === item;
-
- return (
- <MenuItem
- key={key}
- disabled={disabled}
- text={<span>{name}</span>}
- icon={icon ? <img src={icon} alt="" width={20} /> : null}
- onClick={handleClick}
- />
- );
- };
-
- const handleItemSelect = (item: T) => {
- if (onChangeItem) {
- onChangeItem(item);
- } else {
- setSelectedItem(item);
- }
- };
-
- return (
- <Select2
- items={items}
- activeItem={selectedItem}
- itemPredicate={itemPredicate}
- itemRenderer={itemRenderer}
- onItemSelect={handleItemSelect}
- >
- <Button outlined fill alignText={Alignment.LEFT} rightIcon="caret-down"
text={btnText} />
- </Select2>
- );
-};
diff --git a/config-ui/src/plugins/components/data-scope-select/index.tsx
b/config-ui/src/plugins/components/data-scope-select/index.tsx
index f9bf2254e..3f1e86092 100644
--- a/config-ui/src/plugins/components/data-scope-select/index.tsx
+++ b/config-ui/src/plugins/components/data-scope-select/index.tsx
@@ -17,14 +17,14 @@
*/
import { useState, useEffect, useMemo } from 'react';
-import { Flex } from 'antd';
+import { Flex, Select } from 'antd';
import { Button, Intent } from '@blueprintjs/core';
import { useDebounce } from 'ahooks';
import type { McsItem } from 'miller-columns-select';
import MillerColumnsSelect from 'miller-columns-select';
import API from '@/api';
-import { Loading, Block, ExternalLink, Message, MultiSelector } from
'@/components';
+import { Loading, Block, ExternalLink, Message } from '@/components';
import { useRefreshData } from '@/hooks';
import { getPluginScopeId } from '@/plugins';
@@ -133,15 +133,14 @@ export const DataScopeSelect = ({
<Button intent={Intent.PRIMARY} icon="refresh" text="Refresh
Data Scope" />
</Flex>
)}
- <MultiSelector
+ <Select
loading={!ready}
- items={searchItems}
- getName={(it) => it.name}
- getKey={(it) => getPluginScopeId(plugin, it)}
- noResult="No Data Scopes Available."
- onQueryChange={(query) => setQuery(query)}
- selectedItems={searchItems.filter((it) =>
selectedIds.includes(getPluginScopeId(plugin, it)))}
- onChangeItems={(selectedItems) =>
setSelectedIds(selectedItems.map((it) => getPluginScopeId(plugin, it)))}
+ showSearch
+ mode="multiple"
+ options={searchItems.map((it) => ({ label: it.fullName, value:
getPluginScopeId(plugin, it) }))}
+ value={selectedIds}
+ onChange={(value) => setSelectedIds(value)}
+ onSearch={(value) => setQuery(value)}
/>
<MillerColumnsSelect
showSelectAll
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 abb6c18db..4d1be1e88 100644
--- a/config-ui/src/plugins/components/scope-config-form/index.tsx
+++ b/config-ui/src/plugins/components/scope-config-form/index.tsx
@@ -18,11 +18,11 @@
import { useState, useEffect, useMemo } from 'react';
import { omit } from 'lodash';
-import { Flex, Form, Input, Card, Alert, Divider } from 'antd';
+import { Flex, Form, Input, Card, Alert, Divider, Select } from 'antd';
import { Button, Intent } from '@blueprintjs/core';
import API from '@/api';
-import { ExternalLink, Block, MultiSelector, Message } from '@/components';
+import { ExternalLink, Block, Message } from '@/components';
import { transformEntities, EntitiesLabel } from '@/config';
import { getPluginConfig } from '@/plugins';
import { GitHubTransformation } from '@/plugins/register/github';
@@ -145,12 +145,12 @@ export const ScopeConfigForm = ({
}
required
>
- <MultiSelector
- items={transformEntities(config.scopeConfig?.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))}
+ <Select
+ style={{ width: '100%' }}
+ mode="multiple"
+ options={transformEntities(config.scopeConfig?.entities ?? [])}
+ value={entities}
+ onChange={(value) => setEntities(value)}
/>
</Block>
{showWarning && (
diff --git a/config-ui/src/plugins/register/bitbucket/transformation.tsx
b/config-ui/src/plugins/register/bitbucket/transformation.tsx
index f0562a538..6bae7b8a7 100644
--- a/config-ui/src/plugins/register/bitbucket/transformation.tsx
+++ b/config-ui/src/plugins/register/bitbucket/transformation.tsx
@@ -18,9 +18,9 @@
import { useMemo, useState, useEffect } from 'react';
import { CaretRightOutlined } from '@ant-design/icons';
-import { theme, Collapse, Tag, Form, Input, Checkbox } from 'antd';
+import { theme, Collapse, Tag, Form, Input, Checkbox, Select } from 'antd';
-import { ExternalLink, HelpTooltip, MultiSelector } from '@/components';
+import { ExternalLink, HelpTooltip } from '@/components';
import { DOC_URL } from '@/release';
import ExampleJpg from './assets/bitbucket-example.jpg';
@@ -127,55 +127,53 @@ const renderCollapseItems = ({
children: (
<div className="list">
<Form.Item label="TODO">
- <MultiSelector
- items={ALL_STATES}
- disabledItems={selectedStates}
- selectedItems={transformation.issueStatusTodo ?
transformation.issueStatusTodo.split(',') : []}
- onChangeItems={(selectedItems) =>
+ <Select
+ mode="multiple"
+ options={ALL_STATES.map((it) => ({ label: it, value: it }))}
+ value={transformation.issueStatusTodo ?
transformation.issueStatusTodo.split(',') : []}
+ onChange={(value) =>
onChangeTransformation({
...transformation,
- issueStatusTodo: selectedItems.join(','),
+ issueStatusTodo: value.join(','),
})
}
/>
</Form.Item>
<Form.Item label="IN-PROGRESS">
- <MultiSelector
- items={ALL_STATES}
- disabledItems={selectedStates}
- selectedItems={
- transformation.issueStatusInProgress ?
transformation.issueStatusInProgress.split(',') : []
- }
- onChangeItems={(selectedItems) =>
+ <Select
+ mode="multiple"
+ options={ALL_STATES.map((it) => ({ label: it, value: it }))}
+ value={transformation.issueStatusInProgress ?
transformation.issueStatusInProgress.split(',') : []}
+ onChange={(value) =>
onChangeTransformation({
...transformation,
- issueStatusInProgress: selectedItems.join(','),
+ issueStatusInProgress: value.join(','),
})
}
/>
</Form.Item>
<Form.Item label="DONE">
- <MultiSelector
- items={ALL_STATES}
- disabledItems={selectedStates}
- selectedItems={transformation.issueStatusDone ?
transformation.issueStatusDone.split(',') : []}
- onChangeItems={(selectedItems) =>
+ <Select
+ mode="multiple"
+ options={ALL_STATES.map((it) => ({ label: it, value: it }))}
+ value={transformation.issueStatusDone ?
transformation.issueStatusDone.split(',') : []}
+ onChange={(value) =>
onChangeTransformation({
...transformation,
- issueStatusDone: selectedItems.join(','),
+ issueStatusDone: value.join(','),
})
}
/>
</Form.Item>
<Form.Item label="OTHER">
- <MultiSelector
- items={ALL_STATES}
- disabledItems={selectedStates}
- selectedItems={transformation.issueStatusOther ?
transformation.issueStatusOther.split(',') : []}
- onChangeItems={(selectedItems) =>
+ <Select
+ mode="multiple"
+ options={ALL_STATES.map((it) => ({ label: it, value: it }))}
+ value={transformation.issueStatusOther ?
transformation.issueStatusOther.split(',') : []}
+ onChange={(value) =>
onChangeTransformation({
...transformation,
- issueStatusOther: selectedItems.join(','),
+ issueStatusOther: value.join(','),
})
}
/>
diff --git a/config-ui/src/plugins/register/jira/transformation.tsx
b/config-ui/src/plugins/register/jira/transformation.tsx
index 7964674e5..90fd62037 100644
--- a/config-ui/src/plugins/register/jira/transformation.tsx
+++ b/config-ui/src/plugins/register/jira/transformation.tsx
@@ -19,10 +19,10 @@
import { useState, useEffect, useMemo } from 'react';
import { uniqWith } from 'lodash';
import { CaretRightOutlined } from '@ant-design/icons';
-import { theme, Collapse, Tag, Form } from 'antd';
+import { theme, Collapse, Tag, Form, Select } from 'antd';
import API from '@/api';
-import { PageLoading, HelpTooltip, ExternalLink, MultiSelector, Selector }
from '@/components';
+import { PageLoading, HelpTooltip, ExternalLink } from '@/components';
import { useProxyPrefix, useRefreshData } from '@/hooks';
import { DOC_URL } from '@/release';
@@ -165,14 +165,26 @@ const renderCollapseItems = ({
transformation: any;
onChangeTransformation: any;
connectionId: ID;
- issueTypes: any;
+ issueTypes: Array<{
+ id: string;
+ name: string;
+ }>;
fields: Array<{
id: string;
name: string;
}>;
- requirementItems: any;
- bugItems: any;
- incidentItems: any;
+ requirementItems: Array<{
+ id: string;
+ name: string;
+ }>;
+ bugItems: Array<{
+ id: string;
+ name: string;
+ }>;
+ incidentItems: Array<{
+ id: string;
+ name: string;
+ }>;
transformaType: any;
}) =>
[
@@ -194,18 +206,18 @@ const renderCollapseItems = ({
<ExternalLink link={DOC_URL.METRICS.MTTR}>DORA - Median Time to
Restore Service</ExternalLink>, etc.
</p>
<Form.Item label="Requirement">
- <MultiSelector
- items={issueTypes}
- disabledItems={[...bugItems, ...incidentItems]}
- getKey={(it) => it.id}
- getName={(it) => it.name}
- getIcon={(it) => it.iconUrl}
- selectedItems={requirementItems}
- onChangeItems={(selectedItems) =>
+ <Select
+ mode="multiple"
+ options={issueTypes.map((it) => ({ label: it.name, value: it.id
}))}
+ value={requirementItems.map((it) => it.id)}
+ onChange={(value) =>
onChangeTransformation({
...transformation,
typeMappings: {
- ...transformaType(selectedItems, StandardType.Requirement),
+ ...transformaType(
+ requirementItems.filter((it) => value.includes(it.id)),
+ StandardType.Requirement,
+ ),
...transformaType(bugItems, StandardType.Bug),
...transformaType(incidentItems, StandardType.Incident),
},
@@ -214,19 +226,19 @@ const renderCollapseItems = ({
/>
</Form.Item>
<Form.Item label="Bug">
- <MultiSelector
- items={issueTypes}
- disabledItems={[...requirementItems, ...incidentItems]}
- getKey={(it) => it.id}
- getName={(it) => it.name}
- getIcon={(it) => it.iconUrl}
- selectedItems={bugItems}
- onChangeItems={(selectedItems) =>
+ <Select
+ mode="multiple"
+ options={issueTypes.map((it) => ({ label: it.name, value: it.id
}))}
+ value={bugItems.map((it) => it.id)}
+ onChange={(value) =>
onChangeTransformation({
...transformation,
typeMappings: {
...transformaType(requirementItems,
StandardType.Requirement),
- ...transformaType(selectedItems, StandardType.Bug),
+ ...transformaType(
+ bugItems.filter((it) => value.includes(it.id)),
+ StandardType.Bug,
+ ),
...transformaType(incidentItems, StandardType.Incident),
},
})
@@ -243,20 +255,21 @@ const renderCollapseItems = ({
</>
}
>
- <MultiSelector
- items={issueTypes}
- disabledItems={[...requirementItems, ...bugItems]}
- getKey={(it) => it.id}
- getName={(it) => it.name}
- getIcon={(it) => it.iconUrl}
- selectedItems={incidentItems}
- onChangeItems={(selectedItems) =>
+ <Select
+ mode="multiple"
+ options={issueTypes.map((it) => ({ label: it.name, value: it.id
}))}
+ value={incidentItems.map((it) => it.id)}
+ onChange={(value) =>
onChangeTransformation({
...transformation,
typeMappings: {
...transformaType(requirementItems,
StandardType.Requirement),
...transformaType(bugItems, StandardType.Bug),
- ...transformaType(selectedItems, StandardType.Incident),
+ ...transformaType(
+ incidentItems.filter((it) => value.includes(it.id)),
+
+ StandardType.Incident,
+ ),
},
})
}
@@ -270,15 +283,13 @@ const renderCollapseItems = ({
</>
}
>
- <Selector
- items={fields}
- getKey={(it) => it.id}
- getName={(it) => it.name}
- selectedItem={fields.find((it) => it.id ===
transformation.storyPointField)}
- onChangeItem={(selectedItem) =>
+ <Select
+ options={fields.map((it) => ({ label: it.name, value: it.id }))}
+ value={transformation.storyPointField}
+ onChange={(value) =>
onChangeTransformation({
...transformation,
- storyPointField: selectedItem.id,
+ storyPointField: value,
})
}
/>
diff --git a/config-ui/src/plugins/register/tapd/transformation.tsx
b/config-ui/src/plugins/register/tapd/transformation.tsx
index cb4d9e624..b010ed7de 100644
--- a/config-ui/src/plugins/register/tapd/transformation.tsx
+++ b/config-ui/src/plugins/register/tapd/transformation.tsx
@@ -19,10 +19,10 @@
import { useEffect, useState } from 'react';
import { uniqWith } from 'lodash';
import { CaretRightOutlined } from '@ant-design/icons';
-import { theme, Collapse, Tag, Form } from 'antd';
+import { theme, Collapse, Tag, Form, Select } from 'antd';
import API from '@/api';
-import { MultiSelector, PageLoading } from '@/components';
+import { PageLoading } from '@/components';
import { useProxyPrefix, useRefreshData } from '@/hooks';
enum StandardType {
@@ -211,20 +211,15 @@ const renderCollapseItems = ({
and `Bug age` in built-in dashboards.
</p>
<Form.Item label="Requirement">
- <MultiSelector
- items={typeList}
- disabledItems={typeList.filter((v) => [...bugTypeList,
...incidentTypeList].includes(v.id))}
- getKey={(it) => it.id}
- getName={(it) => it.name}
- selectedItems={typeList.filter((v) =>
featureTypeList.includes(v.id))}
- onChangeItems={(selectedItems) =>
+ <Select
+ mode="multiple"
+ options={typeList.map((it) => ({ label: it.name, value: it.id
}))}
+ value={featureTypeList}
+ onChange={(value) =>
onChangeTransformation({
...transformation,
typeMappings: {
- ...transformaType(
- selectedItems.map((v) => v.id),
- StandardType.Requirement,
- ),
+ ...transformaType(value, StandardType.Requirement),
...transformaType(bugTypeList, StandardType.Bug),
...transformaType(incidentTypeList, StandardType.Incident),
},
@@ -233,21 +228,16 @@ const renderCollapseItems = ({
/>
</Form.Item>
<Form.Item label="Bug">
- <MultiSelector
- items={typeList}
- disabledItems={typeList.filter((v) => [...featureTypeList,
...incidentTypeList].includes(v.id))}
- getKey={(it) => it.id}
- getName={(it) => it.name}
- selectedItems={typeList.filter((v) =>
bugTypeList.includes(v.id))}
- onChangeItems={(selectedItems) =>
+ <Select
+ mode="multiple"
+ options={typeList.map((it) => ({ label: it.name, value: it.id
}))}
+ value={bugTypeList}
+ onChange={(value) =>
onChangeTransformation({
...transformation,
typeMappings: {
...transformaType(featureTypeList,
StandardType.Requirement),
- ...transformaType(
- selectedItems.map((v) => v.id),
- StandardType.Bug,
- ),
+ ...transformaType(value, StandardType.Bug),
...transformaType(incidentTypeList, StandardType.Incident),
},
})
@@ -264,22 +254,17 @@ const renderCollapseItems = ({
</>
}
>
- <MultiSelector
- items={typeList}
- disabledItems={typeList.filter((v) => [...featureTypeList,
...bugTypeList].includes(v.id))}
- getKey={(it) => it.id}
- getName={(it) => it.name}
- selectedItems={typeList.filter((v) =>
incidentTypeList.includes(v.id))}
- onChangeItems={(selectedItems) =>
+ <Select
+ mode="multiple"
+ options={typeList.map((it) => ({ label: it.name, value: it.id
}))}
+ value={incidentTypeList}
+ onChange={(value) =>
onChangeTransformation({
...transformation,
typeMappings: {
...transformaType(featureTypeList,
StandardType.Requirement),
...transformaType(bugTypeList, StandardType.Bug),
- ...transformaType(
- selectedItems.map((v) => v.id),
- StandardType.Incident,
- ),
+ ...transformaType(value, StandardType.Incident),
},
})
}
@@ -290,20 +275,15 @@ const renderCollapseItems = ({
Delivery Rate` in built-in dashboards.
</p>
<Form.Item label="TODO">
- <MultiSelector
- items={statusList}
- disabledItems={statusList.filter((v) =>
[...inProgressStatusList, ...doneStatusList].includes(v.name))}
- getKey={(it) => it.id}
- getName={(it) => it.name}
- selectedItems={statusList.filter((v) =>
todoStatusList.includes(v.name))}
- onChangeItems={(selectedItems) =>
+ <Select
+ mode="multiple"
+ options={statusList.map((it) => ({ label: it.name, value: it.id
}))}
+ value={todoStatusList}
+ onChange={(value) =>
onChangeTransformation({
...transformation,
statusMappings: {
- ...transformaType(
- selectedItems.map((v) => v.name),
- StandardStatus.Todo,
- ),
+ ...transformaType(value, StandardStatus.Todo),
...transformaType(inProgressStatusList,
StandardStatus.InProgress),
...transformaType(doneStatusList, StandardStatus.Done),
},
@@ -312,21 +292,16 @@ const renderCollapseItems = ({
/>
</Form.Item>
<Form.Item label="IN-PROGRESS">
- <MultiSelector
- items={statusList}
- disabledItems={statusList.filter((v) => [...todoStatusList,
...doneStatusList].includes(v.name))}
- getKey={(it) => it.id}
- getName={(it) => it.name}
- selectedItems={statusList.filter((v) =>
inProgressStatusList.includes(v.name))}
- onChangeItems={(selectedItems) =>
+ <Select
+ mode="multiple"
+ options={statusList.map((it) => ({ label: it.name, value: it.id
}))}
+ value={inProgressStatusList}
+ onChange={(value) =>
onChangeTransformation({
...transformation,
statusMappings: {
...transformaType(todoStatusList, StandardStatus.Todo),
- ...transformaType(
- selectedItems.map((v) => v.name),
- StandardStatus.InProgress,
- ),
+ ...transformaType(value, StandardStatus.InProgress),
...transformaType(doneStatusList, StandardStatus.Done),
},
})
@@ -334,22 +309,17 @@ const renderCollapseItems = ({
/>
</Form.Item>
<Form.Item label="DONE">
- <MultiSelector
- items={statusList}
- disabledItems={statusList.filter((v) => [...todoStatusList,
...inProgressStatusList].includes(v.name))}
- getKey={(it) => it.id}
- getName={(it) => it.name}
- selectedItems={statusList.filter((v) =>
doneStatusList.includes(v.name))}
- onChangeItems={(selectedItems) =>
+ <Select
+ mode="multiple"
+ options={statusList.map((it) => ({ label: it.name, value: it.id
}))}
+ value={doneStatusList}
+ onChange={(value) =>
onChangeTransformation({
...transformation,
statusMappings: {
...transformaType(todoStatusList, StandardStatus.Todo),
...transformaType(inProgressStatusList,
StandardStatus.InProgress),
- ...transformaType(
- selectedItems.map((v) => v.name),
- StandardStatus.Done,
- ),
+ ...transformaType(value, StandardStatus.Done),
},
})
}
diff --git a/config-ui/src/routes/api-keys/api-keys.tsx
b/config-ui/src/routes/api-keys/api-keys.tsx
index 252ac553f..6271b4674 100644
--- a/config-ui/src/routes/api-keys/api-keys.tsx
+++ b/config-ui/src/routes/api-keys/api-keys.tsx
@@ -17,12 +17,12 @@
*/
import { useState, useMemo } from 'react';
-import { Table, Modal, Input } from 'antd';
+import { Table, Modal, Input, Select } from 'antd';
import { Button, Tag, Intent } from '@blueprintjs/core';
import dayjs from 'dayjs';
import API from '@/api';
-import { PageHeader, Block, Selector, ExternalLink, CopyText, Message } from
'@/components';
+import { PageHeader, Block, ExternalLink, CopyText, Message } from
'@/components';
import { useRefreshData } from '@/hooks';
import { operator, formatTime } from '@/utils';
@@ -53,8 +53,8 @@ export const ApiKeys = () => {
const [dataSource, total] = useMemo(() => [data?.apikeys ?? [], data?.count
?? 0], [data]);
const hasError = useMemo(() => !form.name || !form.allowedPath, [form]);
- const timeSelectedItem = useMemo(() => {
- return C.timeOptions.find((it) => it.value === form.expiredAt ||
!it.value);
+ const timeSelectedValue = useMemo(() => {
+ return C.timeOptions.find((it) => it.value === form.expiredAt ||
!it.value)?.value;
}, [form.expiredAt]);
const handleCancel = () => {
@@ -174,15 +174,12 @@ export const ApiKeys = () => {
/>
</Block>
<Block title="Expiration" description="Set an expiration time for
your API key." required>
- <div style={{ width: 386 }}>
- <Selector
- items={C.timeOptions}
- getKey={(it) => it.value}
- getName={(it) => it.label}
- selectedItem={timeSelectedItem}
- onChangeItem={(it) => setForm({ ...form, expiredAt: it.value ?
it.value : undefined })}
- />
- </div>
+ <Select
+ style={{ width: 386 }}
+ options={C.timeOptions}
+ value={timeSelectedValue}
+ onChange={(value) => setForm({ ...form, expiredAt: value ? value
: undefined })}
+ />
</Block>
<Block
title="Allowed Path"