[WEB-2421] chore: issue display properties and issue identifier improvements. (#5577)
* [WEB-2421] chore: issue display properties and issue identifier improvements. * chore: remove yarn.lock changes.
This commit is contained in:
parent
71f3c5c12a
commit
00b76300f5
15 changed files with 138 additions and 57 deletions
1
packages/types/src/view-props.d.ts
vendored
1
packages/types/src/view-props.d.ts
vendored
|
|
@ -127,6 +127,7 @@ export interface IIssueDisplayProperties {
|
||||||
updated_on?: boolean;
|
updated_on?: boolean;
|
||||||
modules?: boolean;
|
modules?: boolean;
|
||||||
cycle?: boolean;
|
cycle?: boolean;
|
||||||
|
issue_type?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TIssueKanbanFilters = {
|
export type TIssueKanbanFilters = {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
|
// types
|
||||||
|
import { IIssueDisplayProperties } from "@plane/types";
|
||||||
// helpers
|
// helpers
|
||||||
import { cn } from "@/helpers/common.helper";
|
import { cn } from "@/helpers/common.helper";
|
||||||
// hooks
|
// hooks
|
||||||
|
|
@ -8,6 +10,7 @@ type TIssueIdentifierBaseProps = {
|
||||||
projectId: string;
|
projectId: string;
|
||||||
size?: "xs" | "sm" | "md" | "lg";
|
size?: "xs" | "sm" | "md" | "lg";
|
||||||
textContainerClassName?: string;
|
textContainerClassName?: string;
|
||||||
|
displayProperties?: IIssueDisplayProperties | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
type TIssueIdentifierFromStore = TIssueIdentifierBaseProps & {
|
type TIssueIdentifierFromStore = TIssueIdentifierBaseProps & {
|
||||||
|
|
@ -22,7 +25,7 @@ type TIssueIdentifierWithDetails = TIssueIdentifierBaseProps & {
|
||||||
|
|
||||||
type TIssueIdentifierProps = TIssueIdentifierFromStore | TIssueIdentifierWithDetails;
|
type TIssueIdentifierProps = TIssueIdentifierFromStore | TIssueIdentifierWithDetails;
|
||||||
export const IssueIdentifier: React.FC<TIssueIdentifierProps> = observer((props) => {
|
export const IssueIdentifier: React.FC<TIssueIdentifierProps> = observer((props) => {
|
||||||
const { projectId, textContainerClassName } = props;
|
const { projectId, textContainerClassName, displayProperties } = props;
|
||||||
// store hooks
|
// store hooks
|
||||||
const { getProjectIdentifierById } = useProject();
|
const { getProjectIdentifierById } = useProject();
|
||||||
const {
|
const {
|
||||||
|
|
@ -34,6 +37,9 @@ export const IssueIdentifier: React.FC<TIssueIdentifierProps> = observer((props)
|
||||||
const issue = isUsingStoreData ? getIssueById(props.issueId) : null;
|
const issue = isUsingStoreData ? getIssueById(props.issueId) : null;
|
||||||
const projectIdentifier = isUsingStoreData ? getProjectIdentifierById(projectId) : props.projectIdentifier;
|
const projectIdentifier = isUsingStoreData ? getProjectIdentifierById(projectId) : props.projectIdentifier;
|
||||||
const issueSequenceId = isUsingStoreData ? issue?.sequence_id : props.issueSequenceId;
|
const issueSequenceId = isUsingStoreData ? issue?.sequence_id : props.issueSequenceId;
|
||||||
|
const shouldRenderIssueID = displayProperties ? displayProperties.key : true;
|
||||||
|
|
||||||
|
if (!shouldRenderIssueID) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center space-x-2">
|
<div className="flex items-center space-x-2">
|
||||||
|
|
|
||||||
18
web/ce/helpers/issue-filter.helper.ts
Normal file
18
web/ce/helpers/issue-filter.helper.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
// types
|
||||||
|
import { IIssueDisplayProperties } from "@plane/types";
|
||||||
|
|
||||||
|
export type TShouldRenderDisplayProperty = {
|
||||||
|
workspaceSlug: string;
|
||||||
|
projectId: string | undefined;
|
||||||
|
key: keyof IIssueDisplayProperties;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const shouldRenderDisplayProperty = (props: TShouldRenderDisplayProperty) => {
|
||||||
|
const { key } = props;
|
||||||
|
switch (key) {
|
||||||
|
case "issue_type":
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -19,7 +19,7 @@ import { useIssuesActions } from "@/hooks/use-issues-actions";
|
||||||
import { IQuickActionProps } from "../list/list-view-types";
|
import { IQuickActionProps } from "../list/list-view-types";
|
||||||
import { handleDragDrop } from "./utils";
|
import { handleDragDrop } from "./utils";
|
||||||
|
|
||||||
type CalendarStoreType =
|
export type CalendarStoreType =
|
||||||
| EIssuesStoreType.PROJECT
|
| EIssuesStoreType.PROJECT
|
||||||
| EIssuesStoreType.MODULE
|
| EIssuesStoreType.MODULE
|
||||||
| EIssuesStoreType.CYCLE
|
| EIssuesStoreType.CYCLE
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,8 @@ import { Tooltip, ControlLink } from "@plane/ui";
|
||||||
// helpers
|
// helpers
|
||||||
import { cn } from "@/helpers/common.helper";
|
import { cn } from "@/helpers/common.helper";
|
||||||
// hooks
|
// hooks
|
||||||
import { useIssueDetail, useProjectState } from "@/hooks/store";
|
import { useIssueDetail, useIssues, useProjectState } from "@/hooks/store";
|
||||||
|
import { useIssueStoreType } from "@/hooks/use-issue-layout-store";
|
||||||
import useIssuePeekOverviewRedirection from "@/hooks/use-issue-peek-overview-redirection";
|
import useIssuePeekOverviewRedirection from "@/hooks/use-issue-peek-overview-redirection";
|
||||||
import useOutsideClickDetector from "@/hooks/use-outside-click-detector";
|
import useOutsideClickDetector from "@/hooks/use-outside-click-detector";
|
||||||
import { usePlatformOS } from "@/hooks/use-platform-os";
|
import { usePlatformOS } from "@/hooks/use-platform-os";
|
||||||
|
|
@ -20,6 +21,7 @@ import { usePlatformOS } from "@/hooks/use-platform-os";
|
||||||
import { IssueIdentifier } from "@/plane-web/components/issues/issue-details";
|
import { IssueIdentifier } from "@/plane-web/components/issues/issue-details";
|
||||||
// local components
|
// local components
|
||||||
import { TRenderQuickActions } from "../list/list-view-types";
|
import { TRenderQuickActions } from "../list/list-view-types";
|
||||||
|
import { CalendarStoreType } from "./base-calendar-root";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
issue: TIssue;
|
issue: TIssue;
|
||||||
|
|
@ -41,6 +43,8 @@ export const CalendarIssueBlock = observer(
|
||||||
const { getIsIssuePeeked } = useIssueDetail();
|
const { getIsIssuePeeked } = useIssueDetail();
|
||||||
const { handleRedirection } = useIssuePeekOverviewRedirection();
|
const { handleRedirection } = useIssuePeekOverviewRedirection();
|
||||||
const { isMobile } = usePlatformOS();
|
const { isMobile } = usePlatformOS();
|
||||||
|
const storeType = useIssueStoreType() as CalendarStoreType;
|
||||||
|
const { issuesFilter } = useIssues(storeType);
|
||||||
|
|
||||||
const stateColor = getProjectStates(issue?.project_id)?.find((state) => state?.id == issue?.state_id)?.color || "";
|
const stateColor = getProjectStates(issue?.project_id)?.find((state) => state?.id == issue?.state_id)?.color || "";
|
||||||
|
|
||||||
|
|
@ -103,6 +107,7 @@ export const CalendarIssueBlock = observer(
|
||||||
issueId={issue.id}
|
issueId={issue.id}
|
||||||
projectId={issue.project_id}
|
projectId={issue.project_id}
|
||||||
textContainerClassName="text-sm md:text-xs text-custom-text-300"
|
textContainerClassName="text-sm md:text-xs text-custom-text-300"
|
||||||
|
displayProperties={issuesFilter?.issueFilters?.displayProperties}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Tooltip tooltipContent={issue.name} isMobile={isMobile}>
|
<Tooltip tooltipContent={issue.name} isMobile={isMobile}>
|
||||||
|
|
|
||||||
|
|
@ -50,10 +50,11 @@ export const DisplayFiltersSelection: React.FC<Props> = observer((props) => {
|
||||||
return (
|
return (
|
||||||
<div className="vertical-scrollbar scrollbar-sm relative h-full w-full divide-y divide-custom-border-200 overflow-hidden overflow-y-auto px-2.5">
|
<div className="vertical-scrollbar scrollbar-sm relative h-full w-full divide-y divide-custom-border-200 overflow-hidden overflow-y-auto px-2.5">
|
||||||
{/* display properties */}
|
{/* display properties */}
|
||||||
{layoutDisplayFiltersOptions?.display_properties && (
|
{layoutDisplayFiltersOptions?.display_properties && layoutDisplayFiltersOptions.display_properties.length > 0 && (
|
||||||
<div className="py-2">
|
<div className="py-2">
|
||||||
<FilterDisplayProperties
|
<FilterDisplayProperties
|
||||||
displayProperties={displayProperties}
|
displayProperties={displayProperties}
|
||||||
|
displayPropertiesToRender={layoutDisplayFiltersOptions.display_properties}
|
||||||
handleUpdate={handleDisplayPropertiesUpdate}
|
handleUpdate={handleDisplayPropertiesUpdate}
|
||||||
cycleViewDisabled={cycleViewDisabled}
|
cycleViewDisabled={cycleViewDisabled}
|
||||||
moduleViewDisabled={moduleViewDisabled}
|
moduleViewDisabled={moduleViewDisabled}
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,50 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { IIssueDisplayProperties } from "@plane/types";
|
import { useParams } from "next/navigation";
|
||||||
// components
|
|
||||||
import { ISSUE_DISPLAY_PROPERTIES } from "@/constants/issue";
|
|
||||||
import { FilterHeader } from "../helpers/filter-header";
|
|
||||||
// types
|
// types
|
||||||
|
import { IIssueDisplayProperties } from "@plane/types";
|
||||||
// constants
|
// constants
|
||||||
|
import { ISSUE_DISPLAY_PROPERTIES } from "@/constants/issue";
|
||||||
|
// plane web helpers
|
||||||
|
import { shouldRenderDisplayProperty } from "@/plane-web/helpers/issue-filter.helper";
|
||||||
|
// components
|
||||||
|
import { FilterHeader } from "../helpers/filter-header";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
displayProperties: IIssueDisplayProperties;
|
displayProperties: IIssueDisplayProperties;
|
||||||
|
displayPropertiesToRender: (keyof IIssueDisplayProperties)[];
|
||||||
handleUpdate: (updatedDisplayProperties: Partial<IIssueDisplayProperties>) => void;
|
handleUpdate: (updatedDisplayProperties: Partial<IIssueDisplayProperties>) => void;
|
||||||
cycleViewDisabled?: boolean;
|
cycleViewDisabled?: boolean;
|
||||||
moduleViewDisabled?: boolean;
|
moduleViewDisabled?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FilterDisplayProperties: React.FC<Props> = observer((props) => {
|
export const FilterDisplayProperties: React.FC<Props> = observer((props) => {
|
||||||
const { displayProperties, handleUpdate, cycleViewDisabled = false, moduleViewDisabled = false } = props;
|
const {
|
||||||
|
displayProperties,
|
||||||
|
displayPropertiesToRender,
|
||||||
|
handleUpdate,
|
||||||
|
cycleViewDisabled = false,
|
||||||
|
moduleViewDisabled = false,
|
||||||
|
} = props;
|
||||||
|
// router
|
||||||
|
const { workspaceSlug, projectId: routerProjectId } = useParams();
|
||||||
|
// states
|
||||||
const [previewEnabled, setPreviewEnabled] = React.useState(true);
|
const [previewEnabled, setPreviewEnabled] = React.useState(true);
|
||||||
|
// derived values
|
||||||
|
const projectId = !!routerProjectId ? routerProjectId?.toString() : undefined;
|
||||||
|
|
||||||
// Filter out "cycle" and "module" keys if cycleViewDisabled or moduleViewDisabled is true
|
// Filter out "cycle" and "module" keys if cycleViewDisabled or moduleViewDisabled is true
|
||||||
|
// Also filter out display properties that should not be rendered
|
||||||
const filteredDisplayProperties = ISSUE_DISPLAY_PROPERTIES.filter((property) => {
|
const filteredDisplayProperties = ISSUE_DISPLAY_PROPERTIES.filter((property) => {
|
||||||
if (cycleViewDisabled && property.key === "cycle") return false;
|
if (!displayPropertiesToRender.includes(property.key)) return false;
|
||||||
if (moduleViewDisabled && property.key === "modules") return false;
|
switch (property.key) {
|
||||||
return true;
|
case "cycle":
|
||||||
|
return !cycleViewDisabled;
|
||||||
|
case "modules":
|
||||||
|
return !moduleViewDisabled;
|
||||||
|
default:
|
||||||
|
return shouldRenderDisplayProperty({ workspaceSlug: workspaceSlug?.toString(), projectId, key: property.key });
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ interface IBaseGanttRoot {
|
||||||
isCompletedCycle?: boolean;
|
isCompletedCycle?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
type GanttStoreType =
|
export type GanttStoreType =
|
||||||
| EIssuesStoreType.PROJECT
|
| EIssuesStoreType.PROJECT
|
||||||
| EIssuesStoreType.MODULE
|
| EIssuesStoreType.MODULE
|
||||||
| EIssuesStoreType.CYCLE
|
| EIssuesStoreType.CYCLE
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,14 @@ import { Tooltip, ControlLink } from "@plane/ui";
|
||||||
// helpers
|
// helpers
|
||||||
import { renderFormattedDate } from "@/helpers/date-time.helper";
|
import { renderFormattedDate } from "@/helpers/date-time.helper";
|
||||||
// hooks
|
// hooks
|
||||||
import { useIssueDetail, useProjectState } from "@/hooks/store";
|
import { useIssueDetail, useIssues, useProjectState } from "@/hooks/store";
|
||||||
|
import { useIssueStoreType } from "@/hooks/use-issue-layout-store";
|
||||||
import useIssuePeekOverviewRedirection from "@/hooks/use-issue-peek-overview-redirection";
|
import useIssuePeekOverviewRedirection from "@/hooks/use-issue-peek-overview-redirection";
|
||||||
import { usePlatformOS } from "@/hooks/use-platform-os";
|
import { usePlatformOS } from "@/hooks/use-platform-os";
|
||||||
// plane web components
|
// plane web components
|
||||||
import { IssueIdentifier } from "@/plane-web/components/issues";
|
import { IssueIdentifier } from "@/plane-web/components/issues";
|
||||||
|
// local types
|
||||||
|
import { GanttStoreType } from "./base-gantt-root";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
issueId: string;
|
issueId: string;
|
||||||
|
|
@ -80,6 +83,8 @@ export const IssueGanttSidebarBlock: React.FC<Props> = observer((props) => {
|
||||||
issue: { getIssueById },
|
issue: { getIssueById },
|
||||||
} = useIssueDetail();
|
} = useIssueDetail();
|
||||||
const { isMobile } = usePlatformOS();
|
const { isMobile } = usePlatformOS();
|
||||||
|
const storeType = useIssueStoreType() as GanttStoreType;
|
||||||
|
const { issuesFilter } = useIssues(storeType);
|
||||||
|
|
||||||
// handlers
|
// handlers
|
||||||
const { handleRedirection } = useIssuePeekOverviewRedirection();
|
const { handleRedirection } = useIssuePeekOverviewRedirection();
|
||||||
|
|
@ -102,6 +107,7 @@ export const IssueGanttSidebarBlock: React.FC<Props> = observer((props) => {
|
||||||
issueId={issueDetails.id}
|
issueId={issueDetails.id}
|
||||||
projectId={issueDetails.project_id}
|
projectId={issueDetails.project_id}
|
||||||
textContainerClassName="text-xs text-custom-text-300"
|
textContainerClassName="text-xs text-custom-text-300"
|
||||||
|
displayProperties={issuesFilter?.issueFilters?.displayProperties}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Tooltip tooltipContent={issueDetails?.name} isMobile={isMobile}>
|
<Tooltip tooltipContent={issueDetails?.name} isMobile={isMobile}>
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ import { IssueIdentifier } from "@/plane-web/components/issues";
|
||||||
// local components
|
// local components
|
||||||
import { TRenderQuickActions } from "../list/list-view-types";
|
import { TRenderQuickActions } from "../list/list-view-types";
|
||||||
import { IssueProperties } from "../properties/all-properties";
|
import { IssueProperties } from "../properties/all-properties";
|
||||||
import { WithDisplayPropertiesHOC } from "../properties/with-display-properties-HOC";
|
|
||||||
import { getIssueBlockId } from "../utils";
|
import { getIssueBlockId } from "../utils";
|
||||||
|
|
||||||
interface IssueBlockProps {
|
interface IssueBlockProps {
|
||||||
|
|
@ -62,28 +61,27 @@ const KanbanIssueDetailsBlock: React.FC<IssueDetailsBlockProps> = observer((prop
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<WithDisplayPropertiesHOC displayProperties={displayProperties || {}} displayPropertyKey="key">
|
<div className="relative">
|
||||||
<div className="relative">
|
{issue.project_id && (
|
||||||
{issue.project_id && (
|
<IssueIdentifier
|
||||||
<IssueIdentifier
|
issueId={issue.id}
|
||||||
issueId={issue.id}
|
projectId={issue.project_id}
|
||||||
projectId={issue.project_id}
|
textContainerClassName="line-clamp-1 text-xs text-custom-text-300"
|
||||||
textContainerClassName="line-clamp-1 text-xs text-custom-text-300"
|
displayProperties={displayProperties}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<div
|
<div
|
||||||
className={cn("absolute -top-1 right-0", {
|
className={cn("absolute -top-1 right-0", {
|
||||||
"hidden group-hover/kanban-block:block": !isMobile,
|
"hidden group-hover/kanban-block:block": !isMobile,
|
||||||
})}
|
})}
|
||||||
onClick={handleEventPropagation}
|
onClick={handleEventPropagation}
|
||||||
>
|
>
|
||||||
{quickActions({
|
{quickActions({
|
||||||
issue,
|
issue,
|
||||||
parentRef: cardRef,
|
parentRef: cardRef,
|
||||||
})}
|
})}
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</WithDisplayPropertiesHOC>
|
</div>
|
||||||
|
|
||||||
<Tooltip tooltipContent={issue.name} isMobile={isMobile} renderByDefault={false}>
|
<Tooltip tooltipContent={issue.name} isMobile={isMobile} renderByDefault={false}>
|
||||||
<div className="w-full line-clamp-1 text-sm text-custom-text-100">
|
<div className="w-full line-clamp-1 text-sm text-custom-text-100">
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ export const IssueBlock = observer((props: IssueBlockProps) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
//TODO: add better logic. This is to have a min width for ID/Key based on the length of project identifier
|
//TODO: add better logic. This is to have a min width for ID/Key based on the length of project identifier
|
||||||
const keyMinWidth = (projectIdentifier?.length ?? 0) * 7;
|
const keyMinWidth = displayProperties?.key ? (projectIdentifier?.length ?? 0) * 7 : 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row
|
<Row
|
||||||
|
|
@ -184,13 +184,14 @@ export const IssueBlock = observer((props: IssueBlockProps) => {
|
||||||
</div>
|
</div>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
{displayProperties && displayProperties?.key && (
|
{displayProperties && (displayProperties.key || displayProperties.issue_type) && (
|
||||||
<div className="flex-shrink-0" style={{ minWidth: `${keyMinWidth}px` }}>
|
<div className="flex-shrink-0" style={{ minWidth: `${keyMinWidth}px` }}>
|
||||||
{issue.project_id && (
|
{issue.project_id && (
|
||||||
<IssueIdentifier
|
<IssueIdentifier
|
||||||
issueId={issueId}
|
issueId={issueId}
|
||||||
projectId={issue.project_id}
|
projectId={issue.project_id}
|
||||||
textContainerClassName="text-xs font-medium text-custom-text-300"
|
textContainerClassName="text-xs font-medium text-custom-text-300"
|
||||||
|
displayProperties={displayProperties}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ import { usePlatformOS } from "@/hooks/use-platform-os";
|
||||||
import { IssueIdentifier } from "@/plane-web/components/issues";
|
import { IssueIdentifier } from "@/plane-web/components/issues";
|
||||||
// local components
|
// local components
|
||||||
import { TRenderQuickActions } from "../list/list-view-types";
|
import { TRenderQuickActions } from "../list/list-view-types";
|
||||||
import { WithDisplayPropertiesHOC } from "../properties/with-display-properties-HOC";
|
|
||||||
import { IssueColumn } from "./issue-column";
|
import { IssueColumn } from "./issue-column";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|
@ -222,7 +221,9 @@ const IssueRowDetails = observer((props: IssueRowDetailsProps) => {
|
||||||
const canSelectIssues = !disableUserActions && !selectionHelpers.isSelectionDisabled;
|
const canSelectIssues = !disableUserActions && !selectionHelpers.isSelectionDisabled;
|
||||||
|
|
||||||
//TODO: add better logic. This is to have a min width for ID/Key based on the length of project identifier
|
//TODO: add better logic. This is to have a min width for ID/Key based on the length of project identifier
|
||||||
const keyMinWidth = (getProjectIdentifierById(issueDetail.project_id)?.length ?? 0 + 5) * 7;
|
const keyMinWidth = displayProperties?.key
|
||||||
|
? (getProjectIdentifierById(issueDetail.project_id)?.length ?? 0 + 5) * 7
|
||||||
|
: 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
@ -280,7 +281,7 @@ const IssueRowDetails = observer((props: IssueRowDetailsProps) => {
|
||||||
{/* sub issues indentation */}
|
{/* sub issues indentation */}
|
||||||
{nestingLevel !== 0 && <div style={{ width: subIssueIndentation }} />}
|
{nestingLevel !== 0 && <div style={{ width: subIssueIndentation }} />}
|
||||||
|
|
||||||
<WithDisplayPropertiesHOC displayProperties={displayProperties} displayPropertyKey="key">
|
{(displayProperties?.key || displayProperties?.issue_type) && (
|
||||||
<div className="relative flex cursor-pointer items-center text-center text-xs hover:text-custom-text-100">
|
<div className="relative flex cursor-pointer items-center text-center text-xs hover:text-custom-text-100">
|
||||||
<p className={`flex font-medium leading-7`} style={{ minWidth: `${keyMinWidth}px` }}>
|
<p className={`flex font-medium leading-7`} style={{ minWidth: `${keyMinWidth}px` }}>
|
||||||
{issueDetail.project_id && (
|
{issueDetail.project_id && (
|
||||||
|
|
@ -288,11 +289,12 @@ const IssueRowDetails = observer((props: IssueRowDetailsProps) => {
|
||||||
issueId={issueDetail.id}
|
issueId={issueDetail.id}
|
||||||
projectId={issueDetail.project_id}
|
projectId={issueDetail.project_id}
|
||||||
textContainerClassName="text-sm md:text-xs text-custom-text-300"
|
textContainerClassName="text-sm md:text-xs text-custom-text-300"
|
||||||
|
displayProperties={displayProperties}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</WithDisplayPropertiesHOC>
|
)}
|
||||||
|
|
||||||
{/* sub-issues chevron */}
|
{/* sub-issues chevron */}
|
||||||
<div className="grid place-items-center size-4">
|
<div className="grid place-items-center size-4">
|
||||||
|
|
|
||||||
|
|
@ -108,14 +108,34 @@ export const ISSUE_FILTER_OPTIONS: {
|
||||||
// { key: "draft", title: "Draft Issues" },
|
// { key: "draft", title: "Draft Issues" },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const ISSUE_DISPLAY_PROPERTIES_KEYS: (keyof IIssueDisplayProperties)[] = [
|
||||||
|
"assignee",
|
||||||
|
"start_date",
|
||||||
|
"due_date",
|
||||||
|
"labels",
|
||||||
|
"key",
|
||||||
|
"priority",
|
||||||
|
"state",
|
||||||
|
"sub_issue_count",
|
||||||
|
"link",
|
||||||
|
"attachment_count",
|
||||||
|
"estimate",
|
||||||
|
"created_on",
|
||||||
|
"updated_on",
|
||||||
|
"modules",
|
||||||
|
"cycle",
|
||||||
|
"issue_type",
|
||||||
|
];
|
||||||
|
|
||||||
export const ISSUE_DISPLAY_PROPERTIES: {
|
export const ISSUE_DISPLAY_PROPERTIES: {
|
||||||
key: keyof IIssueDisplayProperties;
|
key: keyof IIssueDisplayProperties;
|
||||||
title: string;
|
title: string;
|
||||||
}[] = [
|
}[] = [
|
||||||
|
{ key: "key", title: "ID" },
|
||||||
|
{ key: "issue_type", title: "Issue Type" },
|
||||||
{ key: "assignee", title: "Assignee" },
|
{ key: "assignee", title: "Assignee" },
|
||||||
{ key: "start_date", title: "Start date" },
|
{ key: "start_date", title: "Start date" },
|
||||||
{ key: "due_date", title: "Due date" },
|
{ key: "due_date", title: "Due date" },
|
||||||
{ key: "key", title: "ID" },
|
|
||||||
{ key: "labels", title: "Labels" },
|
{ key: "labels", title: "Labels" },
|
||||||
{ key: "priority", title: "Priority" },
|
{ key: "priority", title: "Priority" },
|
||||||
{ key: "state", title: "State" },
|
{ key: "state", title: "State" },
|
||||||
|
|
@ -166,7 +186,7 @@ export const ISSUE_LAYOUTS: {
|
||||||
|
|
||||||
export interface ILayoutDisplayFiltersOptions {
|
export interface ILayoutDisplayFiltersOptions {
|
||||||
filters: (keyof IIssueFilterOptions)[];
|
filters: (keyof IIssueFilterOptions)[];
|
||||||
display_properties: boolean;
|
display_properties: (keyof IIssueDisplayProperties)[];
|
||||||
display_filters: {
|
display_filters: {
|
||||||
group_by?: TIssueGroupByOptions[];
|
group_by?: TIssueGroupByOptions[];
|
||||||
sub_group_by?: TIssueGroupByOptions[];
|
sub_group_by?: TIssueGroupByOptions[];
|
||||||
|
|
@ -185,7 +205,7 @@ export const ISSUE_DISPLAY_FILTERS_BY_LAYOUT: {
|
||||||
profile_issues: {
|
profile_issues: {
|
||||||
list: {
|
list: {
|
||||||
filters: ["priority", "state_group", "labels", "start_date", "target_date"],
|
filters: ["priority", "state_group", "labels", "start_date", "target_date"],
|
||||||
display_properties: true,
|
display_properties: ISSUE_DISPLAY_PROPERTIES_KEYS,
|
||||||
display_filters: {
|
display_filters: {
|
||||||
group_by: ["state_detail.group", "priority", "project", "labels", null],
|
group_by: ["state_detail.group", "priority", "project", "labels", null],
|
||||||
order_by: ["sort_order", "-created_at", "-updated_at", "start_date", "priority"],
|
order_by: ["sort_order", "-created_at", "-updated_at", "start_date", "priority"],
|
||||||
|
|
@ -198,7 +218,7 @@ export const ISSUE_DISPLAY_FILTERS_BY_LAYOUT: {
|
||||||
},
|
},
|
||||||
kanban: {
|
kanban: {
|
||||||
filters: ["priority", "state_group", "labels", "start_date", "target_date"],
|
filters: ["priority", "state_group", "labels", "start_date", "target_date"],
|
||||||
display_properties: true,
|
display_properties: ISSUE_DISPLAY_PROPERTIES_KEYS,
|
||||||
display_filters: {
|
display_filters: {
|
||||||
group_by: ["state_detail.group", "priority", "project", "labels"],
|
group_by: ["state_detail.group", "priority", "project", "labels"],
|
||||||
order_by: ["sort_order", "-created_at", "-updated_at", "start_date", "priority"],
|
order_by: ["sort_order", "-created_at", "-updated_at", "start_date", "priority"],
|
||||||
|
|
@ -224,7 +244,7 @@ export const ISSUE_DISPLAY_FILTERS_BY_LAYOUT: {
|
||||||
"target_date",
|
"target_date",
|
||||||
"issue_type",
|
"issue_type",
|
||||||
],
|
],
|
||||||
display_properties: true,
|
display_properties: ISSUE_DISPLAY_PROPERTIES_KEYS,
|
||||||
display_filters: {
|
display_filters: {
|
||||||
group_by: [
|
group_by: [
|
||||||
"state",
|
"state",
|
||||||
|
|
@ -249,7 +269,7 @@ export const ISSUE_DISPLAY_FILTERS_BY_LAYOUT: {
|
||||||
draft_issues: {
|
draft_issues: {
|
||||||
list: {
|
list: {
|
||||||
filters: ["priority", "state_group", "cycle", "module", "labels", "start_date", "target_date", "issue_type"],
|
filters: ["priority", "state_group", "cycle", "module", "labels", "start_date", "target_date", "issue_type"],
|
||||||
display_properties: true,
|
display_properties: ISSUE_DISPLAY_PROPERTIES_KEYS,
|
||||||
display_filters: {
|
display_filters: {
|
||||||
group_by: ["state_detail.group", "cycle", "module", "priority", "project", "labels", null],
|
group_by: ["state_detail.group", "cycle", "module", "priority", "project", "labels", null],
|
||||||
order_by: ["sort_order", "-created_at", "-updated_at", "start_date", "priority"],
|
order_by: ["sort_order", "-created_at", "-updated_at", "start_date", "priority"],
|
||||||
|
|
@ -262,7 +282,7 @@ export const ISSUE_DISPLAY_FILTERS_BY_LAYOUT: {
|
||||||
},
|
},
|
||||||
kanban: {
|
kanban: {
|
||||||
filters: ["priority", "state_group", "cycle", "module", "labels", "start_date", "target_date", "issue_type"],
|
filters: ["priority", "state_group", "cycle", "module", "labels", "start_date", "target_date", "issue_type"],
|
||||||
display_properties: true,
|
display_properties: ISSUE_DISPLAY_PROPERTIES_KEYS,
|
||||||
display_filters: {
|
display_filters: {
|
||||||
group_by: ["state_detail.group", "cycle", "module", "priority", "project", "labels"],
|
group_by: ["state_detail.group", "cycle", "module", "priority", "project", "labels"],
|
||||||
order_by: ["sort_order", "-created_at", "-updated_at", "start_date", "priority"],
|
order_by: ["sort_order", "-created_at", "-updated_at", "start_date", "priority"],
|
||||||
|
|
@ -287,7 +307,7 @@ export const ISSUE_DISPLAY_FILTERS_BY_LAYOUT: {
|
||||||
"start_date",
|
"start_date",
|
||||||
"target_date",
|
"target_date",
|
||||||
],
|
],
|
||||||
display_properties: true,
|
display_properties: ISSUE_DISPLAY_PROPERTIES_KEYS,
|
||||||
display_filters: {
|
display_filters: {
|
||||||
order_by: [],
|
order_by: [],
|
||||||
type: [null, "active", "backlog"],
|
type: [null, "active", "backlog"],
|
||||||
|
|
@ -309,7 +329,7 @@ export const ISSUE_DISPLAY_FILTERS_BY_LAYOUT: {
|
||||||
"start_date",
|
"start_date",
|
||||||
"target_date",
|
"target_date",
|
||||||
],
|
],
|
||||||
display_properties: true,
|
display_properties: ISSUE_DISPLAY_PROPERTIES_KEYS,
|
||||||
display_filters: {
|
display_filters: {
|
||||||
type: [null, "active", "backlog"],
|
type: [null, "active", "backlog"],
|
||||||
},
|
},
|
||||||
|
|
@ -334,7 +354,7 @@ export const ISSUE_DISPLAY_FILTERS_BY_LAYOUT: {
|
||||||
"target_date",
|
"target_date",
|
||||||
"issue_type",
|
"issue_type",
|
||||||
],
|
],
|
||||||
display_properties: true,
|
display_properties: ISSUE_DISPLAY_PROPERTIES_KEYS,
|
||||||
display_filters: {
|
display_filters: {
|
||||||
group_by: ["state", "priority", "cycle", "module", "labels", "assignees", "created_by", null],
|
group_by: ["state", "priority", "cycle", "module", "labels", "assignees", "created_by", null],
|
||||||
order_by: ["sort_order", "-created_at", "-updated_at", "start_date", "priority"],
|
order_by: ["sort_order", "-created_at", "-updated_at", "start_date", "priority"],
|
||||||
|
|
@ -359,7 +379,7 @@ export const ISSUE_DISPLAY_FILTERS_BY_LAYOUT: {
|
||||||
"target_date",
|
"target_date",
|
||||||
"issue_type",
|
"issue_type",
|
||||||
],
|
],
|
||||||
display_properties: true,
|
display_properties: ISSUE_DISPLAY_PROPERTIES_KEYS,
|
||||||
display_filters: {
|
display_filters: {
|
||||||
group_by: ["state", "priority", "cycle", "module", "labels", "assignees", "created_by"],
|
group_by: ["state", "priority", "cycle", "module", "labels", "assignees", "created_by"],
|
||||||
sub_group_by: ["state", "priority", "cycle", "module", "labels", "assignees", "created_by", null],
|
sub_group_by: ["state", "priority", "cycle", "module", "labels", "assignees", "created_by", null],
|
||||||
|
|
@ -384,7 +404,7 @@ export const ISSUE_DISPLAY_FILTERS_BY_LAYOUT: {
|
||||||
"start_date",
|
"start_date",
|
||||||
"issue_type",
|
"issue_type",
|
||||||
],
|
],
|
||||||
display_properties: false,
|
display_properties: ["key", "issue_type"],
|
||||||
display_filters: {
|
display_filters: {
|
||||||
type: [null, "active", "backlog"],
|
type: [null, "active", "backlog"],
|
||||||
},
|
},
|
||||||
|
|
@ -407,7 +427,7 @@ export const ISSUE_DISPLAY_FILTERS_BY_LAYOUT: {
|
||||||
"target_date",
|
"target_date",
|
||||||
"issue_type",
|
"issue_type",
|
||||||
],
|
],
|
||||||
display_properties: true,
|
display_properties: ISSUE_DISPLAY_PROPERTIES_KEYS,
|
||||||
display_filters: {
|
display_filters: {
|
||||||
order_by: ["sort_order", "-created_at", "-updated_at", "start_date", "priority"],
|
order_by: ["sort_order", "-created_at", "-updated_at", "start_date", "priority"],
|
||||||
type: [null, "active", "backlog"],
|
type: [null, "active", "backlog"],
|
||||||
|
|
@ -431,7 +451,7 @@ export const ISSUE_DISPLAY_FILTERS_BY_LAYOUT: {
|
||||||
"target_date",
|
"target_date",
|
||||||
"issue_type",
|
"issue_type",
|
||||||
],
|
],
|
||||||
display_properties: false,
|
display_properties: ["key", "issue_type"],
|
||||||
display_filters: {
|
display_filters: {
|
||||||
order_by: ["sort_order", "-created_at", "-updated_at", "start_date", "priority"],
|
order_by: ["sort_order", "-created_at", "-updated_at", "start_date", "priority"],
|
||||||
type: [null, "active", "backlog"],
|
type: [null, "active", "backlog"],
|
||||||
|
|
|
||||||
1
web/ee/helpers/issue-filter.helper.ts
Normal file
1
web/ee/helpers/issue-filter.helper.ts
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export * from "ce/helpers/issue-filter.helper";
|
||||||
|
|
@ -305,4 +305,5 @@ export const getComputedDisplayProperties = (
|
||||||
updated_on: displayProperties?.updated_on ?? true,
|
updated_on: displayProperties?.updated_on ?? true,
|
||||||
modules: displayProperties?.modules ?? true,
|
modules: displayProperties?.modules ?? true,
|
||||||
cycle: displayProperties?.cycle ?? true,
|
cycle: displayProperties?.cycle ?? true,
|
||||||
|
issue_type: displayProperties?.issue_type ?? true,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue