From 2f489e1d35060041aaaafdb715a59ba1f33039a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Suwi=C5=84ski?= Date: Thu, 5 Oct 2023 16:10:52 +0200 Subject: [PATCH] order by compound field --- CHANGELOG.md | 4 ++++ jest.setup.ts | 3 ++- package.json | 4 ++-- src/hydra/dataProvider.test.ts | 43 +++++++++++++++++++++++++++++++++- src/hydra/dataProvider.ts | 6 +++-- src/hydra/fetchHydra.ts | 23 +++++++++++------- src/index.ts | 1 + src/types.ts | 32 ++++++++++++------------- 8 files changed, 86 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ad2d97d..c41b16c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 3.4.5 + +* Fix validation errors shown as "Server communication error" when creating an entity + ## 3.4.4 * Enum support in field guesser diff --git a/jest.setup.ts b/jest.setup.ts index 85e80307..663e582a 100644 --- a/jest.setup.ts +++ b/jest.setup.ts @@ -1,8 +1,9 @@ // eslint-disable-next-line import/no-extraneous-dependencies import '@testing-library/jest-dom'; -import { TextEncoder } from 'util'; +import { TextEncoder, TextDecoder } from 'util'; // eslint-disable-next-line import/no-extraneous-dependencies import { Request } from 'node-fetch'; global.TextEncoder = TextEncoder; +global.TextDecoder = TextDecoder as any; global.Request = Request as any; diff --git a/package.json b/package.json index 2e3ed5a3..e833b785 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@api-platform/admin", - "version": "3.4.4", + "version": "3.4.5", "description": "Automatic administration interface for Hydra-enabled APIs.", "files": [ "*.md", @@ -18,7 +18,7 @@ "license": "MIT", "sideEffects": false, "dependencies": { - "@api-platform/api-doc-parser": "^0.16.1", + "@api-platform/api-doc-parser": "^0.16.2", "history": "^5.0.0", "jsonld": "^8.1.0", "lodash.isplainobject": "^4.0.6", diff --git a/src/hydra/dataProvider.test.ts b/src/hydra/dataProvider.test.ts index 44674b40..874ab8ab 100644 --- a/src/hydra/dataProvider.test.ts +++ b/src/hydra/dataProvider.test.ts @@ -138,7 +138,7 @@ describe('Transform a React Admin request to an Hydra request', () => { perPage: 30, }, sort: { - order: '', + order: 'ASC', field: '', }, filter: { @@ -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', + ); + }); }); diff --git a/src/hydra/dataProvider.ts b/src/hydra/dataProvider.ts index 017f5457..385ada41 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()); @@ -722,7 +724,7 @@ function dataProvider( page: 1, }, filter: { id: params.ids }, - sort: { field: '', order: '' }, + sort: { field: '', order: 'ASC' }, }).then(({ data }) => ({ data })); } diff --git a/src/hydra/fetchHydra.ts b/src/hydra/fetchHydra.ts index 99c8afa0..dcc9f70a 100644 --- a/src/hydra/fetchHydra.ts +++ b/src/hydra/fetchHydra.ts @@ -4,7 +4,7 @@ import { getDocumentationUrlFromHeaders, } from '@api-platform/api-doc-parser'; import jsonld from 'jsonld'; -import type { NodeObject } from 'jsonld'; +import type { ContextDefinition, NodeObject } from 'jsonld'; import type { JsonLdObj } from 'jsonld/jsonld-spec'; import type { HttpClientOptions, HydraHttpClientResponse } from '../types.js'; @@ -40,8 +40,12 @@ function fetchHydra( delete (body as NodeObject).trace; - const documentLoader = (input: string) => - fetchJsonLd(input, authOptions).then((response) => { + const documentLoader = (input: string) => { + const loaderOptions = authOptions; + loaderOptions.method = 'GET'; + delete loaderOptions.body; + + return fetchJsonLd(input, loaderOptions).then((response) => { if (!('body' in response)) { throw new Error( 'An empty response was received when expanding JSON-LD error document.', @@ -49,12 +53,15 @@ function fetchHydra( } return response; }); + }; + + return documentLoader(getDocumentationUrlFromHeaders(headers)) + .then((response) => + jsonld.expand(body, { + expandContext: response.document as ContextDefinition, + }), + ) - return jsonld - .expand(body, { - base: getDocumentationUrlFromHeaders(headers), - documentLoader, - }) .then((json) => Promise.reject( new HttpError( diff --git a/src/index.ts b/src/index.ts index 36dd4479..973f5c71 100644 --- a/src/index.ts +++ b/src/index.ts @@ -34,6 +34,7 @@ export { fetchHydra, } from './hydra/index.js'; export type { HydraAdminProps } from './hydra/index.js'; +export { darkTheme, lightTheme } from './layout/index.js'; export { OpenApiAdmin, dataProvider as openApiDataProvider, diff --git a/src/types.ts b/src/types.ts index f060ef14..30032f7d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -226,22 +226,22 @@ export type ApiPlatformAdminDataProviderTypeParams = T extends typeof GET_LIST ? ApiPlatformAdminGetListParams : T extends typeof GET_ONE - ? ApiPlatformAdminGetOneParams - : T extends typeof GET_MANY - ? ApiPlatformAdminGetManyParams - : T extends typeof GET_MANY_REFERENCE - ? ApiPlatformAdminGetManyReferenceParams - : T extends typeof UPDATE - ? ApiPlatformAdminUpdateParams - : T extends typeof UPDATE_MANY - ? ApiPlatformAdminUpdateManyParams - : T extends typeof CREATE - ? ApiPlatformAdminCreateParams - : T extends typeof DELETE - ? ApiPlatformAdminDeleteParams - : T extends typeof DELETE_MANY - ? ApiPlatformAdminDeleteManyParams - : never; + ? ApiPlatformAdminGetOneParams + : T extends typeof GET_MANY + ? ApiPlatformAdminGetManyParams + : T extends typeof GET_MANY_REFERENCE + ? ApiPlatformAdminGetManyReferenceParams + : T extends typeof UPDATE + ? ApiPlatformAdminUpdateParams + : T extends typeof UPDATE_MANY + ? ApiPlatformAdminUpdateManyParams + : T extends typeof CREATE + ? ApiPlatformAdminCreateParams + : T extends typeof DELETE + ? ApiPlatformAdminDeleteParams + : T extends typeof DELETE_MANY + ? ApiPlatformAdminDeleteManyParams + : never; export interface ApiPlatformAdminDataProviderFactoryParams { entrypoint: string;