@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
package/src/lib/utils.ts
ADDED
|
@@ -0,0 +1,643 @@
|
|
|
1
|
+
import { type ClassValue, clsx } from "clsx";
|
|
2
|
+
import { twMerge } from "tailwind-merge";
|
|
3
|
+
import moment from "moment";
|
|
4
|
+
import { saveAs } from "file-saver";
|
|
5
|
+
import jsPDF from "jspdf";
|
|
6
|
+
import autoTable from "jspdf-autotable";
|
|
7
|
+
import * as XLSX from "xlsx";
|
|
8
|
+
import menu from "@/menu";
|
|
9
|
+
|
|
10
|
+
export const monthNames = ["-", "Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember"];
|
|
11
|
+
|
|
12
|
+
export function cn(...inputs: ClassValue[]) {
|
|
13
|
+
return twMerge(clsx(inputs));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function clearFormSchema(schema: any[]) {
|
|
17
|
+
for (const [_, item] of schema) {
|
|
18
|
+
item.default = item.nullValue;
|
|
19
|
+
if (item.disabledValue) item.disabled = item.disabledValue;
|
|
20
|
+
if (item.schema) clearFormSchema(Object.entries(item.schema));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Helper function to check if a value is meaningful
|
|
25
|
+
export function isValidValue(value: any): boolean {
|
|
26
|
+
if (value === null || value === undefined || value === false) return false;
|
|
27
|
+
if (typeof value === "string" && value.trim() === "") return false;
|
|
28
|
+
if (typeof value === "number" && String(value).trim() === "") return false;
|
|
29
|
+
if (value === "0001-01-01") return false; // Invalid date placeholder
|
|
30
|
+
if (Array.isArray(value) && value.length === 0) return false;
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Helper function to check if a value is meaningful
|
|
35
|
+
function isValidFormValue(value: any): boolean {
|
|
36
|
+
if (value === null || value === undefined) return false;
|
|
37
|
+
if (typeof value === "string" && value.trim() === "") return false;
|
|
38
|
+
if (typeof value === "number" && String(value).trim() === "") return false;
|
|
39
|
+
if (value === "0001-01-01") return false; // Invalid date placeholder
|
|
40
|
+
if (Array.isArray(value) && value.length === 0) return false;
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function fillFormSchema(schema: any, items: any) {
|
|
45
|
+
/**
|
|
46
|
+
* Clear schema before filling new data
|
|
47
|
+
*
|
|
48
|
+
*/
|
|
49
|
+
clearFormSchema(schema);
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Now fill the schema with data
|
|
53
|
+
*
|
|
54
|
+
*/
|
|
55
|
+
for (const [key, item] of schema) {
|
|
56
|
+
// Handle array items with nested object structure
|
|
57
|
+
// Generic pattern: if key ends with "Items" and is an array, transform to selector format
|
|
58
|
+
if (key.endsWith("Items") && Array.isArray(items[key]) && items[key].length > 0) {
|
|
59
|
+
const transformedData = items[key]
|
|
60
|
+
.filter((item: any) => item && item !== null && item !== undefined)
|
|
61
|
+
.map((item: any) => {
|
|
62
|
+
if (!item) return null;
|
|
63
|
+
|
|
64
|
+
const id = item.id || item[`${key.replace("Items", "")}Id`];
|
|
65
|
+
const nameKey = key.replace("Items", "");
|
|
66
|
+
const name = item[nameKey]?.name || item[nameKey]?.nama || item.name || item.nama || `ID: ${id}`;
|
|
67
|
+
|
|
68
|
+
if (id) {
|
|
69
|
+
return { id, name };
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
})
|
|
73
|
+
.filter((item: any) => item !== null);
|
|
74
|
+
|
|
75
|
+
if (transformedData.length > 0) {
|
|
76
|
+
item.default = transformedData;
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Handle dasi_v2_date_range type specifically
|
|
82
|
+
if (item.type === "dasi_v2_date_range") {
|
|
83
|
+
const keyAwal = `${key}Awal`;
|
|
84
|
+
const keyAkhir = `${key}Akhir`;
|
|
85
|
+
|
|
86
|
+
const awalValue = items[keyAwal];
|
|
87
|
+
const akhirValue = items[keyAkhir];
|
|
88
|
+
|
|
89
|
+
// Only set if both dates are valid and not placeholder dates
|
|
90
|
+
if (isValidFormValue(awalValue) && isValidFormValue(akhirValue) && awalValue !== "0001-01-01" && akhirValue !== "0001-01-01") {
|
|
91
|
+
item.default = [new Date(awalValue), new Date(akhirValue)];
|
|
92
|
+
}
|
|
93
|
+
// If invalid, keep the original default value from schema
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (item.type === "dasi_v2_selector_single_v2") {
|
|
98
|
+
const theKey = key.substring(key.length - 2, key.length) === "Id" ? key.substring(0, key.length - 2) : key;
|
|
99
|
+
const value: any = items[theKey];
|
|
100
|
+
if (value && item.subItem) {
|
|
101
|
+
if (item.subItem.fillFromFunc) value.subItemSelected = item.subItem.fillFromFunc(items);
|
|
102
|
+
else value.subItemSelected = items[item.subItem.fillFrom];
|
|
103
|
+
}
|
|
104
|
+
item.default = { value };
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
for (const [key2, item2] of Object.entries(items)) {
|
|
109
|
+
if (key.substring(key.length - 2, key.length) === "Id") {
|
|
110
|
+
// Handle ID fields
|
|
111
|
+
if (key.substring(0, key.length - 2) === key2) {
|
|
112
|
+
// Skip if already processed by custom field mapping
|
|
113
|
+
if (item._processed) {
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (isValidFormValue(item2)) {
|
|
117
|
+
if (item2 && (item2 as any).mimetype) {
|
|
118
|
+
item.default = item2;
|
|
119
|
+
} else {
|
|
120
|
+
item.default = [item2];
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// If invalid, keep the original default value from schema
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* @deprecated
|
|
128
|
+
* ___Code no need to pass object,
|
|
129
|
+
* this is normal dropdown
|
|
130
|
+
*
|
|
131
|
+
*/
|
|
132
|
+
// } else if (key.substring(key.length - 4, key.length) === "Code") {
|
|
133
|
+
// // Handle ID fields
|
|
134
|
+
// if (key.substring(0, key.length - 4) === key2) {
|
|
135
|
+
// if (isValidFormValue(item2)) {
|
|
136
|
+
// if (item2 && (item2 as any).mimetype) {
|
|
137
|
+
// item.default = item2;
|
|
138
|
+
// } else {
|
|
139
|
+
// item.default = [item2];
|
|
140
|
+
// }
|
|
141
|
+
// }
|
|
142
|
+
// // If invalid, keep the original default value from schema
|
|
143
|
+
// }
|
|
144
|
+
} else if (key.substring(key.length - 3, key.length) === "Ids") {
|
|
145
|
+
// Handle multiple selector
|
|
146
|
+
if (key.substring(0, key.length - 3) === key2) {
|
|
147
|
+
if (isValidFormValue(item2)) item.default = item2;
|
|
148
|
+
}
|
|
149
|
+
} else {
|
|
150
|
+
// Handle regular fields
|
|
151
|
+
if (key === key2 && key.substring(key.length - 2, key.length) !== "Id") {
|
|
152
|
+
if (isValidFormValue(item2)) item.default = item2;
|
|
153
|
+
// If invalid, keep the original default value from schema
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Recursively handle nested schemas
|
|
159
|
+
if (item.schema) {
|
|
160
|
+
fillFormSchema(Object.entries(item.schema), items);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export function validateFormSilent(el: any, schema: any, path: string = ""): any {
|
|
166
|
+
let isValid = true;
|
|
167
|
+
for (const [key, item] of Object.entries(schema) as any) {
|
|
168
|
+
let conditionMeet = true;
|
|
169
|
+
if (item.conditions && item.conditions.length > 0) {
|
|
170
|
+
for (const condition of item.conditions) {
|
|
171
|
+
if (condition[1] === "==") {
|
|
172
|
+
const val = el.el$(condition[0]).value;
|
|
173
|
+
if (val !== condition[2]) {
|
|
174
|
+
conditionMeet = false;
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
} else if (condition[1] === "in") {
|
|
178
|
+
const val = el.el$(condition[0]).value;
|
|
179
|
+
if (!condition[2].includes(val)) {
|
|
180
|
+
conditionMeet = false;
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
if (!conditionMeet) continue;
|
|
187
|
+
if (item.rules && item.rules.length > 0 && !el.el$(path + key).value) {
|
|
188
|
+
isValid = false;
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
if (item.schema) {
|
|
192
|
+
isValid = validateFormSilent(el, item.schema, key + ".");
|
|
193
|
+
if (!isValid) break;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
console.log("Validation result", isValid);
|
|
197
|
+
return isValid;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export function formatNumber(number: Number): string {
|
|
201
|
+
return Number(number || 0).toLocaleString("id", { maximumFractionDigits: 1 });
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export function formatNumberIntl(number: number | undefined, minFraction = 0, maxFraction = 3): string {
|
|
205
|
+
return Number(number || 0).toLocaleString("us", {
|
|
206
|
+
maximumFractionDigits: maxFraction,
|
|
207
|
+
minimumFractionDigits: minFraction
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export function displayNumberFormatedIntl(number: number, before: string, after: string) {
|
|
212
|
+
if (!number) return "-";
|
|
213
|
+
return `${before} <b>${formatNumberIntl(number || 0)}</b> ${after}`;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export function intlFormatedToNumber(v: string): number | null {
|
|
217
|
+
return v ? Number(String(v).replace(/\,/g, "")) : null;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export function formatToCommaFloat(value: number): string {
|
|
221
|
+
return value
|
|
222
|
+
.toFixed(0) // Round to 2 decimal places
|
|
223
|
+
.replace(",", ".") // Replace dot with comma
|
|
224
|
+
.replace(/\B(?=(\d{3})+(?!\d))/g, ","); // Add thousand separators
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export function getMenuItemByUrl(url: string) {
|
|
228
|
+
for (const item of menu ?? []) {
|
|
229
|
+
for (const submenu of item.submenu ?? []) {
|
|
230
|
+
if (submenu.url === url) {
|
|
231
|
+
return submenu;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export function numberToWords(n: any) {
|
|
238
|
+
// If input is a string, remove commas
|
|
239
|
+
if (typeof n === "string") {
|
|
240
|
+
n = n.replace(/,/g, "");
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Validate input and convert to string
|
|
244
|
+
if (typeof n !== "number" && typeof n !== "string") {
|
|
245
|
+
return "Input must be a number";
|
|
246
|
+
}
|
|
247
|
+
if (isNaN(Number(n))) {
|
|
248
|
+
return "Input must be a number";
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Convert input to string for splitting on the decimal point.
|
|
252
|
+
let numStr = n.toString();
|
|
253
|
+
let result = "";
|
|
254
|
+
|
|
255
|
+
// Handle negative numbers
|
|
256
|
+
if (numStr[0] === "-") {
|
|
257
|
+
result = "minus ";
|
|
258
|
+
numStr = numStr.slice(1);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Split the number by the decimal point.
|
|
262
|
+
let parts = numStr.split(".");
|
|
263
|
+
let integerPart = parseInt(parts[0]);
|
|
264
|
+
let fractionalPart = parts[1]; // undefined if no decimal
|
|
265
|
+
|
|
266
|
+
// Convert the integer part
|
|
267
|
+
result += convertInteger(integerPart);
|
|
268
|
+
|
|
269
|
+
// If there is a fractional part, convert each digit individually.
|
|
270
|
+
if (fractionalPart !== undefined && fractionalPart.length > 0) {
|
|
271
|
+
result += " koma";
|
|
272
|
+
for (let i = 0; i < fractionalPart.length; i++) {
|
|
273
|
+
let digit = parseInt(fractionalPart[i]);
|
|
274
|
+
result += " " + digitToWord(digit);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
return result;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Number to month name start with 1,
|
|
283
|
+
* 1 = Januari,
|
|
284
|
+
* 2 = Februari,
|
|
285
|
+
* ...
|
|
286
|
+
*
|
|
287
|
+
*/
|
|
288
|
+
export function numberToMonth(n: number = 0) {
|
|
289
|
+
return monthNames[n];
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
export function formatMonthYear(monthYear: string | Date): string {
|
|
293
|
+
if (!monthYear) return "";
|
|
294
|
+
return `${numberToMonth(moment(monthYear).month() + 1)} ${moment(monthYear).year()}`;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function convertInteger(n: number): any {
|
|
298
|
+
// Special case for zero
|
|
299
|
+
if (n === 0) return "nol";
|
|
300
|
+
|
|
301
|
+
const angka = ["", "satu", "dua", "tiga", "empat", "lima", "enam", "tujuh", "delapan", "sembilan", "sepuluh", "sebelas"];
|
|
302
|
+
|
|
303
|
+
if (n < 12) {
|
|
304
|
+
return angka[n];
|
|
305
|
+
} else if (n < 20) {
|
|
306
|
+
return convertInteger(n - 10) + " belas";
|
|
307
|
+
} else if (n < 100) {
|
|
308
|
+
return convertInteger(Math.floor(n / 10)) + " puluh" + (n % 10 !== 0 ? " " + convertInteger(n % 10) : "");
|
|
309
|
+
} else if (n < 200) {
|
|
310
|
+
return "seratus" + (n % 100 !== 0 ? " " + convertInteger(n - 100) : "");
|
|
311
|
+
} else if (n < 1000) {
|
|
312
|
+
return convertInteger(Math.floor(n / 100)) + " ratus" + (n % 100 !== 0 ? " " + convertInteger(n % 100) : "");
|
|
313
|
+
} else if (n < 2000) {
|
|
314
|
+
return "seribu" + (n % 1000 !== 0 ? " " + convertInteger(n - 1000) : "");
|
|
315
|
+
} else if (n < 1000000) {
|
|
316
|
+
return convertInteger(Math.floor(n / 1000)) + " ribu" + (n % 1000 !== 0 ? " " + convertInteger(n % 1000) : "");
|
|
317
|
+
} else if (n < 1000000000) {
|
|
318
|
+
return convertInteger(Math.floor(n / 1000000)) + " juta" + (n % 1000000 !== 0 ? " " + convertInteger(n % 1000000) : "");
|
|
319
|
+
} else if (n < 1000000000000) {
|
|
320
|
+
return convertInteger(Math.floor(n / 1000000000)) + " milyar" + (n % 1000000000 !== 0 ? " " + convertInteger(n % 1000000000) : "");
|
|
321
|
+
} else if (n < 1000000000000000) {
|
|
322
|
+
return convertInteger(Math.floor(n / 1000000000000)) + " triliun" + (n % 1000000000000 !== 0 ? " " + convertInteger(n % 1000000000000) : "");
|
|
323
|
+
} else {
|
|
324
|
+
return "Number too large";
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
function digitToWord(digit: number) {
|
|
329
|
+
const angka = ["nol", "satu", "dua", "tiga", "empat", "lima", "enam", "tujuh", "delapan", "sembilan"];
|
|
330
|
+
return angka[digit];
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
export function isValidDate(value: string) {
|
|
334
|
+
const parsedDate = moment(new Date(value));
|
|
335
|
+
|
|
336
|
+
return parsedDate.isValid();
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
export function upFirst(str: string) {
|
|
340
|
+
return `${str.substring(0, 1).toUpperCase()}${str.substring(1)}`;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export function convertFormatDate(value: string): string | null {
|
|
344
|
+
if (!value) return null;
|
|
345
|
+
|
|
346
|
+
// Try to detect common date patterns using regex
|
|
347
|
+
const dateRegex = /\b\d{1,4}[-/]\d{1,2}[-/]\d{1,4}\b/;
|
|
348
|
+
|
|
349
|
+
if (dateRegex.test(value)) {
|
|
350
|
+
const parsedDate = moment(value, ["YYYY-MM-DD", "DD-MM-YYYY", "MM-DD-YYYY", "YYYY/MM/DD", "DD/MM/YYYY", "MM/DD/YYYY"], true); // 'true' = strict parsing
|
|
351
|
+
|
|
352
|
+
if (parsedDate.isValid()) {
|
|
353
|
+
return parsedDate.format("DD/MM/YYYY");
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
return null;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
export function parseDate(dateString: string) {
|
|
361
|
+
if (!dateString) {
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
const formats = [moment.ISO_8601, "YYYY-MM"];
|
|
365
|
+
|
|
366
|
+
const parsedMoment = moment(dateString, formats);
|
|
367
|
+
|
|
368
|
+
return parsedMoment.isValid() ? parsedMoment : null;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// Helper function to get nested property value
|
|
372
|
+
export function getNestedValue(obj: any, path: string): any {
|
|
373
|
+
return path.split(".").reduce((current, key) => current?.[key], obj);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
export function isValidVariable(variable: string) {
|
|
378
|
+
const regex = /^[a-zA-Z][a-zA-Z0-9_]*$/;
|
|
379
|
+
const disallowedVariables = [
|
|
380
|
+
"null",
|
|
381
|
+
"undefined",
|
|
382
|
+
"var",
|
|
383
|
+
"const",
|
|
384
|
+
"let",
|
|
385
|
+
"type",
|
|
386
|
+
"struct",
|
|
387
|
+
"func",
|
|
388
|
+
"function",
|
|
389
|
+
"package",
|
|
390
|
+
"return",
|
|
391
|
+
"panic",
|
|
392
|
+
"log",
|
|
393
|
+
"error",
|
|
394
|
+
"open",
|
|
395
|
+
"db",
|
|
396
|
+
"nil",
|
|
397
|
+
"err",
|
|
398
|
+
"new",
|
|
399
|
+
"string",
|
|
400
|
+
"int",
|
|
401
|
+
"number",
|
|
402
|
+
"float"
|
|
403
|
+
];
|
|
404
|
+
if (!variable) return false;
|
|
405
|
+
if (disallowedVariables.includes(variable.toLowerCase())) return false;
|
|
406
|
+
return regex.test(variable);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
export function escapeRegex(str: string): string {
|
|
410
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
export function exportToCSV(data: any[], filename: string, columns?: { key: string; label: string }[]) {
|
|
414
|
+
// Handle empty data
|
|
415
|
+
if (!data || !data.length) {
|
|
416
|
+
console.warn("No data to export");
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
try {
|
|
421
|
+
// If columns are not specified, use object keys
|
|
422
|
+
const headers = columns ? columns.map(col => col.label) : Object.keys(data[0]);
|
|
423
|
+
|
|
424
|
+
// Create CSV content
|
|
425
|
+
const csvContent = [
|
|
426
|
+
// Add headers
|
|
427
|
+
headers.join(","),
|
|
428
|
+
// Add data rows
|
|
429
|
+
...data.map(row => {
|
|
430
|
+
return columns
|
|
431
|
+
? columns.map(col => formatCSVCell(row[col.key])).join(",")
|
|
432
|
+
: Object.values(row)
|
|
433
|
+
.map(cell => formatCSVCell(cell))
|
|
434
|
+
.join(",");
|
|
435
|
+
})
|
|
436
|
+
].join("\n");
|
|
437
|
+
|
|
438
|
+
// Create Blob and download
|
|
439
|
+
const blob = new Blob([`\uFEFF${csvContent}`], {
|
|
440
|
+
type: "text/csv;charset=utf-8"
|
|
441
|
+
});
|
|
442
|
+
saveAs(blob, `${filename}.csv`);
|
|
443
|
+
} catch (error) {
|
|
444
|
+
console.error("Error exporting CSV:", error);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
function formatCSVCell(value: any): string {
|
|
449
|
+
if (value === null || value === undefined) {
|
|
450
|
+
return "";
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
const stringValue = String(value);
|
|
454
|
+
|
|
455
|
+
// If value contains comma, quotes, or newline, wrap in quotes
|
|
456
|
+
if (/[,"\n]/.test(stringValue)) {
|
|
457
|
+
return `"${stringValue.replace(/"/g, '""')}"`;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
return stringValue;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
export function exportToPDF(data: any[], filename: string, columns?: { key: string; label: string }[], title?: string, pltuName?: string, periode?: string) {
|
|
464
|
+
if (!data || !data.length) {
|
|
465
|
+
console.warn("No data to export");
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
try {
|
|
470
|
+
const doc = new jsPDF();
|
|
471
|
+
let currentY = 15;
|
|
472
|
+
|
|
473
|
+
// Add PLTU Name as main title
|
|
474
|
+
if (pltuName) {
|
|
475
|
+
doc.setFontSize(16);
|
|
476
|
+
doc.setFont("helvetica", "bold");
|
|
477
|
+
doc.text(pltuName, 14, currentY);
|
|
478
|
+
currentY += 10;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// Add Periode as subtitle
|
|
482
|
+
if (periode) {
|
|
483
|
+
doc.setFontSize(12);
|
|
484
|
+
doc.setFont("helvetica", "normal");
|
|
485
|
+
doc.text(periode, 14, currentY);
|
|
486
|
+
currentY += 10;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// Add additional title if provided
|
|
490
|
+
if (title) {
|
|
491
|
+
doc.setFontSize(14);
|
|
492
|
+
doc.setFont("helvetica", "bold");
|
|
493
|
+
doc.text(title, 14, currentY);
|
|
494
|
+
currentY += 10;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
const headers = columns ? columns.map(col => col.label) : Object.keys(data[0]);
|
|
498
|
+
const rows = data.map(row => {
|
|
499
|
+
return columns ? columns.map(col => formatPDFCell(row[col.key])) : Object.values(row).map(cell => formatPDFCell(cell));
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
autoTable(doc, {
|
|
503
|
+
head: [headers],
|
|
504
|
+
body: rows,
|
|
505
|
+
startY: currentY + 5,
|
|
506
|
+
styles: {
|
|
507
|
+
fontSize: 8,
|
|
508
|
+
cellPadding: 2
|
|
509
|
+
},
|
|
510
|
+
headStyles: {
|
|
511
|
+
fillColor: [66, 139, 202],
|
|
512
|
+
textColor: 255,
|
|
513
|
+
fontStyle: "bold"
|
|
514
|
+
},
|
|
515
|
+
alternateRowStyles: {
|
|
516
|
+
fillColor: [245, 245, 245]
|
|
517
|
+
},
|
|
518
|
+
margin: { top: currentY + 5, left: 10, right: 10 }
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
doc.save(`${filename}.pdf`);
|
|
522
|
+
} catch (error) {
|
|
523
|
+
console.error("Error exporting PDF:", error);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
export function exportToExcel(data: any[], filename: string, columns?: { key: string; label: string }[], sheetName: string = "Sheet1", pltuName?: string, periode?: string) {
|
|
528
|
+
if (!data || !data.length) {
|
|
529
|
+
console.warn("No data to export");
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
try {
|
|
534
|
+
let exportData: any[];
|
|
535
|
+
let headerRowsCount = 0;
|
|
536
|
+
|
|
537
|
+
// Prepare title and subtitle rows
|
|
538
|
+
const titleRows: any[] = [];
|
|
539
|
+
|
|
540
|
+
if (pltuName) {
|
|
541
|
+
titleRows.push({ A: pltuName });
|
|
542
|
+
headerRowsCount++;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
if (periode) {
|
|
546
|
+
titleRows.push({ A: periode });
|
|
547
|
+
headerRowsCount++;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// Add empty row if we have title/subtitle
|
|
551
|
+
if (headerRowsCount > 0) {
|
|
552
|
+
titleRows.push({});
|
|
553
|
+
headerRowsCount++;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
if (columns) {
|
|
557
|
+
const headers = columns.reduce((acc, col) => {
|
|
558
|
+
acc[col.key] = col.label;
|
|
559
|
+
return acc;
|
|
560
|
+
}, {} as any);
|
|
561
|
+
|
|
562
|
+
exportData = [
|
|
563
|
+
...titleRows,
|
|
564
|
+
headers,
|
|
565
|
+
...data.map(row => {
|
|
566
|
+
return columns.reduce((acc, col) => {
|
|
567
|
+
acc[col.key] = formatExcelCell(row[col.key]);
|
|
568
|
+
return acc;
|
|
569
|
+
}, {} as any);
|
|
570
|
+
})
|
|
571
|
+
];
|
|
572
|
+
} else {
|
|
573
|
+
exportData = [
|
|
574
|
+
...titleRows,
|
|
575
|
+
...data.map(row => {
|
|
576
|
+
return Object.keys(row).reduce((acc, key) => {
|
|
577
|
+
acc[key] = formatExcelCell(row[key]);
|
|
578
|
+
return acc;
|
|
579
|
+
}, {} as any);
|
|
580
|
+
})
|
|
581
|
+
];
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
const ws = XLSX.utils.json_to_sheet(exportData, { skipHeader: !!columns });
|
|
585
|
+
|
|
586
|
+
// Style the title and subtitle rows
|
|
587
|
+
if (pltuName && ws['A1']) {
|
|
588
|
+
ws['A1'].s = {
|
|
589
|
+
font: { bold: true, sz: 16 },
|
|
590
|
+
alignment: { horizontal: 'left' }
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
if (periode && ws['A2']) {
|
|
595
|
+
ws['A2'].s = {
|
|
596
|
+
font: { sz: 12 },
|
|
597
|
+
alignment: { horizontal: 'left' }
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
const wb = XLSX.utils.book_new();
|
|
602
|
+
XLSX.utils.book_append_sheet(wb, ws, sheetName);
|
|
603
|
+
|
|
604
|
+
const excelBuffer = XLSX.write(wb, { bookType: "xlsx", type: "array" });
|
|
605
|
+
const blob = new Blob([excelBuffer], {
|
|
606
|
+
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
|
607
|
+
});
|
|
608
|
+
|
|
609
|
+
saveAs(blob, `${filename}.xlsx`);
|
|
610
|
+
} catch (error) {
|
|
611
|
+
console.error("Error exporting Excel:", error);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
function formatPDFCell(value: any): string {
|
|
616
|
+
if (value === null || value === undefined) {
|
|
617
|
+
return "";
|
|
618
|
+
}
|
|
619
|
+
return String(value);
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
function formatExcelCell(value: any): any {
|
|
623
|
+
if (value === null || value === undefined) {
|
|
624
|
+
return "";
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}/.test(value)) {
|
|
628
|
+
return new Date(value);
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
return value;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
export function convertToUtf8(inputString: string) {
|
|
635
|
+
const encoder = new TextEncoder();
|
|
636
|
+
const utf8Bytes = encoder.encode(inputString);
|
|
637
|
+
|
|
638
|
+
const hexString = Array.from(utf8Bytes)
|
|
639
|
+
.map(byte => byte.toString(16).padStart(2, "0"))
|
|
640
|
+
.join("");
|
|
641
|
+
|
|
642
|
+
return `%${hexString}`;
|
|
643
|
+
}
|