mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-12 01:08:18 +00:00
Fix(ui): Task assignee new styling (#21049)
* Task asignee new styling * Task asignee new styling * fixed styling of asignee * removed unused prop * replaced position of edit button in tasktab * fixed sonar test * renamed props * fixed comments * fixed comments * fixed alignment issue of owner label * removed zIndex from owner label * removed unnecessery classes
This commit is contained in:
parent
2465ce391e
commit
7fed86cc99
@ -18,7 +18,6 @@ import { isEmpty, isEqual, isUndefined, lowerCase } from 'lodash';
|
|||||||
import React, { useCallback, useMemo } from 'react';
|
import React, { useCallback, useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
import { ReactComponent as AssigneesIcon } from '../../../assets/svg/ic-assignees.svg';
|
|
||||||
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 ReplyIcon } from '../../../assets/svg/ic-reply-2.svg';
|
import { ReactComponent as ReplyIcon } from '../../../assets/svg/ic-reply-2.svg';
|
||||||
@ -359,8 +358,8 @@ const TaskFeedCard = ({
|
|||||||
? 'task-card-assignee'
|
? 'task-card-assignee'
|
||||||
: ''
|
: ''
|
||||||
}`}>
|
}`}>
|
||||||
<AssigneesIcon height={20} width={20} />
|
|
||||||
<OwnerLabel
|
<OwnerLabel
|
||||||
|
isAssignee
|
||||||
avatarSize={24}
|
avatarSize={24}
|
||||||
isCompactView={false}
|
isCompactView={false}
|
||||||
owners={feed?.task?.assignees}
|
owners={feed?.task?.assignees}
|
||||||
|
@ -75,7 +75,9 @@
|
|||||||
color: @primary-heading-color;
|
color: @primary-heading-color;
|
||||||
max-width: 200px;
|
max-width: 200px;
|
||||||
}
|
}
|
||||||
|
.owner-label-container {
|
||||||
|
max-width: 148px;
|
||||||
|
}
|
||||||
.domain-link-text.render-domain-lebel-style {
|
.domain-link-text.render-domain-lebel-style {
|
||||||
color: @grey-700;
|
color: @grey-700;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@ -48,7 +48,6 @@ import React, {
|
|||||||
} from 'react';
|
} from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Link, useHistory } from 'react-router-dom';
|
import { Link, useHistory } from 'react-router-dom';
|
||||||
import { ReactComponent as EditIcon } from '../../../../assets/svg/edit-new.svg';
|
|
||||||
import { ReactComponent as AssigneesIcon } from '../../../../assets/svg/ic-assignees.svg';
|
import { ReactComponent as AssigneesIcon } from '../../../../assets/svg/ic-assignees.svg';
|
||||||
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';
|
||||||
@ -435,6 +434,8 @@ export const TaskTabNew = ({
|
|||||||
const [hasAddedComment, setHasAddedComment] = useState<boolean>(false);
|
const [hasAddedComment, setHasAddedComment] = useState<boolean>(false);
|
||||||
const [recentComment, setRecentComment] = useState<string>('');
|
const [recentComment, setRecentComment] = useState<string>('');
|
||||||
|
|
||||||
|
const shouldEditAssignee =
|
||||||
|
(isCreator || hasEditAccess) && !isTaskClosed && owners.length === 0;
|
||||||
const onSave = () => {
|
const onSave = () => {
|
||||||
postFeed(comment, taskThread?.id ?? '')
|
postFeed(comment, taskThread?.id ?? '')
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
@ -838,6 +839,12 @@ export const TaskTabNew = ({
|
|||||||
);
|
);
|
||||||
setUsersList(filterData);
|
setUsersList(filterData);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
showErrorToast(
|
||||||
|
error as AxiosError,
|
||||||
|
t('server.entity-fetch-error', {
|
||||||
|
entity: t('label.assignee'),
|
||||||
|
})
|
||||||
|
);
|
||||||
setUsersList([]);
|
setUsersList([]);
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
@ -858,6 +865,10 @@ export const TaskTabNew = ({
|
|||||||
setTaskAction(latestAction);
|
setTaskAction(latestAction);
|
||||||
}, [latestAction]);
|
}, [latestAction]);
|
||||||
|
|
||||||
|
const handleEditClick = () => {
|
||||||
|
setIsEditAssignee(true);
|
||||||
|
};
|
||||||
|
|
||||||
const taskHeader = isTaskTestCaseResult ? (
|
const taskHeader = isTaskTestCaseResult ? (
|
||||||
<TaskTabIncidentManagerHeaderNew thread={taskThread} />
|
<TaskTabIncidentManagerHeaderNew thread={taskThread} />
|
||||||
) : (
|
) : (
|
||||||
@ -937,13 +948,13 @@ export const TaskTabNew = ({
|
|||||||
</Form>
|
</Form>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<Col className="flex items-center gap-2 text-grey-muted" span={8}>
|
<Col className="flex gap-2 text-grey-muted" span={8}>
|
||||||
<AssigneesIcon height={16} />
|
<AssigneesIcon height={16} />
|
||||||
<Typography.Text className="incident-manager-details-label @grey-8">
|
<Typography.Text className="incident-manager-details-label @grey-8">
|
||||||
{t('label.assignee-plural')}
|
{t('label.assignee-plural')}
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
</Col>
|
</Col>
|
||||||
<Col className="flex items-center gap-2" span={16}>
|
<Col className="flex gap-2" span={16}>
|
||||||
{taskThread?.task?.assignees?.length === 1 ? (
|
{taskThread?.task?.assignees?.length === 1 ? (
|
||||||
<div className="d-flex items-center gap-2">
|
<div className="d-flex items-center gap-2">
|
||||||
<UserPopOverCard
|
<UserPopOverCard
|
||||||
@ -965,24 +976,15 @@ export const TaskTabNew = ({
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<OwnerLabel
|
<OwnerLabel
|
||||||
|
isAssignee
|
||||||
avatarSize={24}
|
avatarSize={24}
|
||||||
|
hasPermission={shouldEditAssignee}
|
||||||
isCompactView={false}
|
isCompactView={false}
|
||||||
owners={taskThread?.task?.assignees}
|
owners={taskThread?.task?.assignees}
|
||||||
showLabel={false}
|
showLabel={false}
|
||||||
|
onEditClick={handleEditClick}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{(isCreator || hasEditAccess) &&
|
|
||||||
!isTaskClosed &&
|
|
||||||
owners.length === 0 ? (
|
|
||||||
<Button
|
|
||||||
className="flex-center p-0 h-auto"
|
|
||||||
data-testid="edit-assignees"
|
|
||||||
icon={<EditIcon width="14px" />}
|
|
||||||
size="small"
|
|
||||||
type="text"
|
|
||||||
onClick={() => setIsEditAssignee(true)}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
</Col>
|
</Col>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -10,113 +10,112 @@
|
|||||||
* 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 (reference) '../../styles/variables.less';
|
@import (reference) '../../styles/variables.less';
|
||||||
|
|
||||||
.navbar-container {
|
.navbar-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
> div {
|
> div {
|
||||||
height: 40px;
|
height: 40px;
|
||||||
|
|
||||||
.ant-input-wrapper.ant-input-group,
|
.ant-input-wrapper.ant-input-group,
|
||||||
.ant-input-affix-wrapper {
|
.ant-input-affix-wrapper {
|
||||||
height: 40px;
|
height: 40px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-container {
|
.search-container {
|
||||||
width: 35vw;
|
width: 35vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-user-icon {
|
.app-user-icon {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
.username {
|
.username {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
line-height: 21px;
|
line-height: 21px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.domain-dropdown-menu {
|
.domain-dropdown-menu {
|
||||||
max-height: 400px;
|
max-height: 400px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.slide-in-top {
|
.slide-in-top {
|
||||||
animation: slide-in-top 1s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
|
animation: slide-in-top 1s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes slide-in-top {
|
@keyframes slide-in-top {
|
||||||
0% {
|
0% {
|
||||||
transform: translate(-50%, 100%);
|
transform: translate(-50%, 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
transform: translate(-50%, 0);
|
transform: translate(-50%, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-btn.domain-nav-btn {
|
.ant-btn.domain-nav-btn {
|
||||||
background-color: @white;
|
background-color: @white;
|
||||||
border: 1px solid @grey-15;
|
border: 1px solid @grey-15;
|
||||||
color: @text-color;
|
color: @text-color;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
|
|
||||||
.domain-text {
|
.domain-text {
|
||||||
max-width: 15vw;
|
max-width: 15vw;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&:focus {
|
&:focus {
|
||||||
background-color: @primary-button-background;
|
background-color: @primary-button-background;
|
||||||
border: 1px solid @alert-info-icon-bg-1;
|
border: 1px solid @alert-info-icon-bg-1;
|
||||||
color: @text-color;
|
color: @text-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.domain-active {
|
&.domain-active {
|
||||||
color: @primary-color;
|
color: @primary-color;
|
||||||
border: 1px solid @primary-color;
|
border: 1px solid @primary-color;
|
||||||
background-color: @primary-button-background;
|
background-color: @primary-button-background;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-alert.ant-alert-info.refresh-alert {
|
.ant-alert.ant-alert-info.refresh-alert {
|
||||||
width: 470px;
|
width: 470px;
|
||||||
bottom: 30px;
|
bottom: 30px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
box-shadow: 0px 2px 10px rgba(0, 0, 0, 0.12);
|
box-shadow: 0px 2px 10px rgba(0, 0, 0, 0.12);
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
border: 1px solid @text-color;
|
border: 1px solid @text-color;
|
||||||
background: @text-color;
|
background: @text-color;
|
||||||
color: @white;
|
color: @white;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
|
|
||||||
.ant-alert-message {
|
.ant-alert-message {
|
||||||
color: @white;
|
color: @white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-alert-description {
|
.ant-alert-description {
|
||||||
color: @grey-4;
|
color: @grey-4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-alert-content {
|
.ant-alert-content {
|
||||||
border-right: 1px solid @white;
|
border-right: 1px solid @white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-btn {
|
|
||||||
font-weight: 700;
|
|
||||||
color: @white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
.ant-btn {
|
||||||
|
font-weight: 700;
|
||||||
|
color: @white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -13,17 +13,20 @@
|
|||||||
import Icon from '@ant-design/icons';
|
import Icon from '@ant-design/icons';
|
||||||
import { Typography } from 'antd';
|
import { Typography } from 'antd';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { ReactComponent as AssigneesIcon } from '../../../assets/svg/ic-assignees.svg';
|
||||||
import { ReactComponent as IconTeamsGrey } from '../../../assets/svg/teams-grey.svg';
|
import { ReactComponent as IconTeamsGrey } from '../../../assets/svg/teams-grey.svg';
|
||||||
import { OwnerType } from '../../../enums/user.enum';
|
import { OwnerType } from '../../../enums/user.enum';
|
||||||
import { EntityReference } from '../../../generated/entity/data/table';
|
import { EntityReference } from '../../../generated/entity/data/table';
|
||||||
import { getEntityName } from '../../../utils/EntityUtils';
|
import { getEntityName } from '../../../utils/EntityUtils';
|
||||||
import ProfilePicture from '../ProfilePicture/ProfilePicture';
|
import ProfilePicture from '../ProfilePicture/ProfilePicture';
|
||||||
import './owner-avtar.less';
|
import './owner-avtar.less';
|
||||||
|
|
||||||
interface OwnerAvatarProps {
|
interface OwnerAvatarProps {
|
||||||
owner: EntityReference;
|
owner: EntityReference;
|
||||||
isCompactView: boolean;
|
|
||||||
inheritedIcon?: React.ReactNode;
|
|
||||||
avatarSize?: number;
|
avatarSize?: number;
|
||||||
|
isCompactView?: boolean;
|
||||||
|
inheritedIcon?: React.ReactNode;
|
||||||
|
isAssignee?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const OwnerAvatar: React.FC<OwnerAvatarProps> = ({
|
export const OwnerAvatar: React.FC<OwnerAvatarProps> = ({
|
||||||
@ -31,9 +34,49 @@ export const OwnerAvatar: React.FC<OwnerAvatarProps> = ({
|
|||||||
isCompactView,
|
isCompactView,
|
||||||
inheritedIcon,
|
inheritedIcon,
|
||||||
avatarSize = 32,
|
avatarSize = 32,
|
||||||
|
isAssignee,
|
||||||
}) => {
|
}) => {
|
||||||
const displayName = getEntityName(owner);
|
const displayName = getEntityName(owner);
|
||||||
|
|
||||||
|
if (isAssignee) {
|
||||||
|
return (
|
||||||
|
<div className="flex w-max-full items-center gap-2">
|
||||||
|
{owner.type === OwnerType.TEAM ? (
|
||||||
|
<div className="d-flex gap-2 multi-team-container w-max-full items-center">
|
||||||
|
<Icon
|
||||||
|
className="owner-team-icon"
|
||||||
|
component={AssigneesIcon}
|
||||||
|
data-testid={!isCompactView && getEntityName(owner)}
|
||||||
|
/>
|
||||||
|
<Typography.Text className="text-sm" ellipsis={{ tooltip: true }}>
|
||||||
|
{displayName}
|
||||||
|
</Typography.Text>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
className="owner-avatar-icon"
|
||||||
|
data-testid={!isCompactView && getEntityName(owner)}
|
||||||
|
key={owner.id}
|
||||||
|
style={{ flexBasis: `${avatarSize}px` }}>
|
||||||
|
<ProfilePicture
|
||||||
|
displayName={displayName}
|
||||||
|
key="profile-picture"
|
||||||
|
name={owner.name ?? ''}
|
||||||
|
type="circle"
|
||||||
|
width={isCompactView ? '24' : `${avatarSize}`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{inheritedIcon && (
|
||||||
|
<div className="inherited-icon-styling flex-center">
|
||||||
|
{inheritedIcon}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return owner.type === OwnerType.TEAM ? (
|
return owner.type === OwnerType.TEAM ? (
|
||||||
<div className="d-flex gap-2 w-max-full items-center">
|
<div className="d-flex gap-2 w-max-full items-center">
|
||||||
<Icon
|
<Icon
|
||||||
|
@ -16,6 +16,12 @@
|
|||||||
color: @grey-700;
|
color: @grey-700;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.multi-team-container {
|
||||||
|
background-color: @grey-9;
|
||||||
|
border-radius: 16px;
|
||||||
|
padding: 4px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
.avatar-group {
|
.avatar-group {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -26,6 +26,7 @@ interface OwnerItemProps {
|
|||||||
className?: string;
|
className?: string;
|
||||||
ownerDisplayName?: ReactNode;
|
ownerDisplayName?: ReactNode;
|
||||||
avatarSize?: number;
|
avatarSize?: number;
|
||||||
|
isAssignee?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const OwnerItem: React.FC<OwnerItemProps> = ({
|
export const OwnerItem: React.FC<OwnerItemProps> = ({
|
||||||
@ -34,6 +35,7 @@ export const OwnerItem: React.FC<OwnerItemProps> = ({
|
|||||||
className,
|
className,
|
||||||
ownerDisplayName,
|
ownerDisplayName,
|
||||||
avatarSize = 32,
|
avatarSize = 32,
|
||||||
|
isAssignee,
|
||||||
}) => {
|
}) => {
|
||||||
const displayName = getEntityName(owner);
|
const displayName = getEntityName(owner);
|
||||||
const ownerPath = getOwnerPath(owner);
|
const ownerPath = getOwnerPath(owner);
|
||||||
@ -78,6 +80,7 @@ export const OwnerItem: React.FC<OwnerItemProps> = ({
|
|||||||
<OwnerAvatar
|
<OwnerAvatar
|
||||||
avatarSize={avatarSize}
|
avatarSize={avatarSize}
|
||||||
inheritedIcon={inheritedIcon}
|
inheritedIcon={inheritedIcon}
|
||||||
|
isAssignee={isAssignee}
|
||||||
isCompactView={isCompactView}
|
isCompactView={isCompactView}
|
||||||
owner={owner}
|
owner={owner}
|
||||||
/>
|
/>
|
||||||
@ -91,6 +94,7 @@ export const OwnerItem: React.FC<OwnerItemProps> = ({
|
|||||||
<OwnerAvatar
|
<OwnerAvatar
|
||||||
avatarSize={avatarSize}
|
avatarSize={avatarSize}
|
||||||
inheritedIcon={inheritedIcon}
|
inheritedIcon={inheritedIcon}
|
||||||
|
isAssignee={isAssignee}
|
||||||
isCompactView={isCompactView}
|
isCompactView={isCompactView}
|
||||||
owner={owner}
|
owner={owner}
|
||||||
/>
|
/>
|
||||||
|
@ -11,11 +11,12 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Typography } from 'antd';
|
import { Button, Typography } from 'antd';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { reverse } from 'lodash';
|
import { reverse } from 'lodash';
|
||||||
import React, { useMemo, useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { ReactComponent as EditIcon } from '../../../assets/svg/edit-new.svg';
|
||||||
import { OwnerType } from '../../../enums/user.enum';
|
import { OwnerType } from '../../../enums/user.enum';
|
||||||
import { EntityReference } from '../../../generated/entity/type';
|
import { EntityReference } from '../../../generated/entity/type';
|
||||||
import { NoOwnerFound } from '../NoOwner/NoOwnerFound';
|
import { NoOwnerFound } from '../NoOwner/NoOwnerFound';
|
||||||
@ -41,6 +42,8 @@ export const OwnerLabel = ({
|
|||||||
tooltipText,
|
tooltipText,
|
||||||
isCompactView = true, // renders owner profile followed by its name
|
isCompactView = true, // renders owner profile followed by its name
|
||||||
avatarSize = 32,
|
avatarSize = 32,
|
||||||
|
isAssignee = false,
|
||||||
|
onEditClick,
|
||||||
}: OwnerLabelProps) => {
|
}: OwnerLabelProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [showAllOwners, setShowAllOwners] = useState(false);
|
const [showAllOwners, setShowAllOwners] = useState(false);
|
||||||
@ -87,9 +90,92 @@ export const OwnerLabel = ({
|
|||||||
className,
|
className,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const showMultipleTypeTeam = owners.filter(
|
||||||
|
(owner) => owner.type === OwnerType.TEAM
|
||||||
|
);
|
||||||
|
const showMultipleTypeVisibleUser = owners
|
||||||
|
.filter((owner) => owner.type === OwnerType.USER)
|
||||||
|
.slice(0, maxVisibleOwners)
|
||||||
|
.reverse();
|
||||||
|
const showMultipleTypeRemainingUser = owners
|
||||||
|
.filter((owner) => owner.type === OwnerType.USER)
|
||||||
|
.slice(maxVisibleOwners);
|
||||||
|
const renderMultipleType = useMemo(() => {
|
||||||
|
return (
|
||||||
|
<div className="flex-wrap w-max-full d-flex relative items-center">
|
||||||
|
<div className="flex w-full gap-2 flex-wrap relative">
|
||||||
|
{showMultipleTypeTeam.map((owner, index) => (
|
||||||
|
<div className="w-max-full" key={owner.id}>
|
||||||
|
<OwnerItem
|
||||||
|
avatarSize={avatarSize}
|
||||||
|
className={className}
|
||||||
|
isAssignee={isAssignee}
|
||||||
|
isCompactView={isCompactView}
|
||||||
|
owner={owner}
|
||||||
|
ownerDisplayName={ownerDisplayName?.[index]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
<div className="flex">
|
||||||
|
<div className="flex relative m-l-xs justify-end flex-row-reverse">
|
||||||
|
{showMultipleTypeVisibleUser.map((owner, index) => (
|
||||||
|
<div className="relative" key={owner.id}>
|
||||||
|
<OwnerItem
|
||||||
|
avatarSize={avatarSize}
|
||||||
|
className={className}
|
||||||
|
isAssignee={isAssignee}
|
||||||
|
isCompactView={isCompactView}
|
||||||
|
owner={owner}
|
||||||
|
ownerDisplayName={ownerDisplayName?.[index]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
{showMultipleTypeRemainingUser.length > 0 && (
|
||||||
|
<div className="m-l-xs">
|
||||||
|
<OwnerReveal
|
||||||
|
avatarSize={isCompactView ? 24 : avatarSize}
|
||||||
|
isCompactView={false}
|
||||||
|
isDropdownOpen={isDropdownOpen}
|
||||||
|
owners={showMultipleTypeRemainingUser}
|
||||||
|
remainingCount={showMultipleTypeRemainingUser.length}
|
||||||
|
setIsDropdownOpen={setIsDropdownOpen}
|
||||||
|
setShowAllOwners={setShowAllOwners}
|
||||||
|
showAllOwners={showAllOwners}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{hasPermission && (
|
||||||
|
<Button
|
||||||
|
className="p-0 flex-center h-auto"
|
||||||
|
data-testid="edit-assignees"
|
||||||
|
icon={<EditIcon width="14px" />}
|
||||||
|
type="text"
|
||||||
|
onClick={onEditClick}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}, [
|
||||||
|
showMultipleTypeTeam,
|
||||||
|
showMultipleTypeVisibleUser,
|
||||||
|
showMultipleTypeRemainingUser,
|
||||||
|
avatarSize,
|
||||||
|
className,
|
||||||
|
isCompactView,
|
||||||
|
ownerDisplayName,
|
||||||
|
hasPermission,
|
||||||
|
onEditClick,
|
||||||
|
isDropdownOpen,
|
||||||
|
owners,
|
||||||
|
setIsDropdownOpen,
|
||||||
|
setShowAllOwners,
|
||||||
|
showAllOwners,
|
||||||
|
]);
|
||||||
const ownerElements = useMemo(() => {
|
const ownerElements = useMemo(() => {
|
||||||
const hasOwners = owners && owners.length > 0;
|
const hasOwners = owners && owners.length > 0;
|
||||||
|
|
||||||
// Show all owners when "more" is clicked, regardless of view mode
|
// Show all owners when "more" is clicked, regardless of view mode
|
||||||
const visibleOwners = showAllOwners
|
const visibleOwners = showAllOwners
|
||||||
? owners
|
? owners
|
||||||
@ -118,19 +204,23 @@ export const OwnerLabel = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isAssignee) {
|
||||||
|
return renderMultipleType;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'owner-label-container d-flex flex-col items-start flex-start':
|
'owner-label-container w-full d-flex flex-col items-start flex-start':
|
||||||
!isCompactView,
|
!isCompactView,
|
||||||
'd-flex owner-label-heading gap-2 items-center': isCompactView,
|
'd-flex owner-label-heading gap-2 items-center': isCompactView,
|
||||||
})}
|
})}
|
||||||
data-testid="owner-label">
|
data-testid="owner-label">
|
||||||
{ownerElementsNonCompactView}
|
{ownerElementsNonCompactView}
|
||||||
<div className="d-flex items-center flex-center">
|
<div className="d-flex w-max-full items-center flex-center">
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'avatar-group w-full d-flex relative items-center m-l-xss',
|
'avatar-group w-full d-flex relative items-center m-l-xss',
|
||||||
{
|
{
|
||||||
'gap-2 flex-wrap': isCompactView,
|
'gap-2 flex-wrap': isCompactView,
|
||||||
'flex-row-reverse': !isCompactView,
|
'flex-row-reverse': !isCompactView,
|
||||||
|
@ -29,4 +29,6 @@ export interface OwnerLabelProps {
|
|||||||
tooltipText?: string;
|
tooltipText?: string;
|
||||||
isCompactView?: boolean;
|
isCompactView?: boolean;
|
||||||
avatarSize?: number;
|
avatarSize?: number;
|
||||||
|
isAssignee?: boolean;
|
||||||
|
onEditClick?: () => void;
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,3 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.owner-label-container {
|
|
||||||
max-width: 148px;
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user