mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-11-23 22:22:08 +00:00
Update data contract details fields (#22746)
* update data contract details fields * fix the select option chip not properly displaying the data * supported new form field for UserTeamSelectInput Selector * remove component changes that we not needed * fix the selected owner chip design * supported the userPopoverList width as per screen size with max and min limitation * fix the tab inside userTeamSelect list not proper as the content and some oprimiztion on component side * fix the playwright because of owner changes * fix the description box overflow and owner selcect box overlapping on select input * enum label fix * remove the comment code and fix the localization and sematic status changing issue are contract validation run
This commit is contained in:
parent
882d858972
commit
accc05a494
@ -100,7 +100,7 @@ test.describe('Data Contracts', () => {
|
|||||||
DATA_CONTRACT_DETAILS.description
|
DATA_CONTRACT_DETAILS.description
|
||||||
);
|
);
|
||||||
|
|
||||||
await page.getByTestId('add-owner').click();
|
await page.getByTestId('select-owners').click();
|
||||||
await page.getByRole('tab', { name: 'Users' }).click();
|
await page.getByRole('tab', { name: 'Users' }).click();
|
||||||
await page
|
await page
|
||||||
.getByTestId('owner-select-users-search-bar')
|
.getByTestId('owner-select-users-search-bar')
|
||||||
@ -114,9 +114,7 @@ test.describe('Data Contracts', () => {
|
|||||||
await page.getByTestId('selectable-list-update-btn').click();
|
await page.getByTestId('selectable-list-update-btn').click();
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
page
|
page.getByTestId('user-tag').getByText(user.responseData.name)
|
||||||
.getByTestId('owner-link')
|
|
||||||
.getByTestId(user.responseData.displayName)
|
|
||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -130,10 +130,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ant-btn-group.spaced {
|
.ant-btn-group.spaced {
|
||||||
.ant-btn.data-contract-latest-result-button {
|
.ant-btn.ant-btn-default.data-contract-latest-result-button {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
padding: 6px 12px;
|
padding: 6px 12px;
|
||||||
border-radius: 12px !important;
|
border-radius: 12px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
box-shadow: 0px 2px 2px -1px @grey-35, 0px 4px 6px -2px @grey-35,
|
box-shadow: 0px 2px 2px -1px @grey-35, 0px 4px 6px -2px @grey-35,
|
||||||
0px 12px 16px -4px @grey-35;
|
0px 12px 16px -4px @grey-35;
|
||||||
@ -153,11 +153,6 @@
|
|||||||
color: @orange-7;
|
color: @orange-7;
|
||||||
border: 1px solid @orange-200;
|
border: 1px solid @orange-200;
|
||||||
background-color: @orange-50;
|
background-color: @orange-50;
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border: 1px solid @red-19;
|
|
||||||
background-color: @red-2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.running {
|
&.running {
|
||||||
|
|||||||
@ -10,20 +10,15 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import Icon, { PlusOutlined } from '@ant-design/icons';
|
import Icon from '@ant-design/icons';
|
||||||
import { Button, Card, Form, Typography } from 'antd';
|
import { Button, Card, Form, Typography } from 'antd';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { ReactComponent as RightIcon } from '../../../assets/svg/right-arrow.svg';
|
import { ReactComponent as RightIcon } from '../../../assets/svg/right-arrow.svg';
|
||||||
import { DataContract } from '../../../generated/entity/data/dataContract';
|
import { DataContract } from '../../../generated/entity/data/dataContract';
|
||||||
import { EntityReference } from '../../../generated/type/entityReference';
|
import { FieldProp, FieldTypes } from '../../../interface/FormUtils.interface';
|
||||||
import {
|
|
||||||
FieldProp,
|
|
||||||
FieldTypes,
|
|
||||||
FormItemLayout,
|
|
||||||
} from '../../../interface/FormUtils.interface';
|
|
||||||
import { generateFormFields } from '../../../utils/formUtils';
|
import { generateFormFields } from '../../../utils/formUtils';
|
||||||
import { OwnerLabel } from '../../common/OwnerLabel/OwnerLabel.component';
|
import './contract-detail-form-tab.less';
|
||||||
|
|
||||||
export const ContractDetailFormTab: React.FC<{
|
export const ContractDetailFormTab: React.FC<{
|
||||||
initialValues?: Partial<DataContract>;
|
initialValues?: Partial<DataContract>;
|
||||||
@ -34,8 +29,6 @@ export const ContractDetailFormTab: React.FC<{
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
|
||||||
const owners = Form.useWatch<EntityReference[]>('owners', form);
|
|
||||||
|
|
||||||
const fields: FieldProp[] = [
|
const fields: FieldProp[] = [
|
||||||
{
|
{
|
||||||
label: t('label.contract-title'),
|
label: t('label.contract-title'),
|
||||||
@ -47,6 +40,22 @@ export const ContractDetailFormTab: React.FC<{
|
|||||||
'data-testid': 'contract-name',
|
'data-testid': 'contract-name',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: t('label.owner-plural'),
|
||||||
|
name: 'owners',
|
||||||
|
id: 'root/owner',
|
||||||
|
type: FieldTypes.USER_TEAM_SELECT_INPUT,
|
||||||
|
required: false,
|
||||||
|
props: {
|
||||||
|
owner: initialValues?.owners,
|
||||||
|
hasPermission: true,
|
||||||
|
multiple: { user: true, team: false },
|
||||||
|
},
|
||||||
|
formItemProps: {
|
||||||
|
valuePropName: 'owners',
|
||||||
|
trigger: 'onUpdate',
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: t('label.description'),
|
label: t('label.description'),
|
||||||
id: 'description',
|
id: 'description',
|
||||||
@ -58,31 +67,6 @@ export const ContractDetailFormTab: React.FC<{
|
|||||||
initialValue: initialValues?.description ?? '',
|
initialValue: initialValues?.description ?? '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: t('label.owner-plural'),
|
|
||||||
id: 'owners',
|
|
||||||
name: 'owners',
|
|
||||||
type: FieldTypes.USER_TEAM_SELECT,
|
|
||||||
required: false,
|
|
||||||
props: {
|
|
||||||
owner: initialValues?.owners,
|
|
||||||
hasPermission: true,
|
|
||||||
children: (
|
|
||||||
<Button
|
|
||||||
data-testid="add-owner"
|
|
||||||
icon={<PlusOutlined style={{ color: 'white', fontSize: '12px' }} />}
|
|
||||||
size="small"
|
|
||||||
type="primary"
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
multiple: { user: true, team: false },
|
|
||||||
},
|
|
||||||
formItemLayout: FormItemLayout.HORIZONTAL,
|
|
||||||
formItemProps: {
|
|
||||||
valuePropName: 'owners',
|
|
||||||
trigger: 'onUpdate',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -109,13 +93,11 @@ export const ContractDetailFormTab: React.FC<{
|
|||||||
|
|
||||||
<div className="contract-form-content-container">
|
<div className="contract-form-content-container">
|
||||||
<Form
|
<Form
|
||||||
className="contract-detail-form"
|
className="new-form-style contract-detail-form"
|
||||||
form={form}
|
form={form}
|
||||||
layout="vertical"
|
layout="vertical"
|
||||||
onValuesChange={onChange}>
|
onValuesChange={onChange}>
|
||||||
{generateFormFields(fields)}
|
{generateFormFields(fields)}
|
||||||
|
|
||||||
{owners?.length > 0 && <OwnerLabel owners={owners} />}
|
|
||||||
</Form>
|
</Form>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025 Collate.
|
||||||
|
* Licensed 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.
|
||||||
|
*/
|
||||||
|
.contract-detail-form {
|
||||||
|
.block-editor-wrapper.block-editor-wrapper--bar-menu {
|
||||||
|
.om-block-editor {
|
||||||
|
height: 160px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -266,7 +266,6 @@ const ContractDetail: React.FC<{
|
|||||||
setValidateLoading(true);
|
setValidateLoading(true);
|
||||||
await validateContractById(contract.id);
|
await validateContractById(contract.id);
|
||||||
showSuccessToast(t('message.contract-validation-trigger-successfully'));
|
showSuccessToast(t('message.contract-validation-trigger-successfully'));
|
||||||
fetchLatestContractResults();
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showErrorToast(err as AxiosError);
|
showErrorToast(err as AxiosError);
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@ -246,7 +246,9 @@ export const ContractQualityFormTab: React.FC<{
|
|||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
searchProps={{
|
searchProps={{
|
||||||
placeholder: t('label.search-by-name'),
|
placeholder: t('label.search-by-type', {
|
||||||
|
type: t('label.name'),
|
||||||
|
}),
|
||||||
onSearch: (value) => {
|
onSearch: (value) => {
|
||||||
fetchAllTests({
|
fetchAllTests({
|
||||||
offset: 0,
|
offset: 0,
|
||||||
|
|||||||
@ -11,10 +11,11 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { CloseOutlined } from '@ant-design/icons';
|
import Icon from '@ant-design/icons';
|
||||||
import { Space, Typography } from 'antd';
|
import { Space, Typography } from 'antd';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { isUndefined, toString } from 'lodash';
|
import { isUndefined, toString } from 'lodash';
|
||||||
|
import { ReactComponent as CloseOutlined } from '../../../assets/svg/close.svg';
|
||||||
import ProfilePicture from '../ProfilePicture/ProfilePicture';
|
import ProfilePicture from '../ProfilePicture/ProfilePicture';
|
||||||
import './user-tag.less';
|
import './user-tag.less';
|
||||||
import { UserTags, UserTagSize } from './UserTag.interface';
|
import { UserTags, UserTagSize } from './UserTag.interface';
|
||||||
@ -66,7 +67,14 @@ export const UserTag = ({
|
|||||||
width={toString(width[size])}
|
width={toString(width[size])}
|
||||||
/>
|
/>
|
||||||
<Typography.Text className={fontSizes[size]}>{name}</Typography.Text>
|
<Typography.Text className={fontSizes[size]}>{name}</Typography.Text>
|
||||||
{closable && <CloseOutlined size={width[size]} onClick={onRemove} />}
|
{closable && (
|
||||||
|
<Icon
|
||||||
|
component={CloseOutlined}
|
||||||
|
data-testid="close-icon"
|
||||||
|
size={width[size]}
|
||||||
|
onClick={onRemove}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</Space>
|
</Space>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -63,9 +63,7 @@ describe('UserTag Component', () => {
|
|||||||
|
|
||||||
it('calls onRemove when close icon is clicked', () => {
|
it('calls onRemove when close icon is clicked', () => {
|
||||||
render(<UserTag {...userTagProps} />);
|
render(<UserTag {...userTagProps} />);
|
||||||
const closeIcon = screen
|
const closeIcon = screen.getByTestId('close-icon');
|
||||||
.getByTestId('user-tag')
|
|
||||||
.querySelector('.anticon-close');
|
|
||||||
|
|
||||||
// Simulate click on the close icon
|
// Simulate click on the close icon
|
||||||
closeIcon && fireEvent.click(closeIcon);
|
closeIcon && fireEvent.click(closeIcon);
|
||||||
|
|||||||
@ -51,12 +51,7 @@
|
|||||||
.ant-select-item {
|
.ant-select-item {
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
|
|
||||||
// &:hover {
|
|
||||||
// background-color: @item-hover-bg;
|
|
||||||
// }
|
|
||||||
|
|
||||||
&.selected-option {
|
&.selected-option {
|
||||||
// background-color: @primary-color-1;
|
|
||||||
color: @primary-color;
|
color: @primary-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,14 +111,6 @@
|
|||||||
&.ant-select-open {
|
&.ant-select-open {
|
||||||
.ant-select-selector {
|
.ant-select-selector {
|
||||||
border-color: @primary-color;
|
border-color: @primary-color;
|
||||||
// box-shadow: 0 0 0 2px fade(@primary-color, 20%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.ant-select-disabled {
|
|
||||||
.ant-select-selector {
|
|
||||||
// background-color: @disabled-bg;
|
|
||||||
// color: @disabled-color;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
import Icon from '@ant-design/icons/lib/components/Icon';
|
import Icon from '@ant-design/icons/lib/components/Icon';
|
||||||
import { Popover, Space, Tabs, Typography } from 'antd';
|
import { Popover, Space, Tabs, Typography } from 'antd';
|
||||||
|
import classNames from 'classnames';
|
||||||
import { isArray, isEmpty, noop, toString } from 'lodash';
|
import { isArray, isEmpty, noop, toString } from 'lodash';
|
||||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@ -64,6 +65,7 @@ export const UserTeamSelectableList = ({
|
|||||||
previewSelected = false,
|
previewSelected = false,
|
||||||
listHeight = ADD_USER_CONTAINER_HEIGHT,
|
listHeight = ADD_USER_CONTAINER_HEIGHT,
|
||||||
tooltipText,
|
tooltipText,
|
||||||
|
overlayClassName,
|
||||||
}: UserSelectDropdownProps) => {
|
}: UserSelectDropdownProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [popupVisible, setPopupVisible] = useState(false);
|
const [popupVisible, setPopupVisible] = useState(false);
|
||||||
@ -352,7 +354,10 @@ export const UserTeamSelectableList = ({
|
|||||||
</FocusTrapWithContainer>
|
</FocusTrapWithContainer>
|
||||||
}
|
}
|
||||||
open={popupVisible}
|
open={popupVisible}
|
||||||
overlayClassName="user-team-select-popover card-shadow"
|
overlayClassName={classNames(
|
||||||
|
'user-team-select-popover card-shadow',
|
||||||
|
overlayClassName
|
||||||
|
)}
|
||||||
placement="bottomRight"
|
placement="bottomRight"
|
||||||
showArrow={false}
|
showArrow={false}
|
||||||
trigger="click"
|
trigger="click"
|
||||||
|
|||||||
@ -31,4 +31,5 @@ export interface UserSelectDropdownProps {
|
|||||||
previewSelected?: boolean;
|
previewSelected?: boolean;
|
||||||
listHeight?: number;
|
listHeight?: number;
|
||||||
tooltipText?: string;
|
tooltipText?: string;
|
||||||
|
overlayClassName?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,172 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025 Collate.
|
||||||
|
* Licensed 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 { Select } from 'antd';
|
||||||
|
import { noop } from 'lodash';
|
||||||
|
import type { CustomTagProps } from 'rc-select/lib/BaseSelect';
|
||||||
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
|
import { EntityReference } from '../../../generated/entity/teams/user';
|
||||||
|
import { UserTag } from '../UserTag/UserTag.component';
|
||||||
|
import { UserTagSize } from '../UserTag/UserTag.interface';
|
||||||
|
import { UserTeamSelectableList } from '../UserTeamSelectableList/UserTeamSelectableList.component';
|
||||||
|
import { UserSelectDropdownProps } from '../UserTeamSelectableList/UserTeamSelectableList.interface';
|
||||||
|
import './user-team-selectable-list-search-input.less';
|
||||||
|
|
||||||
|
interface UserTeamSelectableListSearchProps extends UserSelectDropdownProps {
|
||||||
|
disabled?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const UserTeamSelectableListSearchInput: React.FC<UserTeamSelectableListSearchProps> =
|
||||||
|
({
|
||||||
|
disabled,
|
||||||
|
hasPermission,
|
||||||
|
owner,
|
||||||
|
onUpdate = noop,
|
||||||
|
onClose,
|
||||||
|
multiple,
|
||||||
|
label,
|
||||||
|
previewSelected = false,
|
||||||
|
listHeight,
|
||||||
|
tooltipText,
|
||||||
|
}) => {
|
||||||
|
const [popoverVisible, setPopoverVisible] = useState(false);
|
||||||
|
const [selectedUsers, setSelectedUsers] = useState<EntityReference[]>([]);
|
||||||
|
|
||||||
|
const handleFocus = useCallback(() => {
|
||||||
|
setPopoverVisible(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
setPopoverVisible(false);
|
||||||
|
if (onClose) {
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePopoverVisibleChange = (visible: boolean) => {
|
||||||
|
setPopoverVisible(visible);
|
||||||
|
if (!visible && onClose) {
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleUpdate = async (updatedUser?: EntityReference[]) => {
|
||||||
|
if (onUpdate) {
|
||||||
|
setSelectedUsers(updatedUser ?? []);
|
||||||
|
handleClose();
|
||||||
|
onUpdate(updatedUser);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOnChangeSelect = (value: string[]) => {
|
||||||
|
if (onUpdate) {
|
||||||
|
const updatedUser = selectedUsers.filter((item) =>
|
||||||
|
value.includes(item.name ?? '')
|
||||||
|
);
|
||||||
|
|
||||||
|
setSelectedUsers(updatedUser ?? []);
|
||||||
|
handleClose();
|
||||||
|
onUpdate(updatedUser);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectedValues = useMemo(
|
||||||
|
() =>
|
||||||
|
selectedUsers
|
||||||
|
.map((user) => user.name)
|
||||||
|
.filter((name): name is string => Boolean(name)),
|
||||||
|
[selectedUsers]
|
||||||
|
);
|
||||||
|
|
||||||
|
const customTagRender = (props: CustomTagProps) => {
|
||||||
|
const { value, closable, onClose } = props;
|
||||||
|
|
||||||
|
const selectedAssignee = selectedUsers?.find(
|
||||||
|
(option) => option.name === value
|
||||||
|
);
|
||||||
|
|
||||||
|
const tagProps = {
|
||||||
|
id: selectedAssignee?.name ?? value,
|
||||||
|
name: selectedAssignee?.name ?? value,
|
||||||
|
closable: closable,
|
||||||
|
onRemove: onClose,
|
||||||
|
size: UserTagSize.small,
|
||||||
|
isTeam: selectedAssignee?.type === 'team',
|
||||||
|
className: 'assignee-tag',
|
||||||
|
};
|
||||||
|
|
||||||
|
return <UserTag {...tagProps} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectInput = useMemo(() => {
|
||||||
|
return (
|
||||||
|
<Select
|
||||||
|
showSearch
|
||||||
|
className="select-owners"
|
||||||
|
data-testid="select-owners"
|
||||||
|
defaultActiveFirstOption={false}
|
||||||
|
disabled={disabled}
|
||||||
|
filterOption={false}
|
||||||
|
mode="multiple"
|
||||||
|
notFoundContent={null}
|
||||||
|
suffixIcon={null}
|
||||||
|
tagRender={customTagRender}
|
||||||
|
value={selectedValues}
|
||||||
|
onChange={handleOnChangeSelect}
|
||||||
|
onFocus={handleFocus}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}, [
|
||||||
|
disabled,
|
||||||
|
selectedValues,
|
||||||
|
customTagRender,
|
||||||
|
handleOnChangeSelect,
|
||||||
|
handleFocus,
|
||||||
|
]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setSelectedUsers(owner ?? []);
|
||||||
|
}, [owner]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{popoverVisible && (
|
||||||
|
<UserTeamSelectableList
|
||||||
|
hasPermission={hasPermission}
|
||||||
|
label={label}
|
||||||
|
listHeight={listHeight}
|
||||||
|
multiple={multiple}
|
||||||
|
overlayClassName="user-team-selectable-list-search-input-popover"
|
||||||
|
owner={selectedUsers}
|
||||||
|
popoverProps={{
|
||||||
|
open: popoverVisible,
|
||||||
|
onOpenChange: handlePopoverVisibleChange,
|
||||||
|
trigger: 'click',
|
||||||
|
placement: 'bottomLeft',
|
||||||
|
}}
|
||||||
|
previewSelected={previewSelected}
|
||||||
|
tooltipText={tooltipText}
|
||||||
|
onClose={handleClose}
|
||||||
|
onUpdate={handleUpdate}>
|
||||||
|
{/* Have to pass the selectInput as children, so popover can become targetComponent
|
||||||
|
and popover don't overflow on it */}
|
||||||
|
{selectInput}
|
||||||
|
</UserTeamSelectableList>
|
||||||
|
)}
|
||||||
|
{/* Conditionally render the select input, to avoid the UserTeamSelectableList component
|
||||||
|
render unnecessarily */}
|
||||||
|
{!popoverVisible && selectInput}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default UserTeamSelectableListSearchInput;
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025 Collate.
|
||||||
|
* Licensed 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 (reference) url('../../../styles/variables.less');
|
||||||
|
|
||||||
|
.ant-popover.user-team-selectable-list-search-input-popover {
|
||||||
|
width: calc(50vw - 50px);
|
||||||
|
min-width: 260px;
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-owners {
|
||||||
|
.assignee-tag {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-right: 8px;
|
||||||
|
background: @white;
|
||||||
|
padding: 2px 12px;
|
||||||
|
height: 28px;
|
||||||
|
|
||||||
|
border-radius: 6px;
|
||||||
|
gap: 4px;
|
||||||
|
border: 1px solid @grey-300;
|
||||||
|
|
||||||
|
.ant-typography {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: @grey-700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.anticon {
|
||||||
|
color: @grey-400;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-select-selection-item-content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-select-selection-item-remove {
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -39,6 +39,7 @@ export enum FieldTypes {
|
|||||||
DESCRIPTION = 'description',
|
DESCRIPTION = 'description',
|
||||||
TAG_SUGGESTION = 'tag_suggestion',
|
TAG_SUGGESTION = 'tag_suggestion',
|
||||||
USER_TEAM_SELECT = 'user_team_select',
|
USER_TEAM_SELECT = 'user_team_select',
|
||||||
|
USER_TEAM_SELECT_INPUT = 'user_team_select_input',
|
||||||
USER_MULTI_SELECT = 'user_multi_select',
|
USER_MULTI_SELECT = 'user_multi_select',
|
||||||
COLOR_PICKER = 'color_picker',
|
COLOR_PICKER = 'color_picker',
|
||||||
DOMAIN_SELECT = 'domain_select',
|
DOMAIN_SELECT = 'domain_select',
|
||||||
|
|||||||
@ -916,7 +916,7 @@ export const migrateJsonLogic = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
return migrateNode(jsonLogic) as Record<string, unknown>;
|
return migrateNode(jsonLogic) as Record<string, unknown>;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const getFieldsByKeys = (
|
export const getFieldsByKeys = (
|
||||||
keys: EntityReferenceFields[],
|
keys: EntityReferenceFields[],
|
||||||
|
|||||||
@ -49,6 +49,7 @@ import { UserSelectableList } from '../components/common/UserSelectableList/User
|
|||||||
import { UserSelectableListProps } from '../components/common/UserSelectableList/UserSelectableList.interface';
|
import { UserSelectableListProps } from '../components/common/UserSelectableList/UserSelectableList.interface';
|
||||||
import { UserTeamSelectableList } from '../components/common/UserTeamSelectableList/UserTeamSelectableList.component';
|
import { UserTeamSelectableList } from '../components/common/UserTeamSelectableList/UserTeamSelectableList.component';
|
||||||
import { UserSelectDropdownProps } from '../components/common/UserTeamSelectableList/UserTeamSelectableList.interface';
|
import { UserSelectDropdownProps } from '../components/common/UserTeamSelectableList/UserTeamSelectableList.interface';
|
||||||
|
import UserTeamSelectableListSearchInput from '../components/common/UserTeamSelectableListSearchInput/UserTeamSelectableListSearchInput.component';
|
||||||
import { HTTP_STATUS_CODE } from '../constants/Auth.constants';
|
import { HTTP_STATUS_CODE } from '../constants/Auth.constants';
|
||||||
import {
|
import {
|
||||||
FieldProp,
|
FieldProp,
|
||||||
@ -225,6 +226,17 @@ export const getField = (field: FieldProp) => {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case FieldTypes.USER_TEAM_SELECT_INPUT:
|
||||||
|
{
|
||||||
|
fieldElement = (
|
||||||
|
<UserTeamSelectableListSearchInput
|
||||||
|
{...(props as unknown as UserSelectDropdownProps)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
case FieldTypes.USER_MULTI_SELECT:
|
case FieldTypes.USER_MULTI_SELECT:
|
||||||
{
|
{
|
||||||
const { children, ...rest } = props;
|
const { children, ...rest } = props;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user