From 32cdb668025bcdfff07785376d9b10ae23e60f20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Mon, 11 Aug 2025 17:36:53 +0200 Subject: [PATCH] Type fixes and website fix (#13825) Various fixes --- .../twenty-docker/twenty-website/Dockerfile | 4 +- packages/twenty-docker/twenty/Dockerfile | 12 ++-- .../RecordGroupReorderConfirmationModal.tsx | 25 ++++---- .../components/RecordInlineCellEditMode.tsx | 24 ++++---- .../RecordTableCellPortalWrapper.tsx | 58 ++++++++++--------- .../ValidationStep/components/columns.tsx | 20 ++++--- .../date/components/InternalDatePicker.tsx | 15 ++++- .../editor/components/CustomSlashMenu.tsx | 56 +++++++++--------- ...t-github-release-date-from-release-note.ts | 35 +++-------- .../src/shared-utils/formatDisplayDate.ts | 8 ++- 10 files changed, 133 insertions(+), 124 deletions(-) diff --git a/packages/twenty-docker/twenty-website/Dockerfile b/packages/twenty-docker/twenty-website/Dockerfile index 9d1823f335..2ff7cb808b 100644 --- a/packages/twenty-docker/twenty-website/Dockerfile +++ b/packages/twenty-docker/twenty-website/Dockerfile @@ -1,4 +1,4 @@ -FROM node:24-alpine as twenty-website-build +FROM node:24-alpine AS twenty-website-build WORKDIR /app @@ -24,7 +24,7 @@ COPY ./packages/twenty-ui /app/packages/twenty-ui COPY ./packages/twenty-website /app/packages/twenty-website RUN npx nx build twenty-website -FROM node:24-alpine as twenty-website +FROM node:24-alpine AS twenty-website WORKDIR /app/packages/twenty-website diff --git a/packages/twenty-docker/twenty/Dockerfile b/packages/twenty-docker/twenty/Dockerfile index 0c9f01b4d4..7818be7425 100644 --- a/packages/twenty-docker/twenty/Dockerfile +++ b/packages/twenty-docker/twenty/Dockerfile @@ -1,5 +1,5 @@ # Base image for common dependencies -FROM node:24-alpine as common-deps +FROM node:24-alpine AS common-deps WORKDIR /app @@ -21,7 +21,7 @@ RUN yarn && yarn cache clean && npx nx reset # Build the back -FROM common-deps as twenty-server-build +FROM common-deps AS twenty-server-build # Copy sourcecode after installing dependences to accelerate subsequents builds COPY ./packages/twenty-emails /app/packages/twenty-emails @@ -33,7 +33,7 @@ RUN npx nx run twenty-server:build RUN yarn workspaces focus --production twenty-emails twenty-shared twenty-server # Build the front -FROM common-deps as twenty-front-build +FROM common-deps AS twenty-front-build ARG REACT_APP_SERVER_BASE_URL @@ -44,7 +44,7 @@ RUN npx nx build twenty-front # Final stage: Run the application -FROM node:24-alpine as twenty +FROM node:24-alpine AS twenty # Used to run healthcheck in docker RUN apk add --no-cache curl jq @@ -58,10 +58,10 @@ RUN chmod +x /app/entrypoint.sh WORKDIR /app/packages/twenty-server ARG REACT_APP_SERVER_BASE_URL -ENV REACT_APP_SERVER_BASE_URL $REACT_APP_SERVER_BASE_URL +ENV REACT_APP_SERVER_BASE_URL=$REACT_APP_SERVER_BASE_URL ARG APP_VERSION -ENV APP_VERSION $APP_VERSION +ENV APP_VERSION=$APP_VERSION # Copy built applications from previous stages COPY --chown=1000 --from=twenty-server-build /app /app diff --git a/packages/twenty-front/src/modules/object-record/record-group/components/RecordGroupReorderConfirmationModal.tsx b/packages/twenty-front/src/modules/object-record/record-group/components/RecordGroupReorderConfirmationModal.tsx index 276afc8b52..9db9848489 100644 --- a/packages/twenty-front/src/modules/object-record/record-group/components/RecordGroupReorderConfirmationModal.tsx +++ b/packages/twenty-front/src/modules/object-record/record-group/components/RecordGroupReorderConfirmationModal.tsx @@ -2,6 +2,7 @@ import { RECORD_GROUP_REORDER_CONFIRMATION_MODAL_ID } from '@/object-record/reco import { recordIndexRecordGroupSortComponentState } from '@/object-record/record-index/states/recordIndexRecordGroupSortComponentState'; import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; +import { type ReactNode } from 'react'; import { createPortal } from 'react-dom'; type RecordGroupReorderConfirmationModalProps = { @@ -10,19 +11,23 @@ type RecordGroupReorderConfirmationModalProps = { export const RecordGroupReorderConfirmationModal = ({ onConfirmClick, -}: RecordGroupReorderConfirmationModalProps) => { +}: RecordGroupReorderConfirmationModalProps): ReactNode => { const recordGroupSort = useRecoilComponentValue( recordIndexRecordGroupSortComponentState, ); - return createPortal( - , - document.body, + return ( + <> + {createPortal( + , + document.body, + )} + ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-inline-cell/components/RecordInlineCellEditMode.tsx b/packages/twenty-front/src/modules/object-record/record-inline-cell/components/RecordInlineCellEditMode.tsx index fea5e034e4..2cd4889a7d 100644 --- a/packages/twenty-front/src/modules/object-record/record-inline-cell/components/RecordInlineCellEditMode.tsx +++ b/packages/twenty-front/src/modules/object-record/record-inline-cell/components/RecordInlineCellEditMode.tsx @@ -92,17 +92,19 @@ export const RecordInlineCellEditMode = ({ ref={refs.setReference} data-testid="inline-cell-edit-mode-container" > - {createPortal( - - {children} - , - document.body, - )} + <> + {createPortal( + + {children} + , + document.body, + )} + ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellPortalWrapper.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellPortalWrapper.tsx index f34e9eb802..4326c40574 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellPortalWrapper.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellPortalWrapper.tsx @@ -8,7 +8,7 @@ import { RecordTableCellFieldContextWrapper } from '@/object-record/record-table import { visibleTableColumnsComponentSelector } from '@/object-record/record-table/states/selectors/visibleTableColumnsComponentSelector'; import { type TableCellPosition } from '@/object-record/record-table/types/TableCellPosition'; import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; -import ReactDOM from 'react-dom'; +import { createPortal } from 'react-dom'; import { isDefined } from 'twenty-shared/utils'; export const RecordTableCellPortalWrapper = ({ @@ -43,32 +43,36 @@ export const RecordTableCellPortalWrapper = ({ return null; } - return ReactDOM.createPortal( - + {createPortal( + - - - {children} - - - , - anchorElement, + isRecordReadOnly, + }} + > + + + {children} + + + , + anchorElement, + )} + ); }; diff --git a/packages/twenty-front/src/modules/spreadsheet-import/steps/components/ValidationStep/components/columns.tsx b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/ValidationStep/components/columns.tsx index dc40e0695b..6e9900dd57 100644 --- a/packages/twenty-front/src/modules/spreadsheet-import/steps/components/ValidationStep/components/columns.tsx +++ b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/ValidationStep/components/columns.tsx @@ -118,15 +118,17 @@ export const generateColumns = ( {column.label} - {column.description && - createPortal( - , - document.body, - )} + <> + {column.description && + createPortal( + , + document.body, + )} + ), editable: column.fieldType.type !== 'checkbox', diff --git a/packages/twenty-front/src/modules/ui/input/components/internal/date/components/InternalDatePicker.tsx b/packages/twenty-front/src/modules/ui/input/components/internal/date/components/InternalDatePicker.tsx index b63d34f2b4..b2c7a0b38d 100644 --- a/packages/twenty-front/src/modules/ui/input/components/internal/date/components/InternalDatePicker.tsx +++ b/packages/twenty-front/src/modules/ui/input/components/internal/date/components/InternalDatePicker.tsx @@ -1,6 +1,7 @@ import styled from '@emotion/styled'; import { DateTime } from 'luxon'; -import { lazy, Suspense, useContext } from 'react'; +import { lazy, Suspense, useContext, type ComponentType } from 'react'; +import type { ReactDatePickerProps as ReactDatePickerLibProps } from 'react-datepicker'; import Skeleton, { SkeletonTheme } from 'react-loading-skeleton'; import { SKELETON_LOADER_HEIGHT_SIZES } from '@/activities/components/SkeletonLoader'; @@ -325,7 +326,17 @@ type DateTimePickerProps = { onClear?: () => void; }; -const ReactDatePicker = lazy(() => import('react-datepicker')); +type DatePickerPropsType = ReactDatePickerLibProps< + boolean | undefined, + boolean | undefined +>; + +const ReactDatePicker = lazy( + () => + import('react-datepicker') as Promise<{ + default: ComponentType; + }>, +); export const DateTimePicker = ({ date, diff --git a/packages/twenty-front/src/modules/ui/input/editor/components/CustomSlashMenu.tsx b/packages/twenty-front/src/modules/ui/input/editor/components/CustomSlashMenu.tsx index 8d9f00f203..c0b909d031 100644 --- a/packages/twenty-front/src/modules/ui/input/editor/components/CustomSlashMenu.tsx +++ b/packages/twenty-front/src/modules/ui/input/editor/components/CustomSlashMenu.tsx @@ -48,34 +48,36 @@ export const CustomSlashMenu = ({ return ( - {createPortal( - - + {createPortal( + - - - item.title)} - > - {items.map((item) => ( - - ))} - - - - - , - document.body, - )} + + + + item.title)} + > + {items.map((item) => ( + + ))} + + + + + , + document.body, + )} + ); }; diff --git a/packages/twenty-website/src/app/(public)/releases/utils/get-github-release-date-from-release-note.ts b/packages/twenty-website/src/app/(public)/releases/utils/get-github-release-date-from-release-note.ts index d86fe87533..6d885d97a1 100644 --- a/packages/twenty-website/src/app/(public)/releases/utils/get-github-release-date-from-release-note.ts +++ b/packages/twenty-website/src/app/(public)/releases/utils/get-github-release-date-from-release-note.ts @@ -1,43 +1,22 @@ import { type GithubReleases } from '@/database/model'; -function formatDate(dateString: string) { - const date = new Date(dateString); - - const formatter = new Intl.DateTimeFormat('en-US', { - month: 'short', - day: 'numeric', - }); - - return formatter.format(date) + getOrdinal(date.getDate()); -} - -function getOrdinal(day: number) { - if (day > 3 && day < 21) return 'th'; - switch (day % 10) { - case 1: - return 'st'; - case 2: - return 'nd'; - case 3: - return 'rd'; - default: - return 'th'; - } -} - +// Return an ISO date string so downstream components can format consistently export const getGithubReleaseDateFromReleaseNote = ( githubReleases: GithubReleases[], noteTagName: string, noteDate: string, ) => { const formattedNoteTagName = `v${noteTagName}`; - const date = githubReleases?.find?.( + const publishedAt = githubReleases?.find?.( (githubRelease) => githubRelease?.tagName === formattedNoteTagName, )?.publishedAt; - if (date) { - return formatDate(date); + // If we have a GitHub publishedAt date, return it as-is (ISO date string) + if (publishedAt) { + return publishedAt; } + // Fall back to the MDX frontmatter date return noteDate; }; + diff --git a/packages/twenty-website/src/shared-utils/formatDisplayDate.ts b/packages/twenty-website/src/shared-utils/formatDisplayDate.ts index 5854b56fa6..9134f27c8f 100644 --- a/packages/twenty-website/src/shared-utils/formatDisplayDate.ts +++ b/packages/twenty-website/src/shared-utils/formatDisplayDate.ts @@ -2,11 +2,15 @@ export const formatGithubPublishedAtDisplayDate = ( dateString: string, ): string => { const date = new Date(dateString); + if (Number.isNaN(date.getTime())) return ''; + + const now = new Date(); + const isCurrentYear = date.getFullYear() === now.getFullYear(); const formatter = new Intl.DateTimeFormat('en-US', { - month: 'short', + month: isCurrentYear ? 'long' : 'short', day: 'numeric', - year: 'numeric', + ...(isCurrentYear ? {} : { year: 'numeric' }), }); return formatter.format(date);