forked from github/plane
chore: issue sidebar and peek overview improvement (#3488)
* chore: issue peek overview and sidebar properties focused state improvement * fix: added name of the issue in issue relation * chore: issue sidebar and peek overview properties improvement * chore: issue assignee improvement for sidebar and peek overview --------- Co-authored-by: NarayanBavisetti <narayan3119@gmail.com>
This commit is contained in:
parent
09a1a55da8
commit
483fc57601
@ -304,6 +304,7 @@ class IssueRelationSerializer(BaseSerializer):
|
||||
sequence_id = serializers.IntegerField(
|
||||
source="related_issue.sequence_id", read_only=True
|
||||
)
|
||||
name = serializers.CharField(source="related_issue.name", read_only=True)
|
||||
relation_type = serializers.CharField(read_only=True)
|
||||
|
||||
class Meta:
|
||||
@ -313,6 +314,7 @@ class IssueRelationSerializer(BaseSerializer):
|
||||
"project_id",
|
||||
"sequence_id",
|
||||
"relation_type",
|
||||
"name",
|
||||
]
|
||||
read_only_fields = [
|
||||
"workspace",
|
||||
@ -328,6 +330,7 @@ class RelatedIssueSerializer(BaseSerializer):
|
||||
sequence_id = serializers.IntegerField(
|
||||
source="issue.sequence_id", read_only=True
|
||||
)
|
||||
name = serializers.CharField(source="issue.name", read_only=True)
|
||||
relation_type = serializers.CharField(read_only=True)
|
||||
|
||||
class Meta:
|
||||
@ -337,6 +340,7 @@ class RelatedIssueSerializer(BaseSerializer):
|
||||
"project_id",
|
||||
"sequence_id",
|
||||
"relation_type",
|
||||
"name",
|
||||
]
|
||||
read_only_fields = [
|
||||
"workspace",
|
||||
|
@ -30,6 +30,7 @@ type ButtonProps = {
|
||||
hideIcon: boolean;
|
||||
hideText?: boolean;
|
||||
dropdownArrow: boolean;
|
||||
isActive?: boolean;
|
||||
dropdownArrowClassName: string;
|
||||
placeholder: string;
|
||||
tooltip: boolean;
|
||||
@ -51,6 +52,7 @@ const BorderButton = (props: ButtonProps) => {
|
||||
dropdownArrowClassName,
|
||||
hideIcon = false,
|
||||
hideText = false,
|
||||
isActive = false,
|
||||
placeholder,
|
||||
tooltip,
|
||||
} = props;
|
||||
@ -60,6 +62,7 @@ const BorderButton = (props: ButtonProps) => {
|
||||
<div
|
||||
className={cn(
|
||||
"h-full flex items-center gap-1.5 border-[0.5px] border-custom-border-300 hover:bg-custom-background-80 rounded text-xs px-2 py-0.5",
|
||||
{ "bg-custom-background-80": isActive },
|
||||
className
|
||||
)}
|
||||
>
|
||||
@ -111,6 +114,7 @@ const TransparentButton = (props: ButtonProps) => {
|
||||
dropdownArrowClassName,
|
||||
hideIcon = false,
|
||||
hideText = false,
|
||||
isActive = false,
|
||||
placeholder,
|
||||
tooltip,
|
||||
} = props;
|
||||
@ -120,6 +124,7 @@ const TransparentButton = (props: ButtonProps) => {
|
||||
<div
|
||||
className={cn(
|
||||
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 hover:bg-custom-background-80",
|
||||
{ "bg-custom-background-80": isActive },
|
||||
className
|
||||
)}
|
||||
>
|
||||
@ -268,6 +273,7 @@ export const CycleDropdown: React.FC<Props> = observer((props) => {
|
||||
dropdownArrowClassName={dropdownArrowClassName}
|
||||
hideIcon={hideIcon}
|
||||
placeholder={placeholder}
|
||||
isActive={isOpen}
|
||||
tooltip={tooltip}
|
||||
/>
|
||||
) : buttonVariant === "border-without-text" ? (
|
||||
@ -279,6 +285,7 @@ export const CycleDropdown: React.FC<Props> = observer((props) => {
|
||||
hideIcon={hideIcon}
|
||||
hideText
|
||||
placeholder={placeholder}
|
||||
isActive={isOpen}
|
||||
tooltip={tooltip}
|
||||
/>
|
||||
) : buttonVariant === "background-with-text" ? (
|
||||
@ -310,6 +317,7 @@ export const CycleDropdown: React.FC<Props> = observer((props) => {
|
||||
dropdownArrowClassName={dropdownArrowClassName}
|
||||
hideIcon={hideIcon}
|
||||
placeholder={placeholder}
|
||||
isActive={isOpen}
|
||||
tooltip={tooltip}
|
||||
/>
|
||||
) : buttonVariant === "transparent-without-text" ? (
|
||||
@ -321,6 +329,7 @@ export const CycleDropdown: React.FC<Props> = observer((props) => {
|
||||
hideIcon={hideIcon}
|
||||
hideText
|
||||
placeholder={placeholder}
|
||||
isActive={isOpen}
|
||||
tooltip={tooltip}
|
||||
/>
|
||||
) : null}
|
||||
|
@ -2,7 +2,7 @@ import React, { useRef, useState } from "react";
|
||||
import { Combobox } from "@headlessui/react";
|
||||
import DatePicker from "react-datepicker";
|
||||
import { usePopper } from "react-popper";
|
||||
import { CalendarDays, X } from "lucide-react";
|
||||
import { Calendar, CalendarDays, X } from "lucide-react";
|
||||
// hooks
|
||||
import { useDropdownKeyDown } from "hooks/use-dropdown-key-down";
|
||||
import useOutsideClickDetector from "hooks/use-outside-click-detector";
|
||||
@ -23,6 +23,7 @@ type Props = TDropdownProps & {
|
||||
onChange: (val: Date | null) => void;
|
||||
value: Date | string | null;
|
||||
closeOnSelect?: boolean;
|
||||
showPlaceholderIcon?: boolean;
|
||||
};
|
||||
|
||||
type ButtonProps = {
|
||||
@ -33,9 +34,11 @@ type ButtonProps = {
|
||||
isClearable: boolean;
|
||||
hideIcon?: boolean;
|
||||
hideText?: boolean;
|
||||
isActive?: boolean;
|
||||
onClear: () => void;
|
||||
placeholder: string;
|
||||
tooltip: boolean;
|
||||
showPlaceholderIcon?: boolean;
|
||||
};
|
||||
|
||||
const BorderButton = (props: ButtonProps) => {
|
||||
@ -47,6 +50,7 @@ const BorderButton = (props: ButtonProps) => {
|
||||
isClearable,
|
||||
hideIcon = false,
|
||||
hideText = false,
|
||||
isActive = false,
|
||||
onClear,
|
||||
placeholder,
|
||||
tooltip,
|
||||
@ -61,6 +65,7 @@ const BorderButton = (props: ButtonProps) => {
|
||||
<div
|
||||
className={cn(
|
||||
"h-full flex items-center gap-1.5 border-[0.5px] border-custom-border-300 hover:bg-custom-background-80 rounded text-xs px-2 py-0.5",
|
||||
{ "bg-custom-background-80": isActive },
|
||||
className
|
||||
)}
|
||||
>
|
||||
@ -131,9 +136,11 @@ const TransparentButton = (props: ButtonProps) => {
|
||||
isClearable,
|
||||
hideIcon = false,
|
||||
hideText = false,
|
||||
isActive = false,
|
||||
onClear,
|
||||
placeholder,
|
||||
tooltip,
|
||||
showPlaceholderIcon = false,
|
||||
} = props;
|
||||
|
||||
return (
|
||||
@ -145,11 +152,16 @@ const TransparentButton = (props: ButtonProps) => {
|
||||
<div
|
||||
className={cn(
|
||||
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 hover:bg-custom-background-80",
|
||||
{ "bg-custom-background-80": isActive },
|
||||
className
|
||||
)}
|
||||
>
|
||||
{!hideIcon && icon}
|
||||
{!hideText && <span className="flex-grow truncate">{date ? renderFormattedDate(date) : placeholder}</span>}
|
||||
{showPlaceholderIcon && !date && (
|
||||
<Calendar className="h-2.5 w-2.5 flex-shrink-0 hidden group-hover:inline text-custom-text-400" />
|
||||
)}
|
||||
|
||||
{isClearable && (
|
||||
<X
|
||||
className={cn("h-2 w-2 flex-shrink-0", clearIconClassName)}
|
||||
@ -183,6 +195,7 @@ export const DateDropdown: React.FC<Props> = (props) => {
|
||||
placement,
|
||||
tabIndex,
|
||||
tooltip = false,
|
||||
showPlaceholderIcon = false,
|
||||
value,
|
||||
} = props;
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
@ -246,6 +259,7 @@ export const DateDropdown: React.FC<Props> = (props) => {
|
||||
placeholder={placeholder}
|
||||
isClearable={isClearable && isDateSelected}
|
||||
onClear={() => onChange(null)}
|
||||
isActive={isOpen}
|
||||
tooltip={tooltip}
|
||||
/>
|
||||
) : buttonVariant === "border-without-text" ? (
|
||||
@ -258,6 +272,7 @@ export const DateDropdown: React.FC<Props> = (props) => {
|
||||
placeholder={placeholder}
|
||||
isClearable={isClearable && isDateSelected}
|
||||
onClear={() => onChange(null)}
|
||||
isActive={isOpen}
|
||||
tooltip={tooltip}
|
||||
hideText
|
||||
/>
|
||||
@ -296,7 +311,9 @@ export const DateDropdown: React.FC<Props> = (props) => {
|
||||
placeholder={placeholder}
|
||||
isClearable={isClearable && isDateSelected}
|
||||
onClear={() => onChange(null)}
|
||||
isActive={isOpen}
|
||||
tooltip={tooltip}
|
||||
showPlaceholderIcon={showPlaceholderIcon}
|
||||
/>
|
||||
) : buttonVariant === "transparent-without-text" ? (
|
||||
<TransparentButton
|
||||
@ -308,8 +325,10 @@ export const DateDropdown: React.FC<Props> = (props) => {
|
||||
placeholder={placeholder}
|
||||
isClearable={isClearable && isDateSelected}
|
||||
onClear={() => onChange(null)}
|
||||
isActive={isOpen}
|
||||
tooltip={tooltip}
|
||||
hideText
|
||||
showPlaceholderIcon={showPlaceholderIcon}
|
||||
/>
|
||||
) : null}
|
||||
</button>
|
||||
|
@ -31,6 +31,7 @@ type ButtonProps = {
|
||||
dropdownArrowClassName: string;
|
||||
hideIcon?: boolean;
|
||||
hideText?: boolean;
|
||||
isActive?: boolean;
|
||||
placeholder: string;
|
||||
tooltip: boolean;
|
||||
};
|
||||
@ -51,6 +52,7 @@ const BorderButton = (props: ButtonProps) => {
|
||||
dropdownArrowClassName,
|
||||
hideIcon = false,
|
||||
hideText = false,
|
||||
isActive = false,
|
||||
placeholder,
|
||||
tooltip,
|
||||
} = props;
|
||||
@ -64,6 +66,7 @@ const BorderButton = (props: ButtonProps) => {
|
||||
<div
|
||||
className={cn(
|
||||
"h-full flex items-center gap-1.5 border-[0.5px] border-custom-border-300 hover:bg-custom-background-80 rounded text-xs px-2 py-0.5",
|
||||
{ "bg-custom-background-80": isActive },
|
||||
className
|
||||
)}
|
||||
>
|
||||
@ -123,6 +126,7 @@ const TransparentButton = (props: ButtonProps) => {
|
||||
dropdownArrowClassName,
|
||||
hideIcon = false,
|
||||
hideText = false,
|
||||
isActive = false,
|
||||
placeholder,
|
||||
tooltip,
|
||||
} = props;
|
||||
@ -136,6 +140,7 @@ const TransparentButton = (props: ButtonProps) => {
|
||||
<div
|
||||
className={cn(
|
||||
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 hover:bg-custom-background-80",
|
||||
{ "bg-custom-background-80": isActive },
|
||||
className
|
||||
)}
|
||||
>
|
||||
@ -276,6 +281,7 @@ export const EstimateDropdown: React.FC<Props> = observer((props) => {
|
||||
dropdownArrowClassName={dropdownArrowClassName}
|
||||
hideIcon={hideIcon}
|
||||
placeholder={placeholder}
|
||||
isActive={isOpen}
|
||||
tooltip={tooltip}
|
||||
/>
|
||||
) : buttonVariant === "border-without-text" ? (
|
||||
@ -287,6 +293,7 @@ export const EstimateDropdown: React.FC<Props> = observer((props) => {
|
||||
hideIcon={hideIcon}
|
||||
hideText
|
||||
placeholder={placeholder}
|
||||
isActive={isOpen}
|
||||
tooltip={tooltip}
|
||||
/>
|
||||
) : buttonVariant === "background-with-text" ? (
|
||||
@ -318,6 +325,7 @@ export const EstimateDropdown: React.FC<Props> = observer((props) => {
|
||||
dropdownArrowClassName={dropdownArrowClassName}
|
||||
hideIcon={hideIcon}
|
||||
placeholder={placeholder}
|
||||
isActive={isOpen}
|
||||
tooltip={tooltip}
|
||||
/>
|
||||
) : buttonVariant === "transparent-without-text" ? (
|
||||
@ -329,6 +337,7 @@ export const EstimateDropdown: React.FC<Props> = observer((props) => {
|
||||
hideIcon={hideIcon}
|
||||
hideText
|
||||
placeholder={placeholder}
|
||||
isActive={isOpen}
|
||||
tooltip={tooltip}
|
||||
/>
|
||||
) : null}
|
||||
|
@ -14,6 +14,7 @@ type ButtonProps = {
|
||||
placeholder: string;
|
||||
hideIcon?: boolean;
|
||||
hideText?: boolean;
|
||||
isActive?: boolean;
|
||||
tooltip: boolean;
|
||||
userIds: string | string[] | null;
|
||||
};
|
||||
@ -50,6 +51,7 @@ export const BorderButton = observer((props: ButtonProps) => {
|
||||
dropdownArrowClassName,
|
||||
hideIcon = false,
|
||||
hideText = false,
|
||||
isActive = false,
|
||||
placeholder,
|
||||
userIds,
|
||||
tooltip,
|
||||
@ -57,7 +59,7 @@ export const BorderButton = observer((props: ButtonProps) => {
|
||||
// store hooks
|
||||
const { getUserDetails } = useMember();
|
||||
|
||||
const isMultiple = Array.isArray(userIds);
|
||||
const isArray = Array.isArray(userIds);
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
@ -68,13 +70,18 @@ export const BorderButton = observer((props: ButtonProps) => {
|
||||
<div
|
||||
className={cn(
|
||||
"h-full flex items-center gap-1.5 border-[0.5px] border-custom-border-300 hover:bg-custom-background-80 rounded text-xs px-2 py-0.5",
|
||||
{ "bg-custom-background-80": isActive },
|
||||
className
|
||||
)}
|
||||
>
|
||||
{!hideIcon && <ButtonAvatars tooltip={tooltip} userIds={userIds} />}
|
||||
{!hideText && (
|
||||
<span className="flex-grow truncate">
|
||||
{userIds ? (isMultiple ? placeholder : getUserDetails(userIds)?.display_name) : placeholder}
|
||||
<span className="flex-grow truncate text-sm leading-5">
|
||||
{isArray && userIds.length > 0
|
||||
? userIds.length === 1
|
||||
? getUserDetails(userIds[0])?.display_name
|
||||
: ""
|
||||
: placeholder}
|
||||
</span>
|
||||
)}
|
||||
{dropdownArrow && (
|
||||
@ -99,7 +106,7 @@ export const BackgroundButton = observer((props: ButtonProps) => {
|
||||
// store hooks
|
||||
const { getUserDetails } = useMember();
|
||||
|
||||
const isMultiple = Array.isArray(userIds);
|
||||
const isArray = Array.isArray(userIds);
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
@ -115,8 +122,12 @@ export const BackgroundButton = observer((props: ButtonProps) => {
|
||||
>
|
||||
{!hideIcon && <ButtonAvatars tooltip={tooltip} userIds={userIds} />}
|
||||
{!hideText && (
|
||||
<span className="flex-grow truncate">
|
||||
{userIds ? (isMultiple ? placeholder : getUserDetails(userIds)?.display_name) : placeholder}
|
||||
<span className="flex-grow truncate text-sm leading-5">
|
||||
{isArray && userIds.length > 0
|
||||
? userIds.length === 1
|
||||
? getUserDetails(userIds[0])?.display_name
|
||||
: ""
|
||||
: placeholder}
|
||||
</span>
|
||||
)}
|
||||
{dropdownArrow && (
|
||||
@ -134,6 +145,7 @@ export const TransparentButton = observer((props: ButtonProps) => {
|
||||
dropdownArrowClassName,
|
||||
hideIcon = false,
|
||||
hideText = false,
|
||||
isActive = false,
|
||||
placeholder,
|
||||
userIds,
|
||||
tooltip,
|
||||
@ -141,7 +153,7 @@ export const TransparentButton = observer((props: ButtonProps) => {
|
||||
// store hooks
|
||||
const { getUserDetails } = useMember();
|
||||
|
||||
const isMultiple = Array.isArray(userIds);
|
||||
const isArray = Array.isArray(userIds);
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
@ -152,13 +164,18 @@ export const TransparentButton = observer((props: ButtonProps) => {
|
||||
<div
|
||||
className={cn(
|
||||
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 hover:bg-custom-background-80",
|
||||
{ "bg-custom-background-80": isActive },
|
||||
className
|
||||
)}
|
||||
>
|
||||
{!hideIcon && <ButtonAvatars tooltip={tooltip} userIds={userIds} />}
|
||||
{!hideText && (
|
||||
<span className="flex-grow truncate">
|
||||
{userIds ? (isMultiple ? placeholder : getUserDetails(userIds)?.display_name) : placeholder}
|
||||
<span className="flex-grow truncate text-sm leading-5">
|
||||
{isArray && userIds.length > 0
|
||||
? userIds.length === 1
|
||||
? getUserDetails(userIds[0])?.display_name
|
||||
: ""
|
||||
: placeholder}
|
||||
</span>
|
||||
)}
|
||||
{dropdownArrow && (
|
||||
|
@ -147,6 +147,7 @@ export const ProjectMemberDropdown: React.FC<Props> = observer((props) => {
|
||||
dropdownArrowClassName={dropdownArrowClassName}
|
||||
hideIcon={hideIcon}
|
||||
placeholder={placeholder}
|
||||
isActive={isOpen}
|
||||
tooltip={tooltip}
|
||||
/>
|
||||
) : buttonVariant === "border-without-text" ? (
|
||||
@ -157,6 +158,7 @@ export const ProjectMemberDropdown: React.FC<Props> = observer((props) => {
|
||||
dropdownArrowClassName={dropdownArrowClassName}
|
||||
hideIcon={hideIcon}
|
||||
placeholder={placeholder}
|
||||
isActive={isOpen}
|
||||
tooltip={tooltip}
|
||||
hideText
|
||||
/>
|
||||
@ -189,6 +191,7 @@ export const ProjectMemberDropdown: React.FC<Props> = observer((props) => {
|
||||
dropdownArrowClassName={dropdownArrowClassName}
|
||||
hideIcon={hideIcon}
|
||||
placeholder={placeholder}
|
||||
isActive={isOpen}
|
||||
tooltip={tooltip}
|
||||
/>
|
||||
) : buttonVariant === "transparent-without-text" ? (
|
||||
@ -199,6 +202,7 @@ export const ProjectMemberDropdown: React.FC<Props> = observer((props) => {
|
||||
dropdownArrowClassName={dropdownArrowClassName}
|
||||
hideIcon={hideIcon}
|
||||
placeholder={placeholder}
|
||||
isActive={isOpen}
|
||||
tooltip={tooltip}
|
||||
hideText
|
||||
/>
|
||||
|
@ -38,6 +38,7 @@ type ButtonProps = {
|
||||
dropdownArrowClassName: string;
|
||||
hideIcon?: boolean;
|
||||
hideText?: boolean;
|
||||
isActive?: boolean;
|
||||
module: IModule | null;
|
||||
placeholder: string;
|
||||
tooltip: boolean;
|
||||
@ -50,6 +51,7 @@ const BorderButton = (props: ButtonProps) => {
|
||||
dropdownArrowClassName,
|
||||
hideIcon = false,
|
||||
hideText = false,
|
||||
isActive = false,
|
||||
module,
|
||||
placeholder,
|
||||
tooltip,
|
||||
@ -60,6 +62,7 @@ const BorderButton = (props: ButtonProps) => {
|
||||
<div
|
||||
className={cn(
|
||||
"h-full flex items-center gap-1.5 border-[0.5px] border-custom-border-300 hover:bg-custom-background-80 rounded text-xs px-2 py-0.5",
|
||||
{ "bg-custom-background-80": isActive },
|
||||
className
|
||||
)}
|
||||
>
|
||||
@ -110,6 +113,7 @@ const TransparentButton = (props: ButtonProps) => {
|
||||
dropdownArrowClassName,
|
||||
hideIcon = false,
|
||||
hideText = false,
|
||||
isActive = false,
|
||||
module,
|
||||
placeholder,
|
||||
tooltip,
|
||||
@ -120,6 +124,7 @@ const TransparentButton = (props: ButtonProps) => {
|
||||
<div
|
||||
className={cn(
|
||||
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 hover:bg-custom-background-80",
|
||||
{ "bg-custom-background-80": isActive },
|
||||
className
|
||||
)}
|
||||
>
|
||||
@ -267,6 +272,7 @@ export const ModuleDropdown: React.FC<Props> = observer((props) => {
|
||||
dropdownArrowClassName={dropdownArrowClassName}
|
||||
hideIcon={hideIcon}
|
||||
placeholder={placeholder}
|
||||
isActive={isOpen}
|
||||
tooltip={tooltip}
|
||||
/>
|
||||
) : buttonVariant === "border-without-text" ? (
|
||||
@ -278,6 +284,7 @@ export const ModuleDropdown: React.FC<Props> = observer((props) => {
|
||||
hideIcon={hideIcon}
|
||||
hideText
|
||||
placeholder={placeholder}
|
||||
isActive={isOpen}
|
||||
tooltip={tooltip}
|
||||
/>
|
||||
) : buttonVariant === "background-with-text" ? (
|
||||
@ -309,6 +316,7 @@ export const ModuleDropdown: React.FC<Props> = observer((props) => {
|
||||
dropdownArrowClassName={dropdownArrowClassName}
|
||||
hideIcon={hideIcon}
|
||||
placeholder={placeholder}
|
||||
isActive={isOpen}
|
||||
tooltip={tooltip}
|
||||
/>
|
||||
) : buttonVariant === "transparent-without-text" ? (
|
||||
@ -320,6 +328,7 @@ export const ModuleDropdown: React.FC<Props> = observer((props) => {
|
||||
hideIcon={hideIcon}
|
||||
hideText
|
||||
placeholder={placeholder}
|
||||
isActive={isOpen}
|
||||
tooltip={tooltip}
|
||||
/>
|
||||
) : null}
|
||||
|
@ -31,6 +31,7 @@ type ButtonProps = {
|
||||
dropdownArrowClassName: string;
|
||||
hideIcon?: boolean;
|
||||
hideText?: boolean;
|
||||
isActive?: boolean;
|
||||
highlightUrgent: boolean;
|
||||
priority: TIssuePriorities;
|
||||
tooltip: boolean;
|
||||
@ -181,6 +182,7 @@ const TransparentButton = (props: ButtonProps) => {
|
||||
dropdownArrowClassName,
|
||||
hideIcon = false,
|
||||
hideText = false,
|
||||
isActive = false,
|
||||
highlightUrgent,
|
||||
priority,
|
||||
tooltip,
|
||||
@ -207,6 +209,7 @@ const TransparentButton = (props: ButtonProps) => {
|
||||
"px-0.5": hideText,
|
||||
// highlight the whole button if text is hidden and priority is urgent
|
||||
"bg-red-500 border-red-500": priority === "urgent" && hideText && highlightUrgent,
|
||||
"bg-custom-background-80": isActive,
|
||||
},
|
||||
className
|
||||
)}
|
||||
@ -312,7 +315,13 @@ export const PriorityDropdown: React.FC<Props> = (props) => {
|
||||
as="div"
|
||||
ref={dropdownRef}
|
||||
tabIndex={tabIndex}
|
||||
className={cn("h-full", className)}
|
||||
className={cn(
|
||||
"h-full",
|
||||
{
|
||||
"bg-custom-background-80": isOpen,
|
||||
},
|
||||
className
|
||||
)}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
disabled={disabled}
|
||||
@ -402,6 +411,7 @@ export const PriorityDropdown: React.FC<Props> = (props) => {
|
||||
dropdownArrow={dropdownArrow && !disabled}
|
||||
dropdownArrowClassName={dropdownArrowClassName}
|
||||
hideIcon={hideIcon}
|
||||
isActive={isOpen}
|
||||
tooltip={tooltip}
|
||||
/>
|
||||
) : buttonVariant === "transparent-without-text" ? (
|
||||
@ -414,6 +424,7 @@ export const PriorityDropdown: React.FC<Props> = (props) => {
|
||||
dropdownArrow={dropdownArrow && !disabled}
|
||||
dropdownArrowClassName={dropdownArrowClassName}
|
||||
hideIcon={hideIcon}
|
||||
isActive={isOpen}
|
||||
tooltip={tooltip}
|
||||
hideText
|
||||
/>
|
||||
|
@ -30,6 +30,7 @@ type ButtonProps = {
|
||||
dropdownArrowClassName: string;
|
||||
hideIcon?: boolean;
|
||||
hideText?: boolean;
|
||||
isActive?: boolean;
|
||||
state: IState | undefined;
|
||||
tooltip: boolean;
|
||||
};
|
||||
@ -41,6 +42,7 @@ const BorderButton = (props: ButtonProps) => {
|
||||
dropdownArrowClassName,
|
||||
hideIcon = false,
|
||||
hideText = false,
|
||||
isActive = false,
|
||||
state,
|
||||
tooltip,
|
||||
} = props;
|
||||
@ -50,6 +52,9 @@ const BorderButton = (props: ButtonProps) => {
|
||||
<div
|
||||
className={cn(
|
||||
"h-full flex items-center gap-1.5 border-[0.5px] border-custom-border-300 hover:bg-custom-background-80 rounded text-xs px-2 py-0.5",
|
||||
{
|
||||
"bg-custom-background-80": isActive,
|
||||
},
|
||||
className
|
||||
)}
|
||||
>
|
||||
@ -111,6 +116,7 @@ const TransparentButton = (props: ButtonProps) => {
|
||||
dropdownArrowClassName,
|
||||
hideIcon = false,
|
||||
hideText = false,
|
||||
isActive = false,
|
||||
state,
|
||||
tooltip,
|
||||
} = props;
|
||||
@ -120,6 +126,9 @@ const TransparentButton = (props: ButtonProps) => {
|
||||
<div
|
||||
className={cn(
|
||||
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 hover:bg-custom-background-80",
|
||||
{
|
||||
"bg-custom-background-80": isActive,
|
||||
},
|
||||
className
|
||||
)}
|
||||
>
|
||||
@ -251,6 +260,7 @@ export const StateDropdown: React.FC<Props> = observer((props) => {
|
||||
dropdownArrow={dropdownArrow && !disabled}
|
||||
dropdownArrowClassName={dropdownArrowClassName}
|
||||
hideIcon={hideIcon}
|
||||
isActive={isOpen}
|
||||
tooltip={tooltip}
|
||||
/>
|
||||
) : buttonVariant === "border-without-text" ? (
|
||||
@ -260,6 +270,7 @@ export const StateDropdown: React.FC<Props> = observer((props) => {
|
||||
dropdownArrow={dropdownArrow && !disabled}
|
||||
dropdownArrowClassName={dropdownArrowClassName}
|
||||
hideIcon={hideIcon}
|
||||
isActive={isOpen}
|
||||
tooltip={tooltip}
|
||||
hideText
|
||||
/>
|
||||
@ -289,6 +300,7 @@ export const StateDropdown: React.FC<Props> = observer((props) => {
|
||||
dropdownArrow={dropdownArrow && !disabled}
|
||||
dropdownArrowClassName={dropdownArrowClassName}
|
||||
hideIcon={hideIcon}
|
||||
isActive={isOpen}
|
||||
tooltip={tooltip}
|
||||
/>
|
||||
) : buttonVariant === "transparent-without-text" ? (
|
||||
@ -298,6 +310,7 @@ export const StateDropdown: React.FC<Props> = observer((props) => {
|
||||
dropdownArrow={dropdownArrow && !disabled}
|
||||
dropdownArrowClassName={dropdownArrowClassName}
|
||||
hideIcon={hideIcon}
|
||||
isActive={isOpen}
|
||||
tooltip={tooltip}
|
||||
hideText
|
||||
/>
|
||||
|
@ -64,6 +64,7 @@ export const IssueParentSelect: React.FC<TIssueParentSelect> = observer((props)
|
||||
{
|
||||
"cursor-not-allowed": disabled,
|
||||
"hover:bg-custom-background-80": !disabled,
|
||||
"bg-custom-background-80": isParentIssueModalOpen,
|
||||
},
|
||||
className
|
||||
)}
|
||||
@ -72,15 +73,20 @@ export const IssueParentSelect: React.FC<TIssueParentSelect> = observer((props)
|
||||
>
|
||||
{issue.parent_id && parentIssue ? (
|
||||
<div className="flex items-center gap-1 bg-green-500/20 text-green-700 rounded px-1.5 py-1">
|
||||
<Link
|
||||
href={`/${workspaceSlug}/projects/${projectId}/issues/${parentIssue?.id}`}
|
||||
className="text-xs font-medium"
|
||||
>
|
||||
{parentIssueProjectDetails?.identifier}-{parentIssue.sequence_id}
|
||||
</Link>
|
||||
<Tooltip tooltipHeading="Title" tooltipContent={parentIssue.name}>
|
||||
<Link
|
||||
href={`/${workspaceSlug}/projects/${projectId}/issues/${parentIssue?.id}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-xs font-medium mt-0.5"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
{parentIssueProjectDetails?.identifier}-{parentIssue.sequence_id}
|
||||
</Link>
|
||||
</Tooltip>
|
||||
|
||||
{!disabled && (
|
||||
<Tooltip tooltipContent="Remove">
|
||||
<Tooltip tooltipContent="Remove" position="bottom">
|
||||
<span
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
@ -96,7 +102,15 @@ export const IssueParentSelect: React.FC<TIssueParentSelect> = observer((props)
|
||||
) : (
|
||||
<span className="text-sm text-custom-text-400">Add parent issue</span>
|
||||
)}
|
||||
{!disabled && <Pencil className="h-4 w-4 flex-shrink-0 hidden group-hover:inline" />}
|
||||
{!disabled && (
|
||||
<span
|
||||
className={cn("p-1 flex-shrink-0 opacity-0 group-hover:opacity-100", {
|
||||
"text-custom-text-400": !issue.parent_id && !parentIssue,
|
||||
})}
|
||||
>
|
||||
<Pencil className="h-2.5 w-2.5 flex-shrink-0" />
|
||||
</span>
|
||||
)}
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React from "react";
|
||||
import Link from "next/link";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { CircleDot, CopyPlus, Pencil, X, XCircle } from "lucide-react";
|
||||
// hooks
|
||||
@ -101,59 +102,72 @@ export const IssueRelationSelect: React.FC<TIssueRelationSelect> = observer((pro
|
||||
<button
|
||||
type="button"
|
||||
className={cn(
|
||||
"group flex items-center justify-between gap-2 px-2 py-0.5 rounded outline-none",
|
||||
"group flex items-center gap-2 px-2 py-0.5 rounded outline-none",
|
||||
{
|
||||
"cursor-not-allowed": disabled,
|
||||
"hover:bg-custom-background-80": !disabled,
|
||||
"bg-custom-background-80": isRelationModalOpen === relationKey,
|
||||
},
|
||||
className
|
||||
)}
|
||||
onClick={() => toggleRelationModal(relationKey)}
|
||||
disabled={disabled}
|
||||
>
|
||||
{relationIssueIds.length > 0 ? (
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
{relationIssueIds.map((relationIssueId) => {
|
||||
const currentIssue = issueMap[relationIssueId];
|
||||
if (!currentIssue) return;
|
||||
<div className="flex items-start justify-between w-full">
|
||||
{relationIssueIds.length > 0 ? (
|
||||
<div className="flex items-center gap-2 py-0.5 flex-wrap">
|
||||
{relationIssueIds.map((relationIssueId) => {
|
||||
const currentIssue = issueMap[relationIssueId];
|
||||
if (!currentIssue) return;
|
||||
|
||||
const projectDetails = getProjectById(currentIssue.project_id);
|
||||
const projectDetails = getProjectById(currentIssue.project_id);
|
||||
|
||||
return (
|
||||
<div
|
||||
key={relationIssueId}
|
||||
className={`group flex items-center gap-1 rounded px-1.5 py-1 ${issueRelationObject[relationKey].className}`}
|
||||
>
|
||||
<a
|
||||
href={`/${workspaceSlug}/projects/${projectDetails?.id}/issues/${currentIssue.id}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-xs font-medium"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
return (
|
||||
<div
|
||||
key={relationIssueId}
|
||||
className={`group flex items-center gap-1 rounded px-1.5 pt-1 pb-1 leading-3 hover:bg-custom-background-90 ${issueRelationObject[relationKey].className}`}
|
||||
>
|
||||
{`${projectDetails?.identifier}-${currentIssue?.sequence_id}`}
|
||||
</a>
|
||||
{!disabled && (
|
||||
<Tooltip tooltipContent="Remove">
|
||||
<span
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
removeRelation(workspaceSlug, projectId, issueId, relationKey, relationIssueId);
|
||||
}}
|
||||
<Tooltip tooltipHeading="Title" tooltipContent={currentIssue.name}>
|
||||
<Link
|
||||
href={`/${workspaceSlug}/projects/${projectDetails?.id}/issues/${currentIssue.id}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-xs font-medium mt-0.5"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<X className="h-2.5 w-2.5 text-custom-text-300 hover:text-red-500" />
|
||||
</span>
|
||||
{`${projectDetails?.identifier}-${currentIssue?.sequence_id}`}
|
||||
</Link>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
) : (
|
||||
<span className="text-sm text-custom-text-400">{issueRelationObject[relationKey].placeholder}</span>
|
||||
)}
|
||||
{!disabled && <Pencil className="h-4 w-4 flex-shrink-0 hidden group-hover:inline" />}
|
||||
{!disabled && (
|
||||
<Tooltip tooltipContent="Remove" position="bottom">
|
||||
<span
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
removeRelation(workspaceSlug, projectId, issueId, relationKey, relationIssueId);
|
||||
}}
|
||||
>
|
||||
<X className="h-2.5 w-2.5 text-custom-text-300 hover:text-red-500" />
|
||||
</span>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
) : (
|
||||
<span className="text-sm text-custom-text-400">{issueRelationObject[relationKey].placeholder}</span>
|
||||
)}
|
||||
{!disabled && (
|
||||
<span
|
||||
className={cn("p-1 flex-shrink-0 opacity-0 group-hover:opacity-100", {
|
||||
"text-custom-text-400": relationIssueIds.length === 0,
|
||||
})}
|
||||
>
|
||||
<Pencil className="h-2.5 w-2.5 flex-shrink-0" />
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
|
@ -184,7 +184,7 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
|
||||
projectId={projectId?.toString() ?? ""}
|
||||
placeholder="Add assignees"
|
||||
multiple
|
||||
buttonVariant={issue?.assignee_ids?.length > 0 ? "transparent-without-text" : "transparent-with-text"}
|
||||
buttonVariant={issue?.assignee_ids?.length > 1 ? "transparent-without-text" : "transparent-with-text"}
|
||||
className="w-3/5 flex-grow group"
|
||||
buttonContainerClassName="w-full text-left"
|
||||
buttonClassName={`text-sm justify-between ${
|
||||
@ -233,6 +233,7 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
|
||||
buttonClassName={`text-sm ${issue?.start_date ? "" : "text-custom-text-400"}`}
|
||||
hideIcon
|
||||
clearIconClassName="h-3 w-3 hidden group-hover:inline"
|
||||
showPlaceholderIcon
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -257,6 +258,7 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
|
||||
buttonClassName={`text-sm ${issue?.target_date ? "" : "text-custom-text-400"}`}
|
||||
hideIcon
|
||||
clearIconClassName="h-3 w-3 hidden group-hover:inline"
|
||||
showPlaceholderIcon
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -332,8 +334,8 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2 min-h-8">
|
||||
<div className="flex items-center gap-1 w-2/5 flex-shrink-0 text-sm text-custom-text-300">
|
||||
<div className="flex gap-2 min-h-8">
|
||||
<div className="flex gap-1 pt-2 w-2/5 flex-shrink-0 text-sm text-custom-text-300">
|
||||
<RelatedIcon className="h-4 w-4 flex-shrink-0" />
|
||||
<span>Relates to</span>
|
||||
</div>
|
||||
@ -347,8 +349,8 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2 min-h-8">
|
||||
<div className="flex items-center gap-1 w-2/5 flex-shrink-0 text-sm text-custom-text-300">
|
||||
<div className="flex gap-2 min-h-8">
|
||||
<div className="flex gap-1 pt-2 w-2/5 flex-shrink-0 text-sm text-custom-text-300">
|
||||
<XCircle className="h-4 w-4 flex-shrink-0" />
|
||||
<span>Blocking</span>
|
||||
</div>
|
||||
@ -362,8 +364,8 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2 min-h-8">
|
||||
<div className="flex items-center gap-1 w-2/5 flex-shrink-0 text-sm text-custom-text-300">
|
||||
<div className="flex gap-2 min-h-8">
|
||||
<div className="flex gap-1 pt-2 w-2/5 flex-shrink-0 text-sm text-custom-text-300">
|
||||
<CircleDot className="h-4 w-4 flex-shrink-0" />
|
||||
<span>Blocked by</span>
|
||||
</div>
|
||||
@ -377,8 +379,8 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2 min-h-8">
|
||||
<div className="flex items-center gap-1 w-2/5 flex-shrink-0 text-sm text-custom-text-300">
|
||||
<div className="flex gap-2 min-h-8">
|
||||
<div className="flex gap-1 pt-2 w-2/5 flex-shrink-0 text-sm text-custom-text-300">
|
||||
<CopyPlus className="h-4 w-4 flex-shrink-0" />
|
||||
<span>Duplicate of</span>
|
||||
</div>
|
||||
|
@ -99,7 +99,7 @@ export const PeekOverviewProperties: FC<IPeekOverviewProperties> = observer((pro
|
||||
projectId={projectId}
|
||||
placeholder="Add assignees"
|
||||
multiple
|
||||
buttonVariant={issue?.assignee_ids?.length > 0 ? "transparent-without-text" : "transparent-with-text"}
|
||||
buttonVariant={issue?.assignee_ids?.length > 1 ? "transparent-without-text" : "transparent-with-text"}
|
||||
className="w-3/4 flex-grow group"
|
||||
buttonContainerClassName="w-full text-left"
|
||||
buttonClassName={`text-sm justify-between ${issue?.assignee_ids.length > 0 ? "" : "text-custom-text-400"}`}
|
||||
@ -148,6 +148,7 @@ export const PeekOverviewProperties: FC<IPeekOverviewProperties> = observer((pro
|
||||
buttonClassName={`text-sm ${issue?.start_date ? "" : "text-custom-text-400"}`}
|
||||
hideIcon
|
||||
clearIconClassName="h-3 w-3 hidden group-hover:inline"
|
||||
showPlaceholderIcon
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -173,6 +174,7 @@ export const PeekOverviewProperties: FC<IPeekOverviewProperties> = observer((pro
|
||||
buttonClassName={`text-sm ${issue?.target_date ? "" : "text-custom-text-400"}`}
|
||||
hideIcon
|
||||
clearIconClassName="h-3 w-3 hidden group-hover:inline"
|
||||
showPlaceholderIcon
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -251,8 +253,8 @@ export const PeekOverviewProperties: FC<IPeekOverviewProperties> = observer((pro
|
||||
</div>
|
||||
|
||||
{/* relates to */}
|
||||
<div className="flex items-center gap-3 min-h-8">
|
||||
<div className="flex items-center gap-1 w-1/4 flex-shrink-0 text-sm text-custom-text-300">
|
||||
<div className="flex gap-3 min-h-8">
|
||||
<div className="flex pt-2 gap-1 w-1/4 flex-shrink-0 text-sm text-custom-text-300">
|
||||
<RelatedIcon className="h-4 w-4 flex-shrink-0" />
|
||||
<span>Relates to</span>
|
||||
</div>
|
||||
@ -267,8 +269,8 @@ export const PeekOverviewProperties: FC<IPeekOverviewProperties> = observer((pro
|
||||
</div>
|
||||
|
||||
{/* blocking */}
|
||||
<div className="flex items-center gap-3 min-h-8">
|
||||
<div className="flex items-center gap-1 w-1/4 flex-shrink-0 text-sm text-custom-text-300">
|
||||
<div className="flex gap-3 min-h-8">
|
||||
<div className="flex pt-2 gap-1 w-1/4 flex-shrink-0 text-sm text-custom-text-300">
|
||||
<XCircle className="h-4 w-4 flex-shrink-0" />
|
||||
<span>Blocking</span>
|
||||
</div>
|
||||
@ -283,8 +285,8 @@ export const PeekOverviewProperties: FC<IPeekOverviewProperties> = observer((pro
|
||||
</div>
|
||||
|
||||
{/* blocked by */}
|
||||
<div className="flex items-center gap-3 min-h-8">
|
||||
<div className="flex items-center gap-1 w-1/4 flex-shrink-0 text-sm text-custom-text-300">
|
||||
<div className="flex gap-3 min-h-8">
|
||||
<div className="flex pt-2 gap-1 w-1/4 flex-shrink-0 text-sm text-custom-text-300">
|
||||
<CircleDot className="h-4 w-4 flex-shrink-0" />
|
||||
<span>Blocked by</span>
|
||||
</div>
|
||||
@ -299,8 +301,8 @@ export const PeekOverviewProperties: FC<IPeekOverviewProperties> = observer((pro
|
||||
</div>
|
||||
|
||||
{/* duplicate of */}
|
||||
<div className="flex items-center gap-3 min-h-8">
|
||||
<div className="flex items-center gap-1 w-1/4 flex-shrink-0 text-sm text-custom-text-300">
|
||||
<div className="flex gap-3 min-h-8">
|
||||
<div className="flex pt-2 gap-1 w-1/4 flex-shrink-0 text-sm text-custom-text-300">
|
||||
<CopyPlus className="h-4 w-4 flex-shrink-0" />
|
||||
<span>Duplicate of</span>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user