diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTable.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTable.tsx index a7ca5c948..3e792cc2b 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTable.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTable.tsx @@ -1,36 +1,17 @@ -import styled from '@emotion/styled'; import { isNonEmptyString } from '@sniptt/guards'; +import { useRef } from 'react'; import { hasRecordGroupsComponentSelector } from '@/object-record/record-group/states/selectors/hasRecordGroupsComponentSelector'; import { recordIndexAllRecordIdsComponentSelector } from '@/object-record/record-index/states/selectors/recordIndexAllRecordIdsComponentSelector'; -import { RecordTableStickyBottomEffect } from '@/object-record/record-table/components/RecordTableStickyBottomEffect'; -import { RecordTableStickyEffect } from '@/object-record/record-table/components/RecordTableStickyEffect'; +import { RecordTableBodyEffectsWrapper } from '@/object-record/record-table/components/RecordTableBodyEffectsWrapper'; +import { RecordTableContent } from '@/object-record/record-table/components/RecordTableContent'; +import { RecordTableEmpty } from '@/object-record/record-table/components/RecordTableEmpty'; import { RECORD_TABLE_CLICK_OUTSIDE_LISTENER_ID } from '@/object-record/record-table/constants/RecordTableClickOutsideListenerId'; import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext'; -import { RecordTableEmptyState } from '@/object-record/record-table/empty-state/components/RecordTableEmptyState'; import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; -import { RecordTableBodyUnselectEffect } from '@/object-record/record-table/record-table-body/components/RecordTableBodyUnselectEffect'; -import { RecordTableNoRecordGroupBody } from '@/object-record/record-table/record-table-body/components/RecordTableNoRecordGroupBody'; -import { RecordTableNoRecordGroupBodyEffect } from '@/object-record/record-table/record-table-body/components/RecordTableNoRecordGroupBodyEffect'; -import { RecordTableRecordGroupBodyEffects } from '@/object-record/record-table/record-table-body/components/RecordTableRecordGroupBodyEffects'; -import { RecordTableRecordGroupsBody } from '@/object-record/record-table/record-table-body/components/RecordTableRecordGroupsBody'; -import { RecordTableHeader } from '@/object-record/record-table/record-table-header/components/RecordTableHeader'; import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState'; -import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect'; import { useClickOutsideListener } from '@/ui/utilities/pointer-event/hooks/useClickOutsideListener'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; -import { useRef } from 'react'; - -const StyledTable = styled.table` - border-radius: ${({ theme }) => theme.border.radius.sm}; - border-spacing: 0; - table-layout: fixed; - width: 100%; - - .footer-sticky tr:nth-last-of-type(2) td { - border-bottom-color: ${({ theme }) => theme.background.transparent}; - } -`; export const RecordTable = () => { const { recordTableId, objectNameSingular } = useRecordTableContextOrThrow(); @@ -56,51 +37,46 @@ export const RecordTable = () => { recordTableId, ); - const recordTableIsEmpty = - !isRecordTableInitialLoading && allRecordIds.length === 0; - const { resetTableRowSelection, setRowSelected } = useRecordTable({ recordTableId, }); + const recordTableIsEmpty = + !isRecordTableInitialLoading && allRecordIds.length === 0; + if (!isNonEmptyString(objectNameSingular)) { return <>; } + const handleDragSelectionStart = () => { + resetTableRowSelection(); + toggleClickOutsideListener(false); + }; + + const handleDragSelectionEnd = () => { + toggleClickOutsideListener(true); + }; + return ( <> - {!hasRecordGroups ? ( - - ) : ( - - )} - + + {recordTableIsEmpty ? ( - + ) : ( - <> - - - {!hasRecordGroups ? ( - - ) : ( - - )} - - - - { - resetTableRowSelection(); - toggleClickOutsideListener(false); - }} - onDragSelectionChange={setRowSelected} - onDragSelectionEnd={() => { - toggleClickOutsideListener(true); - }} - /> - + )} ); diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableBodyEffectsWrapper.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableBodyEffectsWrapper.tsx new file mode 100644 index 000000000..3d2954312 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableBodyEffectsWrapper.tsx @@ -0,0 +1,22 @@ +import { RecordTableBodyUnselectEffect } from '@/object-record/record-table/record-table-body/components/RecordTableBodyUnselectEffect'; +import { RecordTableNoRecordGroupBodyEffect } from '@/object-record/record-table/record-table-body/components/RecordTableNoRecordGroupBodyEffect'; +import { RecordTableRecordGroupBodyEffects } from '@/object-record/record-table/record-table-body/components/RecordTableRecordGroupBodyEffects'; + +export interface RecordTableBodyEffectsWrapperProps { + hasRecordGroups: boolean; + tableBodyRef: React.RefObject; +} + +export const RecordTableBodyEffectsWrapper = ({ + hasRecordGroups, + tableBodyRef, +}: RecordTableBodyEffectsWrapperProps) => ( + <> + {hasRecordGroups ? ( + + ) : ( + + )} + + +); diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableContent.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableContent.tsx new file mode 100644 index 000000000..d5dc7425f --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableContent.tsx @@ -0,0 +1,42 @@ +import { RecordTableStickyBottomEffect } from '@/object-record/record-table/components/RecordTableStickyBottomEffect'; +import { RecordTableStickyEffect } from '@/object-record/record-table/components/RecordTableStickyEffect'; +import { StyledTable } from '@/object-record/record-table/components/RecordTableStyles'; +import { RecordTableNoRecordGroupBody } from '@/object-record/record-table/record-table-body/components/RecordTableNoRecordGroupBody'; +import { RecordTableRecordGroupsBody } from '@/object-record/record-table/record-table-body/components/RecordTableRecordGroupsBody'; +import { RecordTableHeader } from '@/object-record/record-table/record-table-header/components/RecordTableHeader'; +import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect'; + +export interface RecordTableContentProps { + tableBodyRef: React.RefObject; + handleDragSelectionStart: () => void; + handleDragSelectionEnd: () => void; + setRowSelected: (rowId: string, selected: boolean) => void; + hasRecordGroups: boolean; +} + +export const RecordTableContent = ({ + tableBodyRef, + handleDragSelectionStart, + handleDragSelectionEnd, + setRowSelected, + hasRecordGroups, +}: RecordTableContentProps) => ( + <> + + + {hasRecordGroups ? ( + + ) : ( + + )} + + + + + +); diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableEmpty.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableEmpty.tsx new file mode 100644 index 000000000..89887fa10 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableEmpty.tsx @@ -0,0 +1,25 @@ +import { StyledTable } from '@/object-record/record-table/components/RecordTableStyles'; +import { RecordTableEmptyState } from '@/object-record/record-table/empty-state/components/RecordTableEmptyState'; +import { RecordTableRecordGroupsBody } from '@/object-record/record-table/record-table-body/components/RecordTableRecordGroupsBody'; +import { RecordTableHeader } from '@/object-record/record-table/record-table-header/components/RecordTableHeader'; + +export interface RecordTableEmptyProps { + tableBodyRef: React.RefObject; + hasRecordGroups: boolean; +} + +export const RecordTableEmpty = ({ + tableBodyRef, + hasRecordGroups, +}: RecordTableEmptyProps) => ( + <> + + + + {hasRecordGroups ? ( + + ) : ( + + )} + +); diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableStyles.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableStyles.tsx new file mode 100644 index 000000000..bcf481903 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableStyles.tsx @@ -0,0 +1,12 @@ +import styled from '@emotion/styled'; + +export const StyledTable = styled.table` + border-radius: ${({ theme }) => theme.border.radius.sm}; + border-spacing: 0; + table-layout: fixed; + width: 100%; + + .footer-sticky tr:nth-last-of-type(2) td { + border-bottom-color: ${({ theme }) => theme.background.transparent}; + } +`; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderCheckboxColumn.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderCheckboxColumn.tsx index 4008c0aed..5cdd9ce4e 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderCheckboxColumn.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderCheckboxColumn.tsx @@ -1,6 +1,9 @@ import styled from '@emotion/styled'; +import { recordIndexAllRecordIdsComponentSelector } from '@/object-record/record-index/states/selectors/recordIndexAllRecordIdsComponentSelector'; +import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext'; import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; +import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState'; import { allRowsSelectedStatusComponentSelector } from '@/object-record/record-table/states/selectors/allRowsSelectedStatusComponentSelector'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { Checkbox } from 'twenty-ui/input'; @@ -30,6 +33,21 @@ export const RecordTableHeaderCheckboxColumn = () => { allRowsSelectedStatus === 'all' || allRowsSelectedStatus === 'some'; const indeterminate = allRowsSelectedStatus === 'some'; + const { recordTableId } = useRecordTableContextOrThrow(); + + const isRecordTableInitialLoading = useRecoilComponentValueV2( + isRecordTableInitialLoadingComponentState, + recordTableId, + ); + + const allRecordIds = useRecoilComponentValueV2( + recordIndexAllRecordIdsComponentSelector, + recordTableId, + ); + + const recordTableIsEmpty = + !isRecordTableInitialLoading && allRecordIds.length === 0; + const onChange = () => { if (checked) { setHasUserSelectedAllRows(false); @@ -48,6 +66,7 @@ export const RecordTableHeaderCheckboxColumn = () => { checked={checked} onChange={onChange} indeterminate={indeterminate} + disabled={recordTableIsEmpty} />