mirror of
https://github.com/makeplane/plane
synced 2025-08-07 19:59:33 +00:00
[WEB-4365] fix: dates display properties toggle #7262
This commit is contained in:
@@ -1,12 +1,21 @@
|
||||
// plane imports
|
||||
import { SyntheticEvent } from "react";
|
||||
import { SyntheticEvent, useMemo } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { CalendarCheck2, CalendarClock } from "lucide-react";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { IIssueDisplayProperties, TIssue } from "@plane/types";
|
||||
import { getDate, renderFormattedPayloadDate } from "@plane/utils";
|
||||
import { getDate, renderFormattedPayloadDate, shouldHighlightIssueDueDate } from "@plane/utils";
|
||||
// components
|
||||
import { PriorityDropdown, MemberDropdown, StateDropdown, DateRangeDropdown } from "@/components/dropdowns";
|
||||
import {
|
||||
PriorityDropdown,
|
||||
MemberDropdown,
|
||||
StateDropdown,
|
||||
DateRangeDropdown,
|
||||
DateDropdown,
|
||||
} from "@/components/dropdowns";
|
||||
// hooks
|
||||
import { WithDisplayPropertiesHOC } from "@/components/issues/issue-layouts/properties/with-display-properties-HOC";
|
||||
import { useProjectState } from "@/hooks/store/use-project-state";
|
||||
|
||||
type Props = {
|
||||
workspaceSlug: string;
|
||||
@@ -27,6 +36,8 @@ type Props = {
|
||||
|
||||
export const SubIssuesListItemProperties: React.FC<Props> = observer((props) => {
|
||||
const { workspaceSlug, parentIssueId, issueId, disabled, updateSubIssue, displayProperties, issue } = props;
|
||||
const { t } = useTranslation();
|
||||
const { getStateById } = useProjectState();
|
||||
|
||||
const handleEventPropagation = (e: SyntheticEvent<HTMLDivElement>) => {
|
||||
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 <></>;
|
||||
|
||||
const maxDate = getDate(issue.target_date);
|
||||
maxDate?.setDate(maxDate.getDate());
|
||||
const minDate = getDate(issue.start_date);
|
||||
|
||||
return (
|
||||
<div className="relative flex items-center gap-2">
|
||||
<WithDisplayPropertiesHOC displayProperties={displayProperties} displayPropertyKey="state">
|
||||
@@ -104,7 +127,7 @@ export const SubIssuesListItemProperties: React.FC<Props> = observer((props) =>
|
||||
<WithDisplayPropertiesHOC
|
||||
displayProperties={displayProperties}
|
||||
displayPropertyKey={["start_date", "due_date"]}
|
||||
shouldRenderProperty={(properties) => !!(properties.start_date || properties.due_date)}
|
||||
shouldRenderProperty={() => isDateRangeEnabled}
|
||||
>
|
||||
<div className="h-5" onFocus={handleEventPropagation} onClick={handleEventPropagation}>
|
||||
<DateRangeDropdown
|
||||
@@ -122,6 +145,7 @@ export const SubIssuesListItemProperties: React.FC<Props> = observer((props) =>
|
||||
isClearable
|
||||
mergeDates
|
||||
buttonVariant={issue.start_date || issue.target_date ? "border-with-text" : "border-without-text"}
|
||||
buttonClassName={shouldHighlight ? "text-red-500" : ""}
|
||||
disabled={!disabled}
|
||||
showTooltip
|
||||
customTooltipHeading="Date Range"
|
||||
@@ -130,6 +154,50 @@ export const SubIssuesListItemProperties: React.FC<Props> = observer((props) =>
|
||||
</div>
|
||||
</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">
|
||||
<div className="h-5 flex-shrink-0">
|
||||
<MemberDropdown
|
||||
|
||||
@@ -5,7 +5,7 @@ import xor from "lodash/xor";
|
||||
import { observer } from "mobx-react";
|
||||
import { useParams, usePathname } from "next/navigation";
|
||||
// icons
|
||||
import { Layers, Link, Paperclip } from "lucide-react";
|
||||
import { CalendarCheck2, CalendarClock, Layers, Link, Paperclip } from "lucide-react";
|
||||
// types
|
||||
import { WORK_ITEM_TRACKER_EVENTS } from "@plane/constants";
|
||||
// i18n
|
||||
@@ -29,6 +29,7 @@ import {
|
||||
CycleDropdown,
|
||||
StateDropdown,
|
||||
DateRangeDropdown,
|
||||
DateDropdown,
|
||||
} from "@/components/dropdowns";
|
||||
// constants
|
||||
// helpers
|
||||
@@ -267,8 +268,16 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
|
||||
|
||||
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 minDate = getDate(issue.start_date);
|
||||
const maxDate = getDate(issue.target_date);
|
||||
|
||||
const handleEventPropagation = (e: SyntheticEvent<HTMLDivElement>) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
@@ -312,7 +321,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
|
||||
<WithDisplayPropertiesHOC
|
||||
displayProperties={displayProperties}
|
||||
displayPropertyKey={["start_date", "due_date"]}
|
||||
shouldRenderProperty={(properties) => !!(properties.start_date || properties.due_date)}
|
||||
shouldRenderProperty={() => isDateRangeEnabled}
|
||||
>
|
||||
<div className="h-5" onFocus={handleEventPropagation} onClick={handleEventPropagation}>
|
||||
<DateRangeDropdown
|
||||
@@ -331,6 +340,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
|
||||
mergeDates
|
||||
buttonVariant={issue.start_date || issue.target_date ? "border-with-text" : "border-without-text"}
|
||||
buttonClassName={shouldHighlightIssueDueDate(issue.target_date, stateDetails?.group) ? "text-red-500" : ""}
|
||||
clearIconClassName="!text-custom-text-100"
|
||||
disabled={isReadOnly}
|
||||
renderByDefault={isMobile}
|
||||
showTooltip
|
||||
@@ -340,6 +350,52 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
|
||||
</div>
|
||||
</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 */}
|
||||
<WithDisplayPropertiesHOC displayProperties={displayProperties} displayPropertyKey="assignee">
|
||||
<div className="h-5" onFocus={handleEventPropagation} onClick={handleEventPropagation}>
|
||||
|
||||
Reference in New Issue
Block a user