@byline/host-tanstack-start 2.5.1 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/dist/admin-shell/admin-roles/container.js +38 -24
  2. package/dist/admin-shell/admin-roles/delete.js +9 -7
  3. package/dist/admin-shell/admin-roles/list.js +20 -16
  4. package/dist/admin-shell/admin-users/container.js +79 -56
  5. package/dist/admin-shell/admin-users/delete.js +10 -8
  6. package/dist/admin-shell/admin-users/list.js +27 -18
  7. package/dist/admin-shell/chrome/admin-app-bar.js +5 -2
  8. package/dist/admin-shell/chrome/breadcrumbs/breadcrumbs.js +3 -1
  9. package/dist/admin-shell/chrome/dashboard.js +13 -11
  10. package/dist/admin-shell/chrome/hamburger.js +3 -1
  11. package/dist/admin-shell/chrome/menu-drawer.js +7 -5
  12. package/dist/admin-shell/chrome/preview-toggle.js +5 -3
  13. package/dist/admin-shell/chrome/route-error.d.ts +3 -2
  14. package/dist/admin-shell/chrome/route-error.js +29 -22
  15. package/dist/admin-shell/chrome/sign-in-page.d.ts +16 -4
  16. package/dist/admin-shell/chrome/sign-in-page.js +38 -13
  17. package/dist/admin-shell/chrome/sign-in-page.module.js +1 -0
  18. package/dist/admin-shell/chrome/sign-in-page_module.css +8 -1
  19. package/dist/admin-shell/collections/api.js +6 -5
  20. package/dist/admin-shell/collections/create.js +12 -4
  21. package/dist/admin-shell/collections/edit.js +112 -37
  22. package/dist/admin-shell/collections/history.js +17 -12
  23. package/dist/admin-shell/collections/list.js +18 -13
  24. package/dist/admin-shell/collections/preview-link.d.ts +1 -10
  25. package/dist/admin-shell/collections/preview-link.js +9 -11
  26. package/dist/admin-shell/collections/resolve-preview-url.d.ts +34 -0
  27. package/dist/admin-shell/collections/resolve-preview-url.js +17 -0
  28. package/dist/admin-shell/collections/restore-version-modal.js +13 -14
  29. package/dist/admin-shell/collections/tanstack-navigation-guard.d.ts +1 -1
  30. package/dist/admin-shell/collections/view-menu.js +7 -5
  31. package/dist/i18n/index.d.ts +19 -0
  32. package/dist/i18n/index.js +4 -0
  33. package/dist/i18n/locale-cookie.d.ts +17 -0
  34. package/dist/i18n/locale-cookie.js +26 -0
  35. package/dist/i18n/locale-definitions.d.ts +29 -0
  36. package/dist/i18n/locale-definitions.js +27 -0
  37. package/dist/i18n/resolve-locale.d.ts +20 -0
  38. package/dist/i18n/resolve-locale.js +43 -0
  39. package/dist/i18n/server-translator.d.ts +33 -0
  40. package/dist/i18n/server-translator.js +19 -0
  41. package/dist/integrations/byline-admin-services.js +2 -0
  42. package/dist/integrations/byline-field-services.d.ts +3 -3
  43. package/dist/routes/create-admin-account-route.js +6 -3
  44. package/dist/routes/create-admin-dashboard-route.js +3 -1
  45. package/dist/routes/create-admin-layout-route.js +48 -25
  46. package/dist/routes/create-admin-permissions-route.js +4 -2
  47. package/dist/routes/create-admin-role-edit-route.js +5 -3
  48. package/dist/routes/create-admin-roles-list-route.js +4 -2
  49. package/dist/routes/create-admin-user-edit-route.js +5 -3
  50. package/dist/routes/create-admin-users-list-route.js +4 -2
  51. package/dist/routes/create-collection-api-route.js +5 -3
  52. package/dist/routes/create-collection-create-route.js +4 -2
  53. package/dist/routes/create-collection-edit-route.js +4 -2
  54. package/dist/routes/create-collection-history-route.js +5 -3
  55. package/dist/routes/create-collection-list-route.js +11 -5
  56. package/dist/routes/create-sign-in-route.js +10 -1
  57. package/dist/server-fns/admin-account/change-password.d.ts +1 -0
  58. package/dist/server-fns/admin-account/get.d.ts +1 -0
  59. package/dist/server-fns/admin-account/update.d.ts +1 -0
  60. package/dist/server-fns/admin-users/create.d.ts +1 -0
  61. package/dist/server-fns/admin-users/get.d.ts +1 -0
  62. package/dist/server-fns/admin-users/list.d.ts +1 -0
  63. package/dist/server-fns/admin-users/set-password.d.ts +1 -0
  64. package/dist/server-fns/admin-users/update.d.ts +1 -0
  65. package/dist/server-fns/auth/sign-in.js +18 -0
  66. package/dist/server-fns/i18n/get-active-locale.d.ts +8 -0
  67. package/dist/server-fns/i18n/get-active-locale.js +6 -0
  68. package/dist/server-fns/i18n/index.d.ts +10 -0
  69. package/dist/server-fns/i18n/index.js +2 -0
  70. package/dist/server-fns/i18n/set-locale.d.ts +25 -0
  71. package/dist/server-fns/i18n/set-locale.js +42 -0
  72. package/package.json +16 -7
  73. package/src/admin-shell/admin-roles/container.tsx +41 -31
  74. package/src/admin-shell/admin-roles/delete.tsx +10 -11
  75. package/src/admin-shell/admin-roles/list.tsx +29 -16
  76. package/src/admin-shell/admin-users/container.tsx +77 -50
  77. package/src/admin-shell/admin-users/delete.tsx +11 -12
  78. package/src/admin-shell/admin-users/list.tsx +39 -18
  79. package/src/admin-shell/chrome/admin-app-bar.tsx +5 -2
  80. package/src/admin-shell/chrome/breadcrumbs/breadcrumbs.tsx +3 -1
  81. package/src/admin-shell/chrome/dashboard.tsx +9 -3
  82. package/src/admin-shell/chrome/hamburger.tsx +3 -1
  83. package/src/admin-shell/chrome/menu-drawer.tsx +7 -5
  84. package/src/admin-shell/chrome/preview-toggle.tsx +6 -4
  85. package/src/admin-shell/chrome/route-error.tsx +39 -26
  86. package/src/admin-shell/chrome/sign-in-page.module.css +10 -1
  87. package/src/admin-shell/chrome/sign-in-page.tsx +46 -12
  88. package/src/admin-shell/collections/api.tsx +5 -1
  89. package/src/admin-shell/collections/create.tsx +10 -4
  90. package/src/admin-shell/collections/edit.tsx +79 -72
  91. package/src/admin-shell/collections/history.tsx +18 -12
  92. package/src/admin-shell/collections/list.tsx +25 -14
  93. package/src/admin-shell/collections/preview-link.tsx +20 -33
  94. package/src/admin-shell/collections/resolve-preview-url.test.node.ts +167 -0
  95. package/src/admin-shell/collections/resolve-preview-url.ts +67 -0
  96. package/src/admin-shell/collections/restore-version-modal.tsx +11 -12
  97. package/src/admin-shell/collections/tanstack-navigation-guard.ts +1 -1
  98. package/src/admin-shell/collections/view-menu.tsx +9 -5
  99. package/src/i18n/index.ts +26 -0
  100. package/src/i18n/locale-cookie.ts +68 -0
  101. package/src/i18n/locale-definitions.ts +48 -0
  102. package/src/i18n/resolve-locale.ts +96 -0
  103. package/src/i18n/server-translator.ts +60 -0
  104. package/src/integrations/byline-admin-services.ts +2 -0
  105. package/src/integrations/byline-field-services.ts +7 -3
  106. package/src/routes/create-admin-account-route.tsx +6 -4
  107. package/src/routes/create-admin-dashboard-route.tsx +5 -1
  108. package/src/routes/create-admin-layout-route.tsx +53 -20
  109. package/src/routes/create-admin-permissions-route.tsx +4 -2
  110. package/src/routes/create-admin-role-edit-route.tsx +5 -3
  111. package/src/routes/create-admin-roles-list-route.tsx +5 -2
  112. package/src/routes/create-admin-user-edit-route.tsx +5 -3
  113. package/src/routes/create-admin-users-list-route.tsx +4 -2
  114. package/src/routes/create-collection-api-route.tsx +5 -3
  115. package/src/routes/create-collection-create-route.tsx +7 -2
  116. package/src/routes/create-collection-edit-route.tsx +4 -2
  117. package/src/routes/create-collection-history-route.tsx +5 -3
  118. package/src/routes/create-collection-list-route.tsx +8 -10
  119. package/src/routes/create-sign-in-route.tsx +14 -1
  120. package/src/server-fns/auth/sign-in.ts +45 -0
  121. package/src/server-fns/i18n/get-active-locale.ts +26 -0
  122. package/src/server-fns/i18n/index.ts +11 -0
  123. package/src/server-fns/i18n/set-locale.ts +103 -0
@@ -1,19 +1,24 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import { useState } from "react";
3
+ import { FormRenderer } from "@byline/admin/react";
3
4
  import { getDefaultStatus, getWorkflowStatuses } from "@byline/core";
4
- import { Container, FormRenderer, Section, useToastManager } from "@byline/ui/react";
5
+ import { useTranslation } from "@byline/i18n/react";
6
+ import { Container, Section, useToastManager } from "@byline/ui/react";
5
7
  import { copyDocumentToLocale, deleteDocument, duplicateCollectionDocument, unpublishDocument, updateCollectionDocumentWithPatches, updateDocumentStatus } from "../../server-fns/collections/index.js";
6
8
  import { useNavigate } from "../chrome/loose-router.js";
7
9
  import { useTanStackNavigationGuard } from "./tanstack-navigation-guard.js";
8
10
  import { ViewMenu } from "./view-menu.js";
9
11
  const EditView = ({ collectionDefinition, adminConfig, initialData, locale, contentLocales, defaultContentLocale })=>{
10
12
  const toastManager = useToastManager();
13
+ const { t } = useTranslation('byline-admin');
11
14
  const [_editState, setEditState] = useState({
12
15
  status: 'idle',
13
16
  message: ''
14
17
  });
15
18
  const navigate = useNavigate();
16
19
  const { labels, path, fields } = collectionDefinition;
20
+ const singular = labels.singular;
21
+ const singularLower = singular.toLowerCase();
17
22
  const workflowStatuses = getWorkflowStatuses(collectionDefinition);
18
23
  const currentStatus = initialData?.status ?? getDefaultStatus(collectionDefinition);
19
24
  const currentIndex = workflowStatuses.findIndex((s)=>s.name === currentStatus);
@@ -39,9 +44,14 @@ const EditView = ({ collectionDefinition, adminConfig, initialData, locale, cont
39
44
  status
40
45
  }
41
46
  });
47
+ const description = t("collections.edit.statusChangedDescription", {
48
+ status
49
+ });
42
50
  toastManager.add({
43
- title: `${labels.singular} Status Update`,
44
- description: `Status changed to "${status}"`,
51
+ title: t('collections.edit.statusUpdateTitle', {
52
+ label: singular
53
+ }),
54
+ description,
45
55
  data: {
46
56
  intent: 'success',
47
57
  iconType: 'success',
@@ -51,7 +61,7 @@ const EditView = ({ collectionDefinition, adminConfig, initialData, locale, cont
51
61
  });
52
62
  setEditState({
53
63
  status: 'success',
54
- message: `Status changed to "${status}"`
64
+ message: description
55
65
  });
56
66
  navigate({
57
67
  to: '/admin/collections/$collection/$id',
@@ -65,9 +75,14 @@ const EditView = ({ collectionDefinition, adminConfig, initialData, locale, cont
65
75
  });
66
76
  } catch (err) {
67
77
  console.error('Status change error:', err);
78
+ const description = t("collections.edit.statusChangeFailedDescription", {
79
+ message: err.message
80
+ });
68
81
  toastManager.add({
69
- title: `${labels.singular} Status Update`,
70
- description: `Failed to change status: ${err.message}`,
82
+ title: t('collections.edit.statusUpdateTitle', {
83
+ label: singular
84
+ }),
85
+ description,
71
86
  data: {
72
87
  intent: 'danger',
73
88
  iconType: 'danger',
@@ -77,7 +92,7 @@ const EditView = ({ collectionDefinition, adminConfig, initialData, locale, cont
77
92
  });
78
93
  setEditState({
79
94
  status: 'failed',
80
- message: `Failed to change status: ${err.message}`
95
+ message: description
81
96
  });
82
97
  }
83
98
  };
@@ -91,9 +106,12 @@ const EditView = ({ collectionDefinition, adminConfig, initialData, locale, cont
91
106
  id: String(initialData.id)
92
107
  }
93
108
  });
109
+ const description = t("collections.edit.unpublishedDescription");
94
110
  toastManager.add({
95
- title: `${labels.singular} Unpublish`,
96
- description: 'Published version has been taken offline.',
111
+ title: t('collections.edit.unpublishTitle', {
112
+ label: singular
113
+ }),
114
+ description,
97
115
  data: {
98
116
  intent: 'success',
99
117
  iconType: 'success',
@@ -103,7 +121,7 @@ const EditView = ({ collectionDefinition, adminConfig, initialData, locale, cont
103
121
  });
104
122
  setEditState({
105
123
  status: 'success',
106
- message: 'Published version has been taken offline.'
124
+ message: description
107
125
  });
108
126
  navigate({
109
127
  to: '/admin/collections/$collection/$id',
@@ -117,9 +135,14 @@ const EditView = ({ collectionDefinition, adminConfig, initialData, locale, cont
117
135
  });
118
136
  } catch (err) {
119
137
  console.error('Unpublish error:', err);
138
+ const description = t("collections.edit.unpublishFailedDescription", {
139
+ message: err.message
140
+ });
120
141
  toastManager.add({
121
- title: `${labels.singular} Unpublish`,
122
- description: `Failed to unpublish: ${err.message}`,
142
+ title: t('collections.edit.unpublishTitle', {
143
+ label: singular
144
+ }),
145
+ description,
123
146
  data: {
124
147
  intent: 'danger',
125
148
  iconType: 'danger',
@@ -129,7 +152,7 @@ const EditView = ({ collectionDefinition, adminConfig, initialData, locale, cont
129
152
  });
130
153
  setEditState({
131
154
  status: 'failed',
132
- message: `Failed to unpublish: ${err.message}`
155
+ message: description
133
156
  });
134
157
  }
135
158
  };
@@ -141,9 +164,16 @@ const EditView = ({ collectionDefinition, adminConfig, initialData, locale, cont
141
164
  id: String(initialData.id)
142
165
  }
143
166
  });
167
+ const description = result.pathRetried ? t("collections.edit.duplicatedAutoPathDescription", {
168
+ path: result.newPath
169
+ }) : t("collections.edit.duplicatedPathDescription", {
170
+ path: result.newPath
171
+ });
144
172
  toastManager.add({
145
- title: `${labels.singular} Duplicated`,
146
- description: result.pathRetried ? `Created with auto-generated path "${result.newPath}" (the preferred slug was already in use).` : `Created with path "${result.newPath}". Update the title and path in the new document.`,
173
+ title: t('collections.edit.duplicatedTitle', {
174
+ label: singular
175
+ }),
176
+ description,
147
177
  data: {
148
178
  intent: 'success',
149
179
  iconType: 'success',
@@ -153,7 +183,9 @@ const EditView = ({ collectionDefinition, adminConfig, initialData, locale, cont
153
183
  });
154
184
  setEditState({
155
185
  status: 'success',
156
- message: `${labels.singular} duplicated.`
186
+ message: t('collections.edit.duplicatedSuccessMessage', {
187
+ label: singular
188
+ })
157
189
  });
158
190
  navigate({
159
191
  to: '/admin/collections/$collection/$id',
@@ -164,9 +196,14 @@ const EditView = ({ collectionDefinition, adminConfig, initialData, locale, cont
164
196
  });
165
197
  } catch (err) {
166
198
  console.error('Duplicate error:', err);
199
+ const description = t("collections.edit.duplicateFailedDescription", {
200
+ message: err.message
201
+ });
167
202
  toastManager.add({
168
- title: `${labels.singular} Duplicate`,
169
- description: `Failed to duplicate: ${err.message}`,
203
+ title: t('collections.edit.duplicateTitle', {
204
+ label: singular
205
+ }),
206
+ description,
170
207
  data: {
171
208
  intent: 'danger',
172
209
  iconType: 'danger',
@@ -176,7 +213,7 @@ const EditView = ({ collectionDefinition, adminConfig, initialData, locale, cont
176
213
  });
177
214
  setEditState({
178
215
  status: 'failed',
179
- message: `Failed to duplicate: ${err.message}`
216
+ message: description
180
217
  });
181
218
  }
182
219
  };
@@ -193,9 +230,19 @@ const EditView = ({ collectionDefinition, adminConfig, initialData, locale, cont
193
230
  });
194
231
  const sourceLabel = contentLocales.find((l)=>l.code === result.sourceLocale)?.label ?? result.sourceLocale;
195
232
  const targetLabel = contentLocales.find((l)=>l.code === result.targetLocale)?.label ?? result.targetLocale;
233
+ const description = result.fieldsUpdated > 0 ? t("collections.edit.copiedFieldsDescription", {
234
+ count: result.fieldsUpdated,
235
+ source: sourceLabel,
236
+ target: targetLabel
237
+ }) : t("collections.edit.copiedNoFieldsDescription", {
238
+ source: sourceLabel,
239
+ target: targetLabel
240
+ });
196
241
  toastManager.add({
197
- title: `${labels.singular} Copy to Locale`,
198
- description: result.fieldsUpdated > 0 ? `Copied ${result.fieldsUpdated} field${1 === result.fieldsUpdated ? '' : 's'} from ${sourceLabel} to ${targetLabel}.` : `No fields needed copying from ${sourceLabel} to ${targetLabel} under the current rule.`,
242
+ title: t('collections.edit.copyToLocaleTitle', {
243
+ label: singular
244
+ }),
245
+ description,
199
246
  data: {
200
247
  intent: 'success',
201
248
  iconType: 'success',
@@ -205,7 +252,10 @@ const EditView = ({ collectionDefinition, adminConfig, initialData, locale, cont
205
252
  });
206
253
  setEditState({
207
254
  status: 'success',
208
- message: `Copied ${sourceLabel} → ${targetLabel}.`
255
+ message: t('collections.edit.copiedSuccessMessage', {
256
+ source: sourceLabel,
257
+ target: targetLabel
258
+ })
209
259
  });
210
260
  navigate({
211
261
  to: '/admin/collections/$collection/$id',
@@ -219,9 +269,14 @@ const EditView = ({ collectionDefinition, adminConfig, initialData, locale, cont
219
269
  });
220
270
  } catch (err) {
221
271
  console.error('Copy to locale error:', err);
272
+ const description = t("collections.edit.copyFailedDescription", {
273
+ message: err.message
274
+ });
222
275
  toastManager.add({
223
- title: `${labels.singular} Copy to Locale`,
224
- description: `Failed to copy: ${err.message}`,
276
+ title: t('collections.edit.copyToLocaleTitle', {
277
+ label: singular
278
+ }),
279
+ description,
225
280
  data: {
226
281
  intent: 'danger',
227
282
  iconType: 'danger',
@@ -231,7 +286,7 @@ const EditView = ({ collectionDefinition, adminConfig, initialData, locale, cont
231
286
  });
232
287
  setEditState({
233
288
  status: 'failed',
234
- message: `Failed to copy: ${err.message}`
289
+ message: description
235
290
  });
236
291
  }
237
292
  };
@@ -243,9 +298,14 @@ const EditView = ({ collectionDefinition, adminConfig, initialData, locale, cont
243
298
  id: String(initialData.id)
244
299
  }
245
300
  });
301
+ const description = t("collections.edit.deletedDescription", {
302
+ label: singular
303
+ });
246
304
  toastManager.add({
247
- title: `${labels.singular} Deletion`,
248
- description: `${labels.singular} has been deleted.`,
305
+ title: t('collections.edit.deleteTitle', {
306
+ label: singular
307
+ }),
308
+ description,
249
309
  data: {
250
310
  intent: 'success',
251
311
  iconType: 'success',
@@ -255,7 +315,7 @@ const EditView = ({ collectionDefinition, adminConfig, initialData, locale, cont
255
315
  });
256
316
  setEditState({
257
317
  status: 'success',
258
- message: `${labels.singular} has been deleted.`
318
+ message: description
259
319
  });
260
320
  navigate({
261
321
  to: '/admin/collections/$collection',
@@ -265,9 +325,14 @@ const EditView = ({ collectionDefinition, adminConfig, initialData, locale, cont
265
325
  });
266
326
  } catch (err) {
267
327
  console.error('Delete error:', err);
328
+ const description = t("collections.edit.deleteFailedDescription", {
329
+ message: err.message
330
+ });
268
331
  toastManager.add({
269
- title: `${labels.singular} Deletion`,
270
- description: `Failed to delete: ${err.message}`,
332
+ title: t('collections.edit.deleteTitle', {
333
+ label: singular
334
+ }),
335
+ description,
271
336
  data: {
272
337
  intent: 'danger',
273
338
  iconType: 'danger',
@@ -277,7 +342,7 @@ const EditView = ({ collectionDefinition, adminConfig, initialData, locale, cont
277
342
  });
278
343
  setEditState({
279
344
  status: 'failed',
280
- message: `Failed to delete: ${err.message}`
345
+ message: description
281
346
  });
282
347
  }
283
348
  };
@@ -295,9 +360,14 @@ const EditView = ({ collectionDefinition, adminConfig, initialData, locale, cont
295
360
  } : {}
296
361
  }
297
362
  });
363
+ const description = t("collections.edit.updatedDescription", {
364
+ label: singularLower
365
+ });
298
366
  toastManager.add({
299
- title: `${labels.singular} Update`,
300
- description: `Successfully updated ${labels.singular.toLowerCase()}`,
367
+ title: t('collections.edit.updateTitle', {
368
+ label: singular
369
+ }),
370
+ description,
301
371
  data: {
302
372
  intent: 'success',
303
373
  iconType: 'success',
@@ -307,7 +377,7 @@ const EditView = ({ collectionDefinition, adminConfig, initialData, locale, cont
307
377
  });
308
378
  setEditState({
309
379
  status: 'success',
310
- message: `Successfully updated ${labels.singular.toLowerCase()}`
380
+ message: description
311
381
  });
312
382
  navigate({
313
383
  to: '/admin/collections/$collection/$id',
@@ -321,9 +391,14 @@ const EditView = ({ collectionDefinition, adminConfig, initialData, locale, cont
321
391
  });
322
392
  } catch (err) {
323
393
  console.error('Network error:', err);
394
+ const description = t("collections.edit.updateFailedDescription", {
395
+ label: singularLower
396
+ });
324
397
  toastManager.add({
325
- title: `${labels.singular} Update`,
326
- description: `An error occurred while updating ${labels.singular.toLowerCase()}`,
398
+ title: t('collections.edit.updateTitle', {
399
+ label: singular
400
+ }),
401
+ description,
327
402
  data: {
328
403
  intent: 'danger',
329
404
  iconType: 'danger',
@@ -333,7 +408,7 @@ const EditView = ({ collectionDefinition, adminConfig, initialData, locale, cont
333
408
  });
334
409
  setEditState({
335
410
  status: 'failed',
336
- message: `An error occurred while updating ${labels.singular.toLowerCase()}`
411
+ message: description
337
412
  });
338
413
  }
339
414
  };
@@ -1,8 +1,10 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { Suspense, lazy, useState } from "react";
3
3
  import { useParams, useRouterState } from "@tanstack/react-router";
4
+ import { StatusBadge, renderFormatted } from "@byline/admin/react";
4
5
  import { useBylineAdminServices } from "@byline/admin/services";
5
- import { Button, CloseIcon, Container, IconButton, Modal, Section, Select, StatusBadge, Table, renderFormatted } from "@byline/ui/react";
6
+ import { useTranslation } from "@byline/i18n/react";
7
+ import { Button, CloseIcon, Container, IconButton, Modal, Section, Select, Table } from "@byline/ui/react";
6
8
  import classnames from "classnames";
7
9
  import { Link, useNavigate } from "../chrome/loose-router.js";
8
10
  import { RouterPager } from "../chrome/router-pager.js";
@@ -15,7 +17,7 @@ function getColumnValue(document, fieldName) {
15
17
  if (document.fields && fieldName in document.fields) return document.fields[fieldName];
16
18
  return document[fieldName];
17
19
  }
18
- const DiffModal = /*#__PURE__*/ lazy(()=>import("@byline/ui/react").then((m)=>({
20
+ const DiffModal = /*#__PURE__*/ lazy(()=>import("@byline/admin/react").then((m)=>({
19
21
  default: m.DiffModal
20
22
  })));
21
23
  function resolveDisplayValue(value, locale, defaultContentLocale) {
@@ -47,6 +49,7 @@ const HistoryView = ({ collectionDefinition, adminConfig, data, workflowStatuses
47
49
  });
48
50
  const navigate = useNavigate();
49
51
  const { getCollectionDocumentVersion } = useBylineAdminServices();
52
+ const { t } = useTranslation('byline-admin');
50
53
  const columns = adminConfig?.columns || [];
51
54
  const { labels } = collectionDefinition;
52
55
  const location = useRouterState({
@@ -79,8 +82,10 @@ const HistoryView = ({ collectionDefinition, adminConfig, data, workflowStatuses
79
82
  /*#__PURE__*/ jsxs("h2", {
80
83
  className: classnames('byline-coll-history-title', history_module.title),
81
84
  children: [
82
- labels.singular,
83
- " History ",
85
+ t('collections.history.title', {
86
+ label: labels.singular
87
+ }),
88
+ ' ',
84
89
  /*#__PURE__*/ jsx(Stats, {
85
90
  total: data?.meta.total
86
91
  })
@@ -109,7 +114,7 @@ const HistoryView = ({ collectionDefinition, adminConfig, data, workflowStatuses
109
114
  showFirstButton: true,
110
115
  showLastButton: true,
111
116
  componentName: "pagerTop",
112
- "aria-label": "Top Pager"
117
+ "aria-label": t('collections.list.pagerTopAriaLabel')
113
118
  })
114
119
  }),
115
120
  /*#__PURE__*/ jsxs(Table.Container, {
@@ -160,8 +165,8 @@ const HistoryView = ({ collectionDefinition, adminConfig, data, workflowStatuses
160
165
  size: "xs",
161
166
  variant: "outlined",
162
167
  intent: "noeffect",
163
- "aria-label": "Compare this version with the current version",
164
- title: "Compare with current",
168
+ "aria-label": t('collections.history.compareAriaLabel'),
169
+ title: t('collections.history.compareTitle'),
165
170
  className: classnames('byline-coll-history-version-button', history_module.versionButton),
166
171
  onClick: ()=>setSelectedVersion({
167
172
  versionId,
@@ -213,8 +218,8 @@ const HistoryView = ({ collectionDefinition, adminConfig, data, workflowStatuses
213
218
  versionNumber
214
219
  }),
215
220
  className: classnames('byline-coll-history-restore-button', history_module.restoreButton),
216
- title: "Restore this version as the current draft",
217
- children: "Restore"
221
+ title: t('collections.history.restoreButtonTitle'),
222
+ children: t('collections.history.restoreButton')
218
223
  }) : null
219
224
  }, "__restore")
220
225
  ];
@@ -267,7 +272,7 @@ const HistoryView = ({ collectionDefinition, adminConfig, data, workflowStatuses
267
272
  showFirstButton: true,
268
273
  showLastButton: true,
269
274
  componentName: "pagerBottom",
270
- "aria-label": "Bottom Pager"
275
+ "aria-label": t('collections.list.pagerBottomAriaLabel')
271
276
  })
272
277
  ]
273
278
  })
@@ -300,10 +305,10 @@ const HistoryView = ({ collectionDefinition, adminConfig, data, workflowStatuses
300
305
  children: [
301
306
  /*#__PURE__*/ jsx("h3", {
302
307
  className: "m-0",
303
- children: "Restore version"
308
+ children: t('collections.history.restoreModalTitle')
304
309
  }),
305
310
  /*#__PURE__*/ jsx(IconButton, {
306
- "aria-label": "Close",
311
+ "aria-label": t('common.actions.close'),
307
312
  size: "xs",
308
313
  onClick: ()=>setRestoreTarget(null),
309
314
  children: /*#__PURE__*/ jsx(CloseIcon, {
@@ -1,7 +1,9 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useMemo, useState } from "react";
3
3
  import { useRouter, useRouterState } from "@tanstack/react-router";
4
- import { Container, GripperVerticalIcon, IconButton, LoaderRing, PlusIcon, Search, Section, Select, StatusBadge, Table, renderFormatted, useToastManager } from "@byline/ui/react";
4
+ import { StatusBadge, renderFormatted } from "@byline/admin/react";
5
+ import { useTranslation } from "@byline/i18n/react";
6
+ import { Container, GripperVerticalIcon, IconButton, LoaderRing, PlusIcon, Search, Section, Select, Table, useToastManager } from "@byline/ui/react";
5
7
  import { DndContext, KeyboardSensor, PointerSensor, useSensor, useSensors } from "@dnd-kit/core";
6
8
  import { SortableContext, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy } from "@dnd-kit/sortable";
7
9
  import classnames from "classnames";
@@ -35,7 +37,7 @@ function padRows(value) {
35
37
  children: "\xa0"
36
38
  }, `empty-row-${index}`));
37
39
  }
38
- function SortableTableRow({ id, disabled, children }) {
40
+ function SortableTableRow({ id, disabled, t, children }) {
39
41
  const { setNodeRef, attributes, listeners, transform, transition, isDragging } = useSortable({
40
42
  id,
41
43
  disabled
@@ -57,7 +59,7 @@ function SortableTableRow({ id, disabled, children }) {
57
59
  children: /*#__PURE__*/ jsx("button", {
58
60
  type: "button",
59
61
  className: classnames('byline-coll-list-drag-handle', list_module.dragHandle),
60
- "aria-label": disabled ? 'Drag disabled while filters or search are active' : 'Drag to reorder',
62
+ "aria-label": disabled ? t('collections.list.dragDisabledAriaLabel') : t('collections.list.dragHandleAriaLabel'),
61
63
  disabled: disabled,
62
64
  ...attributes,
63
65
  ...listeners,
@@ -72,6 +74,7 @@ const ListView = ({ data, columns, workflowStatuses, useAsTitle, orderable = fal
72
74
  const navigate = useNavigate();
73
75
  const router = useRouter();
74
76
  const toastManager = useToastManager();
77
+ const { t } = useTranslation('byline-admin');
75
78
  const location = useRouterState({
76
79
  select: (s)=>s.location
77
80
  });
@@ -120,8 +123,8 @@ const ListView = ({ data, columns, workflowStatuses, useAsTitle, orderable = fal
120
123
  } catch (_err) {
121
124
  setLocalDocs(previousDocs);
122
125
  toastManager.add({
123
- title: 'Could not save the new order',
124
- description: 'Please try again.',
126
+ title: t('collections.list.reorderFailedToast'),
127
+ description: t("collections.list.reorderFailedDescription"),
125
128
  data: {
126
129
  intent: 'danger',
127
130
  iconType: 'danger',
@@ -136,14 +139,15 @@ const ListView = ({ data, columns, workflowStatuses, useAsTitle, orderable = fal
136
139
  const statusItems = useMemo(()=>[
137
140
  {
138
141
  value: '_all',
139
- label: 'All'
142
+ label: t('collections.list.statusFilterAll')
140
143
  },
141
144
  ...workflowStatuses?.map((ws)=>({
142
145
  value: ws.name,
143
146
  label: ws.label ?? ws.name
144
147
  })) ?? []
145
148
  ], [
146
- workflowStatuses
149
+ workflowStatuses,
150
+ t
147
151
  ]);
148
152
  const handleOnSearch = (query)=>{
149
153
  if (null != query && query.length > 0) {
@@ -212,7 +216,7 @@ const ListView = ({ data, columns, workflowStatuses, useAsTitle, orderable = fal
212
216
  total: data?.meta.total
213
217
  }),
214
218
  /*#__PURE__*/ jsx(IconButton, {
215
- "aria-label": "Create New",
219
+ "aria-label": t('collections.list.createAriaLabel'),
216
220
  render: /*#__PURE__*/ jsx(Link, {
217
221
  to: '/admin/collections/$collection/create',
218
222
  params: {
@@ -234,7 +238,7 @@ const ListView = ({ data, columns, workflowStatuses, useAsTitle, orderable = fal
234
238
  onSearch: handleOnSearch,
235
239
  onClear: handleOnClear,
236
240
  inputSize: "sm",
237
- placeholder: "Search",
241
+ placeholder: t('collections.list.searchPlaceholder'),
238
242
  className: classnames('byline-coll-list-search', list_module.search)
239
243
  }),
240
244
  workflowStatuses && workflowStatuses.length > 1 && /*#__PURE__*/ jsx(Select, {
@@ -251,7 +255,7 @@ const ListView = ({ data, columns, workflowStatuses, useAsTitle, orderable = fal
251
255
  showFirstButton: true,
252
256
  showLastButton: true,
253
257
  componentName: "pagerTop",
254
- "aria-label": "Top Pager"
258
+ "aria-label": t('collections.list.pagerTopAriaLabel')
255
259
  })
256
260
  ]
257
261
  }),
@@ -288,8 +292,8 @@ const ListView = ({ data, columns, workflowStatuses, useAsTitle, orderable = fal
288
292
  search: params
289
293
  });
290
294
  },
291
- "aria-label": "Sort by manual order",
292
- title: "Sort by manual order",
295
+ "aria-label": t('collections.list.sortManualOrderAriaLabel'),
296
+ title: t('collections.list.sortManualOrderAriaLabel'),
293
297
  children: /*#__PURE__*/ jsx(SortAscendingIcon, {})
294
298
  })
295
299
  }),
@@ -308,6 +312,7 @@ const ListView = ({ data, columns, workflowStatuses, useAsTitle, orderable = fal
308
312
  children: localDocs.map((document)=>/*#__PURE__*/ jsx(SortableTableRow, {
309
313
  id: document.id,
310
314
  disabled: !dragEnabled,
315
+ t: t,
311
316
  children: columns.map((column)=>/*#__PURE__*/ jsx(Table.Cell, {
312
317
  className: classnames({
313
318
  'byline-coll-list-cell-right': 'right' === column.align,
@@ -412,7 +417,7 @@ const ListView = ({ data, columns, workflowStatuses, useAsTitle, orderable = fal
412
417
  showFirstButton: true,
413
418
  showLastButton: true,
414
419
  componentName: "pagerBottom",
415
- "aria-label": "Bottom Pager"
420
+ "aria-label": t('collections.list.pagerBottomAriaLabel')
416
421
  })
417
422
  ]
418
423
  })
@@ -6,6 +6,7 @@
6
6
  * Copyright (c) Infonomic Company Limited
7
7
  */
8
8
  import type { CollectionAdminConfig, PreviewDocument } from '@byline/core';
9
+ export { resolvePreviewUrl } from './resolve-preview-url.js';
9
10
  export interface PreviewLinkProps {
10
11
  /** Collection path (e.g. `'news'`, `'pages'`). */
11
12
  collectionPath: string;
@@ -18,14 +19,4 @@ export interface PreviewLinkProps {
18
19
  /** Optional className for the IconButton. */
19
20
  className?: string;
20
21
  }
21
- /**
22
- * Resolve the preview URL for a doc against an admin config. Exported so
23
- * other surfaces (list-row preview links in the future) can share the
24
- * same fallback logic.
25
- *
26
- * Returns:
27
- * - `string` → URL to open
28
- * - `null` → no preview URL meaningful for this doc; hide affordance
29
- */
30
- export declare function resolvePreviewUrl(doc: PreviewDocument, collectionPath: string, adminConfig: CollectionAdminConfig | undefined, locale: string | undefined): string | null;
31
22
  export declare const PreviewLink: ({ collectionPath, doc, adminConfig, locale, className, }: PreviewLinkProps) => import("react").JSX.Element | null;
@@ -1,17 +1,13 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import { useState } from "react";
3
+ import { useTranslation } from "@byline/i18n/react";
3
4
  import { ExternalLinkIcon, IconButton, useToastManager } from "@byline/ui/react";
4
5
  import classnames from "classnames";
5
6
  import { enablePreviewModeFn } from "../../server-fns/preview/index.js";
6
- function resolvePreviewUrl(doc, collectionPath, adminConfig, locale) {
7
- if (adminConfig?.preview) return adminConfig.preview.url(doc, {
8
- locale
9
- });
10
- if (!doc.path) return null;
11
- return `/${collectionPath}/${doc.path}`;
12
- }
7
+ import { resolvePreviewUrl } from "./resolve-preview-url.js";
13
8
  const PreviewLink = ({ collectionPath, doc, adminConfig, locale, className })=>{
14
9
  const toastManager = useToastManager();
10
+ const { t } = useTranslation('byline-admin');
15
11
  const [busy, setBusy] = useState(false);
16
12
  const url = resolvePreviewUrl(doc, collectionPath, adminConfig, locale);
17
13
  if (null == url) return null;
@@ -23,8 +19,10 @@ const PreviewLink = ({ collectionPath, doc, adminConfig, locale, className })=>{
23
19
  window.location.assign(url);
24
20
  } catch (err) {
25
21
  toastManager.add({
26
- title: 'Preview',
27
- description: `Could not enable preview mode: ${err.message}`,
22
+ title: t('collections.preview.toastTitle'),
23
+ description: t("collections.preview.failedDescription", {
24
+ message: err.message
25
+ }),
28
26
  data: {
29
27
  intent: 'danger',
30
28
  iconType: 'danger',
@@ -42,8 +40,8 @@ const PreviewLink = ({ collectionPath, doc, adminConfig, locale, className })=>{
42
40
  variant: "text",
43
41
  disabled: busy,
44
42
  onClick: handleClick,
45
- "aria-label": "Open preview",
46
- title: "Preview",
43
+ "aria-label": t('collections.preview.openAriaLabel'),
44
+ title: t('collections.preview.title'),
47
45
  children: /*#__PURE__*/ jsx(ExternalLinkIcon, {
48
46
  width: "20px",
49
47
  height: "20px",
@@ -0,0 +1,34 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+ /**
9
+ * Pure (no React, no DOM) resolver for the admin Preview button's URL.
10
+ * Lives in its own module so it can be unit-tested without dragging the
11
+ * React UI graph of `preview-link.tsx` into a node-mode test run.
12
+ */
13
+ import { type CollectionAdminConfig, type PreviewDocument } from '@byline/core';
14
+ /**
15
+ * Resolve the preview URL for a doc against an admin config. Exported so
16
+ * other surfaces (list-row preview links in the future) can share the
17
+ * same fallback logic.
18
+ *
19
+ * Cascade:
20
+ * 1. `adminConfig.preview.url(doc, { locale })` — wins outright when
21
+ * configured. The host can do anything (locale prefix, query
22
+ * string, conditional return-null).
23
+ * 2. `CollectionDefinition.buildDocumentPath(doc, { collectionPath })`
24
+ * — the schema-side hook the richtext embed walker also reads.
25
+ * Locale-agnostic by contract; hosts that need a locale prefix
26
+ * keep their own `preview.url`.
27
+ * 3. Generic compose `/${collectionPath}/${doc.path}` — last-resort
28
+ * convention for collections with no schema-side hook.
29
+ *
30
+ * Returns:
31
+ * - `string` → URL to open
32
+ * - `null` → no preview URL meaningful for this doc; hide affordance
33
+ */
34
+ export declare function resolvePreviewUrl(doc: PreviewDocument, collectionPath: string, adminConfig: CollectionAdminConfig | undefined, locale: string | undefined): string | null;