Repository: api-platform/admin
Pull request #510 (2023-10-05 14:39:49)

compound order by
Hi, 

Adds possibility to sort of compound filed, ex.
```
const UserList = (props) => (
<ListGuesser {...props}>
    // ...
    <FunctionField
       label={"Full name"}
       sortBy={"lastName, firstName"}
        render={(record) => `${record.lastName} ${record.firstName}`}
    />
</ListGuesser>
)
```
On column sort it gives queries with multiple order parameters:
```
https://localhost/users?order[lastName]=asc&order[firstName]=asc
https://localhttps://localhost/users?order[lastName]=desc&order[firstName]=desc
```

API Platform Core and SwaggerUI supports  compound order (multiple order parameter), but Api Platform Admin doesn't allow to achieve it in some simple way.  AFAIK ReactAdmin itself doesn't plan to support multicolumn order in data grids components but resolving of single column order based on sortBy porp  it just a dataProvider job, and can be nicely extended to support such kind compound order.


soyuka: yes it supports that ? https://api-platform.com/docs/core/filters/#order-filter-sorting
PawelSuwinski: > yes it supports that ? https://api-platform.com/docs/core/filters/#order-filter-sorting

Yes, backed does (Core) but it can't be used on the frontend side (excluding SwaggerUI) without extending API Platform Admin dataProvider. Correct me if I miss something. 
PawelSuwinski: Hi, what about merging it? I thinks it is quite useful, and covers gap between core and admin. We use it as a patch, but would be nice to have it official. 

Patch:
diff --git a/src/ListGuesser.tsx b/src/ListGuesser.tsx
index 6583f90..9d24464 100644
--- a/src/ListGuesser.tsx
+++ b/src/ListGuesser.tsx
@@ -70,6 +70,7 @@ export const IntrospectedListGuesser = ({
   empty,
   hover,
   expand,
+  expandSingle,
   optimized,
   size,
   children,
@@ -122,6 +123,7 @@ export const IntrospectedListGuesser = ({
         empty={empty}
         hover={hover}
         expand={expand}
+        expandSingle={expandSingle}
         optimized={optimized}
         size={size}
         sx={datagridSx}>
diff --git a/src/hydra/dataProvider.ts b/src/hydra/dataProvider.ts
index bf1ff01..385ada4 100644
--- a/src/hydra/dataProvider.ts
+++ b/src/hydra/dataProvider.ts
@@ -388,7 +388,9 @@ function dataProvider(
         } = params as GetListParams | GetManyReferenceParams;
 
         if (order && field) {
-          url.searchParams.set(`order[${field}]`, order);
+          field.split(',').forEach((fieldName) => {
+            url.searchParams.set(`order[${fieldName.trim()}]`, order);
+          });
         }
         if (page) url.searchParams.set('page', page.toString());
         if (perPage) url.searchParams.set('itemsPerPage', perPage.toString());


Test patch:
diff --git a/src/hydra/dataProvider.test.ts b/src/hydra/dataProvider.test.ts
index 1d07e17..874ab8a 100644
--- a/src/hydra/dataProvider.test.ts
+++ b/src/hydra/dataProvider.test.ts
@@ -603,4 +603,45 @@ describe('Transform a React Admin request to an Hydra request', () => {
       'http://localhost/entrypoint/comments?order%5Bid%5D=ASC&page=1&itemsPerPage=30',
     );
   });
+
+  test('React Admin get list with compound order', async () => {
+    mockFetchHydra.mockClear();
+    mockFetchHydra.mockReturnValueOnce(
+      Promise.resolve({
+        status: 200,
+        headers: new Headers(),
+        json: {
+          'hydra:member': [
+            { '@id': '/comments/423' },
+            { '@id': '/comments/976' },
+          ],
+          'hydra:totalItems': 2,
+          'hydra:view': {
+            '@id': '/comments?page=1',
+            '@type': 'hydra:PartialCollectionView',
+            'hydra:first': '/comments?page=1',
+            'hydra:last': '/comments?page=1',
+            'hydra:next': '/comments?page=1',
+          },
+        },
+      }),
+    );
+    const result = await dataProvider.current.getList('comments', {
+      pagination: { page: 1, perPage: 30 },
+      sort: { field: 'text, id', order: 'DESC' },
+      filter: false,
+    });
+    expect(result).toEqual({
+      data: [
+        { '@id': '/comments/423', id: '/comments/423' },
+        { '@id': '/comments/976', id: '/comments/976' },
+      ],
+      total: 2,
+    });
+    const url = mockFetchHydra.mock.calls?.[0]?.[0] ?? new URL('https://foo');
+    expect(url).toBeInstanceOf(URL);
+    expect(url.toString()).toEqual(
+      'http://localhost/entrypoint/comments?order%5Btext%5D=DESC&order%5Bid%5D=DESC&page=1&itemsPerPage=30',
+    );
+  });
 });