[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:
Prateek Shourya 2024-09-10 21:49:57 +05:30 committed by GitHub
parent 71f3c5c12a
commit 00b76300f5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 138 additions and 57 deletions

View file

@ -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

View file

@ -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}>

View file

@ -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}

View file

@ -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 (

View file

@ -28,7 +28,7 @@ interface IBaseGanttRoot {
isCompletedCycle?: boolean;
}
type GanttStoreType =
export type GanttStoreType =
| EIssuesStoreType.PROJECT
| EIssuesStoreType.MODULE
| EIssuesStoreType.CYCLE

View file

@ -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}>

View file

@ -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">

View file

@ -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>

View file

@ -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">