@byline/admin 2.5.2 → 2.6.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 (260) hide show
  1. package/dist/fields/array/array-field.d.ts +14 -0
  2. package/dist/fields/array/array-field.js +177 -0
  3. package/dist/fields/array/array-field.module.js +11 -0
  4. package/dist/fields/array/array-field_module.css +32 -0
  5. package/dist/fields/blocks/blocks-field.d.ts +13 -0
  6. package/dist/fields/blocks/blocks-field.js +245 -0
  7. package/dist/fields/blocks/blocks-field.module.js +26 -0
  8. package/dist/fields/blocks/blocks-field_module.css +107 -0
  9. package/dist/fields/checkbox/checkbox-field.d.ts +16 -0
  10. package/dist/fields/checkbox/checkbox-field.js +28 -0
  11. package/dist/fields/checkbox/checkbox-field.module.js +6 -0
  12. package/dist/fields/checkbox/checkbox-field_module.css +4 -0
  13. package/dist/fields/column-formatter.d.ts +20 -0
  14. package/dist/fields/column-formatter.js +15 -0
  15. package/dist/fields/date-time-formatter.d.ts +16 -0
  16. package/dist/fields/date-time-formatter.js +8 -0
  17. package/dist/fields/datetime/datetime-field.d.ts +16 -0
  18. package/dist/fields/datetime/datetime-field.js +37 -0
  19. package/dist/fields/datetime/datetime-field.module.js +5 -0
  20. package/dist/fields/datetime/datetime-field_module.css +4 -0
  21. package/dist/fields/draggable-context-menu.d.ts +6 -0
  22. package/dist/fields/draggable-context-menu.js +85 -0
  23. package/dist/fields/draggable-context-menu.module.js +15 -0
  24. package/dist/fields/draggable-context-menu_module.css +91 -0
  25. package/dist/fields/field-helpers.d.ts +26 -0
  26. package/dist/fields/field-helpers.js +50 -0
  27. package/dist/fields/field-renderer.d.ts +37 -0
  28. package/dist/fields/field-renderer.js +206 -0
  29. package/dist/fields/field-renderer.module.js +8 -0
  30. package/dist/fields/field-renderer_module.css +11 -0
  31. package/dist/fields/field-services-context.d.ts +16 -0
  32. package/dist/fields/field-services-context.js +13 -0
  33. package/dist/fields/field-services-types.d.ts +63 -0
  34. package/dist/fields/field-services-types.js +1 -0
  35. package/dist/fields/file/file-field.d.ts +19 -0
  36. package/dist/fields/file/file-field.js +225 -0
  37. package/dist/fields/file/file-field.module.js +18 -0
  38. package/dist/fields/file/file-field_module.css +131 -0
  39. package/dist/fields/file/file-upload-field.d.ts +21 -0
  40. package/dist/fields/file/file-upload-field.js +130 -0
  41. package/dist/fields/file/file-upload-field.module.js +15 -0
  42. package/dist/fields/file/file-upload-field_module.css +74 -0
  43. package/dist/fields/group/group-field.d.ts +15 -0
  44. package/dist/fields/group/group-field.js +59 -0
  45. package/dist/fields/group/group-field.module.js +9 -0
  46. package/dist/fields/group/group-field_module.css +27 -0
  47. package/dist/fields/image/image-field.d.ts +19 -0
  48. package/dist/fields/image/image-field.js +241 -0
  49. package/dist/fields/image/image-field.module.js +22 -0
  50. package/dist/fields/image/image-field_module.css +121 -0
  51. package/dist/fields/image/image-upload-field.d.ts +21 -0
  52. package/dist/fields/image/image-upload-field.js +190 -0
  53. package/dist/fields/image/image-upload-field.module.js +19 -0
  54. package/dist/fields/image/image-upload-field_module.css +92 -0
  55. package/dist/fields/local-date-time.d.ts +27 -0
  56. package/dist/fields/local-date-time.js +49 -0
  57. package/dist/fields/locale-badge.d.ts +18 -0
  58. package/dist/fields/locale-badge.js +10 -0
  59. package/dist/fields/locale-badge.module.js +5 -0
  60. package/dist/fields/locale-badge_module.css +27 -0
  61. package/dist/fields/numerical/numerical-field.d.ts +18 -0
  62. package/dist/fields/numerical/numerical-field.js +74 -0
  63. package/dist/fields/relation/relation-display.d.ts +40 -0
  64. package/dist/fields/relation/relation-display.js +61 -0
  65. package/dist/fields/relation/relation-display.module.js +9 -0
  66. package/dist/fields/relation/relation-display_module.css +21 -0
  67. package/dist/fields/relation/relation-field.d.ts +18 -0
  68. package/dist/fields/relation/relation-field.js +138 -0
  69. package/dist/fields/relation/relation-field.module.js +13 -0
  70. package/dist/fields/relation/relation-field_module.css +62 -0
  71. package/dist/fields/relation/relation-picker.d.ts +59 -0
  72. package/dist/fields/relation/relation-picker.js +237 -0
  73. package/dist/fields/relation/relation-picker.module.js +26 -0
  74. package/dist/fields/relation/relation-picker_module.css +124 -0
  75. package/dist/fields/relation/relation-summary.d.ts +31 -0
  76. package/dist/fields/relation/relation-summary.js +50 -0
  77. package/dist/fields/relation/relation-summary.module.js +11 -0
  78. package/dist/fields/relation/relation-summary_module.css +37 -0
  79. package/dist/fields/select/select-field.d.ts +16 -0
  80. package/dist/fields/select/select-field.js +50 -0
  81. package/dist/fields/select/select-field.module.js +5 -0
  82. package/dist/fields/select/select-field_module.css +4 -0
  83. package/dist/fields/sortable-item.d.ts +15 -0
  84. package/dist/fields/sortable-item.js +81 -0
  85. package/dist/fields/sortable-item.module.js +22 -0
  86. package/dist/fields/sortable-item_module.css +124 -0
  87. package/dist/fields/text/text-field.d.ts +20 -0
  88. package/dist/fields/text/text-field.js +104 -0
  89. package/dist/fields/text/text-field.module.js +6 -0
  90. package/dist/fields/text/text-field_module.css +5 -0
  91. package/dist/fields/text-area/text-area-field.d.ts +20 -0
  92. package/dist/fields/text-area/text-area-field.js +105 -0
  93. package/dist/fields/text-area/text-area-field.module.js +6 -0
  94. package/dist/fields/text-area/text-area-field_module.css +5 -0
  95. package/dist/fields/use-field-change-handler.d.ts +23 -0
  96. package/dist/fields/use-field-change-handler.js +52 -0
  97. package/dist/forms/document-actions.d.ts +48 -0
  98. package/dist/forms/document-actions.js +475 -0
  99. package/dist/forms/document-actions.module.js +34 -0
  100. package/dist/forms/document-actions_module.css +118 -0
  101. package/dist/forms/form-context.d.ts +89 -0
  102. package/dist/forms/form-context.js +466 -0
  103. package/dist/forms/form-renderer.d.ts +98 -0
  104. package/dist/forms/form-renderer.js +597 -0
  105. package/dist/forms/form-renderer.module.js +46 -0
  106. package/dist/forms/form-renderer_module.css +245 -0
  107. package/dist/forms/navigation-guard.d.ts +54 -0
  108. package/dist/forms/navigation-guard.js +22 -0
  109. package/dist/forms/path-widget.d.ts +36 -0
  110. package/dist/forms/path-widget.js +116 -0
  111. package/dist/forms/path-widget.module.js +8 -0
  112. package/dist/forms/path-widget_module.css +29 -0
  113. package/dist/forms/upload-executor.d.ts +57 -0
  114. package/dist/forms/upload-executor.js +94 -0
  115. package/dist/lib/translate-validation-error.d.ts +36 -0
  116. package/dist/lib/translate-validation-error.js +11 -0
  117. package/dist/modules/admin-account/commands.d.ts +2 -1
  118. package/dist/modules/admin-account/commands.js +13 -2
  119. package/dist/modules/admin-account/components/change-password.js +45 -36
  120. package/dist/modules/admin-account/components/container.js +185 -134
  121. package/dist/modules/admin-account/components/preferences.d.ts +8 -0
  122. package/dist/modules/admin-account/components/preferences.js +152 -0
  123. package/dist/modules/admin-account/components/preferences.module.js +11 -0
  124. package/dist/modules/admin-account/components/preferences_module.css +41 -0
  125. package/dist/modules/admin-account/components/update.js +50 -31
  126. package/dist/modules/admin-account/index.d.ts +3 -3
  127. package/dist/modules/admin-account/index.js +2 -2
  128. package/dist/modules/admin-account/schemas.d.ts +4 -0
  129. package/dist/modules/admin-account/schemas.js +4 -1
  130. package/dist/modules/admin-account/service.d.ts +1 -0
  131. package/dist/modules/admin-account/service.js +8 -0
  132. package/dist/modules/admin-permissions/components/inspector.js +31 -41
  133. package/dist/modules/admin-roles/components/create.js +43 -26
  134. package/dist/modules/admin-roles/components/permissions.js +26 -35
  135. package/dist/modules/admin-roles/components/update.js +26 -16
  136. package/dist/modules/admin-users/components/create.js +60 -40
  137. package/dist/modules/admin-users/components/roles.js +9 -15
  138. package/dist/modules/admin-users/components/set-password.js +30 -31
  139. package/dist/modules/admin-users/components/update.js +58 -39
  140. package/dist/modules/admin-users/dto.js +1 -0
  141. package/dist/modules/admin-users/repository.d.ts +17 -0
  142. package/dist/modules/admin-users/schemas.d.ts +4 -0
  143. package/dist/modules/admin-users/schemas.js +6 -2
  144. package/dist/modules/auth/components/sign-in-form.js +10 -8
  145. package/dist/presentation/group.d.ts +27 -0
  146. package/dist/presentation/group.js +14 -0
  147. package/dist/presentation/group.module.js +6 -0
  148. package/dist/presentation/group_module.css +19 -0
  149. package/dist/presentation/row.d.ts +25 -0
  150. package/dist/presentation/row.js +8 -0
  151. package/dist/presentation/row.module.js +5 -0
  152. package/dist/presentation/row_module.css +18 -0
  153. package/dist/presentation/tabs.d.ts +25 -0
  154. package/dist/presentation/tabs.js +39 -0
  155. package/dist/presentation/tabs.module.js +10 -0
  156. package/dist/presentation/tabs_module.css +68 -0
  157. package/dist/react.d.ts +66 -0
  158. package/dist/react.js +36 -0
  159. package/dist/services/admin-services-types.d.ts +16 -0
  160. package/dist/widgets/diff-viewer/diff-modal.d.ts +22 -0
  161. package/dist/widgets/diff-viewer/diff-modal.js +149 -0
  162. package/dist/widgets/diff-viewer/diff-modal.module.js +14 -0
  163. package/dist/widgets/diff-viewer/diff-modal_module.css +56 -0
  164. package/dist/widgets/status-badge/status-badge.d.ts +25 -0
  165. package/dist/widgets/status-badge/status-badge.js +37 -0
  166. package/dist/widgets/status-badge/status-badge.module.js +7 -0
  167. package/dist/widgets/status-badge/status-badge_module.css +20 -0
  168. package/package.json +14 -4
  169. package/src/fields/array/array-field.module.css +48 -0
  170. package/src/fields/array/array-field.tsx +267 -0
  171. package/src/fields/blocks/blocks-field.module.css +148 -0
  172. package/src/fields/blocks/blocks-field.tsx +323 -0
  173. package/src/fields/checkbox/checkbox-field.module.css +4 -0
  174. package/src/fields/checkbox/checkbox-field.tsx +54 -0
  175. package/src/fields/column-formatter.tsx +31 -0
  176. package/src/fields/date-time-formatter.tsx +22 -0
  177. package/src/fields/datetime/datetime-field.module.css +13 -0
  178. package/src/fields/datetime/datetime-field.tsx +54 -0
  179. package/src/fields/draggable-context-menu.module.css +127 -0
  180. package/src/fields/draggable-context-menu.tsx +87 -0
  181. package/src/fields/field-helpers.ts +69 -0
  182. package/src/fields/field-renderer.module.css +22 -0
  183. package/src/fields/field-renderer.tsx +288 -0
  184. package/src/fields/field-services-context.tsx +35 -0
  185. package/src/fields/field-services-types.ts +68 -0
  186. package/src/fields/file/file-field.module.css +153 -0
  187. package/src/fields/file/file-field.tsx +286 -0
  188. package/src/fields/file/file-upload-field.module.css +101 -0
  189. package/src/fields/file/file-upload-field.tsx +187 -0
  190. package/src/fields/group/group-field.module.css +43 -0
  191. package/src/fields/group/group-field.tsx +84 -0
  192. package/src/fields/image/image-field.module.css +155 -0
  193. package/src/fields/image/image-field.tsx +306 -0
  194. package/src/fields/image/image-upload-field.module.css +123 -0
  195. package/src/fields/image/image-upload-field.tsx +276 -0
  196. package/src/fields/local-date-time.tsx +88 -0
  197. package/src/fields/locale-badge.module.css +37 -0
  198. package/src/fields/locale-badge.tsx +32 -0
  199. package/src/fields/numerical/numerical-field.tsx +114 -0
  200. package/src/fields/relation/relation-display.module.css +36 -0
  201. package/src/fields/relation/relation-display.tsx +138 -0
  202. package/src/fields/relation/relation-field.module.css +83 -0
  203. package/src/fields/relation/relation-field.tsx +211 -0
  204. package/src/fields/relation/relation-picker.module.css +168 -0
  205. package/src/fields/relation/relation-picker.tsx +343 -0
  206. package/src/fields/relation/relation-summary.module.css +55 -0
  207. package/src/fields/relation/relation-summary.tsx +123 -0
  208. package/src/fields/select/select-field.module.css +13 -0
  209. package/src/fields/select/select-field.tsx +61 -0
  210. package/src/fields/sortable-item.module.css +167 -0
  211. package/src/fields/sortable-item.tsx +106 -0
  212. package/src/fields/text/text-field.module.css +13 -0
  213. package/src/fields/text/text-field.tsx +146 -0
  214. package/src/fields/text-area/text-area-field.module.css +13 -0
  215. package/src/fields/text-area/text-area-field.tsx +147 -0
  216. package/src/fields/use-field-change-handler.ts +112 -0
  217. package/src/forms/document-actions.module.css +160 -0
  218. package/src/forms/document-actions.tsx +482 -0
  219. package/src/forms/form-context.tsx +704 -0
  220. package/src/forms/form-renderer.module.css +321 -0
  221. package/src/forms/form-renderer.tsx +891 -0
  222. package/src/forms/navigation-guard.tsx +98 -0
  223. package/src/forms/path-widget.module.css +41 -0
  224. package/src/forms/path-widget.test.tsx +217 -0
  225. package/src/forms/path-widget.tsx +183 -0
  226. package/src/forms/upload-executor.ts +192 -0
  227. package/src/lib/translate-validation-error.ts +56 -0
  228. package/src/modules/admin-account/commands.ts +13 -0
  229. package/src/modules/admin-account/components/change-password.tsx +46 -31
  230. package/src/modules/admin-account/components/container.tsx +83 -38
  231. package/src/modules/admin-account/components/preferences.module.css +60 -0
  232. package/src/modules/admin-account/components/preferences.tsx +203 -0
  233. package/src/modules/admin-account/components/update.tsx +53 -27
  234. package/src/modules/admin-account/index.ts +3 -0
  235. package/src/modules/admin-account/schemas.ts +13 -0
  236. package/src/modules/admin-account/service.ts +12 -0
  237. package/src/modules/admin-permissions/components/inspector.tsx +22 -14
  238. package/src/modules/admin-roles/components/create.tsx +51 -23
  239. package/src/modules/admin-roles/components/permissions.tsx +25 -21
  240. package/src/modules/admin-roles/components/update.tsx +37 -19
  241. package/src/modules/admin-users/components/create.tsx +63 -34
  242. package/src/modules/admin-users/components/roles.tsx +9 -8
  243. package/src/modules/admin-users/components/set-password.tsx +34 -28
  244. package/src/modules/admin-users/components/update.tsx +58 -36
  245. package/src/modules/admin-users/dto.ts +1 -0
  246. package/src/modules/admin-users/repository.ts +17 -0
  247. package/src/modules/admin-users/schemas.ts +12 -0
  248. package/src/modules/auth/components/sign-in-form.tsx +14 -8
  249. package/src/presentation/group.module.css +41 -0
  250. package/src/presentation/group.tsx +40 -0
  251. package/src/presentation/row.module.css +32 -0
  252. package/src/presentation/row.tsx +33 -0
  253. package/src/presentation/tabs.module.css +107 -0
  254. package/src/presentation/tabs.tsx +84 -0
  255. package/src/react.ts +84 -0
  256. package/src/services/admin-services-types.ts +18 -0
  257. package/src/widgets/diff-viewer/diff-modal.module.css +79 -0
  258. package/src/widgets/diff-viewer/diff-modal.tsx +186 -0
  259. package/src/widgets/status-badge/status-badge.module.css +31 -0
  260. package/src/widgets/status-badge/status-badge.tsx +71 -0
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useMemo, useState } from "react";
4
+ import { useTranslation } from "@byline/i18n/react";
4
5
  import { Alert, Button, Checkbox, LoaderEllipsis } from "@byline/ui/react";
5
6
  import classnames from "classnames";
6
7
  import { useBylineAdminServices } from "../../../services/admin-services-context.js";
@@ -11,6 +12,7 @@ function setsEqual(a, b) {
11
12
  return true;
12
13
  }
13
14
  function GroupSection({ group, selected, mode, saving, onToggle, onSelectAll, onClearAll }) {
15
+ const { t } = useTranslation('byline-admin');
14
16
  const groupKeys = useMemo(()=>group.abilities.map((a)=>a.key), [
15
17
  group.abilities
16
18
  ]);
@@ -28,15 +30,13 @@ function GroupSection({ group, selected, mode, saving, onToggle, onSelectAll, on
28
30
  className: classnames('byline-role-permissions-group-name', permissions_module["group-name"]),
29
31
  children: group.group
30
32
  }),
31
- /*#__PURE__*/ jsxs("span", {
33
+ /*#__PURE__*/ jsx("span", {
32
34
  className: classnames('muted', 'byline-role-permissions-group-count', permissions_module["group-count"]),
33
- children: [
34
- selectedInGroup,
35
- " of ",
36
- group.abilities.length,
37
- " ",
38
- isEdit ? 'selected' : 'granted'
39
- ]
35
+ children: t('adminRoles.permissions.groupCount', {
36
+ selected: selectedInGroup,
37
+ total: group.abilities.length,
38
+ mode
39
+ })
40
40
  })
41
41
  ]
42
42
  }),
@@ -49,7 +49,7 @@ function GroupSection({ group, selected, mode, saving, onToggle, onSelectAll, on
49
49
  type: "button",
50
50
  disabled: saving || selectedInGroup === group.abilities.length,
51
51
  onClick: ()=>onSelectAll(groupKeys),
52
- children: "Select all"
52
+ children: t('adminRoles.permissions.selectAll')
53
53
  }),
54
54
  /*#__PURE__*/ jsx(Button, {
55
55
  size: "xs",
@@ -57,7 +57,7 @@ function GroupSection({ group, selected, mode, saving, onToggle, onSelectAll, on
57
57
  type: "button",
58
58
  disabled: saving || 0 === selectedInGroup,
59
59
  onClick: ()=>onClearAll(groupKeys),
60
- children: "Clear"
60
+ children: t('adminRoles.permissions.clear')
61
61
  })
62
62
  ]
63
63
  }) : null
@@ -111,6 +111,7 @@ function GroupSection({ group, selected, mode, saving, onToggle, onSelectAll, on
111
111
  }
112
112
  function RolePermissions({ role, registered, initialAbilities, onSaved }) {
113
113
  const { setRoleAbilities } = useBylineAdminServices();
114
+ const { t } = useTranslation('byline-admin');
114
115
  const [mode, setMode] = useState('view');
115
116
  const [initialSet, setInitialSet] = useState(()=>new Set(initialAbilities));
116
117
  const [selected, setSelected] = useState(()=>new Set(initialAbilities));
@@ -172,8 +173,8 @@ function RolePermissions({ role, registered, initialAbilities, onSaved }) {
172
173
  onSaved?.(response);
173
174
  } catch (err) {
174
175
  const code = getErrorCode(err);
175
- if ('admin.permissions.roleNotFound' === code) setError('This role no longer exists.');
176
- else 'admin.permissions.abilityUnregistered' === code ? setError('One or more selected abilities are no longer registered. Reload the page and try again.') : setError('Could not save permissions. Please try again.');
176
+ if ('admin.permissions.roleNotFound' === code) setError(t('adminRoles.permissions.errors.roleNotFound'));
177
+ else 'admin.permissions.abilityUnregistered' === code ? setError(t('adminRoles.permissions.errors.abilityUnregistered')) : setError(t('adminRoles.permissions.errors.fallback'));
177
178
  } finally{
178
179
  setSaving(false);
179
180
  }
@@ -192,25 +193,14 @@ function RolePermissions({ role, registered, initialAbilities, onSaved }) {
192
193
  onView: handleEnterView,
193
194
  onEdit: handleEnterEdit
194
195
  }),
195
- /*#__PURE__*/ jsxs("p", {
196
+ /*#__PURE__*/ jsx("p", {
196
197
  className: classnames('muted', 'byline-role-permissions-counter', permissions_module.counter),
197
- children: [
198
- /*#__PURE__*/ jsx("span", {
199
- className: classnames('byline-role-permissions-counter-num', permissions_module["counter-num"]),
200
- children: totalSelected
201
- }),
202
- ' ',
203
- "of",
204
- ' ',
205
- /*#__PURE__*/ jsx("span", {
206
- className: classnames('byline-role-permissions-counter-num', permissions_module["counter-num"]),
207
- children: registered.total
208
- }),
209
- ' ',
210
- isEdit ? 'selected' : 'granted',
211
- " for ",
212
- role.name
213
- ]
198
+ children: t('adminRoles.permissions.counter', {
199
+ selected: totalSelected,
200
+ total: registered.total,
201
+ mode,
202
+ role: role.name
203
+ })
214
204
  }),
215
205
  isEdit && isDirty ? /*#__PURE__*/ jsxs("div", {
216
206
  className: classnames('byline-role-permissions-actions', permissions_module.actions),
@@ -222,7 +212,7 @@ function RolePermissions({ role, registered, initialAbilities, onSaved }) {
222
212
  onClick: handleCancel,
223
213
  disabled: saving,
224
214
  className: classnames('byline-role-permissions-action', permissions_module.action),
225
- children: "Cancel"
215
+ children: t('common.actions.cancel')
226
216
  }),
227
217
  /*#__PURE__*/ jsx(Button, {
228
218
  type: "button",
@@ -233,7 +223,7 @@ function RolePermissions({ role, registered, initialAbilities, onSaved }) {
233
223
  className: classnames('byline-role-permissions-action', permissions_module.action),
234
224
  children: saving ? /*#__PURE__*/ jsx(LoaderEllipsis, {
235
225
  size: 30
236
- }) : 'Save'
226
+ }) : t('common.actions.save')
237
227
  })
238
228
  ]
239
229
  }) : null
@@ -259,13 +249,14 @@ function RolePermissions({ role, registered, initialAbilities, onSaved }) {
259
249
  });
260
250
  }
261
251
  function ModeToggle({ mode, dirty, saving, onView, onEdit }) {
252
+ const { t } = useTranslation('byline-admin');
262
253
  const isView = 'view' === mode;
263
254
  const isEdit = 'edit' === mode;
264
255
  const viewDisabled = dirty || saving;
265
256
  const editDisabled = saving;
266
257
  return /*#__PURE__*/ jsxs("div", {
267
258
  role: "group",
268
- "aria-label": "Permissions mode",
259
+ "aria-label": t('adminRoles.permissions.modeAriaLabel'),
269
260
  className: classnames('byline-role-permissions-mode-toggle', permissions_module["mode-toggle"]),
270
261
  children: [
271
262
  /*#__PURE__*/ jsx("button", {
@@ -279,7 +270,7 @@ function ModeToggle({ mode, dirty, saving, onView, onEdit }) {
279
270
  'byline-role-permissions-mode-button-disabled',
280
271
  permissions_module["mode-button-disabled"]
281
272
  ]),
282
- children: "View"
273
+ children: t('adminRoles.permissions.viewMode')
283
274
  }),
284
275
  /*#__PURE__*/ jsx("button", {
285
276
  type: "button",
@@ -292,7 +283,7 @@ function ModeToggle({ mode, dirty, saving, onView, onEdit }) {
292
283
  'byline-role-permissions-mode-button-disabled',
293
284
  permissions_module["mode-button-disabled"]
294
285
  ]),
295
- children: "Edit"
286
+ children: t('adminRoles.permissions.editMode')
296
287
  })
297
288
  ]
298
289
  });
@@ -1,16 +1,15 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
- import { useState } from "react";
3
+ import { useMemo, useState } from "react";
4
4
  import { revalidateLogic, useForm } from "@tanstack/react-form-start";
5
+ import { useTranslation } from "@byline/i18n/react";
5
6
  import { Alert, Button, Input, LoaderEllipsis, TextArea } from "@byline/ui/react";
6
7
  import classnames from "classnames";
7
8
  import { z } from "zod";
8
9
  import { useBylineAdminServices } from "../../../services/admin-services-context.js";
9
10
  import update_module from "./update.module.js";
10
- const updateRoleSchema = z.object({
11
- name: z.string().min(1, 'Name is required').max(128, 'Name must not exceed 128 characters'),
12
- description: z.string().max(2000, "Description must not exceed 2000 characters")
13
- });
11
+ const MAX_NAME = 128;
12
+ const MAX_DESCRIPTION = 2000;
14
13
  function defaultsFrom(role) {
15
14
  return {
16
15
  name: role.name,
@@ -28,8 +27,19 @@ function buildPatch(values, role) {
28
27
  }
29
28
  function UpdateRole({ role, onClose, onSuccess }) {
30
29
  const { updateAdminRole } = useBylineAdminServices();
30
+ const { t } = useTranslation('byline-admin');
31
31
  const [formError, setFormError] = useState(null);
32
32
  const [successMessage, setSuccessMessage] = useState(null);
33
+ const updateRoleSchema = useMemo(()=>z.object({
34
+ name: z.string().min(1, t('adminRoles.create.errors.nameRequired')).max(MAX_NAME, t('adminRoles.create.errors.nameTooLong', {
35
+ max: MAX_NAME
36
+ })),
37
+ description: z.string().max(MAX_DESCRIPTION, t("adminRoles.create.errors.descriptionTooLong", {
38
+ max: MAX_DESCRIPTION
39
+ }))
40
+ }), [
41
+ t
42
+ ]);
33
43
  const form = useForm({
34
44
  defaultValues: defaultsFrom(role),
35
45
  validationLogic: revalidateLogic({
@@ -43,7 +53,7 @@ function UpdateRole({ role, onClose, onSuccess }) {
43
53
  setFormError(null);
44
54
  setSuccessMessage(null);
45
55
  const patch = buildPatch(value, role);
46
- if (0 === Object.keys(patch).length) return void setSuccessMessage('No changes to save.');
56
+ if (0 === Object.keys(patch).length) return void setSuccessMessage(t('common.feedback.noChanges'));
47
57
  try {
48
58
  const updated = await updateAdminRole({
49
59
  data: {
@@ -52,13 +62,13 @@ function UpdateRole({ role, onClose, onSuccess }) {
52
62
  patch
53
63
  }
54
64
  });
55
- setSuccessMessage('Saved.');
65
+ setSuccessMessage(t('common.feedback.saved'));
56
66
  onSuccess?.(updated);
57
67
  } catch (err) {
58
68
  const code = getErrorCode(err);
59
- if ('admin.roles.versionConflict' === code) return void setFormError('This role has been modified elsewhere since you opened this form. Reload to get the latest values and try again.');
60
- if ('admin.roles.notFound' === code) return void setFormError('This role no longer exists.');
61
- setFormError('Could not save changes. Please try again.');
69
+ if ('admin.roles.versionConflict' === code) return void setFormError(t('adminRoles.update.errors.versionConflict'));
70
+ if ('admin.roles.notFound' === code) return void setFormError(t('adminRoles.update.errors.notFound'));
71
+ setFormError(t('common.errors.couldNotSave'));
62
72
  }
63
73
  }
64
74
  });
@@ -84,7 +94,7 @@ function UpdateRole({ role, onClose, onSuccess }) {
84
94
  /*#__PURE__*/ jsx(form.Field, {
85
95
  name: "name",
86
96
  children: (field)=>/*#__PURE__*/ jsx(Input, {
87
- label: "Name",
97
+ label: t('adminRoles.fields.name'),
88
98
  id: "role-name",
89
99
  name: field.name,
90
100
  value: field.state.value,
@@ -96,18 +106,18 @@ function UpdateRole({ role, onClose, onSuccess }) {
96
106
  })
97
107
  }),
98
108
  /*#__PURE__*/ jsx(Input, {
99
- label: "Machine name",
109
+ label: t('adminRoles.fields.machineName'),
100
110
  id: "role-machine-name",
101
111
  name: "machine_name",
102
112
  value: role.machine_name,
103
113
  readOnly: true,
104
114
  disabled: true,
105
- helpText: "The stable code-side handle. Cannot be changed after creation."
115
+ helpText: t('adminRoles.update.fields.machineNameHelp')
106
116
  }),
107
117
  /*#__PURE__*/ jsx(form.Field, {
108
118
  name: "description",
109
119
  children: (field)=>/*#__PURE__*/ jsx(TextArea, {
110
- label: "Description",
120
+ label: t("adminRoles.fields.description"),
111
121
  id: "role-description",
112
122
  name: field.name,
113
123
  value: field.state.value,
@@ -127,7 +137,7 @@ function UpdateRole({ role, onClose, onSuccess }) {
127
137
  size: "sm",
128
138
  onClick: onClose,
129
139
  className: classnames('byline-role-update-action', update_module.action),
130
- children: successMessage ? 'Close' : 'Cancel'
140
+ children: successMessage ? t('common.actions.close') : t('common.actions.cancel')
131
141
  }),
132
142
  /*#__PURE__*/ jsx(form.Subscribe, {
133
143
  selector: (state)=>({
@@ -142,7 +152,7 @@ function UpdateRole({ role, onClose, onSuccess }) {
142
152
  className: classnames('byline-role-update-action', update_module.action),
143
153
  children: true === isSubmitting ? /*#__PURE__*/ jsx(LoaderEllipsis, {
144
154
  size: 42
145
- }) : 'Save'
155
+ }) : t('common.actions.save')
146
156
  })
147
157
  })
148
158
  ]
@@ -1,25 +1,18 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
- import { useState } from "react";
3
+ import { useMemo, useState } from "react";
4
4
  import { revalidateLogic, useForm } from "@tanstack/react-form-start";
5
5
  import { passwordSchema } from "@byline/core/validation";
6
+ import { useTranslation } from "@byline/i18n/react";
6
7
  import { Alert, Button, Checkbox, Input, LoaderEllipsis } from "@byline/ui/react";
7
8
  import classnames from "classnames";
8
9
  import { z } from "zod";
10
+ import { translateValidationError } from "../../../lib/translate-validation-error.js";
9
11
  import { useBylineAdminServices } from "../../../services/admin-services-context.js";
10
12
  import create_module from "./create.module.js";
11
- const createAdminUserFormSchema = z.object({
12
- email: z.email({
13
- message: 'Enter a valid email address'
14
- }).min(3).max(254, 'Email must not exceed 254 characters'),
15
- password: passwordSchema,
16
- given_name: z.string().max(100, 'Given name must not exceed 100 characters'),
17
- family_name: z.string().max(100, 'Family name must not exceed 100 characters'),
18
- username: z.string().max(100, 'Username must not exceed 100 characters'),
19
- is_super_admin: z.boolean(),
20
- is_enabled: z.boolean(),
21
- is_email_verified: z.boolean()
22
- });
13
+ const MAX_NAME = 100;
14
+ const MAX_USERNAME = 100;
15
+ const MAX_EMAIL = 254;
23
16
  const initialValues = {
24
17
  email: '',
25
18
  password: '',
@@ -35,7 +28,30 @@ function normaliseText(value) {
35
28
  }
36
29
  function CreateAdminUser({ onClose, onSuccess }) {
37
30
  const { createAdminUser } = useBylineAdminServices();
31
+ const { t } = useTranslation('byline-admin');
38
32
  const [formError, setFormError] = useState(null);
33
+ const createAdminUserFormSchema = useMemo(()=>z.object({
34
+ email: z.email({
35
+ message: t('account.update.errors.invalidEmail')
36
+ }).min(3).max(MAX_EMAIL, t('account.update.errors.emailTooLong', {
37
+ max: MAX_EMAIL
38
+ })),
39
+ password: passwordSchema,
40
+ given_name: z.string().max(MAX_NAME, t('account.update.errors.givenNameTooLong', {
41
+ max: MAX_NAME
42
+ })),
43
+ family_name: z.string().max(MAX_NAME, t('account.update.errors.familyNameTooLong', {
44
+ max: MAX_NAME
45
+ })),
46
+ username: z.string().max(MAX_USERNAME, t('account.update.errors.usernameTooLong', {
47
+ max: MAX_USERNAME
48
+ })),
49
+ is_super_admin: z.boolean(),
50
+ is_enabled: z.boolean(),
51
+ is_email_verified: z.boolean()
52
+ }), [
53
+ t
54
+ ]);
39
55
  const form = useForm({
40
56
  defaultValues: initialValues,
41
57
  validationLogic: revalidateLogic({
@@ -64,17 +80,21 @@ function CreateAdminUser({ onClose, onSuccess }) {
64
80
  onSuccess?.(created);
65
81
  } catch (err) {
66
82
  const code = getErrorCode(err);
67
- if ('admin.users.emailInUse' === code) return void form.setFieldMeta('email', (meta)=>({
68
- ...meta,
69
- errorMap: {
70
- ...meta.errorMap,
71
- onServer: 'This email is already in use.'
72
- },
73
- errors: [
74
- 'This email is already in use.'
75
- ]
76
- }));
77
- setFormError('Could not create this admin user. Please try again.');
83
+ if ('admin.users.emailInUse' === code) {
84
+ const message = t('account.update.errors.emailInUse');
85
+ form.setFieldMeta('email', (meta)=>({
86
+ ...meta,
87
+ errorMap: {
88
+ ...meta.errorMap,
89
+ onServer: message
90
+ },
91
+ errors: [
92
+ message
93
+ ]
94
+ }));
95
+ return;
96
+ }
97
+ setFormError(t('adminUsers.create.errors.fallback'));
78
98
  }
79
99
  }
80
100
  });
@@ -99,7 +119,7 @@ function CreateAdminUser({ onClose, onSuccess }) {
99
119
  /*#__PURE__*/ jsx(form.Field, {
100
120
  name: "given_name",
101
121
  children: (field)=>/*#__PURE__*/ jsx(Input, {
102
- label: "Given name",
122
+ label: t('account.update.fields.givenName'),
103
123
  id: "new-given-name",
104
124
  name: field.name,
105
125
  value: field.state.value,
@@ -113,7 +133,7 @@ function CreateAdminUser({ onClose, onSuccess }) {
113
133
  /*#__PURE__*/ jsx(form.Field, {
114
134
  name: "family_name",
115
135
  children: (field)=>/*#__PURE__*/ jsx(Input, {
116
- label: "Family name",
136
+ label: t('account.update.fields.familyName'),
117
137
  id: "new-family-name",
118
138
  name: field.name,
119
139
  value: field.state.value,
@@ -129,7 +149,7 @@ function CreateAdminUser({ onClose, onSuccess }) {
129
149
  /*#__PURE__*/ jsx(form.Field, {
130
150
  name: "username",
131
151
  children: (field)=>/*#__PURE__*/ jsx(Input, {
132
- label: "Username",
152
+ label: t('account.update.fields.username'),
133
153
  id: "new-username",
134
154
  name: field.name,
135
155
  value: field.state.value,
@@ -137,14 +157,14 @@ function CreateAdminUser({ onClose, onSuccess }) {
137
157
  onChange: (e)=>field.handleChange(e.currentTarget.value),
138
158
  error: field.state.meta.errors.length > 0,
139
159
  errorText: firstError(field.state.meta.errors),
140
- helpText: "Optional.",
160
+ helpText: t('adminUsers.create.fields.usernameHelp'),
141
161
  autoComplete: "username"
142
162
  })
143
163
  }),
144
164
  /*#__PURE__*/ jsx(form.Field, {
145
165
  name: "email",
146
166
  children: (field)=>/*#__PURE__*/ jsx(Input, {
147
- label: "Email",
167
+ label: t('common.fields.email'),
148
168
  id: "new-email",
149
169
  name: field.name,
150
170
  type: "email",
@@ -160,7 +180,7 @@ function CreateAdminUser({ onClose, onSuccess }) {
160
180
  /*#__PURE__*/ jsx(form.Field, {
161
181
  name: "password",
162
182
  children: (field)=>/*#__PURE__*/ jsx(Input, {
163
- label: "Initial password",
183
+ label: t('adminUsers.create.fields.password'),
164
184
  id: "new-password",
165
185
  name: field.name,
166
186
  type: "password",
@@ -168,8 +188,8 @@ function CreateAdminUser({ onClose, onSuccess }) {
168
188
  onBlur: field.handleBlur,
169
189
  onChange: (e)=>field.handleChange(e.currentTarget.value),
170
190
  error: field.state.meta.errors.length > 0,
171
- errorText: firstError(field.state.meta.errors),
172
- helpText: "The user can change it from their own account after signing in.",
191
+ errorText: translateValidationError(t, firstError(field.state.meta.errors)),
192
+ helpText: t('adminUsers.create.fields.passwordHelp'),
173
193
  autoComplete: "new-password",
174
194
  required: true
175
195
  })
@@ -182,10 +202,10 @@ function CreateAdminUser({ onClose, onSuccess }) {
182
202
  children: (field)=>/*#__PURE__*/ jsx(Checkbox, {
183
203
  id: "new-is-enabled",
184
204
  name: field.name,
185
- label: "Enabled",
205
+ label: t('adminUsers.create.flags.enabledLabel'),
186
206
  checked: field.state.value,
187
207
  onCheckedChange: (checked)=>field.handleChange(true === checked),
188
- helpText: "Disabled accounts cannot sign in."
208
+ helpText: t('adminUsers.create.flags.enabledHelp')
189
209
  })
190
210
  }),
191
211
  /*#__PURE__*/ jsx(form.Field, {
@@ -193,10 +213,10 @@ function CreateAdminUser({ onClose, onSuccess }) {
193
213
  children: (field)=>/*#__PURE__*/ jsx(Checkbox, {
194
214
  id: "new-is-email-verified",
195
215
  name: field.name,
196
- label: "Email verified",
216
+ label: t('adminUsers.create.flags.emailVerifiedLabel'),
197
217
  checked: field.state.value,
198
218
  onCheckedChange: (checked)=>field.handleChange(true === checked),
199
- helpText: "Skip the verification flow for this account."
219
+ helpText: t('adminUsers.create.flags.emailVerifiedHelp')
200
220
  })
201
221
  }),
202
222
  /*#__PURE__*/ jsx(form.Field, {
@@ -204,10 +224,10 @@ function CreateAdminUser({ onClose, onSuccess }) {
204
224
  children: (field)=>/*#__PURE__*/ jsx(Checkbox, {
205
225
  id: "new-is-super-admin",
206
226
  name: field.name,
207
- label: "Super admin",
227
+ label: t('adminUsers.create.flags.superAdminLabel'),
208
228
  checked: field.state.value,
209
229
  onCheckedChange: (checked)=>field.handleChange(true === checked),
210
- helpText: "Super admins bypass every ability check — grant with care."
230
+ helpText: t('adminUsers.create.flags.superAdminHelp')
211
231
  })
212
232
  })
213
233
  ]
@@ -221,7 +241,7 @@ function CreateAdminUser({ onClose, onSuccess }) {
221
241
  size: "sm",
222
242
  onClick: onClose,
223
243
  className: classnames('byline-user-create-action', create_module.action),
224
- children: "Cancel"
244
+ children: t('common.actions.cancel')
225
245
  }),
226
246
  /*#__PURE__*/ jsx(form.Subscribe, {
227
247
  selector: (state)=>({
@@ -236,7 +256,7 @@ function CreateAdminUser({ onClose, onSuccess }) {
236
256
  className: classnames('byline-user-create-action', create_module.action),
237
257
  children: true === isSubmitting ? /*#__PURE__*/ jsx(LoaderEllipsis, {
238
258
  size: 42
239
- }) : 'Save'
259
+ }) : t('common.actions.save')
240
260
  })
241
261
  })
242
262
  ]
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useState } from "react";
4
+ import { useTranslation } from "@byline/i18n/react";
4
5
  import { Alert, Button, Checkbox, LoaderEllipsis } from "@byline/ui/react";
5
6
  import classnames from "classnames";
6
7
  import { useBylineAdminServices } from "../../../services/admin-services-context.js";
@@ -12,6 +13,7 @@ function setsEqual(a, b) {
12
13
  }
13
14
  function UserRoles({ user, allRoles, initialRoleIds, onClose, onSaved }) {
14
15
  const { setUserRoles } = useBylineAdminServices();
16
+ const { t } = useTranslation('byline-admin');
15
17
  const [initialSet, setInitialSet] = useState(()=>new Set(initialRoleIds));
16
18
  const [selected, setSelected] = useState(()=>new Set(initialRoleIds));
17
19
  const [saving, setSaving] = useState(false);
@@ -42,12 +44,12 @@ function UserRoles({ user, allRoles, initialRoleIds, onClose, onSaved }) {
42
44
  const storedSet = new Set(response.roles.map((r)=>r.id));
43
45
  setInitialSet(storedSet);
44
46
  setSelected(new Set(storedSet));
45
- setSuccessMessage('Saved.');
47
+ setSuccessMessage(t('common.feedback.saved'));
46
48
  onSaved?.(response);
47
49
  } catch (err) {
48
50
  const code = getErrorCode(err);
49
- if ('admin.roles.userNotFound' === code) setError('This user no longer exists.');
50
- else 'admin.roles.notFound' === code ? setError('One or more selected roles no longer exist. Reload the page and try again.') : setError('Could not save roles. Please try again.');
51
+ if ('admin.roles.userNotFound' === code) setError(t('adminUsers.roles.errors.userNotFound'));
52
+ else 'admin.roles.notFound' === code ? setError(t('adminUsers.roles.errors.roleNotFound')) : setError(t('adminUsers.roles.errors.fallback'));
51
53
  } finally{
52
54
  setSaving(false);
53
55
  }
@@ -63,17 +65,9 @@ function UserRoles({ user, allRoles, initialRoleIds, onClose, onSaved }) {
63
65
  intent: "success",
64
66
  children: successMessage
65
67
  }) : null,
66
- 0 === allRoles.length ? /*#__PURE__*/ jsxs("p", {
68
+ 0 === allRoles.length ? /*#__PURE__*/ jsx("p", {
67
69
  className: classnames('muted', 'byline-user-roles-empty', roles_module.empty),
68
- children: [
69
- "No roles have been created yet. Create roles in",
70
- ' ',
71
- /*#__PURE__*/ jsx("span", {
72
- className: "muted",
73
- children: "/admin/roles"
74
- }),
75
- " first."
76
- ]
70
+ children: t('adminUsers.roles.emptyCatalog')
77
71
  }) : /*#__PURE__*/ jsx("div", {
78
72
  className: classnames('byline-user-roles-list', roles_module.list),
79
73
  children: allRoles.map((role)=>/*#__PURE__*/ jsxs("div", {
@@ -124,7 +118,7 @@ function UserRoles({ user, allRoles, initialRoleIds, onClose, onSaved }) {
124
118
  onClick: onClose,
125
119
  disabled: saving,
126
120
  className: classnames('byline-user-roles-action', roles_module.action),
127
- children: successMessage ? 'Close' : 'Cancel'
121
+ children: successMessage ? t('common.actions.close') : t('common.actions.cancel')
128
122
  }),
129
123
  /*#__PURE__*/ jsx(Button, {
130
124
  type: "button",
@@ -135,7 +129,7 @@ function UserRoles({ user, allRoles, initialRoleIds, onClose, onSaved }) {
135
129
  className: classnames('byline-user-roles-action', roles_module.action),
136
130
  children: saving ? /*#__PURE__*/ jsx(LoaderEllipsis, {
137
131
  size: 30
138
- }) : 'Save'
132
+ }) : t('common.actions.save')
139
133
  })
140
134
  ]
141
135
  })