ding-react-admin 1.0.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/README.md +38 -13
  2. package/dist/index.js +1317 -1060
  3. package/dist/src/crud/InlineFormSet.d.ts +12 -25
  4. package/dist/src/crud/InlineFormSet.d.ts.map +1 -1
  5. package/dist/src/crud/ResourceForm.d.ts +7 -4
  6. package/dist/src/crud/ResourceForm.d.ts.map +1 -1
  7. package/dist/src/crud/ResourceFormModal.d.ts.map +1 -1
  8. package/dist/src/crud/ResourceList.d.ts.map +1 -1
  9. package/dist/src/crud/columns/ImageColumn.d.ts +14 -0
  10. package/dist/src/crud/columns/ImageColumn.d.ts.map +1 -0
  11. package/dist/src/crud/context/InlineFieldsRegistry.d.ts +15 -0
  12. package/dist/src/crud/context/InlineFieldsRegistry.d.ts.map +1 -0
  13. package/dist/src/crud/context/PayloadFieldsContext.d.ts +18 -0
  14. package/dist/src/crud/context/PayloadFieldsContext.d.ts.map +1 -0
  15. package/dist/src/crud/fields/BooleanField.d.ts +3 -1
  16. package/dist/src/crud/fields/BooleanField.d.ts.map +1 -1
  17. package/dist/src/crud/fields/DateField.d.ts +3 -1
  18. package/dist/src/crud/fields/DateField.d.ts.map +1 -1
  19. package/dist/src/crud/fields/FieldWrapper.d.ts +7 -14
  20. package/dist/src/crud/fields/FieldWrapper.d.ts.map +1 -1
  21. package/dist/src/crud/fields/FileField.d.ts +12 -0
  22. package/dist/src/crud/fields/FileField.d.ts.map +1 -0
  23. package/dist/src/crud/fields/ImageField.d.ts +14 -0
  24. package/dist/src/crud/fields/ImageField.d.ts.map +1 -0
  25. package/dist/src/crud/fields/NumberField.d.ts +5 -3
  26. package/dist/src/crud/fields/NumberField.d.ts.map +1 -1
  27. package/dist/src/crud/fields/PasswordField.d.ts +5 -3
  28. package/dist/src/crud/fields/PasswordField.d.ts.map +1 -1
  29. package/dist/src/crud/fields/ReferenceField.d.ts +6 -5
  30. package/dist/src/crud/fields/ReferenceField.d.ts.map +1 -1
  31. package/dist/src/crud/fields/ReferenceManyField.d.ts +3 -1
  32. package/dist/src/crud/fields/ReferenceManyField.d.ts.map +1 -1
  33. package/dist/src/crud/fields/SelectField.d.ts +3 -1
  34. package/dist/src/crud/fields/SelectField.d.ts.map +1 -1
  35. package/dist/src/crud/fields/TextField.d.ts +5 -3
  36. package/dist/src/crud/fields/TextField.d.ts.map +1 -1
  37. package/dist/src/crud/fields/uploadFieldUtils.d.ts +5 -0
  38. package/dist/src/crud/fields/uploadFieldUtils.d.ts.map +1 -0
  39. package/dist/src/crud/fields/useUploadPreviewUrl.d.ts +4 -0
  40. package/dist/src/crud/fields/useUploadPreviewUrl.d.ts.map +1 -0
  41. package/dist/src/crud/index.d.ts +26 -9
  42. package/dist/src/crud/index.d.ts.map +1 -1
  43. package/dist/src/crud/types.d.ts +23 -20
  44. package/dist/src/crud/types.d.ts.map +1 -1
  45. package/dist/src/crud/utils/buildFormPayload.d.ts +6 -0
  46. package/dist/src/crud/utils/buildFormPayload.d.ts.map +1 -0
  47. package/dist/src/crud/utils/buildInlineRowsPayload.d.ts +6 -0
  48. package/dist/src/crud/utils/buildInlineRowsPayload.d.ts.map +1 -0
  49. package/dist/src/crud/utils/buildResourceFormSubmitBody.d.ts +5 -0
  50. package/dist/src/crud/utils/buildResourceFormSubmitBody.d.ts.map +1 -0
  51. package/dist/src/crud/utils/formErrors.d.ts +1 -1
  52. package/dist/src/crud/utils/formErrors.d.ts.map +1 -1
  53. package/dist/src/crud/utils/getFormValue.d.ts +3 -0
  54. package/dist/src/crud/utils/getFormValue.d.ts.map +1 -0
  55. package/dist/src/crud/utils/hasUploadValues.d.ts +3 -0
  56. package/dist/src/crud/utils/hasUploadValues.d.ts.map +1 -0
  57. package/dist/src/crud/utils/nestedFieldPath.d.ts +3 -0
  58. package/dist/src/crud/utils/nestedFieldPath.d.ts.map +1 -0
  59. package/dist/src/crud/utils/prepareFormSubmitBody.d.ts +7 -0
  60. package/dist/src/crud/utils/prepareFormSubmitBody.d.ts.map +1 -0
  61. package/dist/src/crud/utils/setFormValue.d.ts +3 -0
  62. package/dist/src/crud/utils/setFormValue.d.ts.map +1 -0
  63. package/dist/src/crud/utils/toFormData.d.ts +13 -0
  64. package/dist/src/crud/utils/toFormData.d.ts.map +1 -0
  65. package/dist/src/crud/utils/useAbortableEffect.d.ts +7 -0
  66. package/dist/src/crud/utils/useAbortableEffect.d.ts.map +1 -0
  67. package/dist/src/crud/utils/useFormRecord.d.ts +42 -0
  68. package/dist/src/crud/utils/useFormRecord.d.ts.map +1 -0
  69. package/dist/src/data/abortError.d.ts +3 -0
  70. package/dist/src/data/abortError.d.ts.map +1 -0
  71. package/dist/src/data/abortError.test.d.ts +2 -0
  72. package/dist/src/data/abortError.test.d.ts.map +1 -0
  73. package/dist/src/data/createRestResourceHandlers.d.ts +6 -6
  74. package/dist/src/data/createRestResourceHandlers.d.ts.map +1 -1
  75. package/dist/src/data/dataProviderTypes.d.ts +13 -6
  76. package/dist/src/data/dataProviderTypes.d.ts.map +1 -1
  77. package/dist/src/data/parseFormErrorHelpers.d.ts +44 -6
  78. package/dist/src/data/parseFormErrorHelpers.d.ts.map +1 -1
  79. package/dist/src/data/resourceHandlers.d.ts +3 -3
  80. package/dist/src/data/resourceHandlers.d.ts.map +1 -1
  81. package/dist/src/index.d.ts +5 -4
  82. package/dist/src/index.d.ts.map +1 -1
  83. package/dist/src/layouts/AdminLayout.d.ts.map +1 -1
  84. package/package.json +59 -59
  85. package/src/crud/InlineFormSet.tsx +90 -159
  86. package/src/crud/ResourceForm.tsx +83 -204
  87. package/src/crud/ResourceFormModal.tsx +57 -45
  88. package/src/crud/ResourceList.tsx +36 -26
  89. package/src/crud/columns/ImageColumn.tsx +58 -0
  90. package/src/crud/columns/TextColumn.tsx +2 -2
  91. package/src/crud/context/InlineFieldsRegistry.tsx +61 -0
  92. package/src/crud/context/PayloadFieldsContext.tsx +62 -0
  93. package/src/crud/fields/BooleanField.tsx +22 -16
  94. package/src/crud/fields/DateField.tsx +32 -26
  95. package/src/crud/fields/FieldWrapper.tsx +87 -109
  96. package/src/crud/fields/FileField.tsx +123 -0
  97. package/src/crud/fields/ImageField.tsx +120 -0
  98. package/src/crud/fields/NumberField.tsx +36 -34
  99. package/src/crud/fields/PasswordField.tsx +41 -40
  100. package/src/crud/fields/ReferenceField.tsx +35 -130
  101. package/src/crud/fields/ReferenceManyField.tsx +31 -25
  102. package/src/crud/fields/SelectField.tsx +6 -0
  103. package/src/crud/fields/TextField.tsx +32 -30
  104. package/src/crud/fields/uploadFieldUtils.ts +21 -0
  105. package/src/crud/fields/useUploadPreviewUrl.ts +20 -0
  106. package/src/crud/index.ts +35 -14
  107. package/src/crud/types.ts +134 -130
  108. package/src/crud/utils/buildFormPayload.ts +24 -0
  109. package/src/crud/utils/buildInlineRowsPayload.ts +37 -0
  110. package/src/crud/utils/buildResourceFormSubmitBody.ts +29 -0
  111. package/src/crud/utils/formErrors.ts +42 -38
  112. package/src/crud/utils/{getByPath.ts → getFormValue.ts} +2 -2
  113. package/src/crud/utils/hasUploadValues.ts +9 -0
  114. package/src/crud/utils/nestedFieldPath.ts +8 -0
  115. package/src/crud/utils/prepareFormSubmitBody.ts +17 -0
  116. package/src/crud/utils/{setByPath.ts → setFormValue.ts} +2 -2
  117. package/src/crud/utils/toFormData.ts +81 -0
  118. package/src/crud/utils/useAbortableEffect.ts +17 -0
  119. package/src/crud/utils/useFormRecord.ts +156 -0
  120. package/src/data/abortError.test.ts +19 -0
  121. package/src/data/abortError.ts +10 -0
  122. package/src/data/createMemoryResourceHandlers.ts +1 -1
  123. package/src/data/createRestResourceHandlers.ts +22 -16
  124. package/src/data/dataProviderTypes.ts +15 -5
  125. package/src/data/dataUtils.test.ts +118 -6
  126. package/src/data/parseFormErrorHelpers.test.ts +138 -84
  127. package/src/data/parseFormErrorHelpers.ts +311 -224
  128. package/src/data/resourceHandlers.ts +5 -4
  129. package/src/index.ts +34 -9
  130. package/src/layouts/AdminLayout.tsx +2 -1
  131. package/dist/src/crud/context/FormFieldsContext.d.ts +0 -14
  132. package/dist/src/crud/context/FormFieldsContext.d.ts.map +0 -1
  133. package/dist/src/crud/context/InlineFormContext.d.ts +0 -16
  134. package/dist/src/crud/context/InlineFormContext.d.ts.map +0 -1
  135. package/dist/src/crud/fields/useInlineOrFormField.d.ts +0 -10
  136. package/dist/src/crud/fields/useInlineOrFormField.d.ts.map +0 -1
  137. package/dist/src/crud/utils/getByPath.d.ts +0 -3
  138. package/dist/src/crud/utils/getByPath.d.ts.map +0 -1
  139. package/dist/src/crud/utils/inlineArrayName.d.ts +0 -3
  140. package/dist/src/crud/utils/inlineArrayName.d.ts.map +0 -1
  141. package/dist/src/crud/utils/pickBySources.d.ts +0 -6
  142. package/dist/src/crud/utils/pickBySources.d.ts.map +0 -1
  143. package/dist/src/crud/utils/setByPath.d.ts +0 -3
  144. package/dist/src/crud/utils/setByPath.d.ts.map +0 -1
  145. package/src/crud/context/FormFieldsContext.tsx +0 -76
  146. package/src/crud/context/InlineFormContext.tsx +0 -71
  147. package/src/crud/fields/useInlineOrFormField.tsx +0 -91
  148. package/src/crud/utils/inlineArrayName.ts +0 -4
  149. package/src/crud/utils/pickBySources.ts +0 -24
@@ -1,84 +1,138 @@
1
- import { describe, expect, it } from "vitest";
2
- import {
3
- parseDjangoDRFFormErrors,
4
- parseDotNetFormErrors,
5
- parseNodeFormErrors,
6
- } from "./parseFormErrorHelpers";
7
-
8
- const mainCtx = { resource: "users", mutation: "create" as const };
9
- const inlineCtx = {
10
- resource: "invoice-lines",
11
- mutation: "create" as const,
12
- inlineArrayName: "__inline_invoice_lines",
13
- rowIndex: 1,
14
- };
15
-
16
- describe("parseDjangoDRFFormErrors", () => {
17
- it("maps field and non_field_errors", () => {
18
- const parsed = parseDjangoDRFFormErrors(
19
- {
20
- body: {
21
- email: ["Enter a valid email."],
22
- non_field_errors: ["Cannot save"],
23
- },
24
- },
25
- mainCtx,
26
- );
27
- expect(parsed).toEqual({
28
- fields: { email: "Enter a valid email." },
29
- global: ["Cannot save"],
30
- });
31
- });
32
-
33
- it("prefixes inline row fields", () => {
34
- const parsed = parseDjangoDRFFormErrors(
35
- { body: { quantity: ["Must be positive"] } },
36
- inlineCtx,
37
- );
38
- expect(parsed?.fields).toEqual({
39
- "__inline_invoice_lines.1.quantity": "Must be positive",
40
- });
41
- });
42
- });
43
-
44
- describe("parseDotNetFormErrors", () => {
45
- it("maps errors object with camelCase", () => {
46
- const parsed = parseDotNetFormErrors(
47
- {
48
- body: {
49
- errors: { Email: ["The Email field is required."] },
50
- },
51
- },
52
- mainCtx,
53
- );
54
- expect(parsed?.fields).toEqual({
55
- email: "The Email field is required.",
56
- });
57
- });
58
- });
59
-
60
- describe("parseNodeFormErrors", () => {
61
- it("maps express-validator array", () => {
62
- const parsed = parseNodeFormErrors(
63
- {
64
- body: {
65
- errors: [{ path: "email", msg: "Invalid email" }],
66
- },
67
- },
68
- mainCtx,
69
- );
70
- expect(parsed?.fields).toEqual({ email: "Invalid email" });
71
- });
72
-
73
- it("maps Joi details", () => {
74
- const parsed = parseNodeFormErrors(
75
- {
76
- body: {
77
- details: [{ message: "Required", path: ["email"] }],
78
- },
79
- },
80
- mainCtx,
81
- );
82
- expect(parsed?.fields).toEqual({ email: "Required" });
83
- });
84
- });
1
+ import { describe, expect, it } from "vitest";
2
+ import {
3
+ parseDjangoDRFFormErrors,
4
+ parseDotNetFormErrors,
5
+ parseNodeFormErrors,
6
+ flattenNestedArrayErrors,
7
+ resolveErrorBody,
8
+ } from "./parseFormErrorHelpers";
9
+
10
+ const mainCtx = { resource: "users", mutation: "create" as const };
11
+
12
+ describe("parseDjangoDRFFormErrors", () => {
13
+ it("maps field and non_field_errors", () => {
14
+ const parsed = parseDjangoDRFFormErrors(
15
+ {
16
+ body: {
17
+ email: ["Enter a valid email."],
18
+ non_field_errors: ["Cannot save"],
19
+ },
20
+ },
21
+ mainCtx,
22
+ );
23
+ expect(parsed).toEqual({
24
+ fields: { email: "Enter a valid email." },
25
+ global: ["Cannot save"],
26
+ });
27
+ });
28
+
29
+ it("flattens nested inline row errors", () => {
30
+ const parsed = parseDjangoDRFFormErrors(
31
+ {
32
+ body: {
33
+ lines: [
34
+ { quantity: ["Must be positive"] },
35
+ {},
36
+ { label: ["Required"] },
37
+ ],
38
+ },
39
+ },
40
+ mainCtx,
41
+ );
42
+ expect(parsed?.fields).toEqual({
43
+ "lines.0.quantity": "Must be positive",
44
+ "lines.2.label": "Required",
45
+ });
46
+ });
47
+ });
48
+
49
+ describe("resolveErrorBody", () => {
50
+ it("reads axios-style response.data", async () => {
51
+ const body = await resolveErrorBody({
52
+ response: { data: { email: ["Invalid"] } },
53
+ });
54
+ expect(body).toEqual({ email: ["Invalid"] });
55
+ });
56
+
57
+ it("reads fetch ResponseError response.json()", async () => {
58
+ const response = new Response(
59
+ JSON.stringify({ email: ["Enter a valid email address."] }),
60
+ {
61
+ status: 400,
62
+ headers: { "Content-Type": "application/json" },
63
+ },
64
+ );
65
+ const body = await resolveErrorBody({
66
+ name: "ResponseError",
67
+ message: "Response returned an error code",
68
+ response,
69
+ });
70
+ expect(body).toEqual({ email: ["Enter a valid email address."] });
71
+ });
72
+
73
+ it("returns null for non-json fetch responses", async () => {
74
+ const response = new Response("bad request", {
75
+ status: 400,
76
+ headers: { "Content-Type": "text/plain" },
77
+ });
78
+ const body = await resolveErrorBody({ response });
79
+ expect(body).toBeNull();
80
+ });
81
+ });
82
+
83
+ describe("flattenNestedArrayErrors", () => {
84
+ it("maps row errors to RHF paths", () => {
85
+ const fields: Record<string, string | string[]> = {};
86
+ flattenNestedArrayErrors("lines", [
87
+ { label: ["Required"] },
88
+ { quantity: ["Too small", "Invalid"] },
89
+ ], fields);
90
+ expect(fields).toEqual({
91
+ "lines.0.label": "Required",
92
+ "lines.1.quantity": ["Too small", "Invalid"],
93
+ });
94
+ });
95
+ });
96
+
97
+ describe("parseDotNetFormErrors", () => {
98
+ it("maps errors object with camelCase", () => {
99
+ const parsed = parseDotNetFormErrors(
100
+ {
101
+ body: {
102
+ errors: { Email: ["The Email field is required."] },
103
+ },
104
+ },
105
+ mainCtx,
106
+ );
107
+ expect(parsed?.fields).toEqual({
108
+ email: "The Email field is required.",
109
+ });
110
+ });
111
+ });
112
+
113
+ describe("parseNodeFormErrors", () => {
114
+ it("maps express-validator array", () => {
115
+ const parsed = parseNodeFormErrors(
116
+ {
117
+ body: {
118
+ errors: [{ path: "email", msg: "Invalid email" }],
119
+ },
120
+ },
121
+ mainCtx,
122
+ );
123
+ expect(parsed?.fields).toEqual({ email: "Invalid email" });
124
+ });
125
+
126
+ it("maps Joi details", () => {
127
+ const parsed = parseNodeFormErrors(
128
+ {
129
+ body: {
130
+ details: [{ message: "Required", path: ["email"] }],
131
+ },
132
+ },
133
+ mainCtx,
134
+ );
135
+ expect(parsed?.fields).toEqual({ email: "Required" });
136
+ });
137
+ });
138
+