@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.
- package/README.md +346 -0
- package/bin/dasi-cli.cjs +184 -0
- package/dist/date-selector-test-BlukYeWl.js +91 -0
- package/dist/favicon.ico +0 -0
- package/dist/html2canvas.esm-CKxSAI8P.js +4886 -0
- package/dist/img/brand/ic_pln.svg +12 -0
- package/dist/img/brand/mapp_power_logo.svg +21 -0
- package/dist/img/common/pltu_ulumbu_flores_ntt.jpeg +0 -0
- package/dist/index-BQSA2aPs.js +126556 -0
- package/dist/index.es-DQWt-PZn.js +5769 -0
- package/dist/index.es.js +11 -0
- package/dist/index.umd.js +8564 -0
- package/dist/informasi-gudang-BmoEy2RL.js +164 -0
- package/dist/informasi-gudang-DXfS46Nh.js +50 -0
- package/dist/purify.es-C-9oolON.js +546 -0
- package/dist/scripts/pdf.worker.min.js +29 -0
- package/dist/scripts/pdf.worker.min.mjs +29 -0
- package/dist/scripts/pdf.worker.mjs +57722 -0
- package/dist/scripts/pdf.worker.mjs.map +1 -0
- package/dist/style.css +1 -0
- package/dist/test-schema-JFghGc0_.js +8 -0
- package/dist/test-schema-uusFsJe4.js +438 -0
- package/dist/types-l0sNRNKZ.js +1 -0
- package/package.json +178 -0
- package/src/App.vue +18 -0
- package/src/__tests__/index.test.ts +9 -0
- package/src/api/api.ts +117 -0
- package/src/assets/app-selector.svg +3 -0
- package/src/assets/dasi.png +0 -0
- package/src/assets/foto_ss.svg +21 -0
- package/src/assets/icons/circle-blue.svg +4 -0
- package/src/assets/icons/circle-gray.svg +15 -0
- package/src/assets/icons/circle-green.svg +4 -0
- package/src/assets/icons/circle-orange.svg +4 -0
- package/src/assets/icons/circle-purple.svg +4 -0
- package/src/assets/icons/circle-red.svg +15 -0
- package/src/assets/icons/harbor.svg +12 -0
- package/src/assets/icons/ic-box-red.svg +8 -0
- package/src/assets/icons/ic-chevron-right.svg +1 -0
- package/src/assets/icons/ic-loading.svg +9 -0
- package/src/assets/icons/ic-reset.svg +16 -0
- package/src/assets/icons/ic-sailing.svg +5 -0
- package/src/assets/icons/icon-app-selector.svg +3 -0
- package/src/assets/icons/icon-browser-check.svg +4 -0
- package/src/assets/icons/icon-calendar.svg +3 -0
- package/src/assets/icons/icon-chart-bar.svg +3 -0
- package/src/assets/icons/icon-chart-doc.svg +16 -0
- package/src/assets/icons/icon-chart-line.svg +10 -0
- package/src/assets/icons/icon-chart-mix.svg +15 -0
- package/src/assets/icons/icon-chart-pie.svg +11 -0
- package/src/assets/icons/icon-continue.svg +12 -0
- package/src/assets/icons/icon-dashboard-2.svg +17 -0
- package/src/assets/icons/icon-dashboard.svg +3 -0
- package/src/assets/icons/icon-data-kelistrikan.svg +19 -0
- package/src/assets/icons/icon-data-sentral.svg +11 -0
- package/src/assets/icons/icon-database.svg +5 -0
- package/src/assets/icons/icon-desktop.svg +3 -0
- package/src/assets/icons/icon-download.svg +13 -0
- package/src/assets/icons/icon-energi-primer.svg +12 -0
- package/src/assets/icons/icon-faba-apk2.svg +11 -0
- package/src/assets/icons/icon-faba.svg +11 -0
- package/src/assets/icons/icon-factory.svg +14 -0
- package/src/assets/icons/icon-globe-doc.svg +19 -0
- package/src/assets/icons/icon-ikk.svg +10 -0
- package/src/assets/icons/icon-kbb.svg +13 -0
- package/src/assets/icons/icon-kos.svg +16 -0
- package/src/assets/icons/icon-kpi-bod.svg +15 -0
- package/src/assets/icons/icon-kss.svg +14 -0
- package/src/assets/icons/icon-map.svg +12 -0
- package/src/assets/icons/icon-monitoring-harian.svg +13 -0
- package/src/assets/icons/icon-notification.svg +4 -0
- package/src/assets/icons/icon-overview.svg +17 -0
- package/src/assets/icons/icon-pltu.svg +13 -0
- package/src/assets/icons/icon-sebaran-sentral.svg +12 -0
- package/src/assets/icons/icon-select-data-kelistrikan.svg +19 -0
- package/src/assets/icons/icon-select-data-sentral.svg +11 -0
- package/src/assets/icons/icon-select-energi-primer.svg +12 -0
- package/src/assets/icons/icon-select-faba-apk2.svg +11 -0
- package/src/assets/icons/icon-select-ikk.svg +10 -0
- package/src/assets/icons/icon-select-kbb.svg +13 -0
- package/src/assets/icons/icon-select-kos.svg +16 -0
- package/src/assets/icons/icon-select-kpi-bod.svg +15 -0
- package/src/assets/icons/icon-select-kss.svg +14 -0
- package/src/assets/icons/icon-select-monitoring-harian.svg +13 -0
- package/src/assets/icons/icon-select-overview.svg +17 -0
- package/src/assets/icons/icon-select-sebaran-sentral.svg +12 -0
- package/src/assets/icons/icon-sentral-white.svg +13 -0
- package/src/assets/icons/icon-shipping.svg +5 -0
- package/src/assets/icons/icon-sort.svg +5 -0
- package/src/assets/icons/icon-tree-box.svg +14 -0
- package/src/assets/icons/icon-warehouse.svg +12 -0
- package/src/assets/icons/pin-green.svg +3 -0
- package/src/assets/icons/pin-orange.svg +3 -0
- package/src/assets/icons/pin-purple.svg +3 -0
- package/src/assets/icons/ship.svg +3 -0
- package/src/assets/icons/shipment/icon-antri.svg +15 -0
- package/src/assets/icons/shipment/icon-bongkar.svg +4 -0
- package/src/assets/icons/shipment/icon-invoice.svg +6 -0
- package/src/assets/icons/shipment/icon-loading.svg +8 -0
- package/src/assets/icons/shipment/icon-pembayaran.svg +13 -0
- package/src/assets/icons/shipment/icon-pengiriman.svg +4 -0
- package/src/assets/icons/shipment/icon-sailing.svg +4 -0
- package/src/assets/icons/shipment/icon-shipment-completed.svg +6 -0
- package/src/assets/icons/shipment/icon-shipment-in-progress.svg +6 -0
- package/src/assets/icons/shipment/icon-shipment-over-sla.svg +6 -0
- package/src/assets/icons/shipment/icon-spt.svg +4 -0
- package/src/assets/icons/shipment/icon-total-shipment.svg +4 -0
- package/src/assets/icons/upload_doc_icon.svg +42 -0
- package/src/assets/icons/upload_icon_blue.svg +14 -0
- package/src/assets/login-bg-day-min.jpg +0 -0
- package/src/assets/login-bg-night-min.jpg +0 -0
- package/src/assets/login-bg.jpg +0 -0
- package/src/assets/login-day.png +0 -0
- package/src/assets/login-night.png +0 -0
- package/src/assets/lucide-circle-plus-blue.svg +1 -0
- package/src/assets/pdf-logo.svg +11 -0
- package/src/assets/pemasok-card-bg.svg +6 -0
- package/src/assets/success_animation.gif +0 -0
- package/src/assets/success_animation.mp4 +0 -0
- package/src/assets/success_animation.webm +0 -0
- package/src/components/button/BtnAddOutline.vue +14 -0
- package/src/components/button/BtnCircle.vue +10 -0
- package/src/components/button/BtnOutline.vue +15 -0
- package/src/components/button/BtnPrimary.vue +25 -0
- package/src/components/button/BtnSecondary.vue +26 -0
- package/src/components/detail/AccountDetailTimeline.vue +144 -0
- package/src/components/detail/ApprovalInfo.vue +288 -0
- package/src/components/detail/DCI2.vue +164 -0
- package/src/components/detail/DetailContentHeader.vue +83 -0
- package/src/components/detail/DetailContentItem.vue +186 -0
- package/src/components/detail/DetailContentItems.vue +388 -0
- package/src/components/detail/DetailContentLoading.vue +12 -0
- package/src/components/detail/DetailContentTablet.vue +10 -0
- package/src/components/detail/DetailSheet.vue +294 -0
- package/src/components/detail/DetailTimeline.vue +191 -0
- package/src/components/detail/DocApprovalDialog.vue +29 -0
- package/src/components/detail/DocViewerContent.vue +991 -0
- package/src/components/dialog/ConfirmDialog.vue +96 -0
- package/src/components/dialog/DialogBase.vue +53 -0
- package/src/components/dialog/DialogSelect.vue +212 -0
- package/src/components/dialog/ErrorDialog.vue +63 -0
- package/src/components/dialog/FormDialog.vue +141 -0
- package/src/components/dialog/FormInputerDialog.vue +91 -0
- package/src/components/dialog/InfoDialog.vue +74 -0
- package/src/components/dialog/SuccessDialog.vue +51 -0
- package/src/components/examples/TestSchemaExample.vue +288 -0
- package/src/components/forms/auth/LoginForm.vue +806 -0
- package/src/components/forms/auth/PwdScore.vue +68 -0
- package/src/components/helper/ApiTester.vue +153 -0
- package/src/components/helper/ChangePwd.vue +150 -0
- package/src/components/helper/CheckboxElement.vue +43 -0
- package/src/components/helper/ConfigSwitcher.vue +54 -0
- package/src/components/helper/Copyright.vue +10 -0
- package/src/components/helper/ErrorScreen.vue +40 -0
- package/src/components/helper/LucideIcon.vue +27 -0
- package/src/components/helper/PdfViewer.vue +103 -0
- package/src/components/helper/PinInputer.vue +205 -0
- package/src/components/helper/PrivacyPolicy.vue +122 -0
- package/src/components/layout/PageActivityHeader.vue +48 -0
- package/src/components/layout/PageHeader.vue +70 -0
- package/src/components/loadings/LoadingDialog.vue +29 -0
- package/src/components/loadings/LoadingDialogSpin.vue +25 -0
- package/src/components/loadings/LoadingIndicator.vue +38 -0
- package/src/components/loadings/LoadingScreen.vue +23 -0
- package/src/components/notif/Notif.vue +103 -0
- package/src/components/notif/NotifItem.vue +41 -0
- package/src/components/pages/Header.vue +431 -0
- package/src/components/pages/Leftbar.vue +417 -0
- package/src/components/pages/PageActivity.vue +108 -0
- package/src/components/pages/PageActivityContent.vue +597 -0
- package/src/components/pages/PageContentTable.vue +589 -0
- package/src/components/pages/PageTab.vue +84 -0
- package/src/components/selector/BaseSelector.vue +1136 -0
- package/src/components/selector/ConfigDataSelector.vue +136 -0
- package/src/components/settings/SettingsItem.vue +38 -0
- package/src/components/tab/TabView.vue +11 -0
- package/src/components/tab/TabViewItem.vue +18 -0
- package/src/components/tab/TabViewItemBar.vue +9 -0
- package/src/components/tables/CellHover.vue +65 -0
- package/src/components/tables/DashboardDataTable.vue +707 -0
- package/src/components/tables/DataStatusTag.vue +52 -0
- package/src/components/tables/DataTable.vue +156 -0
- package/src/components/tables/DataTableAccordion.vue +249 -0
- package/src/components/tables/DataTableActionRow.vue +64 -0
- package/src/components/tables/DataTableCell.vue +272 -0
- package/src/components/tables/DataTableHeader.vue +60 -0
- package/src/components/tables/DataTableRow.vue +213 -0
- package/src/components/tables/ExpandedTable.vue +259 -0
- package/src/components/tables/PageTable.vue +73 -0
- package/src/components/tables/Pagination.vue +98 -0
- package/src/components/tables/dropdown/BaseDropdownTable.vue +140 -0
- package/src/components/tables/dropdown/DropdownTableActivity.vue +33 -0
- package/src/components/tables/dropdown/DropdownTableAsset.vue +30 -0
- package/src/components/tables/dropdown/DropdownTableConfig.vue +30 -0
- package/src/components/tables/dropdown/DropdownTableDataKonektor.vue +31 -0
- package/src/components/tables/dropdown/DropdownTableDataLabel.vue +30 -0
- package/src/components/tables/dropdown/DropdownTableDataSchema.vue +31 -0
- package/src/components/tables/dropdown/DropdownTableFabaPemanfaat.vue +30 -0
- package/src/components/tables/dropdown/DropdownTableGroup.vue +36 -0
- package/src/components/tables/dropdown/DropdownTableHalaman.vue +33 -0
- package/src/components/tables/dropdown/DropdownTableLevel.vue +66 -0
- package/src/components/tables/dropdown/DropdownTableOrganization.vue +47 -0
- package/src/components/tables/dropdown/DropdownTablePengelola.vue +28 -0
- package/src/components/tables/dropdown/DropdownTableQueryLayer.vue +29 -0
- package/src/components/tables/dropdown/DropdownTableSentral.vue +33 -0
- package/src/components/tables/dropdown/DropdownTableWarehouse.vue +30 -0
- package/src/components/tables/dropdown/TableDropdown.vue +52 -0
- package/src/components/ui/accordion/Accordion.vue +19 -0
- package/src/components/ui/accordion/AccordionContent.vue +24 -0
- package/src/components/ui/accordion/AccordionItem.vue +24 -0
- package/src/components/ui/accordion/AccordionTrigger.vue +42 -0
- package/src/components/ui/accordion/index.ts +4 -0
- package/src/components/ui/alert-dialog/AlertDialog.vue +14 -0
- package/src/components/ui/alert-dialog/AlertDialogAction.vue +20 -0
- package/src/components/ui/alert-dialog/AlertDialogCancel.vue +20 -0
- package/src/components/ui/alert-dialog/AlertDialogContent.vue +42 -0
- package/src/components/ui/alert-dialog/AlertDialogDescription.vue +25 -0
- package/src/components/ui/alert-dialog/AlertDialogFooter.vue +21 -0
- package/src/components/ui/alert-dialog/AlertDialogHeader.vue +16 -0
- package/src/components/ui/alert-dialog/AlertDialogTitle.vue +22 -0
- package/src/components/ui/alert-dialog/AlertDialogTrigger.vue +11 -0
- package/src/components/ui/alert-dialog/index.ts +9 -0
- package/src/components/ui/avatar/Avatar.vue +24 -0
- package/src/components/ui/avatar/AvatarFallback.vue +11 -0
- package/src/components/ui/avatar/AvatarImage.vue +9 -0
- package/src/components/ui/avatar/UsersAvatar.vue +28 -0
- package/src/components/ui/avatar/index.ts +24 -0
- package/src/components/ui/button/Button.vue +27 -0
- package/src/components/ui/button/index.ts +34 -0
- package/src/components/ui/calendar/Calendar.vue +325 -0
- package/src/components/ui/calendar/index.ts +22 -0
- package/src/components/ui/checkbox/Checkbox.vue +33 -0
- package/src/components/ui/checkbox/index.ts +1 -0
- package/src/components/ui/command/Command.vue +30 -0
- package/src/components/ui/command/CommandDialog.vue +21 -0
- package/src/components/ui/command/CommandEmpty.vue +20 -0
- package/src/components/ui/command/CommandGroup.vue +29 -0
- package/src/components/ui/command/CommandInput.vue +33 -0
- package/src/components/ui/command/CommandItem.vue +26 -0
- package/src/components/ui/command/CommandList.vue +27 -0
- package/src/components/ui/command/CommandSeparator.vue +23 -0
- package/src/components/ui/command/CommandShortcut.vue +14 -0
- package/src/components/ui/command/index.ts +9 -0
- package/src/components/ui/context-menu/ContextMenu.vue +15 -0
- package/src/components/ui/context-menu/ContextMenuCheckboxItem.vue +40 -0
- package/src/components/ui/context-menu/ContextMenuContent.vue +36 -0
- package/src/components/ui/context-menu/ContextMenuGroup.vue +11 -0
- package/src/components/ui/context-menu/ContextMenuItem.vue +34 -0
- package/src/components/ui/context-menu/ContextMenuLabel.vue +25 -0
- package/src/components/ui/context-menu/ContextMenuPortal.vue +11 -0
- package/src/components/ui/context-menu/ContextMenuRadioGroup.vue +19 -0
- package/src/components/ui/context-menu/ContextMenuRadioItem.vue +40 -0
- package/src/components/ui/context-menu/ContextMenuSeparator.vue +20 -0
- package/src/components/ui/context-menu/ContextMenuShortcut.vue +14 -0
- package/src/components/ui/context-menu/ContextMenuSub.vue +19 -0
- package/src/components/ui/context-menu/ContextMenuSubContent.vue +35 -0
- package/src/components/ui/context-menu/ContextMenuSubTrigger.vue +34 -0
- package/src/components/ui/context-menu/ContextMenuTrigger.vue +13 -0
- package/src/components/ui/context-menu/index.ts +14 -0
- package/src/components/ui/datetime/DatetimeRangeComponent.vue +52 -0
- package/src/components/ui/dialog/Dialog.vue +14 -0
- package/src/components/ui/dialog/DialogClose.vue +11 -0
- package/src/components/ui/dialog/DialogContent.vue +53 -0
- package/src/components/ui/dialog/DialogDescription.vue +24 -0
- package/src/components/ui/dialog/DialogFooter.vue +19 -0
- package/src/components/ui/dialog/DialogHeader.vue +16 -0
- package/src/components/ui/dialog/DialogScrollContent.vue +59 -0
- package/src/components/ui/dialog/DialogTitle.vue +29 -0
- package/src/components/ui/dialog/DialogTrigger.vue +11 -0
- package/src/components/ui/dialog/index.ts +9 -0
- package/src/components/ui/dropdown-menu/DropdownMenu.vue +14 -0
- package/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +40 -0
- package/src/components/ui/dropdown-menu/DropdownMenuContent.vue +38 -0
- package/src/components/ui/dropdown-menu/DropdownMenuGroup.vue +11 -0
- package/src/components/ui/dropdown-menu/DropdownMenuItem.vue +28 -0
- package/src/components/ui/dropdown-menu/DropdownMenuLabel.vue +24 -0
- package/src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +19 -0
- package/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +41 -0
- package/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue +22 -0
- package/src/components/ui/dropdown-menu/DropdownMenuShortcut.vue +14 -0
- package/src/components/ui/dropdown-menu/DropdownMenuSub.vue +19 -0
- package/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue +30 -0
- package/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +33 -0
- package/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue +13 -0
- package/src/components/ui/dropdown-menu/index.ts +16 -0
- package/src/components/ui/form/FormControl.vue +16 -0
- package/src/components/ui/form/FormDescription.vue +20 -0
- package/src/components/ui/form/FormItem.vue +25 -0
- package/src/components/ui/form/FormLabel.vue +23 -0
- package/src/components/ui/form/FormMessage.vue +16 -0
- package/src/components/ui/form/index.ts +6 -0
- package/src/components/ui/form/useFormField.ts +30 -0
- package/src/components/ui/hover-card/HoverCard.vue +14 -0
- package/src/components/ui/hover-card/HoverCardContent.vue +41 -0
- package/src/components/ui/hover-card/HoverCardTrigger.vue +11 -0
- package/src/components/ui/hover-card/index.ts +3 -0
- package/src/components/ui/input/Input.vue +24 -0
- package/src/components/ui/input/index.ts +1 -0
- package/src/components/ui/label/Label.vue +27 -0
- package/src/components/ui/label/index.ts +1 -0
- package/src/components/ui/pagination/PaginationEllipsis.vue +22 -0
- package/src/components/ui/pagination/PaginationFirst.vue +29 -0
- package/src/components/ui/pagination/PaginationLast.vue +29 -0
- package/src/components/ui/pagination/PaginationNext.vue +29 -0
- package/src/components/ui/pagination/PaginationPrev.vue +29 -0
- package/src/components/ui/pagination/index.ts +10 -0
- package/src/components/ui/pin-input/PinInput.vue +23 -0
- package/src/components/ui/pin-input/PinInputGroup.vue +18 -0
- package/src/components/ui/pin-input/PinInputInput.vue +18 -0
- package/src/components/ui/pin-input/PinInputSeparator.vue +15 -0
- package/src/components/ui/pin-input/index.ts +4 -0
- package/src/components/ui/popover/Popover.vue +15 -0
- package/src/components/ui/popover/PopoverContent.vue +48 -0
- package/src/components/ui/popover/PopoverTrigger.vue +11 -0
- package/src/components/ui/popover/index.ts +4 -0
- package/src/components/ui/preview/PreviewPdf.vue +118 -0
- package/src/components/ui/progress/ProgressCircle.vue +27 -0
- package/src/components/ui/progress/SemiCircularProgressBar.vue +83 -0
- package/src/components/ui/progress/TotalCalories.vue +31 -0
- package/src/components/ui/radio-group/RadioGroup.vue +25 -0
- package/src/components/ui/radio-group/RadioGroupItem.vue +37 -0
- package/src/components/ui/radio-group/index.ts +2 -0
- package/src/components/ui/scroll-area/ScrollArea.vue +29 -0
- package/src/components/ui/scroll-area/ScrollBar.vue +30 -0
- package/src/components/ui/scroll-area/index.ts +2 -0
- package/src/components/ui/select/Select.vue +15 -0
- package/src/components/ui/select/SelectContent.vue +52 -0
- package/src/components/ui/select/SelectGroup.vue +19 -0
- package/src/components/ui/select/SelectInline.vue +84 -0
- package/src/components/ui/select/SelectItem.vue +44 -0
- package/src/components/ui/select/SelectItemText.vue +11 -0
- package/src/components/ui/select/SelectLabel.vue +13 -0
- package/src/components/ui/select/SelectScrollDownButton.vue +24 -0
- package/src/components/ui/select/SelectScrollUpButton.vue +24 -0
- package/src/components/ui/select/SelectSeparator.vue +17 -0
- package/src/components/ui/select/SelectTrigger.vue +31 -0
- package/src/components/ui/select/SelectTriggerCustom.vue +23 -0
- package/src/components/ui/select/SelectValue.vue +11 -0
- package/src/components/ui/select/index.ts +12 -0
- package/src/components/ui/separator/Separator.vue +20 -0
- package/src/components/ui/separator/index.ts +1 -0
- package/src/components/ui/sheet/Sheet.vue +14 -0
- package/src/components/ui/sheet/SheetClose.vue +11 -0
- package/src/components/ui/sheet/SheetContent.vue +48 -0
- package/src/components/ui/sheet/SheetDescription.vue +22 -0
- package/src/components/ui/sheet/SheetFooter.vue +19 -0
- package/src/components/ui/sheet/SheetHeader.vue +16 -0
- package/src/components/ui/sheet/SheetTitle.vue +22 -0
- package/src/components/ui/sheet/SheetTrigger.vue +11 -0
- package/src/components/ui/sheet/index.ts +31 -0
- package/src/components/ui/skeleton/Skeleton.vue +28 -0
- package/src/components/ui/skeleton/index.ts +1 -0
- package/src/components/ui/sonner/Sonner.vue +22 -0
- package/src/components/ui/sonner/index.ts +1 -0
- package/src/components/ui/star/StarRating.vue +19 -0
- package/src/components/ui/switch/Switch.vue +37 -0
- package/src/components/ui/switch/index.ts +1 -0
- package/src/components/ui/table/Table.vue +16 -0
- package/src/components/ui/table/TableBody.vue +14 -0
- package/src/components/ui/table/TableCaption.vue +14 -0
- package/src/components/ui/table/TableCell.vue +21 -0
- package/src/components/ui/table/TableEmpty.vue +37 -0
- package/src/components/ui/table/TableFooter.vue +14 -0
- package/src/components/ui/table/TableHead.vue +14 -0
- package/src/components/ui/table/TableHeader.vue +14 -0
- package/src/components/ui/table/TableRow.vue +14 -0
- package/src/components/ui/table/index.ts +8 -0
- package/src/components/ui/tabs/Tabs.vue +15 -0
- package/src/components/ui/tabs/TabsContent.vue +22 -0
- package/src/components/ui/tabs/TabsList.vue +25 -0
- package/src/components/ui/tabs/TabsTrigger.vue +27 -0
- package/src/components/ui/tabs/index.ts +4 -0
- package/src/components/ui/tags-input/TagsInput.vue +22 -0
- package/src/components/ui/tags-input/TagsInputInput.vue +19 -0
- package/src/components/ui/tags-input/TagsInputItem.vue +22 -0
- package/src/components/ui/tags-input/TagsInputItemDelete.vue +24 -0
- package/src/components/ui/tags-input/TagsInputItemText.vue +19 -0
- package/src/components/ui/tags-input/index.ts +5 -0
- package/src/components/ui/textarea/Textarea.vue +24 -0
- package/src/components/ui/textarea/index.ts +1 -0
- package/src/components/ui/tooltip/Tooltip.vue +14 -0
- package/src/components/ui/tooltip/TooltipContent.vue +31 -0
- package/src/components/ui/tooltip/TooltipProvider.vue +11 -0
- package/src/components/ui/tooltip/TooltipTrigger.vue +11 -0
- package/src/components/ui/tooltip/index.ts +4 -0
- package/src/composables/useAppConfig.ts +332 -0
- package/src/composables/useDarkMode.ts +71 -0
- package/src/config/app.config.ts +318 -0
- package/src/config/examples/ecommerce.config.ts +132 -0
- package/src/config/examples/generic.config.ts +132 -0
- package/src/config/menu.config.ts +149 -0
- package/src/config/my-app.config.ts +134 -0
- package/src/config/test-config.ts +32 -0
- package/src/config/theme.config.ts +250 -0
- package/src/docs/index.ts +21 -0
- package/src/docs.scss +403 -0
- package/src/index.d.ts +5 -0
- package/src/index.ts +20 -0
- package/src/layouts/AuthLayout.vue +68 -0
- package/src/layouts/DefaultLayout.vue +119 -0
- package/src/layouts/DocsLayout.vue +681 -0
- package/src/layouts/FormGlobal.vue +50 -0
- package/src/layouts/GlobalDialog.vue +122 -0
- package/src/layouts/RakorConfirmDialog.vue +95 -0
- package/src/layouts/SettingsLayout.vue +115 -0
- package/src/lib/constants.ts +2 -0
- package/src/lib/detail.utils.ts +213 -0
- package/src/lib/form.utils.ts +1009 -0
- package/src/lib/page.flow.utils.ts +81 -0
- package/src/lib/page.utils.ts +865 -0
- package/src/lib/performance.utils.ts +302 -0
- package/src/lib/tablerow.utils.ts +51 -0
- package/src/lib/utils.ts +643 -0
- package/src/main.scss +717 -0
- package/src/main.ts +74 -0
- package/src/menu.ts +78 -0
- package/src/nestedlist_color.scss +161 -0
- package/src/router/index.ts +92 -0
- package/src/stores/auth.ts +117 -0
- package/src/stores/counter.ts +12 -0
- package/src/stores/dialog.ts +168 -0
- package/src/stores/form.ts +103 -0
- package/src/stores/tabs.ts +52 -0
- package/src/tw.scss +419 -0
- package/src/types/form.types.ts +348 -0
- package/src/types/types.ts +7 -0
- package/src/utils/config.utils.ts +149 -0
- package/src/views/NotFound.vue +30 -0
- package/src/views/PageActivity.vue +15 -0
- package/src/views/auth/LoginView.vue +7 -0
- package/src/views/auth/OauthCallback.vue +101 -0
- package/src/views/dashboard/index.vue +16 -0
- package/src/views/settings/AccountSettingsView.vue +70 -0
- package/src/views/settings/AuditLogsSettingsView.vue +116 -0
- package/src/views/settings/DeviceSettingsView.vue +70 -0
- package/src/views/settings/MainSettingsView.vue +12 -0
- package/src/views/settings/ProfileSettingsView.vue +104 -0
- package/src/vueform/config/informasi-gudang.ts +47 -0
- package/src/vueform/config/test-schema.ts +8 -0
- package/src/vueform/config/types.ts +768 -0
- package/src/vueform/customization/classes.js +46 -0
- package/src/vueform/customization/tailwind.classes.js +2117 -0
- package/src/vueform/elements/ConfigDataSelectorElement.vue +50 -0
- package/src/vueform/elements/DateSelectorElement.vue +323 -0
- package/src/vueform/elements/SelectorElement.vue +153 -0
- package/src/vueform/schemas/date-selector-test.ts +103 -0
- package/src/vueform/schemas/informasi-gudang.ts +160 -0
- package/src/vueform/schemas/test-schema.ts +483 -0
- package/src/vueform.config.js +77 -0
- package/src/vueform.validator.ts +77 -0
|
@@ -0,0 +1,1009 @@
|
|
|
1
|
+
import api from "@/api/api";
|
|
2
|
+
import { clearFormSchema, fillFormSchema, intlFormatedToNumber } from "./utils";
|
|
3
|
+
import type { FormReactiveSchema, FormSchemaHooks } from "@/types/form.types";
|
|
4
|
+
import { useFormSheet } from "@/stores/form";
|
|
5
|
+
import { useConfirmDialog, useErrorDialog, useLoadingDialog, useSuccessDialog } from "@/stores/dialog";
|
|
6
|
+
import { InternalServerError } from "./constants";
|
|
7
|
+
import { toast } from "vue-sonner";
|
|
8
|
+
import { nextTick } from "vue";
|
|
9
|
+
|
|
10
|
+
export interface SubmitFormDataOptions {
|
|
11
|
+
endpoint: string;
|
|
12
|
+
form$: any;
|
|
13
|
+
formSchema: FormReactiveSchema | any;
|
|
14
|
+
formHooks?: FormSchemaHooks;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface BaseFormOptions {
|
|
18
|
+
title: string;
|
|
19
|
+
endpoint: string;
|
|
20
|
+
formSchema: FormReactiveSchema;
|
|
21
|
+
formHooks?: FormSchemaHooks;
|
|
22
|
+
formDialogClass?: string;
|
|
23
|
+
pageConfig?: any;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface AddFormOptions extends BaseFormOptions {}
|
|
27
|
+
|
|
28
|
+
export interface EditFormOptions extends BaseFormOptions {
|
|
29
|
+
item: any;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface DeleteRestoreFormOptions extends BaseFormOptions {
|
|
33
|
+
index: number;
|
|
34
|
+
allData: any[];
|
|
35
|
+
item: any;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// ==========================================
|
|
39
|
+
// CORE INTERFACES FOR GENERIC ADD DATA LIB
|
|
40
|
+
// ==========================================
|
|
41
|
+
|
|
42
|
+
export interface FormStateRefs {
|
|
43
|
+
loadingForm: any;
|
|
44
|
+
formType: any;
|
|
45
|
+
formOpen: any;
|
|
46
|
+
formError: any;
|
|
47
|
+
formEditEl?: any;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface FormHooksConfig {
|
|
51
|
+
onBeforeMount?: (formSchema: any, formType: "add" | "edit", data?: any) => Promise<boolean>;
|
|
52
|
+
onMounted?: (formEl: any, formSchema: any, formType: "add" | "edit", data?: any) => Promise<boolean>;
|
|
53
|
+
onChange?: (after: any, before: any, formEl: any, formSchema: any, formType: "add" | "edit") => void;
|
|
54
|
+
onBeforeSubmit?: (form$: any) => Promise<boolean>;
|
|
55
|
+
onAfterSubmit?: (response: any) => void;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface OrganizationAutoFillConfig {
|
|
59
|
+
enabled: boolean;
|
|
60
|
+
fieldName?: string; // default: 'organizationId'
|
|
61
|
+
accessLevelField?: string; // default: 'accessLevel'
|
|
62
|
+
endpoint?: string; // default: '/organization/my'
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface EndpointSpecificConfig {
|
|
66
|
+
[endpoint: string]: {
|
|
67
|
+
onMount?: (formEditEl: any) => void;
|
|
68
|
+
customFields?: Record<string, any>;
|
|
69
|
+
validation?: (formData: any) => Promise<boolean>;
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Base interface untuk semua add data options
|
|
74
|
+
export interface AddDataBaseOptions {
|
|
75
|
+
title: string;
|
|
76
|
+
endpoint: string;
|
|
77
|
+
formSchema: FormReactiveSchema | any;
|
|
78
|
+
formHooks?: FormSchemaHooks | FormHooksConfig;
|
|
79
|
+
pageConfig?: any;
|
|
80
|
+
|
|
81
|
+
// Callbacks
|
|
82
|
+
onSuccess?: () => void;
|
|
83
|
+
onError?: (error: string) => void;
|
|
84
|
+
|
|
85
|
+
// Auto-fill configuration
|
|
86
|
+
organizationAutoFill?: OrganizationAutoFillConfig;
|
|
87
|
+
|
|
88
|
+
// Endpoint specific configurations
|
|
89
|
+
endpointConfig?: EndpointSpecificConfig;
|
|
90
|
+
|
|
91
|
+
// Flow specific (untuk cases seperti PageActivityFlow)
|
|
92
|
+
previousData?: any;
|
|
93
|
+
previousDataField?: string;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Interface untuk FormSheet mode (seperti PageActivity.vue)
|
|
97
|
+
export interface AddDataSheetOptions extends AddDataBaseOptions {
|
|
98
|
+
mode: "sheet";
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Interface untuk Inline mode (seperti PageActivityNew.vue)
|
|
102
|
+
export interface AddDataInlineOptions extends AddDataBaseOptions {
|
|
103
|
+
mode: "inline";
|
|
104
|
+
formState: FormStateRefs;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Interface untuk Basic mode (seperti Master.vue)
|
|
108
|
+
export interface AddDataBasicOptions extends AddDataBaseOptions {
|
|
109
|
+
mode: "basic";
|
|
110
|
+
formState: FormStateRefs;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Interface untuk Flow mode (seperti PageActivityFlow.vue)
|
|
114
|
+
export interface AddDataFlowOptions extends AddDataBaseOptions {
|
|
115
|
+
mode: "flow";
|
|
116
|
+
formState: FormStateRefs;
|
|
117
|
+
itemData: any; // Data item yang dipilih dari table
|
|
118
|
+
previousDataField: string; // Required untuk flow mode
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Union type untuk semua options
|
|
122
|
+
export type AddDataOptions = AddDataSheetOptions | AddDataInlineOptions | AddDataBasicOptions | AddDataFlowOptions;
|
|
123
|
+
|
|
124
|
+
// Legacy interface untuk backward compatibility
|
|
125
|
+
export interface AddDataGenericOptions extends AddDataBaseOptions {
|
|
126
|
+
// Form state refs untuk inline mode
|
|
127
|
+
formState?: FormStateRefs;
|
|
128
|
+
|
|
129
|
+
// Options
|
|
130
|
+
mode?: "sheet" | "inline" | "basic" | "flow";
|
|
131
|
+
endpointSpecificHandlers?: {
|
|
132
|
+
[key: string]: (formEditEl: any) => void;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
// Auto-fill organization (legacy)
|
|
136
|
+
autoFillOrganization?: boolean;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Dialog
|
|
141
|
+
*
|
|
142
|
+
*/
|
|
143
|
+
const formSheet = useFormSheet();
|
|
144
|
+
const errorDialog = useErrorDialog();
|
|
145
|
+
const successDialog = useSuccessDialog();
|
|
146
|
+
const loadingDialog = useLoadingDialog();
|
|
147
|
+
const confirmDialog = useConfirmDialog();
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Submit form data to API
|
|
151
|
+
* based on vue form schema
|
|
152
|
+
*
|
|
153
|
+
*/
|
|
154
|
+
export async function submitFormData({ endpoint, form$, formSchema, formHooks }: SubmitFormDataOptions) {
|
|
155
|
+
/**
|
|
156
|
+
* Run schema hook if
|
|
157
|
+
* schema has onBeforeSubmit hook
|
|
158
|
+
*
|
|
159
|
+
*/
|
|
160
|
+
if (formHooks && formHooks.onBeforeSubmit) {
|
|
161
|
+
await nextTick();
|
|
162
|
+
if (!(await formHooks.onBeforeSubmit(form$))) return;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const formData = { ...form$.data };
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Transfrom data
|
|
169
|
+
*
|
|
170
|
+
*/
|
|
171
|
+
for (const [k, v] of Object.entries(formData)) {
|
|
172
|
+
/**
|
|
173
|
+
* Update media
|
|
174
|
+
*
|
|
175
|
+
*/
|
|
176
|
+
if (v && (v as any).mimetype) formData[k] = (v as any).id;
|
|
177
|
+
|
|
178
|
+
if (formSchema.value[k]) {
|
|
179
|
+
const schemaItem = formSchema.value[k];
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Format input on fe is formated internaional number
|
|
183
|
+
* and sent to be as a number
|
|
184
|
+
*
|
|
185
|
+
*/
|
|
186
|
+
if (schemaItem.mask?.thousandsSeparator === ",") {
|
|
187
|
+
formData[k] = v ? intlFormatedToNumber(String(v)) : null;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Format number without sparator (input int)
|
|
192
|
+
*
|
|
193
|
+
*/
|
|
194
|
+
if (schemaItem.mask?.thousandsSeparator === "") {
|
|
195
|
+
formData[k] = v ? Number(String(v)) : null;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Format dialog selector,
|
|
200
|
+
* displayed as object selected item,
|
|
201
|
+
* and sent to be as an id string
|
|
202
|
+
*/
|
|
203
|
+
if (['dasi_v2_organization', "dasi_v2_selector_single", "dasi_v2_selector_single_v2"].includes(schemaItem.type)) {
|
|
204
|
+
// Accept object, id string, or single-item array of either
|
|
205
|
+
const rawVal: any = v;
|
|
206
|
+
let val: any = Array.isArray(rawVal) ? rawVal[0] : rawVal;
|
|
207
|
+
|
|
208
|
+
// Fallback: if user didn't touch the field, take id/object from schema default (object or [object])
|
|
209
|
+
if ((!val || (!val.id && typeof val !== 'string')) && schemaItem?.default) {
|
|
210
|
+
const def: any = Array.isArray(schemaItem.default) ? schemaItem.default[0] : schemaItem.default;
|
|
211
|
+
if (def) val = def;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Resolve id
|
|
215
|
+
const resolvedId = typeof val === 'string' ? val : val?.id || null;
|
|
216
|
+
|
|
217
|
+
if (schemaItem.type === "dasi_v2_selector_single_v2" && schemaItem.subItem) {
|
|
218
|
+
formData[k] = {
|
|
219
|
+
id: resolvedId,
|
|
220
|
+
subItemSelectedId: (val as any)?.subItemSelected?.[schemaItem.subItem.submitField || "id"]
|
|
221
|
+
};
|
|
222
|
+
} else {
|
|
223
|
+
formData[k] = resolvedId;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// no-op
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
form$.cancelToken = form$?.$vueform?.services?.axios?.CancelToken?.source();
|
|
232
|
+
return await api.post(endpoint, formData, {
|
|
233
|
+
cancelToken: form$.cancelToken.token
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export async function addFormData(options: AddFormOptions) {
|
|
238
|
+
/**
|
|
239
|
+
* Clear schema
|
|
240
|
+
* and display loading
|
|
241
|
+
*
|
|
242
|
+
*/
|
|
243
|
+
clearFormSchema(Object.entries(options.formSchema.value));
|
|
244
|
+
loadingDialog.open();
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Add on before mount and pass edit data,
|
|
248
|
+
* this might change the schema
|
|
249
|
+
*
|
|
250
|
+
*/
|
|
251
|
+
if (options.formHooks?.onBeforeMount) {
|
|
252
|
+
try {
|
|
253
|
+
if (!(await options.formHooks.onBeforeMount(options.formSchema, "add"))) {
|
|
254
|
+
loadingDialog.close();
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
} catch (err: any) {
|
|
258
|
+
loadingDialog.close();
|
|
259
|
+
errorDialog.open({
|
|
260
|
+
title: "Tamabah Data Gagal",
|
|
261
|
+
description: err.message || InternalServerError
|
|
262
|
+
});
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Auto fill organization from
|
|
269
|
+
* auth session
|
|
270
|
+
*
|
|
271
|
+
*/
|
|
272
|
+
for (const [_, item] of Object.entries(options.formSchema.value)) {
|
|
273
|
+
if (item.autofill) {
|
|
274
|
+
try {
|
|
275
|
+
const r = await api.get("/organization/my");
|
|
276
|
+
if (!item.accessLevel || (r.data.data.accessLevel && r.data.data.accessLevel.code === item.accessLevel)) {
|
|
277
|
+
item.default = [r.data.data];
|
|
278
|
+
}
|
|
279
|
+
} catch (err) {
|
|
280
|
+
toast.error("Get my organization failed!");
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Render form
|
|
287
|
+
* Hide loading data preparation
|
|
288
|
+
*
|
|
289
|
+
*/
|
|
290
|
+
loadingDialog.close();
|
|
291
|
+
return await formSheet.open({
|
|
292
|
+
title: options.title,
|
|
293
|
+
formSchema: options.formSchema,
|
|
294
|
+
loading: false,
|
|
295
|
+
className: options.formDialogClass,
|
|
296
|
+
onChange(after, before, el$) {
|
|
297
|
+
if (options.formHooks?.onChange) {
|
|
298
|
+
options.formHooks?.onChange(after, before, el$, options.formSchema, "add");
|
|
299
|
+
}
|
|
300
|
+
},
|
|
301
|
+
async onMounted(form$) {
|
|
302
|
+
if (options.formHooks?.onMounted) {
|
|
303
|
+
try {
|
|
304
|
+
if (!(await options.formHooks?.onMounted(form$, options.formSchema, "add"))) {
|
|
305
|
+
formSheet.close();
|
|
306
|
+
}
|
|
307
|
+
} catch (err: any) {
|
|
308
|
+
errorDialog
|
|
309
|
+
.open({
|
|
310
|
+
title: "Tamabah Data Gagal",
|
|
311
|
+
description: err.message || InternalServerError
|
|
312
|
+
})
|
|
313
|
+
.then(() => {
|
|
314
|
+
formSheet.close();
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
async onSubmit(form$) {
|
|
320
|
+
formSheet.saving = true;
|
|
321
|
+
try {
|
|
322
|
+
const b = await submitFormData({
|
|
323
|
+
form$,
|
|
324
|
+
endpoint: options.endpoint,
|
|
325
|
+
formSchema: options.formSchema,
|
|
326
|
+
formHooks: options.formHooks
|
|
327
|
+
});
|
|
328
|
+
if (!b) return;
|
|
329
|
+
successDialog.open().then(() => {
|
|
330
|
+
formSheet.close(true);
|
|
331
|
+
});
|
|
332
|
+
} catch (err: any) {
|
|
333
|
+
formSheet.formError = err?.response?.data?.[0]?.message || err.message || InternalServerError;
|
|
334
|
+
} finally {
|
|
335
|
+
formSheet.saving = false;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
export function fieldCapitalFirst(e: any) {
|
|
342
|
+
const val = e.target?.value ?? "";
|
|
343
|
+
if (val.length > 0) {
|
|
344
|
+
let capitalizedString = val[0].toUpperCase() + val.slice(1);
|
|
345
|
+
e.target.value = capitalizedString;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
export function fieldCapitalize(e: any) {
|
|
350
|
+
const val = e.target?.value ?? "";
|
|
351
|
+
if (val.length > 0) {
|
|
352
|
+
e.target.value = val.toUpperCase();
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// ==========================================
|
|
357
|
+
// CORE FUNCTIONS FOR GENERIC ADD DATA LIB
|
|
358
|
+
// ==========================================
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Helper function untuk auto-fill organization
|
|
362
|
+
*/
|
|
363
|
+
async function handleOrganizationAutoFill(formSchema: any, config: OrganizationAutoFillConfig): Promise<void> {
|
|
364
|
+
if (!config.enabled) return;
|
|
365
|
+
|
|
366
|
+
const fieldName = config.fieldName || "organizationId";
|
|
367
|
+
const accessLevelField = config.accessLevelField || "accessLevel";
|
|
368
|
+
const endpoint = config.endpoint || "/organization/my";
|
|
369
|
+
|
|
370
|
+
if (!formSchema.value[fieldName]?.autofill) return;
|
|
371
|
+
|
|
372
|
+
try {
|
|
373
|
+
const response = await api.get(endpoint);
|
|
374
|
+
const orgData = response.data.data;
|
|
375
|
+
|
|
376
|
+
if (!formSchema.value[fieldName][accessLevelField] || (orgData[accessLevelField] && formSchema.value[fieldName][accessLevelField] === orgData[accessLevelField].code)) {
|
|
377
|
+
formSchema.value[fieldName].default = [orgData];
|
|
378
|
+
}
|
|
379
|
+
} catch (err) {
|
|
380
|
+
toast.error("Get my organization failed!");
|
|
381
|
+
throw err;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Helper function untuk endpoint specific configuration
|
|
387
|
+
*/
|
|
388
|
+
function handleEndpointSpecificConfig(endpoint: string, formEditEl: any, config?: EndpointSpecificConfig): void {
|
|
389
|
+
if (!config || !config[endpoint] || !formEditEl) return;
|
|
390
|
+
|
|
391
|
+
const endpointConfig = config[endpoint];
|
|
392
|
+
|
|
393
|
+
if (endpointConfig.onMount) {
|
|
394
|
+
setTimeout(() => {
|
|
395
|
+
endpointConfig.onMount!(formEditEl.value);
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Helper function untuk setup previous data (flow mode)
|
|
402
|
+
*/
|
|
403
|
+
function setupPreviousData(formSchema: any, previousData: any, previousDataField?: string): void {
|
|
404
|
+
if (!previousData || !previousDataField) return;
|
|
405
|
+
|
|
406
|
+
if (formSchema.value[previousDataField]) {
|
|
407
|
+
formSchema.value[previousDataField].default = [previousData];
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Core function - FormSheet Mode (seperti PageActivity.vue)
|
|
413
|
+
*/
|
|
414
|
+
async function executeAddDataSheet(options: AddDataSheetOptions): Promise<boolean> {
|
|
415
|
+
const { title, endpoint, formSchema, formHooks, pageConfig, onSuccess } = options;
|
|
416
|
+
|
|
417
|
+
const savePath = pageConfig?.savePath || endpoint;
|
|
418
|
+
|
|
419
|
+
const success = await addFormData({
|
|
420
|
+
title,
|
|
421
|
+
endpoint: savePath,
|
|
422
|
+
formSchema,
|
|
423
|
+
formHooks
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
if (success && onSuccess) {
|
|
427
|
+
onSuccess();
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
return success || false;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* Core function - Basic Mode (seperti Master.vue)
|
|
435
|
+
*/
|
|
436
|
+
async function executeAddDataBasic(options: AddDataBasicOptions): Promise<boolean> {
|
|
437
|
+
const { formSchema, formState } = options;
|
|
438
|
+
|
|
439
|
+
// Simple clear schema (Master.vue pattern)
|
|
440
|
+
clearFormSchema(Object.entries(formSchema.value || formSchema));
|
|
441
|
+
|
|
442
|
+
formState.loadingForm.value = false;
|
|
443
|
+
formState.formType.value = "add";
|
|
444
|
+
formState.formOpen.value = true;
|
|
445
|
+
formState.formError.value = null;
|
|
446
|
+
|
|
447
|
+
return true;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Core function - Inline Mode (seperti PageActivityNew.vue)
|
|
452
|
+
*/
|
|
453
|
+
async function executeAddDataInline(options: AddDataInlineOptions): Promise<boolean> {
|
|
454
|
+
const { formSchema, formHooks, formState, organizationAutoFill, endpointConfig, endpoint, onError } = options;
|
|
455
|
+
|
|
456
|
+
// Clear schema dan setup form state
|
|
457
|
+
clearFormSchema(Object.entries(formSchema.value));
|
|
458
|
+
|
|
459
|
+
formState.loadingForm.value = true;
|
|
460
|
+
formState.formType.value = "add";
|
|
461
|
+
formState.formOpen.value = true;
|
|
462
|
+
formState.formError.value = null;
|
|
463
|
+
|
|
464
|
+
try {
|
|
465
|
+
// Call schema onMounted hook
|
|
466
|
+
if (formSchema.value.onMounted) {
|
|
467
|
+
if (!(await formSchema.value.onMounted("add", formSchema))) {
|
|
468
|
+
formState.formOpen.value = false;
|
|
469
|
+
return false;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// Call form hooks
|
|
474
|
+
if (formHooks?.onMounted) {
|
|
475
|
+
if (!(await formHooks.onMounted(formState.formEditEl?.value, formSchema, "add"))) {
|
|
476
|
+
formState.formOpen.value = false;
|
|
477
|
+
return false;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// Handle endpoint specific configuration
|
|
482
|
+
handleEndpointSpecificConfig(endpoint, formState.formEditEl, endpointConfig);
|
|
483
|
+
|
|
484
|
+
// Handle organization auto-fill
|
|
485
|
+
if (organizationAutoFill?.enabled) {
|
|
486
|
+
await handleOrganizationAutoFill(formSchema, organizationAutoFill);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
return true;
|
|
490
|
+
} catch (err: any) {
|
|
491
|
+
console.error("Failed to add form");
|
|
492
|
+
onError?.(err.message || InternalServerError);
|
|
493
|
+
formState.formOpen.value = false;
|
|
494
|
+
return false;
|
|
495
|
+
} finally {
|
|
496
|
+
formState.loadingForm.value = false;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Core function - Flow Mode (seperti PageActivityFlow.vue)
|
|
502
|
+
*/
|
|
503
|
+
async function executeAddDataFlow(options: AddDataFlowOptions): Promise<boolean> {
|
|
504
|
+
const { formSchema, formState, itemData, previousDataField, organizationAutoFill, onError } = options;
|
|
505
|
+
|
|
506
|
+
// Clear schema
|
|
507
|
+
clearFormSchema(Object.entries(formSchema.value));
|
|
508
|
+
|
|
509
|
+
// Setup previous data
|
|
510
|
+
setupPreviousData(formSchema, itemData, previousDataField);
|
|
511
|
+
|
|
512
|
+
const needsOrgAutoFill = organizationAutoFill?.enabled;
|
|
513
|
+
formState.loadingForm.value = needsOrgAutoFill || false;
|
|
514
|
+
formState.formType.value = "add";
|
|
515
|
+
formState.formOpen.value = true;
|
|
516
|
+
formState.formError.value = null;
|
|
517
|
+
|
|
518
|
+
try {
|
|
519
|
+
// Handle organization auto-fill
|
|
520
|
+
if (organizationAutoFill?.enabled) {
|
|
521
|
+
await handleOrganizationAutoFill(formSchema, organizationAutoFill);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
return true;
|
|
525
|
+
} catch (err: any) {
|
|
526
|
+
onError?.(err.message || InternalServerError);
|
|
527
|
+
return false;
|
|
528
|
+
} finally {
|
|
529
|
+
formState.loadingForm.value = false;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Main function - Generic Add Data
|
|
535
|
+
* Router untuk semua mode add data
|
|
536
|
+
*/
|
|
537
|
+
export async function addData(options: AddDataOptions): Promise<boolean> {
|
|
538
|
+
// Validation
|
|
539
|
+
if (!options.formSchema?.value && !options.formSchema) {
|
|
540
|
+
options.onError?.("Form schema tidak ditemukan");
|
|
541
|
+
return false;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
try {
|
|
545
|
+
switch (options.mode) {
|
|
546
|
+
case "sheet":
|
|
547
|
+
return await executeAddDataSheet(options);
|
|
548
|
+
|
|
549
|
+
case "basic":
|
|
550
|
+
return await executeAddDataBasic(options);
|
|
551
|
+
|
|
552
|
+
case "inline":
|
|
553
|
+
return await executeAddDataInline(options);
|
|
554
|
+
|
|
555
|
+
case "flow":
|
|
556
|
+
return await executeAddDataFlow(options);
|
|
557
|
+
|
|
558
|
+
default:
|
|
559
|
+
throw new Error(`Unsupported mode: ${(options as any).mode}`);
|
|
560
|
+
}
|
|
561
|
+
} catch (error: any) {
|
|
562
|
+
options.onError?.(error.message || InternalServerError);
|
|
563
|
+
return false;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
/**
|
|
568
|
+
* Legacy function untuk backward compatibility
|
|
569
|
+
* @deprecated Use addData() instead
|
|
570
|
+
*/
|
|
571
|
+
export async function addDataGeneric(options: AddDataGenericOptions): Promise<boolean> {
|
|
572
|
+
// Convert legacy options to new format
|
|
573
|
+
const mode = options.mode || "sheet";
|
|
574
|
+
|
|
575
|
+
// Handle legacy autoFillOrganization
|
|
576
|
+
let organizationAutoFill: OrganizationAutoFillConfig | undefined;
|
|
577
|
+
if (options.autoFillOrganization) {
|
|
578
|
+
organizationAutoFill = { enabled: true };
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
// Handle legacy endpointSpecificHandlers
|
|
582
|
+
let endpointConfig: EndpointSpecificConfig | undefined;
|
|
583
|
+
if (options.endpointSpecificHandlers) {
|
|
584
|
+
endpointConfig = {};
|
|
585
|
+
for (const [endpoint, handler] of Object.entries(options.endpointSpecificHandlers)) {
|
|
586
|
+
endpointConfig[endpoint] = { onMount: handler };
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
const newOptions: AddDataOptions = {
|
|
591
|
+
...options,
|
|
592
|
+
mode: mode as any,
|
|
593
|
+
organizationAutoFill,
|
|
594
|
+
endpointConfig
|
|
595
|
+
} as AddDataOptions;
|
|
596
|
+
|
|
597
|
+
return await addData(newOptions);
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
// ==========================================
|
|
601
|
+
// HELPER FUNCTIONS FOR EASY USAGE
|
|
602
|
+
// ==========================================
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* Helper untuk Sheet Mode (PageActivity.vue pattern)
|
|
606
|
+
* Paling simple untuk digunakan
|
|
607
|
+
*/
|
|
608
|
+
export async function addDataSheet(options: {
|
|
609
|
+
title: string;
|
|
610
|
+
endpoint: string;
|
|
611
|
+
formSchema: any;
|
|
612
|
+
formHooks?: any;
|
|
613
|
+
pageConfig?: any;
|
|
614
|
+
onSuccess?: () => void;
|
|
615
|
+
onError?: (error: string) => void;
|
|
616
|
+
}): Promise<boolean> {
|
|
617
|
+
return await addData({
|
|
618
|
+
...options,
|
|
619
|
+
mode: "sheet"
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
/**
|
|
624
|
+
* Helper untuk Inline Mode (PageActivityNew.vue pattern)
|
|
625
|
+
* Dengan auto-fill organization
|
|
626
|
+
*/
|
|
627
|
+
export async function addDataInline(options: {
|
|
628
|
+
title: string;
|
|
629
|
+
endpoint: string;
|
|
630
|
+
formSchema: any;
|
|
631
|
+
formHooks?: any;
|
|
632
|
+
pageConfig?: any;
|
|
633
|
+
formState: FormStateRefs;
|
|
634
|
+
onSuccess?: () => void;
|
|
635
|
+
onError?: (error: string) => void;
|
|
636
|
+
endpointHandlers?: Record<string, (formEditEl: any) => void>;
|
|
637
|
+
}): Promise<boolean> {
|
|
638
|
+
// Auto-detect organization auto-fill
|
|
639
|
+
const hasOrgField = options.formSchema.value?.organizationId?.autofill;
|
|
640
|
+
|
|
641
|
+
return await addData({
|
|
642
|
+
...options,
|
|
643
|
+
mode: "inline",
|
|
644
|
+
organizationAutoFill: hasOrgField ? { enabled: true } : undefined,
|
|
645
|
+
endpointConfig: options.endpointHandlers ? Object.fromEntries(Object.entries(options.endpointHandlers).map(([key, handler]) => [key, { onMount: handler }])) : undefined
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
/**
|
|
650
|
+
* Helper untuk Basic Mode (Master.vue pattern)
|
|
651
|
+
* Paling simple tanpa auto-fill
|
|
652
|
+
*/
|
|
653
|
+
export async function addDataBasic(options: {
|
|
654
|
+
formSchema: any;
|
|
655
|
+
formState: FormStateRefs;
|
|
656
|
+
onError?: (error: string) => void;
|
|
657
|
+
customClearFunction?: (schema: any) => void; // For Master.vue custom clearSchema
|
|
658
|
+
}): Promise<boolean> {
|
|
659
|
+
// Handle custom clear function for Master.vue pattern
|
|
660
|
+
if (options.customClearFunction) {
|
|
661
|
+
options.customClearFunction(Object.entries(options.formSchema));
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
return await addData({
|
|
665
|
+
title: "Data",
|
|
666
|
+
endpoint: "",
|
|
667
|
+
...options,
|
|
668
|
+
mode: "basic"
|
|
669
|
+
});
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
/**
|
|
673
|
+
* Helper untuk Flow Mode (PageActivityFlow.vue pattern)
|
|
674
|
+
* Dengan previous data auto-fill
|
|
675
|
+
*/
|
|
676
|
+
export async function addDataFlow(options: {
|
|
677
|
+
title: string;
|
|
678
|
+
endpoint: string;
|
|
679
|
+
formSchema: any;
|
|
680
|
+
formState: FormStateRefs;
|
|
681
|
+
itemData: any;
|
|
682
|
+
previousDataField: string;
|
|
683
|
+
onSuccess?: () => void;
|
|
684
|
+
onError?: (error: string) => void;
|
|
685
|
+
withOrganizationAutoFill?: boolean;
|
|
686
|
+
customClearFunction?: (schema: any) => void; // For PageActivityFlow.vue custom clearSchema
|
|
687
|
+
}): Promise<boolean> {
|
|
688
|
+
// Handle custom clear function for PageActivityFlow.vue pattern
|
|
689
|
+
if (options.customClearFunction) {
|
|
690
|
+
options.customClearFunction(Object.entries(options.formSchema.value));
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
return await addData({
|
|
694
|
+
...options,
|
|
695
|
+
mode: "flow",
|
|
696
|
+
organizationAutoFill: options.withOrganizationAutoFill ? { enabled: true } : undefined
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
/**
|
|
701
|
+
* Helper untuk create custom endpoint configuration
|
|
702
|
+
*/
|
|
703
|
+
export function createEndpointConfig(configs: { [endpoint: string]: (formEditEl: any) => void }): EndpointSpecificConfig {
|
|
704
|
+
return Object.fromEntries(Object.entries(configs).map(([endpoint, handler]) => [endpoint, { onMount: handler }]));
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
/**
|
|
708
|
+
* Helper untuk create organization auto-fill config
|
|
709
|
+
*/
|
|
710
|
+
export function createOrgAutoFillConfig(options?: { fieldName?: string; accessLevelField?: string; endpoint?: string }): OrganizationAutoFillConfig {
|
|
711
|
+
return {
|
|
712
|
+
enabled: true,
|
|
713
|
+
fieldName: options?.fieldName || "organizationId",
|
|
714
|
+
accessLevelField: options?.accessLevelField || "accessLevel",
|
|
715
|
+
endpoint: options?.endpoint || "/organization/my"
|
|
716
|
+
};
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
/**
|
|
720
|
+
* Factory function untuk membuat add data function yang sudah dikonfigurasi
|
|
721
|
+
* Berguna untuk halaman yang sering digunakan
|
|
722
|
+
*/
|
|
723
|
+
export function createAddDataFunction(baseConfig: Partial<AddDataOptions>) {
|
|
724
|
+
return async (overrides: Partial<AddDataOptions> = {}): Promise<boolean> => {
|
|
725
|
+
const mergedConfig = { ...baseConfig, ...overrides } as AddDataOptions;
|
|
726
|
+
return await addData(mergedConfig);
|
|
727
|
+
};
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
// ==========================================
|
|
731
|
+
// PRESET CONFIGURATIONS FOR COMMON PATTERNS
|
|
732
|
+
// ==========================================
|
|
733
|
+
|
|
734
|
+
/**
|
|
735
|
+
* Preset untuk halaman dengan FormSheet (seperti PageActivity.vue)
|
|
736
|
+
*/
|
|
737
|
+
export const SHEET_MODE_PRESET = {
|
|
738
|
+
mode: "sheet" as const
|
|
739
|
+
};
|
|
740
|
+
|
|
741
|
+
/**
|
|
742
|
+
* Preset untuk halaman dengan inline form + auto-fill org (seperti PageActivityNew.vue)
|
|
743
|
+
*/
|
|
744
|
+
export const INLINE_WITH_ORG_PRESET = {
|
|
745
|
+
mode: "inline" as const,
|
|
746
|
+
organizationAutoFill: { enabled: true }
|
|
747
|
+
};
|
|
748
|
+
|
|
749
|
+
/**
|
|
750
|
+
* Preset untuk halaman basic (seperti Master.vue)
|
|
751
|
+
*/
|
|
752
|
+
export const BASIC_MODE_PRESET = {
|
|
753
|
+
mode: "basic" as const
|
|
754
|
+
};
|
|
755
|
+
|
|
756
|
+
/**
|
|
757
|
+
* Preset untuk halaman flow (seperti PageActivityFlow.vue)
|
|
758
|
+
*/
|
|
759
|
+
export const FLOW_MODE_PRESET = {
|
|
760
|
+
mode: "flow" as const,
|
|
761
|
+
organizationAutoFill: { enabled: true }
|
|
762
|
+
};
|
|
763
|
+
|
|
764
|
+
/**
|
|
765
|
+
* -------------------------------------------
|
|
766
|
+
* Edit item
|
|
767
|
+
* @return
|
|
768
|
+
* true: data saved to api
|
|
769
|
+
* false: aborted
|
|
770
|
+
*
|
|
771
|
+
*/
|
|
772
|
+
export async function editFormData(options: EditFormOptions) {
|
|
773
|
+
/**
|
|
774
|
+
* Clear schema
|
|
775
|
+
*
|
|
776
|
+
*/
|
|
777
|
+
clearFormSchema(Object.entries(options.formSchema.value));
|
|
778
|
+
let editData: any;
|
|
779
|
+
|
|
780
|
+
/**
|
|
781
|
+
* Generate save api url
|
|
782
|
+
*
|
|
783
|
+
*/
|
|
784
|
+
const slash = options.endpoint.startsWith("/") ? "" : "/";
|
|
785
|
+
const uri = `${slash}${options.endpoint}/${options.item.id}`;
|
|
786
|
+
|
|
787
|
+
/**
|
|
788
|
+
* Render form with loading
|
|
789
|
+
*
|
|
790
|
+
*/
|
|
791
|
+
return await formSheet.open({
|
|
792
|
+
title: options.title,
|
|
793
|
+
formSchema: options.formSchema,
|
|
794
|
+
loading: true,
|
|
795
|
+
className: options.formDialogClass,
|
|
796
|
+
onChange(after, before, el$) {
|
|
797
|
+
if (options.formHooks?.onChange) {
|
|
798
|
+
options.formHooks?.onChange(after, before, el$, options.formSchema, "edit");
|
|
799
|
+
}
|
|
800
|
+
},
|
|
801
|
+
async onDialogOpen() {
|
|
802
|
+
try {
|
|
803
|
+
/**
|
|
804
|
+
* Get edit data from api
|
|
805
|
+
*
|
|
806
|
+
*/
|
|
807
|
+
let editUri = uri;
|
|
808
|
+
// Include extras for relational data (e.g., AccessLevel)
|
|
809
|
+
if (options.pageConfig?.extras?.length > 0) {
|
|
810
|
+
editUri += `?extras=${options.pageConfig.extras.join(",")}`;
|
|
811
|
+
}
|
|
812
|
+
const r = await api.get(editUri);
|
|
813
|
+
editData = r.data.data;
|
|
814
|
+
|
|
815
|
+
/**
|
|
816
|
+
* Add on before mount and pass edit data,
|
|
817
|
+
* this might change the schema
|
|
818
|
+
*
|
|
819
|
+
*/
|
|
820
|
+
if (options.formHooks?.onBeforeMount) {
|
|
821
|
+
if (!(await options.formHooks.onBeforeMount(options.formSchema, "edit", editData))) {
|
|
822
|
+
return;
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
/**
|
|
827
|
+
* Fill schema with editData from API and then
|
|
828
|
+
* Render form by set loading to false
|
|
829
|
+
*
|
|
830
|
+
*/
|
|
831
|
+
fillFormSchema(Object.entries(options.formSchema.value), editData);
|
|
832
|
+
formSheet.loading = false;
|
|
833
|
+
} catch (err: any) {
|
|
834
|
+
errorDialog
|
|
835
|
+
.open({
|
|
836
|
+
title: "Edit Data Gagal",
|
|
837
|
+
description: err.message || InternalServerError
|
|
838
|
+
})
|
|
839
|
+
.then(() => {
|
|
840
|
+
formSheet.close();
|
|
841
|
+
});
|
|
842
|
+
}
|
|
843
|
+
},
|
|
844
|
+
async onMounted(form$) {
|
|
845
|
+
try {
|
|
846
|
+
/**
|
|
847
|
+
* After form rendered
|
|
848
|
+
* run onMounted event
|
|
849
|
+
*
|
|
850
|
+
*/
|
|
851
|
+
if (options.formHooks?.onMounted) {
|
|
852
|
+
console.log('q',options.formHooks?.onMounted )
|
|
853
|
+
if (!(await options.formHooks?.onMounted(form$, options.formSchema, "edit", editData))) {
|
|
854
|
+
console.log('On mounted failed, edit canceled');
|
|
855
|
+
formSheet.close();
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
} catch (err: any) {
|
|
859
|
+
errorDialog
|
|
860
|
+
.open({
|
|
861
|
+
title: "Edit Data Gagal",
|
|
862
|
+
description: err.message || InternalServerError
|
|
863
|
+
})
|
|
864
|
+
.then(() => {
|
|
865
|
+
formSheet.close();
|
|
866
|
+
});
|
|
867
|
+
}
|
|
868
|
+
},
|
|
869
|
+
async onSubmit(form$) {
|
|
870
|
+
formSheet.saving = true;
|
|
871
|
+
try {
|
|
872
|
+
const b = await submitFormData({
|
|
873
|
+
form$,
|
|
874
|
+
endpoint: `${uri}/edit`,
|
|
875
|
+
formSchema: options.formSchema,
|
|
876
|
+
formHooks: options.formHooks
|
|
877
|
+
});
|
|
878
|
+
if (!b) return;
|
|
879
|
+
successDialog.open().then(() => {
|
|
880
|
+
formSheet.close(true);
|
|
881
|
+
});
|
|
882
|
+
} catch (err: any) {
|
|
883
|
+
formSheet.formError = err?.response?.data?.[0]?.message || err.message || InternalServerError;
|
|
884
|
+
} finally {
|
|
885
|
+
formSheet.saving = false;
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
});
|
|
889
|
+
|
|
890
|
+
// loadingForm.value = true;
|
|
891
|
+
// formType.value = "edit";
|
|
892
|
+
// formOpen.value = true;
|
|
893
|
+
// formError.value = null;
|
|
894
|
+
// editId.value = item.id;
|
|
895
|
+
// let editData: any = null;
|
|
896
|
+
// api
|
|
897
|
+
// .get(`${endpoint.value}/${item.id}`)
|
|
898
|
+
// .then(async (r) => {
|
|
899
|
+
// editData = r.data.data;
|
|
900
|
+
// fillFormSchema(Object.entries(formSchema.value || {}), r.data.data);
|
|
901
|
+
// })
|
|
902
|
+
// .catch((err) => {
|
|
903
|
+
// errorDialog.value?.open({
|
|
904
|
+
// title: `Edit ${title.value} Gagal`,
|
|
905
|
+
// description: err.message || "Internal server error. Please try again later.",
|
|
906
|
+
// });
|
|
907
|
+
// })
|
|
908
|
+
// .finally(() => {
|
|
909
|
+
// loadingForm.value = false;
|
|
910
|
+
// if (!formSchema.value) return;
|
|
911
|
+
// setTimeout(async () => {
|
|
912
|
+
// if (formHooks.value && formHooks.value.onMounted) {
|
|
913
|
+
// await formHooks.value.onMounted(formEditEl.value, formSchema, 'edit', editData);
|
|
914
|
+
// }
|
|
915
|
+
// })
|
|
916
|
+
// });
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
/**
|
|
920
|
+
* -------------------------------------------
|
|
921
|
+
* Delete item
|
|
922
|
+
* @return
|
|
923
|
+
* true: data deleted to api
|
|
924
|
+
* false: aborted
|
|
925
|
+
*
|
|
926
|
+
*/
|
|
927
|
+
export async function deleteFormData(options: DeleteRestoreFormOptions) {
|
|
928
|
+
const name = options.pageConfig?.dataName ? options.pageConfig.dataName(options.item) : (options.item?.name || options.item?.nama || "data");
|
|
929
|
+
const b = await confirmDialog.open({
|
|
930
|
+
title: `Hapus ${options.title}`,
|
|
931
|
+
description: `Apakah Anda yakin ingin menghapus ${options.title.toLowerCase()} <b class="font-bold text-red-500">${name}?</b> Data terhapus akan dipindah ke dalam folder Deleted`,
|
|
932
|
+
cancelLabel: "Batal",
|
|
933
|
+
actionLabel: `Hapus ${options.title}`,
|
|
934
|
+
actionIcon: "LucideTrash2",
|
|
935
|
+
negative: true
|
|
936
|
+
});
|
|
937
|
+
|
|
938
|
+
/**
|
|
939
|
+
* Aborted by user
|
|
940
|
+
*
|
|
941
|
+
*/
|
|
942
|
+
if (!b) return false;
|
|
943
|
+
const deletedItem = options.allData.splice(options.index, 1);
|
|
944
|
+
try {
|
|
945
|
+
api.delete(`${options.endpoint}/${options.item.id}/soft`);
|
|
946
|
+
toast.success(`${options.title} ${name} sukses dihapus`, {
|
|
947
|
+
action: {
|
|
948
|
+
label: "Undo",
|
|
949
|
+
onClick: () => {
|
|
950
|
+
options.allData.splice(options.index, 0, deletedItem[0]);
|
|
951
|
+
api
|
|
952
|
+
.put(`${options.endpoint}/${options.item.id}/restore`)
|
|
953
|
+
.then(() => {
|
|
954
|
+
toast.info(`Aksi hapus ${name} dibatalkan`);
|
|
955
|
+
})
|
|
956
|
+
.catch(err => {
|
|
957
|
+
errorDialog.open({
|
|
958
|
+
title: `Undo Hapus ${options.title} Gagal`,
|
|
959
|
+
description: err.message || "Internal server error. Please try again later."
|
|
960
|
+
});
|
|
961
|
+
});
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
});
|
|
965
|
+
} catch (err: any) {
|
|
966
|
+
options.allData.splice(options.index, 0, deletedItem[0]);
|
|
967
|
+
errorDialog.open({
|
|
968
|
+
title: `Hapus ${options.title} Gagal`,
|
|
969
|
+
description: err.message || "Internal server error. Please try again later."
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
/**
|
|
975
|
+
* -------------------------------------------
|
|
976
|
+
* Restore item
|
|
977
|
+
* @return
|
|
978
|
+
* true: data restored to api
|
|
979
|
+
* false: aborted
|
|
980
|
+
*
|
|
981
|
+
*/
|
|
982
|
+
export async function restoreFormData(options: DeleteRestoreFormOptions) {
|
|
983
|
+
const name = options.pageConfig?.dataName ? options.pageConfig.dataName(options.item) : (options.item?.name || options.item?.nama || "data");
|
|
984
|
+
const b = await confirmDialog.open({
|
|
985
|
+
title: `Restore ${options.title}`,
|
|
986
|
+
description: `Apakah Anda yakin ingin mengembalikan ${options.title.toLowerCase()} <b class="font-bold text-red-500">${name}?</b> Data akan tampil kembali di semua data`,
|
|
987
|
+
cancelLabel: "Batal",
|
|
988
|
+
actionLabel: `Restore ${options.title}`,
|
|
989
|
+
actionIcon: "LucideUndo2",
|
|
990
|
+
negative: true
|
|
991
|
+
});
|
|
992
|
+
|
|
993
|
+
/**
|
|
994
|
+
* Aborted by user
|
|
995
|
+
*
|
|
996
|
+
*/
|
|
997
|
+
if (!b) return false;
|
|
998
|
+
const restoredItem = options.allData.splice(options.index, 1);
|
|
999
|
+
try {
|
|
1000
|
+
api.put(`${options.endpoint}/${options.item.id}/restore`);
|
|
1001
|
+
toast.success(`${options.title} ${name} sukses dikembalikan`);
|
|
1002
|
+
} catch (err: any) {
|
|
1003
|
+
options.allData.splice(options.index, 0, restoredItem[0]);
|
|
1004
|
+
errorDialog.open({
|
|
1005
|
+
title: `Restore ${options.title} Gagal`,
|
|
1006
|
+
description: err.message || "Internal server error. Please try again later."
|
|
1007
|
+
});
|
|
1008
|
+
}
|
|
1009
|
+
}
|