@vc-shell/vc-app-skill 2.0.0-alpha.33 → 2.0.0-alpha.34
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/CHANGELOG.md +78 -54
- package/README.md +42 -12
- package/package.json +4 -4
- package/runtime/VERSION +1 -1
- package/runtime/agents/api-analyzer.md +31 -16
- package/runtime/agents/blade-enhancer.md +15 -9
- package/runtime/agents/details-blade-generator.md +47 -31
- package/runtime/agents/list-blade-generator.md +21 -37
- package/runtime/agents/locales-generator.md +3 -0
- package/runtime/agents/migration-agent.md +18 -7
- package/runtime/agents/module-analyzer.md +2 -0
- package/runtime/agents/module-assembler.md +15 -0
- package/runtime/agents/promote-agent.md +15 -4
- package/runtime/agents/type-checker.md +11 -0
- package/runtime/knowledge/docs/_BUILD_HASH.md +1 -1
- package/runtime/knowledge/docs/core/api/platform.docs.md +30 -30
- package/runtime/knowledge/docs/core/blade-navigation/blade-nav-composables.docs.md +41 -41
- package/runtime/knowledge/docs/core/composables/bladeContext/index.docs.md +12 -10
- package/runtime/knowledge/docs/core/composables/useApiClient/useApiClient.docs.md +11 -14
- package/runtime/knowledge/docs/core/composables/useAppBarMobileButtons/useAppBarMobileButtons.docs.md +35 -35
- package/runtime/knowledge/docs/core/composables/useAppBarWidget/useAppBarWidget.docs.md +35 -35
- package/runtime/knowledge/docs/core/composables/useAppInsights/useAppInsights.docs.md +15 -15
- package/runtime/knowledge/docs/core/composables/useAssets/useAssets.docs.md +21 -18
- package/runtime/knowledge/docs/core/composables/useAssetsManager/useAssetsManager.docs.md +28 -24
- package/runtime/knowledge/docs/core/composables/useAsync/useAsync.docs.md +90 -61
- package/runtime/knowledge/docs/core/composables/useBeforeUnload/useBeforeUnload.docs.md +19 -18
- package/runtime/knowledge/docs/core/composables/useBlade/useBlade.docs.md +89 -68
- package/runtime/knowledge/docs/core/composables/useBladeForm/useBladeForm.docs.md +27 -25
- package/runtime/knowledge/docs/core/composables/useBladeRegistry/useBladeRegistry.docs.md +15 -15
- package/runtime/knowledge/docs/core/composables/useBladeWidgets/index.docs.md +43 -47
- package/runtime/knowledge/docs/core/composables/useBreadcrumbs/useBreadcrumbs.docs.md +11 -11
- package/runtime/knowledge/docs/core/composables/useConnectionStatus/useConnectionStatus.docs.md +27 -15
- package/runtime/knowledge/docs/core/composables/useDashboard/useDashboard.docs.md +30 -30
- package/runtime/knowledge/docs/core/composables/useDynamicProperties/useDynamicProperties.docs.md +34 -36
- package/runtime/knowledge/docs/core/composables/useErrorHandler/useErrorHandler.docs.md +44 -23
- package/runtime/knowledge/docs/core/composables/useFunctions/useFunctions.docs.md +14 -11
- package/runtime/knowledge/docs/core/composables/useKeyboardNavigation/useKeyboardNavigation.docs.md +47 -38
- package/runtime/knowledge/docs/core/composables/useLanguages/useLanguages.docs.md +37 -28
- package/runtime/knowledge/docs/core/composables/useLoading/useLoading.docs.md +23 -17
- package/runtime/knowledge/docs/core/composables/useMenuExpanded/index.docs.md +9 -9
- package/runtime/knowledge/docs/core/composables/useMenuService/useMenuService.docs.md +42 -42
- package/runtime/knowledge/docs/core/composables/useModificationTracker/useModificationTracker.docs.md +22 -12
- package/runtime/knowledge/docs/core/composables/useNotifications/useNotifications.docs.md +33 -41
- package/runtime/knowledge/docs/core/composables/usePermissions/usePermissions.docs.md +16 -16
- package/runtime/knowledge/docs/core/composables/usePlatformLocaleSync/usePlatformLocaleSync.docs.md +28 -0
- package/runtime/knowledge/docs/core/composables/usePopup/usePopup.docs.md +32 -24
- package/runtime/knowledge/docs/core/composables/useResponsive/useResponsive.docs.md +32 -11
- package/runtime/knowledge/docs/core/composables/useSettings/useSettings.docs.md +22 -13
- package/runtime/knowledge/docs/core/composables/useSettingsMenu/useSettingsMenu.docs.md +7 -7
- package/runtime/knowledge/docs/core/composables/useSidebarState/useSidebarState.docs.md +32 -24
- package/runtime/knowledge/docs/core/composables/useSlowNetworkDetection/useSlowNetworkDetection.docs.md +21 -17
- package/runtime/knowledge/docs/core/composables/useTheme/useTheme.docs.md +24 -24
- package/runtime/knowledge/docs/core/composables/useToolbar/useToolbar.docs.md +28 -31
- package/runtime/knowledge/docs/core/composables/useUser/useUser.docs.md +43 -24
- package/runtime/knowledge/docs/core/composables/useUserManagement/useUserManagement.docs.md +68 -48
- package/runtime/knowledge/docs/core/composables/useWebVitals/useWebVitals.docs.md +19 -19
- package/runtime/knowledge/docs/core/composables/useWidgets/useWidgets.docs.md +42 -47
- package/runtime/knowledge/docs/core/directives/autofocus/autofocus.docs.md +10 -4
- package/runtime/knowledge/docs/core/directives/loading/loading.docs.md +35 -20
- package/runtime/knowledge/docs/core/notifications/notifications.docs.md +36 -35
- package/runtime/knowledge/docs/core/plugins/ai-agent/ai-agent.docs.md +38 -38
- package/runtime/knowledge/docs/core/plugins/extension-points/extension-points.docs.md +79 -62
- package/runtime/knowledge/docs/core/plugins/global-error-handler/global-error-handler.docs.md +10 -10
- package/runtime/knowledge/docs/core/plugins/i18n/i18n.docs.md +21 -23
- package/runtime/knowledge/docs/core/plugins/modularity/modularity.docs.md +91 -83
- package/runtime/knowledge/docs/core/plugins/permissions/permissions.docs.md +10 -16
- package/runtime/knowledge/docs/core/plugins/signalR/signalR.docs.md +9 -9
- package/runtime/knowledge/docs/core/plugins/validation/validation.docs.md +65 -22
- package/runtime/knowledge/docs/core/services/services.docs.md +19 -22
- package/runtime/knowledge/docs/core/types/types.docs.md +40 -40
- package/runtime/knowledge/docs/core/utilities/date/date-utilities.docs.md +27 -27
- package/runtime/knowledge/docs/core/utilities/shared-utilities.docs.md +23 -23
- package/runtime/knowledge/docs/core/utilities/thumbnail/thumbnail.docs.md +22 -25
- package/runtime/knowledge/docs/core/utilities/utilities.docs.md +64 -64
- package/runtime/knowledge/docs/injection-keys.docs.md +52 -51
- package/runtime/knowledge/docs/modules/assets-manager/assets-manager.docs.md +9 -9
- package/runtime/knowledge/docs/shell/_internal/popup/common/popup-common.docs.md +23 -43
- package/runtime/knowledge/docs/shell/auth/ChangePasswordPage/change-password-page.docs.md +5 -5
- package/runtime/knowledge/docs/shell/auth/ForgotPasswordPage/forgot-password-page.docs.md +5 -5
- package/runtime/knowledge/docs/shell/auth/InvitePage/invite-page.docs.md +8 -7
- package/runtime/knowledge/docs/shell/auth/LoginPage/login-page.docs.md +7 -7
- package/runtime/knowledge/docs/shell/auth/ResetPasswordPage/reset-password-page.docs.md +8 -7
- package/runtime/knowledge/docs/shell/auth/sign-in/sign-in.docs.md +29 -13
- package/runtime/knowledge/docs/shell/components/change-password/change-password.docs.md +13 -16
- package/runtime/knowledge/docs/shell/components/change-password-button/change-password-button.docs.md +1 -7
- package/runtime/knowledge/docs/shell/components/error-interceptor/error-interceptor.docs.md +5 -5
- package/runtime/knowledge/docs/shell/components/language-selector/language-selector.docs.md +1 -1
- package/runtime/knowledge/docs/shell/components/logout-button/logout-button.docs.md +1 -1
- package/runtime/knowledge/docs/shell/components/notification-template/notification-template.docs.md +17 -9
- package/runtime/knowledge/docs/shell/components/settings-menu/settings-menu.docs.md +11 -17
- package/runtime/knowledge/docs/shell/components/settings-menu-item/settings-menu-item.docs.md +34 -65
- package/runtime/knowledge/docs/shell/components/sidebar/sidebar.docs.md +16 -26
- package/runtime/knowledge/docs/shell/components/theme-selector/theme-selector.docs.md +2 -2
- package/runtime/knowledge/docs/shell/components/user-dropdown-button/user-dropdown-button.docs.md +7 -9
- package/runtime/knowledge/docs/shell/dashboard/dashboard-charts/dashboard-charts.docs.md +30 -40
- package/runtime/knowledge/docs/shell/dashboard/dashboard-widget-card/dashboard-widget-card.docs.md +26 -19
- package/runtime/knowledge/docs/shell/dashboard/draggable-dashboard/draggable-dashboard.docs.md +15 -12
- package/runtime/knowledge/docs/ui/components/atoms/vc-badge/vc-badge.docs.md +15 -26
- package/runtime/knowledge/docs/ui/components/atoms/vc-banner/vc-banner.docs.md +21 -19
- package/runtime/knowledge/docs/ui/components/atoms/vc-button/vc-button.docs.md +83 -67
- package/runtime/knowledge/docs/ui/components/atoms/vc-card/vc-card.docs.md +100 -59
- package/runtime/knowledge/docs/ui/components/atoms/vc-col/vc-col.docs.md +28 -11
- package/runtime/knowledge/docs/ui/components/atoms/vc-container/vc-container.docs.md +20 -17
- package/runtime/knowledge/docs/ui/components/atoms/vc-hint/vc-hint.docs.md +26 -17
- package/runtime/knowledge/docs/ui/components/atoms/vc-icon/vc-icon.docs.md +30 -32
- package/runtime/knowledge/docs/ui/components/atoms/vc-image/vc-image.docs.md +25 -48
- package/runtime/knowledge/docs/ui/components/atoms/vc-label/vc-label.docs.md +29 -24
- package/runtime/knowledge/docs/ui/components/atoms/vc-link/vc-link.docs.md +23 -15
- package/runtime/knowledge/docs/ui/components/atoms/vc-loading/vc-loading.docs.md +22 -13
- package/runtime/knowledge/docs/ui/components/atoms/vc-progress/vc-progress.docs.md +33 -18
- package/runtime/knowledge/docs/ui/components/atoms/vc-row/vc-row.docs.md +56 -15
- package/runtime/knowledge/docs/ui/components/atoms/vc-scrollable-container/vc-scrollable-container.docs.md +28 -15
- package/runtime/knowledge/docs/ui/components/atoms/vc-skeleton/vc-skeleton.docs.md +40 -20
- package/runtime/knowledge/docs/ui/components/atoms/vc-status/vc-status.docs.md +25 -14
- package/runtime/knowledge/docs/ui/components/atoms/vc-status-icon/vc-status-icon.docs.md +40 -14
- package/runtime/knowledge/docs/ui/components/atoms/vc-tooltip/vc-tooltip.docs.md +54 -42
- package/runtime/knowledge/docs/ui/components/atoms/vc-video/vc-video.docs.md +17 -17
- package/runtime/knowledge/docs/ui/components/atoms/vc-widget/vc-widget.docs.md +21 -21
- package/runtime/knowledge/docs/ui/components/molecules/multilanguage-selector/multilanguage-selector.docs.md +23 -10
- package/runtime/knowledge/docs/ui/components/molecules/vc-accordion/vc-accordion.docs.md +55 -44
- package/runtime/knowledge/docs/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.docs.md +23 -20
- package/runtime/knowledge/docs/ui/components/molecules/vc-checkbox/vc-checkbox.docs.md +92 -65
- package/runtime/knowledge/docs/ui/components/molecules/vc-checkbox-group/vc-checkbox-group.docs.md +22 -36
- package/runtime/knowledge/docs/ui/components/molecules/vc-color-input/vc-color-input.docs.md +65 -23
- package/runtime/knowledge/docs/ui/components/molecules/vc-date-picker/vc-date-picker.docs.md +52 -73
- package/runtime/knowledge/docs/ui/components/molecules/vc-dropdown/vc-dropdown.docs.md +91 -85
- package/runtime/knowledge/docs/ui/components/molecules/vc-dropdown-panel/vc-dropdown-panel.docs.md +38 -42
- package/runtime/knowledge/docs/ui/components/molecules/vc-editor/vc-editor.docs.md +56 -73
- package/runtime/knowledge/docs/ui/components/molecules/vc-field/vc-field.docs.md +61 -27
- package/runtime/knowledge/docs/ui/components/molecules/vc-file-upload/vc-file-upload.docs.md +42 -50
- package/runtime/knowledge/docs/ui/components/molecules/vc-form/vc-form.docs.md +35 -64
- package/runtime/knowledge/docs/ui/components/molecules/vc-image-tile/vc-image-tile.docs.md +38 -41
- package/runtime/knowledge/docs/ui/components/molecules/vc-input/vc-input.docs.md +109 -131
- package/runtime/knowledge/docs/ui/components/molecules/vc-input-currency/vc-input-currency.docs.md +47 -88
- package/runtime/knowledge/docs/ui/components/molecules/vc-input-dropdown/vc-input-dropdown.docs.md +50 -64
- package/runtime/knowledge/docs/ui/components/molecules/vc-input-group/vc-input-group.docs.md +29 -24
- package/runtime/knowledge/docs/ui/components/molecules/vc-menu/vc-menu.docs.md +32 -28
- package/runtime/knowledge/docs/ui/components/molecules/vc-multivalue/vc-multivalue.docs.md +57 -65
- package/runtime/knowledge/docs/ui/components/molecules/vc-pagination/vc-pagination.docs.md +28 -26
- package/runtime/knowledge/docs/ui/components/molecules/vc-radio-button/vc-radio-button.docs.md +55 -20
- package/runtime/knowledge/docs/ui/components/molecules/vc-radio-group/vc-radio-group.docs.md +21 -35
- package/runtime/knowledge/docs/ui/components/molecules/vc-rating/vc-rating.docs.md +38 -33
- package/runtime/knowledge/docs/ui/components/molecules/vc-select/vc-select.docs.md +72 -83
- package/runtime/knowledge/docs/ui/components/molecules/vc-slider/vc-slider.docs.md +21 -16
- package/runtime/knowledge/docs/ui/components/molecules/vc-switch/vc-switch.docs.md +55 -64
- package/runtime/knowledge/docs/ui/components/molecules/vc-textarea/vc-textarea.docs.md +51 -70
- package/runtime/knowledge/docs/ui/components/molecules/vc-toast/vc-toast.docs.md +58 -57
- package/runtime/knowledge/docs/ui/components/organisms/vc-app/vc-app.docs.md +49 -26
- package/runtime/knowledge/docs/ui/components/organisms/vc-auth-layout/vc-auth-layout.docs.md +82 -28
- package/runtime/knowledge/docs/ui/components/organisms/vc-blade/vc-blade.docs.md +90 -75
- package/runtime/knowledge/docs/ui/components/organisms/vc-data-table/composables/table-composables.docs.md +99 -48
- package/runtime/knowledge/docs/ui/components/organisms/vc-data-table/vc-data-table.docs.md +548 -367
- package/runtime/knowledge/docs/ui/components/organisms/vc-dynamic-property/vc-dynamic-property.docs.md +35 -52
- package/runtime/knowledge/docs/ui/components/organisms/vc-gallery/vc-gallery.docs.md +33 -62
- package/runtime/knowledge/docs/ui/components/organisms/vc-image-upload/vc-image-upload.docs.md +17 -23
- package/runtime/knowledge/docs/ui/components/organisms/vc-popup/vc-popup.docs.md +109 -68
- package/runtime/knowledge/docs/ui/components/organisms/vc-sidebar/vc-sidebar.docs.md +82 -44
- package/runtime/knowledge/docs/ui/composables/ui-composables.docs.md +8 -8
- package/runtime/knowledge/docs/ui/composables/useDataTablePagination.docs.md +164 -0
- package/runtime/knowledge/docs/ui/composables/useDataTableSort.docs.md +34 -26
- package/runtime/knowledge/docs/ui/composables/useTableSelection.docs.md +48 -40
- package/runtime/knowledge/docs/ui/composables/useTableSort.docs.md +30 -17
- package/runtime/knowledge/docs/ui/types/ui-types.docs.md +40 -29
- package/runtime/knowledge/examples/offers-module.md +15 -13
- package/runtime/knowledge/examples/team-module.md +82 -119
- package/runtime/knowledge/examples/videos-module.md +44 -17
- package/runtime/knowledge/index.md +22 -0
- package/runtime/knowledge/migration-prompts/blade-form-migration.md +17 -8
- package/runtime/knowledge/migration-prompts/blade-props-migration.md +1 -2
- package/runtime/knowledge/migration-prompts/datatable-migration.md +801 -0
- package/runtime/knowledge/migration-prompts/icon-migration.md +97 -0
- package/runtime/knowledge/migration-prompts/manual-migration-audit.md +117 -0
- package/runtime/knowledge/migration-prompts/notifications-migration.md +8 -3
- package/runtime/knowledge/migration-prompts/nswag-migration.md +25 -29
- package/runtime/knowledge/migration-prompts/use-assets-migration.md +164 -0
- package/runtime/knowledge/migration-prompts/use-data-table-pagination-migration.md +176 -0
- package/runtime/knowledge/migration-prompts/widgets-migration.md +48 -27
- package/runtime/knowledge/patterns/assets-management.md +20 -20
- package/runtime/knowledge/patterns/blade-navigation.md +7 -14
- package/runtime/knowledge/patterns/blade-widget.md +19 -17
- package/runtime/knowledge/patterns/child-blade-flow.md +19 -7
- package/runtime/knowledge/patterns/composable-details.md +20 -50
- package/runtime/knowledge/patterns/composable-list.md +43 -31
- package/runtime/knowledge/patterns/dashboard-widget.md +14 -16
- package/runtime/knowledge/patterns/datatable-pattern.md +521 -0
- package/runtime/knowledge/patterns/details-blade-pattern.md +78 -116
- package/runtime/knowledge/patterns/extension-points-usage.md +53 -44
- package/runtime/knowledge/patterns/form-validation.md +28 -64
- package/runtime/knowledge/patterns/list-blade-pattern.md +33 -21
- package/runtime/knowledge/patterns/module-structure.md +7 -1
- package/runtime/knowledge/patterns/multilanguage-fields.md +8 -14
- package/runtime/knowledge/patterns/notification-template.md +21 -14
- package/runtime/knowledge/patterns/signalr-notifications.md +30 -32
- package/runtime/knowledge/patterns/toolbar-pattern.md +18 -20
- package/runtime/vc-app.md +241 -62
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
# Data Table Pattern
|
|
2
|
+
|
|
3
|
+
List blades use `VcDataTable` with declarative `<VcColumn>` children to render paginated, sortable, searchable data grids with optional row selection and global filters.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Quick Start
|
|
8
|
+
|
|
9
|
+
Minimal list blade with three columns, sort, search, and pagination. No filters, no selection.
|
|
10
|
+
|
|
11
|
+
### Template
|
|
12
|
+
|
|
13
|
+
```vue
|
|
14
|
+
<template>
|
|
15
|
+
<VcBlade
|
|
16
|
+
:title="title"
|
|
17
|
+
:toolbar-items="bladeToolbar"
|
|
18
|
+
width="50%"
|
|
19
|
+
>
|
|
20
|
+
<VcDataTable
|
|
21
|
+
class="tw-grow tw-basis-0"
|
|
22
|
+
:loading="loading"
|
|
23
|
+
:items="items"
|
|
24
|
+
:total-count="pagination.totalCount"
|
|
25
|
+
:pagination="pagination"
|
|
26
|
+
v-model:active-item-id="selectedItemId"
|
|
27
|
+
v-model:sort-field="sortField"
|
|
28
|
+
v-model:sort-order="sortOrder"
|
|
29
|
+
state-key="entity_list"
|
|
30
|
+
:searchable="true"
|
|
31
|
+
@row-click="onItemClick"
|
|
32
|
+
@pagination-click="pagination.goToPage"
|
|
33
|
+
@search="onSearch"
|
|
34
|
+
>
|
|
35
|
+
<VcColumn
|
|
36
|
+
id="name"
|
|
37
|
+
:title="t('MODULE.PAGES.LIST.TABLE.HEADER.NAME')"
|
|
38
|
+
:sortable="true"
|
|
39
|
+
:always-visible="true"
|
|
40
|
+
mobile-position="top-left"
|
|
41
|
+
/>
|
|
42
|
+
<VcColumn
|
|
43
|
+
id="status"
|
|
44
|
+
:title="t('MODULE.PAGES.LIST.TABLE.HEADER.STATUS')"
|
|
45
|
+
:sortable="true"
|
|
46
|
+
type="status"
|
|
47
|
+
mobile-role="status"
|
|
48
|
+
/>
|
|
49
|
+
<VcColumn
|
|
50
|
+
id="createdDate"
|
|
51
|
+
:title="t('MODULE.PAGES.LIST.TABLE.HEADER.CREATED_DATE')"
|
|
52
|
+
:sortable="true"
|
|
53
|
+
type="date-ago"
|
|
54
|
+
mobile-position="bottom-right"
|
|
55
|
+
/>
|
|
56
|
+
</VcDataTable>
|
|
57
|
+
</VcBlade>
|
|
58
|
+
</template>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Script
|
|
62
|
+
|
|
63
|
+
```vue
|
|
64
|
+
<script lang="ts" setup>
|
|
65
|
+
import { ref, computed, watch, onMounted } from "vue";
|
|
66
|
+
import { IBladeToolbar, useBlade, useDataTableSort } from "@vc-shell/framework";
|
|
67
|
+
import { useI18n } from "vue-i18n";
|
|
68
|
+
import useEntities from "../composables/useEntities";
|
|
69
|
+
|
|
70
|
+
const { openBlade, exposeToChildren, param } = useBlade();
|
|
71
|
+
const { t } = useI18n({ useScope: "global" });
|
|
72
|
+
const { getEntities, searchQuery, loading, items, pagination } = useEntities();
|
|
73
|
+
const { sortField, sortOrder, sortExpression } = useDataTableSort({
|
|
74
|
+
initialField: "createdDate",
|
|
75
|
+
initialDirection: "DESC",
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const selectedItemId = ref<string>();
|
|
79
|
+
const title = computed(() => t("MODULE.PAGES.LIST.TITLE"));
|
|
80
|
+
const bladeToolbar = ref<IBladeToolbar[]>([
|
|
81
|
+
{
|
|
82
|
+
id: "refresh",
|
|
83
|
+
icon: "lucide-refresh-cw",
|
|
84
|
+
title: computed(() => t("MODULE.PAGES.LIST.TOOLBAR.REFRESH")),
|
|
85
|
+
async clickHandler() {
|
|
86
|
+
await reload();
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
]);
|
|
90
|
+
|
|
91
|
+
watch(sortExpression, async (val) => {
|
|
92
|
+
await getEntities({ ...searchQuery.value, sort: val });
|
|
93
|
+
});
|
|
94
|
+
onMounted(async () => {
|
|
95
|
+
await reload();
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const reload = async () => {
|
|
99
|
+
await getEntities({ ...searchQuery.value, skip: pagination.skip, sort: sortExpression.value });
|
|
100
|
+
};
|
|
101
|
+
const onSearch = async (keyword: string | undefined) => {
|
|
102
|
+
await getEntities({ ...searchQuery.value, keyword, skip: 0, sort: sortExpression.value });
|
|
103
|
+
};
|
|
104
|
+
const onItemClick = (event: { data: { id?: string } }) => {
|
|
105
|
+
openBlade({
|
|
106
|
+
name: "EntityDetails",
|
|
107
|
+
param: event.data.id,
|
|
108
|
+
onOpen() {
|
|
109
|
+
selectedItemId.value = event.data.id;
|
|
110
|
+
},
|
|
111
|
+
onClose() {
|
|
112
|
+
selectedItemId.value = undefined;
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
exposeToChildren({ reload });
|
|
118
|
+
</script>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 2. Full Example
|
|
124
|
+
|
|
125
|
+
Demonstrates all major VcDataTable features: selection, global filters, pull-to-refresh, empty state, custom column body slots, and search header actions.
|
|
126
|
+
|
|
127
|
+
### Template
|
|
128
|
+
|
|
129
|
+
```vue
|
|
130
|
+
<template>
|
|
131
|
+
<VcBlade
|
|
132
|
+
:title="title"
|
|
133
|
+
:toolbar-items="toolbarItems"
|
|
134
|
+
width="50%"
|
|
135
|
+
>
|
|
136
|
+
<VcDataTable
|
|
137
|
+
v-model:active-item-id="selectedItemId"
|
|
138
|
+
v-model:sort-field="sortField"
|
|
139
|
+
v-model:sort-order="sortOrder"
|
|
140
|
+
v-model:selection="localSelection"
|
|
141
|
+
class="tw-grow tw-basis-0"
|
|
142
|
+
:loading="loading"
|
|
143
|
+
:items="items"
|
|
144
|
+
:total-count="pagination.totalCount"
|
|
145
|
+
:pagination="pagination"
|
|
146
|
+
:state-key="stateKey"
|
|
147
|
+
:searchable="true"
|
|
148
|
+
:selection-mode="multiselect ? 'multiple' : undefined"
|
|
149
|
+
:global-filters="computedGlobalFilters"
|
|
150
|
+
:pull-to-refresh="true"
|
|
151
|
+
:empty-state="{
|
|
152
|
+
icon: 'lucide-package-open',
|
|
153
|
+
title: $t('MODULE.PAGES.LIST.EMPTY.NO_ITEMS'),
|
|
154
|
+
actionLabel: $t('MODULE.PAGES.LIST.EMPTY.ADD'),
|
|
155
|
+
actionHandler: onAddItem,
|
|
156
|
+
}"
|
|
157
|
+
@row-click="onItemClick"
|
|
158
|
+
@pagination-click="pagination.goToPage"
|
|
159
|
+
@search="onSearch"
|
|
160
|
+
@filter="onFilter"
|
|
161
|
+
@pull-refresh="reload"
|
|
162
|
+
>
|
|
163
|
+
<!-- Slot for custom actions next to the search bar -->
|
|
164
|
+
<template #search-header-actions>
|
|
165
|
+
<VcButton
|
|
166
|
+
icon="lucide-sliders-horizontal"
|
|
167
|
+
variant="outline"
|
|
168
|
+
size="sm"
|
|
169
|
+
@click="toggleAdvancedView"
|
|
170
|
+
>
|
|
171
|
+
{{ $t("MODULE.PAGES.LIST.ACTIONS.TOGGLE_VIEW") }}
|
|
172
|
+
</VcButton>
|
|
173
|
+
</template>
|
|
174
|
+
|
|
175
|
+
<!-- Image column -->
|
|
176
|
+
<VcColumn
|
|
177
|
+
id="img"
|
|
178
|
+
:title="t('MODULE.PAGES.LIST.TABLE.HEADER.IMAGE')"
|
|
179
|
+
:always-visible="true"
|
|
180
|
+
mobile-role="image"
|
|
181
|
+
type="image"
|
|
182
|
+
>
|
|
183
|
+
<template #body="{ data }">
|
|
184
|
+
<img
|
|
185
|
+
:src="data.imgSrc || '/placeholder.png'"
|
|
186
|
+
class="tw-w-10 tw-h-10 tw-rounded tw-object-cover"
|
|
187
|
+
/>
|
|
188
|
+
</template>
|
|
189
|
+
</VcColumn>
|
|
190
|
+
|
|
191
|
+
<!-- Status column with custom body -->
|
|
192
|
+
<VcColumn
|
|
193
|
+
id="status"
|
|
194
|
+
:title="t('MODULE.PAGES.LIST.TABLE.HEADER.STATUS')"
|
|
195
|
+
:sortable="true"
|
|
196
|
+
:always-visible="true"
|
|
197
|
+
mobile-role="status"
|
|
198
|
+
type="status"
|
|
199
|
+
>
|
|
200
|
+
<template #body="{ data }">
|
|
201
|
+
<VcStatus :variant="statusVariant(data.status)">
|
|
202
|
+
{{ data.status }}
|
|
203
|
+
</VcStatus>
|
|
204
|
+
</template>
|
|
205
|
+
</VcColumn>
|
|
206
|
+
|
|
207
|
+
<!-- Name column -->
|
|
208
|
+
<VcColumn
|
|
209
|
+
id="name"
|
|
210
|
+
:title="t('MODULE.PAGES.LIST.TABLE.HEADER.NAME')"
|
|
211
|
+
:sortable="true"
|
|
212
|
+
:always-visible="true"
|
|
213
|
+
mobile-position="top-left"
|
|
214
|
+
/>
|
|
215
|
+
|
|
216
|
+
<!-- Date column (built-in date-ago rendering) -->
|
|
217
|
+
<VcColumn
|
|
218
|
+
id="createdDate"
|
|
219
|
+
:title="t('MODULE.PAGES.LIST.TABLE.HEADER.CREATED_DATE')"
|
|
220
|
+
:sortable="true"
|
|
221
|
+
type="date-ago"
|
|
222
|
+
/>
|
|
223
|
+
|
|
224
|
+
<!-- Plain text column -->
|
|
225
|
+
<VcColumn
|
|
226
|
+
id="sku"
|
|
227
|
+
:title="t('MODULE.PAGES.LIST.TABLE.HEADER.SKU')"
|
|
228
|
+
:always-visible="true"
|
|
229
|
+
mobile-position="bottom-left"
|
|
230
|
+
/>
|
|
231
|
+
|
|
232
|
+
<!-- Boolean status-icon column -->
|
|
233
|
+
<VcColumn
|
|
234
|
+
id="isPublished"
|
|
235
|
+
:title="t('MODULE.PAGES.LIST.TABLE.HEADER.PUBLISHED')"
|
|
236
|
+
:sortable="true"
|
|
237
|
+
mobile-position="bottom-right"
|
|
238
|
+
type="status-icon"
|
|
239
|
+
/>
|
|
240
|
+
|
|
241
|
+
<!-- Nested property via :field dot-path -->
|
|
242
|
+
<VcColumn
|
|
243
|
+
id="category"
|
|
244
|
+
:field="'metadata.category'"
|
|
245
|
+
:title="t('MODULE.PAGES.LIST.TABLE.HEADER.CATEGORY')"
|
|
246
|
+
/>
|
|
247
|
+
</VcDataTable>
|
|
248
|
+
</VcBlade>
|
|
249
|
+
</template>
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Script
|
|
253
|
+
|
|
254
|
+
```vue
|
|
255
|
+
<script lang="ts" setup>
|
|
256
|
+
import { computed, ref, watch, onMounted } from "vue";
|
|
257
|
+
import { useI18n } from "vue-i18n";
|
|
258
|
+
import { IBladeToolbar, useBlade, usePopup, useDataTableSort } from "@vc-shell/framework";
|
|
259
|
+
import useEntities from "../composables/useEntities";
|
|
260
|
+
|
|
261
|
+
const { openBlade, exposeToChildren, param } = useBlade();
|
|
262
|
+
const { t } = useI18n({ useScope: "global" });
|
|
263
|
+
const { showConfirmation } = usePopup();
|
|
264
|
+
const { getEntities, deleteEntities, searchQuery, loading, items, pagination } = useEntities();
|
|
265
|
+
|
|
266
|
+
// Sort state
|
|
267
|
+
const { sortField, sortOrder, sortExpression } = useDataTableSort({
|
|
268
|
+
initialField: "createdDate",
|
|
269
|
+
initialDirection: "DESC",
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
const selectedItemId = ref<string>();
|
|
273
|
+
const multiselect = true;
|
|
274
|
+
const stateKey = "entity_list";
|
|
275
|
+
|
|
276
|
+
// Selection binding — syncs v-model:selection with local ref
|
|
277
|
+
const localSelection = ref<Record<string, unknown>[]>([]);
|
|
278
|
+
|
|
279
|
+
watch(
|
|
280
|
+
localSelection,
|
|
281
|
+
(newSelection) => {
|
|
282
|
+
// Process selection changes (e.g., update toolbar state)
|
|
283
|
+
},
|
|
284
|
+
{ deep: true },
|
|
285
|
+
);
|
|
286
|
+
|
|
287
|
+
// Global filters configuration
|
|
288
|
+
const computedGlobalFilters = computed(() => {
|
|
289
|
+
return [
|
|
290
|
+
{
|
|
291
|
+
id: "status",
|
|
292
|
+
label: t("MODULE.PAGES.LIST.FILTERS.STATUS"),
|
|
293
|
+
filter: {
|
|
294
|
+
options: [
|
|
295
|
+
{ value: "Active", label: t("MODULE.STATUSES.ACTIVE") },
|
|
296
|
+
{ value: "Draft", label: t("MODULE.STATUSES.DRAFT") },
|
|
297
|
+
{ value: "Archived", label: t("MODULE.STATUSES.ARCHIVED") },
|
|
298
|
+
],
|
|
299
|
+
multiple: true,
|
|
300
|
+
},
|
|
301
|
+
},
|
|
302
|
+
];
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
// Status variant mapping
|
|
306
|
+
const statusVariant = (status: string | undefined) => {
|
|
307
|
+
const map: Record<string, string> = {
|
|
308
|
+
Active: "success",
|
|
309
|
+
Published: "success",
|
|
310
|
+
Draft: "warning",
|
|
311
|
+
Pending: "warning",
|
|
312
|
+
Archived: "danger",
|
|
313
|
+
Cancelled: "danger",
|
|
314
|
+
};
|
|
315
|
+
return map[status ?? ""] ?? "info";
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
// Toolbar (computed to react to selection changes)
|
|
319
|
+
const toolbarItems = computed((): IBladeToolbar[] => {
|
|
320
|
+
const items: IBladeToolbar[] = [];
|
|
321
|
+
|
|
322
|
+
items.push({
|
|
323
|
+
id: "add",
|
|
324
|
+
icon: "lucide-plus",
|
|
325
|
+
title: t("MODULE.PAGES.LIST.TOOLBAR.ADD"),
|
|
326
|
+
clickHandler: () => onAddItem(),
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
items.push({
|
|
330
|
+
id: "refresh",
|
|
331
|
+
icon: "lucide-refresh-cw",
|
|
332
|
+
title: t("MODULE.PAGES.LIST.TOOLBAR.REFRESH"),
|
|
333
|
+
clickHandler: async () => await reload(),
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
items.push({
|
|
337
|
+
id: "deleteSelected",
|
|
338
|
+
icon: "lucide-trash-2",
|
|
339
|
+
title: t("MODULE.PAGES.LIST.TOOLBAR.DELETE"),
|
|
340
|
+
disabled: localSelection.value.length === 0,
|
|
341
|
+
clickHandler: async () => {
|
|
342
|
+
if (await showConfirmation(t("MODULE.ALERTS.DELETE_SELECTED"))) {
|
|
343
|
+
const ids = localSelection.value.map((item) => item.id as string);
|
|
344
|
+
await deleteEntities({ ids });
|
|
345
|
+
localSelection.value = [];
|
|
346
|
+
await reload();
|
|
347
|
+
}
|
|
348
|
+
},
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
return items;
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
// Sort reactivity
|
|
355
|
+
watch(sortExpression, async (val) => {
|
|
356
|
+
await getEntities({ ...searchQuery.value, sort: val });
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
// Track selected row when param changes
|
|
360
|
+
watch(
|
|
361
|
+
() => param.value,
|
|
362
|
+
(newVal) => {
|
|
363
|
+
selectedItemId.value = newVal;
|
|
364
|
+
},
|
|
365
|
+
{ immediate: true, deep: true },
|
|
366
|
+
);
|
|
367
|
+
|
|
368
|
+
onMounted(async () => {
|
|
369
|
+
await getEntities({ sort: sortExpression.value });
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
const reload = async () => {
|
|
373
|
+
await getEntities({
|
|
374
|
+
...searchQuery.value,
|
|
375
|
+
skip: pagination.skip,
|
|
376
|
+
sort: sortExpression.value,
|
|
377
|
+
});
|
|
378
|
+
};
|
|
379
|
+
// No manual onPaginationClick — pagination.goToPage handles it via useDataTablePagination
|
|
380
|
+
|
|
381
|
+
const onSearch = async (keyword: string | undefined) => {
|
|
382
|
+
await getEntities({ ...searchQuery.value, keyword, skip: 0, sort: sortExpression.value });
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
// Row click handler — event wraps row data in { data }
|
|
386
|
+
const onItemClick = (event: { data: { id?: string } }) => {
|
|
387
|
+
selectedItemId.value = event.data.id;
|
|
388
|
+
openBlade({
|
|
389
|
+
name: "EntityDetails",
|
|
390
|
+
param: event.data.id,
|
|
391
|
+
onOpen() {
|
|
392
|
+
selectedItemId.value = event.data.id;
|
|
393
|
+
},
|
|
394
|
+
onClose() {
|
|
395
|
+
selectedItemId.value = undefined;
|
|
396
|
+
},
|
|
397
|
+
});
|
|
398
|
+
};
|
|
399
|
+
|
|
400
|
+
async function onFilter(event: { filters: Record<string, unknown> }) {
|
|
401
|
+
const statusFilter = event.filters.status as string[] | undefined;
|
|
402
|
+
await getEntities({
|
|
403
|
+
...searchQuery.value,
|
|
404
|
+
status: statusFilter ?? [],
|
|
405
|
+
skip: 0,
|
|
406
|
+
sort: sortExpression.value,
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
function onAddItem() {
|
|
411
|
+
openBlade({ name: "EntityDetails" });
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
function toggleAdvancedView() {
|
|
415
|
+
// Custom view toggle logic
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// Expose methods to child blades (without title)
|
|
419
|
+
exposeToChildren({
|
|
420
|
+
reload,
|
|
421
|
+
onItemClick,
|
|
422
|
+
});
|
|
423
|
+
</script>
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
## 3. VcColumn Props Reference
|
|
429
|
+
|
|
430
|
+
| Prop | Type | Description |
|
|
431
|
+
| ----------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
432
|
+
| `id` | `string` | Column identifier. Matches the item property name used to extract cell value. |
|
|
433
|
+
| `title` | `string` | Column header text. Accepts an i18n key or plain string. |
|
|
434
|
+
| `sortable` | `boolean` | Enable sorting on this column. Default `false`. |
|
|
435
|
+
| `always-visible` | `boolean` | Column cannot be hidden by the user via column settings. Default `false`. |
|
|
436
|
+
| `type` | `string` | Built-in cell renderer: `"date-ago"`, `"date-time"`, `"image"`, `"status"`, `"status-icon"`, `"money"`, `"number"`, `"date"`, `"datetime"`. |
|
|
437
|
+
| `width` | `string` | CSS width value (e.g., `"60px"`, `"120px"`, `"20%"`). |
|
|
438
|
+
| `visible` | `boolean` | Initial column visibility. Default `true`. Set `false` to hide by default (user can show via column settings). |
|
|
439
|
+
| `field` | `string` | Dot-path to nested property on the row item (e.g., `"metadata.category"`, `"productData.productType"`). Use when `id` alone cannot resolve the value. |
|
|
440
|
+
| `mobile-position` | `string` | Position in mobile card layout: `"top-left"`, `"top-right"`, `"bottom-left"`, `"bottom-right"`. |
|
|
441
|
+
| `mobile-role` | `string` | Special mobile rendering role: `"image"`, `"status"`, `"title"`, `"field"`. |
|
|
442
|
+
|
|
443
|
+
### VcColumn Slots
|
|
444
|
+
|
|
445
|
+
| Slot | Scope | Description |
|
|
446
|
+
| ------- | ---------- | ----------------------------------------------------- |
|
|
447
|
+
| `#body` | `{ data }` | Custom cell body. `data` is the full row item object. |
|
|
448
|
+
|
|
449
|
+
---
|
|
450
|
+
|
|
451
|
+
## 4. VcDataTable Props Reference
|
|
452
|
+
|
|
453
|
+
| Prop | Type | Default | Description |
|
|
454
|
+
| ------------------------ | ----------------------------------------------------------------------------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------- |
|
|
455
|
+
| `items` | `unknown[]` | `[]` | Array of row items to display. |
|
|
456
|
+
| `total-count` | `number` | `0` | Total number of items (for pagination display). |
|
|
457
|
+
| `loading` | `boolean` | `false` | Shows loading indicator overlay. |
|
|
458
|
+
| `pagination` | `UseDataTablePaginationReturn` | -- | Pagination state from `useDataTablePagination()`. Contains `currentPage`, `pages`, `totalCount`, `skip`, `goToPage()`. |
|
|
459
|
+
| `v-model:active-item-id` | `string \| undefined` | -- | Two-way binding for the highlighted/active row id. |
|
|
460
|
+
| `v-model:sort-field` | `string` | -- | Two-way binding for the currently sorted column id. |
|
|
461
|
+
| `v-model:sort-order` | `0 \| 1 \| -1` | -- | Two-way binding for sort order (1=ASC, -1=DESC, 0=none). Use `useDataTableSort()` which manages this internally. |
|
|
462
|
+
| `v-model:selection` | `unknown[]` | -- | Two-way binding for selected row items. |
|
|
463
|
+
| `state-key` | `string` | -- | Unique key for persisting column widths/order/visibility to localStorage. Use snake_case (e.g., `"entity_list"`). |
|
|
464
|
+
| `searchable` | `boolean` | `false` | Shows the search input above the table. |
|
|
465
|
+
| `selection-mode` | `"multiple" \| undefined` | `undefined` | Enables row checkboxes for multi-select. Set to `"multiple"` to enable, `undefined` to disable. |
|
|
466
|
+
| `is-row-selectable` | `(item: unknown) => boolean` | -- | Predicate to control which rows can be selected. |
|
|
467
|
+
| `global-filters` | `GlobalFilter[] \| undefined` | `undefined` | Array of filter definitions shown above the table. |
|
|
468
|
+
| `pull-to-refresh` | `boolean` | `false` | Enables mobile pull-to-refresh gesture. |
|
|
469
|
+
| `empty-state` | `{ icon: string; title: string; actionLabel?: string; actionHandler?: () => void }` | -- | Configuration for empty state display when no items. |
|
|
470
|
+
|
|
471
|
+
---
|
|
472
|
+
|
|
473
|
+
## 5. Events Reference
|
|
474
|
+
|
|
475
|
+
| Event | Payload | Description |
|
|
476
|
+
| ------------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
477
|
+
| `@row-click` | `{ data: RowItem }` | Emitted when a row is clicked. The row item is wrapped in `{ data }`. |
|
|
478
|
+
| `@pagination-click` | `number` | Emitted when a pagination page button is clicked. Payload is the target page number (1-based). |
|
|
479
|
+
| `@search` | `string \| undefined` | Emitted when the user types in the search input. Payload is the search keyword or `undefined` when cleared. |
|
|
480
|
+
| `@filter` | `{ filters: Record<string, unknown> }` | Emitted when a global filter is applied. `filters` is a map of filter id to selected values. |
|
|
481
|
+
| `@pull-refresh` | -- | Emitted when the user triggers pull-to-refresh on mobile. |
|
|
482
|
+
|
|
483
|
+
---
|
|
484
|
+
|
|
485
|
+
## 6. Key Rules
|
|
486
|
+
|
|
487
|
+
1. **Declare columns explicitly, NOT with `v-for`.** Each `<VcColumn>` must be a direct child in the template. This enables custom `#body` slots, per-column `mobile-role`/`mobile-position` attributes, and readable templates.
|
|
488
|
+
|
|
489
|
+
2. **Row click event wraps data in `{ data }`.** The `@row-click` handler receives `{ data: RowItem }`, not the raw item. Always destructure: `const onItemClick = (event: { data: { id?: string } }) => { ... }`.
|
|
490
|
+
|
|
491
|
+
3. **Use `useDataTableSort` for sort state.** It returns `sortField`, `sortOrder` (for v-model bindings), and `sortExpression` (computed `"field:DIR"` string for the API). Watch `sortExpression` to reload data when sort changes.
|
|
492
|
+
|
|
493
|
+
4. **Selection requires a local ref.** Bind `v-model:selection` to a `localSelection` ref, then watch it to sync with external selection state or toolbar actions:
|
|
494
|
+
|
|
495
|
+
```ts
|
|
496
|
+
const localSelection = ref<Item[]>([]);
|
|
497
|
+
watch(
|
|
498
|
+
localSelection,
|
|
499
|
+
(newSelection) => {
|
|
500
|
+
// Update toolbar state, selection handler, etc.
|
|
501
|
+
},
|
|
502
|
+
{ deep: true },
|
|
503
|
+
);
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
5. **`state-key` must be unique across all modules.** Use snake_case naming: `"entity_list"`, `"another_list"`, `"team_members"`.
|
|
507
|
+
|
|
508
|
+
6. **`exposeToChildren` should not include `title`.** Expose only callable methods like `reload` and `onItemClick`. The title is blade metadata, not a child-callable method.
|
|
509
|
+
|
|
510
|
+
7. **Global filters structure:** Each filter is an object with `id`, `label`, and a `filter` object containing `options` (array of `{ value, label }`) and `multiple` (boolean). Return `undefined` from the computed to hide filters entirely.
|
|
511
|
+
|
|
512
|
+
8. **Empty state requires all four properties** when you want an action button: `icon` (Lucide icon name), `title` (i18n string), `actionLabel` (button text), `actionHandler` (callback function). Omit `actionLabel` and `actionHandler` for a passive empty state.
|
|
513
|
+
|
|
514
|
+
9. **Column `type` selection rules:**
|
|
515
|
+
- Date fields: use `"date-ago"` in list blades (relative time), not `"date-time"`
|
|
516
|
+
- Boolean fields (is*, has*, can\*): use `"status-icon"`
|
|
517
|
+
- Status/state enums: use `"status"` with a custom `#body` slot containing `VcStatus`
|
|
518
|
+
- Image URLs: use `"image"` with `mobile-role="image"`
|
|
519
|
+
- Currency fields: use `"money"`
|
|
520
|
+
|
|
521
|
+
10. **`#search-header-actions` slot** renders custom buttons/controls adjacent to the search input. Use for view toggles, breadcrumbs, or additional action buttons that relate to the list as a whole.
|