diff --git a/packages/editor/document-editor/src/ui/components/editor-header.tsx b/packages/editor/document-editor/src/ui/components/editor-header.tsx index a322ddddc..aaa4c7be3 100644 --- a/packages/editor/document-editor/src/ui/components/editor-header.tsx +++ b/packages/editor/document-editor/src/ui/components/editor-header.tsx @@ -72,7 +72,7 @@ export const EditorHeader = (props: IEditorHeader) => { Icon={Archive} backgroundColor="bg-blue-500/20" textColor="text-blue-500" - label={`Archived at ${new Date(archivedAt).toLocaleString()}`} + label={`Archived at ${archivedAt.toLocaleString()}`} /> )} diff --git a/packages/editor/document-editor/src/ui/components/info-popover.tsx b/packages/editor/document-editor/src/ui/components/info-popover.tsx index f78dd3473..9a17a9376 100644 --- a/packages/editor/document-editor/src/ui/components/info-popover.tsx +++ b/packages/editor/document-editor/src/ui/components/info-popover.tsx @@ -52,14 +52,14 @@ export const InfoPopover: React.FC = (props) => {
Last updated on
- {renderDate(new Date(documentDetails.last_updated_at))} + {renderDate(documentDetails.last_updated_at)}
Created on
- {renderDate(new Date(documentDetails.created_on))} + {renderDate(documentDetails.created_on)}
diff --git a/web/components/core/filters/date-filter-modal.tsx b/web/components/core/filters/date-filter-modal.tsx index d1eedc749..1b7b7aaed 100644 --- a/web/components/core/filters/date-filter-modal.tsx +++ b/web/components/core/filters/date-filter-modal.tsx @@ -7,8 +7,8 @@ import { X } from "lucide-react"; // ui import { Button } from "@plane/ui"; // helpers -import { renderFormattedPayloadDate, renderFormattedDate } from "helpers/date-time.helper"; import { DateFilterSelect } from "./date-filter-select"; +import { renderFormattedPayloadDate, renderFormattedDate, getDate } from "helpers/date-time.helper"; type Props = { title: string; @@ -44,10 +44,10 @@ export const DateFilterModal: React.FC = ({ title, handleClose, isOpen, o handleClose(); }; - const date1 = watch("date1"); - const date2 = watch("date2"); + const date1 = getDate(watch("date1")); + const date2 = getDate(watch("date1")); - const isInvalid = watch("filterType") === "range" ? new Date(date1) > new Date(date2) : false; + const isInvalid = watch("filterType") === "range" && date1 && date2 ? date1 > date2 : false; return ( @@ -90,37 +90,45 @@ export const DateFilterModal: React.FC = ({ title, handleClose, isOpen, o ( - { - if (!date) return; - onChange(date); - }} - mode="single" - disabled={[{ after: new Date(watch("date2")) }]} - className="border border-custom-border-200 p-3 rounded-md" - /> - )} - /> - {watch("filterType") === "range" && ( - ( + render={({ field: { value, onChange } }) => { + const dateValue = getDate(value); + const date2Value = getDate(watch("date2")); + return ( { if (!date) return; onChange(date); }} mode="single" - disabled={[{ before: new Date(watch("date1")) }]} + disabled={date2Value ? [{ after: date2Value }] : undefined} className="border border-custom-border-200 p-3 rounded-md" /> - )} + ); + }} + /> + {watch("filterType") === "range" && ( + { + const dateValue = getDate(value); + const date1Value = getDate(watch("date1")); + return ( + { + if (!date) return; + onChange(date); + }} + mode="single" + disabled={date1Value ? [{ before: date1Value }] : undefined} + className="border border-custom-border-200 p-3 rounded-md" + /> + ); + }} /> )} diff --git a/web/components/core/sidebar/progress-chart.tsx b/web/components/core/sidebar/progress-chart.tsx index ca21756fc..b0ff4ba73 100644 --- a/web/components/core/sidebar/progress-chart.tsx +++ b/web/components/core/sidebar/progress-chart.tsx @@ -3,7 +3,7 @@ import { eachDayOfInterval, isValid } from "date-fns"; // ui import { LineGraph } from "components/ui"; // helpers -import { renderFormattedDateWithoutYear } from "helpers/date-time.helper"; +import { getDate, renderFormattedDateWithoutYear } from "helpers/date-time.helper"; //types import { TCompletionChartDistribution } from "@plane/types"; @@ -47,11 +47,11 @@ const ProgressChart: React.FC = ({ distribution, startDate, endDate, tota })); const generateXAxisTickValues = () => { - const start = new Date(startDate); - const end = new Date(endDate); + const start = getDate(startDate); + const end = getDate(endDate); let dates: Date[] = []; - if (isValid(start) && isValid(end)) { + if (start && end && isValid(start) && isValid(end)) { dates = eachDayOfInterval({ start, end }); } diff --git a/web/components/cycles/active-cycle/root.tsx b/web/components/cycles/active-cycle/root.tsx index dd5d65f7e..d11c694d5 100644 --- a/web/components/cycles/active-cycle/root.tsx +++ b/web/components/cycles/active-cycle/root.tsx @@ -28,7 +28,12 @@ import { EmptyState } from "components/empty-state"; // icons import { ArrowRight, CalendarCheck, CalendarDays, Star, Target } from "lucide-react"; // helpers -import { renderFormattedDate, findHowManyDaysLeft, renderFormattedDateWithoutYear } from "helpers/date-time.helper"; +import { + renderFormattedDate, + findHowManyDaysLeft, + renderFormattedDateWithoutYear, + getDate, +} from "helpers/date-time.helper"; import { truncateText } from "helpers/string.helper"; import { cn } from "helpers/common.helper"; // types @@ -124,8 +129,8 @@ export const ActiveCycleRoot: React.FC = observer((props) = ); } - const endDate = new Date(activeCycle.end_date ?? ""); - const startDate = new Date(activeCycle.start_date ?? ""); + const endDate = getDate(activeCycle.end_date); + const startDate = getDate(activeCycle.start_date); const daysLeft = findHowManyDaysLeft(activeCycle.end_date) ?? 0; const cycleStatus = activeCycle.status.toLowerCase() as TCycleGroups; @@ -349,7 +354,11 @@ export const ActiveCycleRoot: React.FC = observer((props) = buttonVariant="background-with-text" /> {issue.target_date && ( - +
{renderFormattedDateWithoutYear(issue.target_date)} diff --git a/web/components/cycles/board/cycles-board-card.tsx b/web/components/cycles/board/cycles-board-card.tsx index c8ac630e7..c1558c5b3 100644 --- a/web/components/cycles/board/cycles-board-card.tsx +++ b/web/components/cycles/board/cycles-board-card.tsx @@ -11,10 +11,12 @@ import { CycleQuickActions } from "components/cycles"; // ui // icons // helpers +import { findHowManyDaysLeft, getDate, renderFormattedDate } from "helpers/date-time.helper"; +// import { copyTextToClipboard } from "helpers/string.helper"; +// constants import { CYCLE_STATUS } from "constants/cycle"; import { CYCLE_FAVORITED, CYCLE_UNFAVORITED } from "constants/event-tracker"; import { EUserWorkspaceRoles } from "constants/workspace"; -import { findHowManyDaysLeft, renderFormattedDate } from "helpers/date-time.helper"; // constants import { useEventTracker, useCycle, useUser, useMember } from "hooks/store"; //.types @@ -45,8 +47,9 @@ export const CyclesBoardCard: FC = observer((props) => { if (!cycleDetails) return null; const cycleStatus = cycleDetails.status.toLocaleLowerCase(); - const endDate = new Date(cycleDetails.end_date ?? ""); - const startDate = new Date(cycleDetails.start_date ?? ""); + // const isCompleted = cycleStatus === "completed"; + const endDate = getDate(cycleDetails.end_date); + const startDate = getDate(cycleDetails.start_date); const isDateValid = cycleDetails.start_date || cycleDetails.end_date; const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; diff --git a/web/components/cycles/form.tsx b/web/components/cycles/form.tsx index d470b1bb9..17953248a 100644 --- a/web/components/cycles/form.tsx +++ b/web/components/cycles/form.tsx @@ -5,8 +5,8 @@ import { Button, Input, TextArea } from "@plane/ui"; import { DateRangeDropdown, ProjectDropdown } from "components/dropdowns"; // ui // helpers -import { renderFormattedPayloadDate } from "helpers/date-time.helper"; import { shouldRenderProject } from "helpers/project.helper"; +import { getDate, renderFormattedPayloadDate } from "helpers/date-time.helper"; // types import { ICycle } from "@plane/types"; @@ -137,8 +137,8 @@ export const CycleForm: React.FC = (props) => { className="h-7" minDate={new Date()} value={{ - from: startDateValue ? new Date(startDateValue) : undefined, - to: endDateValue ? new Date(endDateValue) : undefined, + from: getDate(startDateValue), + to: getDate(endDateValue), }} onSelect={(val) => { onChangeStartDate(val?.from ? renderFormattedPayloadDate(val.from) : null); diff --git a/web/components/cycles/gantt-chart/cycles-list-layout.tsx b/web/components/cycles/gantt-chart/cycles-list-layout.tsx index 094fbea7b..6c439331d 100644 --- a/web/components/cycles/gantt-chart/cycles-list-layout.tsx +++ b/web/components/cycles/gantt-chart/cycles-list-layout.tsx @@ -8,6 +8,7 @@ import { useCycle } from "hooks/store"; // components // types import { ICycle } from "@plane/types"; +import { getDate } from "helpers/date-time.helper"; // constants type Props = { @@ -41,8 +42,8 @@ export const CyclesListGanttChartView: FC = observer((props) => { data: block, id: block?.id ?? "", sort_order: block?.sort_order ?? 0, - start_date: new Date(block?.start_date ?? ""), - target_date: new Date(block?.end_date ?? ""), + start_date: getDate(block?.start_date), + target_date: getDate(block?.end_date), })); return structuredBlocks; diff --git a/web/components/cycles/list/cycles-list-item.tsx b/web/components/cycles/list/cycles-list-item.tsx index 8a5cee535..cb1373a37 100644 --- a/web/components/cycles/list/cycles-list-item.tsx +++ b/web/components/cycles/list/cycles-list-item.tsx @@ -7,9 +7,15 @@ import { usePlatformOS } from "hooks/use-platform-os"; import { Check, Info, Star, User2 } from "lucide-react"; import { Tooltip, CircularProgressIndicator, CycleGroupIcon, AvatarGroup, Avatar, setPromiseToast } from "@plane/ui"; import { CycleQuickActions } from "components/cycles"; +// components +// import { CycleCreateUpdateModal, CycleDeleteModal } from "components/cycles"; +// ui +// icons +// helpers +import { findHowManyDaysLeft, getDate, renderFormattedDate } from "helpers/date-time.helper"; +// constants import { CYCLE_STATUS } from "constants/cycle"; import { CYCLE_FAVORITED, CYCLE_UNFAVORITED } from "constants/event-tracker"; -import { findHowManyDaysLeft, renderFormattedDate } from "helpers/date-time.helper"; import { useEventTracker, useCycle, useUser, useMember } from "hooks/store"; // components // ui @@ -119,8 +125,8 @@ export const CyclesListItem: FC = observer((props) => { // TODO: change this logic once backend fix the response const cycleStatus = cycleDetails.status ? (cycleDetails.status.toLocaleLowerCase() as TCycleGroups) : "draft"; const isCompleted = cycleStatus === "completed"; - const endDate = new Date(cycleDetails.end_date ?? ""); - const startDate = new Date(cycleDetails.start_date ?? ""); + const endDate = getDate(cycleDetails.end_date); + const startDate = getDate(cycleDetails.start_date); const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER; diff --git a/web/components/cycles/sidebar.tsx b/web/components/cycles/sidebar.tsx index bdbe206fc..f13427012 100644 --- a/web/components/cycles/sidebar.tsx +++ b/web/components/cycles/sidebar.tsx @@ -18,12 +18,12 @@ import { CYCLE_STATUS } from "constants/cycle"; import { CYCLE_UPDATED } from "constants/event-tracker"; import { EUserWorkspaceRoles } from "constants/workspace"; // helpers -import { findHowManyDaysLeft, renderFormattedPayloadDate } from "helpers/date-time.helper"; -import { copyUrlToClipboard } from "helpers/string.helper"; // hooks import { useEventTracker, useCycle, useUser, useMember } from "hooks/store"; // services import { CycleService } from "services/cycle.service"; +import { findHowManyDaysLeft, getDate, renderFormattedPayloadDate } from "helpers/date-time.helper"; +import { copyUrlToClipboard } from "helpers/string.helper"; // types import { ICycle } from "@plane/types"; @@ -182,8 +182,11 @@ export const CycleDetailsSidebar: React.FC = observer((props) => { const cycleStatus = cycleDetails?.status.toLocaleLowerCase(); const isCompleted = cycleStatus === "completed"; - const isStartValid = new Date(`${cycleDetails?.start_date}`) <= new Date(); - const isEndValid = new Date(`${cycleDetails?.end_date}`) >= new Date(`${cycleDetails?.start_date}`); + const startDate = getDate(cycleDetails?.start_date); + const endDate = getDate(cycleDetails?.end_date); + + const isStartValid = startDate && startDate <= new Date(); + const isEndValid = endDate && startDate && endDate >= startDate; const progressPercentage = cycleDetails ? isCompleted && cycleDetails?.progress_snapshot @@ -313,8 +316,8 @@ export const CycleDetailsSidebar: React.FC = observer((props) => { buttonVariant="background-with-text" minDate={new Date()} value={{ - from: startDateValue ? new Date(startDateValue) : undefined, - to: endDateValue ? new Date(endDateValue) : undefined, + from: getDate(startDateValue), + to: getDate(endDateValue), }} onSelect={(val) => { onChangeStartDate(val?.from ? renderFormattedPayloadDate(val.from) : null); diff --git a/web/components/dashboard/widgets/issue-panels/issue-list-item.tsx b/web/components/dashboard/widgets/issue-panels/issue-list-item.tsx index a5279f715..47efb4d21 100644 --- a/web/components/dashboard/widgets/issue-panels/issue-list-item.tsx +++ b/web/components/dashboard/widgets/issue-panels/issue-list-item.tsx @@ -4,8 +4,8 @@ import { observer } from "mobx-react-lite"; // ui import { Avatar, AvatarGroup, ControlLink, PriorityIcon } from "@plane/ui"; // helpers -import { findTotalDaysInRange, renderFormattedDate } from "helpers/date-time.helper"; import { useIssueDetail, useMember, useProject } from "hooks/store"; +import { findTotalDaysInRange, getDate, renderFormattedDate } from "helpers/date-time.helper"; // types import { TIssue, TWidgetIssue } from "@plane/types"; @@ -34,6 +34,8 @@ export const AssignedUpcomingIssueListItem: React.FC = obser const blockedByIssueProjectDetails = blockedByIssues.length === 1 ? getProjectById(blockedByIssues[0]?.project_id ?? "") : null; + const targetDate = getDate(issueDetails.target_date); + return ( = obser
{issueDetails.name}
- {issueDetails.target_date - ? isToday(new Date(issueDetails.target_date)) - ? "Today" - : renderFormattedDate(issueDetails.target_date) - : "-"} + {targetDate ? (isToday(targetDate) ? "Today" : renderFormattedDate(targetDate)) : "-"}
{blockedByIssues.length > 0 @@ -83,7 +81,7 @@ export const AssignedOverdueIssueListItem: React.FC = observ const blockedByIssueProjectDetails = blockedByIssues.length === 1 ? getProjectById(blockedByIssues[0]?.project_id ?? "") : null; - const dueBy = findTotalDaysInRange(new Date(issueDetails.target_date ?? ""), new Date(), false) ?? 0; + const dueBy = findTotalDaysInRange(getDate(issueDetails.target_date), new Date(), false) ?? 0; return ( = observe const projectDetails = getProjectById(issue.project_id); - const dueBy = findTotalDaysInRange(new Date(issue.target_date ?? ""), new Date(), false) ?? 0; + const dueBy = findTotalDaysInRange(getDate(issue.target_date), new Date(), false) ?? 0; return ( = (props) => { {...attributes.popper} > { dropdownOnChange(date ?? null); }} diff --git a/web/components/exporter/single-export.tsx b/web/components/exporter/single-export.tsx index 4fdcb4a15..6e28d0466 100644 --- a/web/components/exporter/single-export.tsx +++ b/web/components/exporter/single-export.tsx @@ -2,7 +2,7 @@ import { useState, FC } from "react"; // ui import { Button } from "@plane/ui"; // helpers -import { renderFormattedDate } from "helpers/date-time.helper"; +import { getDate, renderFormattedDate } from "helpers/date-time.helper"; // types import { IExportData } from "@plane/types"; @@ -18,7 +18,8 @@ export const SingleExport: FC = ({ service, refreshing }) => { const checkExpiry = (inputDateString: string) => { const currentDate = new Date(); - const expiryDate = new Date(inputDateString); + const expiryDate = getDate(inputDateString); + if (!expiryDate) return false; expiryDate.setDate(expiryDate.getDate() + 7); return expiryDate > currentDate; }; diff --git a/web/components/gantt-chart/chart/root.tsx b/web/components/gantt-chart/chart/root.tsx index ab04c2ec1..5c9872cf4 100644 --- a/web/components/gantt-chart/chart/root.tsx +++ b/web/components/gantt-chart/chart/root.tsx @@ -64,9 +64,9 @@ export const ChartViewRoot: FC = observer((props) => { useGanttChart(); // rendering the block structure - const renderBlockStructure = (view: any, blocks: IGanttBlock[] | null) => + const renderBlockStructure = (view: ChartDataType, blocks: IGanttBlock[] | null) => blocks - ? blocks.map((block: any) => ({ + ? blocks.map((block: IGanttBlock) => ({ ...block, position: getMonthChartItemPositionWidthInMonth(view, block), })) diff --git a/web/components/gantt-chart/types/index.ts b/web/components/gantt-chart/types/index.ts index 6268e4363..cd90758fc 100644 --- a/web/components/gantt-chart/types/index.ts +++ b/web/components/gantt-chart/types/index.ts @@ -6,8 +6,8 @@ export interface IGanttBlock { width: number; }; sort_order: number; - start_date: Date | null; - target_date: Date | null; + start_date: Date | undefined; + target_date: Date | undefined; } export interface IBlockUpdateData { diff --git a/web/components/gantt-chart/views/month-view.ts b/web/components/gantt-chart/views/month-view.ts index 1e7e6d878..f2d54a9f8 100644 --- a/web/components/gantt-chart/views/month-view.ts +++ b/web/components/gantt-chart/views/month-view.ts @@ -1,5 +1,6 @@ // types import { weeks, months } from "../data"; +import { findTotalDaysInRange } from "helpers/date-time.helper"; import { ChartDataType, IGanttBlock } from "../types"; // data // helpers @@ -167,15 +168,16 @@ export const getMonthChartItemPositionWidthInMonth = (chartData: ChartDataType, const { startDate } = chartData.data; const { start_date: itemStartDate, target_date: itemTargetDate } = itemData; - if (!itemStartDate || !itemTargetDate) return null; + if (!itemStartDate || !itemTargetDate) return; startDate.setHours(0, 0, 0, 0); itemStartDate.setHours(0, 0, 0, 0); itemTargetDate.setHours(0, 0, 0, 0); - // position code starts - const positionTimeDifference: number = startDate.getTime() - itemStartDate.getTime(); - const positionDaysDifference: number = Math.abs(Math.floor(positionTimeDifference / (1000 * 60 * 60 * 24))); + const positionDaysDifference = findTotalDaysInRange(startDate, itemStartDate, false); + + if (!positionDaysDifference) return; + scrollPosition = positionDaysDifference * chartData.data.width; let diffMonths = (itemStartDate.getFullYear() - startDate.getFullYear()) * 12; diff --git a/web/components/inbox/inbox-issue-actions.tsx b/web/components/inbox/inbox-issue-actions.tsx index 661bc2d72..5d921dcd1 100644 --- a/web/components/inbox/inbox-issue-actions.tsx +++ b/web/components/inbox/inbox-issue-actions.tsx @@ -20,6 +20,8 @@ import { EUserProjectRoles } from "constants/project"; import { useUser, useInboxIssues, useIssueDetail, useWorkspace, useEventTracker } from "hooks/store"; // types import type { TInboxDetailedStatus } from "@plane/types"; +//helpers +import { getDate } from "helpers/date-time.helper"; type TInboxIssueActionsHeader = { workspaceSlug: string; @@ -168,11 +170,11 @@ export const InboxIssueActionsHeader: FC = observer((p const isAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER; const today = new Date(); - const tomorrow = new Date(today); - tomorrow.setDate(today.getDate() + 1); + const tomorrow = getDate(today); + tomorrow?.setDate(today.getDate() + 1); useEffect(() => { if (!issueStatus || !issueStatus.snoozed_till) return; - setDate(new Date(issueStatus.snoozed_till)); + setDate(issueStatus.snoozed_till); }, [issueStatus]); if (!issueStatus || !issue || !inboxIssues) return <>; @@ -266,19 +268,23 @@ export const InboxIssueActionsHeader: FC = observer((p {({ close }) => (
{ if (!date) return; setDate(date); }} mode="single" - className="rounded-md border border-custom-border-200 p-3" - disabled={[ - { - before: tomorrow, - }, - ]} + className="border border-custom-border-200 rounded-md p-3" + disabled={ + tomorrow + ? [ + { + before: tomorrow, + }, + ] + : undefined + } />