@strapi/plugin-users-permissions 4.20.5 → 5.0.0-alpha.1

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 (112) hide show
  1. package/admin/src/components/FormModal/index.jsx +1 -2
  2. package/admin/src/components/Permissions/reducer.js +1 -1
  3. package/admin/src/components/UsersPermissions/reducer.js +1 -1
  4. package/admin/src/index.js +15 -32
  5. package/admin/src/pages/AdvancedSettings/index.jsx +72 -112
  6. package/admin/src/pages/AdvancedSettings/utils/layout.js +20 -35
  7. package/admin/src/pages/AdvancedSettings/utils/schema.js +5 -2
  8. package/admin/src/pages/EmailTemplates/components/EmailForm.jsx +47 -74
  9. package/admin/src/pages/EmailTemplates/components/EmailTable.jsx +4 -5
  10. package/admin/src/pages/EmailTemplates/index.jsx +25 -55
  11. package/admin/src/pages/EmailTemplates/utils/schema.js +18 -6
  12. package/admin/src/pages/Providers/index.jsx +91 -108
  13. package/admin/src/pages/Providers/utils/forms.js +11 -11
  14. package/admin/src/pages/Roles/constants.js +3 -3
  15. package/admin/src/pages/Roles/hooks/usePlugins.js +4 -4
  16. package/admin/src/pages/Roles/index.jsx +9 -18
  17. package/admin/src/pages/Roles/pages/CreatePage.jsx +20 -28
  18. package/admin/src/pages/Roles/pages/EditPage.jsx +25 -37
  19. package/admin/src/pages/Roles/pages/ListPage/components/TableBody.jsx +23 -28
  20. package/admin/src/pages/Roles/pages/ListPage/index.jsx +73 -42
  21. package/admin/src/translations/en.json +1 -1
  22. package/admin/src/utils/prefixPluginTranslations.js +13 -0
  23. package/dist/_chunks/EditViewPage-kgrZ8rEg-6k5dfk_x.js +84412 -0
  24. package/dist/_chunks/EditViewPage-kgrZ8rEg-6k5dfk_x.js.map +1 -0
  25. package/dist/_chunks/EditViewPage-kgrZ8rEg-GlayP0Uq.mjs +84382 -0
  26. package/dist/_chunks/EditViewPage-kgrZ8rEg-GlayP0Uq.mjs.map +1 -0
  27. package/dist/_chunks/Helmet-d9JljxUo.js +1010 -0
  28. package/dist/_chunks/Helmet-d9JljxUo.js.map +1 -0
  29. package/dist/_chunks/Helmet-kyJ1Zklj.mjs +1008 -0
  30. package/dist/_chunks/Helmet-kyJ1Zklj.mjs.map +1 -0
  31. package/dist/_chunks/ListViewPage-BNB0ptO7-TUQO_9Hj.js +1617 -0
  32. package/dist/_chunks/ListViewPage-BNB0ptO7-TUQO_9Hj.js.map +1 -0
  33. package/dist/_chunks/ListViewPage-BNB0ptO7-t1ra9JlI.mjs +1594 -0
  34. package/dist/_chunks/ListViewPage-BNB0ptO7-t1ra9JlI.mjs.map +1 -0
  35. package/dist/_chunks/ReviewWorkflowsColumn-56Z6l-FH-3Dq1lGu9.js +33 -0
  36. package/dist/_chunks/ReviewWorkflowsColumn-56Z6l-FH-3Dq1lGu9.js.map +1 -0
  37. package/dist/_chunks/ReviewWorkflowsColumn-56Z6l-FH-mpkuW-HV.mjs +33 -0
  38. package/dist/_chunks/ReviewWorkflowsColumn-56Z6l-FH-mpkuW-HV.mjs.map +1 -0
  39. package/dist/_chunks/constants-evLWZCaJ-0QLv9QPI.mjs +190 -0
  40. package/dist/_chunks/constants-evLWZCaJ-0QLv9QPI.mjs.map +1 -0
  41. package/dist/_chunks/constants-evLWZCaJ-dGs71EWl.js +209 -0
  42. package/dist/_chunks/constants-evLWZCaJ-dGs71EWl.js.map +1 -0
  43. package/dist/_chunks/{en-m608rMZx.js → en-TaNIVnDO.js} +2 -2
  44. package/dist/_chunks/en-TaNIVnDO.js.map +1 -0
  45. package/dist/_chunks/{en-CE3wEy_c.mjs → en-jvJ-d-Qq.mjs} +2 -2
  46. package/dist/_chunks/en-jvJ-d-Qq.mjs.map +1 -0
  47. package/dist/_chunks/{index-XqdaO5WZ.js → index-6E51D69B.js} +149 -149
  48. package/dist/_chunks/index-6E51D69B.js.map +1 -0
  49. package/dist/_chunks/index-BGIcvvEB.mjs +260 -0
  50. package/dist/_chunks/index-BGIcvvEB.mjs.map +1 -0
  51. package/dist/_chunks/{index-6Kdo3KXv.js → index-Bg2Rf_5y.js} +112 -154
  52. package/dist/_chunks/index-Bg2Rf_5y.js.map +1 -0
  53. package/dist/_chunks/index-LpFmy25n.js +279 -0
  54. package/dist/_chunks/index-LpFmy25n.js.map +1 -0
  55. package/dist/_chunks/{index-a9oKDd3C.mjs → index-R05CeNXG.mjs} +106 -148
  56. package/dist/_chunks/index-R05CeNXG.mjs.map +1 -0
  57. package/dist/_chunks/index-YFPS5vYF-ZGkR3L1g.js +16558 -0
  58. package/dist/_chunks/index-YFPS5vYF-ZGkR3L1g.js.map +1 -0
  59. package/dist/_chunks/index-YFPS5vYF-cugkJcLS.mjs +16533 -0
  60. package/dist/_chunks/index-YFPS5vYF-cugkJcLS.mjs.map +1 -0
  61. package/dist/_chunks/{index-ethhTEkj.mjs → index-aEKi1Qb9.mjs} +39 -36
  62. package/dist/_chunks/index-aEKi1Qb9.mjs.map +1 -0
  63. package/dist/_chunks/{index-rryiT0-Z.mjs → index-hG66XSuA.mjs} +131 -130
  64. package/dist/_chunks/index-hG66XSuA.mjs.map +1 -0
  65. package/dist/_chunks/{index-iNtwnT3f.mjs → index-xt3l4qU9.mjs} +35 -35
  66. package/dist/_chunks/index-xt3l4qU9.mjs.map +1 -0
  67. package/dist/_chunks/{index-O9AAUvyy.js → index-yKMi8hKt.js} +36 -36
  68. package/dist/_chunks/index-yKMi8hKt.js.map +1 -0
  69. package/dist/_chunks/{index-1uupZmu0.js → index-ylhaoJtw.js} +43 -40
  70. package/dist/_chunks/index-ylhaoJtw.js.map +1 -0
  71. package/dist/_chunks/useSyncRbac-83vFRiaG-YY4KQcAU.js +57 -0
  72. package/dist/_chunks/useSyncRbac-83vFRiaG-YY4KQcAU.js.map +1 -0
  73. package/dist/_chunks/useSyncRbac-83vFRiaG-ov11t-T1.mjs +39 -0
  74. package/dist/_chunks/useSyncRbac-83vFRiaG-ov11t-T1.mjs.map +1 -0
  75. package/dist/admin/index.js +1 -2
  76. package/dist/admin/index.js.map +1 -1
  77. package/dist/admin/index.mjs +1 -2
  78. package/dist/admin/index.mjs.map +1 -1
  79. package/dist/style.css +84 -0
  80. package/package.json +13 -13
  81. package/server/bootstrap/grant-config.js +9 -0
  82. package/server/bootstrap/index.js +2 -39
  83. package/server/content-types/user/index.js +0 -1
  84. package/server/controllers/auth.js +24 -53
  85. package/server/controllers/content-manager-user.js +24 -28
  86. package/server/controllers/role.js +1 -1
  87. package/server/controllers/user.js +5 -5
  88. package/server/middlewares/rateLimit.js +1 -1
  89. package/server/register.js +1 -1
  90. package/server/services/jwt.js +3 -3
  91. package/server/services/permission.js +3 -7
  92. package/server/services/providers-registry.js +15 -0
  93. package/server/services/providers.js +10 -5
  94. package/server/services/role.js +15 -13
  95. package/server/services/user.js +28 -14
  96. package/server/services/users-permissions.js +12 -10
  97. package/server/utils/sanitize/sanitizers.js +2 -2
  98. package/admin/src/pages/Roles/pages/ListPage/utils/api.js +0 -30
  99. package/dist/_chunks/en-CE3wEy_c.mjs.map +0 -1
  100. package/dist/_chunks/en-m608rMZx.js.map +0 -1
  101. package/dist/_chunks/index-1uupZmu0.js.map +0 -1
  102. package/dist/_chunks/index-6Kdo3KXv.js.map +0 -1
  103. package/dist/_chunks/index-O9AAUvyy.js.map +0 -1
  104. package/dist/_chunks/index-Un-J-cxQ.js +0 -320
  105. package/dist/_chunks/index-Un-J-cxQ.js.map +0 -1
  106. package/dist/_chunks/index-X0yw_GgN.mjs +0 -301
  107. package/dist/_chunks/index-X0yw_GgN.mjs.map +0 -1
  108. package/dist/_chunks/index-XqdaO5WZ.js.map +0 -1
  109. package/dist/_chunks/index-a9oKDd3C.mjs.map +0 -1
  110. package/dist/_chunks/index-ethhTEkj.mjs.map +0 -1
  111. package/dist/_chunks/index-iNtwnT3f.mjs.map +0 -1
  112. package/dist/_chunks/index-rryiT0-Z.mjs.map +0 -1
@@ -0,0 +1,1617 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const React = require("react");
5
+ const designSystem = require("@strapi/design-system");
6
+ const Icons = require("@strapi/icons");
7
+ const isEqual = require("lodash/isEqual");
8
+ const indexYFPS5vYF = require("./index-YFPS5vYF-ZGkR3L1g.js");
9
+ const Helmet = require("./Helmet-d9JljxUo.js");
10
+ const reactIntl = require("react-intl");
11
+ const reactRouterDom = require("react-router-dom");
12
+ const styled = require("styled-components");
13
+ const useSyncRbac83vFRiaG = require("./useSyncRbac-83vFRiaG-YY4KQcAU.js");
14
+ const helperPlugin = require("@strapi/helper-plugin");
15
+ const isEmpty = require("lodash/isEmpty");
16
+ const toString = require("lodash/toString");
17
+ const v2 = require("@strapi/design-system/v2");
18
+ const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
19
+ function _interopNamespace(e) {
20
+ if (e && e.__esModule)
21
+ return e;
22
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
23
+ if (e) {
24
+ for (const k in e) {
25
+ if (k !== "default") {
26
+ const d = Object.getOwnPropertyDescriptor(e, k);
27
+ Object.defineProperty(n, k, d.get ? d : {
28
+ enumerable: true,
29
+ get: () => e[k]
30
+ });
31
+ }
32
+ }
33
+ }
34
+ n.default = e;
35
+ return Object.freeze(n);
36
+ }
37
+ const React__namespace = /* @__PURE__ */ _interopNamespace(React);
38
+ const isEqual__default = /* @__PURE__ */ _interopDefault(isEqual);
39
+ const styled__default = /* @__PURE__ */ _interopDefault(styled);
40
+ const isEmpty__default = /* @__PURE__ */ _interopDefault(isEmpty);
41
+ const toString__default = /* @__PURE__ */ _interopDefault(toString);
42
+ function parseISO(argument, options) {
43
+ var _options$additionalDi;
44
+ indexYFPS5vYF.requiredArgs(1, arguments);
45
+ var additionalDigits = indexYFPS5vYF.toInteger((_options$additionalDi = options === null || options === void 0 ? void 0 : options.additionalDigits) !== null && _options$additionalDi !== void 0 ? _options$additionalDi : 2);
46
+ if (additionalDigits !== 2 && additionalDigits !== 1 && additionalDigits !== 0) {
47
+ throw new RangeError("additionalDigits must be 0, 1 or 2");
48
+ }
49
+ if (!(typeof argument === "string" || Object.prototype.toString.call(argument) === "[object String]")) {
50
+ return /* @__PURE__ */ new Date(NaN);
51
+ }
52
+ var dateStrings = splitDateString(argument);
53
+ var date;
54
+ if (dateStrings.date) {
55
+ var parseYearResult = parseYear(dateStrings.date, additionalDigits);
56
+ date = parseDate(parseYearResult.restDateString, parseYearResult.year);
57
+ }
58
+ if (!date || isNaN(date.getTime())) {
59
+ return /* @__PURE__ */ new Date(NaN);
60
+ }
61
+ var timestamp = date.getTime();
62
+ var time = 0;
63
+ var offset;
64
+ if (dateStrings.time) {
65
+ time = parseTime(dateStrings.time);
66
+ if (isNaN(time)) {
67
+ return /* @__PURE__ */ new Date(NaN);
68
+ }
69
+ }
70
+ if (dateStrings.timezone) {
71
+ offset = parseTimezone(dateStrings.timezone);
72
+ if (isNaN(offset)) {
73
+ return /* @__PURE__ */ new Date(NaN);
74
+ }
75
+ } else {
76
+ var dirtyDate = new Date(timestamp + time);
77
+ var result = /* @__PURE__ */ new Date(0);
78
+ result.setFullYear(dirtyDate.getUTCFullYear(), dirtyDate.getUTCMonth(), dirtyDate.getUTCDate());
79
+ result.setHours(dirtyDate.getUTCHours(), dirtyDate.getUTCMinutes(), dirtyDate.getUTCSeconds(), dirtyDate.getUTCMilliseconds());
80
+ return result;
81
+ }
82
+ return new Date(timestamp + time + offset);
83
+ }
84
+ var patterns = {
85
+ dateTimeDelimiter: /[T ]/,
86
+ timeZoneDelimiter: /[Z ]/i,
87
+ timezone: /([Z+-].*)$/
88
+ };
89
+ var dateRegex = /^-?(?:(\d{3})|(\d{2})(?:-?(\d{2}))?|W(\d{2})(?:-?(\d{1}))?|)$/;
90
+ var timeRegex = /^(\d{2}(?:[.,]\d*)?)(?::?(\d{2}(?:[.,]\d*)?))?(?::?(\d{2}(?:[.,]\d*)?))?$/;
91
+ var timezoneRegex = /^([+-])(\d{2})(?::?(\d{2}))?$/;
92
+ function splitDateString(dateString) {
93
+ var dateStrings = {};
94
+ var array = dateString.split(patterns.dateTimeDelimiter);
95
+ var timeString;
96
+ if (array.length > 2) {
97
+ return dateStrings;
98
+ }
99
+ if (/:/.test(array[0])) {
100
+ timeString = array[0];
101
+ } else {
102
+ dateStrings.date = array[0];
103
+ timeString = array[1];
104
+ if (patterns.timeZoneDelimiter.test(dateStrings.date)) {
105
+ dateStrings.date = dateString.split(patterns.timeZoneDelimiter)[0];
106
+ timeString = dateString.substr(dateStrings.date.length, dateString.length);
107
+ }
108
+ }
109
+ if (timeString) {
110
+ var token = patterns.timezone.exec(timeString);
111
+ if (token) {
112
+ dateStrings.time = timeString.replace(token[1], "");
113
+ dateStrings.timezone = token[1];
114
+ } else {
115
+ dateStrings.time = timeString;
116
+ }
117
+ }
118
+ return dateStrings;
119
+ }
120
+ function parseYear(dateString, additionalDigits) {
121
+ var regex = new RegExp("^(?:(\\d{4}|[+-]\\d{" + (4 + additionalDigits) + "})|(\\d{2}|[+-]\\d{" + (2 + additionalDigits) + "})$)");
122
+ var captures = dateString.match(regex);
123
+ if (!captures)
124
+ return {
125
+ year: NaN,
126
+ restDateString: ""
127
+ };
128
+ var year = captures[1] ? parseInt(captures[1]) : null;
129
+ var century = captures[2] ? parseInt(captures[2]) : null;
130
+ return {
131
+ year: century === null ? year : century * 100,
132
+ restDateString: dateString.slice((captures[1] || captures[2]).length)
133
+ };
134
+ }
135
+ function parseDate(dateString, year) {
136
+ if (year === null)
137
+ return /* @__PURE__ */ new Date(NaN);
138
+ var captures = dateString.match(dateRegex);
139
+ if (!captures)
140
+ return /* @__PURE__ */ new Date(NaN);
141
+ var isWeekDate = !!captures[4];
142
+ var dayOfYear = parseDateUnit(captures[1]);
143
+ var month = parseDateUnit(captures[2]) - 1;
144
+ var day = parseDateUnit(captures[3]);
145
+ var week = parseDateUnit(captures[4]);
146
+ var dayOfWeek = parseDateUnit(captures[5]) - 1;
147
+ if (isWeekDate) {
148
+ if (!validateWeekDate(year, week, dayOfWeek)) {
149
+ return /* @__PURE__ */ new Date(NaN);
150
+ }
151
+ return dayOfISOWeekYear(year, week, dayOfWeek);
152
+ } else {
153
+ var date = /* @__PURE__ */ new Date(0);
154
+ if (!validateDate(year, month, day) || !validateDayOfYearDate(year, dayOfYear)) {
155
+ return /* @__PURE__ */ new Date(NaN);
156
+ }
157
+ date.setUTCFullYear(year, month, Math.max(dayOfYear, day));
158
+ return date;
159
+ }
160
+ }
161
+ function parseDateUnit(value) {
162
+ return value ? parseInt(value) : 1;
163
+ }
164
+ function parseTime(timeString) {
165
+ var captures = timeString.match(timeRegex);
166
+ if (!captures)
167
+ return NaN;
168
+ var hours = parseTimeUnit(captures[1]);
169
+ var minutes = parseTimeUnit(captures[2]);
170
+ var seconds = parseTimeUnit(captures[3]);
171
+ if (!validateTime(hours, minutes, seconds)) {
172
+ return NaN;
173
+ }
174
+ return hours * indexYFPS5vYF.millisecondsInHour + minutes * indexYFPS5vYF.millisecondsInMinute + seconds * 1e3;
175
+ }
176
+ function parseTimeUnit(value) {
177
+ return value && parseFloat(value.replace(",", ".")) || 0;
178
+ }
179
+ function parseTimezone(timezoneString) {
180
+ if (timezoneString === "Z")
181
+ return 0;
182
+ var captures = timezoneString.match(timezoneRegex);
183
+ if (!captures)
184
+ return 0;
185
+ var sign = captures[1] === "+" ? -1 : 1;
186
+ var hours = parseInt(captures[2]);
187
+ var minutes = captures[3] && parseInt(captures[3]) || 0;
188
+ if (!validateTimezone(hours, minutes)) {
189
+ return NaN;
190
+ }
191
+ return sign * (hours * indexYFPS5vYF.millisecondsInHour + minutes * indexYFPS5vYF.millisecondsInMinute);
192
+ }
193
+ function dayOfISOWeekYear(isoWeekYear, week, day) {
194
+ var date = /* @__PURE__ */ new Date(0);
195
+ date.setUTCFullYear(isoWeekYear, 0, 4);
196
+ var fourthOfJanuaryDay = date.getUTCDay() || 7;
197
+ var diff = (week - 1) * 7 + day + 1 - fourthOfJanuaryDay;
198
+ date.setUTCDate(date.getUTCDate() + diff);
199
+ return date;
200
+ }
201
+ var daysInMonths = [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
202
+ function isLeapYearIndex(year) {
203
+ return year % 400 === 0 || year % 4 === 0 && year % 100 !== 0;
204
+ }
205
+ function validateDate(year, month, date) {
206
+ return month >= 0 && month <= 11 && date >= 1 && date <= (daysInMonths[month] || (isLeapYearIndex(year) ? 29 : 28));
207
+ }
208
+ function validateDayOfYearDate(year, dayOfYear) {
209
+ return dayOfYear >= 1 && dayOfYear <= (isLeapYearIndex(year) ? 366 : 365);
210
+ }
211
+ function validateWeekDate(_year, week, day) {
212
+ return week >= 1 && week <= 53 && day >= 0 && day <= 6;
213
+ }
214
+ function validateTime(hours, minutes, seconds) {
215
+ if (hours === 24) {
216
+ return minutes === 0 && seconds === 0;
217
+ }
218
+ return seconds >= 0 && seconds < 60 && minutes >= 0 && minutes < 60 && hours >= 0 && hours < 25;
219
+ }
220
+ function validateTimezone(_hours, minutes) {
221
+ return minutes >= 0 && minutes <= 59;
222
+ }
223
+ const BASE_FILTERS = [
224
+ {
225
+ label: { id: "components.FilterOptions.FILTER_TYPES.$eq", defaultMessage: "is" },
226
+ value: "$eq"
227
+ },
228
+ {
229
+ label: { id: "components.FilterOptions.FILTER_TYPES.$ne", defaultMessage: "is not" },
230
+ value: "$ne"
231
+ },
232
+ {
233
+ label: {
234
+ id: "components.FilterOptions.FILTER_TYPES.$null",
235
+ defaultMessage: "is null"
236
+ },
237
+ value: "$null"
238
+ },
239
+ {
240
+ label: {
241
+ id: "components.FilterOptions.FILTER_TYPES.$notNull",
242
+ defaultMessage: "is not null"
243
+ },
244
+ value: "$notNull"
245
+ }
246
+ ];
247
+ const NUMERIC_FILTERS = [
248
+ {
249
+ label: {
250
+ id: "components.FilterOptions.FILTER_TYPES.$gt",
251
+ defaultMessage: "is greater than"
252
+ },
253
+ value: "$gt"
254
+ },
255
+ {
256
+ label: {
257
+ id: "components.FilterOptions.FILTER_TYPES.$gte",
258
+ defaultMessage: "is greater than or equal to"
259
+ },
260
+ value: "$gte"
261
+ },
262
+ {
263
+ label: {
264
+ id: "components.FilterOptions.FILTER_TYPES.$lt",
265
+ defaultMessage: "is less than"
266
+ },
267
+ value: "$lt"
268
+ },
269
+ {
270
+ label: {
271
+ id: "components.FilterOptions.FILTER_TYPES.$lte",
272
+ defaultMessage: "is less than or equal to"
273
+ },
274
+ value: "$lte"
275
+ }
276
+ ];
277
+ const IS_SENSITIVE_FILTERS = [
278
+ {
279
+ label: {
280
+ id: "components.FilterOptions.FILTER_TYPES.$eqi",
281
+ defaultMessage: "is (case insensitive)"
282
+ },
283
+ value: "$eqi"
284
+ },
285
+ {
286
+ label: {
287
+ id: "components.FilterOptions.FILTER_TYPES.$nei",
288
+ defaultMessage: "is not (case insensitive)"
289
+ },
290
+ value: "$nei"
291
+ }
292
+ ];
293
+ const CONTAINS_FILTERS = [
294
+ {
295
+ label: {
296
+ id: "components.FilterOptions.FILTER_TYPES.$contains",
297
+ defaultMessage: "contains"
298
+ },
299
+ value: "$contains"
300
+ },
301
+ {
302
+ label: {
303
+ id: "components.FilterOptions.FILTER_TYPES.$containsi",
304
+ defaultMessage: "contains (case insensitive)"
305
+ },
306
+ value: "$containsi"
307
+ },
308
+ {
309
+ label: {
310
+ id: "components.FilterOptions.FILTER_TYPES.$notContains",
311
+ defaultMessage: "not contains"
312
+ },
313
+ value: "$notContains"
314
+ },
315
+ {
316
+ label: {
317
+ id: "components.FilterOptions.FILTER_TYPES.$notContainsi",
318
+ defaultMessage: "not contains (case insensitive)"
319
+ },
320
+ value: "$notContainsi"
321
+ }
322
+ ];
323
+ const STRING_PARSE_FILTERS = [
324
+ {
325
+ label: {
326
+ id: "components.FilterOptions.FILTER_TYPES.$startsWith",
327
+ defaultMessage: "starts with"
328
+ },
329
+ value: "$startsWith"
330
+ },
331
+ {
332
+ label: {
333
+ id: "components.FilterOptions.FILTER_TYPES.$startsWithi",
334
+ defaultMessage: "starts with (case insensitive)"
335
+ },
336
+ value: "$startsWithi"
337
+ },
338
+ {
339
+ label: {
340
+ id: "components.FilterOptions.FILTER_TYPES.$endsWith",
341
+ defaultMessage: "ends with"
342
+ },
343
+ value: "$endsWith"
344
+ },
345
+ {
346
+ label: {
347
+ id: "components.FilterOptions.FILTER_TYPES.$endsWithi",
348
+ defaultMessage: "ends with (case insensitive)"
349
+ },
350
+ value: "$endsWithi"
351
+ }
352
+ ];
353
+ const [FiltersProvider, useFilters] = indexYFPS5vYF.createContext("Filters");
354
+ const Root = ({
355
+ children,
356
+ disabled = false,
357
+ onChange,
358
+ onOpenChange,
359
+ open: openProp,
360
+ defaultOpen,
361
+ options = []
362
+ }) => {
363
+ const [triggerNode, setTriggerNode] = React__namespace.useState(null);
364
+ const [open = false, setOpen] = indexYFPS5vYF.useControllableState({
365
+ prop: openProp,
366
+ defaultProp: defaultOpen,
367
+ onChange: onOpenChange
368
+ });
369
+ const handleChange = (data) => {
370
+ if (onChange) {
371
+ onChange(data);
372
+ }
373
+ };
374
+ return /* @__PURE__ */ jsxRuntime.jsx(
375
+ FiltersProvider,
376
+ {
377
+ disabled,
378
+ onChange: handleChange,
379
+ open,
380
+ options,
381
+ setOpen,
382
+ setTriggerNode,
383
+ triggerNode,
384
+ children
385
+ }
386
+ );
387
+ };
388
+ const Trigger = React__namespace.forwardRef(
389
+ ({ label }, forwardedRef) => {
390
+ const { formatMessage } = reactIntl.useIntl();
391
+ const { setTriggerNode, setOpen } = useFilters("Trigger", ({ setTriggerNode: setTriggerNode2, setOpen: setOpen2 }) => ({
392
+ setTriggerNode: setTriggerNode2,
393
+ setOpen: setOpen2
394
+ }));
395
+ const disabled = useFilters("Trigger", ({ disabled: disabled2 }) => disabled2);
396
+ const open = useFilters("Trigger", ({ open: open2 }) => open2);
397
+ const composedRefs = designSystem.useComposedRefs(forwardedRef, setTriggerNode);
398
+ const handleClick = () => setOpen(!open);
399
+ return /* @__PURE__ */ jsxRuntime.jsx(
400
+ designSystem.Button,
401
+ {
402
+ variant: "tertiary",
403
+ ref: composedRefs,
404
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Filter, {}),
405
+ onClick: handleClick,
406
+ size: "S",
407
+ disabled,
408
+ children: label || formatMessage({ id: "app.utils.filters", defaultMessage: "Filters" })
409
+ }
410
+ );
411
+ }
412
+ );
413
+ const PopoverImpl = () => {
414
+ const [{ query }, setQuery] = indexYFPS5vYF.useQueryParams();
415
+ const { formatMessage } = reactIntl.useIntl();
416
+ const open = useFilters("Popover", ({ open: open2 }) => open2);
417
+ const options = useFilters("Popover", ({ options: options2 }) => options2);
418
+ const triggerNode = useFilters("Popover", ({ triggerNode: triggerNode2 }) => triggerNode2);
419
+ const setOpen = useFilters("Popover", ({ setOpen: setOpen2 }) => setOpen2);
420
+ const onChange = useFilters("Popover", ({ onChange: onChange2 }) => onChange2);
421
+ if (!open || options.length === 0 || !triggerNode) {
422
+ return null;
423
+ }
424
+ const handleSubmit = (data) => {
425
+ if (!data.value) {
426
+ return;
427
+ }
428
+ if (onChange) {
429
+ onChange(data);
430
+ }
431
+ const filterType = options.find((filter) => filter.name === data.name).type;
432
+ const operatorValuePairing = {
433
+ [data.filter]: data.value
434
+ };
435
+ const newFilterQuery = {
436
+ ...query.filters,
437
+ $and: [
438
+ ...query.filters?.$and ?? [],
439
+ {
440
+ [data.name]: filterType === "relation" ? {
441
+ id: operatorValuePairing
442
+ } : operatorValuePairing
443
+ }
444
+ ]
445
+ };
446
+ setQuery({ filters: newFilterQuery, page: 1 });
447
+ setOpen(false);
448
+ };
449
+ return /* @__PURE__ */ jsxRuntime.jsx(
450
+ designSystem.PopoverPrimitives.Content,
451
+ {
452
+ source: { current: triggerNode },
453
+ onDismiss: () => setOpen(false),
454
+ padding: 3,
455
+ spacing: 4,
456
+ maxHeight: "unset",
457
+ children: /* @__PURE__ */ jsxRuntime.jsx(
458
+ indexYFPS5vYF.Form,
459
+ {
460
+ method: "POST",
461
+ initialValues: {
462
+ name: options[0]?.name,
463
+ filter: BASE_FILTERS[0].value
464
+ },
465
+ onSubmit: handleSubmit,
466
+ children: ({ values: formValues, modified, isSubmitting }) => {
467
+ const filter = options.find((filter2) => filter2.name === formValues.name);
468
+ const Input = filter?.input || indexYFPS5vYF.InputRenderer;
469
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, style: { minWidth: 184 }, children: [
470
+ [
471
+ {
472
+ ["aria-label"]: formatMessage({
473
+ id: "app.utils.select-field",
474
+ defaultMessage: "Select field"
475
+ }),
476
+ name: "name",
477
+ options: options.map((filter2) => ({
478
+ label: filter2.label,
479
+ value: filter2.name
480
+ })),
481
+ placholder: formatMessage({
482
+ id: "app.utils.select-field",
483
+ defaultMessage: "Select field"
484
+ }),
485
+ type: "enumeration"
486
+ },
487
+ {
488
+ ["aria-label"]: formatMessage({
489
+ id: "app.utils.select-filter",
490
+ defaultMessage: "Select filter"
491
+ }),
492
+ name: "filter",
493
+ options: filter?.operators || getFilterList(filter).map((opt) => ({
494
+ label: formatMessage(opt.label),
495
+ value: opt.value
496
+ })),
497
+ placeholder: formatMessage({
498
+ id: "app.utils.select-filter",
499
+ defaultMessage: "Select filter"
500
+ }),
501
+ type: "enumeration"
502
+ }
503
+ ].map((field) => /* @__PURE__ */ jsxRuntime.jsx(indexYFPS5vYF.InputRenderer, { ...field }, field.name)),
504
+ filter && formValues.filter && formValues.filter !== "$null" && formValues.filter !== "$notNull" ? /* @__PURE__ */ jsxRuntime.jsx(
505
+ Input,
506
+ {
507
+ ...filter,
508
+ label: null,
509
+ "aria-label": filter.label,
510
+ name: "value",
511
+ type: filter.mainField?.type ?? filter.type
512
+ }
513
+ ) : null,
514
+ /* @__PURE__ */ jsxRuntime.jsx(
515
+ designSystem.Button,
516
+ {
517
+ disabled: !modified || isSubmitting,
518
+ size: "L",
519
+ variant: "secondary",
520
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Plus, {}),
521
+ type: "submit",
522
+ fullWidth: true,
523
+ children: formatMessage({ id: "app.utils.add-filter", defaultMessage: "Add filter" })
524
+ }
525
+ )
526
+ ] });
527
+ }
528
+ }
529
+ )
530
+ }
531
+ );
532
+ };
533
+ const getFilterList = (filter) => {
534
+ if (!filter) {
535
+ return [];
536
+ }
537
+ const type = filter.mainField?.type ? filter.mainField.type : filter.type;
538
+ switch (type) {
539
+ case "email":
540
+ case "text":
541
+ case "enumeration":
542
+ case "string": {
543
+ return [
544
+ ...BASE_FILTERS,
545
+ ...IS_SENSITIVE_FILTERS,
546
+ ...CONTAINS_FILTERS,
547
+ ...STRING_PARSE_FILTERS
548
+ ];
549
+ }
550
+ case "float":
551
+ case "integer":
552
+ case "biginteger":
553
+ case "decimal": {
554
+ return [...BASE_FILTERS, ...NUMERIC_FILTERS];
555
+ }
556
+ case "time":
557
+ case "date": {
558
+ return [...BASE_FILTERS, ...NUMERIC_FILTERS, ...CONTAINS_FILTERS];
559
+ }
560
+ case "datetime": {
561
+ return [...BASE_FILTERS, ...NUMERIC_FILTERS];
562
+ }
563
+ default:
564
+ return [...BASE_FILTERS, ...IS_SENSITIVE_FILTERS];
565
+ }
566
+ };
567
+ const List = () => {
568
+ const [{ query }, setQuery] = indexYFPS5vYF.useQueryParams();
569
+ const options = useFilters("List", ({ options: options2 }) => options2);
570
+ const handleClick = (data) => {
571
+ const nextFilters = (query?.filters?.$and ?? []).filter((filter) => {
572
+ const [attributeName] = Object.keys(filter);
573
+ if (attributeName !== data.name) {
574
+ return true;
575
+ }
576
+ const { type, mainField } = options.find(({ name }) => name === attributeName);
577
+ if (type === "relation") {
578
+ const filterObj = filter[attributeName][mainField?.name ?? "id"];
579
+ if (typeof filterObj === "object") {
580
+ const [operator] = Object.keys(filterObj);
581
+ const value = filterObj[operator];
582
+ return !(operator === data.filter && value === data.value);
583
+ }
584
+ return true;
585
+ } else {
586
+ const filterObj = filter[attributeName];
587
+ const [operator] = Object.keys(filterObj);
588
+ const value = filterObj[operator];
589
+ return !(operator === data.filter && value === data.value);
590
+ }
591
+ });
592
+ setQuery({ filters: { $and: nextFilters }, page: 1 });
593
+ };
594
+ if (!query?.filters?.$and?.length) {
595
+ return null;
596
+ }
597
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: query?.filters?.$and?.map((queryFilter) => {
598
+ const [attributeName] = Object.keys(queryFilter);
599
+ const filter = options.find(({ name }) => name === attributeName);
600
+ const filterObj = queryFilter[attributeName];
601
+ if (!filter || typeof filterObj !== "object" || filterObj === null) {
602
+ return null;
603
+ }
604
+ if (filter.type === "relation") {
605
+ const modelFilter = filterObj[filter.mainField?.name ?? "id"];
606
+ if (typeof modelFilter === "object") {
607
+ const [operator] = Object.keys(modelFilter);
608
+ const value = modelFilter[operator];
609
+ return /* @__PURE__ */ jsxRuntime.jsx(
610
+ AttributeTag,
611
+ {
612
+ ...filter,
613
+ onClick: handleClick,
614
+ operator,
615
+ value
616
+ },
617
+ `${attributeName}-${operator}-${value}`
618
+ );
619
+ }
620
+ return null;
621
+ } else {
622
+ const [operator] = Object.keys(filterObj);
623
+ const value = filterObj[operator];
624
+ if (typeof value === "object") {
625
+ return null;
626
+ }
627
+ return /* @__PURE__ */ jsxRuntime.jsx(
628
+ AttributeTag,
629
+ {
630
+ ...filter,
631
+ onClick: handleClick,
632
+ operator,
633
+ value
634
+ },
635
+ `${attributeName}-${operator}-${value}`
636
+ );
637
+ }
638
+ }) });
639
+ };
640
+ const AttributeTag = ({
641
+ input,
642
+ label,
643
+ mainField,
644
+ name,
645
+ onClick,
646
+ operator,
647
+ options,
648
+ value,
649
+ ...filter
650
+ }) => {
651
+ const { formatMessage, formatDate, formatTime, formatNumber } = reactIntl.useIntl();
652
+ const handleClick = () => {
653
+ onClick({ name, value, filter: operator });
654
+ };
655
+ const type = mainField?.type ? mainField.type : filter.type;
656
+ let formattedValue = value;
657
+ switch (type) {
658
+ case "date":
659
+ formattedValue = formatDate(value, { dateStyle: "full" });
660
+ break;
661
+ case "datetime":
662
+ formattedValue = formatDate(value, { dateStyle: "full", timeStyle: "short" });
663
+ break;
664
+ case "time":
665
+ const [hour, minute] = value.split(":");
666
+ const date = /* @__PURE__ */ new Date();
667
+ date.setHours(Number(hour));
668
+ date.setMinutes(Number(minute));
669
+ formattedValue = formatTime(date, {
670
+ hour: "numeric",
671
+ minute: "numeric"
672
+ });
673
+ break;
674
+ case "float":
675
+ case "integer":
676
+ case "biginteger":
677
+ case "decimal":
678
+ formattedValue = formatNumber(Number(value));
679
+ break;
680
+ }
681
+ if (input && options) {
682
+ const selectedOption = options.find((option) => {
683
+ return (typeof option === "string" ? option : option.value) === value;
684
+ });
685
+ formattedValue = selectedOption ? typeof selectedOption === "string" ? selectedOption : selectedOption.label ?? selectedOption.value : value;
686
+ }
687
+ const content = `${label} ${formatMessage({
688
+ id: `components.FilterOptions.FILTER_TYPES.${operator}`,
689
+ defaultMessage: operator
690
+ })} ${operator !== "$null" && operator !== "$notNull" ? formattedValue : ""}`;
691
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tag, { padding: 1, onClick: handleClick, icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}), children: content });
692
+ };
693
+ const Filters = {
694
+ List,
695
+ Popover: PopoverImpl,
696
+ Root,
697
+ Trigger
698
+ };
699
+ const usePrev = (value) => {
700
+ const ref = React.useRef();
701
+ React.useEffect(() => {
702
+ ref.current = value;
703
+ }, [value]);
704
+ return ref.current;
705
+ };
706
+ const REVIEW_WORKFLOW_FILTER_CE = [];
707
+ const NOT_ALLOWED_FILTERS = [
708
+ "json",
709
+ "component",
710
+ "media",
711
+ "richtext",
712
+ "dynamiczone",
713
+ "password",
714
+ "blocks"
715
+ ];
716
+ const DEFAULT_ALLOWED_FILTERS = ["createdAt", "updatedAt"];
717
+ const USER_FILTER_ATTRIBUTES = [...indexYFPS5vYF.CREATOR_FIELDS, "strapi_assignee"];
718
+ const FiltersImpl = ({ disabled, schema }) => {
719
+ const { attributes, uid: model, options } = schema;
720
+ const { formatMessage, locale } = reactIntl.useIntl();
721
+ const { trackUsage } = indexYFPS5vYF.useTracking();
722
+ const { allPermissions } = helperPlugin.useRBACProvider();
723
+ const [{ query }] = indexYFPS5vYF.useQueryParams();
724
+ const { schemas } = indexYFPS5vYF.useContentTypeSchema();
725
+ const canReadAdminUsers = React__namespace.useMemo(
726
+ () => helperPlugin.findMatchingPermissions(allPermissions, [
727
+ {
728
+ action: "admin::users.read",
729
+ subject: null
730
+ }
731
+ ]).length > 0,
732
+ [allPermissions]
733
+ );
734
+ const selectedUserIds = (query?.filters?.$and ?? []).reduce((acc, filter) => {
735
+ const [key, value] = Object.entries(filter)[0];
736
+ if (typeof value.id !== "object") {
737
+ return acc;
738
+ }
739
+ const id = value.id.$eq || value.id.$ne;
740
+ if (id && USER_FILTER_ATTRIBUTES.includes(key) && !acc.includes(id)) {
741
+ acc.push(id);
742
+ }
743
+ return acc;
744
+ }, []);
745
+ const { data: userData, isLoading: isLoadingAdminUsers } = indexYFPS5vYF.useAdminUsers(
746
+ { filters: { id: { $in: selectedUserIds } } },
747
+ {
748
+ // fetch the list of admin users only if the filter contains users and the
749
+ // current user has permissions to display users
750
+ skip: selectedUserIds.length === 0 || !canReadAdminUsers
751
+ }
752
+ );
753
+ const { users = [] } = userData ?? {};
754
+ const { metadata } = indexYFPS5vYF.useGetContentTypeConfigurationQuery(model, {
755
+ selectFromResult: ({ data }) => ({ metadata: data?.contentType.metadatas ?? {} })
756
+ });
757
+ const formatter = designSystem.useCollator(locale, {
758
+ sensitivity: "base"
759
+ });
760
+ const displayedAttributeFilters = React__namespace.useMemo(() => {
761
+ const [{ properties: { fields = [] } = { fields: [] } }] = helperPlugin.findMatchingPermissions(
762
+ allPermissions,
763
+ [
764
+ {
765
+ action: "plugin::content-manager.explorer.read",
766
+ subject: model
767
+ }
768
+ ]
769
+ );
770
+ const allowedFields = fields.filter((field) => {
771
+ const attribute = attributes[field] ?? {};
772
+ return attribute.type && !NOT_ALLOWED_FILTERS.includes(attribute.type);
773
+ });
774
+ return [
775
+ "id",
776
+ ...allowedFields,
777
+ ...DEFAULT_ALLOWED_FILTERS,
778
+ ...canReadAdminUsers ? indexYFPS5vYF.CREATOR_FIELDS : []
779
+ ].map((name) => {
780
+ const attribute = attributes[name];
781
+ if (NOT_ALLOWED_FILTERS.includes(attribute.type)) {
782
+ return null;
783
+ }
784
+ const { mainField: mainFieldName = "", label } = metadata[name].list;
785
+ let filter = {
786
+ name,
787
+ label: label ?? "",
788
+ mainField: indexYFPS5vYF.getMainField(attribute, mainFieldName, { schemas, components: {} }),
789
+ // @ts-expect-error – TODO: this is filtered out above in the `allowedFields` call but TS complains, is there a better way to solve this?
790
+ type: attribute.type
791
+ };
792
+ if (attribute.type === "relation" && "target" in attribute && attribute.target === "admin::user") {
793
+ filter = {
794
+ ...filter,
795
+ input: AdminUsersFilter,
796
+ options: users.map((user) => ({
797
+ label: indexYFPS5vYF.getDisplayName(user, formatMessage),
798
+ value: user.id.toString()
799
+ })),
800
+ operators: [
801
+ {
802
+ label: formatMessage({
803
+ id: "components.FilterOptions.FILTER_TYPES.$eq",
804
+ defaultMessage: "is"
805
+ }),
806
+ value: "$eq"
807
+ },
808
+ {
809
+ label: formatMessage({
810
+ id: "components.FilterOptions.FILTER_TYPES.$ne",
811
+ defaultMessage: "is not"
812
+ }),
813
+ value: "$ne"
814
+ }
815
+ ],
816
+ mainField: {
817
+ name: "id",
818
+ type: "integer"
819
+ }
820
+ };
821
+ }
822
+ return filter;
823
+ }).filter(Boolean);
824
+ }, [
825
+ allPermissions,
826
+ model,
827
+ canReadAdminUsers,
828
+ attributes,
829
+ metadata,
830
+ schemas,
831
+ users,
832
+ formatMessage
833
+ ]);
834
+ const reviewWorkflowFilter = indexYFPS5vYF.useEnterprise(
835
+ REVIEW_WORKFLOW_FILTER_CE,
836
+ async () => (await Promise.resolve().then(() => require("./constants-evLWZCaJ-dGs71EWl.js"))).REVIEW_WORKFLOW_FILTERS,
837
+ {
838
+ combine(ceFilters, eeFilters) {
839
+ return [
840
+ ...ceFilters,
841
+ ...eeFilters.filter((eeFilter) => {
842
+ if (eeFilter.name === "strapi_assignee") {
843
+ return helperPlugin.findMatchingPermissions(allPermissions, [
844
+ {
845
+ action: "admin::users.read",
846
+ subject: null
847
+ }
848
+ ]).length > 0;
849
+ }
850
+ return true;
851
+ }).map((eeFilter) => ({
852
+ ...eeFilter,
853
+ "aria-label": formatMessage(eeFilter.label),
854
+ options: (
855
+ // TODO: strapi_assignee should not be in here and rather defined
856
+ // in the ee directory.
857
+ eeFilter.name === "strapi_assignee" ? users.map((user) => ({
858
+ label: indexYFPS5vYF.getDisplayName(user, formatMessage),
859
+ value: user.id.toString()
860
+ })) : void 0
861
+ )
862
+ }))
863
+ ];
864
+ },
865
+ defaultValue: [],
866
+ // we have to wait for admin users to be fully loaded, because otherwise
867
+ // combine is called to early and does not contain the latest state of
868
+ // the users array
869
+ enabled: !!options?.reviewWorkflows && !isLoadingAdminUsers
870
+ }
871
+ /**
872
+ * this is cast because the data returns MessageDescriptor
873
+ * as `metadatas.label` _then_ we turn it to a string.
874
+ */
875
+ );
876
+ const onOpenChange = (isOpen) => {
877
+ if (isOpen) {
878
+ trackUsage("willFilterEntries");
879
+ }
880
+ };
881
+ const displayedFilters = [...displayedAttributeFilters, ...reviewWorkflowFilter].sort(
882
+ (a, b) => formatter.compare(a.label, b.label)
883
+ );
884
+ const handleFilterChange = (data) => {
885
+ const attribute = attributes[data.name];
886
+ if (attribute) {
887
+ trackUsage("didFilterEntries", {
888
+ useRelation: attribute.type === "relation"
889
+ });
890
+ }
891
+ };
892
+ return /* @__PURE__ */ jsxRuntime.jsxs(
893
+ Filters.Root,
894
+ {
895
+ disabled,
896
+ options: displayedFilters,
897
+ onOpenChange,
898
+ onChange: handleFilterChange,
899
+ children: [
900
+ /* @__PURE__ */ jsxRuntime.jsx(Filters.Trigger, {}),
901
+ /* @__PURE__ */ jsxRuntime.jsx(Filters.Popover, {}),
902
+ /* @__PURE__ */ jsxRuntime.jsx(Filters.List, {})
903
+ ]
904
+ }
905
+ );
906
+ };
907
+ const AdminUsersFilter = ({ name }) => {
908
+ const [page, setPage] = React__namespace.useState(1);
909
+ const { formatMessage } = reactIntl.useIntl();
910
+ const { data, isLoading } = indexYFPS5vYF.useAdminUsers({
911
+ page
912
+ });
913
+ const field = indexYFPS5vYF.useField(name);
914
+ const handleOpenChange = (isOpen) => {
915
+ if (!isOpen) {
916
+ setPage(1);
917
+ }
918
+ };
919
+ const users = data?.users || [];
920
+ return /* @__PURE__ */ jsxRuntime.jsx(
921
+ designSystem.Combobox,
922
+ {
923
+ value: field.value,
924
+ "aria-label": formatMessage({
925
+ id: "content-manager.components.Filters.usersSelect.label",
926
+ defaultMessage: "Search and select a user to filter"
927
+ }),
928
+ onOpenChange: handleOpenChange,
929
+ onChange: (value) => field.onChange(name, value),
930
+ loading: isLoading,
931
+ onLoadMore: () => setPage((prev) => prev + 1),
932
+ children: users.map((user) => {
933
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.ComboboxOption, { value: user.id.toString(), children: indexYFPS5vYF.getDisplayName(user, formatMessage) }, user.id);
934
+ })
935
+ }
936
+ );
937
+ };
938
+ const CellValue = ({ type, value }) => {
939
+ const { formatDate, formatTime, formatNumber } = reactIntl.useIntl();
940
+ let formattedValue = value;
941
+ if (type === "date") {
942
+ formattedValue = formatDate(parseISO(value), { dateStyle: "full" });
943
+ }
944
+ if (type === "datetime") {
945
+ formattedValue = formatDate(value, { dateStyle: "full", timeStyle: "short" });
946
+ }
947
+ if (type === "time") {
948
+ const [hour, minute, second] = value.split(":");
949
+ const date = /* @__PURE__ */ new Date();
950
+ date.setHours(hour);
951
+ date.setMinutes(minute);
952
+ date.setSeconds(second);
953
+ formattedValue = formatTime(date, {
954
+ timeStyle: "short"
955
+ });
956
+ }
957
+ if (["float", "decimal"].includes(type)) {
958
+ formattedValue = formatNumber(value, {
959
+ // Should be kept in sync with the corresponding value
960
+ // in the design-system/NumberInput: https://github.com/strapi/design-system/blob/main/packages/strapi-design-system/src/NumberInput/NumberInput.js#L53
961
+ maximumFractionDigits: 20
962
+ });
963
+ }
964
+ if (["integer", "biginteger"].includes(type)) {
965
+ formattedValue = formatNumber(value, { maximumFractionDigits: 0 });
966
+ }
967
+ return toString__default.default(formattedValue);
968
+ };
969
+ const SingleComponent = ({ content, mainField }) => {
970
+ if (!mainField) {
971
+ return null;
972
+ }
973
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { label: content[mainField.name], children: /* @__PURE__ */ jsxRuntime.jsx(SingleComponentTypography, { textColor: "neutral800", ellipsis: true, children: /* @__PURE__ */ jsxRuntime.jsx(CellValue, { type: mainField.type, value: content[mainField.name] }) }) });
974
+ };
975
+ const SingleComponentTypography = styled__default.default(designSystem.Typography)`
976
+ max-width: 250px;
977
+ `;
978
+ const RepeatableComponent = ({ content, mainField }) => {
979
+ const { formatMessage } = reactIntl.useIntl();
980
+ if (!mainField) {
981
+ return null;
982
+ }
983
+ return /* @__PURE__ */ jsxRuntime.jsxs(v2.Menu.Root, { children: [
984
+ /* @__PURE__ */ jsxRuntime.jsxs(MenuTrigger$1, { onClick: (e) => e.stopPropagation(), children: [
985
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { children: content.length }),
986
+ " ",
987
+ formatMessage(
988
+ {
989
+ id: "content-manager.containers.list.items",
990
+ defaultMessage: "{number, plural, =0 {items} one {item} other {items}}"
991
+ },
992
+ { number: content.length }
993
+ )
994
+ ] }),
995
+ /* @__PURE__ */ jsxRuntime.jsx(v2.Menu.Content, { children: content.map((item) => /* @__PURE__ */ jsxRuntime.jsx(v2.Menu.Item, { disabled: true, children: /* @__PURE__ */ jsxRuntime.jsx(RepeatableComponentTypography, { ellipsis: true, children: /* @__PURE__ */ jsxRuntime.jsx(CellValue, { type: mainField.type, value: item[mainField.name] }) }) }, item.id)) })
996
+ ] });
997
+ };
998
+ const RepeatableComponentTypography = styled__default.default(designSystem.Typography)`
999
+ max-width: 500px;
1000
+ `;
1001
+ const MenuTrigger$1 = styled__default.default(v2.Menu.Trigger)`
1002
+ svg {
1003
+ width: ${6 / 16}rem;
1004
+ height: ${4 / 16}rem;
1005
+ }
1006
+ `;
1007
+ const getFileExtension = (ext) => ext && ext[0] === "." ? ext.substring(1) : ext;
1008
+ const MediaSingle = ({ url, mime, alternativeText, name, ext, formats }) => {
1009
+ const fileURL = indexYFPS5vYF.prefixFileUrlWithBackendUrl(url);
1010
+ if (mime.includes("image")) {
1011
+ const thumbnail = formats?.thumbnail?.url;
1012
+ const mediaURL = indexYFPS5vYF.prefixFileUrlWithBackendUrl(thumbnail) || fileURL;
1013
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Avatar, { src: mediaURL, alt: alternativeText || name, preview: true });
1014
+ }
1015
+ const fileExtension = getFileExtension(ext);
1016
+ const fileName = name.length > 100 ? `${name.substring(0, 100)}...` : name;
1017
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { description: fileName, children: /* @__PURE__ */ jsxRuntime.jsx(FileWrapper, { children: fileExtension }) });
1018
+ };
1019
+ const FileWrapper = ({ children }) => {
1020
+ return /* @__PURE__ */ jsxRuntime.jsx(
1021
+ designSystem.Flex,
1022
+ {
1023
+ as: "span",
1024
+ position: "relative",
1025
+ borderRadius: "50%",
1026
+ width: "26px",
1027
+ height: "26px",
1028
+ borderColor: "neutral200",
1029
+ background: "neutral150",
1030
+ paddingLeft: "1px",
1031
+ justifyContent: "center",
1032
+ alignItems: "center",
1033
+ children: /* @__PURE__ */ jsxRuntime.jsx(FileTypography, { variant: "sigma", textColor: "neutral600", children })
1034
+ }
1035
+ );
1036
+ };
1037
+ const FileTypography = styled__default.default(designSystem.Typography)`
1038
+ font-size: 0.6rem;
1039
+ line-height: 0.6rem;
1040
+ `;
1041
+ const MediaMultiple = ({ content }) => {
1042
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.AvatarGroup, { children: content.map((file, index) => {
1043
+ const key = `${file.id}${index}`;
1044
+ if (index === 3) {
1045
+ const remainingFiles = `+${content.length - 3}`;
1046
+ return /* @__PURE__ */ jsxRuntime.jsx(FileWrapper, { children: remainingFiles }, key);
1047
+ }
1048
+ if (index > 3) {
1049
+ return null;
1050
+ }
1051
+ return /* @__PURE__ */ jsxRuntime.jsx(MediaSingle, { ...file }, key);
1052
+ }) });
1053
+ };
1054
+ const RelationSingle = ({ mainField, content }) => {
1055
+ return /* @__PURE__ */ jsxRuntime.jsx(TypographyMaxWidth$1, { textColor: "neutral800", ellipsis: true, children: indexYFPS5vYF.getRelationLabel(content, mainField) });
1056
+ };
1057
+ const TypographyMaxWidth$1 = styled__default.default(designSystem.Typography)`
1058
+ max-width: 500px;
1059
+ `;
1060
+ const RelationMultiple = ({ mainField, content, rowId, name }) => {
1061
+ const { model } = indexYFPS5vYF.useDoc();
1062
+ const { formatMessage } = reactIntl.useIntl();
1063
+ const { notifyStatus } = designSystem.useNotifyAT();
1064
+ const [isOpen, setIsOpen] = React__namespace.useState(false);
1065
+ const [targetField] = name.split(".");
1066
+ const { data, isLoading } = indexYFPS5vYF.useGetRelationsQuery(
1067
+ {
1068
+ model,
1069
+ id: rowId,
1070
+ targetField
1071
+ },
1072
+ {
1073
+ skip: !isOpen,
1074
+ refetchOnMountOrArgChange: true
1075
+ }
1076
+ );
1077
+ React__namespace.useEffect(() => {
1078
+ if (data) {
1079
+ notifyStatus(
1080
+ formatMessage({
1081
+ id: indexYFPS5vYF.getTranslation("DynamicTable.relation-loaded"),
1082
+ defaultMessage: "Relations have been loaded"
1083
+ })
1084
+ );
1085
+ }
1086
+ }, [data, formatMessage, notifyStatus]);
1087
+ return /* @__PURE__ */ jsxRuntime.jsxs(v2.Menu.Root, { onOpenChange: (isOpen2) => setIsOpen(isOpen2), children: [
1088
+ /* @__PURE__ */ jsxRuntime.jsx(MenuTrigger, { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 1, wrap: "nowrap", children: [
1089
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { children: content.count }),
1090
+ formatMessage(
1091
+ {
1092
+ id: "content-manager.containers.list.items",
1093
+ defaultMessage: "{number, plural, =0 {items} one {item} other {items}}"
1094
+ },
1095
+ { number: content.count }
1096
+ )
1097
+ ] }) }),
1098
+ /* @__PURE__ */ jsxRuntime.jsxs(v2.Menu.Content, { children: [
1099
+ isLoading && /* @__PURE__ */ jsxRuntime.jsx(v2.Menu.Item, { disabled: true, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Loader, { small: true, children: formatMessage({
1100
+ id: indexYFPS5vYF.getTranslation("ListViewTable.relation-loading"),
1101
+ defaultMessage: "Relations are loading"
1102
+ }) }) }),
1103
+ data?.results && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1104
+ data.results.map((entry) => /* @__PURE__ */ jsxRuntime.jsx(v2.Menu.Item, { disabled: true, children: /* @__PURE__ */ jsxRuntime.jsx(TypographyMaxWidth$1, { ellipsis: true, children: indexYFPS5vYF.getRelationLabel(entry, mainField) }) }, entry.documentId)),
1105
+ data?.pagination && data?.pagination.total > 10 && /* @__PURE__ */ jsxRuntime.jsx(
1106
+ v2.Menu.Item,
1107
+ {
1108
+ "aria-disabled": true,
1109
+ "aria-label": formatMessage({
1110
+ id: indexYFPS5vYF.getTranslation("ListViewTable.relation-more"),
1111
+ defaultMessage: "This relation contains more entities than displayed"
1112
+ }),
1113
+ children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: "…" })
1114
+ }
1115
+ )
1116
+ ] })
1117
+ ] })
1118
+ ] });
1119
+ };
1120
+ const MenuTrigger = styled__default.default(v2.Menu.Trigger)`
1121
+ svg {
1122
+ width: ${6 / 16}rem;
1123
+ height: ${4 / 16}rem;
1124
+ }
1125
+ `;
1126
+ const CellContent = ({ content, mainField, attribute, rowId, name }) => {
1127
+ if (!hasContent(content, mainField, attribute)) {
1128
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral800", children: "-" });
1129
+ }
1130
+ switch (attribute.type) {
1131
+ case "media":
1132
+ if (!attribute.multiple) {
1133
+ return /* @__PURE__ */ jsxRuntime.jsx(MediaSingle, { ...content });
1134
+ }
1135
+ return /* @__PURE__ */ jsxRuntime.jsx(MediaMultiple, { content });
1136
+ case "relation": {
1137
+ if (isSingleRelation(attribute.relation)) {
1138
+ return /* @__PURE__ */ jsxRuntime.jsx(RelationSingle, { mainField, content });
1139
+ }
1140
+ return /* @__PURE__ */ jsxRuntime.jsx(RelationMultiple, { rowId, mainField, content, name });
1141
+ }
1142
+ case "component":
1143
+ if (attribute.repeatable) {
1144
+ return /* @__PURE__ */ jsxRuntime.jsx(RepeatableComponent, { mainField, content });
1145
+ }
1146
+ return /* @__PURE__ */ jsxRuntime.jsx(SingleComponent, { mainField, content });
1147
+ case "string":
1148
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { description: content, children: /* @__PURE__ */ jsxRuntime.jsx(TypographyMaxWidth, { ellipsis: true, textColor: "neutral800", children: /* @__PURE__ */ jsxRuntime.jsx(CellValue, { type: attribute.type, value: content }) }) });
1149
+ default:
1150
+ return /* @__PURE__ */ jsxRuntime.jsx(TypographyMaxWidth, { ellipsis: true, textColor: "neutral800", children: /* @__PURE__ */ jsxRuntime.jsx(CellValue, { type: attribute.type, value: content }) });
1151
+ }
1152
+ };
1153
+ const TypographyMaxWidth = styled__default.default(designSystem.Typography)`
1154
+ max-width: 300px;
1155
+ `;
1156
+ const hasContent = (content, mainField, attribute) => {
1157
+ if (attribute.type === "component") {
1158
+ if (attribute.repeatable || !mainField) {
1159
+ return content?.length > 0;
1160
+ }
1161
+ const value = content?.[mainField.name];
1162
+ if (mainField.name === "id" && ![void 0, null].includes(value)) {
1163
+ return true;
1164
+ }
1165
+ return !isEmpty__default.default(value);
1166
+ }
1167
+ if (attribute.type === "relation") {
1168
+ if (isSingleRelation(attribute.relation)) {
1169
+ return !isEmpty__default.default(content);
1170
+ }
1171
+ return content?.count > 0;
1172
+ }
1173
+ if (["integer", "decimal", "float", "number"].includes(attribute.type)) {
1174
+ return typeof content === "number";
1175
+ }
1176
+ if (attribute.type === "boolean") {
1177
+ return content !== null;
1178
+ }
1179
+ return !isEmpty__default.default(content);
1180
+ };
1181
+ const isSingleRelation = (type) => ["oneToOne", "manyToOne", "oneToOneMorph"].includes(type);
1182
+ const ViewSettingsMenu = (props) => {
1183
+ const [isVisible, setIsVisible] = React__namespace.useState(false);
1184
+ const cogButtonRef = React__namespace.useRef(null);
1185
+ const permissions = indexYFPS5vYF.useTypedSelector(
1186
+ (state) => state.admin_app.permissions.contentManager?.collectionTypesConfigurations ?? []
1187
+ );
1188
+ const [{ query }] = indexYFPS5vYF.useQueryParams();
1189
+ const { formatMessage } = reactIntl.useIntl();
1190
+ const {
1191
+ allowedActions: { canViewConfiguration }
1192
+ } = helperPlugin.useRBAC({
1193
+ viewConfiguration: permissions
1194
+ });
1195
+ const handleToggle = () => {
1196
+ setIsVisible((prev) => !prev);
1197
+ };
1198
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1199
+ /* @__PURE__ */ jsxRuntime.jsx(
1200
+ designSystem.IconButton,
1201
+ {
1202
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cog, {}),
1203
+ label: formatMessage({
1204
+ id: "components.ViewSettings.tooltip",
1205
+ defaultMessage: "View Settings"
1206
+ }),
1207
+ ref: cogButtonRef,
1208
+ onClick: handleToggle
1209
+ }
1210
+ ),
1211
+ isVisible && /* @__PURE__ */ jsxRuntime.jsx(
1212
+ designSystem.Popover,
1213
+ {
1214
+ placement: "bottom-end",
1215
+ source: cogButtonRef,
1216
+ onDismiss: handleToggle,
1217
+ spacing: 4,
1218
+ padding: 3,
1219
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "stretch", direction: "column", gap: 3, children: [
1220
+ canViewConfiguration ? /* @__PURE__ */ jsxRuntime.jsx(
1221
+ v2.LinkButton,
1222
+ {
1223
+ size: "S",
1224
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Layer, {}),
1225
+ variant: "secondary",
1226
+ as: reactRouterDom.NavLink,
1227
+ to: {
1228
+ pathname: "configurations/list",
1229
+ search: query.plugins ? indexYFPS5vYF.lib.stringify({ plugins: query.plugins }, { encode: false }) : ""
1230
+ },
1231
+ children: formatMessage({
1232
+ id: "app.links.configure-view",
1233
+ defaultMessage: "Configure the view"
1234
+ })
1235
+ }
1236
+ ) : null,
1237
+ /* @__PURE__ */ jsxRuntime.jsx(FieldPicker, { ...props })
1238
+ ] })
1239
+ }
1240
+ )
1241
+ ] });
1242
+ };
1243
+ const FieldPicker = ({ headers = [], resetHeaders, setHeaders }) => {
1244
+ const { trackUsage } = indexYFPS5vYF.useTracking();
1245
+ const { formatMessage, locale } = reactIntl.useIntl();
1246
+ const { schema, model } = indexYFPS5vYF.useDoc();
1247
+ const { list } = indexYFPS5vYF.useDocumentLayout(model);
1248
+ const formatter = designSystem.useCollator(locale, {
1249
+ sensitivity: "base"
1250
+ });
1251
+ const attributes = schema?.attributes ?? {};
1252
+ const columns = Object.keys(attributes).filter((name) => indexYFPS5vYF.checkIfAttributeIsDisplayable(attributes[name])).map((name) => ({
1253
+ name,
1254
+ label: list.metadatas[name]?.label ?? ""
1255
+ })).sort((a, b) => formatter.compare(a.label, b.label));
1256
+ const handleChange = (name) => {
1257
+ trackUsage("didChangeDisplayedFields");
1258
+ const newHeaders = headers.includes(name) ? headers.filter((header) => header !== name) : [...headers, name];
1259
+ setHeaders(newHeaders);
1260
+ };
1261
+ const handleReset = () => {
1262
+ resetHeaders();
1263
+ };
1264
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { as: "fieldset", direction: "column", alignItems: "stretch", gap: 3, children: [
1265
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", children: [
1266
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "legend", variant: "pi", fontWeight: "bold", children: formatMessage({
1267
+ id: "containers.list.displayedFields",
1268
+ defaultMessage: "Displayed fields"
1269
+ }) }),
1270
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.TextButton, { onClick: handleReset, children: formatMessage({
1271
+ id: "app.components.Button.reset",
1272
+ defaultMessage: "Reset"
1273
+ }) })
1274
+ ] }),
1275
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", children: columns.map((header) => {
1276
+ const isActive = headers.includes(header.name);
1277
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1278
+ ChackboxWrapper,
1279
+ {
1280
+ wrap: "wrap",
1281
+ gap: 2,
1282
+ as: "label",
1283
+ background: isActive ? "primary100" : "transparent",
1284
+ hasRadius: true,
1285
+ padding: 2,
1286
+ children: [
1287
+ /* @__PURE__ */ jsxRuntime.jsx(
1288
+ designSystem.BaseCheckbox,
1289
+ {
1290
+ onChange: () => handleChange(header.name),
1291
+ value: isActive,
1292
+ name: header.name
1293
+ }
1294
+ ),
1295
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontSize: 1, children: header.label })
1296
+ ]
1297
+ },
1298
+ header.name
1299
+ );
1300
+ }) })
1301
+ ] });
1302
+ };
1303
+ const ChackboxWrapper = styled__default.default(designSystem.Flex)`
1304
+ :hover {
1305
+ background-color: ${(props) => props.theme.colors.primary100};
1306
+ }
1307
+ `;
1308
+ const { INJECT_COLUMN_IN_TABLE } = indexYFPS5vYF.HOOKS;
1309
+ const REVIEW_WORKFLOW_COLUMNS_CE = null;
1310
+ const REVIEW_WORKFLOW_COLUMNS_CELL_CE = {
1311
+ ReviewWorkflowsStageEE: () => null,
1312
+ ReviewWorkflowsAssigneeEE: () => null
1313
+ };
1314
+ const ListViewPage = () => {
1315
+ const { trackUsage } = indexYFPS5vYF.useTracking();
1316
+ const navigate = reactRouterDom.useNavigate();
1317
+ const { formatMessage } = reactIntl.useIntl();
1318
+ const { toggleNotification } = indexYFPS5vYF.useNotification();
1319
+ const { _unstableFormatAPIError: formatAPIError } = indexYFPS5vYF.useAPIErrorHandler(indexYFPS5vYF.getTranslation);
1320
+ const { collectionType, model, schema } = indexYFPS5vYF.useDoc();
1321
+ const { list } = indexYFPS5vYF.useDocumentLayout(model);
1322
+ const [displayedHeaders, setDisplayedHeaders] = React__namespace.useState([]);
1323
+ const listLayout = usePrev(list.layout);
1324
+ React__namespace.useEffect(() => {
1325
+ if (!isEqual__default.default(listLayout, list.layout)) {
1326
+ setDisplayedHeaders(list.layout);
1327
+ }
1328
+ }, [list.layout, listLayout]);
1329
+ const handleSetHeaders = (headers) => {
1330
+ setDisplayedHeaders(
1331
+ indexYFPS5vYF.convertListLayoutToFieldLayouts(headers, schema.attributes, list.metadatas)
1332
+ );
1333
+ };
1334
+ const [{ query }] = indexYFPS5vYF.useQueryParams({
1335
+ page: "1",
1336
+ pageSize: list.settings.pageSize.toString(),
1337
+ sort: list.settings.defaultSortBy ? `${list.settings.defaultSortBy}:${list.settings.defaultSortOrder}` : ""
1338
+ });
1339
+ const params = React__namespace.useMemo(() => indexYFPS5vYF.buildValidParams(query), [query]);
1340
+ const { data, error, isLoading } = indexYFPS5vYF.useGetAllDocumentsQuery({
1341
+ model,
1342
+ params
1343
+ });
1344
+ React__namespace.useEffect(() => {
1345
+ if (error) {
1346
+ toggleNotification({
1347
+ type: "danger",
1348
+ message: formatAPIError(error)
1349
+ });
1350
+ }
1351
+ }, [error, formatAPIError, toggleNotification]);
1352
+ const { results = [], pagination } = data ?? {};
1353
+ React__namespace.useEffect(() => {
1354
+ if (pagination && pagination.pageCount > 0 && pagination.page > pagination.pageCount) {
1355
+ navigate(
1356
+ {
1357
+ search: indexYFPS5vYF.lib.stringify({
1358
+ ...query,
1359
+ page: pagination.pageCount
1360
+ })
1361
+ },
1362
+ { replace: true }
1363
+ );
1364
+ }
1365
+ }, [pagination, formatMessage, query, navigate]);
1366
+ const { canCreate } = indexYFPS5vYF.useDocumentRBAC("ListViewPage", ({ canCreate: canCreate2 }) => ({
1367
+ canCreate: canCreate2
1368
+ }));
1369
+ const reviewWorkflowColumns = indexYFPS5vYF.useEnterprise(
1370
+ REVIEW_WORKFLOW_COLUMNS_CE,
1371
+ async () => (await Promise.resolve().then(() => require("./constants-evLWZCaJ-dGs71EWl.js"))).REVIEW_WORKFLOW_COLUMNS_EE,
1372
+ {
1373
+ enabled: !!schema?.options?.reviewWorkflows
1374
+ }
1375
+ );
1376
+ const ReviewWorkflowsColumns = indexYFPS5vYF.useEnterprise(
1377
+ REVIEW_WORKFLOW_COLUMNS_CELL_CE,
1378
+ async () => {
1379
+ const { ReviewWorkflowsStageEE, ReviewWorkflowsAssigneeEE } = await Promise.resolve().then(() => require("./ReviewWorkflowsColumn-56Z6l-FH-3Dq1lGu9.js"));
1380
+ return { ReviewWorkflowsStageEE, ReviewWorkflowsAssigneeEE };
1381
+ },
1382
+ {
1383
+ enabled: !!schema?.options?.reviewWorkflows
1384
+ }
1385
+ );
1386
+ const runHookWaterfall = indexYFPS5vYF.useStrapiApp("ListViewPage", ({ runHookWaterfall: runHookWaterfall2 }) => runHookWaterfall2);
1387
+ const tableHeaders = React__namespace.useMemo(() => {
1388
+ const headers = runHookWaterfall(INJECT_COLUMN_IN_TABLE, {
1389
+ displayedHeaders,
1390
+ layout: list
1391
+ });
1392
+ const formattedHeaders = headers.displayedHeaders.map((header) => {
1393
+ return {
1394
+ ...header,
1395
+ label: typeof header.label === "string" ? header.label : formatMessage(header.label),
1396
+ name: `${header.name}${header.mainField ? `.${header.mainField}` : ""}`
1397
+ };
1398
+ });
1399
+ if (schema?.options?.draftAndPublish) {
1400
+ formattedHeaders.push({
1401
+ attribute: {
1402
+ type: "custom"
1403
+ },
1404
+ name: "status",
1405
+ label: formatMessage({
1406
+ id: indexYFPS5vYF.getTranslation(`containers.list.table-headers.status`),
1407
+ defaultMessage: "status"
1408
+ }),
1409
+ searchable: false,
1410
+ sortable: false
1411
+ });
1412
+ }
1413
+ if (reviewWorkflowColumns) {
1414
+ formattedHeaders.push(
1415
+ ...reviewWorkflowColumns.map((column) => ({
1416
+ ...column,
1417
+ label: formatMessage(column.label)
1418
+ }))
1419
+ );
1420
+ }
1421
+ return formattedHeaders;
1422
+ }, [
1423
+ displayedHeaders,
1424
+ formatMessage,
1425
+ list,
1426
+ reviewWorkflowColumns,
1427
+ runHookWaterfall,
1428
+ schema?.options?.draftAndPublish
1429
+ ]);
1430
+ if (isLoading) {
1431
+ return /* @__PURE__ */ jsxRuntime.jsx(indexYFPS5vYF.Page.Loading, {});
1432
+ }
1433
+ if (error) {
1434
+ return /* @__PURE__ */ jsxRuntime.jsx(indexYFPS5vYF.Page.Error, {});
1435
+ }
1436
+ const contentTypeTitle = schema?.info.displayName ?? "Untitled";
1437
+ const handleRowClick = (id) => () => {
1438
+ trackUsage("willEditEntryFromList");
1439
+ navigate({
1440
+ pathname: id.toString(),
1441
+ search: indexYFPS5vYF.lib.stringify({ plugins: query.plugins })
1442
+ });
1443
+ };
1444
+ return /* @__PURE__ */ jsxRuntime.jsxs(indexYFPS5vYF.Page.Main, { children: [
1445
+ /* @__PURE__ */ jsxRuntime.jsx(Helmet.HelmetExport, { title: `${contentTypeTitle} | Strapi` }),
1446
+ /* @__PURE__ */ jsxRuntime.jsx(
1447
+ designSystem.HeaderLayout,
1448
+ {
1449
+ primaryAction: canCreate ? /* @__PURE__ */ jsxRuntime.jsx(CreateButton, {}) : null,
1450
+ subtitle: formatMessage(
1451
+ {
1452
+ id: indexYFPS5vYF.getTranslation("pages.ListView.header-subtitle"),
1453
+ defaultMessage: "{number, plural, =0 {# entries} one {# entry} other {# entries}} found"
1454
+ },
1455
+ { number: pagination?.total }
1456
+ ),
1457
+ title: contentTypeTitle,
1458
+ navigationAction: /* @__PURE__ */ jsxRuntime.jsx(indexYFPS5vYF.BackButton, {})
1459
+ }
1460
+ ),
1461
+ /* @__PURE__ */ jsxRuntime.jsx(
1462
+ designSystem.ActionLayout,
1463
+ {
1464
+ endActions: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1465
+ /* @__PURE__ */ jsxRuntime.jsx(indexYFPS5vYF.InjectionZone, { area: "contentManager.listView.actions" }),
1466
+ /* @__PURE__ */ jsxRuntime.jsx(
1467
+ ViewSettingsMenu,
1468
+ {
1469
+ setHeaders: handleSetHeaders,
1470
+ resetHeaders: () => setDisplayedHeaders(list.layout),
1471
+ headers: displayedHeaders.map((header) => header.name)
1472
+ }
1473
+ )
1474
+ ] }),
1475
+ startActions: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1476
+ list.settings.searchable && /* @__PURE__ */ jsxRuntime.jsx(
1477
+ indexYFPS5vYF.SearchInput,
1478
+ {
1479
+ disabled: results.length === 0,
1480
+ label: formatMessage(
1481
+ { id: "app.component.search.label", defaultMessage: "Search for {target}" },
1482
+ { target: contentTypeTitle }
1483
+ ),
1484
+ placeholder: formatMessage({
1485
+ id: "global.search",
1486
+ defaultMessage: "Search"
1487
+ }),
1488
+ trackedEvent: "didSearch"
1489
+ }
1490
+ ),
1491
+ list.settings.filterable && schema ? /* @__PURE__ */ jsxRuntime.jsx(FiltersImpl, { disabled: results.length === 0, schema }) : null
1492
+ ] })
1493
+ }
1494
+ ),
1495
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.ContentLayout, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 4, direction: "column", alignItems: "stretch", children: [
1496
+ /* @__PURE__ */ jsxRuntime.jsxs(indexYFPS5vYF.Table.Root, { rows: results, headers: tableHeaders, isLoading, children: [
1497
+ /* @__PURE__ */ jsxRuntime.jsx(indexYFPS5vYF.Table.ActionBar, {}),
1498
+ /* @__PURE__ */ jsxRuntime.jsxs(indexYFPS5vYF.Table.Content, { children: [
1499
+ /* @__PURE__ */ jsxRuntime.jsxs(indexYFPS5vYF.Table.Head, { children: [
1500
+ /* @__PURE__ */ jsxRuntime.jsx(indexYFPS5vYF.Table.HeaderCheckboxCell, {}),
1501
+ tableHeaders.map((header) => /* @__PURE__ */ jsxRuntime.jsx(indexYFPS5vYF.Table.HeaderCell, { ...header }, header.name))
1502
+ ] }),
1503
+ /* @__PURE__ */ jsxRuntime.jsx(indexYFPS5vYF.Table.Loading, {}),
1504
+ /* @__PURE__ */ jsxRuntime.jsx(indexYFPS5vYF.Table.Empty, { action: canCreate ? /* @__PURE__ */ jsxRuntime.jsx(CreateButton, { variant: "secondary" }) : null }),
1505
+ /* @__PURE__ */ jsxRuntime.jsx(indexYFPS5vYF.Table.Body, { children: results.map((row) => {
1506
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1507
+ indexYFPS5vYF.Table.Row,
1508
+ {
1509
+ cursor: "pointer",
1510
+ onClick: handleRowClick(row.documentId),
1511
+ children: [
1512
+ /* @__PURE__ */ jsxRuntime.jsx(indexYFPS5vYF.Table.CheckboxCell, { id: row.id }),
1513
+ tableHeaders.map(({ cellFormatter, ...header }) => {
1514
+ if (header.name === "status") {
1515
+ const { status } = row;
1516
+ return /* @__PURE__ */ jsxRuntime.jsx(indexYFPS5vYF.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(indexYFPS5vYF.DocumentStatus, { status, maxWidth: "min-content" }) }, header.name);
1517
+ }
1518
+ if (schema?.options?.reviewWorkflows) {
1519
+ if (header.name === "strapi_stage") {
1520
+ return /* @__PURE__ */ jsxRuntime.jsx(indexYFPS5vYF.Table.Cell, { children: row.strapi_stage ? /* @__PURE__ */ jsxRuntime.jsx(
1521
+ ReviewWorkflowsColumns.ReviewWorkflowsStageEE,
1522
+ {
1523
+ color: row.strapi_stage.color ?? designSystem.lightTheme.colors.primary600,
1524
+ name: row.strapi_stage.name
1525
+ }
1526
+ ) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral800", children: "-" }) }, header.name);
1527
+ }
1528
+ if (header.name === "strapi_assignee") {
1529
+ return /* @__PURE__ */ jsxRuntime.jsx(indexYFPS5vYF.Table.Cell, { children: row.strapi_assignee ? /* @__PURE__ */ jsxRuntime.jsx(
1530
+ ReviewWorkflowsColumns.ReviewWorkflowsAssigneeEE,
1531
+ {
1532
+ user: row.strapi_assignee
1533
+ }
1534
+ ) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral800", children: "-" }) }, header.name);
1535
+ }
1536
+ }
1537
+ if (["createdBy", "updatedBy"].includes(header.name.split(".")[0])) {
1538
+ return /* @__PURE__ */ jsxRuntime.jsx(indexYFPS5vYF.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral800", children: row[header.name.split(".")[0]] ? indexYFPS5vYF.getDisplayName(row[header.name.split(".")[0]], formatMessage) : "-" }) }, header.name);
1539
+ }
1540
+ if (typeof cellFormatter === "function") {
1541
+ return /* @__PURE__ */ jsxRuntime.jsx(indexYFPS5vYF.Table.Cell, { children: cellFormatter(row, header, { collectionType, model }) }, header.name);
1542
+ }
1543
+ return /* @__PURE__ */ jsxRuntime.jsx(indexYFPS5vYF.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
1544
+ CellContent,
1545
+ {
1546
+ content: row[header.name.split(".")[0]],
1547
+ rowId: row.documentId,
1548
+ ...header
1549
+ }
1550
+ ) }, header.name);
1551
+ }),
1552
+ /* @__PURE__ */ jsxRuntime.jsx(ActionsCell, { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxRuntime.jsx(indexYFPS5vYF.TableActions, { document: row }) })
1553
+ ]
1554
+ },
1555
+ row.id
1556
+ );
1557
+ }) })
1558
+ ] })
1559
+ ] }),
1560
+ /* @__PURE__ */ jsxRuntime.jsxs(
1561
+ indexYFPS5vYF.Pagination.Root,
1562
+ {
1563
+ ...pagination,
1564
+ onPageSizeChange: () => trackUsage("willChangeNumberOfEntriesPerPage"),
1565
+ children: [
1566
+ /* @__PURE__ */ jsxRuntime.jsx(indexYFPS5vYF.Pagination.PageSize, {}),
1567
+ /* @__PURE__ */ jsxRuntime.jsx(indexYFPS5vYF.Pagination.Links, {})
1568
+ ]
1569
+ }
1570
+ )
1571
+ ] }) })
1572
+ ] });
1573
+ };
1574
+ const ActionsCell = styled__default.default(indexYFPS5vYF.Table.Cell)`
1575
+ display: flex;
1576
+ justify-content: flex-end;
1577
+ `;
1578
+ const CreateButton = ({ variant }) => {
1579
+ const { formatMessage } = reactIntl.useIntl();
1580
+ const { trackUsage } = indexYFPS5vYF.useTracking();
1581
+ const [{ query }] = indexYFPS5vYF.useQueryParams();
1582
+ return /* @__PURE__ */ jsxRuntime.jsx(
1583
+ designSystem.Button,
1584
+ {
1585
+ variant,
1586
+ forwardedAs: reactRouterDom.Link,
1587
+ onClick: () => {
1588
+ trackUsage("willCreateEntry", { status: "draft" });
1589
+ },
1590
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Plus, {}),
1591
+ style: { textDecoration: "none" },
1592
+ to: {
1593
+ pathname: "create",
1594
+ search: indexYFPS5vYF.lib.stringify({ plugins: query.plugins })
1595
+ },
1596
+ children: formatMessage({
1597
+ id: indexYFPS5vYF.getTranslation("HeaderLayout.button.label-add-entry"),
1598
+ defaultMessage: "Create new entry"
1599
+ })
1600
+ }
1601
+ );
1602
+ };
1603
+ const ProtectedListViewPage = () => {
1604
+ const { model } = indexYFPS5vYF.useDoc();
1605
+ const [{ query }] = indexYFPS5vYF.useQueryParams();
1606
+ const { permissions = [], isLoading, isError } = useSyncRbac83vFRiaG.useSyncRbac(model, query, "editView");
1607
+ if (isLoading) {
1608
+ return /* @__PURE__ */ jsxRuntime.jsx(indexYFPS5vYF.Page.Loading, {});
1609
+ }
1610
+ if (isError) {
1611
+ return /* @__PURE__ */ jsxRuntime.jsx(indexYFPS5vYF.Page.Error, {});
1612
+ }
1613
+ return /* @__PURE__ */ jsxRuntime.jsx(indexYFPS5vYF.Page.Protect, { permissions, children: ({ permissions: permissions2 }) => /* @__PURE__ */ jsxRuntime.jsx(indexYFPS5vYF.DocumentRBAC, { permissions: permissions2, children: /* @__PURE__ */ jsxRuntime.jsx(ListViewPage, {}) }) });
1614
+ };
1615
+ exports.ListViewPage = ListViewPage;
1616
+ exports.ProtectedListViewPage = ProtectedListViewPage;
1617
+ //# sourceMappingURL=ListViewPage-BNB0ptO7-TUQO_9Hj.js.map