@dasidev/dasi-ui 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (450) hide show
  1. package/README.md +346 -0
  2. package/bin/dasi-cli.cjs +184 -0
  3. package/dist/date-selector-test-BlukYeWl.js +91 -0
  4. package/dist/favicon.ico +0 -0
  5. package/dist/html2canvas.esm-CKxSAI8P.js +4886 -0
  6. package/dist/img/brand/ic_pln.svg +12 -0
  7. package/dist/img/brand/mapp_power_logo.svg +21 -0
  8. package/dist/img/common/pltu_ulumbu_flores_ntt.jpeg +0 -0
  9. package/dist/index-BQSA2aPs.js +126556 -0
  10. package/dist/index.es-DQWt-PZn.js +5769 -0
  11. package/dist/index.es.js +11 -0
  12. package/dist/index.umd.js +8564 -0
  13. package/dist/informasi-gudang-BmoEy2RL.js +164 -0
  14. package/dist/informasi-gudang-DXfS46Nh.js +50 -0
  15. package/dist/purify.es-C-9oolON.js +546 -0
  16. package/dist/scripts/pdf.worker.min.js +29 -0
  17. package/dist/scripts/pdf.worker.min.mjs +29 -0
  18. package/dist/scripts/pdf.worker.mjs +57722 -0
  19. package/dist/scripts/pdf.worker.mjs.map +1 -0
  20. package/dist/style.css +1 -0
  21. package/dist/test-schema-JFghGc0_.js +8 -0
  22. package/dist/test-schema-uusFsJe4.js +438 -0
  23. package/dist/types-l0sNRNKZ.js +1 -0
  24. package/package.json +178 -0
  25. package/src/App.vue +18 -0
  26. package/src/__tests__/index.test.ts +9 -0
  27. package/src/api/api.ts +117 -0
  28. package/src/assets/app-selector.svg +3 -0
  29. package/src/assets/dasi.png +0 -0
  30. package/src/assets/foto_ss.svg +21 -0
  31. package/src/assets/icons/circle-blue.svg +4 -0
  32. package/src/assets/icons/circle-gray.svg +15 -0
  33. package/src/assets/icons/circle-green.svg +4 -0
  34. package/src/assets/icons/circle-orange.svg +4 -0
  35. package/src/assets/icons/circle-purple.svg +4 -0
  36. package/src/assets/icons/circle-red.svg +15 -0
  37. package/src/assets/icons/harbor.svg +12 -0
  38. package/src/assets/icons/ic-box-red.svg +8 -0
  39. package/src/assets/icons/ic-chevron-right.svg +1 -0
  40. package/src/assets/icons/ic-loading.svg +9 -0
  41. package/src/assets/icons/ic-reset.svg +16 -0
  42. package/src/assets/icons/ic-sailing.svg +5 -0
  43. package/src/assets/icons/icon-app-selector.svg +3 -0
  44. package/src/assets/icons/icon-browser-check.svg +4 -0
  45. package/src/assets/icons/icon-calendar.svg +3 -0
  46. package/src/assets/icons/icon-chart-bar.svg +3 -0
  47. package/src/assets/icons/icon-chart-doc.svg +16 -0
  48. package/src/assets/icons/icon-chart-line.svg +10 -0
  49. package/src/assets/icons/icon-chart-mix.svg +15 -0
  50. package/src/assets/icons/icon-chart-pie.svg +11 -0
  51. package/src/assets/icons/icon-continue.svg +12 -0
  52. package/src/assets/icons/icon-dashboard-2.svg +17 -0
  53. package/src/assets/icons/icon-dashboard.svg +3 -0
  54. package/src/assets/icons/icon-data-kelistrikan.svg +19 -0
  55. package/src/assets/icons/icon-data-sentral.svg +11 -0
  56. package/src/assets/icons/icon-database.svg +5 -0
  57. package/src/assets/icons/icon-desktop.svg +3 -0
  58. package/src/assets/icons/icon-download.svg +13 -0
  59. package/src/assets/icons/icon-energi-primer.svg +12 -0
  60. package/src/assets/icons/icon-faba-apk2.svg +11 -0
  61. package/src/assets/icons/icon-faba.svg +11 -0
  62. package/src/assets/icons/icon-factory.svg +14 -0
  63. package/src/assets/icons/icon-globe-doc.svg +19 -0
  64. package/src/assets/icons/icon-ikk.svg +10 -0
  65. package/src/assets/icons/icon-kbb.svg +13 -0
  66. package/src/assets/icons/icon-kos.svg +16 -0
  67. package/src/assets/icons/icon-kpi-bod.svg +15 -0
  68. package/src/assets/icons/icon-kss.svg +14 -0
  69. package/src/assets/icons/icon-map.svg +12 -0
  70. package/src/assets/icons/icon-monitoring-harian.svg +13 -0
  71. package/src/assets/icons/icon-notification.svg +4 -0
  72. package/src/assets/icons/icon-overview.svg +17 -0
  73. package/src/assets/icons/icon-pltu.svg +13 -0
  74. package/src/assets/icons/icon-sebaran-sentral.svg +12 -0
  75. package/src/assets/icons/icon-select-data-kelistrikan.svg +19 -0
  76. package/src/assets/icons/icon-select-data-sentral.svg +11 -0
  77. package/src/assets/icons/icon-select-energi-primer.svg +12 -0
  78. package/src/assets/icons/icon-select-faba-apk2.svg +11 -0
  79. package/src/assets/icons/icon-select-ikk.svg +10 -0
  80. package/src/assets/icons/icon-select-kbb.svg +13 -0
  81. package/src/assets/icons/icon-select-kos.svg +16 -0
  82. package/src/assets/icons/icon-select-kpi-bod.svg +15 -0
  83. package/src/assets/icons/icon-select-kss.svg +14 -0
  84. package/src/assets/icons/icon-select-monitoring-harian.svg +13 -0
  85. package/src/assets/icons/icon-select-overview.svg +17 -0
  86. package/src/assets/icons/icon-select-sebaran-sentral.svg +12 -0
  87. package/src/assets/icons/icon-sentral-white.svg +13 -0
  88. package/src/assets/icons/icon-shipping.svg +5 -0
  89. package/src/assets/icons/icon-sort.svg +5 -0
  90. package/src/assets/icons/icon-tree-box.svg +14 -0
  91. package/src/assets/icons/icon-warehouse.svg +12 -0
  92. package/src/assets/icons/pin-green.svg +3 -0
  93. package/src/assets/icons/pin-orange.svg +3 -0
  94. package/src/assets/icons/pin-purple.svg +3 -0
  95. package/src/assets/icons/ship.svg +3 -0
  96. package/src/assets/icons/shipment/icon-antri.svg +15 -0
  97. package/src/assets/icons/shipment/icon-bongkar.svg +4 -0
  98. package/src/assets/icons/shipment/icon-invoice.svg +6 -0
  99. package/src/assets/icons/shipment/icon-loading.svg +8 -0
  100. package/src/assets/icons/shipment/icon-pembayaran.svg +13 -0
  101. package/src/assets/icons/shipment/icon-pengiriman.svg +4 -0
  102. package/src/assets/icons/shipment/icon-sailing.svg +4 -0
  103. package/src/assets/icons/shipment/icon-shipment-completed.svg +6 -0
  104. package/src/assets/icons/shipment/icon-shipment-in-progress.svg +6 -0
  105. package/src/assets/icons/shipment/icon-shipment-over-sla.svg +6 -0
  106. package/src/assets/icons/shipment/icon-spt.svg +4 -0
  107. package/src/assets/icons/shipment/icon-total-shipment.svg +4 -0
  108. package/src/assets/icons/upload_doc_icon.svg +42 -0
  109. package/src/assets/icons/upload_icon_blue.svg +14 -0
  110. package/src/assets/login-bg-day-min.jpg +0 -0
  111. package/src/assets/login-bg-night-min.jpg +0 -0
  112. package/src/assets/login-bg.jpg +0 -0
  113. package/src/assets/login-day.png +0 -0
  114. package/src/assets/login-night.png +0 -0
  115. package/src/assets/lucide-circle-plus-blue.svg +1 -0
  116. package/src/assets/pdf-logo.svg +11 -0
  117. package/src/assets/pemasok-card-bg.svg +6 -0
  118. package/src/assets/success_animation.gif +0 -0
  119. package/src/assets/success_animation.mp4 +0 -0
  120. package/src/assets/success_animation.webm +0 -0
  121. package/src/components/button/BtnAddOutline.vue +14 -0
  122. package/src/components/button/BtnCircle.vue +10 -0
  123. package/src/components/button/BtnOutline.vue +15 -0
  124. package/src/components/button/BtnPrimary.vue +25 -0
  125. package/src/components/button/BtnSecondary.vue +26 -0
  126. package/src/components/detail/AccountDetailTimeline.vue +144 -0
  127. package/src/components/detail/ApprovalInfo.vue +288 -0
  128. package/src/components/detail/DCI2.vue +164 -0
  129. package/src/components/detail/DetailContentHeader.vue +83 -0
  130. package/src/components/detail/DetailContentItem.vue +186 -0
  131. package/src/components/detail/DetailContentItems.vue +388 -0
  132. package/src/components/detail/DetailContentLoading.vue +12 -0
  133. package/src/components/detail/DetailContentTablet.vue +10 -0
  134. package/src/components/detail/DetailSheet.vue +294 -0
  135. package/src/components/detail/DetailTimeline.vue +191 -0
  136. package/src/components/detail/DocApprovalDialog.vue +29 -0
  137. package/src/components/detail/DocViewerContent.vue +991 -0
  138. package/src/components/dialog/ConfirmDialog.vue +96 -0
  139. package/src/components/dialog/DialogBase.vue +53 -0
  140. package/src/components/dialog/DialogSelect.vue +212 -0
  141. package/src/components/dialog/ErrorDialog.vue +63 -0
  142. package/src/components/dialog/FormDialog.vue +141 -0
  143. package/src/components/dialog/FormInputerDialog.vue +91 -0
  144. package/src/components/dialog/InfoDialog.vue +74 -0
  145. package/src/components/dialog/SuccessDialog.vue +51 -0
  146. package/src/components/examples/TestSchemaExample.vue +288 -0
  147. package/src/components/forms/auth/LoginForm.vue +806 -0
  148. package/src/components/forms/auth/PwdScore.vue +68 -0
  149. package/src/components/helper/ApiTester.vue +153 -0
  150. package/src/components/helper/ChangePwd.vue +150 -0
  151. package/src/components/helper/CheckboxElement.vue +43 -0
  152. package/src/components/helper/ConfigSwitcher.vue +54 -0
  153. package/src/components/helper/Copyright.vue +10 -0
  154. package/src/components/helper/ErrorScreen.vue +40 -0
  155. package/src/components/helper/LucideIcon.vue +27 -0
  156. package/src/components/helper/PdfViewer.vue +103 -0
  157. package/src/components/helper/PinInputer.vue +205 -0
  158. package/src/components/helper/PrivacyPolicy.vue +122 -0
  159. package/src/components/layout/PageActivityHeader.vue +48 -0
  160. package/src/components/layout/PageHeader.vue +70 -0
  161. package/src/components/loadings/LoadingDialog.vue +29 -0
  162. package/src/components/loadings/LoadingDialogSpin.vue +25 -0
  163. package/src/components/loadings/LoadingIndicator.vue +38 -0
  164. package/src/components/loadings/LoadingScreen.vue +23 -0
  165. package/src/components/notif/Notif.vue +103 -0
  166. package/src/components/notif/NotifItem.vue +41 -0
  167. package/src/components/pages/Header.vue +431 -0
  168. package/src/components/pages/Leftbar.vue +417 -0
  169. package/src/components/pages/PageActivity.vue +108 -0
  170. package/src/components/pages/PageActivityContent.vue +597 -0
  171. package/src/components/pages/PageContentTable.vue +589 -0
  172. package/src/components/pages/PageTab.vue +84 -0
  173. package/src/components/selector/BaseSelector.vue +1136 -0
  174. package/src/components/selector/ConfigDataSelector.vue +136 -0
  175. package/src/components/settings/SettingsItem.vue +38 -0
  176. package/src/components/tab/TabView.vue +11 -0
  177. package/src/components/tab/TabViewItem.vue +18 -0
  178. package/src/components/tab/TabViewItemBar.vue +9 -0
  179. package/src/components/tables/CellHover.vue +65 -0
  180. package/src/components/tables/DashboardDataTable.vue +707 -0
  181. package/src/components/tables/DataStatusTag.vue +52 -0
  182. package/src/components/tables/DataTable.vue +156 -0
  183. package/src/components/tables/DataTableAccordion.vue +249 -0
  184. package/src/components/tables/DataTableActionRow.vue +64 -0
  185. package/src/components/tables/DataTableCell.vue +272 -0
  186. package/src/components/tables/DataTableHeader.vue +60 -0
  187. package/src/components/tables/DataTableRow.vue +213 -0
  188. package/src/components/tables/ExpandedTable.vue +259 -0
  189. package/src/components/tables/PageTable.vue +73 -0
  190. package/src/components/tables/Pagination.vue +98 -0
  191. package/src/components/tables/dropdown/BaseDropdownTable.vue +140 -0
  192. package/src/components/tables/dropdown/DropdownTableActivity.vue +33 -0
  193. package/src/components/tables/dropdown/DropdownTableAsset.vue +30 -0
  194. package/src/components/tables/dropdown/DropdownTableConfig.vue +30 -0
  195. package/src/components/tables/dropdown/DropdownTableDataKonektor.vue +31 -0
  196. package/src/components/tables/dropdown/DropdownTableDataLabel.vue +30 -0
  197. package/src/components/tables/dropdown/DropdownTableDataSchema.vue +31 -0
  198. package/src/components/tables/dropdown/DropdownTableFabaPemanfaat.vue +30 -0
  199. package/src/components/tables/dropdown/DropdownTableGroup.vue +36 -0
  200. package/src/components/tables/dropdown/DropdownTableHalaman.vue +33 -0
  201. package/src/components/tables/dropdown/DropdownTableLevel.vue +66 -0
  202. package/src/components/tables/dropdown/DropdownTableOrganization.vue +47 -0
  203. package/src/components/tables/dropdown/DropdownTablePengelola.vue +28 -0
  204. package/src/components/tables/dropdown/DropdownTableQueryLayer.vue +29 -0
  205. package/src/components/tables/dropdown/DropdownTableSentral.vue +33 -0
  206. package/src/components/tables/dropdown/DropdownTableWarehouse.vue +30 -0
  207. package/src/components/tables/dropdown/TableDropdown.vue +52 -0
  208. package/src/components/ui/accordion/Accordion.vue +19 -0
  209. package/src/components/ui/accordion/AccordionContent.vue +24 -0
  210. package/src/components/ui/accordion/AccordionItem.vue +24 -0
  211. package/src/components/ui/accordion/AccordionTrigger.vue +42 -0
  212. package/src/components/ui/accordion/index.ts +4 -0
  213. package/src/components/ui/alert-dialog/AlertDialog.vue +14 -0
  214. package/src/components/ui/alert-dialog/AlertDialogAction.vue +20 -0
  215. package/src/components/ui/alert-dialog/AlertDialogCancel.vue +20 -0
  216. package/src/components/ui/alert-dialog/AlertDialogContent.vue +42 -0
  217. package/src/components/ui/alert-dialog/AlertDialogDescription.vue +25 -0
  218. package/src/components/ui/alert-dialog/AlertDialogFooter.vue +21 -0
  219. package/src/components/ui/alert-dialog/AlertDialogHeader.vue +16 -0
  220. package/src/components/ui/alert-dialog/AlertDialogTitle.vue +22 -0
  221. package/src/components/ui/alert-dialog/AlertDialogTrigger.vue +11 -0
  222. package/src/components/ui/alert-dialog/index.ts +9 -0
  223. package/src/components/ui/avatar/Avatar.vue +24 -0
  224. package/src/components/ui/avatar/AvatarFallback.vue +11 -0
  225. package/src/components/ui/avatar/AvatarImage.vue +9 -0
  226. package/src/components/ui/avatar/UsersAvatar.vue +28 -0
  227. package/src/components/ui/avatar/index.ts +24 -0
  228. package/src/components/ui/button/Button.vue +27 -0
  229. package/src/components/ui/button/index.ts +34 -0
  230. package/src/components/ui/calendar/Calendar.vue +325 -0
  231. package/src/components/ui/calendar/index.ts +22 -0
  232. package/src/components/ui/checkbox/Checkbox.vue +33 -0
  233. package/src/components/ui/checkbox/index.ts +1 -0
  234. package/src/components/ui/command/Command.vue +30 -0
  235. package/src/components/ui/command/CommandDialog.vue +21 -0
  236. package/src/components/ui/command/CommandEmpty.vue +20 -0
  237. package/src/components/ui/command/CommandGroup.vue +29 -0
  238. package/src/components/ui/command/CommandInput.vue +33 -0
  239. package/src/components/ui/command/CommandItem.vue +26 -0
  240. package/src/components/ui/command/CommandList.vue +27 -0
  241. package/src/components/ui/command/CommandSeparator.vue +23 -0
  242. package/src/components/ui/command/CommandShortcut.vue +14 -0
  243. package/src/components/ui/command/index.ts +9 -0
  244. package/src/components/ui/context-menu/ContextMenu.vue +15 -0
  245. package/src/components/ui/context-menu/ContextMenuCheckboxItem.vue +40 -0
  246. package/src/components/ui/context-menu/ContextMenuContent.vue +36 -0
  247. package/src/components/ui/context-menu/ContextMenuGroup.vue +11 -0
  248. package/src/components/ui/context-menu/ContextMenuItem.vue +34 -0
  249. package/src/components/ui/context-menu/ContextMenuLabel.vue +25 -0
  250. package/src/components/ui/context-menu/ContextMenuPortal.vue +11 -0
  251. package/src/components/ui/context-menu/ContextMenuRadioGroup.vue +19 -0
  252. package/src/components/ui/context-menu/ContextMenuRadioItem.vue +40 -0
  253. package/src/components/ui/context-menu/ContextMenuSeparator.vue +20 -0
  254. package/src/components/ui/context-menu/ContextMenuShortcut.vue +14 -0
  255. package/src/components/ui/context-menu/ContextMenuSub.vue +19 -0
  256. package/src/components/ui/context-menu/ContextMenuSubContent.vue +35 -0
  257. package/src/components/ui/context-menu/ContextMenuSubTrigger.vue +34 -0
  258. package/src/components/ui/context-menu/ContextMenuTrigger.vue +13 -0
  259. package/src/components/ui/context-menu/index.ts +14 -0
  260. package/src/components/ui/datetime/DatetimeRangeComponent.vue +52 -0
  261. package/src/components/ui/dialog/Dialog.vue +14 -0
  262. package/src/components/ui/dialog/DialogClose.vue +11 -0
  263. package/src/components/ui/dialog/DialogContent.vue +53 -0
  264. package/src/components/ui/dialog/DialogDescription.vue +24 -0
  265. package/src/components/ui/dialog/DialogFooter.vue +19 -0
  266. package/src/components/ui/dialog/DialogHeader.vue +16 -0
  267. package/src/components/ui/dialog/DialogScrollContent.vue +59 -0
  268. package/src/components/ui/dialog/DialogTitle.vue +29 -0
  269. package/src/components/ui/dialog/DialogTrigger.vue +11 -0
  270. package/src/components/ui/dialog/index.ts +9 -0
  271. package/src/components/ui/dropdown-menu/DropdownMenu.vue +14 -0
  272. package/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +40 -0
  273. package/src/components/ui/dropdown-menu/DropdownMenuContent.vue +38 -0
  274. package/src/components/ui/dropdown-menu/DropdownMenuGroup.vue +11 -0
  275. package/src/components/ui/dropdown-menu/DropdownMenuItem.vue +28 -0
  276. package/src/components/ui/dropdown-menu/DropdownMenuLabel.vue +24 -0
  277. package/src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +19 -0
  278. package/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +41 -0
  279. package/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue +22 -0
  280. package/src/components/ui/dropdown-menu/DropdownMenuShortcut.vue +14 -0
  281. package/src/components/ui/dropdown-menu/DropdownMenuSub.vue +19 -0
  282. package/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue +30 -0
  283. package/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +33 -0
  284. package/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue +13 -0
  285. package/src/components/ui/dropdown-menu/index.ts +16 -0
  286. package/src/components/ui/form/FormControl.vue +16 -0
  287. package/src/components/ui/form/FormDescription.vue +20 -0
  288. package/src/components/ui/form/FormItem.vue +25 -0
  289. package/src/components/ui/form/FormLabel.vue +23 -0
  290. package/src/components/ui/form/FormMessage.vue +16 -0
  291. package/src/components/ui/form/index.ts +6 -0
  292. package/src/components/ui/form/useFormField.ts +30 -0
  293. package/src/components/ui/hover-card/HoverCard.vue +14 -0
  294. package/src/components/ui/hover-card/HoverCardContent.vue +41 -0
  295. package/src/components/ui/hover-card/HoverCardTrigger.vue +11 -0
  296. package/src/components/ui/hover-card/index.ts +3 -0
  297. package/src/components/ui/input/Input.vue +24 -0
  298. package/src/components/ui/input/index.ts +1 -0
  299. package/src/components/ui/label/Label.vue +27 -0
  300. package/src/components/ui/label/index.ts +1 -0
  301. package/src/components/ui/pagination/PaginationEllipsis.vue +22 -0
  302. package/src/components/ui/pagination/PaginationFirst.vue +29 -0
  303. package/src/components/ui/pagination/PaginationLast.vue +29 -0
  304. package/src/components/ui/pagination/PaginationNext.vue +29 -0
  305. package/src/components/ui/pagination/PaginationPrev.vue +29 -0
  306. package/src/components/ui/pagination/index.ts +10 -0
  307. package/src/components/ui/pin-input/PinInput.vue +23 -0
  308. package/src/components/ui/pin-input/PinInputGroup.vue +18 -0
  309. package/src/components/ui/pin-input/PinInputInput.vue +18 -0
  310. package/src/components/ui/pin-input/PinInputSeparator.vue +15 -0
  311. package/src/components/ui/pin-input/index.ts +4 -0
  312. package/src/components/ui/popover/Popover.vue +15 -0
  313. package/src/components/ui/popover/PopoverContent.vue +48 -0
  314. package/src/components/ui/popover/PopoverTrigger.vue +11 -0
  315. package/src/components/ui/popover/index.ts +4 -0
  316. package/src/components/ui/preview/PreviewPdf.vue +118 -0
  317. package/src/components/ui/progress/ProgressCircle.vue +27 -0
  318. package/src/components/ui/progress/SemiCircularProgressBar.vue +83 -0
  319. package/src/components/ui/progress/TotalCalories.vue +31 -0
  320. package/src/components/ui/radio-group/RadioGroup.vue +25 -0
  321. package/src/components/ui/radio-group/RadioGroupItem.vue +37 -0
  322. package/src/components/ui/radio-group/index.ts +2 -0
  323. package/src/components/ui/scroll-area/ScrollArea.vue +29 -0
  324. package/src/components/ui/scroll-area/ScrollBar.vue +30 -0
  325. package/src/components/ui/scroll-area/index.ts +2 -0
  326. package/src/components/ui/select/Select.vue +15 -0
  327. package/src/components/ui/select/SelectContent.vue +52 -0
  328. package/src/components/ui/select/SelectGroup.vue +19 -0
  329. package/src/components/ui/select/SelectInline.vue +84 -0
  330. package/src/components/ui/select/SelectItem.vue +44 -0
  331. package/src/components/ui/select/SelectItemText.vue +11 -0
  332. package/src/components/ui/select/SelectLabel.vue +13 -0
  333. package/src/components/ui/select/SelectScrollDownButton.vue +24 -0
  334. package/src/components/ui/select/SelectScrollUpButton.vue +24 -0
  335. package/src/components/ui/select/SelectSeparator.vue +17 -0
  336. package/src/components/ui/select/SelectTrigger.vue +31 -0
  337. package/src/components/ui/select/SelectTriggerCustom.vue +23 -0
  338. package/src/components/ui/select/SelectValue.vue +11 -0
  339. package/src/components/ui/select/index.ts +12 -0
  340. package/src/components/ui/separator/Separator.vue +20 -0
  341. package/src/components/ui/separator/index.ts +1 -0
  342. package/src/components/ui/sheet/Sheet.vue +14 -0
  343. package/src/components/ui/sheet/SheetClose.vue +11 -0
  344. package/src/components/ui/sheet/SheetContent.vue +48 -0
  345. package/src/components/ui/sheet/SheetDescription.vue +22 -0
  346. package/src/components/ui/sheet/SheetFooter.vue +19 -0
  347. package/src/components/ui/sheet/SheetHeader.vue +16 -0
  348. package/src/components/ui/sheet/SheetTitle.vue +22 -0
  349. package/src/components/ui/sheet/SheetTrigger.vue +11 -0
  350. package/src/components/ui/sheet/index.ts +31 -0
  351. package/src/components/ui/skeleton/Skeleton.vue +28 -0
  352. package/src/components/ui/skeleton/index.ts +1 -0
  353. package/src/components/ui/sonner/Sonner.vue +22 -0
  354. package/src/components/ui/sonner/index.ts +1 -0
  355. package/src/components/ui/star/StarRating.vue +19 -0
  356. package/src/components/ui/switch/Switch.vue +37 -0
  357. package/src/components/ui/switch/index.ts +1 -0
  358. package/src/components/ui/table/Table.vue +16 -0
  359. package/src/components/ui/table/TableBody.vue +14 -0
  360. package/src/components/ui/table/TableCaption.vue +14 -0
  361. package/src/components/ui/table/TableCell.vue +21 -0
  362. package/src/components/ui/table/TableEmpty.vue +37 -0
  363. package/src/components/ui/table/TableFooter.vue +14 -0
  364. package/src/components/ui/table/TableHead.vue +14 -0
  365. package/src/components/ui/table/TableHeader.vue +14 -0
  366. package/src/components/ui/table/TableRow.vue +14 -0
  367. package/src/components/ui/table/index.ts +8 -0
  368. package/src/components/ui/tabs/Tabs.vue +15 -0
  369. package/src/components/ui/tabs/TabsContent.vue +22 -0
  370. package/src/components/ui/tabs/TabsList.vue +25 -0
  371. package/src/components/ui/tabs/TabsTrigger.vue +27 -0
  372. package/src/components/ui/tabs/index.ts +4 -0
  373. package/src/components/ui/tags-input/TagsInput.vue +22 -0
  374. package/src/components/ui/tags-input/TagsInputInput.vue +19 -0
  375. package/src/components/ui/tags-input/TagsInputItem.vue +22 -0
  376. package/src/components/ui/tags-input/TagsInputItemDelete.vue +24 -0
  377. package/src/components/ui/tags-input/TagsInputItemText.vue +19 -0
  378. package/src/components/ui/tags-input/index.ts +5 -0
  379. package/src/components/ui/textarea/Textarea.vue +24 -0
  380. package/src/components/ui/textarea/index.ts +1 -0
  381. package/src/components/ui/tooltip/Tooltip.vue +14 -0
  382. package/src/components/ui/tooltip/TooltipContent.vue +31 -0
  383. package/src/components/ui/tooltip/TooltipProvider.vue +11 -0
  384. package/src/components/ui/tooltip/TooltipTrigger.vue +11 -0
  385. package/src/components/ui/tooltip/index.ts +4 -0
  386. package/src/composables/useAppConfig.ts +332 -0
  387. package/src/composables/useDarkMode.ts +71 -0
  388. package/src/config/app.config.ts +318 -0
  389. package/src/config/examples/ecommerce.config.ts +132 -0
  390. package/src/config/examples/generic.config.ts +132 -0
  391. package/src/config/menu.config.ts +149 -0
  392. package/src/config/my-app.config.ts +134 -0
  393. package/src/config/test-config.ts +32 -0
  394. package/src/config/theme.config.ts +250 -0
  395. package/src/docs/index.ts +21 -0
  396. package/src/docs.scss +403 -0
  397. package/src/index.d.ts +5 -0
  398. package/src/index.ts +20 -0
  399. package/src/layouts/AuthLayout.vue +68 -0
  400. package/src/layouts/DefaultLayout.vue +119 -0
  401. package/src/layouts/DocsLayout.vue +681 -0
  402. package/src/layouts/FormGlobal.vue +50 -0
  403. package/src/layouts/GlobalDialog.vue +122 -0
  404. package/src/layouts/RakorConfirmDialog.vue +95 -0
  405. package/src/layouts/SettingsLayout.vue +115 -0
  406. package/src/lib/constants.ts +2 -0
  407. package/src/lib/detail.utils.ts +213 -0
  408. package/src/lib/form.utils.ts +1009 -0
  409. package/src/lib/page.flow.utils.ts +81 -0
  410. package/src/lib/page.utils.ts +865 -0
  411. package/src/lib/performance.utils.ts +302 -0
  412. package/src/lib/tablerow.utils.ts +51 -0
  413. package/src/lib/utils.ts +643 -0
  414. package/src/main.scss +717 -0
  415. package/src/main.ts +74 -0
  416. package/src/menu.ts +78 -0
  417. package/src/nestedlist_color.scss +161 -0
  418. package/src/router/index.ts +92 -0
  419. package/src/stores/auth.ts +117 -0
  420. package/src/stores/counter.ts +12 -0
  421. package/src/stores/dialog.ts +168 -0
  422. package/src/stores/form.ts +103 -0
  423. package/src/stores/tabs.ts +52 -0
  424. package/src/tw.scss +419 -0
  425. package/src/types/form.types.ts +348 -0
  426. package/src/types/types.ts +7 -0
  427. package/src/utils/config.utils.ts +149 -0
  428. package/src/views/NotFound.vue +30 -0
  429. package/src/views/PageActivity.vue +15 -0
  430. package/src/views/auth/LoginView.vue +7 -0
  431. package/src/views/auth/OauthCallback.vue +101 -0
  432. package/src/views/dashboard/index.vue +16 -0
  433. package/src/views/settings/AccountSettingsView.vue +70 -0
  434. package/src/views/settings/AuditLogsSettingsView.vue +116 -0
  435. package/src/views/settings/DeviceSettingsView.vue +70 -0
  436. package/src/views/settings/MainSettingsView.vue +12 -0
  437. package/src/views/settings/ProfileSettingsView.vue +104 -0
  438. package/src/vueform/config/informasi-gudang.ts +47 -0
  439. package/src/vueform/config/test-schema.ts +8 -0
  440. package/src/vueform/config/types.ts +768 -0
  441. package/src/vueform/customization/classes.js +46 -0
  442. package/src/vueform/customization/tailwind.classes.js +2117 -0
  443. package/src/vueform/elements/ConfigDataSelectorElement.vue +50 -0
  444. package/src/vueform/elements/DateSelectorElement.vue +323 -0
  445. package/src/vueform/elements/SelectorElement.vue +153 -0
  446. package/src/vueform/schemas/date-selector-test.ts +103 -0
  447. package/src/vueform/schemas/informasi-gudang.ts +160 -0
  448. package/src/vueform/schemas/test-schema.ts +483 -0
  449. package/src/vueform.config.js +77 -0
  450. package/src/vueform.validator.ts +77 -0
@@ -0,0 +1,865 @@
1
+ import type { ColumnAction, ColumnRef, CustomBtnConfig, FilterForm, PageConfig, SortBy, ToggleConfig } from "@/vueform/config/types";
2
+ import { convertToUtf8, formatMonthYear, formatNumberIntl, getMenuItemByUrl, isValidValue } from "./utils";
3
+ import type { DasiV2FormSchema, FormSchema, FormSchemaHooks } from "@/types/form.types";
4
+ import type { Submenu } from "@/menu";
5
+ import { ref } from "vue";
6
+ import api from "@/api/api";
7
+ import type { AxiosResponse } from "axios";
8
+ import moment from "moment";
9
+ import { useErrorDialog } from "@/stores/dialog";
10
+ import { InternalServerError } from "./constants";
11
+
12
+ /**
13
+ * Dialog
14
+ *
15
+ */
16
+ const errorDialog = useErrorDialog();
17
+
18
+ // Helper function to process mapped filter values
19
+ function processMappedValue(mappedValue: any, filterItem: any) {
20
+ if (!mappedValue || typeof mappedValue !== "object") return;
21
+
22
+ Object.entries(mappedValue).forEach(([fieldKey, fieldValue]) => {
23
+ if (typeof fieldValue === "object" && fieldValue !== null) {
24
+ // Nested object: { field: { gte: "value", lte: "value" } }
25
+ Object.entries(fieldValue).forEach(([op, val]) => {
26
+ filterItem[`filters[${fieldKey}][${op}]`] = { type: op, value: String(val) };
27
+ });
28
+ } else {
29
+ // Simple value: { field: "value" }
30
+ filterItem[`filters[${fieldKey}][eq]`] = { type: "eq", value: String(fieldValue) };
31
+ }
32
+ });
33
+ }
34
+
35
+ /**
36
+ * ----------------------------------
37
+ * Filter & Toggle
38
+ * ----------------------------------
39
+ *
40
+ */
41
+ export interface FilterItem {
42
+ [key: string]: { type: string; value: string };
43
+ }
44
+
45
+ export interface ToggleState {
46
+ checked: boolean;
47
+ endpoint: string;
48
+ }
49
+
50
+ interface FilterQueryWithCondition {
51
+ filterQueryyString: string;
52
+ conditions: string[];
53
+ }
54
+
55
+ /**
56
+ * Returns two FilterForm objects:
57
+ * - The first contains filters to display on the page action menu (showOnPageActionMenu === true)
58
+ * - The second contains filters to display on the filter form dialog (showOnPageActionMenu !== true)
59
+ *
60
+ */
61
+ export function getFilterSeparated(filter: FilterForm): [FilterForm, FilterForm] {
62
+ const pageActionMenuFilter: FilterForm = {};
63
+ const formDialogFilter: FilterForm = {};
64
+
65
+ for (const [key, value] of Object.entries(filter)) {
66
+ /**
67
+ * If filter state saved, then get from storage
68
+ *
69
+ */
70
+ if (value.saveSate) {
71
+ const saveSate = value.stateStorage ?? "session";
72
+ const storage = saveSate === "local" ? localStorage : sessionStorage;
73
+ const valueStr = storage.getItem(`dasiv2.filter.${value.stateKey ?? key}`);
74
+ if (valueStr) {
75
+ try {
76
+ const savedValue = JSON.parse(valueStr);
77
+ if (savedValue) {
78
+ if (value.filterType === "month|year" && typeof savedValue === "string") {
79
+ value.nullValue = new Date(savedValue);
80
+ } else {
81
+ value.nullValue = savedValue;
82
+ }
83
+ }
84
+ } catch (err) {
85
+ console.error("Failed get filter state", err);
86
+ }
87
+ }
88
+ }
89
+
90
+ if (value.showOnPageActionMenu) pageActionMenuFilter[key] = value;
91
+ else formDialogFilter[key] = value;
92
+ }
93
+
94
+ return [pageActionMenuFilter, formDialogFilter];
95
+ }
96
+
97
+ export function genFilterQuery(filterSchema: FilterForm, formData?: any): FilterItem {
98
+ const filterItem: FilterItem = {};
99
+ for (const [key, item] of Object.entries(filterSchema || {}) as any[]) {
100
+ /**
101
+ * Set the filter item value to default
102
+ * it not yet set
103
+ *
104
+ */
105
+ const itemValue = formData?.[key] ?? item.default;
106
+ if (itemValue === undefined || itemValue === null) continue;
107
+
108
+ /**
109
+ * Save state
110
+ *
111
+ */
112
+ if (item.saveSate) {
113
+ const saveSate = item.stateStorage ?? "session";
114
+ const valueStr = JSON.stringify(itemValue);
115
+ if (valueStr) {
116
+ try {
117
+ const storage = saveSate === "local" ? localStorage : sessionStorage;
118
+ storage.setItem(`dasiv2.filter.${item.stateKey ?? key}`, valueStr);
119
+ } catch (err) {
120
+ console.error("Failed get filter state", err);
121
+ }
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Set default so when filter dialog opened again
127
+ * it will set to prev data
128
+ *
129
+ */
130
+ item.default = itemValue;
131
+
132
+ if (item.filterType === "month|year") {
133
+ const d = new Date(String(itemValue));
134
+ if (item.isStokReal) {
135
+ filterItem[`month`] = { type: "eq", value: String(d.getMonth() + 1) };
136
+ filterItem[`year`] = { type: "eq", value: String(d.getFullYear()) };
137
+ } else {
138
+ filterItem[`filters[${key}][month]`] = { type: "eq", value: String(d.getMonth() + 1) };
139
+ filterItem[`filters[${key}][year]`] = { type: "eq", value: String(d.getFullYear()) };
140
+ }
141
+ } else if (item.filterType === "custom" && item.mapFilterValue) {
142
+ const mappedValue = item.mapFilterValue(String(itemValue));
143
+ processMappedValue(mappedValue, filterItem);
144
+
145
+ // Fallback for non-object values
146
+ if (!mappedValue || typeof mappedValue !== "object") {
147
+ filterItem[`filters[${key}][custom]`] = { type: "custom", value: String(mappedValue) };
148
+ }
149
+ } else {
150
+ if (item.isRaw) {
151
+ filterItem[`${key}`] = { type: item.filterType, value: String(itemValue) };
152
+ } else {
153
+ filterItem[`filters[${key}][${item.filterType}]`] = { type: item.filterType, value: String(itemValue) };
154
+ }
155
+ }
156
+ }
157
+ return filterItem;
158
+ }
159
+
160
+ export function genFilterQueryString(filterItem: FilterItem): FilterQueryWithCondition {
161
+ const regexForKeyCondition = /\[([^\]]+)\]/;
162
+ const searchParams = new URLSearchParams();
163
+ const conditions = [];
164
+ for (const [key, value] of Object.entries(filterItem)) {
165
+ const conditionKey = key.match(regexForKeyCondition);
166
+ if (value.type === "condition") conditions.push(`${key}:${value.value}`);
167
+ else if (value.type === "asCondition" && conditionKey && conditionKey[1]) {
168
+ conditions.push(`${conditionKey[1]}:${value.value}`);
169
+ } else searchParams.append(key, value.value);
170
+ }
171
+ return { filterQueryyString: searchParams.toString(), conditions };
172
+ }
173
+
174
+ export function filterQueryString(filterItem: FilterItem): string {
175
+ return "";
176
+ // const searchParams = new URLSearchParams();
177
+ // Object.entries(filterItem).forEach(([key, value]) => {
178
+ // searchParams.append(key, value);
179
+ // });
180
+ // return searchParams.toString();
181
+ }
182
+
183
+ /**
184
+ * Initialize toggle state based on pageConfig
185
+ * Returns the initial toggle state and modified endpoint
186
+ */
187
+ export function initToggleState(pageConfig: PageConfig, baseEndpoint: string): ToggleState {
188
+ if (!pageConfig.toggleConfig?.show) {
189
+ return { checked: true, endpoint: baseEndpoint };
190
+ }
191
+
192
+ const toggleConfig = pageConfig.toggleConfig;
193
+ const defaultChecked = toggleConfig.defaultChecked ?? true;
194
+
195
+ let modifiedEndpoint = baseEndpoint;
196
+
197
+ if (toggleConfig.onChange) {
198
+ modifiedEndpoint = toggleConfig.onChange(defaultChecked, baseEndpoint);
199
+ } else if (toggleConfig.urlSuffixes) {
200
+ const suffix = defaultChecked ? toggleConfig.urlSuffixes.checked : toggleConfig.urlSuffixes.unchecked;
201
+ modifiedEndpoint = baseEndpoint + suffix;
202
+ }
203
+
204
+ return {
205
+ checked: defaultChecked,
206
+ endpoint: modifiedEndpoint
207
+ };
208
+ }
209
+
210
+ /**
211
+ * Apply toggle change and return new endpoint
212
+ */
213
+ export function applyToggleChange(toggleConfig: ToggleConfig, checked: boolean, currentEndpoint: string): string {
214
+ if (!toggleConfig.show) return currentEndpoint;
215
+
216
+ // Get base endpoint by removing existing toggle suffixes
217
+ let baseEndpoint = currentEndpoint;
218
+ if (toggleConfig.urlSuffixes) {
219
+ if (toggleConfig.urlSuffixes.checked && baseEndpoint.endsWith(toggleConfig.urlSuffixes.checked)) {
220
+ baseEndpoint = baseEndpoint.slice(0, -toggleConfig.urlSuffixes.checked.length);
221
+ } else if (toggleConfig.urlSuffixes.unchecked && baseEndpoint.endsWith(toggleConfig.urlSuffixes.unchecked)) {
222
+ baseEndpoint = baseEndpoint.slice(0, -toggleConfig.urlSuffixes.unchecked.length);
223
+ }
224
+ }
225
+
226
+ // Apply new toggle state
227
+ if (toggleConfig.onChange) {
228
+ return toggleConfig.onChange(checked, baseEndpoint);
229
+ } else if (toggleConfig.urlSuffixes) {
230
+ const suffix = checked ? toggleConfig.urlSuffixes.checked : toggleConfig.urlSuffixes.unchecked;
231
+ return baseEndpoint + suffix;
232
+ }
233
+
234
+ return currentEndpoint;
235
+ }
236
+
237
+ /**
238
+ * ----------------------------------
239
+ * Row renderer
240
+ * ----------------------------------
241
+ *
242
+ */
243
+
244
+ /**
245
+ * Generic render function for nested object with code/name pattern
246
+ * Example: renderObjectWithCode(item, 'contract', 'contractCode')
247
+ */
248
+ export function renderObjectWithCode(item: any, objectKey: string, codeKey?: string) {
249
+ if (!item) return "";
250
+ const obj = item[objectKey];
251
+ if (!obj) return "";
252
+ const code = codeKey ? obj[codeKey] : obj.code || obj.no || obj.number || "";
253
+ const amendment = obj.amendment || obj.amandemen;
254
+ return `${code}${amendment ? ` / ${amendment.code || amendment.no || amendment.number || ""}` : ""}`;
255
+ }
256
+
257
+ /**
258
+ * Generic render function for nested object from child field
259
+ */
260
+ export function renderObjectFromChild(jp: any, childField: string, objectKey: string, codeKey?: string) {
261
+ if (!isValidValue(jp?.[childField])) return "";
262
+ return renderObjectWithCode(jp?.[childField]?.[0], objectKey, codeKey);
263
+ }
264
+
265
+ /**
266
+ * Generic render function for date from nested object
267
+ */
268
+ export function renderDateFromChild(jp: any, childField: string, dateField: string, format = "DD/MM/YYYY") {
269
+ if (!isValidValue(jp?.[childField]) || !jp?.[childField]?.[0]?.[dateField]) return "";
270
+ return moment(jp?.[childField]?.[0]?.[dateField]).format(format);
271
+ }
272
+
273
+ /**
274
+ * Generic render function for approval status
275
+ */
276
+ export function renderApprovalStatus(jp: any, prevField: string, nextField: string) {
277
+ if (!jp) return "";
278
+ if (!isValidValue(jp[prevField])) return "<b>Belum Disubmit</b>";
279
+ if (!isValidValue(jp[nextField]) || (isValidValue(jp[prevField]) && jp[prevField][0]?.submitUlang)) {
280
+ return '<b class="text-orange-500">Menunggu Persetujuan</b>';
281
+ }
282
+ return jp[nextField][0]?.disetujui ? '<b class="text-green-500">Disetujui</b>' : `<b class="text-red-500">Tidak Disetujui</b>`;
283
+ }
284
+
285
+ /**
286
+ * ----------------------------------
287
+ * Page initialization
288
+ * ----------------------------------
289
+ *
290
+ */
291
+ interface BaseInitOptions {
292
+ tabReactive: any;
293
+ onRestore: (i: number, item: any) => void;
294
+ onDelete: (i: number, item: any) => void;
295
+ onEdit: (i: number, item: any) => void;
296
+ onCustomBtnClick?: (i: number, item: any, btnId?: string) => void;
297
+ }
298
+
299
+ interface PageInitOptions extends BaseInitOptions {
300
+ pageCode: string;
301
+ endpoint: string;
302
+ fullPath: string;
303
+ }
304
+
305
+ interface InitPageReturn {
306
+ pageConfig: PageConfig;
307
+ queryString: string;
308
+ endpoint: string;
309
+ formSchema: DasiV2FormSchema;
310
+ formHooks: FormSchemaHooks;
311
+ menuItem?: Submenu;
312
+ title: string;
313
+ columns: ColumnRef[];
314
+ }
315
+
316
+ interface InitColumnsOptions extends BaseInitOptions {
317
+ pageInfo: any;
318
+ pageConfig: PageConfig;
319
+ formSchema: DasiV2FormSchema;
320
+ title: string;
321
+ }
322
+
323
+ export async function initPageConfig(endpoint: string): Promise<PageConfig> {
324
+ let pageConfig: PageConfig;
325
+
326
+ /**
327
+ * Dynamically import the page config
328
+ * for the current endpoint,
329
+ * if not found, use dault page config
330
+ *
331
+ */
332
+ try {
333
+ const configModule = await import(`@/vueform/config/${endpoint}.ts`);
334
+ pageConfig = configModule.default;
335
+ } catch (err) {
336
+ console.log(`No specific config found for ${endpoint}, using defaults`);
337
+ pageConfig = {};
338
+ }
339
+
340
+ return pageConfig;
341
+ }
342
+
343
+ export async function initPageSchema(pageCode: string, schemaPath: string): Promise<FormSchema> {
344
+ let schema: DasiV2FormSchema = {};
345
+ let hooks: FormSchemaHooks = {};
346
+
347
+ /**
348
+ * Init form schema and table column
349
+ * from the same schema file
350
+ *
351
+ */
352
+ try {
353
+ const schemaImported = (await import(`@/vueform/schemas/${pageCode}/${schemaPath}.ts`)).default;
354
+ schema = schemaImported.schema ?? schemaImported;
355
+ hooks = schemaImported.hooks ?? schemaImported;
356
+ } catch (err) {
357
+ /**
358
+ * @deprecated
359
+ * all schema should be foldered
360
+ *
361
+ */
362
+ try {
363
+ const schemaImported = (await import(`@/vueform/schemas/${schemaPath}.ts`)).default;
364
+ schema = schemaImported.schema ?? schemaImported;
365
+ hooks = schemaImported.hooks ?? schemaImported;
366
+ } catch (err) {
367
+ /**
368
+ * Now page activity can run without schema
369
+ * for some page that use custom form
370
+ * or display read only pages
371
+ *
372
+ */
373
+ console.log("Schema not found, read only or custom form page");
374
+ // throw new Error('Schema not found')
375
+ }
376
+ }
377
+
378
+ return { schema, hooks };
379
+ }
380
+
381
+ export function genColumnFromSchema(formSchema: DasiV2FormSchema): ColumnRef[] {
382
+ const columns: ColumnRef[] = [];
383
+ let i = 0;
384
+ for (const [key, item] of Object.entries(formSchema)) {
385
+ /**
386
+ * Skip static content
387
+ *
388
+ */
389
+ if ((item as any).showField === false || ["static", "container", "group"].includes((item as any).type)) continue;
390
+
391
+ /**
392
+ * Format {field}Id {field}Ids {field}Code
393
+ * Used on selector and config data relation
394
+ *
395
+ */
396
+ let newKey = key;
397
+ if (key.substring(key.length - 2) === "Id") newKey = key.substring(0, key.length - 2);
398
+ else if (key.substring(key.length - 3) === "Ids") newKey = key.substring(0, key.length - 3);
399
+ else if (key.substring(key.length - 4) === "Code" && key !== "unitCode") newKey = key.substring(0, key.length - 4);
400
+ const itemAny = item as any;
401
+
402
+ /**
403
+ * Set item visible or not
404
+ *
405
+ */
406
+ itemAny.showInTable = itemAny.showInTable ?? i < 5;
407
+
408
+ columns.push({
409
+ key: item.key ?? newKey,
410
+ type: "cell",
411
+ sortKey: itemAny.sortKey,
412
+ header: itemAny.cellHeader ?? itemAny.label ?? itemAny.text,
413
+ description: itemAny.cellDescripton,
414
+ visible: itemAny.showInTable,
415
+ cellType: itemAny.cellType ?? itemAny.type,
416
+ items: itemAny.items,
417
+ dataSource: itemAny.cellDataSource,
418
+
419
+ /**
420
+ * Number formatting
421
+ *
422
+ */
423
+ mask: itemAny.mask,
424
+ addons: itemAny.addons,
425
+
426
+ /**
427
+ * Selector props (from BaseSelector.vue)
428
+ *
429
+ */
430
+ showAvatar: itemAny.showAvatar,
431
+ returnObject: itemAny.returnObject,
432
+ autoFillOrg: itemAny.autoFillOrg,
433
+ multiple: itemAny.multiple,
434
+ params: itemAny.params,
435
+ condition: itemAny.condition,
436
+ orderBy: itemAny.orderBy,
437
+ sort: itemAny.sort,
438
+ objectKey: itemAny.objectKey,
439
+ nameField: itemAny.nameField,
440
+ nameFieldFunc: itemAny.nameFieldFunc,
441
+ descriptionField: itemAny.descriptionField,
442
+ descriptionFieldFunc: itemAny.descriptionFieldFunc,
443
+
444
+ /**
445
+ * Date Selector props (from DateSelectorElement.vue)
446
+ *
447
+ */
448
+ pickerType: itemAny.pickerType,
449
+ range: itemAny.range,
450
+ displayFormat: itemAny.displayFormat,
451
+ yearRange: itemAny.yearRange,
452
+ autoApply: itemAny.autoApply,
453
+ textInput: itemAny.textInput,
454
+ startDate: itemAny.startDate,
455
+ minDate: itemAny.minDate,
456
+ maxDate: itemAny.maxDate,
457
+
458
+ /**
459
+ * Custom render html
460
+ *
461
+ */
462
+ cellRender: itemAny.cellRender,
463
+
464
+ /**
465
+ * Header and cell align
466
+ *
467
+ */
468
+ textAlign: itemAny.textAlign,
469
+ headAlign: itemAny.headAlign
470
+ });
471
+ i += 1;
472
+ }
473
+ return columns;
474
+ }
475
+
476
+ export function initPageColumns(pageInfo: any, pageConfig: PageConfig, formSchema: DasiV2FormSchema): ColumnRef[] {
477
+ /**
478
+ * Columns are auto generated from pageConfig
479
+ * and fallback to schema
480
+ *
481
+ */
482
+ const columnSchema = pageConfig.columns ?? formSchema ?? {};
483
+
484
+ /**
485
+ * Auto generate columns
486
+ * columns are auto generated from pageConfig
487
+ * and fallback to schema
488
+ *
489
+ */
490
+ const columns: ColumnRef[] = [{ key: "id", header: "ID", visible: false, cellType: "text" }];
491
+ if (Array.isArray(columnSchema)) {
492
+ columns.push(...columnSchema);
493
+ } else {
494
+ columns.push(...genColumnFromSchema(columnSchema));
495
+ }
496
+
497
+ if (pageInfo.isApprovalRequired && !pageConfig.hideApprovalStatus) {
498
+ columns.push({ key: "status", cellType: "approval_status", header: "Status Approval", sortKey: "status", visible: true });
499
+ }
500
+
501
+ columns.push({ key: "createdAt", cellType: "dasi_v2_datetime", header: "Tanggal Dibuat", sortKey: "created_at" });
502
+ return columns;
503
+ }
504
+
505
+ function initColumns(options: InitColumnsOptions) {
506
+ /**
507
+ * Auto generate columns
508
+ *
509
+ */
510
+ const columns = initPageColumns(options.pageInfo, options.pageConfig, options.formSchema);
511
+
512
+ /**
513
+ * Add column for row action
514
+ *
515
+ */
516
+ if (options.pageConfig.showActionRow !== false) {
517
+ let actionRow: ColumnRef = { key: "action" };
518
+ if (options.pageConfig.actionRowConfig) {
519
+ actionRow = { ...options.pageConfig.actionRowConfig };
520
+ }
521
+
522
+ actionRow.type = "action";
523
+ if (typeof actionRow.visible !== "boolean") actionRow.visible = true;
524
+ if (typeof actionRow.showAction !== "boolean") {
525
+ actionRow.showAction = options.pageConfig.showActionRowOptions;
526
+ }
527
+
528
+ /**
529
+ * Row action button
530
+ *
531
+ */
532
+ let customBtnConfig = options.pageConfig.actionRowBtnConfig ? options.pageConfig.actionRowBtnConfig : { show: !!options.pageConfig.showActionRowButton };
533
+ if (!actionRow.customBtnConfig) actionRow.customBtnConfig = customBtnConfig;
534
+ if (!actionRow.onCustomBtnClick) actionRow.onCustomBtnClick = options.onCustomBtnClick;
535
+ if (!actionRow.actions) {
536
+ actionRow.actions = (i, row) => {
537
+ const moreActions: ColumnAction[] = [];
538
+ const pcMoreActions: ColumnAction[] = [];
539
+ if (options.pageConfig.moreRowActions) {
540
+ if (typeof options.pageConfig.moreRowActions === "function") {
541
+ pcMoreActions.push(...options.pageConfig.moreRowActions(i, row));
542
+ } else {
543
+ pcMoreActions.push(...options.pageConfig.moreRowActions);
544
+ }
545
+ }
546
+ for (const moreAction of pcMoreActions) {
547
+ const actionItem = { ...moreAction };
548
+ if (!actionItem.action) actionItem.action = options.onCustomBtnClick;
549
+ moreActions.push(actionItem);
550
+ }
551
+
552
+ return options.tabReactive.value === "deleted"
553
+ ? [
554
+ {
555
+ id: "restore",
556
+ label: `Restore ${options.title}`,
557
+ icon: "LucideUndo2",
558
+ action: options.onRestore
559
+ }
560
+ ]
561
+ : (() => {
562
+ const base = options.pageConfig.hideEditAction
563
+ ? [...moreActions]
564
+ : [
565
+ {
566
+ id: "edit",
567
+ label: `Edit ${options.title}`,
568
+ icon: "LucideEdit",
569
+ action: options.onEdit
570
+ },
571
+ ...moreActions
572
+ ];
573
+ if (options.pageConfig.hideDeleteAction) return base;
574
+ return [
575
+ ...base,
576
+ {
577
+ type: "separator",
578
+ action: () => {}
579
+ },
580
+ {
581
+ id: "delete",
582
+ label: `Hapus ${options.title}`,
583
+ icon: "LucideTrash2",
584
+ action: options.onDelete,
585
+ negative: true
586
+ }
587
+ ];
588
+ })();
589
+ };
590
+ }
591
+ columns.push(actionRow);
592
+ }
593
+
594
+ return columns;
595
+ }
596
+
597
+ export async function initPageActivity(options: PageInitOptions): Promise<InitPageReturn> {
598
+ /**
599
+ * Prepare variables
600
+ * set endpoint without /
601
+ *
602
+ */
603
+ let newEndpoint = options.endpoint.replace(/^\/+/, "");
604
+ let queryString = "";
605
+
606
+ /**
607
+ * Init page config
608
+ *
609
+ */
610
+ const pageConfig = await initPageConfig(newEndpoint);
611
+
612
+ /**
613
+ * If there is parentField, that mean
614
+ * this is page for flow, we update status
615
+ * from child
616
+ *
617
+ */
618
+ if (pageConfig.parentField && pageConfig.nextDataField) {
619
+ if (!pageConfig.dataTransformer) {
620
+ pageConfig.dataTransformer = data => {
621
+ for (const item of data) {
622
+ item.status = item?.[pageConfig.nextDataField ?? "_"]?.[0]?.status;
623
+ }
624
+ return data;
625
+ };
626
+ }
627
+ }
628
+
629
+ /**
630
+ * Retrieve endpoint from pageConfig
631
+ * and format if endpoint conaints query params
632
+ *
633
+ */
634
+ if (pageConfig.endpoint) {
635
+ const endpointSplited = pageConfig.endpoint.split("?");
636
+ newEndpoint = endpointSplited[0].replace(/^\/+/, "");
637
+ queryString = endpointSplited.length > 1 ? endpointSplited[1] : "";
638
+ }
639
+
640
+ /**
641
+ * Apply toggle configuration to endpoint if present
642
+ * This modifies the endpoint based on the default toggle state
643
+ */
644
+ const toggleState = initToggleState(pageConfig, `/${newEndpoint}`);
645
+ newEndpoint = toggleState.endpoint.replace(/^\/+/, "");
646
+
647
+ /**
648
+ * Get page info,
649
+ * if user allowed to do certain things
650
+ *
651
+ */
652
+ const pageInfoUrl = pageConfig.savePath ?? newEndpoint;
653
+ const r = await api.get(`${pageInfoUrl}/init`);
654
+ const pageInfo = r.data.data ?? {};
655
+
656
+ /**
657
+ * Load form schema, default to endpoint
658
+ * unless specified on page config
659
+ *
660
+ */
661
+ const schemaPath = pageConfig.schema ?? newEndpoint;
662
+ const schema = await initPageSchema(options.pageCode, schemaPath);
663
+ const formSchema = schema.schema ?? schema;
664
+ const formHooks = schema.hooks ?? schema;
665
+
666
+ /**
667
+ * Get menu item from url
668
+ * and set for title
669
+ *
670
+ */
671
+ const menuItem = getMenuItemByUrl(options.fullPath);
672
+ let title = String(menuItem?.name ?? "");
673
+
674
+ // Fallback title based on endpoint if menu item not found
675
+ if (!title) {
676
+ title = "Data";
677
+ }
678
+
679
+ /**
680
+ * Init table columns
681
+ *
682
+ */
683
+ const columns = initColumns({
684
+ pageInfo,
685
+ pageConfig,
686
+ formSchema,
687
+ tabReactive: options.tabReactive,
688
+ title,
689
+ onRestore: options.onRestore,
690
+ onDelete: options.onDelete,
691
+ onEdit: options.onEdit,
692
+ onCustomBtnClick: options.onCustomBtnClick
693
+ });
694
+
695
+ return {
696
+ pageConfig,
697
+ queryString,
698
+ endpoint: `/${newEndpoint}`,
699
+ formSchema,
700
+ formHooks: formHooks as any,
701
+ menuItem,
702
+ title,
703
+ columns
704
+ };
705
+ }
706
+
707
+ /**
708
+ * ----------------------------------
709
+ * Get data
710
+ * ----------------------------------
711
+ *
712
+ */
713
+ interface GetPageDataOptions {
714
+ endpoint: string;
715
+ tabActive: string;
716
+ queryParams: string;
717
+ searchQuery: string;
718
+ columns: ColumnRef[];
719
+ sortBy?: SortBy;
720
+ filterQueryForm: FilterItem;
721
+ filterQueryPageMenu: FilterItem;
722
+ pageConfig: PageConfig;
723
+ pagination: DataPagination;
724
+ }
725
+
726
+ interface GetPageDataDetailOptions {
727
+ item: any;
728
+ endpoint: string;
729
+ formSchema: DasiV2FormSchema;
730
+ pageConfig?: PageConfig;
731
+ includeExtras?: boolean;
732
+ }
733
+
734
+ interface DataPagination {
735
+ page: number;
736
+ limit: number;
737
+ }
738
+
739
+ export function addStringToUri(uri: string, newStr: string) {
740
+ if (!newStr) return uri;
741
+ return `${uri.includes("?") ? "&" : "?"}${newStr}`;
742
+ }
743
+
744
+ export async function getPageDataDetail(options: GetPageDataDetailOptions): Promise<AxiosResponse<any, any> | null> {
745
+ if (options.pageConfig?.pageDetailHooks?.onDetailOpen) {
746
+ try {
747
+ if (!(await options.pageConfig?.pageDetailHooks?.onDetailOpen(options.formSchema, options.item))) return Promise.resolve(null);
748
+ } catch (err: any) {
749
+ errorDialog.open({ title: "Gagal Menampilkan Data Detail", description: err.message ?? InternalServerError });
750
+ }
751
+ }
752
+
753
+ let detailUri;
754
+ if (options.pageConfig?.pageDetailHooks?.setEndpoint) {
755
+ detailUri = await options.pageConfig?.pageDetailHooks?.setEndpoint(options.formSchema, options.item);
756
+ } else {
757
+ detailUri = `${options.endpoint}/${options.item.id}`;
758
+ const queryParams: string[] = [];
759
+ if (options.pageConfig?.extras && options.includeExtras !== false) {
760
+ queryParams.push(`extras=${(options.pageConfig.extras ?? []).join(",")}`);
761
+ }
762
+ if (options.pageConfig?.conditions) {
763
+ queryParams.push(`condition=${(options.pageConfig.conditions ?? []).join(",")}`);
764
+ }
765
+ detailUri += `?${queryParams.join("&")}`;
766
+ }
767
+ const r = await api.get(detailUri);
768
+ if (options.pageConfig?.dataDetailTransformer) {
769
+ r.data.data = options.pageConfig?.dataDetailTransformer(r.data.data);
770
+ }
771
+
772
+ if (options.pageConfig?.pageDetailHooks?.onBeforeMount) {
773
+ try {
774
+ if (!(await options.pageConfig?.pageDetailHooks?.onBeforeMount(options.formSchema, r.data.data))) return Promise.resolve(null);
775
+ } catch (err: any) {
776
+ errorDialog.open({ title: "Gagal Menampilkan Data Detail", description: err.message ?? InternalServerError });
777
+ }
778
+ }
779
+
780
+ return r;
781
+ }
782
+
783
+ export async function getPageData(options: GetPageDataOptions): Promise<AxiosResponse<any, any>> {
784
+ /**
785
+ * Standard endpoint handling
786
+ *
787
+ */
788
+ const uriArr = options.endpoint.split("?");
789
+ let baseUri = uriArr[0];
790
+ if (options.tabActive === "deleted") baseUri += "/deleted";
791
+
792
+ /**
793
+ * Add query params if any
794
+ *
795
+ */
796
+ if (options.queryParams) baseUri += addStringToUri(baseUri, options.queryParams);
797
+ if (baseUri.endsWith("?") || baseUri.endsWith("&")) baseUri.substring(0, baseUri.length - 1);
798
+
799
+ /**
800
+ * Add search query
801
+ *
802
+ */
803
+ if (options.searchQuery) {
804
+ baseUri += addStringToUri(baseUri, `search=${options.searchQuery}`);
805
+ const searchColumns = ["id"];
806
+ for (const [_, item] of Object.entries(options.columns)) {
807
+ if (!item.sortKey || !item.visible) continue;
808
+ searchColumns.push(item.sortKey);
809
+ }
810
+ if (searchColumns.length > 0) baseUri += addStringToUri(baseUri, `searchColumns=${searchColumns.join(",")}${options.pageConfig?.searchColumns ? `,${options.pageConfig.searchColumns}` : ""}`);
811
+ }
812
+
813
+ /**
814
+ * Add pagination
815
+ *
816
+ */
817
+ const pg = options.pagination;
818
+ baseUri += addStringToUri(baseUri, `limit=${pg.limit}&page=${pg.page}`);
819
+
820
+ /**
821
+ * Add sort by
822
+ *
823
+ */
824
+ if (options.sortBy) baseUri += addStringToUri(baseUri, `orderBy=${options.sortBy.key}&sort=${options.sortBy.by}`);
825
+
826
+ /**
827
+ * Set filter and conditions
828
+ *
829
+ */
830
+ const fcForm = genFilterQueryString(options.filterQueryForm);
831
+ const fcPage = genFilterQueryString(options.filterQueryPageMenu);
832
+ if (fcForm.filterQueryyString) baseUri += addStringToUri(baseUri, fcForm.filterQueryyString);
833
+ if (fcPage.filterQueryyString) baseUri += addStringToUri(baseUri, fcPage.filterQueryyString);
834
+
835
+ const cdArr = [];
836
+ if (fcForm.conditions) cdArr.push(...fcForm.conditions);
837
+ if (fcPage.conditions) cdArr.push(...fcPage.conditions);
838
+ if (options.pageConfig.conditions) cdArr.push(...options.pageConfig.conditions);
839
+ let conditions = [...cdArr];
840
+ const { searchQuery } = options;
841
+
842
+ if (typeof searchQuery === "string" && /^\W$/.test(searchQuery) && convertToUtf8(searchQuery)) {
843
+ conditions.push(`satuan:${convertToUtf8(searchQuery)}`);
844
+ }
845
+
846
+ if (conditions.length > 0) baseUri += addStringToUri(baseUri, `condition=${conditions.join(",")}`);
847
+
848
+ /**
849
+ * Add extras data relation
850
+ *
851
+ */
852
+ const extrasStr = (options.pageConfig.extras ?? []).join(",");
853
+ if (extrasStr) baseUri += addStringToUri(baseUri, `extras=${extrasStr}`);
854
+
855
+ /**
856
+ * Get the data from api
857
+ *
858
+ */
859
+ const r = await api.get(baseUri);
860
+ if (options.pageConfig.dataTransformer) {
861
+ r.data.data = options.pageConfig.dataTransformer(r.data.data);
862
+ }
863
+
864
+ return r;
865
+ }