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:
@ -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>
|
||||||
|
|||||||
@ -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(
|
||||||
|
|||||||
@ -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());
|
||||||
|
|||||||
@ -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>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user