mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-09-08 16:38:04 +00:00
supported task assignee with owner name in task thread (#17435)
* supported task assigne with owner name in task thread * fix the mis-allignment due to conversation thread present * fix the cypress test and assignee not updating in the task after editing
This commit is contained in:
parent
455e66bc37
commit
def0fcc5eb
@ -19,7 +19,9 @@ import {
|
|||||||
|
|
||||||
const owner = 'admin';
|
const owner = 'admin';
|
||||||
const assignee = 'adam.matthews2';
|
const assignee = 'adam.matthews2';
|
||||||
|
const assigneeDisplayName = 'Adam Matthews';
|
||||||
const secondAssignee = 'aaron_johnson0';
|
const secondAssignee = 'aaron_johnson0';
|
||||||
|
const secondAssigneeDisplayName = 'Aaron Johnson';
|
||||||
|
|
||||||
export type TaskDetails = {
|
export type TaskDetails = {
|
||||||
assignee?: string;
|
assignee?: string;
|
||||||
@ -44,9 +46,14 @@ export const verifyTaskDetails = (
|
|||||||
expect(matches).to.not.be.null;
|
expect(matches).to.not.be.null;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// creator of the task
|
||||||
cy.get('[data-testid="owner-link"]').should('contain', owner);
|
cy.get('[data-testid="owner-link"]').should('contain', owner);
|
||||||
|
|
||||||
cy.get(`[data-testid="${taskAssignee ?? assignee}"]`).should('be.visible');
|
// assignee of the task
|
||||||
|
cy.get('[data-testid="task-assignees"] [data-testid="owner-link"]').should(
|
||||||
|
'contain',
|
||||||
|
taskAssignee ?? assigneeDisplayName
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const editAssignee = () => {
|
export const editAssignee = () => {
|
||||||
@ -71,7 +78,14 @@ export const editAssignee = () => {
|
|||||||
|
|
||||||
verifyResponseStatusCode('@editAssignee', 200);
|
verifyResponseStatusCode('@editAssignee', 200);
|
||||||
|
|
||||||
cy.get(`[data-testid="${assignee}"]`).should('be.visible');
|
cy.get('[data-testid="task-assignees"] [data-testid="owner-link"]').should(
|
||||||
|
'contain',
|
||||||
|
assigneeDisplayName
|
||||||
|
);
|
||||||
|
cy.get('[data-testid="task-assignees"] [data-testid="owner-link"]').should(
|
||||||
|
'contain',
|
||||||
|
secondAssigneeDisplayName
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createDescriptionTask = (
|
export const createDescriptionTask = (
|
||||||
|
@ -369,9 +369,10 @@ describe('Task flow should work', { tags: 'DataAssets' }, () => {
|
|||||||
verifyResponseStatusCode('@taskFeed', 200);
|
verifyResponseStatusCode('@taskFeed', 200);
|
||||||
|
|
||||||
// verify the task details
|
// verify the task details
|
||||||
verifyTaskDetails(/#(\d+) Request to update description for/, USER_NAME);
|
verifyTaskDetails(
|
||||||
|
/#(\d+) Request to update description for/,
|
||||||
cy.get(`[data-testid="${USER_NAME}"]`).should('be.visible');
|
USER_DETAILS.firstName
|
||||||
|
);
|
||||||
|
|
||||||
// Accept the description suggestion which is created
|
// Accept the description suggestion which is created
|
||||||
cy.get('.ant-btn-compact-first-item').contains('Accept Suggestion').click();
|
cy.get('.ant-btn-compact-first-item').contains('Accept Suggestion').click();
|
||||||
|
@ -245,6 +245,21 @@ const ActivityFeedProvider = ({ children, user }: Props) => {
|
|||||||
setEntityThread([...threads]);
|
setEntityThread([...threads]);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const updateEntityThread = useCallback(
|
||||||
|
(thread: Thread) => {
|
||||||
|
setEntityThread((prev) => {
|
||||||
|
return prev.map((threadItem) => {
|
||||||
|
if (threadItem.id === thread.id) {
|
||||||
|
return thread;
|
||||||
|
} else {
|
||||||
|
return threadItem;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[setEntityThread]
|
||||||
|
);
|
||||||
|
|
||||||
const deleteFeed = useCallback(
|
const deleteFeed = useCallback(
|
||||||
async (threadId: string, postId: string, isThread: boolean) => {
|
async (threadId: string, postId: string, isThread: boolean) => {
|
||||||
if (isThread) {
|
if (isThread) {
|
||||||
@ -457,6 +472,7 @@ const ActivityFeedProvider = ({ children, user }: Props) => {
|
|||||||
hideDrawer,
|
hideDrawer,
|
||||||
updateEditorFocus,
|
updateEditorFocus,
|
||||||
setActiveThread,
|
setActiveThread,
|
||||||
|
updateEntityThread,
|
||||||
entityPaging,
|
entityPaging,
|
||||||
userId: user ?? currentUser?.id ?? '',
|
userId: user ?? currentUser?.id ?? '',
|
||||||
testCaseResolutionStatus,
|
testCaseResolutionStatus,
|
||||||
@ -481,6 +497,7 @@ const ActivityFeedProvider = ({ children, user }: Props) => {
|
|||||||
hideDrawer,
|
hideDrawer,
|
||||||
updateEditorFocus,
|
updateEditorFocus,
|
||||||
setActiveThread,
|
setActiveThread,
|
||||||
|
updateEntityThread,
|
||||||
entityPaging,
|
entityPaging,
|
||||||
user,
|
user,
|
||||||
currentUser,
|
currentUser,
|
||||||
|
@ -34,6 +34,7 @@ export interface ActivityFeedProviderContextType {
|
|||||||
focusReplyEditor: boolean;
|
focusReplyEditor: boolean;
|
||||||
entityPaging: Paging;
|
entityPaging: Paging;
|
||||||
setActiveThread: (thread?: Thread) => void;
|
setActiveThread: (thread?: Thread) => void;
|
||||||
|
updateEntityThread: (thread: Thread) => void;
|
||||||
userId: string;
|
userId: string;
|
||||||
deleteFeed: (
|
deleteFeed: (
|
||||||
threadId: string,
|
threadId: string,
|
||||||
|
@ -11,6 +11,11 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
TaskType,
|
||||||
|
ThreadTaskStatus,
|
||||||
|
} from '../../../generated/entity/feed/thread';
|
||||||
|
|
||||||
export const mockThreadData = [
|
export const mockThreadData = [
|
||||||
{
|
{
|
||||||
id: '465b2dfb-300e-45f5-a1a6-e19c6225e9e7',
|
id: '465b2dfb-300e-45f5-a1a6-e19c6225e9e7',
|
||||||
@ -26,6 +31,32 @@ export const mockThreadData = [
|
|||||||
postsCount: 0,
|
postsCount: 0,
|
||||||
posts: [],
|
posts: [],
|
||||||
relativeDay: 'Today',
|
relativeDay: 'Today',
|
||||||
|
task: {
|
||||||
|
id: 153,
|
||||||
|
type: TaskType.RequestTag,
|
||||||
|
assignees: [
|
||||||
|
{
|
||||||
|
id: 'ef1b9e8a-75ba-4c12-9874-034c135be925',
|
||||||
|
type: 'team',
|
||||||
|
name: 'Sales',
|
||||||
|
fullyQualifiedName: 'Sales',
|
||||||
|
displayName: 'Sales',
|
||||||
|
deleted: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '83bd6004-9237-47a1-b917-ef006b3192d7',
|
||||||
|
type: 'user',
|
||||||
|
name: 'aaron_johnson0',
|
||||||
|
fullyQualifiedName: 'aaron_johnson0',
|
||||||
|
displayName: 'Aaron Johnson',
|
||||||
|
deleted: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
status: ThreadTaskStatus.Open,
|
||||||
|
oldValue: '[]',
|
||||||
|
suggestion:
|
||||||
|
'[{"tagFQN":"PII.None","source":"Classification","name":"None","description":"Non PII"}]',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '40c2faec-0159-4d86-9b15-c17f3e1c081b',
|
id: '40c2faec-0159-4d86-9b15-c17f3e1c081b',
|
||||||
|
@ -11,7 +11,12 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { findByTestId, queryByTestId, render } from '@testing-library/react';
|
import {
|
||||||
|
findByTestId,
|
||||||
|
getByText,
|
||||||
|
queryByTestId,
|
||||||
|
render,
|
||||||
|
} from '@testing-library/react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import { mockThreadData } from './ActivityThread.mock';
|
import { mockThreadData } from './ActivityThread.mock';
|
||||||
@ -50,6 +55,10 @@ jest.mock('../ActivityFeedCard/FeedCardFooter/FeedCardFooter', () => {
|
|||||||
return jest.fn().mockReturnValue(<p>FeedCardFooter</p>);
|
return jest.fn().mockReturnValue(<p>FeedCardFooter</p>);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
jest.mock('../../common/OwnerLabel/OwnerLabel.component', () => ({
|
||||||
|
OwnerLabel: jest.fn().mockReturnValue(<div>OwnerLabel</div>),
|
||||||
|
}));
|
||||||
|
|
||||||
describe('Test ActivityThreadList Component', () => {
|
describe('Test ActivityThreadList Component', () => {
|
||||||
it('Check if it has all child elements', async () => {
|
it('Check if it has all child elements', async () => {
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
@ -145,4 +154,16 @@ describe('Test ActivityThreadList Component', () => {
|
|||||||
expect(thread2MainMessage).toBeInTheDocument();
|
expect(thread2MainMessage).toBeInTheDocument();
|
||||||
expect(thread2QuickReplyEditor).toBeInTheDocument();
|
expect(thread2QuickReplyEditor).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should render task assignee when there is task', async () => {
|
||||||
|
const { container } = render(
|
||||||
|
<ActivityThreadList {...mockActivityThreadListProp} />,
|
||||||
|
{
|
||||||
|
wrapper: MemoryRouter,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(getByText(container, 'label.assignee-plural:')).toBeInTheDocument();
|
||||||
|
expect(getByText(container, 'OwnerLabel')).toBeInTheDocument();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
* 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 { Card, Space } from 'antd';
|
import { Card, Typography } from 'antd';
|
||||||
import { isEqual } from 'lodash';
|
import { isEqual } from 'lodash';
|
||||||
import React, { FC, Fragment } from 'react';
|
import React, { FC, Fragment } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@ -29,7 +29,7 @@ import {
|
|||||||
} from '../../../generated/entity/feed/thread';
|
} from '../../../generated/entity/feed/thread';
|
||||||
import { getFeedListWithRelativeDays } from '../../../utils/FeedUtils';
|
import { getFeedListWithRelativeDays } from '../../../utils/FeedUtils';
|
||||||
import { getTaskDetailPath } from '../../../utils/TasksUtils';
|
import { getTaskDetailPath } from '../../../utils/TasksUtils';
|
||||||
import AssigneeList from '../../common/AssigneeList/AssigneeList';
|
import { OwnerLabel } from '../../common/OwnerLabel/OwnerLabel.component';
|
||||||
import ActivityFeedCard from '../ActivityFeedCard/ActivityFeedCard';
|
import ActivityFeedCard from '../ActivityFeedCard/ActivityFeedCard';
|
||||||
import FeedCardFooter from '../ActivityFeedCard/FeedCardFooter/FeedCardFooter';
|
import FeedCardFooter from '../ActivityFeedCard/FeedCardFooter/FeedCardFooter';
|
||||||
import ActivityFeedEditor from '../ActivityFeedEditor/ActivityFeedEditor';
|
import ActivityFeedEditor from '../ActivityFeedEditor/ActivityFeedEditor';
|
||||||
@ -166,14 +166,12 @@ const ActivityThreadList: FC<ActivityThreadListProp> = ({
|
|||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
{thread.task && (
|
{thread.task && (
|
||||||
<Space wrap className="m-y-xs" size={4}>
|
<div className="d-flex m-y-xs gap-2">
|
||||||
<span className="text-grey-muted">
|
<Typography.Text className="text-grey-muted">
|
||||||
{t('label.assignee-plural')}:{' '}
|
{t('label.assignee-plural')}:{' '}
|
||||||
</span>
|
</Typography.Text>
|
||||||
<AssigneeList
|
<OwnerLabel owners={thread.task.assignees} />
|
||||||
assignees={thread.task.assignees || []}
|
</div>
|
||||||
/>
|
|
||||||
</Space>
|
|
||||||
)}
|
)}
|
||||||
</Card>
|
</Card>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
@ -34,9 +34,9 @@ jest.mock('../ActivityFeedProvider/ActivityFeedProvider', () => ({
|
|||||||
default: 'ActivityFeedProvider',
|
default: 'ActivityFeedProvider',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('../../../components/common/AssigneeList/AssigneeList', () => {
|
jest.mock('../../common/OwnerLabel/OwnerLabel.component', () => ({
|
||||||
return jest.fn().mockImplementation(() => <p>AssigneeList</p>);
|
OwnerLabel: jest.fn().mockReturnValue(<p>OwnerLabel</p>),
|
||||||
});
|
}));
|
||||||
|
|
||||||
jest.mock('../../../components/common/PopOverCard/EntityPopOverCard', () => {
|
jest.mock('../../../components/common/PopOverCard/EntityPopOverCard', () => {
|
||||||
return jest.fn().mockImplementation(({ children }) => children);
|
return jest.fn().mockImplementation(({ children }) => children);
|
||||||
@ -102,4 +102,15 @@ describe('Test TaskFeedCard Component', () => {
|
|||||||
expect(screen.getByTestId('task-status-icon-open')).toBeInTheDocument();
|
expect(screen.getByTestId('task-status-icon-open')).toBeInTheDocument();
|
||||||
expect(screen.getByTestId('redirect-task-button-link')).toBeInTheDocument();
|
expect(screen.getByTestId('redirect-task-button-link')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Should render OwnerLabel when show thread is true', async () => {
|
||||||
|
await act(async () => {
|
||||||
|
render(<TaskFeedCard {...mockProps} />, {
|
||||||
|
wrapper: MemoryRouter,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(screen.getByText('label.assignee-plural:')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('OwnerLabel')).toBeInTheDocument();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -20,7 +20,6 @@ import { useHistory } from 'react-router-dom';
|
|||||||
import { ReactComponent as TaskCloseIcon } from '../../../assets/svg/ic-close-task.svg';
|
import { ReactComponent as TaskCloseIcon } from '../../../assets/svg/ic-close-task.svg';
|
||||||
import { ReactComponent as TaskOpenIcon } from '../../../assets/svg/ic-open-task.svg';
|
import { ReactComponent as TaskOpenIcon } from '../../../assets/svg/ic-open-task.svg';
|
||||||
import { ReactComponent as ThreadIcon } from '../../../assets/svg/thread.svg';
|
import { ReactComponent as ThreadIcon } from '../../../assets/svg/thread.svg';
|
||||||
import AssigneeList from '../../../components/common/AssigneeList/AssigneeList';
|
|
||||||
import EntityPopOverCard from '../../../components/common/PopOverCard/EntityPopOverCard';
|
import EntityPopOverCard from '../../../components/common/PopOverCard/EntityPopOverCard';
|
||||||
import UserPopOverCard from '../../../components/common/PopOverCard/UserPopOverCard';
|
import UserPopOverCard from '../../../components/common/PopOverCard/UserPopOverCard';
|
||||||
import {
|
import {
|
||||||
@ -38,6 +37,7 @@ import { getEntityFQN, getEntityType } from '../../../utils/FeedUtils';
|
|||||||
|
|
||||||
import { TASK_TYPES } from '../../../constants/Task.constant';
|
import { TASK_TYPES } from '../../../constants/Task.constant';
|
||||||
import { getTaskDetailPath } from '../../../utils/TasksUtils';
|
import { getTaskDetailPath } from '../../../utils/TasksUtils';
|
||||||
|
import { OwnerLabel } from '../../common/OwnerLabel/OwnerLabel.component';
|
||||||
import ProfilePicture from '../../common/ProfilePicture/ProfilePicture';
|
import ProfilePicture from '../../common/ProfilePicture/ProfilePicture';
|
||||||
import { useActivityFeedProvider } from '../ActivityFeedProvider/ActivityFeedProvider';
|
import { useActivityFeedProvider } from '../ActivityFeedProvider/ActivityFeedProvider';
|
||||||
import ActivityFeedActions from '../Shared/ActivityFeedActions';
|
import ActivityFeedActions from '../Shared/ActivityFeedActions';
|
||||||
@ -206,7 +206,7 @@ const TaskFeedCard = ({
|
|||||||
</Col>
|
</Col>
|
||||||
{!showThread ? (
|
{!showThread ? (
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<div className="d-flex items-center p-l-lg gap-2">
|
<div className="d-flex items-start p-l-lg gap-2">
|
||||||
{postLength > 0 && (
|
{postLength > 0 && (
|
||||||
<>
|
<>
|
||||||
<div className="thread-users-profile-pic">
|
<div className="thread-users-profile-pic">
|
||||||
@ -228,24 +228,23 @@ const TaskFeedCard = ({
|
|||||||
className="d-flex items-center thread-count cursor-pointer m-l-xs"
|
className="d-flex items-center thread-count cursor-pointer m-l-xs"
|
||||||
onClick={!hidePopover ? showReplies : noop}>
|
onClick={!hidePopover ? showReplies : noop}>
|
||||||
<ThreadIcon width={20} />{' '}
|
<ThreadIcon width={20} />{' '}
|
||||||
<span className="text-xs p-l-xss">{postLength}</span>
|
<span className="text-xs p-t-xss p-l-xss">
|
||||||
|
{postLength}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Typography.Text
|
<Typography.Text
|
||||||
className={
|
className={classNames(
|
||||||
|
'p-t-xss',
|
||||||
postLength > 0
|
postLength > 0
|
||||||
? 'm-l-sm text-sm text-grey-muted'
|
? 'm-l-sm text-sm text-grey-muted'
|
||||||
: 'text-sm text-grey-muted'
|
: 'text-sm text-grey-muted'
|
||||||
}>
|
)}>
|
||||||
{`${t('label.assignee-plural')}: `}
|
{`${t('label.assignee-plural')}: `}
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
<AssigneeList
|
<OwnerLabel className="p-t-05" owners={feed?.task?.assignees} />
|
||||||
assignees={feed?.task?.assignees || []}
|
|
||||||
className="d-flex gap-1"
|
|
||||||
showUserName={false}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
) : null}
|
) : null}
|
||||||
|
@ -54,10 +54,6 @@ jest.mock('../../../ActivityFeed/ActivityFeedEditor/ActivityFeedEditor', () => {
|
|||||||
));
|
));
|
||||||
});
|
});
|
||||||
|
|
||||||
jest.mock('../../../common/AssigneeList/AssigneeList', () => {
|
|
||||||
return jest.fn().mockImplementation(() => <p>AssigneeList</p>);
|
|
||||||
});
|
|
||||||
|
|
||||||
jest.mock('../../../common/OwnerLabel/OwnerLabel.component', () => ({
|
jest.mock('../../../common/OwnerLabel/OwnerLabel.component', () => ({
|
||||||
OwnerLabel: jest.fn().mockImplementation(() => <p>OwnerLabel</p>),
|
OwnerLabel: jest.fn().mockImplementation(() => <p>OwnerLabel</p>),
|
||||||
}));
|
}));
|
||||||
@ -171,6 +167,16 @@ describe('Test TaskFeedCard component', () => {
|
|||||||
expect(activityFeedCard).toBeInTheDocument();
|
expect(activityFeedCard).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Should render the assignee and creator of task', async () => {
|
||||||
|
render(<TaskTab {...mockProps} />, {
|
||||||
|
wrapper: MemoryRouter,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(screen.getByText('label.assignee-plural:')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('label.created-by:')).toBeInTheDocument();
|
||||||
|
expect(screen.getAllByText('OwnerLabel')).toHaveLength(2);
|
||||||
|
});
|
||||||
|
|
||||||
it('should not render task action button to the task owner if task has reviewer', async () => {
|
it('should not render task action button to the task owner if task has reviewer', async () => {
|
||||||
render(<TaskTab {...mockProps} hasGlossaryReviewer />, {
|
render(<TaskTab {...mockProps} hasGlossaryReviewer />, {
|
||||||
wrapper: MemoryRouter,
|
wrapper: MemoryRouter,
|
||||||
|
@ -103,7 +103,6 @@ import ActivityFeedEditor, {
|
|||||||
EditorContentRef,
|
EditorContentRef,
|
||||||
} from '../../../ActivityFeed/ActivityFeedEditor/ActivityFeedEditor';
|
} from '../../../ActivityFeed/ActivityFeedEditor/ActivityFeedEditor';
|
||||||
import { useActivityFeedProvider } from '../../../ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
|
import { useActivityFeedProvider } from '../../../ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
|
||||||
import AssigneeList from '../../../common/AssigneeList/AssigneeList';
|
|
||||||
import InlineEdit from '../../../common/InlineEdit/InlineEdit.component';
|
import InlineEdit from '../../../common/InlineEdit/InlineEdit.component';
|
||||||
import { OwnerLabel } from '../../../common/OwnerLabel/OwnerLabel.component';
|
import { OwnerLabel } from '../../../common/OwnerLabel/OwnerLabel.component';
|
||||||
import EntityPopOverCard from '../../../common/PopOverCard/EntityPopOverCard';
|
import EntityPopOverCard from '../../../common/PopOverCard/EntityPopOverCard';
|
||||||
@ -144,7 +143,7 @@ export const TaskTab = ({
|
|||||||
const { isAdminUser } = useAuth();
|
const { isAdminUser } = useAuth();
|
||||||
const {
|
const {
|
||||||
postFeed,
|
postFeed,
|
||||||
setActiveThread,
|
updateEntityThread,
|
||||||
fetchUpdatedThread,
|
fetchUpdatedThread,
|
||||||
updateTestCaseIncidentStatus,
|
updateTestCaseIncidentStatus,
|
||||||
testCaseResolutionStatus,
|
testCaseResolutionStatus,
|
||||||
@ -233,7 +232,7 @@ export const TaskTab = ({
|
|||||||
const [comment, setComment] = useState('');
|
const [comment, setComment] = useState('');
|
||||||
const [isEditAssignee, setIsEditAssignee] = useState<boolean>(false);
|
const [isEditAssignee, setIsEditAssignee] = useState<boolean>(false);
|
||||||
const [options, setOptions] = useState<Option[]>([]);
|
const [options, setOptions] = useState<Option[]>([]);
|
||||||
|
const [isAssigneeLoading, setIsAssigneeLoading] = useState<boolean>(false);
|
||||||
const { initialAssignees, assigneeOptions } = useMemo(() => {
|
const { initialAssignees, assigneeOptions } = useMemo(() => {
|
||||||
const initialAssignees = generateOptions(taskDetails?.assignees ?? []);
|
const initialAssignees = generateOptions(taskDetails?.assignees ?? []);
|
||||||
const assigneeOptions = unionBy(
|
const assigneeOptions = unionBy(
|
||||||
@ -773,6 +772,7 @@ export const TaskTab = ({
|
|||||||
}, [taskDetails, isTaskDescription]);
|
}, [taskDetails, isTaskDescription]);
|
||||||
|
|
||||||
const handleAssigneeUpdate = async () => {
|
const handleAssigneeUpdate = async () => {
|
||||||
|
setIsAssigneeLoading(true);
|
||||||
const updatedTaskThread = {
|
const updatedTaskThread = {
|
||||||
...taskThread,
|
...taskThread,
|
||||||
task: {
|
task: {
|
||||||
@ -787,9 +787,11 @@ export const TaskTab = ({
|
|||||||
const patch = compare(taskThread, updatedTaskThread);
|
const patch = compare(taskThread, updatedTaskThread);
|
||||||
const data = await updateThread(taskThread.id, patch);
|
const data = await updateThread(taskThread.id, patch);
|
||||||
setIsEditAssignee(false);
|
setIsEditAssignee(false);
|
||||||
setActiveThread(data);
|
updateEntityThread(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
showErrorToast(error as AxiosError);
|
showErrorToast(error as AxiosError);
|
||||||
|
} finally {
|
||||||
|
setIsAssigneeLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -806,12 +808,13 @@ export const TaskTab = ({
|
|||||||
<TaskTabIncidentManagerHeader thread={taskThread} />
|
<TaskTabIncidentManagerHeader thread={taskThread} />
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
className={classNames('d-flex justify-between', {
|
className={classNames('d-flex justify-between flex-wrap gap-2', {
|
||||||
'flex-column': isEditAssignee,
|
'flex-column': isEditAssignee,
|
||||||
})}>
|
})}>
|
||||||
<div className={classNames('gap-2', { 'flex-center': !isEditAssignee })}>
|
<div className="d-flex gap-2" data-testid="task-assignees">
|
||||||
{isEditAssignee ? (
|
{isEditAssignee ? (
|
||||||
<Form
|
<Form
|
||||||
|
className="w-full"
|
||||||
form={assigneesForm}
|
form={assigneesForm}
|
||||||
layout="vertical"
|
layout="vertical"
|
||||||
onFinish={handleAssigneeUpdate}>
|
onFinish={handleAssigneeUpdate}>
|
||||||
@ -830,6 +833,7 @@ export const TaskTab = ({
|
|||||||
<InlineEdit
|
<InlineEdit
|
||||||
className="assignees-edit-input"
|
className="assignees-edit-input"
|
||||||
direction="horizontal"
|
direction="horizontal"
|
||||||
|
isLoading={isAssigneeLoading}
|
||||||
onCancel={() => {
|
onCancel={() => {
|
||||||
setIsEditAssignee(false);
|
setIsEditAssignee(false);
|
||||||
assigneesForm.setFieldValue('assignees', initialAssignees);
|
assigneesForm.setFieldValue('assignees', initialAssignees);
|
||||||
@ -859,15 +863,12 @@ export const TaskTab = ({
|
|||||||
<Typography.Text className="text-grey-muted">
|
<Typography.Text className="text-grey-muted">
|
||||||
{t('label.assignee-plural')}:{' '}
|
{t('label.assignee-plural')}:{' '}
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
<AssigneeList
|
<OwnerLabel owners={taskDetails?.assignees} />
|
||||||
assignees={taskDetails?.assignees ?? []}
|
|
||||||
showUserName={false}
|
|
||||||
/>
|
|
||||||
{(isCreator || hasEditAccess) &&
|
{(isCreator || hasEditAccess) &&
|
||||||
!isTaskClosed &&
|
!isTaskClosed &&
|
||||||
owners.length === 0 ? (
|
owners.length === 0 ? (
|
||||||
<Button
|
<Button
|
||||||
className="flex-center p-0"
|
className="flex-center p-0 h-auto"
|
||||||
data-testid="edit-assignees"
|
data-testid="edit-assignees"
|
||||||
icon={<EditIcon color={DE_ACTIVE_COLOR} width="14px" />}
|
icon={<EditIcon color={DE_ACTIVE_COLOR} width="14px" />}
|
||||||
size="small"
|
size="small"
|
||||||
@ -878,7 +879,7 @@ export const TaskTab = ({
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className={classNames('gap-2', { 'flex-center': !isEditAssignee })}>
|
<div className="d-flex gap-2">
|
||||||
<Typography.Text className="text-grey-muted">
|
<Typography.Text className="text-grey-muted">
|
||||||
{t('label.created-by')}:{' '}
|
{t('label.created-by')}:{' '}
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
|
@ -21,7 +21,6 @@ import { TestCaseResolutionStatusTypes } from '../../../../generated/tests/testC
|
|||||||
import { formatDateTime } from '../../../../utils/date-time/DateTimeUtils';
|
import { formatDateTime } from '../../../../utils/date-time/DateTimeUtils';
|
||||||
import { getEntityName } from '../../../../utils/EntityUtils';
|
import { getEntityName } from '../../../../utils/EntityUtils';
|
||||||
import { useActivityFeedProvider } from '../../../ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
|
import { useActivityFeedProvider } from '../../../ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
|
||||||
import AssigneeList from '../../../common/AssigneeList/AssigneeList';
|
|
||||||
import { OwnerLabel } from '../../../common/OwnerLabel/OwnerLabel.component';
|
import { OwnerLabel } from '../../../common/OwnerLabel/OwnerLabel.component';
|
||||||
import RichTextEditorPreviewer from '../../../common/RichTextEditor/RichTextEditorPreviewer';
|
import RichTextEditorPreviewer from '../../../common/RichTextEditor/RichTextEditorPreviewer';
|
||||||
import Severity from '../../../DataQuality/IncidentManager/Severity/Severity.component';
|
import Severity from '../../../DataQuality/IncidentManager/Severity/Severity.component';
|
||||||
@ -136,7 +135,7 @@ const TaskTabIncidentManagerHeader = ({ thread }: { thread: Thread }) => {
|
|||||||
isEmpty(thread.task?.assignees) ? (
|
isEmpty(thread.task?.assignees) ? (
|
||||||
NO_DATA_PLACEHOLDER
|
NO_DATA_PLACEHOLDER
|
||||||
) : (
|
) : (
|
||||||
<AssigneeList assignees={thread.task?.assignees ?? []} />
|
<OwnerLabel owners={thread.task?.assignees} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="gap-2 flex-center">
|
<div className="gap-2 flex-center">
|
||||||
|
@ -151,9 +151,6 @@ jest.mock('../../../common/OwnerLabel/OwnerLabel.component', () => {
|
|||||||
.mockImplementation(() => <div>OwnerLabel.component</div>),
|
.mockImplementation(() => <div>OwnerLabel.component</div>),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
jest.mock('../../../common/AssigneeList/AssigneeList', () => {
|
|
||||||
return jest.fn().mockImplementation(() => <div>AssigneeList.component</div>);
|
|
||||||
});
|
|
||||||
jest.mock(
|
jest.mock(
|
||||||
'../../../DataQuality/IncidentManager/Severity/Severity.component',
|
'../../../DataQuality/IncidentManager/Severity/Severity.component',
|
||||||
() => {
|
() => {
|
||||||
@ -177,10 +174,7 @@ describe('Test TaskTabIncidentManagerHeader component', () => {
|
|||||||
await screen.findByTestId('task-resolution-steps')
|
await screen.findByTestId('task-resolution-steps')
|
||||||
).toBeInTheDocument();
|
).toBeInTheDocument();
|
||||||
expect(await screen.findByTestId('failure-reason')).toBeInTheDocument();
|
expect(await screen.findByTestId('failure-reason')).toBeInTheDocument();
|
||||||
expect(await screen.findByText('OwnerLabel.component')).toBeInTheDocument();
|
expect(await screen.findAllByText('OwnerLabel.component')).toHaveLength(2);
|
||||||
expect(
|
|
||||||
await screen.findByText('AssigneeList.component')
|
|
||||||
).toBeInTheDocument();
|
|
||||||
expect(await screen.findByText('Severity.component')).toBeInTheDocument();
|
expect(await screen.findByText('Severity.component')).toBeInTheDocument();
|
||||||
expect(
|
expect(
|
||||||
await screen.findByText('RichTextEditorPreviewer.component')
|
await screen.findByText('RichTextEditorPreviewer.component')
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2023 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 { HTMLAttributes } from 'react';
|
|
||||||
import { EntityReference } from '../../../generated/entity/type';
|
|
||||||
|
|
||||||
export interface AssigneeListProps extends HTMLAttributes<HTMLDivElement> {
|
|
||||||
assignees: EntityReference[];
|
|
||||||
showUserName?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum UserTeam {
|
|
||||||
User = 'user',
|
|
||||||
Team = 'team',
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2022 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 React, { FC } from 'react';
|
|
||||||
import { getEntityName } from '../../../utils/EntityUtils';
|
|
||||||
import UserPopOverCard from '../PopOverCard/UserPopOverCard';
|
|
||||||
import { AssigneeListProps, UserTeam } from './AssigneeList.interface';
|
|
||||||
|
|
||||||
const AssigneeList: FC<AssigneeListProps> = ({
|
|
||||||
assignees,
|
|
||||||
showUserName = true,
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<div className="d-flex gap-1 flex-wrap">
|
|
||||||
{assignees.map((assignee) => (
|
|
||||||
<UserPopOverCard
|
|
||||||
displayName={getEntityName(assignee)}
|
|
||||||
key={assignee.name}
|
|
||||||
showUserName={showUserName}
|
|
||||||
type={assignee.type as UserTeam}
|
|
||||||
userName={assignee.name ?? ''}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AssigneeList;
|
|
@ -134,7 +134,7 @@ export const OwnerLabel = ({
|
|||||||
})}
|
})}
|
||||||
{remainingOwnersCount > 0 && (
|
{remainingOwnersCount > 0 && (
|
||||||
<Button
|
<Button
|
||||||
className="more-owners-button text-xs"
|
className="more-owners-button text-xs h-auto"
|
||||||
size="small"
|
size="small"
|
||||||
type="link"
|
type="link"
|
||||||
onClick={() => setShowAllOwners(!showAllOwners)}>
|
onClick={() => setShowAllOwners(!showAllOwners)}>
|
||||||
|
@ -33,6 +33,7 @@ import {
|
|||||||
TERM_ADMIN,
|
TERM_ADMIN,
|
||||||
} from '../../../constants/constants';
|
} from '../../../constants/constants';
|
||||||
import { TabSpecificField } from '../../../enums/entity.enum';
|
import { TabSpecificField } from '../../../enums/entity.enum';
|
||||||
|
import { OwnerType } from '../../../enums/user.enum';
|
||||||
import { EntityReference } from '../../../generated/type/entityReference';
|
import { EntityReference } from '../../../generated/type/entityReference';
|
||||||
import { useApplicationStore } from '../../../hooks/useApplicationStore';
|
import { useApplicationStore } from '../../../hooks/useApplicationStore';
|
||||||
import { useUserProfile } from '../../../hooks/user-profile/useUserProfile';
|
import { useUserProfile } from '../../../hooks/user-profile/useUserProfile';
|
||||||
@ -40,7 +41,6 @@ import { getUserByName } from '../../../rest/userAPI';
|
|||||||
import { getNonDeletedTeams } from '../../../utils/CommonUtils';
|
import { getNonDeletedTeams } from '../../../utils/CommonUtils';
|
||||||
import { getEntityName } from '../../../utils/EntityUtils';
|
import { getEntityName } from '../../../utils/EntityUtils';
|
||||||
import { getUserWithImage } from '../../../utils/UserDataUtils';
|
import { getUserWithImage } from '../../../utils/UserDataUtils';
|
||||||
import { UserTeam } from '../AssigneeList/AssigneeList.interface';
|
|
||||||
import Loader from '../Loader/Loader';
|
import Loader from '../Loader/Loader';
|
||||||
import ProfilePicture from '../ProfilePicture/ProfilePicture';
|
import ProfilePicture from '../ProfilePicture/ProfilePicture';
|
||||||
|
|
||||||
@ -107,12 +107,12 @@ const UserRoles = React.memo(({ userName }: { userName: string }) => {
|
|||||||
const PopoverContent = React.memo(
|
const PopoverContent = React.memo(
|
||||||
({
|
({
|
||||||
userName,
|
userName,
|
||||||
type = UserTeam.User,
|
type = OwnerType.USER,
|
||||||
}: {
|
}: {
|
||||||
userName: string;
|
userName: string;
|
||||||
type: UserTeam;
|
type: OwnerType;
|
||||||
}) => {
|
}) => {
|
||||||
const isTeam = type === UserTeam.Team;
|
const isTeam = type === OwnerType.TEAM;
|
||||||
const [, , user = {}] = useUserProfile({
|
const [, , user = {}] = useUserProfile({
|
||||||
permission: true,
|
permission: true,
|
||||||
name: userName,
|
name: userName,
|
||||||
@ -175,18 +175,18 @@ const PopoverTitle = React.memo(
|
|||||||
({
|
({
|
||||||
userName,
|
userName,
|
||||||
profilePicture,
|
profilePicture,
|
||||||
type = UserTeam.User,
|
type = OwnerType.USER,
|
||||||
}: {
|
}: {
|
||||||
userName: string;
|
userName: string;
|
||||||
profilePicture: JSX.Element;
|
profilePicture: JSX.Element;
|
||||||
type: UserTeam;
|
type: OwnerType;
|
||||||
}) => {
|
}) => {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
const [, , userData] = useUserProfile({
|
const [, , userData] = useUserProfile({
|
||||||
permission: true,
|
permission: true,
|
||||||
name: userName,
|
name: userName,
|
||||||
isTeam: type === UserTeam.Team,
|
isTeam: type === OwnerType.TEAM,
|
||||||
});
|
});
|
||||||
|
|
||||||
const onTitleClickHandler = (path: string) => {
|
const onTitleClickHandler = (path: string) => {
|
||||||
@ -221,7 +221,7 @@ const PopoverTitle = React.memo(
|
|||||||
interface Props extends HTMLAttributes<HTMLDivElement> {
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
||||||
userName: string;
|
userName: string;
|
||||||
displayName?: ReactNode;
|
displayName?: ReactNode;
|
||||||
type?: UserTeam;
|
type?: OwnerType;
|
||||||
showUserName?: boolean;
|
showUserName?: boolean;
|
||||||
showUserProfile?: boolean;
|
showUserProfile?: boolean;
|
||||||
profileWidth?: number;
|
profileWidth?: number;
|
||||||
@ -231,7 +231,7 @@ interface Props extends HTMLAttributes<HTMLDivElement> {
|
|||||||
const UserPopOverCard: FC<Props> = ({
|
const UserPopOverCard: FC<Props> = ({
|
||||||
userName,
|
userName,
|
||||||
displayName,
|
displayName,
|
||||||
type = UserTeam.User,
|
type = OwnerType.USER,
|
||||||
showUserName = false,
|
showUserName = false,
|
||||||
showUserProfile = true,
|
showUserProfile = true,
|
||||||
children,
|
children,
|
||||||
@ -241,7 +241,7 @@ const UserPopOverCard: FC<Props> = ({
|
|||||||
const profilePicture = (
|
const profilePicture = (
|
||||||
<ProfilePicture
|
<ProfilePicture
|
||||||
avatarType="outlined"
|
avatarType="outlined"
|
||||||
isTeam={type === UserTeam.Team}
|
isTeam={type === OwnerType.TEAM}
|
||||||
name={userName}
|
name={userName}
|
||||||
width={`${profileWidth}`}
|
width={`${profileWidth}`}
|
||||||
/>
|
/>
|
||||||
@ -271,7 +271,7 @@ const UserPopOverCard: FC<Props> = ({
|
|||||||
)}
|
)}
|
||||||
data-testid={userName}
|
data-testid={userName}
|
||||||
to={
|
to={
|
||||||
type === UserTeam.Team
|
type === OwnerType.TEAM
|
||||||
? getTeamAndUserDetailsPath(userName)
|
? getTeamAndUserDetailsPath(userName)
|
||||||
: getUserPath(userName ?? '')
|
: getUserPath(userName ?? '')
|
||||||
}>
|
}>
|
||||||
|
@ -501,6 +501,9 @@
|
|||||||
.p-t-xs {
|
.p-t-xs {
|
||||||
padding-top: @padding-xs;
|
padding-top: @padding-xs;
|
||||||
}
|
}
|
||||||
|
.p-t-05 {
|
||||||
|
padding-top: 2px;
|
||||||
|
}
|
||||||
.p-t-xss {
|
.p-t-xss {
|
||||||
padding-top: @padding-xss;
|
padding-top: @padding-xss;
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@ import TurndownService from 'turndown';
|
|||||||
import { ReactComponent as AddIcon } from '../assets/svg/added-icon.svg';
|
import { ReactComponent as AddIcon } from '../assets/svg/added-icon.svg';
|
||||||
import { ReactComponent as UpdatedIcon } from '../assets/svg/updated-icon.svg';
|
import { ReactComponent as UpdatedIcon } from '../assets/svg/updated-icon.svg';
|
||||||
import { MentionSuggestionsItem } from '../components/ActivityFeed/FeedEditor/FeedEditor.interface';
|
import { MentionSuggestionsItem } from '../components/ActivityFeed/FeedEditor/FeedEditor.interface';
|
||||||
import { UserTeam } from '../components/common/AssigneeList/AssigneeList.interface';
|
|
||||||
import { FQN_SEPARATOR_CHAR } from '../constants/char.constants';
|
import { FQN_SEPARATOR_CHAR } from '../constants/char.constants';
|
||||||
import {
|
import {
|
||||||
EntityField,
|
EntityField,
|
||||||
@ -41,6 +40,7 @@ import {
|
|||||||
} from '../constants/Feeds.constants';
|
} from '../constants/Feeds.constants';
|
||||||
import { EntityType, FqnPart, TabSpecificField } from '../enums/entity.enum';
|
import { EntityType, FqnPart, TabSpecificField } from '../enums/entity.enum';
|
||||||
import { SearchIndex } from '../enums/search.enum';
|
import { SearchIndex } from '../enums/search.enum';
|
||||||
|
import { OwnerType } from '../enums/user.enum';
|
||||||
import {
|
import {
|
||||||
CardStyle,
|
CardStyle,
|
||||||
EntityTestResultSummaryObject,
|
EntityTestResultSummaryObject,
|
||||||
@ -200,7 +200,8 @@ export async function suggestions(
|
|||||||
ENTITY_URL_MAP[entityType as EntityUrlMapType],
|
ENTITY_URL_MAP[entityType as EntityUrlMapType],
|
||||||
hit._source.name
|
hit._source.name
|
||||||
),
|
),
|
||||||
type: hit._index === SearchIndex.USER ? UserTeam.User : UserTeam.Team,
|
type:
|
||||||
|
hit._index === SearchIndex.USER ? OwnerType.USER : OwnerType.TEAM,
|
||||||
name: hit._source.name,
|
name: hit._source.name,
|
||||||
displayName: hit._source.displayName,
|
displayName: hit._source.displayName,
|
||||||
};
|
};
|
||||||
|
@ -18,12 +18,12 @@ import { isUndefined } from 'lodash';
|
|||||||
import { ServiceTypes } from 'Models';
|
import { ServiceTypes } from 'Models';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { UserTeam } from '../components/common/AssigneeList/AssigneeList.interface';
|
|
||||||
import UserPopOverCard from '../components/common/PopOverCard/UserPopOverCard';
|
import UserPopOverCard from '../components/common/PopOverCard/UserPopOverCard';
|
||||||
import RichTextEditorPreviewer from '../components/common/RichTextEditor/RichTextEditorPreviewer';
|
import RichTextEditorPreviewer from '../components/common/RichTextEditor/RichTextEditorPreviewer';
|
||||||
import TagsViewer from '../components/Tag/TagsViewer/TagsViewer';
|
import TagsViewer from '../components/Tag/TagsViewer/TagsViewer';
|
||||||
import { NO_DATA_PLACEHOLDER } from '../constants/constants';
|
import { NO_DATA_PLACEHOLDER } from '../constants/constants';
|
||||||
import { ServiceCategory } from '../enums/service.enum';
|
import { ServiceCategory } from '../enums/service.enum';
|
||||||
|
import { OwnerType } from '../enums/user.enum';
|
||||||
import { Database } from '../generated/entity/data/database';
|
import { Database } from '../generated/entity/data/database';
|
||||||
import { Pipeline } from '../generated/entity/data/pipeline';
|
import { Pipeline } from '../generated/entity/data/pipeline';
|
||||||
import { EntityReference } from '../generated/entity/type';
|
import { EntityReference } from '../generated/entity/type';
|
||||||
@ -101,7 +101,7 @@ export const getServiceMainTabColumns = (
|
|||||||
displayName={owner.displayName}
|
displayName={owner.displayName}
|
||||||
key={owner.id}
|
key={owner.id}
|
||||||
profileWidth={20}
|
profileWidth={20}
|
||||||
type={owner.type as UserTeam}
|
type={owner.type as OwnerType}
|
||||||
userName={owner.name ?? ''}
|
userName={owner.name ?? ''}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user