Migrate Export feature to the action bar (#4417)

* Migrate Export feature to the action bar

* Fixed predicate derived state

* Fixed bug useFindManyParams outside context

* Added export row selection

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
Dragoș Cojocaru
2024-03-14 18:57:09 +02:00
committed by GitHub
parent 04efe5c455
commit 595c7a9ba4
5 changed files with 54 additions and 28 deletions

View File

@ -11,16 +11,14 @@ export const ObjectMetadataItemsProvider = ({
}: React.PropsWithChildren) => { }: React.PropsWithChildren) => {
const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); const objectMetadataItems = useRecoilValue(objectMetadataItemsState());
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState());
const shouldDisplayChildren = () => {
if (objectMetadataItems.length > 0) { const shouldDisplayChildren =
return true; objectMetadataItems.length > 0 || !currentWorkspaceMember;
}
return !currentWorkspaceMember;
};
return ( return (
<> <>
<ObjectMetadataItemsLoadEffect /> <ObjectMetadataItemsLoadEffect />
{shouldDisplayChildren() && ( {shouldDisplayChildren && (
<RelationPickerScope relationPickerScopeId="relation-picker"> <RelationPickerScope relationPickerScopeId="relation-picker">
{children} {children}
</RelationPickerScope> </RelationPickerScope>

View File

@ -6,9 +6,11 @@ import { useFavorites } from '@/favorites/hooks/useFavorites';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { useDeleteManyRecords } from '@/object-record/hooks/useDeleteManyRecords'; import { useDeleteManyRecords } from '@/object-record/hooks/useDeleteManyRecords';
import { useExecuteQuickActionOnOneRecord } from '@/object-record/hooks/useExecuteQuickActionOnOneRecord'; import { useExecuteQuickActionOnOneRecord } from '@/object-record/hooks/useExecuteQuickActionOnOneRecord';
import { useExportTableData } from '@/object-record/record-index/options/hooks/useExportTableData';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { import {
IconClick, IconClick,
IconFileExport,
IconHeart, IconHeart,
IconHeartOff, IconHeartOff,
IconMail, IconMail,
@ -94,6 +96,13 @@ export const useRecordActionBar = ({
); );
}, [callback, executeQuickActionOnOneRecord, selectedRecordIds]); }, [callback, executeQuickActionOnOneRecord, selectedRecordIds]);
const { progress, download } = useExportTableData({
delayMs: 100,
filename: `${objectMetadataItem.nameSingular}.csv`,
objectNameSingular: objectMetadataItem.nameSingular,
recordIndexId: objectMetadataItem.namePlural,
});
const baseActions: ContextMenuEntry[] = useMemo( const baseActions: ContextMenuEntry[] = useMemo(
() => [ () => [
{ {
@ -102,8 +111,14 @@ export const useRecordActionBar = ({
accent: 'danger', accent: 'danger',
onClick: () => handleDeleteClick(), onClick: () => handleDeleteClick(),
}, },
{
label: `${progress === undefined ? `Export` : `Export (${progress}%)`}`,
Icon: IconFileExport,
accent: 'default',
onClick: () => download(),
},
], ],
[handleDeleteClick], [handleDeleteClick, download, progress],
); );
const dataExecuteQuickActionOnmentEnabled = useIsFeatureEnabled( const dataExecuteQuickActionOnmentEnabled = useIsFeatureEnabled(

View File

@ -10,12 +10,16 @@ import { SIGN_IN_BACKGROUND_MOCK_COMPANIES } from '@/sign-in-background-mock/con
import { useFindManyRecords } from '../../hooks/useFindManyRecords'; import { useFindManyRecords } from '../../hooks/useFindManyRecords';
export const useFindManyParams = (objectNameSingular: string) => { export const useFindManyParams = (
objectNameSingular: string,
recordTableId?: string,
) => {
const { objectMetadataItem } = useObjectMetadataItem({ const { objectMetadataItem } = useObjectMetadataItem({
objectNameSingular, objectNameSingular,
}); });
const { getTableFiltersState, getTableSortsState } = useRecordTableStates(); const { getTableFiltersState, getTableSortsState } =
useRecordTableStates(recordTableId);
const tableFilters = useRecoilValue(getTableFiltersState()); const tableFilters = useRecoilValue(getTableFiltersState());
const tableSorts = useRecoilValue(getTableSortsState()); const tableSorts = useRecoilValue(getTableSortsState());

View File

@ -10,7 +10,6 @@ import { useSpreadsheetRecordImport } from '@/object-record/spreadsheet-import/u
import { import {
IconBaselineDensitySmall, IconBaselineDensitySmall,
IconChevronLeft, IconChevronLeft,
IconFileExport,
IconFileImport, IconFileImport,
IconTag, IconTag,
} from '@/ui/display/icon'; } from '@/ui/display/icon';
@ -27,8 +26,6 @@ import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates'
import { useViewBar } from '@/views/hooks/useViewBar'; import { useViewBar } from '@/views/hooks/useViewBar';
import { ViewType } from '@/views/types/ViewType'; import { ViewType } from '@/views/types/ViewType';
import { useExportTableData } from '../hooks/useExportTableData';
type RecordIndexOptionsMenu = 'fields'; type RecordIndexOptionsMenu = 'fields';
type RecordIndexOptionsDropdownContentProps = { type RecordIndexOptionsDropdownContentProps = {
@ -122,13 +119,6 @@ export const RecordIndexOptionsDropdownContent = ({
const { openRecordSpreadsheetImport } = const { openRecordSpreadsheetImport } =
useSpreadsheetRecordImport(objectNameSingular); useSpreadsheetRecordImport(objectNameSingular);
const { progress, download } = useExportTableData({
delayMs: 100,
filename: `${objectNameSingular}.csv`,
objectNameSingular,
recordIndexId,
});
return ( return (
<> <>
{!currentMenu && ( {!currentMenu && (
@ -157,11 +147,6 @@ export const RecordIndexOptionsDropdownContent = ({
LeftIcon={IconFileImport} LeftIcon={IconFileImport}
text="Import" text="Import"
/> />
<MenuItem
onClick={download}
LeftIcon={IconFileExport}
text={progress === undefined ? `Export` : `Export (${progress}%)`}
/>
</DropdownMenuItemsContainer> </DropdownMenuItemsContainer>
</> </>
)} )}

View File

@ -108,12 +108,36 @@ export const useExportTableData = ({
const [pageCount, setPageCount] = useState(0); const [pageCount, setPageCount] = useState(0);
const [progress, setProgress] = useState<number | undefined>(undefined); const [progress, setProgress] = useState<number | undefined>(undefined);
const [hasNextPage, setHasNextPage] = useState(true); const [hasNextPage, setHasNextPage] = useState(true);
const { getVisibleTableColumnsSelector } =
const { getVisibleTableColumnsSelector, getSelectedRowIdsSelector } =
useRecordTableStates(recordIndexId); useRecordTableStates(recordIndexId);
const columns = useRecoilValue(getVisibleTableColumnsSelector()); const columns = useRecoilValue(getVisibleTableColumnsSelector());
const params = useFindManyParams(objectNameSingular); const selectedRowIds = useRecoilValue(getSelectedRowIdsSelector());
const hasSelectedRows = selectedRowIds.length > 0;
const findManyRecordsParams = useFindManyParams(
objectNameSingular,
recordIndexId,
);
const selectedFindManyParams = {
...findManyRecordsParams,
filter: {
...findManyRecordsParams.filter,
id: {
in: selectedRowIds,
},
},
};
const usedFindManyParams = hasSelectedRows
? selectedFindManyParams
: findManyRecordsParams;
const { totalCount, records, fetchMoreRecords } = useFindManyRecords({ const { totalCount, records, fetchMoreRecords } = useFindManyRecords({
...params, ...usedFindManyParams,
limit: pageSize, limit: pageSize,
onCompleted: (_data, { hasNextPage }) => { onCompleted: (_data, { hasNextPage }) => {
setHasNextPage(hasNextPage ?? false); setHasNextPage(hasNextPage ?? false);