@ketvietlab/ketsuite 0.1.3 → 0.1.6

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 (359) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/deployment.d.ts.map +1 -1
  3. package/dist/deployment.js +3 -0
  4. package/dist/deployment.js.map +1 -1
  5. package/dist/index.d.ts +8 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +7 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/modules/account_staff_channel/channel-routes.d.ts.map +1 -1
  10. package/dist/modules/account_staff_channel/channel-routes.js +1 -12
  11. package/dist/modules/account_staff_channel/channel-routes.js.map +1 -1
  12. package/dist/modules/attendance/channel-routes.d.ts.map +1 -1
  13. package/dist/modules/attendance/channel-routes.js +1 -12
  14. package/dist/modules/attendance/channel-routes.js.map +1 -1
  15. package/dist/modules/backend/design/HANDOFF.md +2 -2
  16. package/dist/modules/backend/design/auth.css +12 -0
  17. package/dist/modules/backend/design/client/table-selection.d.mts +3 -3
  18. package/dist/modules/backend/design/client/table-selection.d.mts.map +1 -1
  19. package/dist/modules/backend/design/client/table-selection.mjs +1 -1
  20. package/dist/modules/backend/design/client/table-selection.mjs.map +4 -4
  21. package/dist/modules/backend/design/content.css +43 -0
  22. package/dist/modules/backend/design/design-system.css +1 -1
  23. package/dist/modules/backend/design/forms.css +84 -1
  24. package/dist/modules/backend/design/lists.css +26 -18
  25. package/dist/modules/backend/design/record.css +5 -2
  26. package/dist/modules/backend/design/responsive.css +5 -6
  27. package/dist/modules/backend/design/user-workflow.css +257 -0
  28. package/dist/modules/backend/forms.d.ts +38 -1
  29. package/dist/modules/backend/forms.d.ts.map +1 -1
  30. package/dist/modules/backend/forms.js +29 -0
  31. package/dist/modules/backend/forms.js.map +1 -1
  32. package/dist/modules/backend/index.d.ts +3 -2
  33. package/dist/modules/backend/index.d.ts.map +1 -1
  34. package/dist/modules/backend/index.js +3 -2
  35. package/dist/modules/backend/index.js.map +1 -1
  36. package/dist/modules/backend/messages.d.ts.map +1 -1
  37. package/dist/modules/backend/messages.js +42 -2
  38. package/dist/modules/backend/messages.js.map +1 -1
  39. package/dist/modules/channel_api/core.d.ts +30 -0
  40. package/dist/modules/channel_api/core.d.ts.map +1 -1
  41. package/dist/modules/channel_api/core.js +28 -0
  42. package/dist/modules/channel_api/core.js.map +1 -1
  43. package/dist/modules/crm/functions.d.ts +5 -0
  44. package/dist/modules/crm/functions.d.ts.map +1 -1
  45. package/dist/modules/crm/functions.js +105 -10
  46. package/dist/modules/crm/functions.js.map +1 -1
  47. package/dist/modules/crm/jobs.d.ts.map +1 -1
  48. package/dist/modules/crm/jobs.js +1 -0
  49. package/dist/modules/crm/jobs.js.map +1 -1
  50. package/dist/modules/crm/operations.d.ts.map +1 -1
  51. package/dist/modules/crm/operations.js +2 -1
  52. package/dist/modules/crm/operations.js.map +1 -1
  53. package/dist/modules/crm_backend/index.d.ts.map +1 -1
  54. package/dist/modules/crm_backend/index.js +5 -2
  55. package/dist/modules/crm_backend/index.js.map +1 -1
  56. package/dist/modules/crm_backend/messages.d.ts +116 -0
  57. package/dist/modules/crm_backend/messages.d.ts.map +1 -1
  58. package/dist/modules/crm_backend/messages.js +122 -6
  59. package/dist/modules/crm_backend/messages.js.map +1 -1
  60. package/dist/modules/crm_backend/routes.d.ts.map +1 -1
  61. package/dist/modules/crm_backend/routes.js +434 -174
  62. package/dist/modules/crm_backend/routes.js.map +1 -1
  63. package/dist/modules/crm_backend/screens/case-create.d.ts +7 -0
  64. package/dist/modules/crm_backend/screens/case-create.d.ts.map +1 -1
  65. package/dist/modules/crm_backend/screens/case-create.js +13 -4
  66. package/dist/modules/crm_backend/screens/case-create.js.map +1 -1
  67. package/dist/modules/crm_backend/screens/case-detail.d.ts +6 -0
  68. package/dist/modules/crm_backend/screens/case-detail.d.ts.map +1 -1
  69. package/dist/modules/crm_backend/screens/case-detail.js +73 -23
  70. package/dist/modules/crm_backend/screens/case-detail.js.map +1 -1
  71. package/dist/modules/crm_backend/screens/configuration.d.ts +21 -3
  72. package/dist/modules/crm_backend/screens/configuration.d.ts.map +1 -1
  73. package/dist/modules/crm_backend/screens/configuration.js +260 -55
  74. package/dist/modules/crm_backend/screens/configuration.js.map +1 -1
  75. package/dist/modules/crm_backend/screens/index.d.ts +3 -3
  76. package/dist/modules/crm_backend/screens/index.d.ts.map +1 -1
  77. package/dist/modules/crm_backend/screens/index.js +2 -2
  78. package/dist/modules/crm_backend/screens/index.js.map +1 -1
  79. package/dist/modules/crm_staff_channel/channel-routes.d.ts.map +1 -1
  80. package/dist/modules/crm_staff_channel/channel-routes.js +1 -12
  81. package/dist/modules/crm_staff_channel/channel-routes.js.map +1 -1
  82. package/dist/modules/flow/membership.d.ts.map +1 -1
  83. package/dist/modules/flow/membership.js +7 -1
  84. package/dist/modules/flow/membership.js.map +1 -1
  85. package/dist/modules/flow/operations.d.ts +10 -4
  86. package/dist/modules/flow/operations.d.ts.map +1 -1
  87. package/dist/modules/flow/operations.js +10 -4
  88. package/dist/modules/flow/operations.js.map +1 -1
  89. package/dist/modules/flow_staff_channel/channel-routes.d.ts.map +1 -1
  90. package/dist/modules/flow_staff_channel/channel-routes.js +1 -20
  91. package/dist/modules/flow_staff_channel/channel-routes.js.map +1 -1
  92. package/dist/modules/hospitality_core/messages.d.ts.map +1 -1
  93. package/dist/modules/hospitality_core/messages.js +44 -0
  94. package/dist/modules/hospitality_core/messages.js.map +1 -1
  95. package/dist/modules/hospitality_core/night-audit.d.ts.map +1 -1
  96. package/dist/modules/hospitality_core/night-audit.js +7 -0
  97. package/dist/modules/hospitality_core/night-audit.js.map +1 -1
  98. package/dist/modules/hospitality_core/operations.d.ts.map +1 -1
  99. package/dist/modules/hospitality_core/operations.js +150 -40
  100. package/dist/modules/hospitality_core/operations.js.map +1 -1
  101. package/dist/modules/hospitality_core/routes.d.ts.map +1 -1
  102. package/dist/modules/hospitality_core/routes.js +24 -2
  103. package/dist/modules/hospitality_core/routes.js.map +1 -1
  104. package/dist/modules/hospitality_core/screens/check-out-prep.d.ts +46 -0
  105. package/dist/modules/hospitality_core/screens/check-out-prep.d.ts.map +1 -0
  106. package/dist/modules/hospitality_core/screens/check-out-prep.js +133 -0
  107. package/dist/modules/hospitality_core/screens/check-out-prep.js.map +1 -0
  108. package/dist/modules/hospitality_core/screens/folio-detail.d.ts.map +1 -1
  109. package/dist/modules/hospitality_core/screens/folio-detail.js +2 -4
  110. package/dist/modules/hospitality_core/screens/folio-detail.js.map +1 -1
  111. package/dist/modules/hospitality_core/screens/index.d.ts +2 -0
  112. package/dist/modules/hospitality_core/screens/index.d.ts.map +1 -1
  113. package/dist/modules/hospitality_core/screens/index.js +1 -0
  114. package/dist/modules/hospitality_core/screens/index.js.map +1 -1
  115. package/dist/modules/hospitality_core/screens/reservation-detail.d.ts.map +1 -1
  116. package/dist/modules/hospitality_core/screens/reservation-detail.js +8 -1
  117. package/dist/modules/hospitality_core/screens/reservation-detail.js.map +1 -1
  118. package/dist/modules/hospitality_core/screens/shared.d.ts +12 -0
  119. package/dist/modules/hospitality_core/screens/shared.d.ts.map +1 -1
  120. package/dist/modules/hospitality_core/screens/shared.js +25 -4
  121. package/dist/modules/hospitality_core/screens/shared.js.map +1 -1
  122. package/dist/modules/hospitality_core/services.d.ts +48 -0
  123. package/dist/modules/hospitality_core/services.d.ts.map +1 -1
  124. package/dist/modules/hospitality_core/services.js +70 -0
  125. package/dist/modules/hospitality_core/services.js.map +1 -1
  126. package/dist/modules/hospitality_staff_channel/channel-routes.d.ts.map +1 -1
  127. package/dist/modules/hospitality_staff_channel/channel-routes.js +1 -12
  128. package/dist/modules/hospitality_staff_channel/channel-routes.js.map +1 -1
  129. package/dist/modules/inventory_staff_channel/channel-routes.d.ts.map +1 -1
  130. package/dist/modules/inventory_staff_channel/channel-routes.js +1 -12
  131. package/dist/modules/inventory_staff_channel/channel-routes.js.map +1 -1
  132. package/dist/modules/loyalty/admin-functions.d.ts +2 -0
  133. package/dist/modules/loyalty/admin-functions.d.ts.map +1 -1
  134. package/dist/modules/loyalty/admin-functions.js +96 -20
  135. package/dist/modules/loyalty/admin-functions.js.map +1 -1
  136. package/dist/modules/loyalty/engine.d.ts +4 -1
  137. package/dist/modules/loyalty/engine.d.ts.map +1 -1
  138. package/dist/modules/loyalty/engine.js +125 -18
  139. package/dist/modules/loyalty/engine.js.map +1 -1
  140. package/dist/modules/loyalty/index.d.ts.map +1 -1
  141. package/dist/modules/loyalty/index.js +4 -3
  142. package/dist/modules/loyalty/index.js.map +1 -1
  143. package/dist/modules/loyalty/jobs.d.ts.map +1 -1
  144. package/dist/modules/loyalty/jobs.js +0 -1
  145. package/dist/modules/loyalty/jobs.js.map +1 -1
  146. package/dist/modules/loyalty/membership-functions.d.ts +5 -0
  147. package/dist/modules/loyalty/membership-functions.d.ts.map +1 -1
  148. package/dist/modules/loyalty/membership-functions.js +37 -23
  149. package/dist/modules/loyalty/membership-functions.js.map +1 -1
  150. package/dist/modules/loyalty/messages.d.ts +14 -0
  151. package/dist/modules/loyalty/messages.d.ts.map +1 -1
  152. package/dist/modules/loyalty/messages.js +14 -0
  153. package/dist/modules/loyalty/messages.js.map +1 -1
  154. package/dist/modules/loyalty/models.d.ts.map +1 -1
  155. package/dist/modules/loyalty/models.js +17 -0
  156. package/dist/modules/loyalty/models.js.map +1 -1
  157. package/dist/modules/loyalty/order-functions.d.ts.map +1 -1
  158. package/dist/modules/loyalty/order-functions.js +70 -17
  159. package/dist/modules/loyalty/order-functions.js.map +1 -1
  160. package/dist/modules/loyalty/program-design.d.ts +11 -0
  161. package/dist/modules/loyalty/program-design.d.ts.map +1 -0
  162. package/dist/modules/loyalty/program-design.js +356 -0
  163. package/dist/modules/loyalty/program-design.js.map +1 -0
  164. package/dist/modules/loyalty/stats.d.ts +0 -13
  165. package/dist/modules/loyalty/stats.d.ts.map +1 -1
  166. package/dist/modules/loyalty/stats.js +11 -6
  167. package/dist/modules/loyalty/stats.js.map +1 -1
  168. package/dist/modules/loyalty/stored-value.d.ts.map +1 -1
  169. package/dist/modules/loyalty/stored-value.js +7 -2
  170. package/dist/modules/loyalty/stored-value.js.map +1 -1
  171. package/dist/modules/loyalty/types.d.ts +1 -1
  172. package/dist/modules/loyalty/types.d.ts.map +1 -1
  173. package/dist/modules/loyalty_backend/design-messages.d.ts +221 -0
  174. package/dist/modules/loyalty_backend/design-messages.d.ts.map +1 -0
  175. package/dist/modules/loyalty_backend/design-messages.js +221 -0
  176. package/dist/modules/loyalty_backend/design-messages.js.map +1 -0
  177. package/dist/modules/loyalty_backend/index.js +224 -412
  178. package/dist/modules/loyalty_backend/index.js.map +1 -1
  179. package/dist/modules/loyalty_backend/messages.d.ts +642 -214
  180. package/dist/modules/loyalty_backend/messages.d.ts.map +1 -1
  181. package/dist/modules/loyalty_backend/messages.js +19 -13
  182. package/dist/modules/loyalty_backend/messages.js.map +1 -1
  183. package/dist/modules/loyalty_backend/program-workspace.d.ts +4 -0
  184. package/dist/modules/loyalty_backend/program-workspace.d.ts.map +1 -0
  185. package/dist/modules/loyalty_backend/program-workspace.js +600 -0
  186. package/dist/modules/loyalty_backend/program-workspace.js.map +1 -0
  187. package/dist/modules/loyalty_backend/screens/index.d.ts +12 -36
  188. package/dist/modules/loyalty_backend/screens/index.d.ts.map +1 -1
  189. package/dist/modules/loyalty_backend/screens/index.js +148 -292
  190. package/dist/modules/loyalty_backend/screens/index.js.map +1 -1
  191. package/dist/modules/loyalty_backend/screens/page-frame.d.ts.map +1 -1
  192. package/dist/modules/loyalty_backend/screens/page-frame.js +2 -2
  193. package/dist/modules/loyalty_backend/screens/page-frame.js.map +1 -1
  194. package/dist/modules/loyalty_pos/functions.d.ts.map +1 -1
  195. package/dist/modules/loyalty_pos/functions.js +1 -0
  196. package/dist/modules/loyalty_pos/functions.js.map +1 -1
  197. package/dist/modules/loyalty_pos/index.js +1 -1
  198. package/dist/modules/loyalty_pos/index.js.map +1 -1
  199. package/dist/modules/loyalty_sale/functions.d.ts +1 -0
  200. package/dist/modules/loyalty_sale/functions.d.ts.map +1 -1
  201. package/dist/modules/loyalty_sale/functions.js +1 -0
  202. package/dist/modules/loyalty_sale/functions.js.map +1 -1
  203. package/dist/modules/partner_backend/client/partner.css +3 -1
  204. package/dist/modules/partner_backend/index.d.ts.map +1 -1
  205. package/dist/modules/partner_backend/index.js +4 -0
  206. package/dist/modules/partner_backend/index.js.map +1 -1
  207. package/dist/modules/partner_backend/routes.d.ts.map +1 -1
  208. package/dist/modules/partner_backend/routes.js +6 -1
  209. package/dist/modules/partner_backend/routes.js.map +1 -1
  210. package/dist/modules/partner_backend/screens/form.d.ts +1 -0
  211. package/dist/modules/partner_backend/screens/form.d.ts.map +1 -1
  212. package/dist/modules/partner_backend/screens/form.js +1 -0
  213. package/dist/modules/partner_backend/screens/form.js.map +1 -1
  214. package/dist/modules/purchase_staff_channel/order-routes.d.ts.map +1 -1
  215. package/dist/modules/purchase_staff_channel/order-routes.js +1 -12
  216. package/dist/modules/purchase_staff_channel/order-routes.js.map +1 -1
  217. package/dist/modules/quality_staff_channel/channel-routes.d.ts.map +1 -1
  218. package/dist/modules/quality_staff_channel/channel-routes.js +1 -12
  219. package/dist/modules/quality_staff_channel/channel-routes.js.map +1 -1
  220. package/dist/modules/sale/functions.d.ts.map +1 -1
  221. package/dist/modules/sale/functions.js +27 -17
  222. package/dist/modules/sale/functions.js.map +1 -1
  223. package/dist/modules/sale_staff_channel/channel-routes.d.ts.map +1 -1
  224. package/dist/modules/sale_staff_channel/channel-routes.js +1 -12
  225. package/dist/modules/sale_staff_channel/channel-routes.js.map +1 -1
  226. package/dist/modules/sale_staff_channel/order-routes.d.ts.map +1 -1
  227. package/dist/modules/sale_staff_channel/order-routes.js +1 -12
  228. package/dist/modules/sale_staff_channel/order-routes.js.map +1 -1
  229. package/dist/modules/stock_staff_channel/operation-routes.d.ts.map +1 -1
  230. package/dist/modules/stock_staff_channel/operation-routes.js +1 -12
  231. package/dist/modules/stock_staff_channel/operation-routes.js.map +1 -1
  232. package/dist/modules/user/authorization.d.ts +64 -1
  233. package/dist/modules/user/authorization.d.ts.map +1 -1
  234. package/dist/modules/user/authorization.js +445 -53
  235. package/dist/modules/user/authorization.js.map +1 -1
  236. package/dist/modules/user/functions.d.ts.map +1 -1
  237. package/dist/modules/user/functions.js +45 -23
  238. package/dist/modules/user/functions.js.map +1 -1
  239. package/dist/modules/user/index.d.ts +2 -1
  240. package/dist/modules/user/index.d.ts.map +1 -1
  241. package/dist/modules/user/index.js +1 -1
  242. package/dist/modules/user/index.js.map +1 -1
  243. package/dist/modules/user/models.d.ts.map +1 -1
  244. package/dist/modules/user/models.js +5 -0
  245. package/dist/modules/user/models.js.map +1 -1
  246. package/dist/modules/user/roles.d.ts.map +1 -1
  247. package/dist/modules/user/roles.js +2 -1
  248. package/dist/modules/user/roles.js.map +1 -1
  249. package/dist/modules/user_backend/access-routes.d.ts +31 -0
  250. package/dist/modules/user_backend/access-routes.d.ts.map +1 -0
  251. package/dist/modules/user_backend/access-routes.js +447 -0
  252. package/dist/modules/user_backend/access-routes.js.map +1 -0
  253. package/dist/modules/user_backend/index.d.ts +1 -0
  254. package/dist/modules/user_backend/index.d.ts.map +1 -1
  255. package/dist/modules/user_backend/index.js +1 -0
  256. package/dist/modules/user_backend/index.js.map +1 -1
  257. package/dist/modules/user_backend/messages.d.ts +4 -0
  258. package/dist/modules/user_backend/messages.d.ts.map +1 -1
  259. package/dist/modules/user_backend/messages.js +4 -0
  260. package/dist/modules/user_backend/messages.js.map +1 -1
  261. package/dist/modules/user_backend/routes.d.ts.map +1 -1
  262. package/dist/modules/user_backend/routes.js +38 -3
  263. package/dist/modules/user_backend/routes.js.map +1 -1
  264. package/dist/modules/user_backend/screens/user-form.d.ts +1 -0
  265. package/dist/modules/user_backend/screens/user-form.d.ts.map +1 -1
  266. package/dist/modules/user_backend/screens/user-form.js +28 -0
  267. package/dist/modules/user_backend/screens/user-form.js.map +1 -1
  268. package/dist/modules/website/cms.d.ts.map +1 -1
  269. package/dist/modules/website/cms.js +283 -6
  270. package/dist/modules/website/cms.js.map +1 -1
  271. package/dist/modules/website/index.d.ts.map +1 -1
  272. package/dist/modules/website/index.js +12 -0
  273. package/dist/modules/website/index.js.map +1 -1
  274. package/dist/modules/website/media-usage.d.ts +38 -0
  275. package/dist/modules/website/media-usage.d.ts.map +1 -0
  276. package/dist/modules/website/media-usage.js +87 -0
  277. package/dist/modules/website/media-usage.js.map +1 -0
  278. package/dist/modules/website/paths.js +1 -1
  279. package/dist/modules/website/paths.js.map +1 -1
  280. package/dist/modules/website/sections.d.ts.map +1 -1
  281. package/dist/modules/website/sections.js +12 -1
  282. package/dist/modules/website/sections.js.map +1 -1
  283. package/dist/modules/website_backend/index.js +138 -0
  284. package/dist/modules/website_backend/index.js.map +1 -1
  285. package/dist/modules/website_backend/menus.d.ts.map +1 -1
  286. package/dist/modules/website_backend/menus.js +11 -0
  287. package/dist/modules/website_backend/menus.js.map +1 -1
  288. package/dist/modules/website_backend/routes.d.ts.map +1 -1
  289. package/dist/modules/website_backend/routes.js +414 -31
  290. package/dist/modules/website_backend/routes.js.map +1 -1
  291. package/dist/modules/website_backend/screens/index.d.ts +98 -6
  292. package/dist/modules/website_backend/screens/index.d.ts.map +1 -1
  293. package/dist/modules/website_backend/screens/index.js +600 -154
  294. package/dist/modules/website_backend/screens/index.js.map +1 -1
  295. package/dist/modules/website_backend/screens/page-frame.d.ts +3 -1
  296. package/dist/modules/website_backend/screens/page-frame.d.ts.map +1 -1
  297. package/dist/modules/website_backend/screens/page-frame.js +1 -1
  298. package/dist/modules/website_backend/screens/page-frame.js.map +1 -1
  299. package/dist/modules/website_menu/functions.d.ts.map +1 -1
  300. package/dist/modules/website_menu/functions.js +51 -0
  301. package/dist/modules/website_menu/functions.js.map +1 -1
  302. package/dist/modules/website_menu/index.js +2 -0
  303. package/dist/modules/website_menu/index.js.map +1 -1
  304. package/dist/modules/website_search/functions.d.ts.map +1 -1
  305. package/dist/modules/website_search/functions.js +10 -120
  306. package/dist/modules/website_search/functions.js.map +1 -1
  307. package/dist/modules/website_search/index.js +2 -0
  308. package/dist/modules/website_search/index.js.map +1 -1
  309. package/dist/modules/website_search/jobs.d.ts +3 -0
  310. package/dist/modules/website_search/jobs.d.ts.map +1 -0
  311. package/dist/modules/website_search/jobs.js +101 -0
  312. package/dist/modules/website_search/jobs.js.map +1 -0
  313. package/dist/modules/website_search/rebuild.d.ts +33 -0
  314. package/dist/modules/website_search/rebuild.d.ts.map +1 -0
  315. package/dist/modules/website_search/rebuild.js +125 -0
  316. package/dist/modules/website_search/rebuild.js.map +1 -0
  317. package/dist/permission-catalogue.d.ts.map +1 -1
  318. package/dist/permission-catalogue.js +21 -1
  319. package/dist/permission-catalogue.js.map +1 -1
  320. package/dist/scaffold/index.js +1 -1
  321. package/dist/ui/chrome.d.ts +8 -0
  322. package/dist/ui/chrome.d.ts.map +1 -1
  323. package/dist/ui/chrome.js +9 -1
  324. package/dist/ui/chrome.js.map +1 -1
  325. package/dist/ui/client/table-selection-view.d.ts.map +1 -1
  326. package/dist/ui/client/table-selection-view.js +161 -5
  327. package/dist/ui/client/table-selection-view.js.map +1 -1
  328. package/dist/ui/client/user-workflow.d.ts +2 -0
  329. package/dist/ui/client/user-workflow.d.ts.map +1 -0
  330. package/dist/ui/client/user-workflow.js +141 -0
  331. package/dist/ui/client/user-workflow.js.map +1 -0
  332. package/dist/ui/form.d.ts +9 -0
  333. package/dist/ui/form.d.ts.map +1 -1
  334. package/dist/ui/form.js +29 -15
  335. package/dist/ui/form.js.map +1 -1
  336. package/dist/ui/icons.d.ts.map +1 -1
  337. package/dist/ui/icons.js +2 -0
  338. package/dist/ui/icons.js.map +1 -1
  339. package/dist/ui/index.d.ts +7 -3
  340. package/dist/ui/index.d.ts.map +1 -1
  341. package/dist/ui/index.js +6 -3
  342. package/dist/ui/index.js.map +1 -1
  343. package/dist/ui/layout.d.ts.map +1 -1
  344. package/dist/ui/layout.js +14 -4
  345. package/dist/ui/layout.js.map +1 -1
  346. package/dist/ui/nav.d.ts.map +1 -1
  347. package/dist/ui/nav.js +2 -1
  348. package/dist/ui/nav.js.map +1 -1
  349. package/dist/ui/state.d.ts +20 -1
  350. package/dist/ui/state.d.ts.map +1 -1
  351. package/dist/ui/state.js +17 -0
  352. package/dist/ui/state.js.map +1 -1
  353. package/dist/ui/table.js +1 -1
  354. package/dist/ui/table.js.map +1 -1
  355. package/dist/ui/user-workflow.d.ts +72 -0
  356. package/dist/ui/user-workflow.d.ts.map +1 -0
  357. package/dist/ui/user-workflow.js +144 -0
  358. package/dist/ui/user-workflow.js.map +1 -0
  359. package/package.json +8 -4
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "@ketvietlab/ketjs-view/jsx-runtime";
2
- import { badge, code, dataTable, emptyState, RecordScreen, inline, linkButton, Notice, RecordActions, RecordForm, Section, stack, Surface, } from '../../../ui/index.js';
2
+ import { badge, code, dataTable, emptyState, RecordScreen, inline, linkButton, Notice, pagerBar, RecordActions, RecordForm, Section, stack, Surface, } from '../../../ui/index.js';
3
3
  import { FormScreenFrame, ListScreenFrame } from './page-frame.js';
4
4
  const statusTone = (status) => status === 'published'
5
5
  ? 'positive'
@@ -8,7 +8,29 @@ const statusTone = (status) => status === 'published'
8
8
  : status === 'trash'
9
9
  ? 'warning'
10
10
  : 'neutral';
11
- export const sitesScreen = (_, rows, frame, locale = '') => (_jsx(ListScreenFrame, { translator: _, title: _('website_backend.sites.title'), frame: frame, body: stack([
11
+ /**
12
+ * All / on / off, as three links.
13
+ *
14
+ * `active` is on every one of these list contracts and no screen passed it, so
15
+ * a suspended site and a retired form were indistinguishable from a live one
16
+ * in the only place anybody looks.
17
+ */
18
+ const activeFilter = (_, href, chosen) => inline([
19
+ linkButton({ label: _('website_backend.state.all'), href: href('all'), size: 'compact' }),
20
+ linkButton({
21
+ label: _('website_backend.state.active'),
22
+ href: href('active'),
23
+ size: 'compact',
24
+ variant: chosen === 'active' ? 'secondary' : 'tertiary',
25
+ }),
26
+ linkButton({
27
+ label: _('website_backend.state.inactive'),
28
+ href: href('inactive'),
29
+ size: 'compact',
30
+ variant: chosen === 'inactive' ? 'secondary' : 'tertiary',
31
+ }),
32
+ ]);
33
+ export const sitesScreen = (_, rows, frame, locale = '', active = 'all') => (_jsx(ListScreenFrame, { translator: _, title: _('website_backend.sites.title'), frame: frame, body: stack([
12
34
  inline([
13
35
  linkButton({
14
36
  label: _('website_backend.action.newSite'),
@@ -21,6 +43,7 @@ export const sitesScreen = (_, rows, frame, locale = '') => (_jsx(ListScreenFram
21
43
  variant: 'secondary',
22
44
  }),
23
45
  ]),
46
+ activeFilter(_, (state) => `/admin/website/sites?state=${state}${locale ? `&${locale.slice(1)}` : ''}`, active),
24
47
  rows.length === 0
25
48
  ? emptyState(_('website_backend.sites.empty'), _('website_backend.sites.emptyHint'))
26
49
  : dataTable(_, {
@@ -108,6 +131,17 @@ export const siteFormScreen = (_, row, themes, frame, options = {}) => {
108
131
  options: themes,
109
132
  required: true,
110
133
  },
134
+ {
135
+ // The layer order already puts a site above its theme, so
136
+ // these override rather than replace: a site that sets
137
+ // nothing looks exactly as it did.
138
+ name: 'tokens',
139
+ label: _('website_backend.field.tokens'),
140
+ type: 'textarea',
141
+ value: JSON.stringify(row.tokens ?? {}, null, 2),
142
+ help: _('website_backend.field.tokensHint'),
143
+ span: 'full',
144
+ },
111
145
  {
112
146
  name: 'active',
113
147
  label: _('website_backend.field.active'),
@@ -118,7 +152,9 @@ export const siteFormScreen = (_, row, themes, frame, options = {}) => {
118
152
  ], submit: _('website_backend.action.save'), submitVariant: "primary", errors: options.errors, cancelHref: `/admin/website/sites${options.locale ?? ''}`, cancelLabel: _('website_backend.action.cancel') }) }) }),
119
153
  ]) }));
120
154
  };
121
- export const contentScreen = (_, rows, sites, siteId, frame, locale = '', kind = { basePath: '/admin/website/pages', titleKey: 'pages' }) => (_jsx(ListScreenFrame, { translator: _, title: _(`website_backend.${kind.titleKey}.title`), frame: frame, body: stack([
155
+ export const contentScreen = (_, rows, sites, siteId, frame, locale = '', kind = { basePath: '/admin/website/pages', titleKey: 'pages' }, pager = null,
156
+ /** What the URL asked for, so the controls come back showing it. */
157
+ query = {}) => (_jsx(ListScreenFrame, { translator: _, title: _(`website_backend.${kind.titleKey}.title`), frame: frame, footer: pager ? pagerBar(_, pager) : null, body: stack([
122
158
  _jsx(Surface, { padding: "compact", body: _jsx(RecordForm, { action: `${kind.basePath}${locale}`, method: "get", layout: "inline", fields: [
123
159
  {
124
160
  name: 'site',
@@ -127,7 +163,27 @@ export const contentScreen = (_, rows, sites, siteId, frame, locale = '', kind =
127
163
  value: siteId,
128
164
  options: sites,
129
165
  },
130
- ], submit: _('website_backend.action.switchSite'), submitVariant: "secondary" }) }),
166
+ {
167
+ name: 'q',
168
+ label: _('website_backend.field.search'),
169
+ value: query.search ?? '',
170
+ },
171
+ {
172
+ name: 'status',
173
+ label: _('website_backend.field.status'),
174
+ type: 'select',
175
+ value: query.status ?? 'all',
176
+ options: [
177
+ { value: 'all', label: _('website_backend.state.all') },
178
+ { value: 'draft', label: _('website_backend.state.draft') },
179
+ { value: 'scheduled', label: _('website_backend.state.scheduled') },
180
+ { value: 'published', label: _('website_backend.state.published') },
181
+ // Only by asking: the list leaves the bin out otherwise, the
182
+ // way every other reader in the module already does.
183
+ { value: 'trash', label: _('website_backend.state.trash') },
184
+ ],
185
+ },
186
+ ], submit: _('website_backend.action.apply'), submitVariant: "secondary" }) }),
131
187
  inline([
132
188
  linkButton({
133
189
  label: _(`website_backend.action.new${kind.titleKey === 'pages' ? 'Page' : 'Post'}`),
@@ -173,6 +229,70 @@ export const contentScreen = (_, rows, sites, siteId, frame, locale = '', kind =
173
229
  ],
174
230
  }),
175
231
  ]) }));
232
+ /**
233
+ * Which taxonomy terms this entry carries.
234
+ *
235
+ * assignTerm shipped with the taxonomy module and nothing ever read the
236
+ * assignment back or took it off, so a term put on a page went invisible the
237
+ * moment it was assigned - and deleteTerm refuses while an assignment exists,
238
+ * which made the term itself permanent as well.
239
+ */
240
+ export const entryTermsSection = (_, entryId, assigned, available, locale = '') => {
241
+ const unassigned = available.filter((term) => !assigned.some((row) => row.termId === term.id));
242
+ return (_jsx(Section, { title: _('website_backend.terms.title'), description: _('website_backend.terms.hint'), body: _jsx(Surface, { body: stack([
243
+ assigned.length === 0
244
+ ? emptyState(_('website_backend.terms.empty'), _('website_backend.terms.emptyHint'))
245
+ : dataTable(_, {
246
+ rows: assigned,
247
+ id: (row) => row.id,
248
+ columns: [
249
+ {
250
+ key: 'taxonomy',
251
+ label: _('website_backend.field.taxonomy'),
252
+ cell: (row) => badge(row.taxonomy, 'info'),
253
+ },
254
+ {
255
+ key: 'name',
256
+ label: _('website_backend.terms.name'),
257
+ priority: 'primary',
258
+ cell: (row) => row.name,
259
+ },
260
+ {
261
+ key: 'slug',
262
+ label: _('website_backend.field.slug'),
263
+ kind: 'identifier',
264
+ cell: (row) => code(row.slug),
265
+ },
266
+ {
267
+ key: 'remove',
268
+ label: _('website_backend.action.remove'),
269
+ cell: (row) => (_jsx(RecordActions, { action: `/admin/website/content/${entryId}/terms/${row.termId}/remove${locale}`, size: "compact", actions: [
270
+ {
271
+ value: 'remove',
272
+ label: _('website_backend.action.remove'),
273
+ variant: 'destructive',
274
+ },
275
+ ] })),
276
+ },
277
+ ],
278
+ }),
279
+ ...(unassigned.length
280
+ ? [
281
+ _jsx(RecordForm, { action: `/admin/website/content/${entryId}/terms${locale}`, layout: "inline", fields: [
282
+ {
283
+ name: 'termId',
284
+ label: _('website_backend.terms.add'),
285
+ type: 'select',
286
+ options: unassigned.map((term) => ({
287
+ value: term.id,
288
+ label: `${term.taxonomy} / ${term.name}`,
289
+ })),
290
+ },
291
+ ], submit: _('website_backend.action.assign'), submitVariant: "secondary" }),
292
+ ]
293
+ : [emptyState(_('website_backend.terms.none'), _('website_backend.terms.noneHint'))]),
294
+ ]) }) }));
295
+ };
176
296
  export const entryFormScreen = (_, detail, siteId, kind, frame, options = {}) => {
177
297
  const entry = detail?.entry;
178
298
  const revision = detail?.revision;
@@ -250,18 +370,63 @@ export const entryFormScreen = (_, detail, siteId, kind, frame, options = {}) =>
250
370
  ], submit: _('website_backend.action.saveDraft'), submitVariant: "primary", errors: options.errors, cancelHref: `${kind.basePath}?site=${encodeURIComponent(siteId)}${options.locale ? `&${options.locale.slice(1)}` : ''}`, cancelLabel: _('website_backend.action.cancel') }) }) }),
251
371
  ...(existing
252
372
  ? [
253
- _jsx(Section, { title: _('website_backend.publish.title'), description: _('website_backend.publish.hint'), body: _jsx(Surface, { body: _jsx(RecordActions, { action: `${kind.basePath}/${entry.id}/publish${options.locale ?? ''}`, hidden: revision?.id ? { expectedRevisionId: revision.id } : undefined, actions: [
254
- {
255
- value: 'publish',
256
- label: _('website_backend.action.publish'),
257
- variant: 'primary',
258
- },
259
- ] }) }) }),
373
+ _jsx(Section, { title: _('website_backend.publish.title'), description: _('website_backend.publish.hint'), body: _jsx(Surface, { body: stack([
374
+ _jsx(RecordForm, { action: `${kind.basePath}/${entry.id}/publish${options.locale ?? ''}`, hidden: revision?.id ? { expectedRevisionId: revision.id } : undefined, layout: "inline", fields: [
375
+ {
376
+ name: 'publishAt',
377
+ label: _('website_backend.publish.at'),
378
+ type: 'datetime-local',
379
+ value: entry.publishAt ? String(entry.publishAt).slice(0, 16) : '',
380
+ help: _('website_backend.publish.atHint'),
381
+ },
382
+ ], submit: _('website_backend.action.publish'), submitVariant: "primary" }),
383
+ ...(entry.status === 'trash'
384
+ ? [
385
+ _jsx(RecordActions, { action: `${kind.basePath}/${entry.id}/untrash${options.locale ?? ''}`, label: _('website_backend.publish.untrashHint'), actions: [
386
+ {
387
+ value: 'untrash',
388
+ label: _('website_backend.action.untrash'),
389
+ variant: 'primary',
390
+ },
391
+ ] }),
392
+ ]
393
+ : [
394
+ _jsx(RecordActions, { action: `${kind.basePath}/${entry.id}/trash${options.locale ?? ''}`, label: _('website_backend.publish.trashHint'), actions: [
395
+ {
396
+ value: 'trash',
397
+ label: _('website_backend.action.trash'),
398
+ variant: 'destructive',
399
+ },
400
+ ] }),
401
+ ]),
402
+ ...(entry.status === 'published' || entry.status === 'scheduled'
403
+ ? [
404
+ _jsx(RecordActions, { action: `${kind.basePath}/${entry.id}/unpublish${options.locale ?? ''}`, label: entry.status === 'scheduled'
405
+ ? _('website_backend.publish.cancelHint')
406
+ : _('website_backend.publish.downHint'), actions: [
407
+ {
408
+ value: 'unpublish',
409
+ label: entry.status === 'scheduled'
410
+ ? _('website_backend.action.cancelSchedule')
411
+ : _('website_backend.action.unpublish'),
412
+ variant: 'destructive',
413
+ },
414
+ ] }),
415
+ ]
416
+ : []),
417
+ ]) }) }),
260
418
  ]
261
419
  : []),
262
420
  // Only on a page that exists: the head tags describe a revision, and
263
421
  // there is no revision until the page has been saved once.
264
422
  ...(existing && options.seo ? [entrySeoSection(_, entry.id, options.seo, options.locale ?? '')] : []),
423
+ // Same reason: an assignment points at an entry, and there is no entry
424
+ // to point at until the page has been saved once.
425
+ ...(existing && options.terms
426
+ ? [
427
+ entryTermsSection(_, entry.id, options.terms.assigned, options.terms.available, options.locale ?? ''),
428
+ ]
429
+ : []),
265
430
  ]) }));
266
431
  };
267
432
  /**
@@ -379,33 +544,69 @@ export const revisionsScreen = (_, entry, rows, frame, locale = '', basePath = '
379
544
  // the content back is how it gets repaired.
380
545
  key: 'restore',
381
546
  label: _('website_backend.action.restore'),
382
- cell: (row) => linkButton({
383
- label: _('website_backend.action.restore'),
384
- href: `${basePath}/${entry.id}/revisions/${row.id}/restore${locale}`,
385
- size: 'compact',
386
- }),
547
+ cell: (row) => (_jsx(RecordActions, { action: `${basePath}/${entry.id}/revisions/${row.id}/restore${locale}`, size: "compact", actions: [{ value: 'restore', label: _('website_backend.action.restore') }] })),
387
548
  },
388
549
  ],
389
550
  }),
390
551
  ]) }));
391
- export const previewScreen = (_, entry, token, expiresAt, frame, basePath = '/admin/website/pages') => (_jsx(RecordScreen, { translator: _, title: _('website_backend.preview.title'), frame: frame, body: stack([
552
+ /**
553
+ * One preview link, and the way to withdraw all of them.
554
+ *
555
+ * Every visit here mints another token, so the links accumulate: a preview
556
+ * pasted into a chat outlives the reason it was shared, and until now nothing
557
+ * could call any of them back.
558
+ */
559
+ export const previewScreen = (_, entry, minted, frame, basePath = '/admin/website/pages', locale = '') => (_jsx(RecordScreen, { translator: _, title: _('website_backend.preview.title'), frame: frame, body: stack([
392
560
  _jsx(Notice, { tone: "info", title: entry.title, message: _('website_backend.preview.hint') }),
393
- _jsx(Surface, { body: _jsx(RecordForm, { action: basePath, method: "get", fields: [
561
+ _jsx(Surface, { body: _jsx(RecordForm, { action: `${basePath}/${entry.id}/preview${locale}`, fields: [
394
562
  {
395
- name: 'token',
396
- label: _('website_backend.preview.token'),
397
- value: token,
398
- disabled: true,
399
- span: 'full',
563
+ name: 'ttlSeconds',
564
+ label: _('website_backend.preview.ttl'),
565
+ type: 'select',
566
+ value: '900',
567
+ options: [
568
+ { value: '300', label: _('website_backend.preview.ttl5') },
569
+ { value: '900', label: _('website_backend.preview.ttl15') },
570
+ { value: '3600', label: _('website_backend.preview.ttl60') },
571
+ ],
572
+ help: _('website_backend.preview.ttlHint'),
400
573
  },
401
574
  {
402
- name: 'expiresAt',
403
- label: _('website_backend.preview.expires'),
404
- value: expiresAt,
405
- disabled: true,
575
+ name: 'oneTime',
576
+ label: _('website_backend.preview.oneTime'),
577
+ type: 'checkbox',
578
+ help: _('website_backend.preview.oneTimeHint'),
406
579
  span: 'full',
407
580
  },
408
- ], submit: _('website_backend.action.backToContent'), submitVariant: "secondary" }) }),
581
+ ], submit: _('website_backend.action.createPreview'), submitVariant: "primary" }) }),
582
+ ...(minted
583
+ ? [
584
+ _jsx(Surface, { body: _jsx(RecordForm, { action: basePath, method: "get", fields: [
585
+ {
586
+ name: 'link',
587
+ label: _('website_backend.preview.link'),
588
+ value: `/_ket/preview?token=${encodeURIComponent(minted.token)}`,
589
+ disabled: true,
590
+ help: _('website_backend.preview.linkHint'),
591
+ span: 'full',
592
+ },
593
+ {
594
+ name: 'expiresAt',
595
+ label: _('website_backend.preview.expires'),
596
+ value: minted.expiresAt,
597
+ disabled: true,
598
+ span: 'full',
599
+ },
600
+ ], submit: _('website_backend.action.backToContent'), submitVariant: "secondary" }) }),
601
+ ]
602
+ : []),
603
+ _jsx(Section, { title: _('website_backend.preview.revokeTitle'), description: _('website_backend.preview.revokeHint'), body: _jsx(Surface, { body: _jsx(RecordActions, { action: `${basePath}/${entry.id}/preview/revoke${locale}`, actions: [
604
+ {
605
+ value: 'revoke',
606
+ label: _('website_backend.action.revokePreviews'),
607
+ variant: 'destructive',
608
+ },
609
+ ] }) }) }),
409
610
  ]) }));
410
611
  const siteSwitcher = (_, action, sites, siteId, locale) => (_jsx(Surface, { padding: "compact", body: _jsx(RecordForm, { action: `${action}${locale}`, method: "get", layout: "inline", fields: [
411
612
  {
@@ -526,6 +727,7 @@ export const mediaScreen = (_, rows, sites, siteId, frame, locale = '') => (_jsx
526
727
  ]) }));
527
728
  export const mediaFormScreen = (_, row, frame, options = {}) => {
528
729
  const existing = !!row.id;
730
+ const usage = options.usage ?? null;
529
731
  return (_jsx(FormScreenFrame, { translator: _, title: existing ? String(row.attachmentId) : _('website_backend.media.newTitle'), frame: frame, body: stack([
530
732
  _jsx(Section, { title: existing ? String(row.attachmentId) : _('website_backend.media.newTitle'), description: _('website_backend.media.formHint'), body: _jsx(Surface, { body: _jsx(RecordForm, { action: existing
531
733
  ? `/admin/website/media/${row.id}${options.locale ?? ''}`
@@ -569,6 +771,39 @@ export const mediaFormScreen = (_, row, frame, options = {}) => {
569
771
  ] }) }),
570
772
  ]
571
773
  : []),
774
+ // Delete refuses while a page draws this, so saying which pages is the
775
+ // difference between a refusal an editor can act on and one they argue
776
+ // with.
777
+ ...(existing && usage
778
+ ? [
779
+ _jsx(Section, { title: _('website_backend.media.usage'), description: _('website_backend.media.usageHint'), body: _jsx(Surface, { body: usage.capped ? (_jsx(Notice, { tone: "warning", title: _('website_backend.media.usageUnknown'), message: _('website_backend.media.usageUnknownHint') })) : usage.uses.length === 0 ? (emptyState(_('website_backend.media.usageNone'), _('website_backend.media.usageNoneHint'))) : (dataTable(_, {
780
+ rows: usage.uses,
781
+ id: (use) => use.entryId,
782
+ rowHref: (use) => `/admin/website/pages/${use.entryId}`,
783
+ columns: [
784
+ {
785
+ key: 'title',
786
+ label: _('website_backend.field.title'),
787
+ priority: 'primary',
788
+ cell: (use) => use.title,
789
+ },
790
+ {
791
+ key: 'path',
792
+ label: _('website_backend.field.path'),
793
+ kind: 'identifier',
794
+ cell: (use) => code(use.path),
795
+ },
796
+ {
797
+ key: 'state',
798
+ label: _('website_backend.field.status'),
799
+ cell: (use) => badge(use.published
800
+ ? _('website_backend.state.published')
801
+ : _('website_backend.state.draft'), use.published ? 'positive' : 'neutral'),
802
+ },
803
+ ],
804
+ })) }) }),
805
+ ]
806
+ : []),
572
807
  ]) }));
573
808
  };
574
809
  /**
@@ -579,12 +814,26 @@ export const mediaFormScreen = (_, row, frame, options = {}) => {
579
814
  * nobody should have to think about. It is a button, and this is where it
580
815
  * lands.
581
816
  */
582
- export const preflightScreen = (_, result, siteId, frame, locale = '') => (_jsx(RecordScreen, { translator: _, title: _('website_backend.preflight.title'), frame: frame, body: stack([
817
+ export const preflightScreen = (_, result, siteId, frame, locale = '', scope = 'all') => (_jsx(RecordScreen, { translator: _, title: _('website_backend.preflight.title'), frame: frame, body: stack([
583
818
  inline([
584
819
  linkButton({
585
820
  label: _('website_backend.action.backToContent'),
586
821
  href: `/admin/website/pages?site=${encodeURIComponent(siteId)}${locale ? `&${locale.slice(1)}` : ''}`,
587
822
  }),
823
+ // The scan over every page is the one that can be capped; asking about
824
+ // the published set is a bounded question with a definite answer.
825
+ linkButton({
826
+ label: _('website_backend.preflight.scopeAll'),
827
+ href: `/admin/website/preflight?site=${encodeURIComponent(siteId)}&scope=all${locale ? `&${locale.slice(1)}` : ''}`,
828
+ size: 'compact',
829
+ variant: scope === 'all' ? 'secondary' : 'tertiary',
830
+ }),
831
+ linkButton({
832
+ label: _('website_backend.preflight.scopePublished'),
833
+ href: `/admin/website/preflight?site=${encodeURIComponent(siteId)}&scope=published${locale ? `&${locale.slice(1)}` : ''}`,
834
+ size: 'compact',
835
+ variant: scope === 'published' ? 'secondary' : 'tertiary',
836
+ }),
588
837
  ]),
589
838
  ...(result.capped
590
839
  ? [
@@ -658,6 +907,17 @@ export const menusScreen = (_, rows, sites, siteId, frame, locale = '', dangling
658
907
  kind: 'number',
659
908
  cell: (row) => String(row.position),
660
909
  },
910
+ {
911
+ // Buttons, so the order is editable from a keyboard without
912
+ // anything having to be dragged - and without an editor doing
913
+ // arithmetic in the position box, which was the only way.
914
+ key: 'move',
915
+ label: _('website_backend.menus.move'),
916
+ cell: (row) => (_jsx(RecordActions, { action: `/admin/website/menus/${row.id}/move${locale}`, hidden: { site: row.siteId }, size: "compact", actions: [
917
+ { value: 'up', label: _('website_backend.menus.up') },
918
+ { value: 'down', label: _('website_backend.menus.down') },
919
+ ] })),
920
+ },
661
921
  ],
662
922
  }),
663
923
  ]) }));
@@ -702,7 +962,8 @@ export const menuFormScreen = (_, row, parents, frame, options = {}) => {
702
962
  : []),
703
963
  ]) }));
704
964
  };
705
- export const formsScreen = (_, rows, siteId, frame, locale = '') => (_jsx(ListScreenFrame, { translator: _, title: _('website_backend.forms.title'), frame: frame, body: stack([
965
+ export const formsScreen = (_, rows, siteId, frame, locale = '', active = 'all') => (_jsx(ListScreenFrame, { translator: _, title: _('website_backend.forms.title'), frame: frame, body: stack([
966
+ activeFilter(_, (state) => `/admin/website/forms?site=${encodeURIComponent(siteId ?? '')}&state=${state}${locale ? `&${locale.slice(1)}` : ''}`, active),
706
967
  inline([
707
968
  linkButton({
708
969
  label: _('website_backend.action.newForm'),
@@ -922,13 +1183,15 @@ export const submissionRecordScreen = (_, record, audit, frame, locale = '') =>
922
1183
  * up somewhere nobody can account for; an erasure says the window it will
923
1184
  * apply and asks to be confirmed, because it cannot be undone.
924
1185
  */
925
- const submissionActions = (_, formId, fields, retentionDays, locale) => [
926
- _jsx(Section, { title: _('website_backend.submissions.export'), description: _('website_backend.submissions.exportHint'), body: _jsx(Surface, { padding: "compact", body: _jsx(RecordForm, { action: `/admin/website/forms/${formId}/submissions/export${locale}`, method: "get", layout: "inline", fields: [
1186
+ const submissionActions = (_, formId, fields, retentionDays, locale, status = 'all') => [
1187
+ _jsx(Section, { title: _('website_backend.submissions.export'), description: _('website_backend.submissions.exportHint'), body: _jsx(Surface, { padding: "compact", body: _jsx(RecordForm, { action: `/admin/website/forms/${formId}/submissions/export${locale}`, method: "get", layout: "inline", hidden: { status }, fields: [
927
1188
  {
928
1189
  name: 'fields',
929
1190
  label: _('website_backend.submissions.exportFields'),
930
1191
  value: fields.join(', '),
931
- help: _('website_backend.submissions.exportFieldsHint'),
1192
+ help: status === 'all'
1193
+ ? _('website_backend.submissions.exportFieldsHint')
1194
+ : `${_('website_backend.submissions.exportFieldsHint')} ${_('website_backend.submissions.exportScoped')}`,
932
1195
  required: true,
933
1196
  },
934
1197
  ], submit: _('website_backend.submissions.export'), submitVariant: "secondary" }) }) }),
@@ -945,9 +1208,29 @@ const submissionActions = (_, formId, fields, retentionDays, locale) => [
945
1208
  ], submit: _('website_backend.submissions.purge'), submitVariant: "secondary" }) }) }),
946
1209
  ]),
947
1210
  ];
948
- export const submissionsScreen = (_, rows, frame, options = {}) => (_jsx(ListScreenFrame, { translator: _, title: _('website_backend.submissions.title'), frame: frame, body: stack([
1211
+ export const submissionsScreen = (_, rows, frame, options = {}) => (_jsx(ListScreenFrame, { translator: _, title: _('website_backend.submissions.title'), frame: frame, footer: options.pager ? pagerBar(_, options.pager) : null, body: stack([
1212
+ // `listSubmissions` and `countSubmissions` have both taken this since
1213
+ // they were written. Without it a form with a year of entries is read
1214
+ // thirty at a time and the erased rows sit among the live ones.
949
1215
  ...(options.formId
950
- ? submissionActions(_, options.formId, options.fields ?? [], options.retentionDays ?? null, options.locale ?? '')
1216
+ ? [
1217
+ _jsx(Surface, { padding: "compact", body: _jsx(RecordForm, { action: `/admin/website/forms/${options.formId}/submissions${options.locale ?? ''}`, method: "get", layout: "inline", fields: [
1218
+ {
1219
+ name: 'status',
1220
+ label: _('website_backend.field.status'),
1221
+ type: 'select',
1222
+ value: options.status ?? 'all',
1223
+ options: [
1224
+ { value: 'all', label: _('website_backend.state.all') },
1225
+ { value: 'new', label: _('website_backend.state.new') },
1226
+ { value: 'purged', label: _('website_backend.state.purged') },
1227
+ ],
1228
+ },
1229
+ ], submit: _('website_backend.action.apply'), submitVariant: "secondary" }) }),
1230
+ ]
1231
+ : []),
1232
+ ...(options.formId
1233
+ ? submissionActions(_, options.formId, options.fields ?? [], options.retentionDays ?? null, options.locale ?? '', options.status ?? 'all')
951
1234
  : []),
952
1235
  rows.length === 0
953
1236
  ? emptyState(_('website_backend.submissions.empty'), _('website_backend.submissions.emptyHint'))
@@ -1046,11 +1329,13 @@ export const siteMembersScreen = (_, site, rows, frame, options = {}) => (_jsx(L
1046
1329
  {
1047
1330
  key: 'remove',
1048
1331
  label: _('website_backend.action.remove'),
1049
- cell: (row) => linkButton({
1050
- label: _('website_backend.action.remove'),
1051
- href: `/admin/website/sites/${site.id}/members/${row.id}/remove${options.locale ?? ''}`,
1052
- size: 'compact',
1053
- }),
1332
+ cell: (row) => (_jsx(RecordActions, { action: `/admin/website/sites/${site.id}/members/${row.id}/remove${options.locale ?? ''}`, size: "compact", actions: [
1333
+ {
1334
+ value: 'remove',
1335
+ label: _('website_backend.action.remove'),
1336
+ variant: 'destructive',
1337
+ },
1338
+ ] })),
1054
1339
  },
1055
1340
  ],
1056
1341
  }),
@@ -1062,59 +1347,95 @@ export const siteMembersScreen = (_, site, rows, frame, options = {}) => (_jsx(L
1062
1347
  * from it, so a site with the wrong primary publishes the wrong address to
1063
1348
  * every crawler that asks.
1064
1349
  */
1065
- export const siteDomainsScreen = (_, site, rows, frame, options = {}) => (_jsx(ListScreenFrame, { translator: _, title: _('website_backend.domains.title'), frame: frame, body: stack([
1066
- inline([
1067
- linkButton({
1068
- label: _('website_backend.action.backToSite'),
1069
- href: `/admin/website/sites/${site.id}${options.locale ?? ''}`,
1070
- }),
1071
- ]),
1072
- _jsx(Section, { title: _('website_backend.domains.add'), description: _('website_backend.domains.addHint'), body: _jsx(Surface, { padding: "compact", body: _jsx(RecordForm, { action: `/admin/website/sites/${site.id}/domains${options.locale ?? ''}`, layout: "inline", fields: [
1350
+ export const siteDomainsScreen = (_, site, rows, frame, options = {}) => {
1351
+ const editing = options.editing ?? null;
1352
+ const values = options.values ?? {};
1353
+ return (_jsx(ListScreenFrame, { translator: _, title: _('website_backend.domains.title'), frame: frame, body: stack([
1354
+ inline([
1355
+ linkButton({
1356
+ label: _('website_backend.action.backToSite'),
1357
+ href: `/admin/website/sites/${site.id}${options.locale ?? ''}`,
1358
+ }),
1359
+ ...(editing
1360
+ ? [
1361
+ linkButton({
1362
+ label: _('website_backend.action.cancel'),
1363
+ href: `/admin/website/sites/${site.id}/domains${options.locale ?? ''}`,
1364
+ }),
1365
+ ]
1366
+ : []),
1367
+ ]),
1368
+ _jsx(Section, { title: editing ? _('website_backend.domains.edit') : _('website_backend.domains.add'), description: _('website_backend.domains.addHint'), body: _jsx(Surface, { padding: "compact", body: _jsx(RecordForm, { action: `/admin/website/sites/${site.id}/domains${editing ? `/${editing.id}` : ''}${options.locale ?? ''}`, layout: "inline", fields: [
1369
+ {
1370
+ name: 'host',
1371
+ label: _('website_backend.domains.host'),
1372
+ value: values.host ?? editing?.host,
1373
+ required: true,
1374
+ },
1375
+ {
1376
+ name: 'primary',
1377
+ label: _('website_backend.domains.primary'),
1378
+ type: 'checkbox',
1379
+ value: values.primary != null ? values.primary === '1' : (editing?.primary ?? false),
1380
+ help: _('website_backend.domains.primaryHint'),
1381
+ },
1382
+ {
1383
+ name: 'redirectToPrimary',
1384
+ label: _('website_backend.domains.redirect'),
1385
+ type: 'checkbox',
1386
+ value: values.redirectToPrimary != null
1387
+ ? values.redirectToPrimary === '1'
1388
+ : (editing?.redirectToPrimary ?? false),
1389
+ },
1390
+ ], submit: _('website_backend.action.save'), submitVariant: "primary", errors: options.errors }) }) }),
1391
+ rows.length === 0
1392
+ ? emptyState(_('website_backend.domains.empty'), _('website_backend.domains.emptyHint'))
1393
+ : dataTable(_, {
1394
+ rows,
1395
+ id: (row) => row.id,
1396
+ columns: [
1073
1397
  {
1074
- name: 'host',
1398
+ key: 'host',
1075
1399
  label: _('website_backend.domains.host'),
1076
- value: options.values?.host,
1077
- required: true,
1400
+ priority: 'primary',
1401
+ cell: (row) => row.host,
1078
1402
  },
1079
1403
  {
1080
- name: 'primary',
1404
+ key: 'primary',
1081
1405
  label: _('website_backend.domains.primary'),
1082
- type: 'checkbox',
1083
- help: _('website_backend.domains.primaryHint'),
1406
+ cell: (row) => row.primary
1407
+ ? badge(_('website_backend.state.yes'), 'positive')
1408
+ : badge(_('website_backend.state.no'), 'neutral'),
1084
1409
  },
1085
1410
  {
1086
- name: 'redirectToPrimary',
1411
+ key: 'redirect',
1087
1412
  label: _('website_backend.domains.redirect'),
1088
- type: 'checkbox',
1413
+ cell: (row) => badge(row.redirectToPrimary ? _('website_backend.state.yes') : _('website_backend.state.no'), 'neutral'),
1089
1414
  },
1090
- ], submit: _('website_backend.action.save'), submitVariant: "primary", errors: options.errors }) }) }),
1091
- rows.length === 0
1092
- ? emptyState(_('website_backend.domains.empty'), _('website_backend.domains.emptyHint'))
1093
- : dataTable(_, {
1094
- rows,
1095
- id: (row) => row.id,
1096
- columns: [
1097
- {
1098
- key: 'host',
1099
- label: _('website_backend.domains.host'),
1100
- priority: 'primary',
1101
- cell: (row) => row.host,
1102
- },
1103
- {
1104
- key: 'primary',
1105
- label: _('website_backend.domains.primary'),
1106
- cell: (row) => row.primary
1107
- ? badge(_('website_backend.state.yes'), 'positive')
1108
- : badge(_('website_backend.state.no'), 'neutral'),
1109
- },
1110
- {
1111
- key: 'redirect',
1112
- label: _('website_backend.domains.redirect'),
1113
- cell: (row) => badge(row.redirectToPrimary ? _('website_backend.state.yes') : _('website_backend.state.no'), 'neutral'),
1114
- },
1115
- ],
1116
- }),
1117
- ]) }));
1415
+ {
1416
+ key: 'edit',
1417
+ label: _('website_backend.action.edit'),
1418
+ cell: (row) => linkButton({
1419
+ label: _('website_backend.action.edit'),
1420
+ href: `/admin/website/sites/${site.id}/domains?edit=${encodeURIComponent(row.id)}${options.locale ? `&${options.locale.slice(1)}` : ''}`,
1421
+ size: 'compact',
1422
+ }),
1423
+ },
1424
+ {
1425
+ key: 'remove',
1426
+ label: _('website_backend.action.remove'),
1427
+ cell: (row) => (_jsx(RecordActions, { action: `/admin/website/sites/${site.id}/domains/${row.id}/remove${options.locale ?? ''}`, size: "compact", actions: [
1428
+ {
1429
+ value: 'remove',
1430
+ label: _('website_backend.action.remove'),
1431
+ variant: 'destructive',
1432
+ },
1433
+ ] })),
1434
+ },
1435
+ ],
1436
+ }),
1437
+ ]) }));
1438
+ };
1118
1439
  /**
1119
1440
  * Where an address that used to work now goes.
1120
1441
  *
@@ -1122,62 +1443,111 @@ export const siteDomainsScreen = (_, site, rows, frame, options = {}) => (_jsx(L
1122
1443
  * the one operation that keeps old links alive after a restructure could only
1123
1444
  * be performed by an agent.
1124
1445
  */
1125
- export const redirectsScreen = (_, rows, sites, siteId, frame, options = {}) => (_jsx(ListScreenFrame, { translator: _, title: _('website_backend.redirects.title'), frame: frame, body: stack([
1126
- siteSwitcher(_, '/admin/website/redirects', sites, siteId, options.locale ?? ''),
1127
- ...(siteId
1128
- ? [
1129
- _jsx(Section, { title: _('website_backend.redirects.add'), description: _('website_backend.redirects.addHint'), body: _jsx(Surface, { padding: "compact", body: _jsx(RecordForm, { action: `/admin/website/redirects${options.locale ?? ''}`, hidden: { siteId }, layout: "inline", fields: [
1130
- {
1131
- name: 'fromPath',
1132
- label: _('website_backend.redirects.from'),
1133
- value: options.values?.fromPath,
1134
- required: true,
1135
- },
1136
- {
1137
- name: 'toPath',
1138
- label: _('website_backend.redirects.to'),
1139
- value: options.values?.toPath,
1140
- required: true,
1141
- },
1142
- {
1143
- name: 'permanent',
1144
- label: _('website_backend.redirects.permanent'),
1145
- type: 'checkbox',
1146
- help: _('website_backend.redirects.permanentHint'),
1147
- },
1148
- ], submit: _('website_backend.action.save'), submitVariant: "primary", errors: options.errors }) }) }),
1149
- ]
1150
- : []),
1151
- !siteId
1152
- ? emptyState(_('website_backend.content.noSite'), _('website_backend.content.noSiteHint'))
1153
- : rows.length === 0
1154
- ? emptyState(_('website_backend.redirects.empty'), _('website_backend.redirects.emptyHint'))
1155
- : dataTable(_, {
1156
- rows,
1157
- id: (row) => row.id,
1158
- columns: [
1159
- {
1160
- key: 'from',
1161
- label: _('website_backend.redirects.from'),
1162
- priority: 'primary',
1163
- cell: (row) => row.fromPath,
1164
- },
1165
- { key: 'to', label: _('website_backend.redirects.to'), cell: (row) => row.toPath },
1166
- {
1167
- key: 'kind',
1168
- label: _('website_backend.redirects.permanent'),
1169
- cell: (row) => badge(row.permanent
1170
- ? _('website_backend.redirects.p301')
1171
- : _('website_backend.redirects.p302'), row.permanent ? 'info' : 'neutral'),
1172
- },
1173
- {
1174
- key: 'status',
1175
- label: _('website_backend.field.status'),
1176
- cell: (row) => badge(row.active ? _('website_backend.state.active') : _('website_backend.state.inactive'), row.active ? 'positive' : 'neutral'),
1177
- },
1178
- ],
1179
- }),
1180
- ]) }));
1446
+ export const redirectsScreen = (_, rows, sites, siteId, frame, options = {}) => {
1447
+ const editing = options.editing ?? null;
1448
+ const values = options.values ?? {};
1449
+ const query = (params) => {
1450
+ const search = new URLSearchParams({ site: siteId ?? '', ...params });
1451
+ if (options.locale)
1452
+ search.set('lang', options.locale.slice('?lang='.length));
1453
+ return `/admin/website/redirects?${search.toString()}`;
1454
+ };
1455
+ return (_jsx(ListScreenFrame, { translator: _, title: _('website_backend.redirects.title'), frame: frame, body: stack([
1456
+ siteSwitcher(_, '/admin/website/redirects', sites, siteId, options.locale ?? ''),
1457
+ ...(siteId
1458
+ ? [
1459
+ _jsx(Section, { title: editing ? _('website_backend.redirects.edit') : _('website_backend.redirects.add'), description: _('website_backend.redirects.addHint'), body: _jsx(Surface, { padding: "compact", body: _jsx(RecordForm, { action: `/admin/website/redirects${editing ? `/${editing.id}` : ''}${options.locale ?? ''}`, hidden: { siteId }, layout: "inline", fields: [
1460
+ {
1461
+ name: 'fromPath',
1462
+ label: _('website_backend.redirects.from'),
1463
+ value: values.fromPath ?? editing?.fromPath,
1464
+ required: true,
1465
+ },
1466
+ {
1467
+ name: 'toPath',
1468
+ label: _('website_backend.redirects.to'),
1469
+ value: values.toPath ?? editing?.toPath,
1470
+ required: true,
1471
+ },
1472
+ {
1473
+ name: 'permanent',
1474
+ label: _('website_backend.redirects.permanent'),
1475
+ type: 'checkbox',
1476
+ value: values.permanent != null
1477
+ ? values.permanent === '1'
1478
+ : (editing?.permanent ?? true),
1479
+ help: _('website_backend.redirects.permanentHint'),
1480
+ },
1481
+ ], submit: _('website_backend.action.save'), submitVariant: "primary", errors: options.errors }) }) }),
1482
+ // The list already had a column for a state nothing could produce:
1483
+ // the route wrote `active: true` every time, so every row read
1484
+ // "active" for ever and the off switch on the contract was unreachable.
1485
+ inline([
1486
+ linkButton({ label: _('website_backend.redirects.all'), href: query({}) }),
1487
+ linkButton({
1488
+ label: _('website_backend.state.active'),
1489
+ href: query({ state: 'active' }),
1490
+ }),
1491
+ linkButton({
1492
+ label: _('website_backend.state.inactive'),
1493
+ href: query({ state: 'inactive' }),
1494
+ }),
1495
+ ]),
1496
+ ]
1497
+ : []),
1498
+ !siteId
1499
+ ? emptyState(_('website_backend.content.noSite'), _('website_backend.content.noSiteHint'))
1500
+ : rows.length === 0
1501
+ ? emptyState(_('website_backend.redirects.empty'), _('website_backend.redirects.emptyHint'))
1502
+ : dataTable(_, {
1503
+ rows,
1504
+ id: (row) => row.id,
1505
+ columns: [
1506
+ {
1507
+ key: 'from',
1508
+ label: _('website_backend.redirects.from'),
1509
+ priority: 'primary',
1510
+ cell: (row) => row.fromPath,
1511
+ },
1512
+ { key: 'to', label: _('website_backend.redirects.to'), cell: (row) => row.toPath },
1513
+ {
1514
+ key: 'kind',
1515
+ label: _('website_backend.redirects.permanent'),
1516
+ cell: (row) => badge(row.permanent
1517
+ ? _('website_backend.redirects.p301')
1518
+ : _('website_backend.redirects.p302'), row.permanent ? 'info' : 'neutral'),
1519
+ },
1520
+ {
1521
+ key: 'status',
1522
+ label: _('website_backend.field.status'),
1523
+ cell: (row) => badge(row.active ? _('website_backend.state.active') : _('website_backend.state.inactive'), row.active ? 'positive' : 'neutral'),
1524
+ },
1525
+ {
1526
+ key: 'edit',
1527
+ label: _('website_backend.action.edit'),
1528
+ cell: (row) => linkButton({
1529
+ label: _('website_backend.action.edit'),
1530
+ href: query({ edit: row.id }),
1531
+ size: 'compact',
1532
+ }),
1533
+ },
1534
+ {
1535
+ // Off rather than deleted: the unique index holds one row per
1536
+ // `fromPath`, so deleting to "free" the path and deactivating
1537
+ // to stop it are the same reversible act, and one of them
1538
+ // keeps the history of what that address used to do.
1539
+ key: 'state',
1540
+ label: _('website_backend.redirects.state'),
1541
+ cell: (row) => (_jsx(RecordActions, { action: `/admin/website/redirects/${row.id}/state${options.locale ?? ''}`, size: "compact", actions: [
1542
+ row.active
1543
+ ? { value: 'deactivate', label: _('website_backend.action.deactivate') }
1544
+ : { value: 'activate', label: _('website_backend.action.activate') },
1545
+ ] })),
1546
+ },
1547
+ ],
1548
+ }),
1549
+ ]) }));
1550
+ };
1181
1551
  /**
1182
1552
  * Whether search is answering from the content that is actually live.
1183
1553
  *
@@ -1228,6 +1598,26 @@ const publicationTone = (state) => state === 'active' ? 'positive' : state === '
1228
1598
  */
1229
1599
  export const publicationsScreen = (_, rows, entries, sites, siteId, frame, options = {}) => (_jsx(ListScreenFrame, { translator: _, title: _('website_backend.publications.title'), frame: frame, body: stack([
1230
1600
  siteSwitcher(_, '/admin/website/publications', sites, siteId, options.locale ?? ''),
1601
+ // Superseded sets accumulate one per activation and are the majority of
1602
+ // the list within a week, which buries the two rows anybody came to see.
1603
+ ...(siteId
1604
+ ? [
1605
+ _jsx(Surface, { padding: "compact", body: _jsx(RecordForm, { action: `/admin/website/publications${options.locale ?? ''}`, method: "get", layout: "inline", hidden: { site: siteId }, fields: [
1606
+ {
1607
+ name: 'state',
1608
+ label: _('website_backend.field.status'),
1609
+ type: 'select',
1610
+ value: options.state ?? 'all',
1611
+ options: [
1612
+ { value: 'all', label: _('website_backend.state.all') },
1613
+ { value: 'prepared', label: _('website_backend.pubstate.prepared') },
1614
+ { value: 'active', label: _('website_backend.pubstate.active') },
1615
+ { value: 'superseded', label: _('website_backend.pubstate.superseded') },
1616
+ ],
1617
+ },
1618
+ ], submit: _('website_backend.action.apply'), submitVariant: "secondary" }) }),
1619
+ ]
1620
+ : []),
1231
1621
  ...(options.notice
1232
1622
  ? [_jsx(Notice, { tone: "positive", title: _('website_backend.publications.done'), message: options.notice })]
1233
1623
  : []),
@@ -1275,20 +1665,13 @@ export const publicationsScreen = (_, rows, entries, sites, siteId, frame, optio
1275
1665
  {
1276
1666
  key: 'act',
1277
1667
  label: _('website_backend.publications.action'),
1278
- cell: (row) => row.state === 'prepared'
1279
- ? linkButton({
1280
- label: _('website_backend.action.activate'),
1281
- href: `/admin/website/publications/${row.id}/activate${options.locale ?? ''}`,
1282
- size: 'compact',
1283
- variant: 'primary',
1284
- })
1285
- : row.state === 'active'
1286
- ? linkButton({
1287
- label: _('website_backend.action.rollback'),
1288
- href: `/admin/website/publications/${row.id}/rollback${options.locale ?? ''}`,
1289
- size: 'compact',
1290
- })
1291
- : '',
1668
+ cell: (row) => row.state === 'prepared' ? (_jsx(RecordActions, { action: `/admin/website/publications/${row.id}/activate${options.locale ?? ''}`, hidden: { expectedPublicationId: options.activeId ?? '' }, size: "compact", actions: [
1669
+ {
1670
+ value: 'activate',
1671
+ label: _('website_backend.action.activate'),
1672
+ variant: 'primary',
1673
+ },
1674
+ ] })) : row.state === 'active' ? (_jsx(RecordActions, { action: `/admin/website/publications/${row.id}/rollback${options.locale ?? ''}`, size: "compact", actions: [{ value: 'rollback', label: _('website_backend.action.rollback') }] })) : (''),
1292
1675
  },
1293
1676
  ],
1294
1677
  }),
@@ -1329,4 +1712,67 @@ export const entrySeoSection = (_, entryId, seo, locale = '') => (_jsx(Section,
1329
1712
  span: 'full',
1330
1713
  },
1331
1714
  ], submit: _('website_backend.action.save'), submitVariant: "secondary" }) }) }));
1715
+ /** One row's worth of trouble, in the order somebody would act on it. */
1716
+ export const concernsOf = (_, health) => {
1717
+ const concerns = [];
1718
+ // A site with no host answers nowhere, which outranks anything about content.
1719
+ if (health.domainCount === 0)
1720
+ concerns.push({ key: 'noDomain', label: _('website_backend.health.noDomain'), tone: 'danger' });
1721
+ else if (!health.primaryHost)
1722
+ concerns.push({ key: 'noPrimary', label: _('website_backend.health.noPrimary'), tone: 'danger' });
1723
+ if (!health.active)
1724
+ concerns.push({ key: 'suspended', label: _('website_backend.health.suspended'), tone: 'warning' });
1725
+ if (health.preparedCount > 0)
1726
+ concerns.push({ key: 'prepared', label: _('website_backend.health.prepared'), tone: 'info' });
1727
+ if (!health.indexCurrent && health.indexState !== 'absent')
1728
+ concerns.push({ key: 'staleIndex', label: _('website_backend.health.staleIndex'), tone: 'warning' });
1729
+ return concerns;
1730
+ };
1731
+ /**
1732
+ * Which site needs looking at, across all of them.
1733
+ *
1734
+ * Every other screen here is scoped to one site, because every contract behind
1735
+ * them takes a `siteId`. That makes "is anything wrong" a question you can only
1736
+ * answer by opening each site in turn and remembering - and the things worth
1737
+ * knowing are exactly the ones nobody goes looking for: a site with no primary
1738
+ * host publishing the wrong canonical to every crawler, a publication prepared
1739
+ * last week and never activated, an index that has not caught up.
1740
+ *
1741
+ * Read-only and built from reads that already existed. It is a place to notice,
1742
+ * and every row leads to the screen that fixes the thing.
1743
+ */
1744
+ export const siteHealthScreen = (_, rows, frame, locale = '') => {
1745
+ const troubled = rows.filter((row) => concernsOf(_, row).length > 0);
1746
+ return (_jsx(ListScreenFrame, { translator: _, title: _('website_backend.health.title'), frame: frame, body: stack([
1747
+ rows.length === 0 ? (emptyState(_('website_backend.sites.empty'), _('website_backend.sites.emptyHint'))) : troubled.length === 0 ? (_jsx(Notice, { tone: "positive", title: _('website_backend.health.allWell'), message: _('website_backend.health.allWellHint') })) : (dataTable(_, {
1748
+ rows: troubled,
1749
+ id: (row) => row.siteId,
1750
+ rowHref: (row) => `/admin/website/sites/${row.siteId}${locale}`,
1751
+ columns: [
1752
+ {
1753
+ key: 'site',
1754
+ label: _('website_backend.field.site'),
1755
+ priority: 'primary',
1756
+ cell: (row) => row.title,
1757
+ },
1758
+ {
1759
+ key: 'host',
1760
+ label: _('website_backend.domains.host'),
1761
+ kind: 'identifier',
1762
+ cell: (row) => row.primaryHost ? code(row.primaryHost) : badge(_('website_backend.health.none'), 'danger'),
1763
+ },
1764
+ {
1765
+ key: 'concerns',
1766
+ label: _('website_backend.health.concerns'),
1767
+ cell: (row) => inline(concernsOf(_, row).map((concern) => badge(concern.label, concern.tone))),
1768
+ },
1769
+ ],
1770
+ })),
1771
+ // The quiet sites are worth showing too: a list that only ever holds
1772
+ // problems cannot tell "nothing is wrong" from "nothing was checked".
1773
+ ...(rows.length
1774
+ ? [_jsx(Notice, { tone: "info", title: _('website_backend.health.checked'), message: `${rows.length}` })]
1775
+ : []),
1776
+ ]) }));
1777
+ };
1332
1778
  //# sourceMappingURL=index.js.map