Skip to content

Commit

Permalink
[TypeScript] Improve List exporter type
Browse files Browse the repository at this point in the history
  • Loading branch information
fzaninotto committed Jul 1, 2024
1 parent 39ee8d0 commit 7f54479
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 18 deletions.
1 change: 1 addition & 0 deletions examples/crm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"@testing-library/user-event": "^14.5.2",
"@types/faker": "^5.1.7",
"@types/jest": "^29.5.2",
"@types/jsonexport": "^3.0.5",
"@types/lodash": "~4.14.168",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
Expand Down
63 changes: 53 additions & 10 deletions examples/crm/src/contacts/ContactList.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
/* eslint-disable import/no-anonymous-default-export */
import * as React from 'react';
import {
BulkActionsToolbar,
BulkDeleteButton,
CreateButton,
downloadCSV,
ExportButton,
List as RaList,
SimpleListLoading,
Pagination,
RecordContextProvider,
ReferenceField,
TextField,
useListContext,
ExportButton,
SimpleListLoading,
SortButton,
TextField,
TopToolbar,
CreateButton,
Pagination,
useGetIdentity,
BulkActionsToolbar,
BulkDeleteButton,
RecordContextProvider,
useListContext,
number,
} from 'react-admin';
import type { FetchRelatedRecords, DataProvider } from 'react-admin';
import {
List,
ListItem,
Expand All @@ -28,12 +31,13 @@ import {
} from '@mui/material';
import { Link } from 'react-router-dom';
import { formatDistance } from 'date-fns';
import jsonExport from 'jsonexport/dist';

import { Avatar } from './Avatar';
import { Status } from '../misc/Status';
import { TagsList } from './TagsList';
import { ContactListFilter } from './ContactListFilter';
import { Contact } from '../types';
import { Contact, Company, Sale, Tag } from '../types';

const ContactListContent = () => {
const {
Expand Down Expand Up @@ -140,6 +144,44 @@ const ContactListActions = () => (
</TopToolbar>
);

const exporter = async (
records: Contact[],
fetchRelatedRecords: FetchRelatedRecords,
dataProvider: DataProvider
) => {
const companies = await fetchRelatedRecords<Company>(
records,
'company_id',
'companies'
);
const sales = await fetchRelatedRecords<Sale>(records, 'sales_id', 'sales');
const tagIds = records.reduce<number[]>(
(acc, contact) => acc.concat(contact.tags as number[]),
[]
);
const { data: tags } = await dataProvider.getMany<Tag>('tags', {
ids: Array.from(new Set(tagIds)),
});
const tagsById = tags.reduce<{ [key: number]: Tag }>((acc, tag) => {
acc[tag.id as number] = tag;
return acc;
}, {});

const contacts = records.map(contact => ({
...contact,
company: companies[contact.company_id as number].name,
sales: `${sales[contact.sales_id as number].first_name} ${
sales[contact.sales_id as number].last_name
}`,
tags: contact.tags
.map(tagId => tagsById[tagId as number].name)
.join(', '),
}));
return jsonExport(contacts, {}, (_err: any, csv: string) => {
downloadCSV(csv, 'contacts');
});
};

export const ContactList = () => {
const { identity } = useGetIdentity();
return identity ? (
Expand All @@ -150,6 +192,7 @@ export const ContactList = () => {
pagination={<Pagination rowsPerPageOptions={[10, 25, 50, 100]} />}
filterDefaultValues={{ sales_id: identity?.id }}
sort={{ field: 'last_seen', order: 'DESC' }}
exporter={exporter}
>
<ContactListContent />
</RaList>
Expand Down
3 changes: 2 additions & 1 deletion examples/simple/src/comments/CommentList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
ListActions,
DateField,
EditButton,
FetchRelatedRecords,
Pagination,
ReferenceField,
ReferenceInput,
Expand All @@ -36,7 +37,7 @@ const commentFilters = [
<ReferenceInput source="post_id" reference="posts" />,
];

const exporter = (records, fetchRelatedRecords) =>
const exporter = (records, fetchRelatedRecords: FetchRelatedRecords) =>
fetchRelatedRecords(records, 'post_id', 'posts').then(posts => {
const data = records.map(record => {
const { author, ...recordForExport } = record; // omit author
Expand Down
10 changes: 8 additions & 2 deletions packages/ra-core/src/export/fetchRelatedRecords.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { RaRecord, Identifier, DataProvider } from '../types';
import {
RaRecord,
Identifier,
DataProvider,
FetchRelatedRecords,
} from '../types';

/**
* Helper function for calling the dataProvider.getMany() method,
Expand All @@ -13,7 +18,8 @@ import { RaRecord, Identifier, DataProvider } from '../types';
* );
*/
const fetchRelatedRecords =
(dataProvider: DataProvider) => (data, field, resource) =>
(dataProvider: DataProvider): FetchRelatedRecords =>
(data, field, resource) =>
dataProvider
.getMany(resource, { ids: getRelatedIds(data, field) })
.then(({ data }) =>
Expand Down
12 changes: 7 additions & 5 deletions packages/ra-core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -368,15 +368,17 @@ export interface ResourceProps {

export type Exporter = (
data: any,
fetchRelatedRecords: (
data: any,
field: string,
resource: string
) => Promise<any>,
fetchRelatedRecords: FetchRelatedRecords,
dataProvider: DataProvider,
resource?: string
) => void | Promise<void>;

export type FetchRelatedRecords = <RecordType = any>(
data: any[],
field: string,
resource: string
) => Promise<{ [key: Identifier]: RecordType }>;

export type SetOnSave = (
onSave?: (values: object, redirect: any) => void
) => void;
Expand Down
10 changes: 10 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5975,6 +5975,15 @@ __metadata:
languageName: node
linkType: hard

"@types/jsonexport@npm:^3.0.5":
version: 3.0.5
resolution: "@types/jsonexport@npm:3.0.5"
dependencies:
"@types/node": "npm:*"
checksum: 5234efbccb2d28632bf5f47272c838d1f011a1e34c9bf36f329edafe17c51b81d12ceb455c919adf7f5c6cd946ba9049c2a9782d7caf7cb0ff60aa0e5e2fa63b
languageName: node
linkType: hard

"@types/lodash@npm:^4.14.167, @types/lodash@npm:^4.14.168, @types/lodash@npm:^4.14.175, @types/lodash@npm:~4.14.168":
version: 4.14.194
resolution: "@types/lodash@npm:4.14.194"
Expand Down Expand Up @@ -18058,6 +18067,7 @@ __metadata:
"@testing-library/user-event": "npm:^14.5.2"
"@types/faker": "npm:^5.1.7"
"@types/jest": "npm:^29.5.2"
"@types/jsonexport": "npm:^3.0.5"
"@types/lodash": "npm:~4.14.168"
"@types/react": "npm:^18.3.3"
"@types/react-dom": "npm:^18.3.0"
Expand Down

0 comments on commit 7f54479

Please sign in to comment.