shutro-erp 0.3.4 → 0.3.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 (618) hide show
  1. package/dist/account_asset/.kosh/bindings.d.ts +22 -0
  2. package/dist/account_asset/.kosh/bindings.js +15 -0
  3. package/dist/account_asset/.kosh/schema.d.ts +1755 -0
  4. package/dist/account_asset/board.d.ts +61 -0
  5. package/dist/account_asset/board.js +86 -0
  6. package/dist/account_asset/books.d.ts +42 -0
  7. package/dist/account_asset/books.js +398 -0
  8. package/dist/account_asset/demo.d.ts +7 -0
  9. package/dist/account_asset/demo.js +72 -0
  10. package/dist/account_asset/index.d.ts +9 -0
  11. package/dist/account_asset/index.js +335 -0
  12. package/dist/account_asset/module.d.ts +7622 -0
  13. package/dist/account_asset/module.js +230 -0
  14. package/dist/account_budget/.kosh/bindings.d.ts +22 -0
  15. package/dist/account_budget/.kosh/bindings.js +15 -0
  16. package/dist/account_budget/.kosh/schema.d.ts +1767 -0
  17. package/dist/account_budget/budget.d.ts +5 -0
  18. package/dist/account_budget/budget.js +142 -0
  19. package/dist/account_budget/demo.d.ts +6 -0
  20. package/dist/account_budget/demo.js +30 -0
  21. package/dist/account_budget/index.d.ts +4 -0
  22. package/dist/account_budget/index.js +223 -0
  23. package/dist/account_budget/module.d.ts +13863 -0
  24. package/dist/account_budget/module.js +167 -0
  25. package/dist/account_portal/.kosh/bindings.js +1 -1
  26. package/dist/account_portal/.kosh/schema.d.ts +176 -6
  27. package/dist/account_portal/module.d.ts +505 -6
  28. package/dist/accounting/.kosh/bindings.js +1 -1
  29. package/dist/accounting/.kosh/schema.d.ts +176 -6
  30. package/dist/accounting/index.d.ts +1 -1
  31. package/dist/accounting/index.js +344 -4
  32. package/dist/accounting/module.d.ts +513 -5
  33. package/dist/accounting/module.js +55 -3
  34. package/dist/approvals/.kosh/bindings.d.ts +22 -0
  35. package/dist/approvals/.kosh/bindings.js +15 -0
  36. package/dist/approvals/.kosh/schema.d.ts +611 -0
  37. package/dist/approvals/index.d.ts +18 -0
  38. package/dist/approvals/index.js +302 -0
  39. package/dist/approvals/mails.d.ts +25 -0
  40. package/dist/approvals/mails.js +82 -0
  41. package/dist/approvals/module.d.ts +1 -0
  42. package/dist/approvals/module.js +12 -0
  43. package/dist/approvals/web/History.d.ts +4 -0
  44. package/dist/approvals/web/History.js +13 -0
  45. package/dist/approvals/web/Inbox.d.ts +9 -0
  46. package/dist/approvals/web/Inbox.js +114 -0
  47. package/dist/approvals/web/Mine.d.ts +7 -0
  48. package/dist/approvals/web/Mine.js +27 -0
  49. package/dist/approvals/web/index.d.ts +13 -0
  50. package/dist/approvals/web/index.js +22 -0
  51. package/dist/approvals/web/messages.d.ts +2 -0
  52. package/dist/approvals/web/messages.js +119 -0
  53. package/dist/approvals/web/shared.d.ts +59 -0
  54. package/dist/approvals/web/shared.js +46 -0
  55. package/dist/attendance/.kosh/bindings.d.ts +22 -0
  56. package/dist/attendance/.kosh/bindings.js +15 -0
  57. package/dist/attendance/.kosh/schema.d.ts +1048 -0
  58. package/dist/attendance/days.d.ts +96 -0
  59. package/dist/attendance/days.js +430 -0
  60. package/dist/attendance/demo.d.ts +7 -0
  61. package/dist/attendance/demo.js +58 -0
  62. package/dist/attendance/index.d.ts +4 -0
  63. package/dist/attendance/index.js +513 -0
  64. package/dist/attendance/module.d.ts +3969 -0
  65. package/dist/attendance/module.js +412 -0
  66. package/dist/attendance/routes.d.ts +16 -0
  67. package/dist/attendance/routes.js +266 -0
  68. package/dist/attendance/web/Check.d.ts +8 -0
  69. package/dist/attendance/web/Check.js +40 -0
  70. package/dist/attendance/web/Kiosk.d.ts +8 -0
  71. package/dist/attendance/web/Kiosk.js +62 -0
  72. package/dist/attendance/web/PinButton.d.ts +7 -0
  73. package/dist/attendance/web/PinButton.js +29 -0
  74. package/dist/attendance/web/index.d.ts +13 -0
  75. package/dist/attendance/web/index.js +22 -0
  76. package/dist/attendance/web/messages.d.ts +2 -0
  77. package/dist/attendance/web/messages.js +61 -0
  78. package/dist/calendar/.kosh/bindings.d.ts +22 -0
  79. package/dist/calendar/.kosh/bindings.js +15 -0
  80. package/dist/calendar/.kosh/schema.d.ts +795 -0
  81. package/dist/calendar/demo.d.ts +6 -0
  82. package/dist/calendar/demo.js +24 -0
  83. package/dist/calendar/index.d.ts +3 -0
  84. package/dist/calendar/index.js +291 -0
  85. package/dist/calendar/module.d.ts +1705 -0
  86. package/dist/calendar/module.js +180 -0
  87. package/dist/cli/init.js +80 -0
  88. package/dist/cli/templates.d.ts +1 -1
  89. package/dist/cli/templates.js +226 -0
  90. package/dist/contacts/.kosh/bindings.js +1 -1
  91. package/dist/contacts/.kosh/schema.d.ts +78 -3
  92. package/dist/contacts/demo.js +30 -1
  93. package/dist/contacts/index.d.ts +1 -1
  94. package/dist/contacts/index.js +155 -9
  95. package/dist/contacts/module.d.ts +338 -2
  96. package/dist/contacts/module.js +93 -5
  97. package/dist/crm/.kosh/bindings.d.ts +22 -0
  98. package/dist/crm/.kosh/bindings.js +15 -0
  99. package/dist/crm/.kosh/schema.d.ts +800 -0
  100. package/dist/crm/demo.d.ts +6 -0
  101. package/dist/crm/demo.js +45 -0
  102. package/dist/crm/index.d.ts +3 -0
  103. package/dist/crm/index.js +361 -0
  104. package/dist/crm/module.d.ts +1845 -0
  105. package/dist/crm/module.js +208 -0
  106. package/dist/documents/.kosh/bindings.d.ts +22 -0
  107. package/dist/documents/.kosh/bindings.js +15 -0
  108. package/dist/documents/.kosh/schema.d.ts +862 -0
  109. package/dist/documents/demo.d.ts +6 -0
  110. package/dist/documents/demo.js +22 -0
  111. package/dist/documents/documents.d.ts +98 -0
  112. package/dist/documents/documents.js +318 -0
  113. package/dist/documents/index.d.ts +30 -0
  114. package/dist/documents/index.js +442 -0
  115. package/dist/documents/module.d.ts +2781 -0
  116. package/dist/documents/module.js +214 -0
  117. package/dist/documents/web/Versions.d.ts +7 -0
  118. package/dist/documents/web/Versions.js +45 -0
  119. package/dist/documents/web/index.d.ts +11 -0
  120. package/dist/documents/web/index.js +16 -0
  121. package/dist/documents/web/messages.d.ts +2 -0
  122. package/dist/documents/web/messages.js +21 -0
  123. package/dist/event/.kosh/bindings.d.ts +22 -0
  124. package/dist/event/.kosh/bindings.js +15 -0
  125. package/dist/event/.kosh/schema.d.ts +843 -0
  126. package/dist/event/demo.d.ts +6 -0
  127. package/dist/event/demo.js +65 -0
  128. package/dist/event/index.d.ts +14 -0
  129. package/dist/event/index.js +333 -0
  130. package/dist/event/mails.d.ts +15 -0
  131. package/dist/event/mails.js +112 -0
  132. package/dist/event/module.d.ts +2800 -0
  133. package/dist/event/module.js +323 -0
  134. package/dist/event/web/CheckInBox.d.ts +9 -0
  135. package/dist/event/web/CheckInBox.js +87 -0
  136. package/dist/event/web/index.d.ts +11 -0
  137. package/dist/event/web/index.js +16 -0
  138. package/dist/event/web/messages.d.ts +2 -0
  139. package/dist/event/web/messages.js +23 -0
  140. package/dist/event_account/.kosh/bindings.d.ts +22 -0
  141. package/dist/event_account/.kosh/bindings.js +15 -0
  142. package/dist/event_account/.kosh/schema.d.ts +1758 -0
  143. package/dist/event_account/index.d.ts +3 -0
  144. package/dist/event_account/index.js +28 -0
  145. package/dist/event_account/module.d.ts +7114 -0
  146. package/dist/event_account/module.js +90 -0
  147. package/dist/expense/.kosh/bindings.d.ts +22 -0
  148. package/dist/expense/.kosh/bindings.js +15 -0
  149. package/dist/expense/.kosh/schema.d.ts +1299 -0
  150. package/dist/expense/demo.d.ts +7 -0
  151. package/dist/expense/demo.js +69 -0
  152. package/dist/expense/index.d.ts +3 -0
  153. package/dist/expense/index.js +495 -0
  154. package/dist/expense/module.d.ts +4747 -0
  155. package/dist/expense/module.js +647 -0
  156. package/dist/expense_account/.kosh/bindings.d.ts +22 -0
  157. package/dist/expense_account/.kosh/bindings.js +15 -0
  158. package/dist/expense_account/.kosh/schema.d.ts +1936 -0
  159. package/dist/expense_account/index.d.ts +3 -0
  160. package/dist/expense_account/index.js +74 -0
  161. package/dist/expense_account/module.d.ts +9153 -0
  162. package/dist/expense_account/module.js +318 -0
  163. package/dist/helpdesk/.kosh/bindings.d.ts +22 -0
  164. package/dist/helpdesk/.kosh/bindings.js +15 -0
  165. package/dist/helpdesk/.kosh/schema.d.ts +885 -0
  166. package/dist/helpdesk/demo.d.ts +7 -0
  167. package/dist/helpdesk/demo.js +65 -0
  168. package/dist/helpdesk/hours.d.ts +17 -0
  169. package/dist/helpdesk/hours.js +94 -0
  170. package/dist/helpdesk/index.d.ts +10 -0
  171. package/dist/helpdesk/index.js +461 -0
  172. package/dist/helpdesk/module.d.ts +2940 -0
  173. package/dist/helpdesk/module.js +326 -0
  174. package/dist/helpdesk/routes.d.ts +12 -0
  175. package/dist/helpdesk/routes.js +132 -0
  176. package/dist/helpdesk/sla.d.ts +37 -0
  177. package/dist/helpdesk/sla.js +226 -0
  178. package/dist/hr/.kosh/bindings.d.ts +22 -0
  179. package/dist/hr/.kosh/bindings.js +15 -0
  180. package/dist/hr/.kosh/schema.d.ts +878 -0
  181. package/dist/hr/demo.d.ts +6 -0
  182. package/dist/hr/demo.js +60 -0
  183. package/dist/hr/index.d.ts +3 -0
  184. package/dist/hr/index.js +483 -0
  185. package/dist/hr/module.d.ts +2611 -0
  186. package/dist/hr/module.js +350 -0
  187. package/dist/l10n_bd/.kosh/bindings.js +1 -1
  188. package/dist/l10n_bd/.kosh/schema.d.ts +176 -6
  189. package/dist/l10n_bd/module.d.ts +505 -6
  190. package/dist/l10n_bd_payroll/.kosh/bindings.d.ts +22 -0
  191. package/dist/l10n_bd_payroll/.kosh/bindings.js +15 -0
  192. package/dist/l10n_bd_payroll/.kosh/schema.d.ts +2312 -0
  193. package/dist/l10n_bd_payroll/data.d.ts +47 -0
  194. package/dist/l10n_bd_payroll/data.js +347 -0
  195. package/dist/l10n_bd_payroll/index.d.ts +4 -0
  196. package/dist/l10n_bd_payroll/index.js +24 -0
  197. package/dist/l10n_bd_payroll/module.d.ts +12932 -0
  198. package/dist/l10n_bd_payroll/module.js +86 -0
  199. package/dist/l10n_in/.kosh/bindings.js +1 -1
  200. package/dist/l10n_in/.kosh/schema.d.ts +176 -6
  201. package/dist/l10n_in/module.d.ts +527 -7
  202. package/dist/mail/inbound/handle.js +6 -1
  203. package/dist/maintenance/.kosh/bindings.d.ts +22 -0
  204. package/dist/maintenance/.kosh/bindings.js +15 -0
  205. package/dist/maintenance/.kosh/schema.d.ts +911 -0
  206. package/dist/maintenance/demo.d.ts +6 -0
  207. package/dist/maintenance/demo.js +60 -0
  208. package/dist/maintenance/index.d.ts +3 -0
  209. package/dist/maintenance/index.js +422 -0
  210. package/dist/maintenance/module.d.ts +3545 -0
  211. package/dist/maintenance/module.js +446 -0
  212. package/dist/maintenance_stock/.kosh/bindings.d.ts +22 -0
  213. package/dist/maintenance_stock/.kosh/bindings.js +15 -0
  214. package/dist/maintenance_stock/.kosh/schema.d.ts +1446 -0
  215. package/dist/maintenance_stock/index.d.ts +9 -0
  216. package/dist/maintenance_stock/index.js +52 -0
  217. package/dist/maintenance_stock/module.d.ts +7675 -0
  218. package/dist/maintenance_stock/module.js +192 -0
  219. package/dist/modules-sdk/index.d.ts +1 -1
  220. package/dist/modules-sdk/manifest.d.ts +109 -2
  221. package/dist/modules-sdk/manifest.js +35 -1
  222. package/dist/mrp/.kosh/bindings.d.ts +22 -0
  223. package/dist/mrp/.kosh/bindings.js +15 -0
  224. package/dist/mrp/.kosh/schema.d.ts +1453 -0
  225. package/dist/mrp/demo.d.ts +7 -0
  226. package/dist/mrp/demo.js +42 -0
  227. package/dist/mrp/index.d.ts +3 -0
  228. package/dist/mrp/index.js +393 -0
  229. package/dist/mrp/module.d.ts +9335 -0
  230. package/dist/mrp/module.js +757 -0
  231. package/dist/mrp_account/.kosh/bindings.d.ts +22 -0
  232. package/dist/mrp_account/.kosh/bindings.js +15 -0
  233. package/dist/mrp_account/.kosh/schema.d.ts +2299 -0
  234. package/dist/mrp_account/index.d.ts +3 -0
  235. package/dist/mrp_account/index.js +22 -0
  236. package/dist/mrp_account/module.d.ts +23151 -0
  237. package/dist/mrp_account/module.js +123 -0
  238. package/dist/payment/.kosh/bindings.js +1 -1
  239. package/dist/payment/.kosh/schema.d.ts +178 -7
  240. package/dist/payment/index.d.ts +41 -0
  241. package/dist/payment/index.js +131 -74
  242. package/dist/payment/module.d.ts +569 -12
  243. package/dist/payment/module.js +19 -3
  244. package/dist/payment/settle.js +10 -1
  245. package/dist/payroll/.kosh/bindings.d.ts +22 -0
  246. package/dist/payroll/.kosh/bindings.js +15 -0
  247. package/dist/payroll/.kosh/schema.d.ts +1390 -0
  248. package/dist/payroll/compute.d.ts +35 -0
  249. package/dist/payroll/compute.js +398 -0
  250. package/dist/payroll/demo.d.ts +55 -0
  251. package/dist/payroll/demo.js +121 -0
  252. package/dist/payroll/formula.d.ts +62 -0
  253. package/dist/payroll/formula.js +320 -0
  254. package/dist/payroll/index.d.ts +230 -0
  255. package/dist/payroll/index.js +713 -0
  256. package/dist/payroll/module.d.ts +9390 -0
  257. package/dist/payroll/module.js +606 -0
  258. package/dist/payroll/routes.d.ts +10 -0
  259. package/dist/payroll/routes.js +112 -0
  260. package/dist/payroll_account/.kosh/bindings.d.ts +22 -0
  261. package/dist/payroll_account/.kosh/bindings.js +15 -0
  262. package/dist/payroll_account/.kosh/schema.d.ts +2308 -0
  263. package/dist/payroll_account/index.d.ts +3 -0
  264. package/dist/payroll_account/index.js +40 -0
  265. package/dist/payroll_account/module.d.ts +12396 -0
  266. package/dist/payroll_account/module.js +256 -0
  267. package/dist/permissions/approvals.d.ts +131 -9
  268. package/dist/permissions/approvals.js +662 -57
  269. package/dist/permissions/index.d.ts +1 -1
  270. package/dist/permissions/index.js +2 -2
  271. package/dist/permissions/models.js +191 -12
  272. package/dist/permissions/routes.d.ts +6 -1
  273. package/dist/permissions/routes.js +37 -4
  274. package/dist/permissions/web/ApprovalPanel.d.ts +5 -4
  275. package/dist/permissions/web/ApprovalPanel.js +39 -13
  276. package/dist/permissions/web/index.d.ts +6 -4
  277. package/dist/permissions/web/index.js +13 -4
  278. package/dist/permissions/web/messages.d.ts +2 -0
  279. package/dist/permissions/web/messages.js +43 -0
  280. package/dist/portal/.kosh/bindings.js +1 -1
  281. package/dist/portal/.kosh/schema.d.ts +78 -3
  282. package/dist/portal/index.js +1 -1
  283. package/dist/portal/module.d.ts +166 -2
  284. package/dist/pos/.kosh/bindings.d.ts +22 -0
  285. package/dist/pos/.kosh/bindings.js +15 -0
  286. package/dist/pos/.kosh/schema.d.ts +1809 -0
  287. package/dist/pos/accounting.d.ts +10 -0
  288. package/dist/pos/accounting.js +149 -0
  289. package/dist/pos/demo.d.ts +6 -0
  290. package/dist/pos/demo.js +90 -0
  291. package/dist/pos/index.d.ts +9 -0
  292. package/dist/pos/index.js +353 -0
  293. package/dist/pos/module.d.ts +9783 -0
  294. package/dist/pos/module.js +423 -0
  295. package/dist/pos/routes.d.ts +39 -0
  296. package/dist/pos/routes.js +368 -0
  297. package/dist/pos/web/Register.d.ts +9 -0
  298. package/dist/pos/web/Register.js +252 -0
  299. package/dist/pos/web/index.d.ts +11 -0
  300. package/dist/pos/web/index.js +16 -0
  301. package/dist/pos/web/messages.d.ts +2 -0
  302. package/dist/pos/web/messages.js +87 -0
  303. package/dist/pos_stock/.kosh/bindings.d.ts +22 -0
  304. package/dist/pos_stock/.kosh/bindings.js +15 -0
  305. package/dist/pos_stock/.kosh/schema.d.ts +2208 -0
  306. package/dist/pos_stock/index.d.ts +9 -0
  307. package/dist/pos_stock/index.js +35 -0
  308. package/dist/pos_stock/module.d.ts +12803 -0
  309. package/dist/pos_stock/module.js +115 -0
  310. package/dist/product/.kosh/bindings.js +1 -1
  311. package/dist/product/.kosh/schema.d.ts +52 -1
  312. package/dist/product/index.js +94 -4
  313. package/dist/product/module.d.ts +45 -1
  314. package/dist/product/module.js +11 -3
  315. package/dist/project/.kosh/bindings.js +1 -1
  316. package/dist/project/.kosh/schema.d.ts +725 -3
  317. package/dist/project/index.d.ts +3 -1
  318. package/dist/project/index.js +1045 -18
  319. package/dist/project/module.d.ts +10168 -458
  320. package/dist/project/module.js +1578 -14
  321. package/dist/project/routes.d.ts +44 -0
  322. package/dist/project/routes.js +314 -0
  323. package/dist/project/schedule.d.ts +72 -0
  324. package/dist/project/schedule.js +192 -0
  325. package/dist/project/web/Refresh.d.ts +8 -0
  326. package/dist/project/web/Refresh.js +29 -0
  327. package/dist/project/web/Schedule.d.ts +9 -0
  328. package/dist/project/web/Schedule.js +93 -0
  329. package/dist/project/web/Structure.d.ts +8 -0
  330. package/dist/project/web/Structure.js +86 -0
  331. package/dist/project/web/Workload.d.ts +8 -0
  332. package/dist/project/web/Workload.js +43 -0
  333. package/dist/project/web/index.d.ts +14 -0
  334. package/dist/project/web/index.js +25 -0
  335. package/dist/project/web/messages.d.ts +2 -0
  336. package/dist/project/web/messages.js +85 -0
  337. package/dist/project_account/.kosh/bindings.d.ts +22 -0
  338. package/dist/project_account/.kosh/bindings.js +15 -0
  339. package/dist/project_account/.kosh/schema.d.ts +2241 -0
  340. package/dist/project_account/index.d.ts +3 -0
  341. package/dist/project_account/index.js +27 -0
  342. package/dist/project_account/module.d.ts +11539 -0
  343. package/dist/project_account/module.js +76 -0
  344. package/dist/project_portal/.kosh/bindings.js +1 -1
  345. package/dist/project_portal/.kosh/schema.d.ts +725 -3
  346. package/dist/project_portal/module.d.ts +5137 -119
  347. package/dist/project_purchase/.kosh/bindings.d.ts +22 -0
  348. package/dist/project_purchase/.kosh/bindings.js +15 -0
  349. package/dist/project_purchase/.kosh/schema.d.ts +2320 -0
  350. package/dist/project_purchase/index.d.ts +9 -0
  351. package/dist/project_purchase/index.js +22 -0
  352. package/dist/project_purchase/module.d.ts +25147 -0
  353. package/dist/project_purchase/module.js +56 -0
  354. package/dist/purchase/.kosh/bindings.js +1 -1
  355. package/dist/purchase/.kosh/schema.d.ts +150 -6
  356. package/dist/purchase/index.js +163 -3
  357. package/dist/purchase/module.d.ts +228 -5
  358. package/dist/purchase/module.js +30 -3
  359. package/dist/purchase_account/.kosh/bindings.js +1 -1
  360. package/dist/purchase_account/.kosh/schema.d.ts +180 -8
  361. package/dist/purchase_account/index.js +27 -1
  362. package/dist/purchase_account/module.d.ts +591 -30
  363. package/dist/purchase_account/module.js +13 -2
  364. package/dist/purchase_portal/.kosh/bindings.js +1 -1
  365. package/dist/purchase_portal/.kosh/schema.d.ts +150 -6
  366. package/dist/purchase_portal/module.d.ts +372 -6
  367. package/dist/purchase_stock/.kosh/bindings.d.ts +22 -0
  368. package/dist/purchase_stock/.kosh/bindings.js +15 -0
  369. package/dist/purchase_stock/.kosh/schema.d.ts +1479 -0
  370. package/dist/purchase_stock/index.d.ts +7 -0
  371. package/dist/purchase_stock/index.js +98 -0
  372. package/dist/purchase_stock/module.d.ts +7535 -0
  373. package/dist/purchase_stock/module.js +380 -0
  374. package/dist/purchase_stock_account/.kosh/bindings.d.ts +22 -0
  375. package/dist/purchase_stock_account/.kosh/bindings.js +15 -0
  376. package/dist/purchase_stock_account/.kosh/schema.d.ts +2155 -0
  377. package/dist/purchase_stock_account/index.d.ts +3 -0
  378. package/dist/purchase_stock_account/index.js +24 -0
  379. package/dist/purchase_stock_account/module.d.ts +38015 -0
  380. package/dist/purchase_stock_account/module.js +168 -0
  381. package/dist/recruitment/.kosh/bindings.d.ts +22 -0
  382. package/dist/recruitment/.kosh/bindings.js +15 -0
  383. package/dist/recruitment/.kosh/schema.d.ts +991 -0
  384. package/dist/recruitment/demo.d.ts +6 -0
  385. package/dist/recruitment/demo.js +45 -0
  386. package/dist/recruitment/index.d.ts +3 -0
  387. package/dist/recruitment/index.js +385 -0
  388. package/dist/recruitment/module.d.ts +3249 -0
  389. package/dist/recruitment/module.js +194 -0
  390. package/dist/recruitment/web/HireButton.d.ts +9 -0
  391. package/dist/recruitment/web/HireButton.js +32 -0
  392. package/dist/recruitment/web/index.d.ts +11 -0
  393. package/dist/recruitment/web/index.js +16 -0
  394. package/dist/recruitment/web/messages.d.ts +2 -0
  395. package/dist/recruitment/web/messages.js +19 -0
  396. package/dist/reporting/documents.d.ts +5 -0
  397. package/dist/reporting/documents.js +28 -1
  398. package/dist/reporting/index.d.ts +1 -1
  399. package/dist/reporting/index.js +4 -2
  400. package/dist/reporting/models.js +9 -0
  401. package/dist/reporting/overviews.d.ts +16 -0
  402. package/dist/reporting/overviews.js +56 -0
  403. package/dist/reporting/routes-documents.js +1 -1
  404. package/dist/reporting/routes.js +138 -80
  405. package/dist/reporting/web/DashboardView.d.ts +11 -0
  406. package/dist/reporting/web/DashboardView.js +2 -2
  407. package/dist/reporting/web/DesignerView.js +5 -0
  408. package/dist/reporting/web/Overview.d.ts +9 -0
  409. package/dist/reporting/web/Overview.js +53 -0
  410. package/dist/reporting/web/index.d.ts +1 -0
  411. package/dist/reporting/web/index.js +4 -1
  412. package/dist/reporting/web/messages.js +9 -0
  413. package/dist/sale_account/.kosh/bindings.js +1 -1
  414. package/dist/sale_account/.kosh/schema.d.ts +181 -6
  415. package/dist/sale_account/index.js +22 -1
  416. package/dist/sale_account/module.d.ts +639 -38
  417. package/dist/sale_portal/.kosh/bindings.js +1 -1
  418. package/dist/sale_portal/.kosh/schema.d.ts +59 -3
  419. package/dist/sale_portal/module.d.ts +435 -5
  420. package/dist/sale_project/.kosh/bindings.js +1 -1
  421. package/dist/sale_project/.kosh/schema.d.ts +732 -3
  422. package/dist/sale_project/module.d.ts +5349 -208
  423. package/dist/sale_project/module.js +17 -1
  424. package/dist/sale_stock/.kosh/bindings.d.ts +22 -0
  425. package/dist/sale_stock/.kosh/bindings.js +15 -0
  426. package/dist/sale_stock/.kosh/schema.d.ts +1303 -0
  427. package/dist/sale_stock/index.d.ts +7 -0
  428. package/dist/sale_stock/index.js +84 -0
  429. package/dist/sale_stock/module.d.ts +7514 -0
  430. package/dist/sale_stock/module.js +146 -0
  431. package/dist/sales/.kosh/bindings.js +1 -1
  432. package/dist/sales/.kosh/schema.d.ts +59 -3
  433. package/dist/sales/index.js +195 -4
  434. package/dist/sales/module.d.ts +356 -3
  435. package/dist/sales/module.js +78 -3
  436. package/dist/server/api/metadata.d.ts +5 -0
  437. package/dist/server/api/metadata.js +5 -0
  438. package/dist/server/api/rest.js +64 -1
  439. package/dist/server/api/views.js +1 -0
  440. package/dist/server/app-settings.d.ts +7 -0
  441. package/dist/server/app-settings.js +10 -0
  442. package/dist/server/auth/base.js +9 -0
  443. package/dist/server/index.d.ts +1 -0
  444. package/dist/server/index.js +1 -0
  445. package/dist/settings/app-settings.d.ts +2 -0
  446. package/dist/settings/app-settings.js +518 -0
  447. package/dist/settings/index.d.ts +1 -0
  448. package/dist/settings/index.js +15 -0
  449. package/dist/settings/people.js +29 -5
  450. package/dist/settings/web/AppSettingsPage.d.ts +11 -0
  451. package/dist/settings/web/AppSettingsPage.js +210 -0
  452. package/dist/settings/web/OverviewPage.js +16 -3
  453. package/dist/settings/web/PeoplePage.js +20 -6
  454. package/dist/settings/web/index.d.ts +1 -0
  455. package/dist/settings/web/index.js +3 -0
  456. package/dist/settings/web/messages.js +118 -2
  457. package/dist/sign/.kosh/bindings.d.ts +22 -0
  458. package/dist/sign/.kosh/bindings.js +15 -0
  459. package/dist/sign/.kosh/schema.d.ts +990 -0
  460. package/dist/sign/index.d.ts +14 -0
  461. package/dist/sign/index.js +350 -0
  462. package/dist/sign/module.d.ts +4478 -0
  463. package/dist/sign/module.js +158 -0
  464. package/dist/sign/sign.d.ts +82 -0
  465. package/dist/sign/sign.js +474 -0
  466. package/dist/stock/.kosh/bindings.d.ts +22 -0
  467. package/dist/stock/.kosh/bindings.js +15 -0
  468. package/dist/stock/.kosh/schema.d.ts +1222 -0
  469. package/dist/stock/demo.d.ts +8 -0
  470. package/dist/stock/demo.js +82 -0
  471. package/dist/stock/index.d.ts +4 -0
  472. package/dist/stock/index.js +903 -0
  473. package/dist/stock/module.d.ts +7856 -0
  474. package/dist/stock/module.js +1880 -0
  475. package/dist/stock/replenish.d.ts +38 -0
  476. package/dist/stock/replenish.js +176 -0
  477. package/dist/stock/web/Replenishment.d.ts +8 -0
  478. package/dist/stock/web/Replenishment.js +84 -0
  479. package/dist/stock/web/ScanBox.d.ts +8 -0
  480. package/dist/stock/web/ScanBox.js +90 -0
  481. package/dist/stock/web/index.d.ts +13 -0
  482. package/dist/stock/web/index.js +20 -0
  483. package/dist/stock/web/messages.d.ts +2 -0
  484. package/dist/stock/web/messages.js +77 -0
  485. package/dist/stock_account/.kosh/bindings.d.ts +22 -0
  486. package/dist/stock_account/.kosh/bindings.js +15 -0
  487. package/dist/stock_account/.kosh/schema.d.ts +2068 -0
  488. package/dist/stock_account/index.d.ts +3 -0
  489. package/dist/stock_account/index.js +140 -0
  490. package/dist/stock_account/module.d.ts +11523 -0
  491. package/dist/stock_account/module.js +339 -0
  492. package/dist/storage/attachments.d.ts +5 -0
  493. package/dist/storage/attachments.js +12 -1
  494. package/dist/storage/models.js +3 -0
  495. package/dist/storage/routes.js +13 -2
  496. package/dist/todo/.kosh/bindings.d.ts +22 -0
  497. package/dist/todo/.kosh/bindings.js +15 -0
  498. package/dist/todo/.kosh/schema.d.ts +732 -0
  499. package/dist/todo/demo.d.ts +6 -0
  500. package/dist/todo/demo.js +35 -0
  501. package/dist/todo/index.d.ts +3 -0
  502. package/dist/todo/index.js +187 -0
  503. package/dist/todo/module.d.ts +1180 -0
  504. package/dist/todo/module.js +130 -0
  505. package/dist/trade_finance/.kosh/bindings.d.ts +22 -0
  506. package/dist/trade_finance/.kosh/bindings.js +15 -0
  507. package/dist/trade_finance/.kosh/schema.d.ts +884 -0
  508. package/dist/trade_finance/demo.d.ts +6 -0
  509. package/dist/trade_finance/demo.js +63 -0
  510. package/dist/trade_finance/index.d.ts +3 -0
  511. package/dist/trade_finance/index.js +415 -0
  512. package/dist/trade_finance/module.d.ts +3779 -0
  513. package/dist/trade_finance/module.js +507 -0
  514. package/dist/trade_finance_account/.kosh/bindings.d.ts +22 -0
  515. package/dist/trade_finance_account/.kosh/bindings.js +15 -0
  516. package/dist/trade_finance_account/.kosh/schema.d.ts +1830 -0
  517. package/dist/trade_finance_account/index.d.ts +3 -0
  518. package/dist/trade_finance_account/index.js +93 -0
  519. package/dist/trade_finance_account/module.d.ts +8074 -0
  520. package/dist/trade_finance_account/module.js +245 -0
  521. package/dist/trade_finance_purchase/.kosh/bindings.d.ts +22 -0
  522. package/dist/trade_finance_purchase/.kosh/bindings.js +15 -0
  523. package/dist/trade_finance_purchase/.kosh/schema.d.ts +1246 -0
  524. package/dist/trade_finance_purchase/index.d.ts +8 -0
  525. package/dist/trade_finance_purchase/index.js +50 -0
  526. package/dist/trade_finance_purchase/module.d.ts +4257 -0
  527. package/dist/trade_finance_purchase/module.js +44 -0
  528. package/dist/trade_finance_sale/.kosh/bindings.d.ts +22 -0
  529. package/dist/trade_finance_sale/.kosh/bindings.js +15 -0
  530. package/dist/trade_finance_sale/.kosh/schema.d.ts +1072 -0
  531. package/dist/trade_finance_sale/index.d.ts +8 -0
  532. package/dist/trade_finance_sale/index.js +50 -0
  533. package/dist/trade_finance_sale/module.d.ts +4281 -0
  534. package/dist/trade_finance_sale/module.js +44 -0
  535. package/dist/ui/api.d.ts +2 -1
  536. package/dist/ui/api.js +2 -1
  537. package/dist/ui/app.js +26 -13
  538. package/dist/ui/components/AppIcon.js +30 -1
  539. package/dist/ui/components/primitives.d.ts +2 -0
  540. package/dist/ui/components/primitives.js +7 -1
  541. package/dist/ui/i18n/messages.d.ts +27 -0
  542. package/dist/ui/i18n/messages.js +46 -0
  543. package/dist/ui/index.d.ts +1 -0
  544. package/dist/ui/index.js +1 -0
  545. package/dist/ui/offline/queue.d.ts +5 -1
  546. package/dist/ui/offline/queue.js +2 -0
  547. package/dist/ui/registry.d.ts +5 -0
  548. package/dist/ui/shell/Home.js +55 -4
  549. package/dist/ui/views/FormView.js +102 -19
  550. package/dist/ui/views/KanbanView.d.ts +2 -0
  551. package/dist/ui/views/KanbanView.js +40 -3
  552. package/dist/ui/views/ListView.js +110 -11
  553. package/dist/ui/views/StatsRow.d.ts +14 -0
  554. package/dist/ui/views/StatsRow.js +88 -0
  555. package/dist/ui/views/widgets.d.ts +2 -1
  556. package/dist/ui/views/widgets.js +200 -1
  557. package/dist/views/builders.d.ts +19 -2
  558. package/dist/views/builders.js +21 -1
  559. package/dist/views/condition.d.ts +6 -0
  560. package/dist/views/condition.js +20 -0
  561. package/dist/views/documents.d.ts +8 -0
  562. package/dist/views/extend.d.ts +2 -2
  563. package/dist/views/extend.js +11 -1
  564. package/dist/views/index.d.ts +2 -2
  565. package/dist/views/index.js +2 -2
  566. package/dist/views/types.d.ts +52 -5
  567. package/dist/views/validate.js +39 -1
  568. package/dist/website/.kosh/bindings.d.ts +22 -0
  569. package/dist/website/.kosh/bindings.js +15 -0
  570. package/dist/website/.kosh/schema.d.ts +881 -0
  571. package/dist/website/demo.d.ts +6 -0
  572. package/dist/website/demo.js +115 -0
  573. package/dist/website/index.d.ts +9 -0
  574. package/dist/website/index.js +251 -0
  575. package/dist/website/module.d.ts +2987 -0
  576. package/dist/website/module.js +282 -0
  577. package/dist/website/render.d.ts +45 -0
  578. package/dist/website/render.js +102 -0
  579. package/dist/website/routes.d.ts +12 -0
  580. package/dist/website/routes.js +246 -0
  581. package/dist/website/web/PagePreview.d.ts +7 -0
  582. package/dist/website/web/PagePreview.js +33 -0
  583. package/dist/website/web/index.d.ts +11 -0
  584. package/dist/website/web/index.js +16 -0
  585. package/dist/website/web/messages.d.ts +2 -0
  586. package/dist/website/web/messages.js +15 -0
  587. package/dist/website_crm/.kosh/bindings.d.ts +22 -0
  588. package/dist/website_crm/.kosh/bindings.js +15 -0
  589. package/dist/website_crm/.kosh/schema.d.ts +967 -0
  590. package/dist/website_crm/index.d.ts +3 -0
  591. package/dist/website_crm/index.js +39 -0
  592. package/dist/website_crm/module.d.ts +2956 -0
  593. package/dist/website_crm/module.js +44 -0
  594. package/dist/website_sale/.kosh/bindings.d.ts +22 -0
  595. package/dist/website_sale/.kosh/bindings.js +15 -0
  596. package/dist/website_sale/.kosh/schema.d.ts +2284 -0
  597. package/dist/website_sale/couriers.d.ts +50 -0
  598. package/dist/website_sale/couriers.js +59 -0
  599. package/dist/website_sale/demo.d.ts +7 -0
  600. package/dist/website_sale/demo.js +90 -0
  601. package/dist/website_sale/growth.d.ts +31 -0
  602. package/dist/website_sale/growth.js +163 -0
  603. package/dist/website_sale/index.d.ts +49 -0
  604. package/dist/website_sale/index.js +538 -0
  605. package/dist/website_sale/module.d.ts +22027 -0
  606. package/dist/website_sale/module.js +397 -0
  607. package/dist/website_sale/shipments.d.ts +16 -0
  608. package/dist/website_sale/shipments.js +113 -0
  609. package/dist/website_sale/shop.d.ts +81 -0
  610. package/dist/website_sale/shop.js +649 -0
  611. package/dist/website_sale_stock/.kosh/bindings.d.ts +22 -0
  612. package/dist/website_sale_stock/.kosh/bindings.js +15 -0
  613. package/dist/website_sale_stock/.kosh/schema.d.ts +2681 -0
  614. package/dist/website_sale_stock/index.d.ts +9 -0
  615. package/dist/website_sale_stock/index.js +20 -0
  616. package/dist/website_sale_stock/module.d.ts +24998 -0
  617. package/dist/website_sale_stock/module.js +28 -0
  618. package/package.json +200 -2
@@ -0,0 +1,44 @@
1
+ /**
2
+ * The data layer of the Trade Finance ↔ Sales bridge (RFC 0021, Trade Finance step 3): an export LC received for a sales order takes its customer, currency and amount; the order lists its LCs.
3
+ */
4
+ import { salesShutro } from '../sales/index.js';
5
+ import { orm } from '../server/orm.js';
6
+ import { tradeFinanceShutro } from '../trade_finance/index.js';
7
+ import { defineModule, extendModel, f, onchange } from './.kosh/bindings.js';
8
+ export const LcSale = extendModel('trade.lc', {
9
+ fields: {
10
+ saleOrder: f.many2one('sale.order', { ondelete: 'set null', label: 'Sales order' }),
11
+ },
12
+ onchange: {
13
+ // The order's counterparty, currency and total; the LC's direction and source document.
14
+ saleOrder: onchange('trade.lc', async (d) => {
15
+ const order = await d.record('saleOrder');
16
+ if (order === null || order === undefined)
17
+ return;
18
+ d.set('direction', 'export');
19
+ d.set('partner', order.partner.id);
20
+ d.set('currency', order.currency.id);
21
+ d.set('amount', order.amountTotal?.amount.toString() ?? null);
22
+ d.set('origin', order.name);
23
+ }),
24
+ },
25
+ });
26
+ export const SaleLcs = extendModel('sale.order', {
27
+ fields: {
28
+ lcs: f.one2many('trade.lc', 'saleOrder', { label: 'Letters of credit' }),
29
+ },
30
+ });
31
+ export const tradeFinanceSaleShutro = defineModule({
32
+ name: 'trade_finance_sale',
33
+ version: '0.1.0',
34
+ depends: [tradeFinanceShutro, salesShutro],
35
+ groups: [
36
+ orm.defineGroup({
37
+ code: 'trade_finance_sale.user',
38
+ label: 'Export LCs for sales orders',
39
+ implies: ['trade_finance.user', 'sales.user'],
40
+ }),
41
+ ],
42
+ models: [],
43
+ extensions: [LcSale, SaleLcs],
44
+ });
package/dist/ui/api.d.ts CHANGED
@@ -36,6 +36,7 @@ export interface ViewField {
36
36
  readonly label: string;
37
37
  readonly required: boolean;
38
38
  readonly readonly: boolean;
39
+ readonly help?: string;
39
40
  readonly target?: string;
40
41
  readonly options?: readonly {
41
42
  readonly value: string;
@@ -190,7 +191,7 @@ export interface KoshApi {
190
191
  readonly filename: string;
191
192
  }>;
192
193
  /** Sends a file as the raw body (`Content-Type` from the file, `X-Filename` URI-encoded); the JSON answer. */
193
- upload<T>(path: string, file: Blob, filename: string): Promise<T>;
194
+ upload<T>(path: string, file: Blob, filename: string, extra?: Readonly<Record<string, string>>): Promise<T>;
194
195
  /**
195
196
  * POSTs `body` and reads the server-sent events of the answer (`event:` and JSON `data:` lines), calling
196
197
  * `onEvent` for each (`message` when the event has no name) until the stream ends. @throws {ApiError} when the
package/dist/ui/api.js CHANGED
@@ -226,8 +226,9 @@ export function createKoshApi(options = {}) {
226
226
  if (buffered.trim() !== '')
227
227
  flush(buffered);
228
228
  },
229
- async upload(path, file, filename) {
229
+ async upload(path, file, filename, extra = {}) {
230
230
  const headers = {
231
+ ...extra,
231
232
  'content-type': file.type === '' ? 'application/octet-stream' : file.type,
232
233
  'x-filename': encodeURIComponent(filename),
233
234
  };
package/dist/ui/app.js CHANGED
@@ -12,7 +12,7 @@ import { compileSearch, decodeSearch, encodeSearch } from '../search/index.js';
12
12
  import { onlineManager, QueryClient, QueryClientProvider, useQuery, useQueryClient, } from '@tanstack/react-query';
13
13
  import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client';
14
14
  import { createRootRoute, createRoute, createRouter, Link, Navigate, Outlet, RouterProvider, useNavigate, useParams, useSearch, } from '@tanstack/react-router';
15
- import { CalendarDays, ChartColumn, ChartGantt, ChevronDown, ChevronRight, ChevronsUpDown, Columns3, Grid2x2, House, Languages, LayoutDashboard, List, LogOut, Map as MapIcon, Monitor, Moon, Network, PanelLeft, Plus, Search, Sheet, Sun, Table2, } from 'lucide-react';
15
+ import { Building2, CalendarDays, ChartColumn, ChartGantt, ChevronDown, ChevronRight, ChevronsUpDown, Columns3, Grid2x2, House, Languages, LayoutDashboard, List, LogOut, Map as MapIcon, Monitor, Moon, Network, PanelLeft, Plus, Search, Sheet, Sun, Table2, } from 'lucide-react';
16
16
  import { Direction } from 'radix-ui';
17
17
  import { createContext, useCallback, useContext, useEffect, useMemo, useState, } from 'react';
18
18
  import { I18nextProvider, useTranslation } from 'react-i18next';
@@ -139,6 +139,7 @@ function LanguageMenu() {
139
139
  function CompanyBlock({ me, company, collapsed, onChange, }) {
140
140
  const { t } = useTranslation();
141
141
  const { api } = useServices();
142
+ const navigate = useNavigate();
142
143
  const names = useQuery({
143
144
  queryKey: ['names', 'res.company', me.companies],
144
145
  queryFn: () => api.names('res.company', { ids: me.companies }),
@@ -147,15 +148,21 @@ function CompanyBlock({ me, company, collapsed, onChange, }) {
147
148
  const name = names.data?.find((c) => c.id === company)?.displayName ?? t('app.name');
148
149
  // The company's logo, else its initial.
149
150
  const badge = (_jsx(Avatar, { name: name.slice(0, 1), src: imageUrl('company', company, me.logos?.[String(company)]), shape: "square", className: "font-semibold" }));
150
- if (collapsed)
151
- return _jsx("span", { title: name, children: badge });
152
- if (me.companies.length < 2)
153
- return (_jsxs("div", { className: "flex items-center gap-2.5 px-1 py-1", children: [badge, _jsx("span", { className: "truncate text-sm font-semibold", children: name })] }));
154
- // Several companies: a switcher (also in the palette: "Switch to …").
155
- return (_jsxs(Menu, { children: [_jsx(MenuTrigger, { asChild: true, children: _jsxs("button", { type: "button", "aria-label": t('shell.switchCompany', { name }), className: "flex w-full items-center gap-2.5 rounded-md px-1 py-1 text-start hover:bg-muted", children: [badge, _jsx("span", { className: "min-w-0 flex-1 truncate text-sm font-semibold", children: name }), _jsx(ChevronsUpDown, { className: "size-4 shrink-0 text-muted-foreground", "aria-hidden": true })] }) }), _jsxs(MenuContent, { align: "start", className: "w-64", children: [_jsx(MenuLabel, { children: t('shell.company') }), (names.data ?? []).map((c) => (_jsx(MenuCheckboxItem, { checked: c.id === company, onCheckedChange: () => {
151
+ const several = me.companies.length > 1;
152
+ // Nothing to switch to and nothing to manage: the company's name only.
153
+ if (!several && !me.administrator)
154
+ return collapsed ? (_jsx("span", { title: name, children: badge })) : (_jsxs("div", { className: "flex items-center gap-2.5 px-1 py-1", children: [badge, _jsx("span", { className: "truncate text-sm font-semibold", children: name })] }));
155
+ // A menu: the companies to switch to (also in the palette: "Switch to …"), and for administrators the Companies
156
+ // page, where companies are added — so a one-company installation still shows where multi-company starts.
157
+ return (_jsxs(Menu, { children: [_jsx(MenuTrigger, { asChild: true, children: _jsxs("button", { type: "button", "aria-label": t(several ? 'shell.switchCompany' : 'shell.companyMenu', { name }), title: collapsed ? name : undefined, className: collapsed
158
+ ? 'rounded-md hover:bg-muted'
159
+ : 'flex w-full items-center gap-2.5 rounded-md px-1 py-1 text-start hover:bg-muted', children: [badge, collapsed ? null : (_jsxs(_Fragment, { children: [_jsx("span", { className: "min-w-0 flex-1 truncate text-sm font-semibold", children: name }), _jsx(ChevronsUpDown, { className: "size-4 shrink-0 text-muted-foreground", "aria-hidden": true })] }))] }) }), _jsxs(MenuContent, { align: "start", className: "w-64", children: [_jsx(MenuLabel, { children: t('shell.company') }), (names.data ?? []).map((c) => (_jsx(MenuCheckboxItem, { checked: c.id === company, onCheckedChange: () => {
156
160
  if (c.id !== company)
157
161
  onChange(c.id);
158
- }, children: _jsxs("span", { className: "flex items-center gap-2", children: [_jsx("span", { "aria-hidden": true, className: "grid size-5 place-items-center rounded bg-muted text-[10px] font-semibold", children: c.displayName.slice(0, 1).toUpperCase() }), c.displayName] }) }, c.id)))] })] }));
162
+ }, children: _jsxs("span", { className: "flex items-center gap-2", children: [_jsx("span", { "aria-hidden": true, className: "grid size-5 place-items-center rounded bg-muted text-[10px] font-semibold", children: c.displayName.slice(0, 1).toUpperCase() }), c.displayName] }) }, c.id))), me.administrator ? (_jsxs(_Fragment, { children: [_jsx(MenuSeparator, {}), _jsxs(MenuItem, { onSelect: () => void navigate({
163
+ to: '/$app/a/$action',
164
+ params: { app: 'settings', action: 'settings.action_companies' },
165
+ }), children: [_jsx(Building2, { "aria-hidden": true }), t(several ? 'shell.manageCompanies' : 'shell.addCompany')] })] })) : null] })] }));
159
166
  }
160
167
  function UserMenu({ user, collapsed, corner, }) {
161
168
  const { t } = useTranslation();
@@ -163,10 +170,15 @@ function UserMenu({ user, collapsed, corner, }) {
163
170
  const { theme, setTheme, density, setDensity } = useKosh();
164
171
  const queryClient = useQueryClient();
165
172
  const navigate = useNavigate();
166
- return (_jsxs(Menu, { children: [_jsx(MenuTrigger, { asChild: true, children: _jsxs("button", { type: "button", "aria-label": user.name, "data-kosh-account": corner === undefined ? 'sidebar' : 'corner', className: cn('flex min-w-0 items-center gap-2 rounded-md px-1.5 py-1.5 text-sm hover:bg-muted', corner === undefined ? 'w-full' : 'rounded-full border bg-surface pe-3', collapsed && 'justify-center'), children: [_jsx(Avatar, { name: user.name, src: imageUrl('user', user.id, user.avatar) }), collapsed ? null : _jsx("span", { className: "truncate", children: user.name }), corner === undefined ? null : (_jsx(ChevronDown, { className: "size-3.5 text-muted-foreground", "aria-hidden": true }))] }) }), _jsxs(MenuContent, { align: corner === undefined ? 'start' : 'end', side: corner === undefined ? 'top' : 'bottom', className: corner === undefined ? undefined : 'max-h-[80vh] w-64 overflow-y-auto', children: [_jsxs(MenuLabel, { children: [user.name, _jsx("span", { className: "block text-xs font-normal text-muted-foreground", children: user.login })] }), registry.userPages().map((p) => (_jsx(MenuItem, { onSelect: () => void navigate({ to: '/me/$page', params: { page: p.name } }), children: t(p.label) }, p.name))), corner === undefined ? null : (_jsxs(_Fragment, { children: [corner.companies.length < 2 ? null : (_jsxs(_Fragment, { children: [_jsx(MenuSeparator, {}), _jsx(MenuLabel, { children: t('shell.company') }), corner.companies.map((c) => (_jsx(MenuCheckboxItem, { checked: c.id === corner.current, onCheckedChange: () => {
167
- if (c.id !== corner.current)
168
- corner.onSwitch(c.id);
169
- }, children: c.name }, c.id)))] })), _jsx(MenuSeparator, {}), _jsx(MenuLabel, { children: t('shell.language') }), LANGUAGES.map((l) => (_jsx(MenuCheckboxItem, { checked: lang === l.code, onCheckedChange: () => setLang(l.code), children: _jsx("span", { lang: l.code.replace('_', '-'), children: l.name }) }, l.code))), _jsx(MenuSeparator, {}), _jsx(MenuLabel, { children: t('shell.theme') }), ['light', 'dark', 'system'].map((choice) => (_jsx(MenuCheckboxItem, { checked: theme === choice, onCheckedChange: () => setTheme(choice), children: t(`shell.${choice}`) }, choice))), _jsx(MenuLabel, { children: t('shell.density') }), ['comfortable', 'compact'].map((choice) => (_jsx(MenuCheckboxItem, { checked: density === choice, onCheckedChange: () => setDensity(choice), children: t(`views.${choice}`) }, choice)))] })), _jsx(MenuSeparator, {}), _jsxs(MenuItem, { onSelect: async () => {
173
+ return (_jsxs(Menu, { children: [_jsx(MenuTrigger, { asChild: true, children: _jsxs("button", { type: "button", "aria-label": user.name, "data-kosh-account": corner === undefined ? 'sidebar' : 'corner', className: cn('flex min-w-0 items-center gap-2 rounded-md px-1.5 py-1.5 text-sm hover:bg-muted', corner === undefined ? 'w-full' : 'rounded-full border bg-surface pe-3', collapsed && 'justify-center'), children: [_jsx(Avatar, { name: user.name, src: imageUrl('user', user.id, user.avatar) }), collapsed ? null : _jsx("span", { className: "truncate", children: user.name }), corner === undefined ? null : (_jsx(ChevronDown, { className: "size-3.5 text-muted-foreground", "aria-hidden": true }))] }) }), _jsxs(MenuContent, { align: corner === undefined ? 'start' : 'end', side: corner === undefined ? 'top' : 'bottom', className: corner === undefined ? undefined : 'max-h-[80vh] w-64 overflow-y-auto', children: [_jsxs(MenuLabel, { children: [user.name, _jsx("span", { className: "block text-xs font-normal text-muted-foreground", children: user.login })] }), registry.userPages().map((p) => (_jsx(MenuItem, { onSelect: () => void navigate({ to: '/me/$page', params: { page: p.name } }), children: t(p.label) }, p.name))), corner === undefined ? null : (_jsxs(_Fragment, { children: [corner.companies.length < 2 && !user.administrator ? null : (_jsxs(_Fragment, { children: [_jsx(MenuSeparator, {}), _jsx(MenuLabel, { children: t('shell.company') }), corner.companies.length < 2
174
+ ? null
175
+ : corner.companies.map((c) => (_jsx(MenuCheckboxItem, { checked: c.id === corner.current, onCheckedChange: () => {
176
+ if (c.id !== corner.current)
177
+ corner.onSwitch(c.id);
178
+ }, children: c.name }, c.id))), user.administrator ? (_jsxs(MenuItem, { onSelect: () => void navigate({
179
+ to: '/$app/a/$action',
180
+ params: { app: 'settings', action: 'settings.action_companies' },
181
+ }), children: [_jsx(Building2, { "aria-hidden": true }), t(corner.companies.length < 2 ? 'shell.addCompany' : 'shell.manageCompanies')] })) : null] })), _jsx(MenuSeparator, {}), _jsx(MenuLabel, { children: t('shell.language') }), LANGUAGES.map((l) => (_jsx(MenuCheckboxItem, { checked: lang === l.code, onCheckedChange: () => setLang(l.code), children: _jsx("span", { lang: l.code.replace('_', '-'), children: l.name }) }, l.code))), _jsx(MenuSeparator, {}), _jsx(MenuLabel, { children: t('shell.theme') }), ['light', 'dark', 'system'].map((choice) => (_jsx(MenuCheckboxItem, { checked: theme === choice, onCheckedChange: () => setTheme(choice), children: t(`shell.${choice}`) }, choice))), _jsx(MenuLabel, { children: t('shell.density') }), ['comfortable', 'compact'].map((choice) => (_jsx(MenuCheckboxItem, { checked: density === choice, onCheckedChange: () => setDensity(choice), children: t(`views.${choice}`) }, choice)))] })), _jsx(MenuSeparator, {}), _jsxs(MenuItem, { onSelect: async () => {
170
182
  await api.logout();
171
183
  queryClient.clear();
172
184
  await dropOfflineCache(persister);
@@ -302,10 +314,11 @@ function useServedView(action, type) {
302
314
  function ClientPage({ action }) {
303
315
  const { registry, api } = useServices();
304
316
  const { t } = useTranslation();
317
+ const params = useParams({ strict: false });
305
318
  const Page = registry.page(action.page);
306
319
  if (Page === undefined)
307
320
  return _jsx(Alert, { children: t('app.unknownPage', { page: action.page }) });
308
- return _jsx(Page, { api: api, ...(action.label === undefined ? {} : { label: action.label }) });
321
+ return (_jsx(Page, { api: api, ...(action.label === undefined ? {} : { label: action.label }), ...(params.app === undefined ? {} : { app: params.app }), ...(params.action === undefined ? {} : { action: params.action }) }));
309
322
  }
310
323
  function ActionPage() {
311
324
  const { action: actionId } = useParams({ strict: false });
@@ -3,7 +3,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
3
3
  * App icons by name (`app.icon` in a module manifest): the launcher's tiles and the App manager's cards. Names
4
4
  * follow Lucide; an unknown name shows a neutral grid, never a broken image.
5
5
  */
6
- import { BookOpen, Boxes, Briefcase, Building, Building2, ChartColumn, FolderKanban, LayoutGrid, LockKeyhole, Mail, MessageSquare, MessagesSquare, Package, PencilRuler, Plug, Receipt, Ruler, ScrollText, Settings, ShieldCheck, ShoppingCart, Sparkles, Users, Wallet, Warehouse, Workflow, } from 'lucide-react';
6
+ import { BadgeCheck, Banknote, BookOpen, Boxes, Briefcase, Building, Building2, CalendarDays, ChartColumn, Clock, Factory, FolderKanban, FolderOpen, Globe, Landmark, LayoutGrid, LifeBuoy, ListChecks, LockKeyhole, Mail, MessageSquare, MessagesSquare, Package, PencilRuler, Plug, Receipt, Ruler, ScrollText, Settings, ShieldCheck, ShoppingCart, Signature, Sparkles, Store, Ticket, TrendingUp, UserPlus, Users, Wallet, Warehouse, Workflow, Wrench, } from 'lucide-react';
7
7
  import { cn } from '../lib/cn.js';
8
8
  const ICONS = {
9
9
  settings: Settings,
@@ -38,6 +38,35 @@ const ICONS = {
38
38
  permissions: ShieldCheck,
39
39
  briefcase: Briefcase,
40
40
  plug: Plug,
41
+ focus: ListChecks,
42
+ agenda: CalendarDays,
43
+ pipeline: TrendingUp,
44
+ workforce: Briefcase,
45
+ hiring: UserPlus,
46
+ stockroom: Warehouse,
47
+ production: Factory,
48
+ assetcare: Wrench,
49
+ tradefinance: Landmark,
50
+ eventhub: Ticket,
51
+ sites: Globe,
52
+ counter: Store,
53
+ spend: Wallet,
54
+ attendance: Clock,
55
+ payroll: Banknote,
56
+ helpdesk: LifeBuoy,
57
+ documents: FolderOpen,
58
+ sign: Signature,
59
+ approvals: BadgeCheck,
60
+ event: Ticket,
61
+ trade_finance: Landmark,
62
+ maintenance: Wrench,
63
+ mrp: Factory,
64
+ stock: Warehouse,
65
+ recruitment: UserPlus,
66
+ hr: Briefcase,
67
+ crm: TrendingUp,
68
+ calendar: CalendarDays,
69
+ todo: ListChecks,
41
70
  integrations: Plug,
42
71
  cart: ShoppingCart,
43
72
  company: Building2,
@@ -76,3 +76,5 @@ export declare function EmptyState({ icon, title, description, action, }: {
76
76
  readonly description?: string;
77
77
  readonly action?: ReactNode;
78
78
  }): ReactElement;
79
+ /** The classes of a button, for elements that must look like one (a file picker's label). */
80
+ export declare function buttonClass(variant?: ButtonProps['variant'], size?: ButtonProps['size']): string;
@@ -23,7 +23,9 @@ const buttonVariants = cva('inline-flex items-center justify-center gap-2 whites
23
23
  });
24
24
  export function Button({ className, variant, size, asChild, busy, children, disabled, ...props }) {
25
25
  const Comp = asChild === true ? Slot.Root : 'button';
26
- return (_jsxs(Comp, { className: cn(buttonVariants({ variant, size }), className), disabled: disabled === true || busy === true, "aria-busy": busy === true ? true : undefined, ...props, children: [busy === true ? _jsx(Loader2, { className: "animate-spin", "aria-hidden": true }) : null, children] }));
26
+ return (_jsxs(Comp
27
+ // A button inside a record's form must not save it: only `type="submit"` submits.
28
+ , { ...(asChild === true ? {} : { type: 'button' }), className: cn(buttonVariants({ variant, size }), className), disabled: disabled === true || busy === true, "aria-busy": busy === true ? true : undefined, ...props, children: [busy === true ? _jsx(Loader2, { className: "animate-spin", "aria-hidden": true }) : null, children] }));
27
29
  }
28
30
  const field = 'w-full rounded-md border border-input bg-surface px-3 text-sm text-surface-foreground placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-60 read-only:bg-muted aria-invalid:border-danger';
29
31
  export function Input({ className, ...props }) {
@@ -120,3 +122,7 @@ export function Skeleton({ className, ...props }) {
120
122
  export function EmptyState({ icon, title, description, action, }) {
121
123
  return (_jsxs("div", { className: "flex flex-col items-center gap-2 px-6 py-12 text-center", children: [icon === undefined ? null : (_jsx("div", { className: "mb-1 flex size-12 items-center justify-center rounded-full bg-muted text-muted-foreground [&_svg]:size-6", children: icon })), _jsx("p", { className: "font-medium", children: title }), description === undefined ? null : (_jsx("p", { className: "max-w-md text-sm text-muted-foreground", children: description })), action === undefined ? null : _jsx("div", { className: "mt-2", children: action })] }));
122
124
  }
125
+ /** The classes of a button, for elements that must look like one (a file picker's label). */
126
+ export function buttonClass(variant = 'primary', size = 'md') {
127
+ return buttonVariants({ variant, size });
128
+ }
@@ -48,6 +48,9 @@ export declare const en: {
48
48
  home: string;
49
49
  appNamed: string;
50
50
  switchCompany: string;
51
+ companyMenu: string;
52
+ manageCompanies: string;
53
+ addCompany: string;
51
54
  sidebar: string;
52
55
  collapseSidebar: string;
53
56
  expandSidebar: string;
@@ -88,8 +91,13 @@ export declare const en: {
88
91
  export: string;
89
92
  exportCsv: string;
90
93
  exportXlsx: string;
94
+ exportPdf: string;
91
95
  exportFailed: string;
92
96
  columns: string;
97
+ pinned: string;
98
+ pinColumn: string;
99
+ resetWidths: string;
100
+ resize: string;
93
101
  density: string;
94
102
  statusOf: string;
95
103
  nextState: string;
@@ -167,6 +175,23 @@ export declare const en: {
167
175
  none: string;
168
176
  lines: string;
169
177
  addLine: string;
178
+ nextStep: {
179
+ ready: string;
180
+ before: string;
181
+ missing_one: string;
182
+ missing_other: string;
183
+ };
184
+ daysLeft: {
185
+ today: string;
186
+ in: string;
187
+ late: string;
188
+ };
189
+ image: {
190
+ choose: string;
191
+ remove: string;
192
+ none: string;
193
+ saveFirst: string;
194
+ };
170
195
  removeLine: string;
171
196
  choose: string;
172
197
  pasted_one: string;
@@ -239,6 +264,8 @@ export declare const en: {
239
264
  approve: string;
240
265
  review: string;
241
266
  dueToday: string;
267
+ todo: string;
268
+ meetings: string;
242
269
  mentioned: string;
243
270
  saved: string;
244
271
  };
@@ -48,6 +48,9 @@ export const en = {
48
48
  home: 'Home',
49
49
  appNamed: '{{app}} app',
50
50
  switchCompany: 'Company: {{name}} (switch)',
51
+ companyMenu: 'Company: {{name}}',
52
+ manageCompanies: 'Companies…',
53
+ addCompany: 'Add a company…',
51
54
  sidebar: 'Sidebar',
52
55
  collapseSidebar: 'Collapse the sidebar',
53
56
  expandSidebar: 'Expand the sidebar',
@@ -88,8 +91,13 @@ export const en = {
88
91
  export: 'Export',
89
92
  exportCsv: 'CSV (all columns)',
90
93
  exportXlsx: 'Excel',
94
+ exportPdf: 'Print as PDF',
91
95
  exportFailed: 'The export failed: {{reason}}',
92
96
  columns: 'Columns',
97
+ pinned: 'Pinned at the start',
98
+ pinColumn: 'Pin {{name}}',
99
+ resetWidths: 'Reset column widths',
100
+ resize: 'Resize {{column}}',
93
101
  density: 'Density',
94
102
  statusOf: '{{field}}: {{state}}',
95
103
  nextState: 'Next',
@@ -164,6 +172,19 @@ export const en = {
164
172
  none: 'None',
165
173
  lines: 'Lines',
166
174
  addLine: 'Add a line',
175
+ nextStep: {
176
+ ready: 'Next step: {{step}}.',
177
+ before: 'Before {{step}}:',
178
+ missing_one: '{{count}} thing to fill in',
179
+ missing_other: '{{count}} things to fill in',
180
+ },
181
+ daysLeft: { today: 'Today', in: 'In {{count}} days', late: '{{count}} days late' },
182
+ image: {
183
+ choose: 'Choose a picture',
184
+ remove: 'Remove',
185
+ none: 'No picture',
186
+ saveFirst: 'Save the record first, then add its picture.',
187
+ },
167
188
  removeLine: 'Remove line',
168
189
  choose: 'Choose…',
169
190
  pasted_one: '{{count}} cell pasted',
@@ -236,6 +257,8 @@ export const en = {
236
257
  approve: 'Approve {{record}}',
237
258
  review: 'Review',
238
259
  dueToday: 'due today',
260
+ todo: 'Focus to-do',
261
+ meetings: 'Today’s meetings',
239
262
  mentioned: '{{actor}} mentioned you on {{record}}',
240
263
  saved: 'Your saved views',
241
264
  },
@@ -359,6 +382,9 @@ export const bn = {
359
382
  home: 'হোম',
360
383
  appNamed: '{{app}} অ্যাপ',
361
384
  switchCompany: 'প্রতিষ্ঠান: {{name}} (বদলান)',
385
+ companyMenu: 'প্রতিষ্ঠান: {{name}}',
386
+ manageCompanies: 'প্রতিষ্ঠানসমূহ…',
387
+ addCompany: 'প্রতিষ্ঠান যোগ করুন…',
362
388
  sidebar: 'সাইডবার',
363
389
  collapseSidebar: 'সাইডবার ছোট করুন',
364
390
  expandSidebar: 'সাইডবার বড় করুন',
@@ -399,8 +425,13 @@ export const bn = {
399
425
  export: 'এক্সপোর্ট',
400
426
  exportCsv: 'CSV (সব কলাম)',
401
427
  exportXlsx: 'এক্সেল',
428
+ exportPdf: 'PDF হিসেবে ছাপুন',
402
429
  exportFailed: 'এক্সপোর্ট ব্যর্থ: {{reason}}',
403
430
  columns: 'কলাম',
431
+ pinned: 'শুরুতে আটকানো',
432
+ pinColumn: '{{name}} আটকান',
433
+ resetWidths: 'কলামের প্রস্থ মুছুন',
434
+ resize: '{{column}} প্রস্থ বদলান',
404
435
  density: 'ঘনত্ব',
405
436
  statusOf: '{{field}}: {{state}}',
406
437
  nextState: 'পরবর্তী',
@@ -472,6 +503,19 @@ export const bn = {
472
503
  none: 'কিছু না',
473
504
  lines: 'লাইন',
474
505
  addLine: 'লাইন যোগ করুন',
506
+ nextStep: {
507
+ ready: 'পরের ধাপ: {{step}}।',
508
+ before: '{{step}}-এর আগে:',
509
+ missing_one: '{{count}}টি ঘর পূরণ করতে হবে',
510
+ missing_other: '{{count}}টি ঘর পূরণ করতে হবে',
511
+ },
512
+ daysLeft: { today: 'আজ', in: '{{count}} দিনে', late: '{{count}} দিন দেরি' },
513
+ image: {
514
+ choose: 'ছবি বাছুন',
515
+ remove: 'সরান',
516
+ none: 'ছবি নেই',
517
+ saveFirst: 'আগে রেকর্ডটি সংরক্ষণ করুন, তারপর ছবি যোগ করুন।',
518
+ },
475
519
  removeLine: 'লাইন সরান',
476
520
  choose: 'বেছে নিন…',
477
521
  pasted_one: '{{count}}টি ঘর পেস্ট হয়েছে',
@@ -544,6 +588,8 @@ export const bn = {
544
588
  approve: '{{record}} অনুমোদন করুন',
545
589
  review: 'দেখুন',
546
590
  dueToday: 'আজকের',
591
+ todo: 'Focus করণীয়',
592
+ meetings: 'আজকের সভা',
547
593
  mentioned: '{{actor}} আপনাকে {{record}}-এ উল্লেখ করেছেন',
548
594
  saved: 'আপনার সংরক্ষিত ভিউ',
549
595
  },
@@ -41,3 +41,4 @@ export declare const PACKAGE: {
41
41
  readonly name: string;
42
42
  readonly rfc: string;
43
43
  };
44
+ export { DateField } from './views/DateField.js';
package/dist/ui/index.js CHANGED
@@ -52,3 +52,4 @@ export const PACKAGE = Object.freeze({
52
52
  name: 'shutro-erp/ui',
53
53
  rfc: 'RFC 0007',
54
54
  });
55
+ export { DateField } from './views/DateField.js';
@@ -11,8 +11,12 @@ export type ChangeStatus = 'pending' | 'conflict' | 'refused';
11
11
  export interface QueuedChange {
12
12
  readonly id: string;
13
13
  readonly at: number;
14
- readonly kind: 'create' | 'update';
14
+ /** A record created or updated through the generated API, or a module's route replayed as sent (`request`). */
15
+ readonly kind: 'create' | 'update' | 'request';
15
16
  readonly model: string;
17
+ /** `request` only: the method and path, with `values` as the body. */
18
+ readonly method?: 'POST' | 'PATCH' | 'PUT' | undefined;
19
+ readonly path?: string | undefined;
16
20
  /** The list's label, for people (e.g. "Contacts"). */
17
21
  readonly modelLabel: string;
18
22
  readonly recordId: number | null;
@@ -127,6 +127,8 @@ export class OfflineQueue {
127
127
  try {
128
128
  if (item.kind === 'create')
129
129
  await this.api.create(item.model, { ...item.values });
130
+ else if (item.kind === 'request')
131
+ await this.api.call(item.method ?? 'POST', item.path ?? '', { ...item.values });
130
132
  else
131
133
  await this.api.update(item.model, item.recordId, { ...item.values }, item.etag);
132
134
  return 'synced';
@@ -17,6 +17,8 @@ export interface WidgetProps {
17
17
  /** Absent in display-only contexts (list cells, cards). */
18
18
  readonly onChange?: (value: unknown) => void;
19
19
  readonly invalid?: boolean;
20
+ /** The record's model, on forms (an image widget attaches its file to the record). */
21
+ readonly model?: string;
20
22
  }
21
23
  /** Props of a registered node component (`{ kind: 'component', component: 'approvals.Panel' }`). */
22
24
  export interface NodeComponentProps {
@@ -96,6 +98,9 @@ export interface PageProps {
96
98
  readonly api: KoshApi;
97
99
  /** The action's label. */
98
100
  readonly label?: string;
101
+ /** The app and action the page was opened from (a client action's page; absent for user pages). */
102
+ readonly app?: string;
103
+ readonly action?: string;
99
104
  }
100
105
  export declare class RegistryError extends Error {
101
106
  constructor(problem: string);
@@ -9,7 +9,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
9
  import { encodeSearch } from '../../search/index.js';
10
10
  import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
11
11
  import { Link, useNavigate } from '@tanstack/react-router';
12
- import { AtSign, BarChart3, CalendarClock, CircleCheckBig, History, List, Search, ShieldCheck, Star, Table2, } from 'lucide-react';
12
+ import { AtSign, BarChart3, CalendarClock, CalendarDays, CheckCircle2, CircleCheckBig, History, List, Search, ShieldCheck, Star, Table2, } from 'lucide-react';
13
13
  import { useTranslation } from 'react-i18next';
14
14
  import { AppIcon } from '../components/AppIcon.js';
15
15
  import { Badge, Button, Card, Skeleton } from '../components/primitives.js';
@@ -17,6 +17,8 @@ import { useKosh } from '../context.js';
17
17
  import { cn } from '../lib/cn.js';
18
18
  import { usePalette } from './CommandPalette.js';
19
19
  import { recentRecords } from './recent.js';
20
+ /** 09:30 in the browser's language and time zone. */
21
+ const clock = (iso) => new Date(iso).toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });
20
22
  /** A tint per category, stable for the session: the same category always gets the same colour. */
21
23
  const TINTS = [
22
24
  'bg-accent text-accent-foreground',
@@ -80,6 +82,50 @@ export function Home() {
80
82
  .then((r) => r.items.filter((n) => n.kind === 'mention'))
81
83
  .catch(() => []),
82
84
  });
85
+ // Focus (RFC 0021): my open to-dos due today or before; nothing when Focus is not installed or not mine.
86
+ const todos = useQuery({
87
+ queryKey: ['home', 'todos'],
88
+ queryFn: () => api
89
+ .list('todo.task', {
90
+ filter: {
91
+ state: 'open',
92
+ owner: uid,
93
+ dueDate: { lte: new Date().toISOString().slice(0, 10) },
94
+ },
95
+ fields: ['name', 'dueDate', 'priority'],
96
+ order: ['dueDate asc', 'id asc'],
97
+ limit: 20,
98
+ })
99
+ .then((r) => r.items)
100
+ .catch(() => []),
101
+ });
102
+ const complete = useMutation({
103
+ mutationFn: (id) => api.transition('todo.task', id, 'complete'),
104
+ onSuccess: () => queryClient.invalidateQueries({ queryKey: ['home', 'todos'] }),
105
+ });
106
+ // Agenda (RFC 0021): today's confirmed events I organize or am invited to; nothing without Agenda.
107
+ const meetings = useQuery({
108
+ queryKey: ['home', 'meetings'],
109
+ queryFn: () => {
110
+ const from = new Date();
111
+ from.setHours(0, 0, 0, 0);
112
+ const to = new Date(from.getTime() + 86_400_000);
113
+ return api
114
+ .list('calendar.event', {
115
+ filter: {
116
+ state: 'confirmed',
117
+ start: { lt: to.toISOString() },
118
+ stop: { gt: from.toISOString() },
119
+ or: [{ organizer: uid }, { attendees: { any: { user: uid } } }],
120
+ },
121
+ fields: ['name', 'start', 'stop', 'room', 'location'],
122
+ order: ['start asc'],
123
+ limit: 20,
124
+ })
125
+ .then((r) => r.items)
126
+ .catch(() => []);
127
+ },
128
+ });
83
129
  const saved = useQuery({
84
130
  queryKey: ['home', 'saved-views'],
85
131
  queryFn: () => api
@@ -129,15 +175,20 @@ export function Home() {
129
175
  const categories = [...new Set((apps.data ?? []).map((a) => a.category ?? ''))].sort((a, b) => a.localeCompare(b));
130
176
  const tint = (a) => TINTS[categories.indexOf(a.category ?? '') % TINTS.length];
131
177
  const recent = recentRecords(uid);
132
- const waiting = (approvals.data?.length ?? 0) + due.length + (mentions.data?.length ?? 0);
178
+ const waiting = (approvals.data?.length ?? 0) +
179
+ due.length +
180
+ (mentions.data?.length ?? 0) +
181
+ (todos.data?.length ?? 0);
133
182
  const views = (saved.data ?? []).filter((v) => routes.data?.[v.targetModel]?.app !== undefined);
134
- return (_jsxs("div", { className: "mx-auto grid max-w-5xl gap-8 py-4", children: [_jsxs("header", { className: "grid gap-4", children: [_jsxs("div", { children: [_jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t('home.today', { date: format.date(today) }) }), _jsx("h1", { className: "text-2xl font-semibold", children: me.data === undefined ? (_jsx(Skeleton, { className: "h-8 w-64" })) : (t(`home.${greeting}`, { name: me.data.name.split(' ')[0] })) })] }), _jsxs("button", { type: "button", onClick: openPalette, className: "flex h-12 w-full items-center gap-3 rounded-xl border bg-surface px-4 text-start text-muted-foreground shadow-sm hover:bg-muted", children: [_jsx(Search, { className: "size-5", "aria-hidden": true }), _jsx("span", { className: "flex-1", children: t('home.search') }), _jsx("kbd", { className: "rounded border px-1.5 text-xs", children: "Ctrl K" })] })] }), _jsxs("section", { "aria-labelledby": "home-attention", className: "grid gap-3", children: [_jsxs("h2", { id: "home-attention", className: "flex items-center gap-2 text-sm font-semibold text-muted-foreground", children: [t('home.attention'), waiting === 0 ? null : _jsx(Badge, { tone: "info", children: waiting })] }), approvals.isPending || activities.isPending || mentions.isPending ? (_jsx(Skeleton, { className: "h-16" })) : waiting === 0 ? (_jsxs(Card, { className: "flex items-center gap-3 p-4 text-sm text-muted-foreground", children: [_jsx(CircleCheckBig, { className: "size-5 text-success", "aria-hidden": true }), t('home.nothing')] })) : (_jsx(Card, { className: "p-0", children: _jsxs("ul", { className: "divide-y", children: [(approvals.data ?? []).map((a) => (_jsx(Item, { icon: _jsx(ShieldCheck, { className: "size-4" }), title: t('home.approve', { record: a.record }), detail: a.levelName, children: _jsx(Button, { size: "sm", onClick: () => open(a.targetModel, a.targetId), children: t('home.review') }) }, `approval-${a.id}`))), due.map((a) => (_jsxs(Item, { icon: _jsx(CalendarClock, { className: "size-4" }), title: _jsxs("span", { className: "flex items-center gap-2", children: [_jsx("span", { className: "truncate", children: a.summary ?? a.type.name }), a.deadline < today ? (_jsx(Badge, { tone: "danger", children: t('home.overdue') })) : (_jsx(Badge, { tone: "warning", children: t('home.dueToday') }))] }), detail: `${a.type.name} · ${a.record}`, children: [_jsx(Button, { size: "sm", variant: "ghost", onClick: () => open(a.model, a.resId), children: t('home.open') }), _jsx(Button, { size: "sm", busy: done.isPending && done.variables === a.id, onClick: () => done.mutate(a.id), children: t('home.done') })] }, `activity-${a.id}`))), (mentions.data ?? []).map((m) => (_jsx(Item, { icon: _jsx(AtSign, { className: "size-4" }), title: t('home.mentioned', {
183
+ return (_jsxs("div", { className: "mx-auto grid max-w-5xl gap-8 py-4", children: [_jsxs("header", { className: "grid gap-4", children: [_jsxs("div", { children: [_jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t('home.today', { date: format.date(today) }) }), _jsx("h1", { className: "text-2xl font-semibold", children: me.data === undefined ? (_jsx(Skeleton, { className: "h-8 w-64" })) : (t(`home.${greeting}`, { name: me.data.name.split(' ')[0] })) })] }), _jsxs("button", { type: "button", onClick: openPalette, className: "flex h-12 w-full items-center gap-3 rounded-xl border bg-surface px-4 text-start text-muted-foreground shadow-sm hover:bg-muted", children: [_jsx(Search, { className: "size-5", "aria-hidden": true }), _jsx("span", { className: "flex-1", children: t('home.search') }), _jsx("kbd", { className: "rounded border px-1.5 text-xs", children: "Ctrl K" })] })] }), _jsxs("section", { "aria-labelledby": "home-attention", className: "grid gap-3", children: [_jsxs("h2", { id: "home-attention", className: "flex items-center gap-2 text-sm font-semibold text-muted-foreground", children: [t('home.attention'), waiting === 0 ? null : _jsx(Badge, { tone: "info", children: waiting })] }), approvals.isPending || activities.isPending || mentions.isPending || todos.isPending ? (_jsx(Skeleton, { className: "h-16" })) : waiting === 0 ? (_jsxs(Card, { className: "flex items-center gap-3 p-4 text-sm text-muted-foreground", children: [_jsx(CircleCheckBig, { className: "size-5 text-success", "aria-hidden": true }), t('home.nothing')] })) : (_jsx(Card, { className: "p-0", children: _jsxs("ul", { className: "divide-y", children: [(approvals.data ?? []).map((a) => (_jsx(Item, { icon: _jsx(ShieldCheck, { className: "size-4" }), title: t('home.approve', { record: a.record }), detail: a.levelName, children: _jsx(Button, { size: "sm", onClick: () => open(a.targetModel, a.targetId), children: t('home.review') }) }, `approval-${a.id}`))), due.map((a) => (_jsxs(Item, { icon: _jsx(CalendarClock, { className: "size-4" }), title: _jsxs("span", { className: "flex items-center gap-2", children: [_jsx("span", { className: "truncate", children: a.summary ?? a.type.name }), a.deadline < today ? (_jsx(Badge, { tone: "danger", children: t('home.overdue') })) : (_jsx(Badge, { tone: "warning", children: t('home.dueToday') }))] }), detail: `${a.type.name} · ${a.record}`, children: [_jsx(Button, { size: "sm", variant: "ghost", onClick: () => open(a.model, a.resId), children: t('home.open') }), _jsx(Button, { size: "sm", busy: done.isPending && done.variables === a.id, onClick: () => done.mutate(a.id), children: t('home.done') })] }, `activity-${a.id}`))), (todos.data ?? []).map((todo) => (_jsxs(Item, { icon: _jsx(CheckCircle2, { className: "size-4" }), title: _jsxs("span", { className: "flex items-center gap-2", children: [_jsx("span", { className: "truncate", children: todo.name }), todo.dueDate < today ? (_jsx(Badge, { tone: "danger", children: t('home.overdue') })) : (_jsx(Badge, { tone: "warning", children: t('home.dueToday') }))] }), detail: t('home.todo'), children: [_jsx(Button, { size: "sm", variant: "ghost", onClick: () => open('todo.task', todo.id), children: t('home.open') }), _jsx(Button, { size: "sm", busy: complete.isPending && complete.variables === todo.id, onClick: () => complete.mutate(todo.id), children: t('home.done') })] }, `todo-${todo.id}`))), (mentions.data ?? []).map((m) => (_jsx(Item, { icon: _jsx(AtSign, { className: "size-4" }), title: t('home.mentioned', {
135
184
  actor: m.params.actor ?? '',
136
185
  record: m.params.record ?? '',
137
186
  }), detail: m.params.preview ?? format.datetime(m.createdAt), children: _jsx(Button, { size: "sm", onClick: () => {
138
187
  read.mutate(m.id);
139
188
  open(m.model, m.resId);
140
- }, children: t('home.open') }) }, `mention-${m.id}`)))] }) }))] }), recent.length === 0 ? null : (_jsxs("section", { "aria-labelledby": "home-recent", className: "grid gap-3", children: [_jsx("h2", { id: "home-recent", className: "text-sm font-semibold text-muted-foreground", children: t('home.recent') }), _jsx("ul", { className: "flex flex-wrap gap-2", children: recent.slice(0, 8).map((r) => (_jsx("li", { children: _jsxs(Link, { to: "/$app/a/$action/$id", params: { app: r.app, action: r.action, id: String(r.id) }, className: "flex items-center gap-2 rounded-full border bg-surface px-3 py-1.5 text-sm hover:bg-muted", children: [_jsx(History, { className: "size-3.5 text-muted-foreground", "aria-hidden": true }), _jsx("span", { className: "max-w-56 truncate", children: r.title }), _jsx("span", { className: "text-xs text-muted-foreground", children: format.date(new Date(r.at).toISOString().slice(0, 10)) })] }) }, `${r.model}:${r.id}`))) })] })), views.length === 0 ? null : (_jsxs("section", { "aria-labelledby": "home-saved", className: "grid gap-3", children: [_jsx("h2", { id: "home-saved", className: "text-sm font-semibold text-muted-foreground", children: t('home.saved') }), _jsx("ul", { className: "grid grid-cols-[repeat(auto-fill,minmax(14rem,1fr))] gap-2", children: views.map((v) => {
189
+ }, children: t('home.open') }) }, `mention-${m.id}`)))] }) }))] }), (meetings.data ?? []).length === 0 ? null : (_jsxs("section", { "aria-labelledby": "home-meetings", className: "grid gap-3", children: [_jsx("h2", { id: "home-meetings", className: "text-sm font-semibold text-muted-foreground", children: t('home.meetings') }), _jsx(Card, { className: "p-0", children: _jsx("ul", { className: "divide-y", children: (meetings.data ?? []).map((m) => (_jsx(Item, { icon: _jsx(CalendarDays, { className: "size-4" }), title: m.name, detail: [`${clock(m.start)}–${clock(m.stop)}`, m.location]
190
+ .filter((x) => x !== null && x !== '')
191
+ .join(' · '), children: _jsx(Button, { size: "sm", variant: "ghost", onClick: () => open('calendar.event', m.id), children: t('home.open') }) }, `meeting-${m.id}`))) }) })] })), recent.length === 0 ? null : (_jsxs("section", { "aria-labelledby": "home-recent", className: "grid gap-3", children: [_jsx("h2", { id: "home-recent", className: "text-sm font-semibold text-muted-foreground", children: t('home.recent') }), _jsx("ul", { className: "flex flex-wrap gap-2", children: recent.slice(0, 8).map((r) => (_jsx("li", { children: _jsxs(Link, { to: "/$app/a/$action/$id", params: { app: r.app, action: r.action, id: String(r.id) }, className: "flex items-center gap-2 rounded-full border bg-surface px-3 py-1.5 text-sm hover:bg-muted", children: [_jsx(History, { className: "size-3.5 text-muted-foreground", "aria-hidden": true }), _jsx("span", { className: "max-w-56 truncate", children: r.title }), _jsx("span", { className: "text-xs text-muted-foreground", children: format.date(new Date(r.at).toISOString().slice(0, 10)) })] }) }, `${r.model}:${r.id}`))) })] })), views.length === 0 ? null : (_jsxs("section", { "aria-labelledby": "home-saved", className: "grid gap-3", children: [_jsx("h2", { id: "home-saved", className: "text-sm font-semibold text-muted-foreground", children: t('home.saved') }), _jsx("ul", { className: "grid grid-cols-[repeat(auto-fill,minmax(14rem,1fr))] gap-2", children: views.map((v) => {
141
192
  const Icon = VIEW_ICONS[v.viewType] ?? List;
142
193
  return (_jsx("li", { children: _jsxs("button", { type: "button", onClick: () => openSaved(v), className: "flex w-full items-center gap-2 rounded-lg border bg-surface px-3 py-2 text-start text-sm hover:bg-muted", children: [_jsx(Icon, { className: "size-4 shrink-0 text-muted-foreground", "aria-hidden": true }), _jsx("span", { className: "min-w-0 flex-1 truncate", children: v.name }), _jsx(Star, { className: "size-3.5 shrink-0 text-muted-foreground", "aria-hidden": true })] }) }, v.id));
143
194
  }) })] })), _jsxs("section", { "aria-labelledby": "apps-title", className: "grid gap-3", children: [_jsx("h2", { id: "apps-title", className: "text-sm font-semibold text-muted-foreground", children: t('home.apps') }), apps.isPending ? (_jsx("div", { className: "grid grid-cols-[repeat(auto-fill,minmax(11rem,1fr))] gap-3", children: [0, 1, 2, 3].map((i) => (_jsx(Skeleton, { className: "h-16" }, i))) })) : (apps.data ?? []).length === 0 ? (_jsx("p", { className: "text-muted-foreground", children: t('shell.noApps') })) : (_jsx("ul", { className: "grid grid-cols-[repeat(auto-fill,minmax(13rem,1fr))] gap-2", children: (apps.data ?? []).map((a) => (_jsx("li", { children: _jsx(Link, { to: "/$app", params: { app: a.code }, className: "block h-full", children: _jsxs(Card, { className: "flex h-full items-center gap-3 p-3 hover:bg-muted", children: [_jsx(AppIcon, { name: a.icon ?? a.code, className: cn('size-9', tint(a)) }), _jsxs("div", { className: "grid min-w-0 gap-0.5", children: [_jsx("span", { className: "truncate font-medium", children: a.label }), a.summary === undefined ? null : (_jsx("span", { className: "truncate text-xs text-muted-foreground", children: a.summary }))] })] }) }) }, a.code))) }))] })] }));