[WEB-4365] fix: dates display properties toggle #7262

This commit is contained in:
Vamsi Krishna
2025-06-30 16:10:06 +05:30
committed by GitHub
parent 4a065e14d0
commit 912246c592
2 changed files with 131 additions and 7 deletions

View File

@@ -1,12 +1,21 @@
// plane imports // plane imports
import { SyntheticEvent } from "react"; import { SyntheticEvent, useMemo } from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { CalendarCheck2, CalendarClock } from "lucide-react";
import { useTranslation } from "@plane/i18n";
import { IIssueDisplayProperties, TIssue } from "@plane/types"; import { IIssueDisplayProperties, TIssue } from "@plane/types";
import { getDate, renderFormattedPayloadDate } from "@plane/utils"; import { getDate, renderFormattedPayloadDate, shouldHighlightIssueDueDate } from "@plane/utils";
// components // components
import { PriorityDropdown, MemberDropdown, StateDropdown, DateRangeDropdown } from "@/components/dropdowns"; import {
PriorityDropdown,
MemberDropdown,
StateDropdown,
DateRangeDropdown,
DateDropdown,
} from "@/components/dropdowns";
// hooks // hooks
import { WithDisplayPropertiesHOC } from "@/components/issues/issue-layouts/properties/with-display-properties-HOC"; import { WithDisplayPropertiesHOC } from "@/components/issues/issue-layouts/properties/with-display-properties-HOC";
import { useProjectState } from "@/hooks/store/use-project-state";
type Props = { type Props = {
workspaceSlug: string; workspaceSlug: string;
@@ -27,6 +36,8 @@ type Props = {
export const SubIssuesListItemProperties: React.FC<Props> = observer((props) => { export const SubIssuesListItemProperties: React.FC<Props> = observer((props) => {
const { workspaceSlug, parentIssueId, issueId, disabled, updateSubIssue, displayProperties, issue } = props; const { workspaceSlug, parentIssueId, issueId, disabled, updateSubIssue, displayProperties, issue } = props;
const { t } = useTranslation();
const { getStateById } = useProjectState();
const handleEventPropagation = (e: SyntheticEvent<HTMLDivElement>) => { const handleEventPropagation = (e: SyntheticEvent<HTMLDivElement>) => {
e.stopPropagation(); e.stopPropagation();
@@ -49,10 +60,22 @@ export const SubIssuesListItemProperties: React.FC<Props> = observer((props) =>
} }
}; };
//derived values
const stateDetails = useMemo(() => getStateById(issue.state_id), [getStateById, issue.state_id]);
const shouldHighlight = useMemo(
() => shouldHighlightIssueDueDate(issue.target_date, stateDetails?.group),
[issue.target_date, stateDetails?.group]
);
// date range is enabled only when both dates are available and both dates are enabled
const isDateRangeEnabled: boolean = Boolean(
issue.start_date && issue.target_date && displayProperties?.start_date && displayProperties?.due_date
);
if (!displayProperties) return <></>; if (!displayProperties) return <></>;
const maxDate = getDate(issue.target_date); const maxDate = getDate(issue.target_date);
maxDate?.setDate(maxDate.getDate()); const minDate = getDate(issue.start_date);
return ( return (
<div className="relative flex items-center gap-2"> <div className="relative flex items-center gap-2">
<WithDisplayPropertiesHOC displayProperties={displayProperties} displayPropertyKey="state"> <WithDisplayPropertiesHOC displayProperties={displayProperties} displayPropertyKey="state">
@@ -104,7 +127,7 @@ export const SubIssuesListItemProperties: React.FC<Props> = observer((props) =>
<WithDisplayPropertiesHOC <WithDisplayPropertiesHOC
displayProperties={displayProperties} displayProperties={displayProperties}
displayPropertyKey={["start_date", "due_date"]} displayPropertyKey={["start_date", "due_date"]}
shouldRenderProperty={(properties) => !!(properties.start_date || properties.due_date)} shouldRenderProperty={() => isDateRangeEnabled}
> >
<div className="h-5" onFocus={handleEventPropagation} onClick={handleEventPropagation}> <div className="h-5" onFocus={handleEventPropagation} onClick={handleEventPropagation}>
<DateRangeDropdown <DateRangeDropdown
@@ -122,6 +145,7 @@ export const SubIssuesListItemProperties: React.FC<Props> = observer((props) =>
isClearable isClearable
mergeDates mergeDates
buttonVariant={issue.start_date || issue.target_date ? "border-with-text" : "border-without-text"} buttonVariant={issue.start_date || issue.target_date ? "border-with-text" : "border-without-text"}
buttonClassName={shouldHighlight ? "text-red-500" : ""}
disabled={!disabled} disabled={!disabled}
showTooltip showTooltip
customTooltipHeading="Date Range" customTooltipHeading="Date Range"
@@ -130,6 +154,50 @@ export const SubIssuesListItemProperties: React.FC<Props> = observer((props) =>
</div> </div>
</WithDisplayPropertiesHOC> </WithDisplayPropertiesHOC>
{/* start date */}
<WithDisplayPropertiesHOC
displayProperties={displayProperties}
displayPropertyKey="start_date"
shouldRenderProperty={() => !isDateRangeEnabled}
>
<div className="h-5">
<DateDropdown
value={issue.start_date ?? null}
onChange={handleStartDate}
maxDate={maxDate}
placeholder={t("common.order_by.start_date")}
icon={<CalendarClock className="h-3 w-3 flex-shrink-0" />}
buttonVariant={issue.start_date ? "border-with-text" : "border-without-text"}
optionsClassName="z-30"
disabled={!disabled}
showTooltip
/>
</div>
</WithDisplayPropertiesHOC>
{/* target/due date */}
<WithDisplayPropertiesHOC
displayProperties={displayProperties}
displayPropertyKey="due_date"
shouldRenderProperty={() => !isDateRangeEnabled}
>
<div className="h-5">
<DateDropdown
value={issue?.target_date ?? null}
onChange={handleTargetDate}
minDate={minDate}
placeholder={t("common.order_by.due_date")}
icon={<CalendarCheck2 className="h-3 w-3 flex-shrink-0" />}
buttonVariant={issue.target_date ? "border-with-text" : "border-without-text"}
buttonClassName={shouldHighlight ? "text-red-500" : ""}
clearIconClassName="text-custom-text-100"
optionsClassName="z-30"
disabled={!disabled}
showTooltip
/>
</div>
</WithDisplayPropertiesHOC>
<WithDisplayPropertiesHOC displayProperties={displayProperties} displayPropertyKey="assignee"> <WithDisplayPropertiesHOC displayProperties={displayProperties} displayPropertyKey="assignee">
<div className="h-5 flex-shrink-0"> <div className="h-5 flex-shrink-0">
<MemberDropdown <MemberDropdown

View File

@@ -5,7 +5,7 @@ import xor from "lodash/xor";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { useParams, usePathname } from "next/navigation"; import { useParams, usePathname } from "next/navigation";
// icons // icons
import { Layers, Link, Paperclip } from "lucide-react"; import { CalendarCheck2, CalendarClock, Layers, Link, Paperclip } from "lucide-react";
// types // types
import { WORK_ITEM_TRACKER_EVENTS } from "@plane/constants"; import { WORK_ITEM_TRACKER_EVENTS } from "@plane/constants";
// i18n // i18n
@@ -29,6 +29,7 @@ import {
CycleDropdown, CycleDropdown,
StateDropdown, StateDropdown,
DateRangeDropdown, DateRangeDropdown,
DateDropdown,
} from "@/components/dropdowns"; } from "@/components/dropdowns";
// constants // constants
// helpers // helpers
@@ -267,8 +268,16 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
if (!displayProperties || !issue.project_id) return null; if (!displayProperties || !issue.project_id) return null;
// date range is enabled only when both dates are available and both dates are enabled
const isDateRangeEnabled: boolean = Boolean(
issue.start_date && issue.target_date && displayProperties.start_date && displayProperties.due_date
);
const defaultLabelOptions = issue?.label_ids?.map((id) => labelMap[id]) || []; const defaultLabelOptions = issue?.label_ids?.map((id) => labelMap[id]) || [];
const minDate = getDate(issue.start_date);
const maxDate = getDate(issue.target_date);
const handleEventPropagation = (e: SyntheticEvent<HTMLDivElement>) => { const handleEventPropagation = (e: SyntheticEvent<HTMLDivElement>) => {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
@@ -312,7 +321,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
<WithDisplayPropertiesHOC <WithDisplayPropertiesHOC
displayProperties={displayProperties} displayProperties={displayProperties}
displayPropertyKey={["start_date", "due_date"]} displayPropertyKey={["start_date", "due_date"]}
shouldRenderProperty={(properties) => !!(properties.start_date || properties.due_date)} shouldRenderProperty={() => isDateRangeEnabled}
> >
<div className="h-5" onFocus={handleEventPropagation} onClick={handleEventPropagation}> <div className="h-5" onFocus={handleEventPropagation} onClick={handleEventPropagation}>
<DateRangeDropdown <DateRangeDropdown
@@ -331,6 +340,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
mergeDates mergeDates
buttonVariant={issue.start_date || issue.target_date ? "border-with-text" : "border-without-text"} buttonVariant={issue.start_date || issue.target_date ? "border-with-text" : "border-without-text"}
buttonClassName={shouldHighlightIssueDueDate(issue.target_date, stateDetails?.group) ? "text-red-500" : ""} buttonClassName={shouldHighlightIssueDueDate(issue.target_date, stateDetails?.group) ? "text-red-500" : ""}
clearIconClassName="!text-custom-text-100"
disabled={isReadOnly} disabled={isReadOnly}
renderByDefault={isMobile} renderByDefault={isMobile}
showTooltip showTooltip
@@ -340,6 +350,52 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
</div> </div>
</WithDisplayPropertiesHOC> </WithDisplayPropertiesHOC>
{/* start date */}
<WithDisplayPropertiesHOC
displayProperties={displayProperties}
displayPropertyKey="start_date"
shouldRenderProperty={() => !isDateRangeEnabled}
>
<div className="h-5" onFocus={handleEventPropagation} onClick={handleEventPropagation}>
<DateDropdown
value={issue.start_date ?? null}
onChange={handleStartDate}
maxDate={maxDate}
placeholder={t("common.order_by.start_date")}
icon={<CalendarClock className="h-3 w-3 flex-shrink-0" />}
buttonVariant={issue.start_date ? "border-with-text" : "border-without-text"}
optionsClassName="z-10"
disabled={isReadOnly}
renderByDefault={isMobile}
showTooltip
/>
</div>
</WithDisplayPropertiesHOC>
{/* target/due date */}
<WithDisplayPropertiesHOC
displayProperties={displayProperties}
displayPropertyKey="due_date"
shouldRenderProperty={() => !isDateRangeEnabled}
>
<div className="h-5" onFocus={handleEventPropagation} onClick={handleEventPropagation}>
<DateDropdown
value={issue?.target_date ?? null}
onChange={handleTargetDate}
minDate={minDate}
placeholder={t("common.order_by.due_date")}
icon={<CalendarCheck2 className="h-3 w-3 flex-shrink-0" />}
buttonVariant={issue.target_date ? "border-with-text" : "border-without-text"}
buttonClassName={shouldHighlightIssueDueDate(issue.target_date, stateDetails?.group) ? "text-red-500" : ""}
clearIconClassName="!text-custom-text-100"
optionsClassName="z-10"
disabled={isReadOnly}
renderByDefault={isMobile}
showTooltip
/>
</div>
</WithDisplayPropertiesHOC>
{/* assignee */} {/* assignee */}
<WithDisplayPropertiesHOC displayProperties={displayProperties} displayPropertyKey="assignee"> <WithDisplayPropertiesHOC displayProperties={displayProperties} displayPropertyKey="assignee">
<div className="h-5" onFocus={handleEventPropagation} onClick={handleEventPropagation}> <div className="h-5" onFocus={handleEventPropagation} onClick={handleEventPropagation}>