[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
|
|
@ -19,7 +19,7 @@ import { useIssuesActions } from "@/hooks/use-issues-actions";
|
|||
import { IQuickActionProps } from "../list/list-view-types";
|
||||
import { handleDragDrop } from "./utils";
|
||||
|
||||
type CalendarStoreType =
|
||||
export type CalendarStoreType =
|
||||
| EIssuesStoreType.PROJECT
|
||||
| EIssuesStoreType.MODULE
|
||||
| EIssuesStoreType.CYCLE
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ import { Tooltip, ControlLink } from "@plane/ui";
|
|||
// helpers
|
||||
import { cn } from "@/helpers/common.helper";
|
||||
// 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 useOutsideClickDetector from "@/hooks/use-outside-click-detector";
|
||||
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";
|
||||
// local components
|
||||
import { TRenderQuickActions } from "../list/list-view-types";
|
||||
import { CalendarStoreType } from "./base-calendar-root";
|
||||
|
||||
type Props = {
|
||||
issue: TIssue;
|
||||
|
|
@ -41,6 +43,8 @@ export const CalendarIssueBlock = observer(
|
|||
const { getIsIssuePeeked } = useIssueDetail();
|
||||
const { handleRedirection } = useIssuePeekOverviewRedirection();
|
||||
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 || "";
|
||||
|
||||
|
|
@ -103,6 +107,7 @@ export const CalendarIssueBlock = observer(
|
|||
issueId={issue.id}
|
||||
projectId={issue.project_id}
|
||||
textContainerClassName="text-sm md:text-xs text-custom-text-300"
|
||||
displayProperties={issuesFilter?.issueFilters?.displayProperties}
|
||||
/>
|
||||
)}
|
||||
<Tooltip tooltipContent={issue.name} isMobile={isMobile}>
|
||||
|
|
|
|||
|
|
@ -50,10 +50,11 @@ export const DisplayFiltersSelection: React.FC<Props> = observer((props) => {
|
|||
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">
|
||||
{/* display properties */}
|
||||
{layoutDisplayFiltersOptions?.display_properties && (
|
||||
{layoutDisplayFiltersOptions?.display_properties && layoutDisplayFiltersOptions.display_properties.length > 0 && (
|
||||
<div className="py-2">
|
||||
<FilterDisplayProperties
|
||||
displayProperties={displayProperties}
|
||||
displayPropertiesToRender={layoutDisplayFiltersOptions.display_properties}
|
||||
handleUpdate={handleDisplayPropertiesUpdate}
|
||||
cycleViewDisabled={cycleViewDisabled}
|
||||
moduleViewDisabled={moduleViewDisabled}
|
||||
|
|
|
|||
|
|
@ -1,29 +1,50 @@
|
|||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { IIssueDisplayProperties } from "@plane/types";
|
||||
// components
|
||||
import { ISSUE_DISPLAY_PROPERTIES } from "@/constants/issue";
|
||||
import { FilterHeader } from "../helpers/filter-header";
|
||||
import { useParams } from "next/navigation";
|
||||
// types
|
||||
import { IIssueDisplayProperties } from "@plane/types";
|
||||
// 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 = {
|
||||
displayProperties: IIssueDisplayProperties;
|
||||
displayPropertiesToRender: (keyof IIssueDisplayProperties)[];
|
||||
handleUpdate: (updatedDisplayProperties: Partial<IIssueDisplayProperties>) => void;
|
||||
cycleViewDisabled?: boolean;
|
||||
moduleViewDisabled?: boolean;
|
||||
};
|
||||
|
||||
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);
|
||||
// derived values
|
||||
const projectId = !!routerProjectId ? routerProjectId?.toString() : undefined;
|
||||
|
||||
// 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) => {
|
||||
if (cycleViewDisabled && property.key === "cycle") return false;
|
||||
if (moduleViewDisabled && property.key === "modules") return false;
|
||||
return true;
|
||||
if (!displayPropertiesToRender.includes(property.key)) return false;
|
||||
switch (property.key) {
|
||||
case "cycle":
|
||||
return !cycleViewDisabled;
|
||||
case "modules":
|
||||
return !moduleViewDisabled;
|
||||
default:
|
||||
return shouldRenderDisplayProperty({ workspaceSlug: workspaceSlug?.toString(), projectId, key: property.key });
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ interface IBaseGanttRoot {
|
|||
isCompletedCycle?: boolean;
|
||||
}
|
||||
|
||||
type GanttStoreType =
|
||||
export type GanttStoreType =
|
||||
| EIssuesStoreType.PROJECT
|
||||
| EIssuesStoreType.MODULE
|
||||
| EIssuesStoreType.CYCLE
|
||||
|
|
|
|||
|
|
@ -7,11 +7,14 @@ import { Tooltip, ControlLink } from "@plane/ui";
|
|||
// helpers
|
||||
import { renderFormattedDate } from "@/helpers/date-time.helper";
|
||||
// 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 { usePlatformOS } from "@/hooks/use-platform-os";
|
||||
// plane web components
|
||||
import { IssueIdentifier } from "@/plane-web/components/issues";
|
||||
// local types
|
||||
import { GanttStoreType } from "./base-gantt-root";
|
||||
|
||||
type Props = {
|
||||
issueId: string;
|
||||
|
|
@ -80,6 +83,8 @@ export const IssueGanttSidebarBlock: React.FC<Props> = observer((props) => {
|
|||
issue: { getIssueById },
|
||||
} = useIssueDetail();
|
||||
const { isMobile } = usePlatformOS();
|
||||
const storeType = useIssueStoreType() as GanttStoreType;
|
||||
const { issuesFilter } = useIssues(storeType);
|
||||
|
||||
// handlers
|
||||
const { handleRedirection } = useIssuePeekOverviewRedirection();
|
||||
|
|
@ -102,6 +107,7 @@ export const IssueGanttSidebarBlock: React.FC<Props> = observer((props) => {
|
|||
issueId={issueDetails.id}
|
||||
projectId={issueDetails.project_id}
|
||||
textContainerClassName="text-xs text-custom-text-300"
|
||||
displayProperties={issuesFilter?.issueFilters?.displayProperties}
|
||||
/>
|
||||
)}
|
||||
<Tooltip tooltipContent={issueDetails?.name} isMobile={isMobile}>
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ import { IssueIdentifier } from "@/plane-web/components/issues";
|
|||
// local components
|
||||
import { TRenderQuickActions } from "../list/list-view-types";
|
||||
import { IssueProperties } from "../properties/all-properties";
|
||||
import { WithDisplayPropertiesHOC } from "../properties/with-display-properties-HOC";
|
||||
import { getIssueBlockId } from "../utils";
|
||||
|
||||
interface IssueBlockProps {
|
||||
|
|
@ -62,28 +61,27 @@ const KanbanIssueDetailsBlock: React.FC<IssueDetailsBlockProps> = observer((prop
|
|||
|
||||
return (
|
||||
<>
|
||||
<WithDisplayPropertiesHOC displayProperties={displayProperties || {}} displayPropertyKey="key">
|
||||
<div className="relative">
|
||||
{issue.project_id && (
|
||||
<IssueIdentifier
|
||||
issueId={issue.id}
|
||||
projectId={issue.project_id}
|
||||
textContainerClassName="line-clamp-1 text-xs text-custom-text-300"
|
||||
/>
|
||||
)}
|
||||
<div
|
||||
className={cn("absolute -top-1 right-0", {
|
||||
"hidden group-hover/kanban-block:block": !isMobile,
|
||||
})}
|
||||
onClick={handleEventPropagation}
|
||||
>
|
||||
{quickActions({
|
||||
issue,
|
||||
parentRef: cardRef,
|
||||
})}
|
||||
</div>
|
||||
<div className="relative">
|
||||
{issue.project_id && (
|
||||
<IssueIdentifier
|
||||
issueId={issue.id}
|
||||
projectId={issue.project_id}
|
||||
textContainerClassName="line-clamp-1 text-xs text-custom-text-300"
|
||||
displayProperties={displayProperties}
|
||||
/>
|
||||
)}
|
||||
<div
|
||||
className={cn("absolute -top-1 right-0", {
|
||||
"hidden group-hover/kanban-block:block": !isMobile,
|
||||
})}
|
||||
onClick={handleEventPropagation}
|
||||
>
|
||||
{quickActions({
|
||||
issue,
|
||||
parentRef: cardRef,
|
||||
})}
|
||||
</div>
|
||||
</WithDisplayPropertiesHOC>
|
||||
</div>
|
||||
|
||||
<Tooltip tooltipContent={issue.name} isMobile={isMobile} renderByDefault={false}>
|
||||
<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
|
||||
const keyMinWidth = (projectIdentifier?.length ?? 0) * 7;
|
||||
const keyMinWidth = displayProperties?.key ? (projectIdentifier?.length ?? 0) * 7 : 0;
|
||||
|
||||
return (
|
||||
<Row
|
||||
|
|
@ -184,13 +184,14 @@ export const IssueBlock = observer((props: IssueBlockProps) => {
|
|||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
{displayProperties && displayProperties?.key && (
|
||||
{displayProperties && (displayProperties.key || displayProperties.issue_type) && (
|
||||
<div className="flex-shrink-0" style={{ minWidth: `${keyMinWidth}px` }}>
|
||||
{issue.project_id && (
|
||||
<IssueIdentifier
|
||||
issueId={issueId}
|
||||
projectId={issue.project_id}
|
||||
textContainerClassName="text-xs font-medium text-custom-text-300"
|
||||
displayProperties={displayProperties}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ import { usePlatformOS } from "@/hooks/use-platform-os";
|
|||
import { IssueIdentifier } from "@/plane-web/components/issues";
|
||||
// local components
|
||||
import { TRenderQuickActions } from "../list/list-view-types";
|
||||
import { WithDisplayPropertiesHOC } from "../properties/with-display-properties-HOC";
|
||||
import { IssueColumn } from "./issue-column";
|
||||
|
||||
interface Props {
|
||||
|
|
@ -222,7 +221,9 @@ const IssueRowDetails = observer((props: IssueRowDetailsProps) => {
|
|||
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
|
||||
const keyMinWidth = (getProjectIdentifierById(issueDetail.project_id)?.length ?? 0 + 5) * 7;
|
||||
const keyMinWidth = displayProperties?.key
|
||||
? (getProjectIdentifierById(issueDetail.project_id)?.length ?? 0 + 5) * 7
|
||||
: 0;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
@ -280,7 +281,7 @@ const IssueRowDetails = observer((props: IssueRowDetailsProps) => {
|
|||
{/* sub issues indentation */}
|
||||
{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">
|
||||
<p className={`flex font-medium leading-7`} style={{ minWidth: `${keyMinWidth}px` }}>
|
||||
{issueDetail.project_id && (
|
||||
|
|
@ -288,11 +289,12 @@ const IssueRowDetails = observer((props: IssueRowDetailsProps) => {
|
|||
issueId={issueDetail.id}
|
||||
projectId={issueDetail.project_id}
|
||||
textContainerClassName="text-sm md:text-xs text-custom-text-300"
|
||||
displayProperties={displayProperties}
|
||||
/>
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</WithDisplayPropertiesHOC>
|
||||
)}
|
||||
|
||||
{/* sub-issues chevron */}
|
||||
<div className="grid place-items-center size-4">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue