bitboss-ui 3.0.0-beta.65 → 3.0.0-beta.66
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 +78 -16
- package/bin/bitboss-ui-mcp.mjs +8 -8
- package/bin/bitboss-ui.mjs +73 -12
- package/dist/ai/BbAccordion.md +4 -3
- package/dist/ai/BbAlert.md +1 -1
- package/dist/ai/BbBadge.md +1 -0
- package/dist/ai/BbBadgeButton.md +4 -3
- package/dist/ai/BbBaseButton.md +25 -20
- package/dist/ai/BbBaseCheckboxIcon.md +1 -0
- package/dist/ai/BbBaseRadioIcon.md +1 -0
- package/dist/ai/BbBaseSwitchIcon.md +1 -0
- package/dist/ai/BbBreadcrumbs.md +8 -0
- package/dist/ai/BbButton.md +67 -21
- package/dist/ai/BbCalendar.md +56 -3
- package/dist/ai/BbCheckbox.md +1 -1
- package/dist/ai/BbCheckboxGroup.md +44 -8
- package/dist/ai/BbColorInput.md +3 -2
- package/dist/ai/BbColorPalette.md +7 -3
- package/dist/ai/BbConfirm.md +36 -80
- package/dist/ai/BbConfirmPortal.md +1 -1
- package/dist/ai/BbDatePicker.md +41 -5
- package/dist/ai/BbDatePickerInput.md +38 -6
- package/dist/ai/BbDialog.md +63 -58
- package/dist/ai/BbDropdown.md +25 -24
- package/dist/ai/BbDropdownButton.md +5 -12
- package/dist/ai/BbDropzone.md +2 -3
- package/dist/ai/BbForm.md +66 -42
- package/dist/ai/BbHost.md +29 -41
- package/dist/ai/BbIcon.md +3 -0
- package/dist/ai/BbNumberInput.md +2 -2
- package/dist/ai/BbOffCanvas.md +16 -9
- package/dist/ai/BbPagination.md +17 -17
- package/dist/ai/BbPopover.md +8 -3
- package/dist/ai/BbPtScope.md +5 -5
- package/dist/ai/BbRadio.md +1 -1
- package/dist/ai/BbRadioGroup.md +44 -7
- package/dist/ai/BbRating.md +1 -0
- package/dist/ai/BbSelect.md +146 -21
- package/dist/ai/BbSelectPopover.md +16 -12
- package/dist/ai/BbSlider.md +5 -3
- package/dist/ai/BbSwitch.md +1 -1
- package/dist/ai/BbTable.md +51 -39
- package/dist/ai/BbTabs.md +127 -63
- package/dist/ai/BbTabsList.md +4 -2
- package/dist/ai/BbTabsPanels.md +3 -1
- package/dist/ai/BbTabsRoot.md +4 -4
- package/dist/ai/BbTag.md +2 -2
- package/dist/ai/BbTextInput.md +23 -9
- package/dist/ai/BbTextarea.md +3 -3
- package/dist/ai/BbTimePicker.md +5 -4
- package/dist/ai/BbTimePickerInput.md +3 -3
- package/dist/ai/BbToast.md +33 -87
- package/dist/ai/BbToastPortal.md +1 -1
- package/dist/ai/CommonFieldInput.md +2 -1
- package/dist/ai/FlatListBox.md +1 -1
- package/dist/ai/GroupedListBox.md +1 -1
- package/dist/ai/ListBox.md +1 -1
- package/dist/ai/OptionsContainer.md +1 -1
- package/dist/ai/changelog.json +366 -4
- package/dist/ai/components.json +87 -83
- package/dist/ai/composables/{useBbDialogContext.md → useBbDialog.md} +18 -18
- package/dist/ai/composables/{useBbDropdownContext.md → useBbDropdown.md} +31 -31
- package/dist/ai/composables/{useBbFormContext.md → useBbForm.md} +11 -11
- package/dist/ai/composables/useBbFormField.md +2 -2
- package/dist/ai/composables/{useBbOffCanvasContext.md → useBbOffCanvas.md} +13 -13
- package/dist/ai/composables/{useBbTableContext.md → useBbTable.md} +20 -20
- package/dist/ai/composables/{useBbTabsContext.md → useBbTabs.md} +12 -12
- package/dist/ai/composables/useConfirm.md +42 -54
- package/dist/ai/composables/useToast.md +9 -26
- package/dist/ai/guides/agent-contract.md +57 -43
- package/dist/ai/guides/ai-router.md +1 -1
- package/dist/ai/guides/app-layout.md +32 -23
- package/dist/ai/guides/coherence-playbook.md +4 -2
- package/dist/ai/guides/component-picker.md +35 -32
- package/dist/ai/guides/design-language.md +26 -12
- package/dist/ai/guides/design-tokens.md +73 -32
- package/dist/ai/guides/eslint-rules.md +8 -4
- package/dist/ai/guides/fetch-items-playbook.md +3 -3
- package/dist/ai/guides/floating-bottom-panel.md +1 -1
- package/dist/ai/guides/inertia-helpers.md +661 -210
- package/dist/ai/guides/installation-and-plugin-setup.md +6 -3
- package/dist/ai/guides/migration/adoption-checklist.md +44 -2
- package/dist/ai/guides/migration/components/bb-dialog.md +13 -13
- package/dist/ai/guides/migration/components/bb-dropdown.md +16 -16
- package/dist/ai/guides/migration/components/bb-host.md +15 -14
- package/dist/ai/guides/migration/components/bb-offcanvas.md +10 -10
- package/dist/ai/guides/migration/components/bb-pagination.md +9 -9
- package/dist/ai/guides/migration/components/bb-select.md +1 -1
- package/dist/ai/guides/migration/components/bb-table.md +12 -12
- package/dist/ai/guides/migration/components/bb-tabs.md +1 -1
- package/dist/ai/guides/migration/from-async-validator.md +9 -9
- package/dist/ai/guides/migration/v2-to-v3.md +158 -13
- package/dist/ai/guides/options-items-playbook.md +2 -2
- package/dist/ai/guides/page-shell.md +15 -3
- package/dist/ai/guides/passthrough.md +9 -5
- package/dist/ai/guides/preset-components.md +102 -43
- package/dist/ai/guides/typescript-generic-components.md +21 -5
- package/dist/ai/guides/validated-forms.md +20 -11
- package/dist/ai/guides/validation-providers.md +3 -3
- package/dist/ai/helpers/definePreset.json +11 -4
- package/dist/ai/helpers/definePreset.ts +98 -41
- package/dist/ai/helpers/inertia/manifest.json +234 -76
- package/dist/ai/helpers/inertia/useConfirmOnRouteLeave.ts +24 -12
- package/dist/ai/helpers/inertia/usePromiseForm.ts +38 -151
- package/dist/ai/helpers/inertia/usePromiseRouter.ts +295 -0
- package/dist/ai/helpers/inertia/useQueryObject.ts +36 -5
- package/dist/ai/helpers/inertia/useRouteQuery.ts +28 -9
- package/dist/ai/helpers/inertia/utils.ts +53 -10
- package/dist/ai/index.md +15 -15
- package/dist/ai/manifest/common.json +2 -1
- package/dist/ai/manifest/components/BbAccordion.tree.json +3 -1
- package/dist/ai/manifest/components/BbAlert.json +1 -1
- package/dist/ai/manifest/components/BbBadge.tree.json +3 -1
- package/dist/ai/manifest/components/BbBadgeButton.json +9 -4
- package/dist/ai/manifest/components/BbBadgeButton.tree.json +1 -0
- package/dist/ai/manifest/components/BbBaseButton.json +9 -4
- package/dist/ai/manifest/components/BbBaseCheckboxIcon.tree.json +3 -1
- package/dist/ai/manifest/components/BbBaseRadioIcon.tree.json +3 -1
- package/dist/ai/manifest/components/BbBaseSwitchIcon.tree.json +3 -1
- package/dist/ai/manifest/components/BbBreadcrumbs.tree.json +7 -3
- package/dist/ai/manifest/components/BbButton.json +9 -4
- package/dist/ai/manifest/components/BbButton.tree.json +5 -3
- package/dist/ai/manifest/components/BbCalendar.json +4 -3
- package/dist/ai/manifest/components/BbCalendar.tree.json +10 -1
- package/dist/ai/manifest/components/BbCheckbox.json +1 -1
- package/dist/ai/manifest/components/BbCheckbox.tree.json +1 -1
- package/dist/ai/manifest/components/BbCheckboxGroup.json +1 -1
- package/dist/ai/manifest/components/BbCheckboxGroup.tree.json +62 -3
- package/dist/ai/manifest/components/BbCollapsible.json +4 -1
- package/dist/ai/manifest/components/BbColorInput.json +1 -1
- package/dist/ai/manifest/components/BbColorInput.tree.json +5 -3
- package/dist/ai/manifest/components/BbColorPalette.json +3 -0
- package/dist/ai/manifest/components/BbColorPalette.tree.json +7 -2
- package/dist/ai/manifest/components/BbConfirm.tree.json +2 -2
- package/dist/ai/manifest/components/BbDatePicker.json +7 -3
- package/dist/ai/manifest/components/BbDatePicker.tree.json +3 -4
- package/dist/ai/manifest/components/BbDatePickerInput.json +4 -3
- package/dist/ai/manifest/components/BbDatePickerInput.tree.json +5 -3
- package/dist/ai/manifest/components/BbDialog.json +1 -1
- package/dist/ai/manifest/components/BbDialog.tree.json +2 -2
- package/dist/ai/manifest/components/BbDropdown.json +3 -3
- package/dist/ai/manifest/components/BbDropdown.tree.json +2 -2
- package/dist/ai/manifest/components/BbDropdownButton.json +11 -6
- package/dist/ai/manifest/components/BbDropdownButton.tree.json +2 -3
- package/dist/ai/manifest/components/BbDropzone.json +4 -1
- package/dist/ai/manifest/components/BbForm.json +2 -2
- package/dist/ai/manifest/components/BbHost.json +1 -1
- package/dist/ai/manifest/components/BbHost.tree.json +1 -1
- package/dist/ai/manifest/components/BbHoverCard.json +1 -1
- package/dist/ai/manifest/components/BbNumberInput.json +1 -1
- package/dist/ai/manifest/components/BbNumberInput.tree.json +1 -1
- package/dist/ai/manifest/components/BbOffCanvas.json +1 -1
- package/dist/ai/manifest/components/BbOffCanvas.tree.json +3 -1
- package/dist/ai/manifest/components/BbPagination.json +4 -4
- package/dist/ai/manifest/components/BbPagination.tree.json +2 -1
- package/dist/ai/manifest/components/BbPopover.json +1 -1
- package/dist/ai/manifest/components/BbPopover.tree.json +1 -1
- package/dist/ai/manifest/components/BbProgress.json +4 -1
- package/dist/ai/manifest/components/BbRadio.json +1 -1
- package/dist/ai/manifest/components/BbRadio.tree.json +1 -1
- package/dist/ai/manifest/components/BbRadioGroup.json +5 -5
- package/dist/ai/manifest/components/BbRadioGroup.tree.json +62 -3
- package/dist/ai/manifest/components/BbRating.tree.json +3 -1
- package/dist/ai/manifest/components/BbSelect.json +5 -5
- package/dist/ai/manifest/components/BbSelect.tree.json +3 -3
- package/dist/ai/manifest/components/BbSelectPopover.json +7 -3
- package/dist/ai/manifest/components/BbSelectPopover.tree.json +2 -2
- package/dist/ai/manifest/components/BbSlider.json +3 -3
- package/dist/ai/manifest/components/BbSlider.tree.json +3 -0
- package/dist/ai/manifest/components/BbSmoothHeight.json +4 -1
- package/dist/ai/manifest/components/BbSwitch.json +1 -1
- package/dist/ai/manifest/components/BbSwitch.tree.json +1 -1
- package/dist/ai/manifest/components/BbSwitchGroup.tree.json +1 -1
- package/dist/ai/manifest/components/BbTable.json +6 -2
- package/dist/ai/manifest/components/BbTable.tree.json +4 -1
- package/dist/ai/manifest/components/BbTabs.json +9 -12
- package/dist/ai/manifest/components/BbTabs.tree.json +4 -1
- package/dist/ai/manifest/components/BbTabsList.json +4 -7
- package/dist/ai/manifest/components/BbTabsList.tree.json +4 -1
- package/dist/ai/manifest/components/BbTabsPanels.json +1 -1
- package/dist/ai/manifest/components/BbTabsPanels.tree.json +4 -1
- package/dist/ai/manifest/components/BbTabsRoot.json +5 -5
- package/dist/ai/manifest/components/BbTag.json +1 -1
- package/dist/ai/manifest/components/BbTag.tree.json +2 -2
- package/dist/ai/manifest/components/BbTextInput.json +4 -4
- package/dist/ai/manifest/components/BbTextInput.tree.json +1 -1
- package/dist/ai/manifest/components/BbTextarea.json +2 -2
- package/dist/ai/manifest/components/BbTextarea.tree.json +1 -1
- package/dist/ai/manifest/components/BbTimePicker.json +4 -1
- package/dist/ai/manifest/components/BbTimePicker.tree.json +5 -3
- package/dist/ai/manifest/components/BbTimePickerInput.json +2 -2
- package/dist/ai/manifest/components/BbTimePickerInput.tree.json +5 -3
- package/dist/ai/manifest/components/BbToast.json +1 -1
- package/dist/ai/manifest/components/BbToast.tree.json +3 -1
- package/dist/ai/manifest/components/BbTooltip.json +3 -0
- package/dist/ai/manifest/components/ChipsBox.tree.json +1 -1
- package/dist/ai/manifest/components/CommonField.tree.json +1 -0
- package/dist/ai/manifest/components/CommonFieldInput.tree.json +4 -2
- package/dist/ai/manifest/components/CommonTimeSelector.tree.json +1 -0
- package/dist/ai/manifest/components/FlatListBox.json +1 -1
- package/dist/ai/manifest/components/GroupedListBox.json +1 -1
- package/dist/ai/manifest/components/ListBox.json +1 -1
- package/dist/ai/manifest/components/OptionsContainer.json +2 -2
- package/dist/ai/manifest/index.json +3 -3
- package/dist/ai/manifest/meta.json +31 -16
- package/dist/ai/manifest/types.advanced.json +15 -11
- package/dist/ai/manifest/types.api.json +2 -2
- package/dist/ai/recipes/inertia/approvals-inbox.md +86 -115
- package/dist/ai/recipes/inertia/inline-edit-workspace.md +112 -120
- package/dist/ai/recipes/inertia/layout-scaffold.md +15 -4
- package/dist/ai/recipes/inertia/onboarding.md +76 -58
- package/dist/ai/recipes/inertia/ownership-atlas.md +74 -105
- package/dist/ai/recipes/inertia/record-form.md +18 -7
- package/dist/ai/recipes/inertia/records-workspace.md +106 -127
- package/dist/ai/recipes/inertia/settings-workspace.md +131 -73
- package/dist/ai/recipes/inertia/upload-center.md +97 -121
- package/dist/ai/recipes/inertia/wizard-form.md +25 -15
- package/dist/ai/recipes/nuxt/approvals-inbox.md +67 -48
- package/dist/ai/recipes/nuxt/inline-edit-workspace.md +73 -58
- package/dist/ai/recipes/nuxt/layout-scaffold.md +15 -4
- package/dist/ai/recipes/nuxt/onboarding.md +27 -10
- package/dist/ai/recipes/nuxt/ownership-atlas.md +40 -22
- package/dist/ai/recipes/nuxt/record-form.md +20 -7
- package/dist/ai/recipes/nuxt/records-workspace.md +120 -96
- package/dist/ai/recipes/nuxt/settings-workspace.md +36 -23
- package/dist/ai/recipes/nuxt/upload-center.md +63 -37
- package/dist/ai/recipes/nuxt/wizard-form.md +28 -16
- package/dist/ai/recipes/vue/approvals-inbox.md +74 -46
- package/dist/ai/recipes/vue/inline-edit-workspace.md +83 -56
- package/dist/ai/recipes/vue/layout-scaffold.md +15 -4
- package/dist/ai/recipes/vue/onboarding.md +27 -10
- package/dist/ai/recipes/vue/ownership-atlas.md +40 -22
- package/dist/ai/recipes/vue/record-form.md +20 -7
- package/dist/ai/recipes/vue/records-workspace.md +132 -95
- package/dist/ai/recipes/vue/settings-workspace.md +36 -23
- package/dist/ai/recipes/vue/upload-center.md +73 -37
- package/dist/ai/recipes/vue/wizard-form.md +28 -16
- package/dist/ai/source/BbAccordion.md +36 -6
- package/dist/ai/source/BbAlert.md +11 -5
- package/dist/ai/source/BbAsterisk.md +4 -1
- package/dist/ai/source/BbAvatar.md +11 -5
- package/dist/ai/source/BbBadge.md +42 -11
- package/dist/ai/source/BbBadgeButton.md +41 -8
- package/dist/ai/source/BbBaseButton.md +57 -15
- package/dist/ai/source/BbBaseCheckboxIcon.md +37 -13
- package/dist/ai/source/BbBaseRadioIcon.md +32 -9
- package/dist/ai/source/BbBaseSwitchIcon.md +31 -7
- package/dist/ai/source/BbBreadcrumbs.md +32 -9
- package/dist/ai/source/BbButton.md +91 -27
- package/dist/ai/source/BbCalendar.md +571 -300
- package/dist/ai/source/BbCheckbox.md +18 -7
- package/dist/ai/source/BbCheckboxGroup.md +16 -5
- package/dist/ai/source/BbCollapsible.md +15 -6
- package/dist/ai/source/BbColorInput.md +68 -20
- package/dist/ai/source/BbColorPalette.md +107 -23
- package/dist/ai/source/BbConfirmPortal.md +1 -1
- package/dist/ai/source/BbDatePicker.md +106 -25
- package/dist/ai/source/BbDatePickerInput.md +105 -42
- package/dist/ai/source/BbDialog.md +60 -44
- package/dist/ai/source/BbDropdown.md +44 -32
- package/dist/ai/source/BbDropdownButton.md +26 -20
- package/dist/ai/source/BbDropdownGroup.md +5 -5
- package/dist/ai/source/BbDropzone.md +53 -16
- package/dist/ai/source/BbForm.md +18 -7
- package/dist/ai/source/BbHost.md +25 -12
- package/dist/ai/source/BbHoverCard.md +20 -9
- package/dist/ai/source/BbIcon.md +9 -3
- package/dist/ai/source/BbIndicator.md +11 -4
- package/dist/ai/source/BbNumberInput.md +23 -6
- package/dist/ai/source/BbOffCanvas.md +73 -32
- package/dist/ai/source/BbPagination.md +59 -31
- package/dist/ai/source/BbPopover.md +28 -16
- package/dist/ai/source/BbProgress.md +13 -5
- package/dist/ai/source/BbRadio.md +16 -9
- package/dist/ai/source/BbRadioGroup.md +15 -4
- package/dist/ai/source/BbRating.md +51 -10
- package/dist/ai/source/BbSelect.md +56 -27
- package/dist/ai/source/BbSelectPopover.md +81 -35
- package/dist/ai/source/BbSlider.md +111 -33
- package/dist/ai/source/BbSmoothHeight.md +16 -7
- package/dist/ai/source/BbSpinner.md +9 -3
- package/dist/ai/source/BbSwitch.md +16 -9
- package/dist/ai/source/BbSwitchGroup.md +18 -7
- package/dist/ai/source/BbTable.md +172 -38
- package/dist/ai/source/BbTabs.md +58 -40
- package/dist/ai/source/BbTabsList.md +109 -50
- package/dist/ai/source/BbTabsPanels.md +65 -31
- package/dist/ai/source/BbTabsRoot.md +35 -24
- package/dist/ai/source/BbTag.md +18 -4
- package/dist/ai/source/BbTextInput.md +20 -3
- package/dist/ai/source/BbTextarea.md +15 -1
- package/dist/ai/source/BbTimePicker.md +81 -21
- package/dist/ai/source/BbTimePickerInput.md +63 -15
- package/dist/ai/source/BbToast.md +20 -3
- package/dist/ai/source/BbToastPortal.md +21 -4
- package/dist/ai/source/BbTooltip.md +16 -8
- package/dist/ai/source/BbTree.md +10 -3
- package/dist/ai/source/ClearableButton.md +5 -1
- package/dist/ai/source/CommonField.md +65 -9
- package/dist/ai/source/CommonFieldInput.md +61 -27
- package/dist/ai/source/CommonPopover.md +17 -6
- package/dist/ai/source/CommonTimeSelector.md +21 -2
- package/dist/ai/source/ErrorIcon.md +4 -0
- package/dist/ai/source/ListBox.md +9 -1
- package/dist/ai/source/OptionsContainer.md +5 -1
- package/dist/ai/source/WarningIcon.md +4 -0
- package/dist/components/BbAccordion/BbAccordion.vue.d.ts +2 -1
- package/dist/components/BbAccordion/BbAccordion.vue_vue_type_script_setup_true_lang.js +6 -6
- package/dist/components/BbAlert/BbAlert.vue.d.ts +2 -1
- package/dist/components/BbAlert/BbAlert.vue_vue_type_script_setup_true_lang.js +10 -10
- package/dist/components/BbAsterisk/BbAsterisk.vue.d.ts +3 -1
- package/dist/components/BbAvatar/BbAvatar.vue.d.ts +3 -1
- package/dist/components/BbAvatar/BbAvatar.vue_vue_type_script_setup_true_lang.js +7 -7
- package/dist/components/BbBadge/BbBadge.vue.d.ts +5 -3
- package/dist/components/BbBadge/BbBadge.vue_vue_type_script_setup_true_lang.js +7 -7
- package/dist/components/BbBadge/BbBadgeButton.vue.d.ts +3 -1
- package/dist/components/BbBadge/BbBadgeButton.vue_vue_type_script_setup_true_lang.js +7 -7
- package/dist/components/BbBaseButton/BbBaseButton.vue.d.ts +3 -1
- package/dist/components/BbBaseButton/BbBaseButton.vue_vue_type_script_setup_true_lang.js +85 -85
- package/dist/components/BbBaseButton/types.d.ts +8 -5
- package/dist/components/BbBaseButton/useLinkState.d.ts +2 -0
- package/dist/components/BbBaseButton/useLinkState.js +21 -20
- package/dist/components/BbBaseCheckboxIcon/BbBaseCheckboxIcon.vue.d.ts +3 -1
- package/dist/components/BbBaseRadioIcon/BbBaseRadioIcon.vue.d.ts +3 -1
- package/dist/components/BbBaseSwitchIcon/BbBaseSwitchIcon.vue.d.ts +3 -1
- package/dist/components/BbBreadcrumbs/BbBreadcrumbs.vue.d.ts +3 -1
- package/dist/components/BbBreadcrumbs/BbBreadcrumbs.vue_vue_type_script_setup_true_lang.js +7 -7
- package/dist/components/BbButton/BbButton.vue.d.ts +2 -1
- package/dist/components/BbButton/BbButton.vue_vue_type_script_setup_true_lang.js +93 -93
- package/dist/components/BbButton/types.d.ts +7 -4
- package/dist/components/BbCalendar/BbCalendar.vue.d.ts +157 -30
- package/dist/components/BbCalendar/BbCalendar.vue_vue_type_script_setup_true_lang.js +364 -331
- package/dist/components/BbCalendar/CalendarMonthPanel.vue_vue_type_script_setup_true_lang.js +5 -5
- package/dist/components/BbCalendar/types.d.ts +36 -8
- package/dist/components/BbCalendar/useCalendarGrid.d.ts +133 -0
- package/dist/components/BbCalendar/useCalendarGrid.js +193 -183
- package/dist/components/BbCalendar/useDayGrid.d.ts +24 -19
- package/dist/components/BbCalendar/useDayGrid.js +105 -102
- package/dist/components/BbCheckbox/BbCheckbox.vue.d.ts +4 -2
- package/dist/components/BbCheckboxGroup/BbCheckboxGroup.vue.d.ts +327 -2
- package/dist/components/BbCollapsible/BbCollapsible.vue.d.ts +3 -1
- package/dist/components/BbCollapsible/BbCollapsible.vue_vue_type_script_setup_true_lang.js +6 -6
- package/dist/components/BbColorInput/BbColorInput.vue.d.ts +8 -5
- package/dist/components/BbColorInput/BbColorInput.vue_vue_type_script_setup_true_lang.js +5 -5
- package/dist/components/BbColorInput/types.d.ts +2 -0
- package/dist/components/BbColorPalette/BbColorPalette.vue.d.ts +7 -5
- package/dist/components/BbColorPalette/BbColorPalette.vue_vue_type_script_setup_true_lang.js +216 -215
- package/dist/components/BbConfirm/BbConfirm.vue_vue_type_script_setup_true_lang.js +25 -25
- package/dist/components/BbDatePicker/BbDatePicker.vue.d.ts +206 -41
- package/dist/components/BbDatePicker/BbDatePicker.vue_vue_type_script_setup_true_lang.js +112 -106
- package/dist/components/BbDatePicker/types.d.ts +27 -8
- package/dist/components/BbDatePickerInput/BbDatePickerInput.vue.d.ts +519 -37
- package/dist/components/BbDatePickerInput/BbDatePickerInput.vue_vue_type_script_setup_true_lang.js +11 -8
- package/dist/components/BbDatePickerInput/types.d.ts +31 -9
- package/dist/components/BbDialog/BbDialog.vue.d.ts +6 -5
- package/dist/components/BbDialog/BbDialog.vue_vue_type_script_setup_true_lang.js +231 -233
- package/dist/components/BbDialog/types.d.ts +7 -7
- package/dist/components/BbDialog/useDialogStack.d.ts +2 -0
- package/dist/components/BbDialog/useDialogStack.js +6 -2
- package/dist/components/BbDropdown/AdaptiveDropdown.vue_vue_type_script_setup_true_lang.js +25 -25
- package/dist/components/BbDropdown/BbDropdown.vue.d.ts +8 -6
- package/dist/components/BbDropdown/BbDropdown.vue_vue_type_script_setup_true_lang.js +226 -225
- package/dist/components/BbDropdown/BbDropdownList.vue_vue_type_script_setup_true_lang.js +49 -49
- package/dist/components/BbDropdown/DropdownPipelineResolver.vue_vue_type_script_setup_true_lang.js +7 -7
- package/dist/components/BbDropdown/normalizeGroups.js +14 -14
- package/dist/components/BbDropdown/types.d.ts +5 -5
- package/dist/components/BbDropdown/useDropdownContext.js +1 -1
- package/dist/components/BbDropdown/useDropdownGroupRegistry.d.ts +1 -1
- package/dist/components/BbDropdownButton/BbDropdownButton.vue.d.ts +6 -4
- package/dist/components/BbDropdownButton/BbDropdownButton.vue_vue_type_script_setup_true_lang.js +36 -38
- package/dist/components/BbDropdownButton/types.js +4 -4
- package/dist/components/BbDropzone/BbDropzone.vue.d.ts +57 -22
- package/dist/components/BbDropzone/BbDropzone.vue_vue_type_script_setup_true_lang.js +4 -4
- package/dist/components/BbDropzone/types.d.ts +16 -4
- package/dist/components/BbForm/BbForm.vue.d.ts +52 -4
- package/dist/components/BbForm/BbForm.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/BbHost/BbHost.vue_vue_type_script_setup_true_lang.js +19 -23
- package/dist/components/BbHost/BbHostOpening.js +1 -1
- package/dist/components/BbHoverCard/BbHoverCard.vue.d.ts +5 -4
- package/dist/components/BbHoverCard/BbHoverCard.vue_vue_type_script_setup_true_lang.js +116 -116
- package/dist/components/BbIcon/BbIcon.vue.d.ts +3 -1
- package/dist/components/BbIcon/BbIcon.vue_vue_type_script_setup_true_lang.js +7 -7
- package/dist/components/BbIndicator/BbIndicator.vue.d.ts +3 -1
- package/dist/components/BbNumberInput/BbNumberInput.vue.d.ts +6 -3
- package/dist/components/BbNumberInput/types.d.ts +2 -0
- package/dist/components/BbOffCanvas/BbOffCanvas.vue.d.ts +5 -4
- package/dist/components/BbOffCanvas/BbOffCanvas.vue_vue_type_script_setup_true_lang.js +366 -369
- package/dist/components/BbOffCanvas/sheetAttrs.d.ts +9 -0
- package/dist/components/BbOffCanvas/sheetAttrs.js +10 -0
- package/dist/components/BbOffCanvas/types.d.ts +7 -7
- package/dist/components/BbOffCanvas/useOffCanvasStack.d.ts +2 -0
- package/dist/components/BbOffCanvas/useOffCanvasStack.js +7 -3
- package/dist/components/BbPagination/BbPagination.vue.d.ts +2 -1
- package/dist/components/BbPagination/BbPagination.vue_vue_type_script_setup_true_lang.js +8 -8
- package/dist/components/BbPagination/types.d.ts +5 -5
- package/dist/components/BbPopover/BbPopover.vue.d.ts +5 -4
- package/dist/components/BbPopover/BbPopover.vue_vue_type_script_setup_true_lang.js +92 -91
- package/dist/components/BbProgress/BbProgress.vue.d.ts +6 -1
- package/dist/components/BbRadio/BbRadio.vue.d.ts +4 -2
- package/dist/components/BbRadioGroup/BbRadioGroup.vue.d.ts +281 -1
- package/dist/components/BbRating/BbRating.vue.d.ts +4 -2
- package/dist/components/BbRating/BbRating.vue_vue_type_script_setup_true_lang.js +7 -7
- package/dist/components/BbSelect/BbSelect.vue.d.ts +575 -4
- package/dist/components/BbSelect/BbSelect.vue_vue_type_script_setup_true_lang.js +7 -7
- package/dist/components/BbSelect/types.d.ts +12 -2
- package/dist/components/BbSelectPopover/BbSelectPopover.vue.d.ts +105 -3
- package/dist/components/BbSelectPopover/BbSelectPopover.vue_vue_type_script_setup_true_lang.js +688 -685
- package/dist/components/BbSelectPopover/types.d.ts +9 -1
- package/dist/components/BbSlider/BbSlider.vue.d.ts +135 -33
- package/dist/components/BbSlider/BbSlider.vue_vue_type_script_setup_true_lang.js +5 -5
- package/dist/components/BbSlider/types.d.ts +19 -4
- package/dist/components/BbSmoothHeight/BbSmoothHeight.vue.d.ts +3 -1
- package/dist/components/BbSpinner/BbSpinner.vue.d.ts +3 -1
- package/dist/components/BbSwitch/BbSwitch.vue.d.ts +4 -2
- package/dist/components/BbSwitchGroup/BbSwitchGroup.vue.d.ts +131 -1
- package/dist/components/BbTable/BbTable.vue.d.ts +5 -2
- package/dist/components/BbTable/BbTable.vue_vue_type_script_setup_true_lang.js +593 -578
- package/dist/components/BbTable/types.d.ts +14 -1
- package/dist/components/BbTable/utils.d.ts +2 -1
- package/dist/components/BbTable/utils.js +37 -38
- package/dist/components/BbTabs/BbTabs.vue.d.ts +96 -2
- package/dist/components/BbTabs/BbTabs.vue_vue_type_script_setup_true_lang.js +8 -6
- package/dist/components/BbTabs/BbTabsList.vue.d.ts +11 -1
- package/dist/components/BbTabs/BbTabsList.vue_vue_type_script_setup_true_lang.js +102 -92
- package/dist/components/BbTabs/BbTabsPanels.vue.d.ts +9 -1
- package/dist/components/BbTabs/BbTabsPanels.vue_vue_type_script_setup_true_lang.js +20 -17
- package/dist/components/BbTabs/BbTabsRoot.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/BbTabs/types.d.ts +34 -23
- package/dist/components/BbTag/BbTag.vue.d.ts +5 -2
- package/dist/components/BbTag/types.d.ts +2 -0
- package/dist/components/BbTextInput/BbTextInput.vue.d.ts +195 -2
- package/dist/components/BbTextInput/BbTextInput.vue_vue_type_script_setup_true_lang.js +5 -5
- package/dist/components/BbTextInput/types.d.ts +2 -0
- package/dist/components/BbTextarea/BbTextarea.vue.d.ts +193 -2
- package/dist/components/BbTextarea/types.d.ts +2 -0
- package/dist/components/BbTimePicker/BbTimePicker.vue.d.ts +78 -38
- package/dist/components/BbTimePicker/BbTimePicker.vue_vue_type_script_setup_true_lang.js +138 -137
- package/dist/components/BbTimePicker/types.d.ts +18 -4
- package/dist/components/BbTimePickerInput/BbTimePickerInput.vue.d.ts +272 -33
- package/dist/components/BbTimePickerInput/BbTimePickerInput.vue_vue_type_script_setup_true_lang.js +16 -16
- package/dist/components/BbTimePickerInput/types.d.ts +20 -5
- package/dist/components/BbToast/BbToastMessage.vue_vue_type_script_setup_true_lang.js +6 -6
- package/dist/components/BbToast/BbToastRegion.vue_vue_type_script_setup_true_lang.js +20 -20
- package/dist/components/BbTooltip/BbTooltip.vue.d.ts +3 -2
- package/dist/components/BbTooltip/BbTooltip.vue_vue_type_script_setup_true_lang.js +109 -109
- package/dist/components/BbTree/BbTree.vue.d.ts +1 -1
- package/dist/components/ClearableButton/ClearableButton.vue.d.ts +3 -1
- package/dist/components/CloseIcon/CloseButton.vue.d.ts +3 -1
- package/dist/components/CloseIcon/CloseButton.vue.js +1 -1
- package/dist/components/CommonField/CommonField.vue.d.ts +3 -1
- package/dist/components/CommonFieldInput/CommonFieldInput.vue.d.ts +5 -3
- package/dist/components/CommonPopover/CommonPopover.vue.d.ts +5 -4
- package/dist/components/CommonPopover/CommonPopover.vue_vue_type_script_setup_true_lang.js +55 -55
- package/dist/components/ErrorIcon/ErrorIcon.vue.d.ts +3 -1
- package/dist/components/FlatListBox/FlatListBox.vue_vue_type_script_setup_true_lang.js +124 -124
- package/dist/components/GroupedListBox/GroupedListBox.vue_vue_type_script_setup_true_lang.js +71 -71
- package/dist/components/ListBox/ListBox.vue.d.ts +1 -1
- package/dist/components/OptionsContainer/OptionsContainer.vue.d.ts +1 -1
- package/dist/components/OptionsContainer/OptionsContainer.vue_vue_type_script_setup_true_lang.js +4 -4
- package/dist/components/Transitions/Slide.vue.d.ts +1 -1
- package/dist/components/WarningIcon/WarningIcon.vue.d.ts +3 -1
- package/dist/composables/autoHost.d.ts +22 -0
- package/dist/composables/autoHost.js +20 -0
- package/dist/composables/hostOpenings.d.ts +3 -3
- package/dist/composables/hostOpenings.js +1 -1
- package/dist/composables/hostRegistry.d.ts +10 -2
- package/dist/composables/hostRegistry.js +5 -3
- package/dist/composables/overlayRegistry.d.ts +1 -1
- package/dist/composables/overlayRegistry.js +2 -2
- package/dist/composables/{useBbDialogContext.d.ts → useBbDialog.d.ts} +9 -9
- package/dist/composables/{useBbDialogContext.js → useBbDialog.js} +4 -4
- package/dist/composables/{useBbDropdownContext.d.ts → useBbDropdown.d.ts} +14 -14
- package/dist/composables/{useBbDropdownContext.js → useBbDropdown.js} +2 -2
- package/dist/composables/{useBbFormContext.d.ts → useBbForm.d.ts} +8 -8
- package/dist/composables/{useBbFormContext.js → useBbForm.js} +3 -3
- package/dist/composables/useBbOffCanvas.d.ts +23 -0
- package/dist/composables/{useBbOffCanvasContext.js → useBbOffCanvas.js} +3 -3
- package/dist/composables/{useBbTableContext.d.ts → useBbTable.d.ts} +29 -29
- package/dist/composables/{useBbTableContext.js → useBbTable.js} +2 -2
- package/dist/composables/{useBbTabsContext.d.ts → useBbTabs.d.ts} +19 -3
- package/dist/composables/useBbTabs.js +266 -0
- package/dist/composables/useConfirm.d.ts +6 -7
- package/dist/composables/useConfirm.js +1 -1
- package/dist/composables/useOnDemandOpener.d.ts +4 -4
- package/dist/composables/useOnDemandOpener.js +1 -1
- package/dist/composables/useToast.d.ts +4 -5
- package/dist/composables/useToast.js +1 -1
- package/dist/directives/bbDialog.d.ts +1 -1
- package/dist/directives/bbDropdown.js +3 -3
- package/dist/directives/bbOffCanvas.d.ts +1 -1
- package/dist/directives/overlayTrigger.js +18 -18
- package/dist/index.d.ts +15 -15
- package/dist/index.js +55 -55
- package/dist/llms-full.txt +4355 -2761
- package/dist/llms-medium.txt +127 -93
- package/dist/llms.txt +12 -12
- package/dist/nuxt-auto-imports.js +6 -6
- package/dist/nuxt.js +1 -1
- package/dist/plugin.js +30 -28
- package/dist/runtime/nuxt-plugin.js +30 -28
- package/dist/styles.css +2 -2
- package/dist/types/ShapeErased.d.ts +15 -0
- package/dist/types/fallthrough.d.ts +134 -0
- package/dist/utilities/functions/normalizeDateBound.d.ts +7 -5
- package/dist/utilities/functions/normalizeDateBound.js +9 -9
- package/dist/utils/versionCheck.js +1 -1
- package/llms.txt +12 -12
- package/package.json +1 -1
- package/scripts/lib/adoption-checklist.json +2 -1
- package/scripts/lib/css-class-surface.mjs +39 -3
- package/scripts/lib/eslint-disable.mjs +9 -1
- package/scripts/lib/eslint-plugin.d.ts +7 -1
- package/scripts/lib/eslint-plugin.mjs +280 -3
- package/scripts/lib/form-v-model.mjs +2 -2
- package/scripts/lib/helper-canon.mjs +34 -2
- package/scripts/lib/helpers-add.mjs +80 -13
- package/scripts/lib/hidden-label-placeholder.mjs +138 -0
- package/scripts/lib/html-attributes.mjs +82 -0
- package/scripts/lib/idiom-scan.mjs +175 -2
- package/scripts/lib/portal-names.mjs +3 -3
- package/scripts/lib/prefer-v-bb-dialog.mjs +1 -1
- package/scripts/lib/tab-links.mjs +209 -0
- package/scripts/lib/token-color-mix.mjs +114 -0
- package/scripts/lib/toolchain-check.mjs +34 -3
- package/scripts/lib/unstyled-variants.mjs +57 -0
- package/scripts/lib/validate-bb-markup.mjs +72 -1
- package/dist/composables/useBbOffCanvasContext.d.ts +0 -23
- package/dist/composables/useBbTabsContext.js +0 -252
|
@@ -27,7 +27,6 @@ Sibling recipes: [Nuxt](../nuxt/approvals-inbox.md) ·
|
|
|
27
27
|
those files before anything below, and do not hand-roll replacements —
|
|
28
28
|
the peek stack, the close semantics and the sidebar's out-of-flow
|
|
29
29
|
behaviour are all load-bearing here.
|
|
30
|
-
- `<BbHost />` mounted once in the app root (`App.vue`) — never in a page.
|
|
31
30
|
- Each toast and alert variant's icon set once in the build config; the
|
|
32
31
|
code below passes no `icon` for them:
|
|
33
32
|
`toastVariants: { success: { icon: 'lucide:circle-check' }, destructive: { icon: 'lucide:circle-x' } }`
|
|
@@ -47,7 +46,7 @@ Sibling recipes: [Nuxt](../nuxt/approvals-inbox.md) ·
|
|
|
47
46
|
|
|
48
47
|
- **Highlight drives the peek, not a click handler.** The table gets
|
|
49
48
|
`keyboard-navigation`; `ctx.table.highlighted` (the coopted table
|
|
50
|
-
|
|
49
|
+
handle, seeded with `highlighted: null` because highlight is opt-in) is
|
|
51
50
|
watched in `context.ts`, and every highlight change replaces the
|
|
52
51
|
sidebar's stack with that expense — a click, or Enter on a focused row,
|
|
53
52
|
opens it with zero markup in `Index.vue`. Arrows only move focus (the
|
|
@@ -59,7 +58,7 @@ Sibling recipes: [Nuxt](../nuxt/approvals-inbox.md) ·
|
|
|
59
58
|
`{ all, unselected, filters }` instead of the ids, and `selectedCount`
|
|
60
59
|
(the total minus the unticked rows) is what the bar and the dialog show.
|
|
61
60
|
- **One coopting page context.** `provideApprovalsInbox()` joins the
|
|
62
|
-
page-shell stack and the table
|
|
61
|
+
page-shell stack and the table handle once, owns filters/tab and when
|
|
63
62
|
the dialogs open, and exposes complete actions. Every leaf calls `useApprovalsInbox()` and
|
|
64
63
|
nothing else.
|
|
65
64
|
- **Three dispatch surfaces, one set of actions.** Approve / reject /
|
|
@@ -79,9 +78,10 @@ Sibling recipes: [Nuxt](../nuxt/approvals-inbox.md) ·
|
|
|
79
78
|
- **Clicking a submitter's name always stacks**, from a row or from inside
|
|
80
79
|
the expense peek — the back arrow appears once the stack is two deep,
|
|
81
80
|
exactly the "peek vs stack" grammar of the flagship.
|
|
82
|
-
- **
|
|
83
|
-
|
|
84
|
-
|
|
81
|
+
- **The status strip is a URL filter with live counts**, a `BbRadioGroup` with
|
|
82
|
+
the tabs look (`variant="pill"`): one value over one table, so radios, not a
|
|
83
|
+
tablist (`Needs approval` / `Approved` / `Rejected` / `All`), same shape as
|
|
84
|
+
every other workspace in the folder.
|
|
85
85
|
- **Buttons are `md` by default**; `sm`/`xs` apply only where the doctrine
|
|
86
86
|
allows it — table rows, the peek footers, the bulk bar, the shortcut
|
|
87
87
|
bar.
|
|
@@ -124,13 +124,13 @@ Chrome assumed from the guides: [App Layout](../../guides/app-layout.md)
|
|
|
124
124
|
| 3 | Filter by category | filter rail pill | `BbSelectPopover` multiple |
|
|
125
125
|
| 4 | Quick filter: amount over | filter rail pill | `BbSelectPopover` single, preset thresholds |
|
|
126
126
|
| 5 | Clear filters | rail right (only when active) | context `clearFilters()` |
|
|
127
|
-
| 6 | Switch tab |
|
|
127
|
+
| 6 | Switch tab | URL status strip with counts | URL + fetch dependency |
|
|
128
128
|
| 7 | Arrow through rows | `keyboard-navigation` roving tabindex | table's own Arrow/Home/End |
|
|
129
129
|
| 8 | Preview an expense | highlight a row (click, Enter/Space, arrow-then-Enter) | `ctx.table.highlighted` watcher → `peekExpense` (replace) |
|
|
130
130
|
| 9 | Approve (one click) | row icon button, peek footer, key `A` | `approve(expense)` — API + refresh + toast |
|
|
131
131
|
| 10 | Reject with reason | row icon button, peek footer, key `R` | `v-bb-dialog` / `openReject` → `RejectDialog` (required `BbTextarea`) |
|
|
132
132
|
| 11 | Snooze | row icon button, peek footer, key `S` | `v-bb-dialog` / `openSnooze` → `SnoozeDialog` (`BbDatePickerInput`) |
|
|
133
|
-
| 12 | Select rows / select all | table checkboxes | table
|
|
133
|
+
| 12 | Select rows / select all | table checkboxes | table handle |
|
|
134
134
|
| 13 | Bulk approve | floating bottom panel | `bulkApprove()`: the ids, or `{ all, unselected, filters }` |
|
|
135
135
|
| 14 | Bulk reject with reason | floating bottom panel | `v-bb-dialog` → `BulkRejectDialog`, destructive |
|
|
136
136
|
| 15 | Stack a submitter | submitter cell / peek property | `stackSubmitter(id)` → shell stack, back arrow |
|
|
@@ -161,13 +161,14 @@ import {
|
|
|
161
161
|
type InjectionKey,
|
|
162
162
|
type Ref,
|
|
163
163
|
} from 'vue';
|
|
164
|
+
import { useRoute, useRouter } from 'vue-router';
|
|
164
165
|
import { useMagicKeys, whenever } from '@vueuse/core';
|
|
165
166
|
import {
|
|
166
|
-
|
|
167
|
-
|
|
167
|
+
useBbDialog,
|
|
168
|
+
useBbTable,
|
|
168
169
|
useConfirm,
|
|
169
170
|
useToast,
|
|
170
|
-
type
|
|
171
|
+
type BbTableHandle,
|
|
171
172
|
type BbTableItemsContext,
|
|
172
173
|
} from 'bitboss-ui';
|
|
173
174
|
import {
|
|
@@ -214,7 +215,7 @@ export const CATEGORY_OPTIONS = (
|
|
|
214
215
|
).map((value) => ({ value, text: CATEGORY_LABEL[value] }));
|
|
215
216
|
|
|
216
217
|
export interface ApprovalsFilters {
|
|
217
|
-
search: string;
|
|
218
|
+
search: string | null;
|
|
218
219
|
submitterId: number | null;
|
|
219
220
|
categories: ExpenseCategory[];
|
|
220
221
|
/** Preset threshold from the quick filter (`50`, `100`, `250`…), or `null`. */
|
|
@@ -222,9 +223,9 @@ export interface ApprovalsFilters {
|
|
|
222
223
|
}
|
|
223
224
|
|
|
224
225
|
export interface ApprovalsInboxContext {
|
|
225
|
-
// -- Coopted contexts
|
|
226
|
+
// -- Coopted contexts and handles ------------------------------------------
|
|
226
227
|
shell: PageShellContext<PeekItem>;
|
|
227
|
-
table:
|
|
228
|
+
table: BbTableHandle;
|
|
228
229
|
// -- Page-owned state --------------------------------------------------------
|
|
229
230
|
filters: ApprovalsFilters;
|
|
230
231
|
hasActiveFilters: ComputedRef<boolean>;
|
|
@@ -270,13 +271,27 @@ const isInteractiveElementFocused = (): boolean => {
|
|
|
270
271
|
|
|
271
272
|
export function provideApprovalsInbox(): ApprovalsInboxContext {
|
|
272
273
|
const { toast } = useToast();
|
|
274
|
+
// A write that fails tells the user instead of escaping as an
|
|
275
|
+
// `Uncaught (in promise)`: the action resolves, the page stays as it was.
|
|
276
|
+
const failSoft =
|
|
277
|
+
<A extends unknown[]>(action: (...args: A) => Promise<unknown>) =>
|
|
278
|
+
async (...args: A) => {
|
|
279
|
+
try {
|
|
280
|
+
await action(...args);
|
|
281
|
+
} catch {
|
|
282
|
+
toast({
|
|
283
|
+
title: 'That did not go through. Try again.',
|
|
284
|
+
variant: 'destructive',
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
};
|
|
273
288
|
const { confirm } = useConfirm();
|
|
274
289
|
|
|
275
|
-
// -- Coopt the
|
|
290
|
+
// -- Coopt the shell and the table handle: once, for the whole page. -------
|
|
276
291
|
const shell = usePageShellContext<PeekItem>();
|
|
277
292
|
// Highlight is opt-in: seeding it with `null` switches it on. Unseeded, a
|
|
278
293
|
// row click highlights nothing and the peek never opens.
|
|
279
|
-
const table =
|
|
294
|
+
const table = useBbTable('approvals-table', {
|
|
280
295
|
perPage: 25,
|
|
281
296
|
highlighted: null,
|
|
282
297
|
});
|
|
@@ -290,12 +305,21 @@ export function provideApprovalsInbox(): ApprovalsInboxContext {
|
|
|
290
305
|
});
|
|
291
306
|
const hasActiveFilters = computed(
|
|
292
307
|
() =>
|
|
293
|
-
filters.search
|
|
308
|
+
!!filters.search ||
|
|
294
309
|
filters.submitterId !== null ||
|
|
295
310
|
filters.categories.length > 0 ||
|
|
296
311
|
filters.amountOver !== null
|
|
297
312
|
);
|
|
298
|
-
|
|
313
|
+
// The tab lives in `?tab=`: seeded from it, mirrored back with `replace`
|
|
314
|
+
// (a filter pick is not a history entry), the other query keys kept.
|
|
315
|
+
const route = useRoute();
|
|
316
|
+
const router = useRouter();
|
|
317
|
+
const tab = ref<ApprovalsTab>(
|
|
318
|
+
(route.query.tab as ApprovalsTab | undefined) ?? 'needsApproval'
|
|
319
|
+
);
|
|
320
|
+
watch(tab, (next) => {
|
|
321
|
+
void router.replace({ query: { ...route.query, tab: next } });
|
|
322
|
+
});
|
|
299
323
|
const tabCounts = ref<Record<ApprovalsTab, number>>({
|
|
300
324
|
needsApproval: 0,
|
|
301
325
|
approved: 0,
|
|
@@ -306,9 +330,9 @@ export function provideApprovalsInbox(): ApprovalsInboxContext {
|
|
|
306
330
|
// The page owns WHEN its dialogs open (row actions, the peek, the
|
|
307
331
|
// shortcuts) through these handles; each dialog is opened by id and reads
|
|
308
332
|
// its subject as `data`, so no open-state refs live here.
|
|
309
|
-
const rejectDialog =
|
|
310
|
-
const snoozeDialog =
|
|
311
|
-
const bulkRejectDialog =
|
|
333
|
+
const rejectDialog = useBbDialog<Expense>('reject-expense');
|
|
334
|
+
const snoozeDialog = useBbDialog<Expense>('snooze-expense');
|
|
335
|
+
const bulkRejectDialog = useBbDialog('bulk-reject');
|
|
312
336
|
|
|
313
337
|
const clearFilters = () => {
|
|
314
338
|
filters.search = '';
|
|
@@ -319,7 +343,7 @@ export function provideApprovalsInbox(): ApprovalsInboxContext {
|
|
|
319
343
|
|
|
320
344
|
// -- Data -----------------------------------------------------------------------
|
|
321
345
|
// Cached so the keyboard shortcuts and the peek watcher can resolve a full
|
|
322
|
-
// expense from the id the table
|
|
346
|
+
// expense from the id the table handle reports.
|
|
323
347
|
const lastItems = ref<Expense[]>([]);
|
|
324
348
|
const fetchExpenses = async ({
|
|
325
349
|
signal,
|
|
@@ -400,21 +424,21 @@ export function provideApprovalsInbox(): ApprovalsInboxContext {
|
|
|
400
424
|
table.all.value = false;
|
|
401
425
|
};
|
|
402
426
|
|
|
403
|
-
const approve = async (expense: Expense) => {
|
|
427
|
+
const approve = failSoft(async (expense: Expense) => {
|
|
404
428
|
await api.expenses.approve(expense.id);
|
|
405
429
|
refresh();
|
|
406
430
|
toast({
|
|
407
431
|
title: `Approved ${expense.merchant} — $${expense.amount.toFixed(2)}.`,
|
|
408
432
|
variant: 'success',
|
|
409
433
|
});
|
|
410
|
-
};
|
|
434
|
+
});
|
|
411
435
|
|
|
412
436
|
// The R / S shortcuts open these dialogs from code; the row and peek
|
|
413
437
|
// buttons carry `v-bb-dialog` themselves.
|
|
414
438
|
const openReject = (expense: Expense) => {
|
|
415
439
|
rejectDialog.show(expense);
|
|
416
440
|
};
|
|
417
|
-
const reject = async (expense: Expense, reason: string) => {
|
|
441
|
+
const reject = failSoft(async (expense: Expense, reason: string) => {
|
|
418
442
|
await api.expenses.reject(expense.id, reason);
|
|
419
443
|
rejectDialog.hide();
|
|
420
444
|
refresh();
|
|
@@ -422,12 +446,12 @@ export function provideApprovalsInbox(): ApprovalsInboxContext {
|
|
|
422
446
|
title: `Rejected ${expense.merchant}.`,
|
|
423
447
|
variant: 'success',
|
|
424
448
|
});
|
|
425
|
-
};
|
|
449
|
+
});
|
|
426
450
|
|
|
427
451
|
const openSnooze = (expense: Expense) => {
|
|
428
452
|
snoozeDialog.show(expense);
|
|
429
453
|
};
|
|
430
|
-
const snooze = async (expense: Expense, until: string) => {
|
|
454
|
+
const snooze = failSoft(async (expense: Expense, until: string) => {
|
|
431
455
|
await api.expenses.snooze(expense.id, until);
|
|
432
456
|
snoozeDialog.hide();
|
|
433
457
|
refresh();
|
|
@@ -435,9 +459,9 @@ export function provideApprovalsInbox(): ApprovalsInboxContext {
|
|
|
435
459
|
title: `${expense.merchant} snoozed.`,
|
|
436
460
|
variant: 'success',
|
|
437
461
|
});
|
|
438
|
-
};
|
|
462
|
+
});
|
|
439
463
|
|
|
440
|
-
const bulkApprove = async () => {
|
|
464
|
+
const bulkApprove = failSoft(async () => {
|
|
441
465
|
const count = selectedCount.value;
|
|
442
466
|
await api.expenses.approveMany(bulkSelection());
|
|
443
467
|
clearSelection();
|
|
@@ -446,9 +470,9 @@ export function provideApprovalsInbox(): ApprovalsInboxContext {
|
|
|
446
470
|
title: `${count} expenses approved.`,
|
|
447
471
|
variant: 'success',
|
|
448
472
|
});
|
|
449
|
-
};
|
|
473
|
+
});
|
|
450
474
|
|
|
451
|
-
const bulkReject = async (reason: string) => {
|
|
475
|
+
const bulkReject = failSoft(async (reason: string) => {
|
|
452
476
|
const count = selectedCount.value;
|
|
453
477
|
const ok = await confirm({
|
|
454
478
|
variant: 'destructive',
|
|
@@ -466,7 +490,7 @@ export function provideApprovalsInbox(): ApprovalsInboxContext {
|
|
|
466
490
|
title: `${count} expenses rejected.`,
|
|
467
491
|
variant: 'success',
|
|
468
492
|
});
|
|
469
|
-
};
|
|
493
|
+
});
|
|
470
494
|
|
|
471
495
|
// -- Keyboard-shortcut dispatch: same actions, resolved against the row
|
|
472
496
|
// under the roving tabindex. Guarded exactly like `useDeleteCmd`.
|
|
@@ -566,32 +590,34 @@ export function useApprovalsInbox(): ApprovalsInboxContext {
|
|
|
566
590
|
<FilterRail />
|
|
567
591
|
|
|
568
592
|
<div class="flex items-center justify-between gap-2">
|
|
569
|
-
<!--
|
|
570
|
-
|
|
593
|
+
<!-- The status filter: one value over one table, so a radio group
|
|
594
|
+
with the tabs look (a tablist would promise panels). The context
|
|
595
|
+
keeps it in `?tab=`; the counts come from the server on every
|
|
596
|
+
fetch. -->
|
|
597
|
+
<BbRadioGroup
|
|
571
598
|
v-model="ctx.tab.value"
|
|
572
599
|
compact
|
|
600
|
+
hide-legend
|
|
573
601
|
:items="[
|
|
574
602
|
{
|
|
575
603
|
value: 'needsApproval',
|
|
576
604
|
label: `Needs approval · ${ctx.tabCounts.value.needsApproval}`,
|
|
577
|
-
href: '?tab=needsApproval',
|
|
578
605
|
},
|
|
579
606
|
{
|
|
580
607
|
value: 'approved',
|
|
581
608
|
label: `Approved · ${ctx.tabCounts.value.approved}`,
|
|
582
|
-
href: '?tab=approved',
|
|
583
609
|
},
|
|
584
610
|
{
|
|
585
611
|
value: 'rejected',
|
|
586
612
|
label: `Rejected · ${ctx.tabCounts.value.rejected}`,
|
|
587
|
-
href: '?tab=rejected',
|
|
588
613
|
},
|
|
589
614
|
{
|
|
590
615
|
value: 'all',
|
|
591
616
|
label: `All · ${ctx.tabCounts.value.all}`,
|
|
592
|
-
href: '?tab=all',
|
|
593
617
|
},
|
|
594
618
|
]"
|
|
619
|
+
legend="Status"
|
|
620
|
+
variant="pill"
|
|
595
621
|
/>
|
|
596
622
|
<ShortcutsHint />
|
|
597
623
|
</div>
|
|
@@ -697,8 +723,8 @@ import {
|
|
|
697
723
|
BbBreadcrumbs,
|
|
698
724
|
BbButton,
|
|
699
725
|
BbPagination,
|
|
726
|
+
BbRadioGroup,
|
|
700
727
|
BbTable,
|
|
701
|
-
BbTabs,
|
|
702
728
|
BbTextInput,
|
|
703
729
|
} from 'bitboss-ui';
|
|
704
730
|
import PageShell from '@/components/layout/PageShell.vue';
|
|
@@ -1094,7 +1120,7 @@ import {
|
|
|
1094
1120
|
BbDialog,
|
|
1095
1121
|
BbForm,
|
|
1096
1122
|
BbTextarea,
|
|
1097
|
-
|
|
1123
|
+
useBbDialog,
|
|
1098
1124
|
} from 'bitboss-ui';
|
|
1099
1125
|
import { useApprovalsInbox } from './context';
|
|
1100
1126
|
import type { Expense } from '@/types';
|
|
@@ -1103,7 +1129,7 @@ const ctx = useApprovalsInbox();
|
|
|
1103
1129
|
|
|
1104
1130
|
// The expense the opener handed over (the context closes the dialog after
|
|
1105
1131
|
// the request succeeds).
|
|
1106
|
-
const { data: expense } =
|
|
1132
|
+
const { data: expense } = useBbDialog<Expense>('reject-expense');
|
|
1107
1133
|
|
|
1108
1134
|
const reason = ref<string | null>('');
|
|
1109
1135
|
const submit = () =>
|
|
@@ -1211,14 +1237,14 @@ import {
|
|
|
1211
1237
|
BbDatePickerInput,
|
|
1212
1238
|
BbDialog,
|
|
1213
1239
|
BbForm,
|
|
1214
|
-
|
|
1240
|
+
useBbDialog,
|
|
1215
1241
|
} from 'bitboss-ui';
|
|
1216
1242
|
import { useApprovalsInbox } from './context';
|
|
1217
1243
|
import type { Expense } from '@/types';
|
|
1218
1244
|
|
|
1219
1245
|
const ctx = useApprovalsInbox();
|
|
1220
1246
|
|
|
1221
|
-
const { data: expense } =
|
|
1247
|
+
const { data: expense } = useBbDialog<Expense>('snooze-expense');
|
|
1222
1248
|
|
|
1223
1249
|
// Tomorrow as a LOCAL `YYYY-MM-DD` (`toISOString()` is the UTC date, a day
|
|
1224
1250
|
// early east of Greenwich just after midnight).
|
|
@@ -1229,9 +1255,11 @@ const tomorrow = [
|
|
|
1229
1255
|
String(next.getMonth() + 1).padStart(2, '0'),
|
|
1230
1256
|
String(next.getDate()).padStart(2, '0'),
|
|
1231
1257
|
].join('-');
|
|
1232
|
-
const until = ref(tomorrow);
|
|
1258
|
+
const until = ref<string | null>(tomorrow);
|
|
1233
1259
|
const submit = () =>
|
|
1234
|
-
expense.value
|
|
1260
|
+
expense.value && until.value
|
|
1261
|
+
? ctx.snooze(expense.value, until.value)
|
|
1262
|
+
: undefined;
|
|
1235
1263
|
</script>
|
|
1236
1264
|
```
|
|
1237
1265
|
|
|
@@ -1587,7 +1615,7 @@ const currency = new Intl.NumberFormat('en-US', {
|
|
|
1587
1615
|
`v-bb-dialog="{ id: 'reject-expense', data: expense }"` (the selection
|
|
1588
1616
|
bar's Reject `v-bb-dialog="'bulk-reject'"`), and the `R` shortcut, which
|
|
1589
1617
|
has no button, calls the context's `openReject(expense)` →
|
|
1590
|
-
`
|
|
1618
|
+
`useBbDialog<Expense>('reject-expense').show(expense)`. The dialog
|
|
1591
1619
|
reads that expense as `data`, and the context closes it with `hide()`
|
|
1592
1620
|
once the request succeeds — no open-state refs, no `v-model`, no event
|
|
1593
1621
|
for a parent to turn into `show()`. Each form is a `BbForm` whose
|
|
@@ -70,7 +70,7 @@ label state) · [Page Shell](../../guides/page-shell.md) ·
|
|
|
70
70
|
`v-model` autosave is one request per keystroke. Pickers commit on pick —
|
|
71
71
|
the click already _is_ the commit.
|
|
72
72
|
- **One coopting page context.** `provideBacklogWorkspace()` joins the
|
|
73
|
-
page-shell stack and the table
|
|
73
|
+
page-shell stack and the table handle once, owns filters/tab/overlay, and
|
|
74
74
|
exposes complete actions. Eleven components share everything through one
|
|
75
75
|
`useBacklogWorkspace()` call — zero prop drilling.
|
|
76
76
|
- **Options resolve once, at page level.** Status and priority are static
|
|
@@ -116,29 +116,29 @@ needs a modal to edit.
|
|
|
116
116
|
|
|
117
117
|
## Action inventory
|
|
118
118
|
|
|
119
|
-
| # | Action | Trigger
|
|
120
|
-
| --- | ------------------------ |
|
|
121
|
-
| 1 | New issue | topbar, the page's one `primary`
|
|
122
|
-
| 2 | Page search | topbar right
|
|
123
|
-
| 3 | Switch sprint tab |
|
|
124
|
-
| 4 | Filter by status | rail pill
|
|
125
|
-
| 5 | Filter by priority | rail pill
|
|
126
|
-
| 6 | Filter by assignee | rail pill
|
|
127
|
-
| 7 | Clear filters | rail right (only when active)
|
|
128
|
-
| 8 | Rename issue | title cell (grid)
|
|
129
|
-
| 9 | Re-estimate | estimate cell (grid)
|
|
130
|
-
| 10 | Change status | status badge (grid **and** peek)
|
|
131
|
-
| 11 | Change priority | priority badge (grid **and** peek)
|
|
132
|
-
| 12 | Reassign | assignee badge (grid **and** peek)
|
|
133
|
-
| 13 | Peek issue | issue ref cell
|
|
134
|
-
| 14 | Duplicate | row `…` dropdown
|
|
135
|
-
| 15 | Move to next sprint | row `…` **and** bulk bar
|
|
136
|
-
| 16 | Delete | row `…`, peek footer
|
|
137
|
-
| 17 | Bulk set status | bottom panel picker
|
|
138
|
-
| 18 | Bulk assign | bottom panel picker
|
|
139
|
-
| 19 | Select rows / select all | table checkboxes
|
|
140
|
-
| 20 | Open full issue | peek footer
|
|
141
|
-
| 21 | Close peek | shell chrome
|
|
119
|
+
| # | Action | Trigger | Mechanism |
|
|
120
|
+
| --- | ------------------------ | ----------------------------------- | ------------------------------------------------------ |
|
|
121
|
+
| 1 | New issue | topbar, the page's one `primary` | navigation (`/issues/new`) |
|
|
122
|
+
| 2 | Page search | topbar right | `filters.search` → fetch dependency |
|
|
123
|
+
| 3 | Switch sprint tab | a URL status strip with live counts | URL + fetch dependency |
|
|
124
|
+
| 4 | Filter by status | rail pill | `BbSelectPopover` multiple over the static catalog |
|
|
125
|
+
| 5 | Filter by priority | rail pill | `BbSelectPopover` multiple over the static catalog |
|
|
126
|
+
| 6 | Filter by assignee | rail pill | the shared people provider, single select |
|
|
127
|
+
| 7 | Clear filters | rail right (only when active) | context `clearFilters()` |
|
|
128
|
+
| 8 | Rename issue | title cell (grid) | commit-on-blur `@change` → `persistField('title')` |
|
|
129
|
+
| 9 | Re-estimate | estimate cell (grid) | commit-on-change number → `persistField('estimate')` |
|
|
130
|
+
| 10 | Change status | status badge (grid **and** peek) | pick = commit; spinner in the chevron (autosave cells) |
|
|
131
|
+
| 11 | Change priority | priority badge (grid **and** peek) | same grammar, its own leaf |
|
|
132
|
+
| 12 | Reassign | assignee badge (grid **and** peek) | async people search; one shared provider |
|
|
133
|
+
| 13 | Peek issue | issue ref cell | `peekIssue(id)` → shell stack |
|
|
134
|
+
| 14 | Duplicate | row `…` dropdown | context action + toast |
|
|
135
|
+
| 15 | Move to next sprint | row `…` **and** bulk bar | `moveToNextSprint` / `bulkMoveToNextSprint` |
|
|
136
|
+
| 16 | Delete | row `…`, peek footer | destructive behind `useConfirm` |
|
|
137
|
+
| 17 | Bulk set status | bottom panel picker | `bulkStatus` on `table.selected` |
|
|
138
|
+
| 18 | Bulk assign | bottom panel picker | `bulkAssign` on `table.selected` |
|
|
139
|
+
| 19 | Select rows / select all | table checkboxes | table handle |
|
|
140
|
+
| 20 | Open full issue | peek footer | navigation (`/issues/:id`) |
|
|
141
|
+
| 21 | Close peek | shell chrome | shell stack close |
|
|
142
142
|
|
|
143
143
|
Rows 8–12 are the recipe's reason to exist: five editable fields of three
|
|
144
144
|
different control kinds, each persisting itself, two of them able to be in
|
|
@@ -219,17 +219,19 @@ import {
|
|
|
219
219
|
provide,
|
|
220
220
|
reactive,
|
|
221
221
|
ref,
|
|
222
|
+
watch,
|
|
222
223
|
type ComputedRef,
|
|
223
224
|
type InjectionKey,
|
|
224
225
|
type Ref,
|
|
225
226
|
} from 'vue';
|
|
227
|
+
import { useRoute, useRouter } from 'vue-router';
|
|
226
228
|
import {
|
|
227
|
-
|
|
229
|
+
useBbTable,
|
|
228
230
|
useConfirm,
|
|
229
231
|
useToast,
|
|
230
232
|
type BadgeVariantType,
|
|
231
233
|
type BbSelectPopoverItemsContext,
|
|
232
|
-
type
|
|
234
|
+
type BbTableHandle,
|
|
233
235
|
type BbTableItemsContext,
|
|
234
236
|
} from 'bitboss-ui';
|
|
235
237
|
import {
|
|
@@ -267,7 +269,7 @@ export type IssuePatch = Partial<
|
|
|
267
269
|
export type EditableKey = keyof IssuePatch;
|
|
268
270
|
|
|
269
271
|
export interface BacklogFilters {
|
|
270
|
-
search: string;
|
|
272
|
+
search: string | null;
|
|
271
273
|
status: IssueStatus[];
|
|
272
274
|
priority: IssuePriority[];
|
|
273
275
|
/** The whole member, not an id — the pill labels itself with zero fetches. */
|
|
@@ -336,9 +338,9 @@ export const searchMembers = async ({
|
|
|
336
338
|
};
|
|
337
339
|
|
|
338
340
|
export interface BacklogWorkspaceContext {
|
|
339
|
-
// -- Coopted contexts
|
|
341
|
+
// -- Coopted contexts and handles ------------------------------------------
|
|
340
342
|
shell: PageShellContext<PeekItem>;
|
|
341
|
-
table:
|
|
343
|
+
table: BbTableHandle;
|
|
342
344
|
// -- Page-owned state ------------------------------------------------------
|
|
343
345
|
filters: BacklogFilters;
|
|
344
346
|
hasActiveFilters: ComputedRef<boolean>;
|
|
@@ -387,11 +389,25 @@ const key: InjectionKey<BacklogWorkspaceContext> = Symbol('backlog-workspace');
|
|
|
387
389
|
|
|
388
390
|
export function provideBacklogWorkspace(): BacklogWorkspaceContext {
|
|
389
391
|
const { toast } = useToast();
|
|
392
|
+
// A write that fails tells the user instead of escaping as an
|
|
393
|
+
// `Uncaught (in promise)`: the action resolves, the page stays as it was.
|
|
394
|
+
const failSoft =
|
|
395
|
+
<A extends unknown[]>(action: (...args: A) => Promise<unknown>) =>
|
|
396
|
+
async (...args: A) => {
|
|
397
|
+
try {
|
|
398
|
+
await action(...args);
|
|
399
|
+
} catch {
|
|
400
|
+
toast({
|
|
401
|
+
title: 'That did not go through. Try again.',
|
|
402
|
+
variant: 'destructive',
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
};
|
|
390
406
|
const { confirm } = useConfirm();
|
|
391
407
|
|
|
392
|
-
// -- Coopt the
|
|
408
|
+
// -- Coopt the shell and the table handle: once, for the whole page. -------
|
|
393
409
|
const shell = usePageShellContext<PeekItem>();
|
|
394
|
-
const table =
|
|
410
|
+
const table = useBbTable('backlog-table', { perPage: 25 });
|
|
395
411
|
|
|
396
412
|
// -- Page state -------------------------------------------------------------
|
|
397
413
|
const filters = reactive<BacklogFilters>({
|
|
@@ -402,12 +418,21 @@ export function provideBacklogWorkspace(): BacklogWorkspaceContext {
|
|
|
402
418
|
});
|
|
403
419
|
const hasActiveFilters = computed(
|
|
404
420
|
() =>
|
|
405
|
-
filters.search
|
|
421
|
+
!!filters.search ||
|
|
406
422
|
filters.status.length > 0 ||
|
|
407
423
|
filters.priority.length > 0 ||
|
|
408
424
|
filters.assignee !== null
|
|
409
425
|
);
|
|
410
|
-
|
|
426
|
+
// The tab lives in `?tab=`: seeded from it, mirrored back with `replace`
|
|
427
|
+
// (a filter pick is not a history entry), the other query keys kept.
|
|
428
|
+
const route = useRoute();
|
|
429
|
+
const router = useRouter();
|
|
430
|
+
const tab = ref<SprintTab>(
|
|
431
|
+
(route.query.tab as SprintTab | undefined) ?? 'current'
|
|
432
|
+
);
|
|
433
|
+
watch(tab, (next) => {
|
|
434
|
+
void router.replace({ query: { ...route.query, tab: next } });
|
|
435
|
+
});
|
|
411
436
|
const tabCounts = ref<Record<SprintTab, number>>({
|
|
412
437
|
backlog: 0,
|
|
413
438
|
current: 0,
|
|
@@ -517,7 +542,7 @@ export function provideBacklogWorkspace(): BacklogWorkspaceContext {
|
|
|
517
542
|
|
|
518
543
|
// -- Data ---------------------------------------------------------------------
|
|
519
544
|
// The one place the list is fetched. Writes the paging totals into the
|
|
520
|
-
// table
|
|
545
|
+
// table handle, keeps the tab counts live, and — the autosave subtlety —
|
|
521
546
|
// retires the overlay.
|
|
522
547
|
// The filters as the api takes them. The assignee pill holds the WHOLE
|
|
523
548
|
// member; the wire takes its id, and `'none'` is "unassigned" (`id: null`),
|
|
@@ -584,25 +609,25 @@ export function provideBacklogWorkspace(): BacklogWorkspaceContext {
|
|
|
584
609
|
refreshKey.value++;
|
|
585
610
|
};
|
|
586
611
|
|
|
587
|
-
const duplicateIssue = async (issue: Issue) => {
|
|
612
|
+
const duplicateIssue = failSoft(async (issue: Issue) => {
|
|
588
613
|
const copy = await api.issues.duplicate(issue.id);
|
|
589
614
|
refresh();
|
|
590
615
|
toast({
|
|
591
616
|
title: `Duplicated as ${copy.ref}.`,
|
|
592
617
|
variant: 'success',
|
|
593
618
|
});
|
|
594
|
-
};
|
|
619
|
+
});
|
|
595
620
|
|
|
596
|
-
const moveToNextSprint = async (issue: Issue) => {
|
|
621
|
+
const moveToNextSprint = failSoft(async (issue: Issue) => {
|
|
597
622
|
await api.issues.moveToNextSprint([issue.id]);
|
|
598
623
|
refresh();
|
|
599
624
|
toast({
|
|
600
625
|
title: `${issue.ref} moved to Sprint 25.`,
|
|
601
626
|
variant: 'success',
|
|
602
627
|
});
|
|
603
|
-
};
|
|
628
|
+
});
|
|
604
629
|
|
|
605
|
-
const deleteIssue = async (issue: Issue) => {
|
|
630
|
+
const deleteIssue = failSoft(async (issue: Issue) => {
|
|
606
631
|
const ok = await confirm({
|
|
607
632
|
variant: 'destructive',
|
|
608
633
|
title: 'Delete issue',
|
|
@@ -617,9 +642,9 @@ export function provideBacklogWorkspace(): BacklogWorkspaceContext {
|
|
|
617
642
|
title: `${issue.ref} deleted.`,
|
|
618
643
|
variant: 'success',
|
|
619
644
|
});
|
|
620
|
-
};
|
|
645
|
+
});
|
|
621
646
|
|
|
622
|
-
// Bulk actions read and clear the coopted table
|
|
647
|
+
// Bulk actions read and clear the coopted table handle themselves. The
|
|
623
648
|
// header checkbox is BbTable's "all across pages" select-all: it enumerates
|
|
624
649
|
// no ids, so the payload becomes `{ all, unselected, filters }` — what is
|
|
625
650
|
// on screen minus the exceptions — and the count is the total minus those
|
|
@@ -643,7 +668,7 @@ export function provideBacklogWorkspace(): BacklogWorkspaceContext {
|
|
|
643
668
|
table.all.value = false;
|
|
644
669
|
};
|
|
645
670
|
|
|
646
|
-
const bulkStatus = async (status: IssueStatus) => {
|
|
671
|
+
const bulkStatus = failSoft(async (status: IssueStatus) => {
|
|
647
672
|
const count = selectedCount.value;
|
|
648
673
|
await api.issues.patchMany(bulkSelection(), { status });
|
|
649
674
|
clearSelection();
|
|
@@ -653,9 +678,9 @@ export function provideBacklogWorkspace(): BacklogWorkspaceContext {
|
|
|
653
678
|
title: `${count} issues moved to ${label}.`,
|
|
654
679
|
variant: 'success',
|
|
655
680
|
});
|
|
656
|
-
};
|
|
681
|
+
});
|
|
657
682
|
|
|
658
|
-
const bulkAssign = async (assignee: Member) => {
|
|
683
|
+
const bulkAssign = failSoft(async (assignee: Member) => {
|
|
659
684
|
const count = selectedCount.value;
|
|
660
685
|
await api.issues.patchMany(bulkSelection(), { assignee });
|
|
661
686
|
clearSelection();
|
|
@@ -664,9 +689,9 @@ export function provideBacklogWorkspace(): BacklogWorkspaceContext {
|
|
|
664
689
|
title: `${count} issues assigned to ${assignee.name}.`,
|
|
665
690
|
variant: 'success',
|
|
666
691
|
});
|
|
667
|
-
};
|
|
692
|
+
});
|
|
668
693
|
|
|
669
|
-
const bulkMoveToNextSprint = async () => {
|
|
694
|
+
const bulkMoveToNextSprint = failSoft(async () => {
|
|
670
695
|
const count = selectedCount.value;
|
|
671
696
|
await api.issues.moveToNextSprint(bulkSelection());
|
|
672
697
|
clearSelection();
|
|
@@ -675,7 +700,7 @@ export function provideBacklogWorkspace(): BacklogWorkspaceContext {
|
|
|
675
700
|
title: `${count} issues moved to Sprint 25.`,
|
|
676
701
|
variant: 'success',
|
|
677
702
|
});
|
|
678
|
-
};
|
|
703
|
+
});
|
|
679
704
|
|
|
680
705
|
const ctx: BacklogWorkspaceContext = {
|
|
681
706
|
shell,
|
|
@@ -760,28 +785,30 @@ export function useBacklogWorkspace(): BacklogWorkspaceContext {
|
|
|
760
785
|
<div class="flex flex-col gap-3 p-4">
|
|
761
786
|
<FilterRail />
|
|
762
787
|
|
|
763
|
-
<!--
|
|
764
|
-
|
|
765
|
-
|
|
788
|
+
<!-- The sprint filter: one value over one table, so a radio group
|
|
789
|
+
with the tabs look (a tablist would promise panels). The context
|
|
790
|
+
keeps it in `?tab=`; the counts come from the server on every
|
|
791
|
+
fetch. -->
|
|
792
|
+
<BbRadioGroup
|
|
766
793
|
v-model="ctx.tab.value"
|
|
767
794
|
compact
|
|
795
|
+
hide-legend
|
|
768
796
|
:items="[
|
|
769
797
|
{
|
|
770
798
|
value: 'backlog',
|
|
771
799
|
label: `Backlog · ${ctx.tabCounts.value.backlog}`,
|
|
772
|
-
href: '?tab=backlog',
|
|
773
800
|
},
|
|
774
801
|
{
|
|
775
802
|
value: 'current',
|
|
776
803
|
label: `Current sprint · ${ctx.tabCounts.value.current}`,
|
|
777
|
-
href: '?tab=current',
|
|
778
804
|
},
|
|
779
805
|
{
|
|
780
806
|
value: 'done',
|
|
781
807
|
label: `Done · ${ctx.tabCounts.value.done}`,
|
|
782
|
-
href: '?tab=done',
|
|
783
808
|
},
|
|
784
809
|
]"
|
|
810
|
+
legend="Sprint"
|
|
811
|
+
variant="pill"
|
|
785
812
|
/>
|
|
786
813
|
|
|
787
814
|
<BbTable
|
|
@@ -886,7 +913,7 @@ export function useBacklogWorkspace(): BacklogWorkspaceContext {
|
|
|
886
913
|
</template>
|
|
887
914
|
</BbTable>
|
|
888
915
|
|
|
889
|
-
<!-- Joins the table
|
|
916
|
+
<!-- Joins the table by id: no page/totalPages wiring at all. -->
|
|
890
917
|
<BbPagination label="Backlog pagination" table-id="backlog-table" />
|
|
891
918
|
</div>
|
|
892
919
|
|
|
@@ -913,11 +940,11 @@ import { computed } from 'vue';
|
|
|
913
940
|
import {
|
|
914
941
|
BbBaseButton,
|
|
915
942
|
BbBreadcrumbs,
|
|
916
|
-
BbIcon,
|
|
917
943
|
BbButton,
|
|
944
|
+
BbIcon,
|
|
918
945
|
BbPagination,
|
|
946
|
+
BbRadioGroup,
|
|
919
947
|
BbTable,
|
|
920
|
-
BbTabs,
|
|
921
948
|
BbTextInput,
|
|
922
949
|
} from 'bitboss-ui';
|
|
923
950
|
import PageShell from '@/components/layout/PageShell.vue';
|