@vendure/docs 0.0.0-202601161541
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/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.d.ts +3 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +857 -0
- package/dist/manifest.js.map +1 -0
- package/docs/guides/core-concepts/auth/admin-role.webp +0 -0
- package/docs/guides/core-concepts/auth/admin.webp +0 -0
- package/docs/guides/core-concepts/auth/customer.webp +0 -0
- package/docs/guides/core-concepts/auth/index.md +557 -0
- package/docs/guides/core-concepts/auth/roles.webp +0 -0
- package/docs/guides/core-concepts/channels/channel-token.webp +0 -0
- package/docs/guides/core-concepts/channels/channels.webp +0 -0
- package/docs/guides/core-concepts/channels/channels_currencies_diagram.png +0 -0
- package/docs/guides/core-concepts/channels/channels_diagram.png +0 -0
- package/docs/guides/core-concepts/channels/channels_prices_diagram.png +0 -0
- package/docs/guides/core-concepts/channels/default-currency.webp +0 -0
- package/docs/guides/core-concepts/channels/index.md +154 -0
- package/docs/guides/core-concepts/channels/variant-prices.webp +0 -0
- package/docs/guides/core-concepts/collections/collection-filters.webp +0 -0
- package/docs/guides/core-concepts/collections/collections.webp +0 -0
- package/docs/guides/core-concepts/collections/filter-inheritance.webp +0 -0
- package/docs/guides/core-concepts/collections/index.mdx +125 -0
- package/docs/guides/core-concepts/customers/customer.webp +0 -0
- package/docs/guides/core-concepts/customers/index.mdx +21 -0
- package/docs/guides/core-concepts/email/email-plugin-flow.webp +0 -0
- package/docs/guides/core-concepts/email/index.mdx +155 -0
- package/docs/guides/core-concepts/images-assets/asset-flow.webp +0 -0
- package/docs/guides/core-concepts/images-assets/asset-tags.webp +0 -0
- package/docs/guides/core-concepts/images-assets/index.mdx +42 -0
- package/docs/guides/core-concepts/money/index.mdx +246 -0
- package/docs/guides/core-concepts/orders/custom-order-ui.webp +0 -0
- package/docs/guides/core-concepts/orders/index.md +366 -0
- package/docs/guides/core-concepts/orders/order-process.webp +0 -0
- package/docs/guides/core-concepts/orders/order.webp +0 -0
- package/docs/guides/core-concepts/payment/index.md +410 -0
- package/docs/guides/core-concepts/payment/payment-method.webp +0 -0
- package/docs/guides/core-concepts/payment/payment_sequence_one_step.png +0 -0
- package/docs/guides/core-concepts/payment/payment_sequence_two_step.png +0 -0
- package/docs/guides/core-concepts/products/facets.webp +0 -0
- package/docs/guides/core-concepts/products/index.mdx +59 -0
- package/docs/guides/core-concepts/products/product-relations.webp +0 -0
- package/docs/guides/core-concepts/products/products-variants.webp +0 -0
- package/docs/guides/core-concepts/promotions/index.md +324 -0
- package/docs/guides/core-concepts/shipping/index.md +225 -0
- package/docs/guides/core-concepts/shipping/shipping-method.webp +0 -0
- package/docs/guides/core-concepts/stock-control/global-stock-control.webp +0 -0
- package/docs/guides/core-concepts/stock-control/index.md +233 -0
- package/docs/guides/core-concepts/stock-control/stock-levels.webp +0 -0
- package/docs/guides/core-concepts/taxes/index.mdx +76 -0
- package/docs/guides/deployment/deploy-to-digital-ocean-app-platform/01-create-space.webp +0 -0
- package/docs/guides/deployment/deploy-to-digital-ocean-app-platform/02-space-access-keys.webp +0 -0
- package/docs/guides/deployment/deploy-to-digital-ocean-app-platform/03-create-app.webp +0 -0
- package/docs/guides/deployment/deploy-to-digital-ocean-app-platform/04-configure-server.webp +0 -0
- package/docs/guides/deployment/deploy-to-digital-ocean-app-platform/05-open-server-settings.webp +0 -0
- package/docs/guides/deployment/deploy-to-digital-ocean-app-platform/06-admin-app-route.webp +0 -0
- package/docs/guides/deployment/deploy-to-digital-ocean-app-platform/07-open-app.webp +0 -0
- package/docs/guides/deployment/deploy-to-digital-ocean-app-platform/deploy-to-do-app-platform.webp +0 -0
- package/docs/guides/deployment/deploy-to-digital-ocean-app-platform/index.md +246 -0
- package/docs/guides/deployment/deploy-to-google-cloud-run/deploy-to-gcr.webp +0 -0
- package/docs/guides/deployment/deploy-to-google-cloud-run/index.md +53 -0
- package/docs/guides/deployment/deploy-to-northflank/01-create-template-screen.webp +0 -0
- package/docs/guides/deployment/deploy-to-northflank/02-paste-config.webp +0 -0
- package/docs/guides/deployment/deploy-to-northflank/03-run-template.webp +0 -0
- package/docs/guides/deployment/deploy-to-northflank/04-find-project.webp +0 -0
- package/docs/guides/deployment/deploy-to-northflank/05-server-service.webp +0 -0
- package/docs/guides/deployment/deploy-to-northflank/06-find-url.webp +0 -0
- package/docs/guides/deployment/deploy-to-northflank/deploy-to-northflank.webp +0 -0
- package/docs/guides/deployment/deploy-to-northflank/index.md +606 -0
- package/docs/guides/deployment/deploy-to-railway/01-new-service.webp +0 -0
- package/docs/guides/deployment/deploy-to-railway/02-env-vars.webp +0 -0
- package/docs/guides/deployment/deploy-to-railway/03-test-server.webp +0 -0
- package/docs/guides/deployment/deploy-to-railway/deploy-to-railway.webp +0 -0
- package/docs/guides/deployment/deploy-to-railway/index.md +202 -0
- package/docs/guides/deployment/deploy-to-render/01-create-db.webp +0 -0
- package/docs/guides/deployment/deploy-to-render/02-env-group.webp +0 -0
- package/docs/guides/deployment/deploy-to-render/03-db-connection.webp +0 -0
- package/docs/guides/deployment/deploy-to-render/04-link-env-group.webp +0 -0
- package/docs/guides/deployment/deploy-to-render/05-server-url.webp +0 -0
- package/docs/guides/deployment/deploy-to-render/deploy-to-render.webp +0 -0
- package/docs/guides/deployment/deploy-to-render/index.md +221 -0
- package/docs/guides/deployment/deploying-admin-ui.md +130 -0
- package/docs/guides/deployment/getting-data-into-production.md +50 -0
- package/docs/guides/deployment/horizontal-scaling.md +75 -0
- package/docs/guides/deployment/production-configuration/env-var-ui.webp +0 -0
- package/docs/guides/deployment/production-configuration/index.md +140 -0
- package/docs/guides/deployment/server-resource-requirements.md +29 -0
- package/docs/guides/deployment/using-docker.md +193 -0
- package/docs/guides/developer-guide/cache/cache-service.webp +0 -0
- package/docs/guides/developer-guide/cache/index.mdx +327 -0
- package/docs/guides/developer-guide/channel-aware/index.md +117 -0
- package/docs/guides/developer-guide/cli/add-command.webp +0 -0
- package/docs/guides/developer-guide/cli/index.md +418 -0
- package/docs/guides/developer-guide/cli/migrate-command.webp +0 -0
- package/docs/guides/developer-guide/cli/schema-command.webp +0 -0
- package/docs/guides/developer-guide/configuration/index.md +226 -0
- package/docs/guides/developer-guide/custom-fields/custom-fields-data-table.webp +0 -0
- package/docs/guides/developer-guide/custom-fields/custom-fields-ui.webp +0 -0
- package/docs/guides/developer-guide/custom-fields/index.md +1423 -0
- package/docs/guides/developer-guide/custom-permissions/index.md +186 -0
- package/docs/guides/developer-guide/custom-strategies-in-plugins/index.mdx +467 -0
- package/docs/guides/developer-guide/database-entity/index.md +136 -0
- package/docs/guides/developer-guide/dataloaders/index.md +137 -0
- package/docs/guides/developer-guide/db-subscribers/index.md +115 -0
- package/docs/guides/developer-guide/error-handling/index.mdx +324 -0
- package/docs/guides/developer-guide/events/index.mdx +406 -0
- package/docs/guides/developer-guide/extend-graphql-api/index.md +501 -0
- package/docs/guides/developer-guide/has-custom-fields/index.md +174 -0
- package/docs/guides/developer-guide/importing-data/index.md +488 -0
- package/docs/guides/developer-guide/importing-data/reindex.webp +0 -0
- package/docs/guides/developer-guide/logging/index.md +77 -0
- package/docs/guides/developer-guide/migrating-from-v1/breaking-api-changes.md +213 -0
- package/docs/guides/developer-guide/migrating-from-v1/database-migration.md +39 -0
- package/docs/guides/developer-guide/migrating-from-v1/index.md +41 -0
- package/docs/guides/developer-guide/migrating-from-v1/storefront-migration.md +30 -0
- package/docs/guides/developer-guide/migrations/index.md +197 -0
- package/docs/guides/developer-guide/migrations/migration.webp +0 -0
- package/docs/guides/developer-guide/nest-devtools/index.md +74 -0
- package/docs/guides/developer-guide/nest-devtools/nest-devtools-bootstrap-perf.webp +0 -0
- package/docs/guides/developer-guide/nest-devtools/nest-devtools-graph.webp +0 -0
- package/docs/guides/developer-guide/overview/Vendure_docs-architecture.webp +0 -0
- package/docs/guides/developer-guide/overview/index.md +40 -0
- package/docs/guides/developer-guide/plugins/index.mdx +806 -0
- package/docs/guides/developer-guide/rest-endpoint/index.md +99 -0
- package/docs/guides/developer-guide/scheduled-tasks/index.md +298 -0
- package/docs/guides/developer-guide/security/index.md +264 -0
- package/docs/guides/developer-guide/settings-store/index.mdx +553 -0
- package/docs/guides/developer-guide/stand-alone-scripts/index.md +119 -0
- package/docs/guides/developer-guide/strategies-configurable-operations/collection-filters-args.webp +0 -0
- package/docs/guides/developer-guide/strategies-configurable-operations/collection-filters.webp +0 -0
- package/docs/guides/developer-guide/strategies-configurable-operations/index.mdx +373 -0
- package/docs/guides/developer-guide/testing/index.md +254 -0
- package/docs/guides/developer-guide/the-api-layer/Vendure_docs-api_request.webp +0 -0
- package/docs/guides/developer-guide/the-api-layer/index.mdx +474 -0
- package/docs/guides/developer-guide/the-service-layer/index.mdx +311 -0
- package/docs/guides/developer-guide/translatable/index.md +224 -0
- package/docs/guides/developer-guide/translations/index.md +165 -0
- package/docs/guides/developer-guide/updating/index.md +79 -0
- package/docs/guides/developer-guide/uploading-files/index.md +220 -0
- package/docs/guides/developer-guide/worker-job-queue/Vendure_docs-job-queue-2.webp +0 -0
- package/docs/guides/developer-guide/worker-job-queue/Vendure_docs-job-queue-3.webp +0 -0
- package/docs/guides/developer-guide/worker-job-queue/Vendure_docs-job-queue.webp +0 -0
- package/docs/guides/developer-guide/worker-job-queue/index.mdx +522 -0
- package/docs/guides/developer-guide/worker-job-queue/worker-job-queue.webp +0 -0
- package/docs/guides/extending-the-admin-ui/add-actions-to-pages/index.md +233 -0
- package/docs/guides/extending-the-admin-ui/add-actions-to-pages/ui-extensions-actionbar-dropdown.webp +0 -0
- package/docs/guides/extending-the-admin-ui/add-actions-to-pages/ui-extensions-actionbar.webp +0 -0
- package/docs/guides/extending-the-admin-ui/adding-ui-translations/index.md +113 -0
- package/docs/guides/extending-the-admin-ui/adding-ui-translations/ui-translations-01.webp +0 -0
- package/docs/guides/extending-the-admin-ui/admin-ui-theming-branding/index.md +133 -0
- package/docs/guides/extending-the-admin-ui/alerts/alerts-01.webp +0 -0
- package/docs/guides/extending-the-admin-ui/alerts/index.md +56 -0
- package/docs/guides/extending-the-admin-ui/bulk-actions/bulk-actions-screenshot.webp +0 -0
- package/docs/guides/extending-the-admin-ui/bulk-actions/index.md +78 -0
- package/docs/guides/extending-the-admin-ui/creating-detail-views/index.md +332 -0
- package/docs/guides/extending-the-admin-ui/creating-list-views/index.md +331 -0
- package/docs/guides/extending-the-admin-ui/custom-data-table-components/custom-data-table-location.webp +0 -0
- package/docs/guides/extending-the-admin-ui/custom-data-table-components/custom-data-table.webp +0 -0
- package/docs/guides/extending-the-admin-ui/custom-data-table-components/index.md +111 -0
- package/docs/guides/extending-the-admin-ui/custom-detail-components/detail-component.webp +0 -0
- package/docs/guides/extending-the-admin-ui/custom-detail-components/index.md +198 -0
- package/docs/guides/extending-the-admin-ui/custom-form-inputs/index.md +285 -0
- package/docs/guides/extending-the-admin-ui/custom-form-inputs/ui-extensions-custom-field-default.webp +0 -0
- package/docs/guides/extending-the-admin-ui/custom-form-inputs/ui-extensions-custom-field-slider.webp +0 -0
- package/docs/guides/extending-the-admin-ui/custom-timeline-components/index.md +79 -0
- package/docs/guides/extending-the-admin-ui/custom-timeline-components/timeline-entry.webp +0 -0
- package/docs/guides/extending-the-admin-ui/dashboard-widgets/dashboard-widgets.webp +0 -0
- package/docs/guides/extending-the-admin-ui/dashboard-widgets/index.md +149 -0
- package/docs/guides/extending-the-admin-ui/defining-routes/index.md +777 -0
- package/docs/guides/extending-the-admin-ui/defining-routes/route-area.webp +0 -0
- package/docs/guides/extending-the-admin-ui/defining-routes/ui-extensions-greeter.webp +0 -0
- package/docs/guides/extending-the-admin-ui/getting-started/index.md +656 -0
- package/docs/guides/extending-the-admin-ui/getting-started/provider-extension-points.webp +0 -0
- package/docs/guides/extending-the-admin-ui/nav-menu/index.md +97 -0
- package/docs/guides/extending-the-admin-ui/nav-menu/nav-menu-id.webp +0 -0
- package/docs/guides/extending-the-admin-ui/nav-menu/ui-extensions-navbar.webp +0 -0
- package/docs/guides/extending-the-admin-ui/page-tabs/index.md +44 -0
- package/docs/guides/extending-the-admin-ui/page-tabs/ui-extensions-tabs.webp +0 -0
- package/docs/guides/extending-the-admin-ui/ui-library/buttons.webp +0 -0
- package/docs/guides/extending-the-admin-ui/ui-library/card.webp +0 -0
- package/docs/guides/extending-the-admin-ui/ui-library/form-inputs.webp +0 -0
- package/docs/guides/extending-the-admin-ui/ui-library/icons.webp +0 -0
- package/docs/guides/extending-the-admin-ui/ui-library/index.md +356 -0
- package/docs/guides/extending-the-admin-ui/ui-library/layout.webp +0 -0
- package/docs/guides/extending-the-admin-ui/using-other-frameworks/index.md +205 -0
- package/docs/guides/extending-the-admin-ui/using-other-frameworks/ui-extensions-cra.jpg +0 -0
- package/docs/guides/extending-the-dashboard/alerts/alert.webp +0 -0
- package/docs/guides/extending-the-dashboard/alerts/index.md +89 -0
- package/docs/guides/extending-the-dashboard/creating-pages/detail-pages.md +316 -0
- package/docs/guides/extending-the-dashboard/creating-pages/index.md +90 -0
- package/docs/guides/extending-the-dashboard/creating-pages/list-pages.md +206 -0
- package/docs/guides/extending-the-dashboard/creating-pages/tabbed-page-example.webp +0 -0
- package/docs/guides/extending-the-dashboard/creating-pages/tabbed-pages.md +144 -0
- package/docs/guides/extending-the-dashboard/custom-form-components/color-picker.webp +0 -0
- package/docs/guides/extending-the-dashboard/custom-form-components/dev-mode.webp +0 -0
- package/docs/guides/extending-the-dashboard/custom-form-components/example-currency-input.webp +0 -0
- package/docs/guides/extending-the-dashboard/custom-form-components/example-email-input.webp +0 -0
- package/docs/guides/extending-the-dashboard/custom-form-components/example-slug-input.webp +0 -0
- package/docs/guides/extending-the-dashboard/custom-form-components/example-tags-input.webp +0 -0
- package/docs/guides/extending-the-dashboard/custom-form-components/form-component-examples.mdx +445 -0
- package/docs/guides/extending-the-dashboard/custom-form-components/index.md +465 -0
- package/docs/guides/extending-the-dashboard/custom-form-components/locator.webp +0 -0
- package/docs/guides/extending-the-dashboard/custom-form-components/relation-selectors.md +687 -0
- package/docs/guides/extending-the-dashboard/customizing-pages/action-bar-button.webp +0 -0
- package/docs/guides/extending-the-dashboard/customizing-pages/action-bar-dropdown.webp +0 -0
- package/docs/guides/extending-the-dashboard/customizing-pages/action-bar-items.md +272 -0
- package/docs/guides/extending-the-dashboard/customizing-pages/custom-widget.webp +0 -0
- package/docs/guides/extending-the-dashboard/customizing-pages/customizing-detail-pages.md +129 -0
- package/docs/guides/extending-the-dashboard/customizing-pages/customizing-list-pages.md +93 -0
- package/docs/guides/extending-the-dashboard/customizing-pages/customizing-login-page.md +66 -0
- package/docs/guides/extending-the-dashboard/customizing-pages/history-entries.md +43 -0
- package/docs/guides/extending-the-dashboard/customizing-pages/history-entry.webp +0 -0
- package/docs/guides/extending-the-dashboard/customizing-pages/index.md +10 -0
- package/docs/guides/extending-the-dashboard/customizing-pages/insights-widgets.md +57 -0
- package/docs/guides/extending-the-dashboard/customizing-pages/login-page.webp +0 -0
- package/docs/guides/extending-the-dashboard/customizing-pages/page-blocks.md +244 -0
- package/docs/guides/extending-the-dashboard/data-fetching/index.md +126 -0
- package/docs/guides/extending-the-dashboard/data-fetching/type-inference.webp +0 -0
- package/docs/guides/extending-the-dashboard/deployment/index.md +200 -0
- package/docs/guides/extending-the-dashboard/extending-overview/dev-mode.webp +0 -0
- package/docs/guides/extending-the-dashboard/extending-overview/index.md +228 -0
- package/docs/guides/extending-the-dashboard/extending-overview/location-id.webp +0 -0
- package/docs/guides/extending-the-dashboard/getting-started/detail-view.webp +0 -0
- package/docs/guides/extending-the-dashboard/getting-started/index.md +194 -0
- package/docs/guides/extending-the-dashboard/getting-started/list-view-empty.webp +0 -0
- package/docs/guides/extending-the-dashboard/getting-started/list-view-full.webp +0 -0
- package/docs/guides/extending-the-dashboard/getting-started/page-block.webp +0 -0
- package/docs/guides/extending-the-dashboard/getting-started/test-page.webp +0 -0
- package/docs/guides/extending-the-dashboard/localization/index.md +94 -0
- package/docs/guides/extending-the-dashboard/migration/index.md +1902 -0
- package/docs/guides/extending-the-dashboard/navigation/dev-mode-nav.webp +0 -0
- package/docs/guides/extending-the-dashboard/navigation/index.md +322 -0
- package/docs/guides/extending-the-dashboard/navigation/unauthenticated-page.webp +0 -0
- package/docs/guides/extending-the-dashboard/tech-stack/index.md +395 -0
- package/docs/guides/extending-the-dashboard/theming/index.md +180 -0
- package/docs/guides/extending-the-dashboard/theming/show-colour-value-inspection.gif +0 -0
- package/docs/guides/getting-started/graphql-intro/index.mdx +572 -0
- package/docs/guides/getting-started/installation/app-screens.webp +0 -0
- package/docs/guides/getting-started/installation/index.md +234 -0
- package/docs/guides/getting-started/try-the-api/graphiql-docs.jpeg +0 -0
- package/docs/guides/getting-started/try-the-api/graphiql.jpeg +0 -0
- package/docs/guides/getting-started/try-the-api/index.mdx +238 -0
- package/docs/guides/how-to/cms-integration-plugin/index.mdx +2083 -0
- package/docs/guides/how-to/codegen/index.md +280 -0
- package/docs/guides/how-to/configurable-products/index.md +138 -0
- package/docs/guides/how-to/digital-products/index.mdx +485 -0
- package/docs/guides/how-to/digital-products/product-variant.webp +0 -0
- package/docs/guides/how-to/digital-products/shipping-method.webp +0 -0
- package/docs/guides/how-to/github-oauth-authentication/index.mdx +360 -0
- package/docs/guides/how-to/google-oauth-authentication/index.mdx +494 -0
- package/docs/guides/how-to/multi-vendor-marketplaces/aggregate-order.webp +0 -0
- package/docs/guides/how-to/multi-vendor-marketplaces/index.md +197 -0
- package/docs/guides/how-to/paginated-list/index.mdx +360 -0
- package/docs/guides/how-to/publish-plugin/index.mdx +402 -0
- package/docs/guides/how-to/s3-asset-storage/index.mdx +572 -0
- package/docs/guides/how-to/telemetry/grafana-logs.webp +0 -0
- package/docs/guides/how-to/telemetry/grafana-trace.webp +0 -0
- package/docs/guides/how-to/telemetry/index.md +260 -0
- package/docs/guides/how-to/telemetry/jaeger-trace.webp +0 -0
- package/docs/guides/storefront/active-order/index.mdx +201 -0
- package/docs/guides/storefront/checkout-flow/index.mdx +428 -0
- package/docs/guides/storefront/codegen/index.mdx +157 -0
- package/docs/guides/storefront/connect-api/index.mdx +677 -0
- package/docs/guides/storefront/customer-accounts/index.mdx +389 -0
- package/docs/guides/storefront/customer-accounts/pw-reset.webp +0 -0
- package/docs/guides/storefront/customer-accounts/verification.webp +0 -0
- package/docs/guides/storefront/listing-products/index.mdx +711 -0
- package/docs/guides/storefront/navigation-menu/index.mdx +157 -0
- package/docs/guides/storefront/order-workflow/index.md +231 -0
- package/docs/guides/storefront/order-workflow/order_class_diagram.png +0 -0
- package/docs/guides/storefront/order-workflow/order_state_diagram.png +0 -0
- package/docs/guides/storefront/product-detail/index.mdx +295 -0
- package/docs/guides/storefront/storefront-starters/angular-storefront.webp +0 -0
- package/docs/guides/storefront/storefront-starters/index.mdx +69 -0
- package/docs/guides/storefront/storefront-starters/next-storefront.webp +0 -0
- package/docs/guides/storefront/storefront-starters/qwik-storefront.webp +0 -0
- package/docs/guides/storefront/storefront-starters/remix-storefront.webp +0 -0
- package/docs/reference/admin-ui-api/action-bar/action-bar-context.md +82 -0
- package/docs/reference/admin-ui-api/action-bar/action-bar-dropdown-menu-item.md +93 -0
- package/docs/reference/admin-ui-api/action-bar/action-bar-item.md +106 -0
- package/docs/reference/admin-ui-api/action-bar/action-bar-location-id.md +17 -0
- package/docs/reference/admin-ui-api/action-bar/add-action-bar-dropdown-menu-item.md +38 -0
- package/docs/reference/admin-ui-api/action-bar/add-action-bar-item.md +36 -0
- package/docs/reference/admin-ui-api/action-bar/index.md +5 -0
- package/docs/reference/admin-ui-api/action-bar/page-location-id.md +61 -0
- package/docs/reference/admin-ui-api/action-bar/router-link-definition.md +16 -0
- package/docs/reference/admin-ui-api/alerts/alert-config.md +88 -0
- package/docs/reference/admin-ui-api/alerts/alert-context.md +52 -0
- package/docs/reference/admin-ui-api/alerts/index.md +5 -0
- package/docs/reference/admin-ui-api/alerts/register-alert.md +23 -0
- package/docs/reference/admin-ui-api/bulk-actions/bulk-action.md +229 -0
- package/docs/reference/admin-ui-api/bulk-actions/index.md +5 -0
- package/docs/reference/admin-ui-api/bulk-actions/register-bulk-action.md +63 -0
- package/docs/reference/admin-ui-api/components/asset-picker-dialog-component.md +160 -0
- package/docs/reference/admin-ui-api/components/chip-component.md +63 -0
- package/docs/reference/admin-ui-api/components/currency-input-component.md +174 -0
- package/docs/reference/admin-ui-api/components/data-table-component.md +238 -0
- package/docs/reference/admin-ui-api/components/data-table2component.md +354 -0
- package/docs/reference/admin-ui-api/components/datetime-picker-component.md +262 -0
- package/docs/reference/admin-ui-api/components/dropdown-component.md +86 -0
- package/docs/reference/admin-ui-api/components/facet-value-selector-component.md +155 -0
- package/docs/reference/admin-ui-api/components/index.md +5 -0
- package/docs/reference/admin-ui-api/components/object-tree-component.md +86 -0
- package/docs/reference/admin-ui-api/components/order-state-label-component.md +41 -0
- package/docs/reference/admin-ui-api/components/product-variant-selector-component.md +75 -0
- package/docs/reference/admin-ui-api/components/rich-text-editor-component.md +108 -0
- package/docs/reference/admin-ui-api/components/zone-selector-component.md +124 -0
- package/docs/reference/admin-ui-api/custom-detail-components/custom-detail-component-config.md +41 -0
- package/docs/reference/admin-ui-api/custom-detail-components/custom-detail-component-location-id.md +36 -0
- package/docs/reference/admin-ui-api/custom-detail-components/custom-detail-component.md +36 -0
- package/docs/reference/admin-ui-api/custom-detail-components/index.md +5 -0
- package/docs/reference/admin-ui-api/custom-detail-components/register-custom-detail-component.md +69 -0
- package/docs/reference/admin-ui-api/custom-history-entry-components/customer-history-entry-component.md +32 -0
- package/docs/reference/admin-ui-api/custom-history-entry-components/history-entry-component.md +57 -0
- package/docs/reference/admin-ui-api/custom-history-entry-components/history-entry-config.md +35 -0
- package/docs/reference/admin-ui-api/custom-history-entry-components/index.md +5 -0
- package/docs/reference/admin-ui-api/custom-history-entry-components/order-history-entry-component.md +32 -0
- package/docs/reference/admin-ui-api/custom-history-entry-components/register-history-entry-component.md +79 -0
- package/docs/reference/admin-ui-api/custom-input-components/default-inputs.md +1034 -0
- package/docs/reference/admin-ui-api/custom-input-components/form-input-component.md +56 -0
- package/docs/reference/admin-ui-api/custom-input-components/index.md +5 -0
- package/docs/reference/admin-ui-api/custom-input-components/register-form-input-component.md +71 -0
- package/docs/reference/admin-ui-api/custom-table-components/custom-column-component.md +32 -0
- package/docs/reference/admin-ui-api/custom-table-components/data-table-component-config.md +48 -0
- package/docs/reference/admin-ui-api/custom-table-components/index.md +5 -0
- package/docs/reference/admin-ui-api/custom-table-components/register-data-table-component.md +55 -0
- package/docs/reference/admin-ui-api/dashboard-widgets/dashboard-widget-config.md +60 -0
- package/docs/reference/admin-ui-api/dashboard-widgets/index.md +5 -0
- package/docs/reference/admin-ui-api/dashboard-widgets/register-dashboard-widget.md +27 -0
- package/docs/reference/admin-ui-api/dashboard-widgets/set-dashboard-widget-layout.md +22 -0
- package/docs/reference/admin-ui-api/dashboard-widgets/widget-layout-definition.md +16 -0
- package/docs/reference/admin-ui-api/directives/if-multichannel-directive.md +41 -0
- package/docs/reference/admin-ui-api/directives/if-permissions-directive.md +43 -0
- package/docs/reference/admin-ui-api/directives/index.md +5 -0
- package/docs/reference/admin-ui-api/index.md +13 -0
- package/docs/reference/admin-ui-api/list-detail-views/base-detail-component.md +168 -0
- package/docs/reference/admin-ui-api/list-detail-views/base-entity-resolver.md +54 -0
- package/docs/reference/admin-ui-api/list-detail-views/base-list-component.md +155 -0
- package/docs/reference/admin-ui-api/list-detail-views/detail-component-with-resolver.md +52 -0
- package/docs/reference/admin-ui-api/list-detail-views/index.md +5 -0
- package/docs/reference/admin-ui-api/list-detail-views/typed-base-detail-component.md +51 -0
- package/docs/reference/admin-ui-api/list-detail-views/typed-base-list-component.md +125 -0
- package/docs/reference/admin-ui-api/nav-menu/add-nav-menu-item.md +52 -0
- package/docs/reference/admin-ui-api/nav-menu/add-nav-menu-section.md +47 -0
- package/docs/reference/admin-ui-api/nav-menu/index.md +5 -0
- package/docs/reference/admin-ui-api/nav-menu/nav-menu-item.md +66 -0
- package/docs/reference/admin-ui-api/nav-menu/nav-menu-section.md +83 -0
- package/docs/reference/admin-ui-api/nav-menu/navigation-types.md +38 -0
- package/docs/reference/admin-ui-api/pipes/asset-preview-pipe.md +41 -0
- package/docs/reference/admin-ui-api/pipes/duration-pipe.md +45 -0
- package/docs/reference/admin-ui-api/pipes/file-size-pipe.md +38 -0
- package/docs/reference/admin-ui-api/pipes/has-permission-pipe.md +51 -0
- package/docs/reference/admin-ui-api/pipes/index.md +5 -0
- package/docs/reference/admin-ui-api/pipes/locale-currency-name-pipe.md +47 -0
- package/docs/reference/admin-ui-api/pipes/locale-currency-pipe.md +54 -0
- package/docs/reference/admin-ui-api/pipes/locale-date-pipe.md +48 -0
- package/docs/reference/admin-ui-api/pipes/locale-language-name-pipe.md +47 -0
- package/docs/reference/admin-ui-api/pipes/locale-region-name-pipe.md +47 -0
- package/docs/reference/admin-ui-api/pipes/time-ago-pipe.md +44 -0
- package/docs/reference/admin-ui-api/react-components/action-bar.md +36 -0
- package/docs/reference/admin-ui-api/react-components/card.md +36 -0
- package/docs/reference/admin-ui-api/react-components/cds-icon.md +34 -0
- package/docs/reference/admin-ui-api/react-components/form-field.md +42 -0
- package/docs/reference/admin-ui-api/react-components/index.md +5 -0
- package/docs/reference/admin-ui-api/react-components/link.md +34 -0
- package/docs/reference/admin-ui-api/react-components/page-block.md +36 -0
- package/docs/reference/admin-ui-api/react-components/page-detail-layout.md +36 -0
- package/docs/reference/admin-ui-api/react-components/rich-text-editor.md +42 -0
- package/docs/reference/admin-ui-api/react-extensions/index.md +5 -0
- package/docs/reference/admin-ui-api/react-extensions/react-custom-detail-component-config.md +41 -0
- package/docs/reference/admin-ui-api/react-extensions/react-data-table-component-config.md +48 -0
- package/docs/reference/admin-ui-api/react-extensions/register-react-custom-detail-component.md +23 -0
- package/docs/reference/admin-ui-api/react-extensions/register-react-data-table-component.md +55 -0
- package/docs/reference/admin-ui-api/react-extensions/register-react-form-input-component.md +26 -0
- package/docs/reference/admin-ui-api/react-extensions/register-react-route-component-options.md +18 -0
- package/docs/reference/admin-ui-api/react-extensions/register-react-route-component.md +22 -0
- package/docs/reference/admin-ui-api/react-hooks/index.md +5 -0
- package/docs/reference/admin-ui-api/react-hooks/use-detail-component-data.md +39 -0
- package/docs/reference/admin-ui-api/react-hooks/use-form-control.md +36 -0
- package/docs/reference/admin-ui-api/react-hooks/use-injector.md +39 -0
- package/docs/reference/admin-ui-api/react-hooks/use-lazy-query.md +74 -0
- package/docs/reference/admin-ui-api/react-hooks/use-mutation.md +62 -0
- package/docs/reference/admin-ui-api/react-hooks/use-page-metadata.md +36 -0
- package/docs/reference/admin-ui-api/react-hooks/use-query.md +59 -0
- package/docs/reference/admin-ui-api/react-hooks/use-rich-text-editor.md +30 -0
- package/docs/reference/admin-ui-api/react-hooks/use-route-params.md +29 -0
- package/docs/reference/admin-ui-api/routes/index.md +5 -0
- package/docs/reference/admin-ui-api/routes/register-route-component-options.md +28 -0
- package/docs/reference/admin-ui-api/routes/register-route-component.md +57 -0
- package/docs/reference/admin-ui-api/services/data-service.md +142 -0
- package/docs/reference/admin-ui-api/services/index.md +5 -0
- package/docs/reference/admin-ui-api/services/modal-service.md +199 -0
- package/docs/reference/admin-ui-api/services/notification-service.md +126 -0
- package/docs/reference/admin-ui-api/tabs/index.md +5 -0
- package/docs/reference/admin-ui-api/tabs/page-tab-config.md +70 -0
- package/docs/reference/admin-ui-api/tabs/register-page-tab.md +38 -0
- package/docs/reference/admin-ui-api/ui-devkit/admin-ui-extension.md +417 -0
- package/docs/reference/admin-ui-api/ui-devkit/compile-ui-extensions.md +22 -0
- package/docs/reference/admin-ui-api/ui-devkit/helpers.md +39 -0
- package/docs/reference/admin-ui-api/ui-devkit/index.md +5 -0
- package/docs/reference/admin-ui-api/ui-devkit/ui-devkit-client.md +160 -0
- package/docs/reference/admin-ui-api/ui-devkit/ui-extension-build-command.md +16 -0
- package/docs/reference/admin-ui-api/ui-devkit/ui-extension-compiler-options.md +118 -0
- package/docs/reference/admin-ui-api/ui-devkit/ui-extension-compiler-process-argument.md +16 -0
- package/docs/reference/core-plugins/admin-ui-plugin/admin-ui-plugin-options.md +67 -0
- package/docs/reference/core-plugins/admin-ui-plugin/index.md +94 -0
- package/docs/reference/core-plugins/asset-server-plugin/asset-server-options.md +106 -0
- package/docs/reference/core-plugins/asset-server-plugin/cache-config.md +36 -0
- package/docs/reference/core-plugins/asset-server-plugin/hashed-asset-naming-strategy.md +47 -0
- package/docs/reference/core-plugins/asset-server-plugin/image-transform-mode.md +21 -0
- package/docs/reference/core-plugins/asset-server-plugin/image-transform-preset.md +57 -0
- package/docs/reference/core-plugins/asset-server-plugin/image-transform-strategy.md +144 -0
- package/docs/reference/core-plugins/asset-server-plugin/index.md +189 -0
- package/docs/reference/core-plugins/asset-server-plugin/local-asset-storage-strategy.md +74 -0
- package/docs/reference/core-plugins/asset-server-plugin/preset-only-strategy.md +118 -0
- package/docs/reference/core-plugins/asset-server-plugin/s3asset-storage-strategy.md +225 -0
- package/docs/reference/core-plugins/asset-server-plugin/sharp-asset-preview-strategy.md +118 -0
- package/docs/reference/core-plugins/dashboard-plugin/dashboard-plugin-options.md +43 -0
- package/docs/reference/core-plugins/dashboard-plugin/index.md +106 -0
- package/docs/reference/core-plugins/elasticsearch-plugin/elasticsearch-options.md +695 -0
- package/docs/reference/core-plugins/elasticsearch-plugin/index.md +193 -0
- package/docs/reference/core-plugins/email-plugin/email-event-handler-with-async-data.md +33 -0
- package/docs/reference/core-plugins/email-plugin/email-event-handler.md +299 -0
- package/docs/reference/core-plugins/email-plugin/email-event-listener.md +42 -0
- package/docs/reference/core-plugins/email-plugin/email-generator.md +78 -0
- package/docs/reference/core-plugins/email-plugin/email-plugin-options.md +154 -0
- package/docs/reference/core-plugins/email-plugin/email-plugin-types.md +276 -0
- package/docs/reference/core-plugins/email-plugin/email-send-event.md +34 -0
- package/docs/reference/core-plugins/email-plugin/email-sender.md +92 -0
- package/docs/reference/core-plugins/email-plugin/email-utils.md +54 -0
- package/docs/reference/core-plugins/email-plugin/index.md +309 -0
- package/docs/reference/core-plugins/email-plugin/template-loader.md +96 -0
- package/docs/reference/core-plugins/email-plugin/transport-options.md +241 -0
- package/docs/reference/core-plugins/graphiql-plugin/index.md +89 -0
- package/docs/reference/core-plugins/harden-plugin/default-vendure-complexity-estimator.md +30 -0
- package/docs/reference/core-plugins/harden-plugin/harden-plugin-options.md +106 -0
- package/docs/reference/core-plugins/harden-plugin/index.md +169 -0
- package/docs/reference/core-plugins/index.md +5 -0
- package/docs/reference/core-plugins/job-queue-plugin/bull-mqjob-queue-plugin.md +211 -0
- package/docs/reference/core-plugins/job-queue-plugin/bull-mqjob-queue-strategy.md +93 -0
- package/docs/reference/core-plugins/job-queue-plugin/bull-mqplugin-options.md +142 -0
- package/docs/reference/core-plugins/job-queue-plugin/index.md +5 -0
- package/docs/reference/core-plugins/job-queue-plugin/pub-sub-job-queue-strategy.md +65 -0
- package/docs/reference/core-plugins/job-queue-plugin/pub-sub-plugin.md +36 -0
- package/docs/reference/core-plugins/payments-plugin/braintree-plugin.md +350 -0
- package/docs/reference/core-plugins/payments-plugin/index.md +5 -0
- package/docs/reference/core-plugins/payments-plugin/mollie-plugin.md +209 -0
- package/docs/reference/core-plugins/payments-plugin/stripe-plugin.md +355 -0
- package/docs/reference/core-plugins/sentry-plugin/index.md +158 -0
- package/docs/reference/core-plugins/sentry-plugin/sentry-plugin-options.md +32 -0
- package/docs/reference/core-plugins/sentry-plugin/sentry-service.md +47 -0
- package/docs/reference/core-plugins/stellate-plugin/index.md +277 -0
- package/docs/reference/core-plugins/stellate-plugin/purge-rule.md +91 -0
- package/docs/reference/core-plugins/stellate-plugin/stellate-plugin-options.md +65 -0
- package/docs/reference/core-plugins/stellate-plugin/stellate-service.md +71 -0
- package/docs/reference/core-plugins/telemetry-plugin/get-sdk-configuration.md +92 -0
- package/docs/reference/core-plugins/telemetry-plugin/index.md +131 -0
- package/docs/reference/core-plugins/telemetry-plugin/otel-logger.md +102 -0
- package/docs/reference/core-plugins/telemetry-plugin/register-method-hooks.md +46 -0
- package/docs/reference/core-plugins/telemetry-plugin/telemetry-plugin-options.md +77 -0
- package/docs/reference/dashboard/components/asset-gallery.md +127 -0
- package/docs/reference/dashboard/components/asset-picker-dialog.md +76 -0
- package/docs/reference/dashboard/components/channel-chip.md +22 -0
- package/docs/reference/dashboard/components/detail-page-button.md +49 -0
- package/docs/reference/dashboard/components/facet-value-chip.md +22 -0
- package/docs/reference/dashboard/components/facet-value-selector.md +85 -0
- package/docs/reference/dashboard/components/index.md +5 -0
- package/docs/reference/dashboard/components/permission-guard.md +63 -0
- package/docs/reference/dashboard/components/vendure-image.md +199 -0
- package/docs/reference/dashboard/detail-views/detail-page.md +91 -0
- package/docs/reference/dashboard/detail-views/index.md +5 -0
- package/docs/reference/dashboard/detail-views/use-detail-page.md +234 -0
- package/docs/reference/dashboard/detail-views/use-generated-form.md +105 -0
- package/docs/reference/dashboard/extensions-api/action-bar.md +66 -0
- package/docs/reference/dashboard/extensions-api/alerts.md +78 -0
- package/docs/reference/dashboard/extensions-api/data-tables.md +55 -0
- package/docs/reference/dashboard/extensions-api/define-dashboard-extension.md +142 -0
- package/docs/reference/dashboard/extensions-api/detail-forms.md +81 -0
- package/docs/reference/dashboard/extensions-api/form-components.md +188 -0
- package/docs/reference/dashboard/extensions-api/history-entries.md +246 -0
- package/docs/reference/dashboard/extensions-api/index.md +5 -0
- package/docs/reference/dashboard/extensions-api/login.md +113 -0
- package/docs/reference/dashboard/extensions-api/navigation.md +128 -0
- package/docs/reference/dashboard/extensions-api/page-blocks.md +143 -0
- package/docs/reference/dashboard/extensions-api/routes.md +69 -0
- package/docs/reference/dashboard/extensions-api/widgets.md +61 -0
- package/docs/reference/dashboard/form-components/affixed-input.md +34 -0
- package/docs/reference/dashboard/form-components/boolean-input.md +22 -0
- package/docs/reference/dashboard/form-components/checkbox-input.md +22 -0
- package/docs/reference/dashboard/form-components/date-time-input.md +22 -0
- package/docs/reference/dashboard/form-components/form-field-wrapper.md +80 -0
- package/docs/reference/dashboard/form-components/index.md +5 -0
- package/docs/reference/dashboard/form-components/money-input.md +23 -0
- package/docs/reference/dashboard/form-components/number-input.md +22 -0
- package/docs/reference/dashboard/form-components/password-input.md +22 -0
- package/docs/reference/dashboard/form-components/rich-text-input.md +22 -0
- package/docs/reference/dashboard/form-components/slug-input.md +57 -0
- package/docs/reference/dashboard/form-components/text-input.md +13 -0
- package/docs/reference/dashboard/form-components/textarea-input.md +22 -0
- package/docs/reference/dashboard/form-components/translatable-form-field-wrapper.md +70 -0
- package/docs/reference/dashboard/hooks/index.md +5 -0
- package/docs/reference/dashboard/hooks/use-alerts.md +65 -0
- package/docs/reference/dashboard/hooks/use-auth.md +84 -0
- package/docs/reference/dashboard/hooks/use-channel.md +72 -0
- package/docs/reference/dashboard/hooks/use-custom-field-config.md +24 -0
- package/docs/reference/dashboard/hooks/use-display-locale.md +32 -0
- package/docs/reference/dashboard/hooks/use-drag-and-drop.md +22 -0
- package/docs/reference/dashboard/hooks/use-local-format.md +30 -0
- package/docs/reference/dashboard/hooks/use-paginated-list.md +29 -0
- package/docs/reference/dashboard/hooks/use-permissions.md +25 -0
- package/docs/reference/dashboard/hooks/use-sorted-languages.md +30 -0
- package/docs/reference/dashboard/hooks/use-ui-language-loader.md +18 -0
- package/docs/reference/dashboard/hooks/use-widget-filters.md +16 -0
- package/docs/reference/dashboard/list-views/bulk-actions.md +199 -0
- package/docs/reference/dashboard/list-views/data-table-cell-component.md +45 -0
- package/docs/reference/dashboard/list-views/data-table.md +209 -0
- package/docs/reference/dashboard/list-views/index.md +5 -0
- package/docs/reference/dashboard/list-views/list-page.md +493 -0
- package/docs/reference/dashboard/list-views/paginated-list-data-table.md +303 -0
- package/docs/reference/dashboard/page-layout/index.md +54 -0
- package/docs/reference/dashboard/page-layout/page-action-bar.md +62 -0
- package/docs/reference/dashboard/page-layout/page-block.md +137 -0
- package/docs/reference/dashboard/page-layout/page-title.md +22 -0
- package/docs/reference/dashboard/page-layout/page.md +100 -0
- package/docs/reference/dashboard/page-layout/use-page-block.md +32 -0
- package/docs/reference/dashboard/vite-plugin/index.md +5 -0
- package/docs/reference/dashboard/vite-plugin/vendure-dashboard-plugin.md +356 -0
- package/docs/reference/graphql-api/_index.md +16 -0
- package/docs/reference/graphql-api/admin/_index.md +13 -0
- package/docs/reference/graphql-api/admin/enums.md +1142 -0
- package/docs/reference/graphql-api/admin/input-types.md +4631 -0
- package/docs/reference/graphql-api/admin/mutations.md +1985 -0
- package/docs/reference/graphql-api/admin/object-types.md +4515 -0
- package/docs/reference/graphql-api/admin/queries.md +760 -0
- package/docs/reference/graphql-api/shop/_index.md +13 -0
- package/docs/reference/graphql-api/shop/enums.md +1072 -0
- package/docs/reference/graphql-api/shop/input-types.md +1192 -0
- package/docs/reference/graphql-api/shop/mutations.md +431 -0
- package/docs/reference/graphql-api/shop/object-types.md +3406 -0
- package/docs/reference/graphql-api/shop/queries.md +247 -0
- package/docs/reference/index.mdx +38 -0
- package/docs/reference/links.webp +0 -0
- package/docs/reference/typescript-api/_index.md +13 -0
- package/docs/reference/typescript-api/assets/asset-naming-strategy.md +56 -0
- package/docs/reference/typescript-api/assets/asset-options.md +58 -0
- package/docs/reference/typescript-api/assets/asset-preview-strategy.md +45 -0
- package/docs/reference/typescript-api/assets/asset-storage-strategy.md +84 -0
- package/docs/reference/typescript-api/assets/default-asset-naming-strategy.md +39 -0
- package/docs/reference/typescript-api/assets/index.md +5 -0
- package/docs/reference/typescript-api/auth/auth-options.md +165 -0
- package/docs/reference/typescript-api/auth/authentication-strategy.md +97 -0
- package/docs/reference/typescript-api/auth/bcrypt-password-hashing-strategy.md +38 -0
- package/docs/reference/typescript-api/auth/cookie-options.md +108 -0
- package/docs/reference/typescript-api/auth/default-password-validation-strategy.md +44 -0
- package/docs/reference/typescript-api/auth/default-session-cache-strategy.md +73 -0
- package/docs/reference/typescript-api/auth/default-verification-token-strategy.md +47 -0
- package/docs/reference/typescript-api/auth/external-authentication-service.md +98 -0
- package/docs/reference/typescript-api/auth/in-memory-session-cache-strategy.md +63 -0
- package/docs/reference/typescript-api/auth/index.md +5 -0
- package/docs/reference/typescript-api/auth/native-authentication-strategy.md +58 -0
- package/docs/reference/typescript-api/auth/noop-session-cache-strategy.md +51 -0
- package/docs/reference/typescript-api/auth/password-hashing-strategy.md +45 -0
- package/docs/reference/typescript-api/auth/password-validation-strategy.md +43 -0
- package/docs/reference/typescript-api/auth/permission-definition.md +269 -0
- package/docs/reference/typescript-api/auth/session-cache-strategy.md +275 -0
- package/docs/reference/typescript-api/auth/superadmin-credentials.md +36 -0
- package/docs/reference/typescript-api/auth/verification-token-strategy.md +45 -0
- package/docs/reference/typescript-api/cache/cache-config.md +44 -0
- package/docs/reference/typescript-api/cache/cache-service.md +76 -0
- package/docs/reference/typescript-api/cache/cache-strategy.md +103 -0
- package/docs/reference/typescript-api/cache/default-cache-plugin.md +73 -0
- package/docs/reference/typescript-api/cache/index.md +79 -0
- package/docs/reference/typescript-api/cache/redis-cache-plugin.md +85 -0
- package/docs/reference/typescript-api/cache/redis-cache-strategy.md +75 -0
- package/docs/reference/typescript-api/cache/request-context-cache-service.md +54 -0
- package/docs/reference/typescript-api/cache/self-refreshing-cache.md +152 -0
- package/docs/reference/typescript-api/cache/sql-cache-strategy.md +87 -0
- package/docs/reference/typescript-api/common/admin-ui/admin-ui-app-config.md +43 -0
- package/docs/reference/typescript-api/common/admin-ui/admin-ui-app-dev-mode-config.md +47 -0
- package/docs/reference/typescript-api/common/admin-ui/admin-ui-config.md +139 -0
- package/docs/reference/typescript-api/common/admin-ui/index.md +5 -0
- package/docs/reference/typescript-api/common/async-queue.md +38 -0
- package/docs/reference/typescript-api/common/bootstrap.md +129 -0
- package/docs/reference/typescript-api/common/currency-code.md +174 -0
- package/docs/reference/typescript-api/common/entity-relation-paths.md +34 -0
- package/docs/reference/typescript-api/common/i18n-service.md +74 -0
- package/docs/reference/typescript-api/common/id.md +17 -0
- package/docs/reference/typescript-api/common/index.md +5 -0
- package/docs/reference/typescript-api/common/injectable-strategy.md +48 -0
- package/docs/reference/typescript-api/common/injector.md +47 -0
- package/docs/reference/typescript-api/common/job-state.md +23 -0
- package/docs/reference/typescript-api/common/json-compatible.md +23 -0
- package/docs/reference/typescript-api/common/language-code.md +177 -0
- package/docs/reference/typescript-api/common/middleware.md +72 -0
- package/docs/reference/typescript-api/common/paginated-list.md +36 -0
- package/docs/reference/typescript-api/common/permission.md +136 -0
- package/docs/reference/typescript-api/common/price-calculation-result.md +36 -0
- package/docs/reference/typescript-api/common/process-context.md +55 -0
- package/docs/reference/typescript-api/common/vendure_version.md +22 -0
- package/docs/reference/typescript-api/configurable-operation-def/config-arg-type.md +22 -0
- package/docs/reference/typescript-api/configurable-operation-def/config-args.md +89 -0
- package/docs/reference/typescript-api/configurable-operation-def/configurable-operation-def-options.md +57 -0
- package/docs/reference/typescript-api/configurable-operation-def/default-form-component-id.md +34 -0
- package/docs/reference/typescript-api/configurable-operation-def/default-form-config-hash.md +137 -0
- package/docs/reference/typescript-api/configurable-operation-def/index.md +149 -0
- package/docs/reference/typescript-api/configurable-operation-def/localized-string-array.md +28 -0
- package/docs/reference/typescript-api/configuration/api-options.md +159 -0
- package/docs/reference/typescript-api/configuration/collection-filter.md +76 -0
- package/docs/reference/typescript-api/configuration/default-config.md +13 -0
- package/docs/reference/typescript-api/configuration/default-slug-strategy.md +46 -0
- package/docs/reference/typescript-api/configuration/entity-duplicator.md +195 -0
- package/docs/reference/typescript-api/configuration/entity-id-decorator.md +24 -0
- package/docs/reference/typescript-api/configuration/entity-id-strategy.md +168 -0
- package/docs/reference/typescript-api/configuration/entity-options.md +153 -0
- package/docs/reference/typescript-api/configuration/index.md +5 -0
- package/docs/reference/typescript-api/configuration/merge-config.md +49 -0
- package/docs/reference/typescript-api/configuration/product-variant-price-selection-strategy.md +71 -0
- package/docs/reference/typescript-api/configuration/product-variant-price-update-strategy.md +185 -0
- package/docs/reference/typescript-api/configuration/runtime-vendure-config.md +111 -0
- package/docs/reference/typescript-api/configuration/settings-store-fields.md +29 -0
- package/docs/reference/typescript-api/configuration/slug-strategy.md +47 -0
- package/docs/reference/typescript-api/configuration/system-options.md +50 -0
- package/docs/reference/typescript-api/configuration/trust-proxy-options.md +19 -0
- package/docs/reference/typescript-api/configuration/vendure-config.md +168 -0
- package/docs/reference/typescript-api/custom-fields/custom-field-config.md +25 -0
- package/docs/reference/typescript-api/custom-fields/custom-field-type.md +42 -0
- package/docs/reference/typescript-api/custom-fields/index.md +70 -0
- package/docs/reference/typescript-api/custom-fields/struct-custom-field-config.md +21 -0
- package/docs/reference/typescript-api/custom-fields/struct-field-config.md +41 -0
- package/docs/reference/typescript-api/custom-fields/typed-custom-single-field-config.md +24 -0
- package/docs/reference/typescript-api/data-access/calculated-property-subscriber.md +38 -0
- package/docs/reference/typescript-api/data-access/calculated.md +62 -0
- package/docs/reference/typescript-api/data-access/entity-hydrator.md +103 -0
- package/docs/reference/typescript-api/data-access/get-entity-or-throw-options.md +53 -0
- package/docs/reference/typescript-api/data-access/hydrate-options.md +40 -0
- package/docs/reference/typescript-api/data-access/index.md +5 -0
- package/docs/reference/typescript-api/data-access/list-query-builder.md +239 -0
- package/docs/reference/typescript-api/data-access/transactional-connection.md +173 -0
- package/docs/reference/typescript-api/default-search-plugin/default-search-plugin-init-options.md +126 -0
- package/docs/reference/typescript-api/default-search-plugin/index.md +64 -0
- package/docs/reference/typescript-api/default-search-plugin/mysql-search-strategy.md +56 -0
- package/docs/reference/typescript-api/default-search-plugin/postgres-search-strategy.md +56 -0
- package/docs/reference/typescript-api/default-search-plugin/search-strategy.md +58 -0
- package/docs/reference/typescript-api/default-search-plugin/sqlite-search-strategy.md +57 -0
- package/docs/reference/typescript-api/entities/address.md +124 -0
- package/docs/reference/typescript-api/entities/administrator.md +78 -0
- package/docs/reference/typescript-api/entities/anonymous-session.md +34 -0
- package/docs/reference/typescript-api/entities/asset.md +135 -0
- package/docs/reference/typescript-api/entities/authenticated-session.md +48 -0
- package/docs/reference/typescript-api/entities/authentication-method.md +156 -0
- package/docs/reference/typescript-api/entities/channel.md +233 -0
- package/docs/reference/typescript-api/entities/collection.md +152 -0
- package/docs/reference/typescript-api/entities/country.md +40 -0
- package/docs/reference/typescript-api/entities/customer-group.md +63 -0
- package/docs/reference/typescript-api/entities/customer-history-entry.md +40 -0
- package/docs/reference/typescript-api/entities/customer.md +122 -0
- package/docs/reference/typescript-api/entities/facet-value.md +98 -0
- package/docs/reference/typescript-api/entities/facet.md +89 -0
- package/docs/reference/typescript-api/entities/fulfillment.md +84 -0
- package/docs/reference/typescript-api/entities/global-settings.md +66 -0
- package/docs/reference/typescript-api/entities/history-entry.md +66 -0
- package/docs/reference/typescript-api/entities/index.md +5 -0
- package/docs/reference/typescript-api/entities/interfaces.md +125 -0
- package/docs/reference/typescript-api/entities/order-history-entry.md +40 -0
- package/docs/reference/typescript-api/entities/order-line-reference.md +174 -0
- package/docs/reference/typescript-api/entities/order-line.md +344 -0
- package/docs/reference/typescript-api/entities/order-modification.md +103 -0
- package/docs/reference/typescript-api/entities/order.md +284 -0
- package/docs/reference/typescript-api/entities/orderable-asset.md +61 -0
- package/docs/reference/typescript-api/entities/payment-method.md +94 -0
- package/docs/reference/typescript-api/entities/payment.md +96 -0
- package/docs/reference/typescript-api/entities/product-option-group.md +84 -0
- package/docs/reference/typescript-api/entities/product-option.md +90 -0
- package/docs/reference/typescript-api/entities/product-variant-price.md +70 -0
- package/docs/reference/typescript-api/entities/product-variant.md +251 -0
- package/docs/reference/typescript-api/entities/product.md +134 -0
- package/docs/reference/typescript-api/entities/promotion.md +190 -0
- package/docs/reference/typescript-api/entities/province.md +39 -0
- package/docs/reference/typescript-api/entities/refund.md +120 -0
- package/docs/reference/typescript-api/entities/region.md +87 -0
- package/docs/reference/typescript-api/entities/role.md +62 -0
- package/docs/reference/typescript-api/entities/seller.md +63 -0
- package/docs/reference/typescript-api/entities/session.md +87 -0
- package/docs/reference/typescript-api/entities/settings-store-entry.md +57 -0
- package/docs/reference/typescript-api/entities/shipping-line.md +150 -0
- package/docs/reference/typescript-api/entities/shipping-method.md +123 -0
- package/docs/reference/typescript-api/entities/stock-level.md +87 -0
- package/docs/reference/typescript-api/entities/stock-location.md +76 -0
- package/docs/reference/typescript-api/entities/stock-movement.md +270 -0
- package/docs/reference/typescript-api/entities/surcharge.md +102 -0
- package/docs/reference/typescript-api/entities/tag.md +40 -0
- package/docs/reference/typescript-api/entities/tax-category.md +68 -0
- package/docs/reference/typescript-api/entities/tax-rate.md +138 -0
- package/docs/reference/typescript-api/entities/user.md +111 -0
- package/docs/reference/typescript-api/entities/vendure-entity.md +49 -0
- package/docs/reference/typescript-api/entities/zone.md +78 -0
- package/docs/reference/typescript-api/errors/error-handler-strategy.md +88 -0
- package/docs/reference/typescript-api/errors/error-result-union.md +30 -0
- package/docs/reference/typescript-api/errors/error-types.md +197 -0
- package/docs/reference/typescript-api/errors/i18n-error.md +39 -0
- package/docs/reference/typescript-api/errors/index.md +5 -0
- package/docs/reference/typescript-api/errors/is-graph-ql-error-result.md +40 -0
- package/docs/reference/typescript-api/events/blocking-event-handler-options.md +57 -0
- package/docs/reference/typescript-api/events/event-bus.md +136 -0
- package/docs/reference/typescript-api/events/event-types.md +1689 -0
- package/docs/reference/typescript-api/events/index.md +5 -0
- package/docs/reference/typescript-api/events/vendure-entity-event.md +57 -0
- package/docs/reference/typescript-api/events/vendure-event.md +35 -0
- package/docs/reference/typescript-api/fulfillment/fulfillment-handler.md +173 -0
- package/docs/reference/typescript-api/fulfillment/fulfillment-process.md +71 -0
- package/docs/reference/typescript-api/fulfillment/fulfillment-state.md +21 -0
- package/docs/reference/typescript-api/fulfillment/fulfillment-states.md +18 -0
- package/docs/reference/typescript-api/fulfillment/fulfillment-transition-data.md +41 -0
- package/docs/reference/typescript-api/fulfillment/index.md +5 -0
- package/docs/reference/typescript-api/health-check/health-check-registry-service.md +70 -0
- package/docs/reference/typescript-api/health-check/health-check-strategy.md +70 -0
- package/docs/reference/typescript-api/health-check/http-health-check-strategy.md +61 -0
- package/docs/reference/typescript-api/health-check/index.md +5 -0
- package/docs/reference/typescript-api/health-check/type-ormhealth-check-strategy.md +64 -0
- package/docs/reference/typescript-api/import-export/asset-import-strategy.md +46 -0
- package/docs/reference/typescript-api/import-export/asset-importer.md +32 -0
- package/docs/reference/typescript-api/import-export/default-asset-import-strategy.md +48 -0
- package/docs/reference/typescript-api/import-export/fast-importer-service.md +67 -0
- package/docs/reference/typescript-api/import-export/import-export-options.md +36 -0
- package/docs/reference/typescript-api/import-export/import-parser.md +280 -0
- package/docs/reference/typescript-api/import-export/importer.md +54 -0
- package/docs/reference/typescript-api/import-export/index.md +5 -0
- package/docs/reference/typescript-api/import-export/initial-data.md +71 -0
- package/docs/reference/typescript-api/import-export/populate.md +71 -0
- package/docs/reference/typescript-api/import-export/populator.md +38 -0
- package/docs/reference/typescript-api/job-queue/default-job-queue-plugin.md +245 -0
- package/docs/reference/typescript-api/job-queue/in-memory-job-buffer-storage-strategy.md +55 -0
- package/docs/reference/typescript-api/job-queue/in-memory-job-queue-strategy.md +110 -0
- package/docs/reference/typescript-api/job-queue/index.md +84 -0
- package/docs/reference/typescript-api/job-queue/inspectable-job-queue-strategy.md +60 -0
- package/docs/reference/typescript-api/job-queue/job-buffer-storage-strategy.md +78 -0
- package/docs/reference/typescript-api/job-queue/job-buffer.md +119 -0
- package/docs/reference/typescript-api/job-queue/job-queue-options.md +56 -0
- package/docs/reference/typescript-api/job-queue/job-queue-service.md +128 -0
- package/docs/reference/typescript-api/job-queue/job-queue-strategy.md +59 -0
- package/docs/reference/typescript-api/job-queue/job.md +195 -0
- package/docs/reference/typescript-api/job-queue/polling-job-queue-strategy.md +122 -0
- package/docs/reference/typescript-api/job-queue/sql-job-queue-strategy.md +84 -0
- package/docs/reference/typescript-api/job-queue/subscribable-job.md +44 -0
- package/docs/reference/typescript-api/job-queue/types.md +199 -0
- package/docs/reference/typescript-api/logger/default-logger.md +81 -0
- package/docs/reference/typescript-api/logger/index.md +120 -0
- package/docs/reference/typescript-api/logger/log-level.md +30 -0
- package/docs/reference/typescript-api/logger/vendure-logger.md +60 -0
- package/docs/reference/typescript-api/migration/generate-migration.md +28 -0
- package/docs/reference/typescript-api/migration/index.md +5 -0
- package/docs/reference/typescript-api/migration/migration-options.md +36 -0
- package/docs/reference/typescript-api/migration/revert-last-migration.md +23 -0
- package/docs/reference/typescript-api/migration/run-migrations.md +23 -0
- package/docs/reference/typescript-api/money/big-int-money-strategy.md +68 -0
- package/docs/reference/typescript-api/money/default-money-strategy.md +47 -0
- package/docs/reference/typescript-api/money/index.md +5 -0
- package/docs/reference/typescript-api/money/money-decorator.md +23 -0
- package/docs/reference/typescript-api/money/money-strategy.md +116 -0
- package/docs/reference/typescript-api/money/round-money.md +26 -0
- package/docs/reference/typescript-api/orders/active-order-service.md +69 -0
- package/docs/reference/typescript-api/orders/active-order-strategy.md +203 -0
- package/docs/reference/typescript-api/orders/changed-price-handling-strategy.md +51 -0
- package/docs/reference/typescript-api/orders/custom-order-states.md +18 -0
- package/docs/reference/typescript-api/orders/default-active-order-strategy.md +52 -0
- package/docs/reference/typescript-api/orders/default-guest-checkout-strategy.md +93 -0
- package/docs/reference/typescript-api/orders/default-order-item-price-calculation-strategy.md +33 -0
- package/docs/reference/typescript-api/orders/default-order-placed-strategy.md +33 -0
- package/docs/reference/typescript-api/orders/default-stock-allocation-strategy.md +33 -0
- package/docs/reference/typescript-api/orders/guest-checkout-strategy.md +56 -0
- package/docs/reference/typescript-api/orders/index.md +5 -0
- package/docs/reference/typescript-api/orders/merge-strategies.md +114 -0
- package/docs/reference/typescript-api/orders/order-by-code-access-strategy.md +91 -0
- package/docs/reference/typescript-api/orders/order-code-strategy.md +88 -0
- package/docs/reference/typescript-api/orders/order-interceptor.md +250 -0
- package/docs/reference/typescript-api/orders/order-item-price-calculation-strategy.md +91 -0
- package/docs/reference/typescript-api/orders/order-merge-strategy.md +80 -0
- package/docs/reference/typescript-api/orders/order-options.md +145 -0
- package/docs/reference/typescript-api/orders/order-placed-strategy.md +54 -0
- package/docs/reference/typescript-api/orders/order-process.md +271 -0
- package/docs/reference/typescript-api/orders/order-seller-strategy.md +124 -0
- package/docs/reference/typescript-api/orders/stock-allocation-strategy.md +46 -0
- package/docs/reference/typescript-api/payment/default-payment-process.md +13 -0
- package/docs/reference/typescript-api/payment/default-refund-process.md +13 -0
- package/docs/reference/typescript-api/payment/dummy-payment-handler.md +31 -0
- package/docs/reference/typescript-api/payment/index.md +5 -0
- package/docs/reference/typescript-api/payment/payment-method-config-options.md +69 -0
- package/docs/reference/typescript-api/payment/payment-method-eligibility-checker.md +95 -0
- package/docs/reference/typescript-api/payment/payment-method-handler.md +83 -0
- package/docs/reference/typescript-api/payment/payment-method-types.md +386 -0
- package/docs/reference/typescript-api/payment/payment-options.md +57 -0
- package/docs/reference/typescript-api/payment/payment-process.md +62 -0
- package/docs/reference/typescript-api/payment/payment-state.md +20 -0
- package/docs/reference/typescript-api/payment/payment-states.md +18 -0
- package/docs/reference/typescript-api/payment/payment-transition-data.md +42 -0
- package/docs/reference/typescript-api/payment/refund-process.md +55 -0
- package/docs/reference/typescript-api/payment/refund-state.md +16 -0
- package/docs/reference/typescript-api/payment/refund-states.md +18 -0
- package/docs/reference/typescript-api/payment/refund-transition-data.md +41 -0
- package/docs/reference/typescript-api/plugin/index.md +5 -0
- package/docs/reference/typescript-api/plugin/plugin-common-module.md +28 -0
- package/docs/reference/typescript-api/plugin/plugin-utilities.md +96 -0
- package/docs/reference/typescript-api/plugin/vendure-plugin-metadata.md +147 -0
- package/docs/reference/typescript-api/plugin/vendure-plugin.md +52 -0
- package/docs/reference/typescript-api/products-stock/catalog-options.md +70 -0
- package/docs/reference/typescript-api/products-stock/default-product-variant-price-calculation-strategy.md +38 -0
- package/docs/reference/typescript-api/products-stock/default-stock-display-strategy.md +40 -0
- package/docs/reference/typescript-api/products-stock/default-stock-location-strategy.md +47 -0
- package/docs/reference/typescript-api/products-stock/index.md +5 -0
- package/docs/reference/typescript-api/products-stock/multi-channel-stock-location-strategy.md +47 -0
- package/docs/reference/typescript-api/products-stock/product-variant-price-calculation-strategy.md +95 -0
- package/docs/reference/typescript-api/products-stock/stock-display-strategy.md +47 -0
- package/docs/reference/typescript-api/products-stock/stock-location-strategy.md +157 -0
- package/docs/reference/typescript-api/promotions/facet-value-checker.md +78 -0
- package/docs/reference/typescript-api/promotions/index.md +5 -0
- package/docs/reference/typescript-api/promotions/promotion-action.md +454 -0
- package/docs/reference/typescript-api/promotions/promotion-condition.md +117 -0
- package/docs/reference/typescript-api/promotions/promotion-options.md +35 -0
- package/docs/reference/typescript-api/request/allow-decorator.md +53 -0
- package/docs/reference/typescript-api/request/api-decorator.md +28 -0
- package/docs/reference/typescript-api/request/api-type.md +16 -0
- package/docs/reference/typescript-api/request/ctx-decorator.md +23 -0
- package/docs/reference/typescript-api/request/index.md +5 -0
- package/docs/reference/typescript-api/request/relations-decorator.md +116 -0
- package/docs/reference/typescript-api/request/request-context-service.md +47 -0
- package/docs/reference/typescript-api/request/request-context.md +205 -0
- package/docs/reference/typescript-api/request/transaction-decorator.md +82 -0
- package/docs/reference/typescript-api/scheduled-tasks/clean-sessions-task.md +40 -0
- package/docs/reference/typescript-api/scheduled-tasks/default-scheduler-plugin.md +86 -0
- package/docs/reference/typescript-api/scheduled-tasks/default-scheduler-strategy.md +76 -0
- package/docs/reference/typescript-api/scheduled-tasks/index.md +5 -0
- package/docs/reference/typescript-api/scheduled-tasks/scheduled-task.md +196 -0
- package/docs/reference/typescript-api/scheduled-tasks/scheduler-options.md +47 -0
- package/docs/reference/typescript-api/scheduled-tasks/scheduler-service.md +62 -0
- package/docs/reference/typescript-api/scheduled-tasks/scheduler-strategy.md +141 -0
- package/docs/reference/typescript-api/service-helpers/entity-duplicator-service.md +43 -0
- package/docs/reference/typescript-api/service-helpers/index.md +5 -0
- package/docs/reference/typescript-api/service-helpers/order-calculator.md +54 -0
- package/docs/reference/typescript-api/service-helpers/order-modifier.md +91 -0
- package/docs/reference/typescript-api/service-helpers/product-price-applicator.md +62 -0
- package/docs/reference/typescript-api/service-helpers/slug-validator.md +86 -0
- package/docs/reference/typescript-api/service-helpers/translatable-saver.md +66 -0
- package/docs/reference/typescript-api/service-helpers/translator-service.md +63 -0
- package/docs/reference/typescript-api/services/administrator-service.md +71 -0
- package/docs/reference/typescript-api/services/asset-service.md +177 -0
- package/docs/reference/typescript-api/services/auth-service.md +54 -0
- package/docs/reference/typescript-api/services/channel-service.md +111 -0
- package/docs/reference/typescript-api/services/collection-service.md +186 -0
- package/docs/reference/typescript-api/services/country-service.md +71 -0
- package/docs/reference/typescript-api/services/customer-group-service.md +77 -0
- package/docs/reference/typescript-api/services/customer-service.md +203 -0
- package/docs/reference/typescript-api/services/entity-slug-service.md +37 -0
- package/docs/reference/typescript-api/services/facet-service.md +95 -0
- package/docs/reference/typescript-api/services/facet-value-service.md +104 -0
- package/docs/reference/typescript-api/services/fulfillment-service.md +69 -0
- package/docs/reference/typescript-api/services/global-settings-service.md +41 -0
- package/docs/reference/typescript-api/services/history-service.md +172 -0
- package/docs/reference/typescript-api/services/index.md +5 -0
- package/docs/reference/typescript-api/services/initializer-service.md +36 -0
- package/docs/reference/typescript-api/services/order-service.md +440 -0
- package/docs/reference/typescript-api/services/order-testing-service.md +44 -0
- package/docs/reference/typescript-api/services/payment-method-service.md +105 -0
- package/docs/reference/typescript-api/services/payment-service.md +105 -0
- package/docs/reference/typescript-api/services/product-option-group-service.md +67 -0
- package/docs/reference/typescript-api/services/product-option-service.md +64 -0
- package/docs/reference/typescript-api/services/product-service.md +111 -0
- package/docs/reference/typescript-api/services/product-variant-service.md +179 -0
- package/docs/reference/typescript-api/services/promotion-service.md +127 -0
- package/docs/reference/typescript-api/services/province-service.md +59 -0
- package/docs/reference/typescript-api/services/role-service.md +113 -0
- package/docs/reference/typescript-api/services/search-service.md +37 -0
- package/docs/reference/typescript-api/services/seller-service.md +65 -0
- package/docs/reference/typescript-api/services/session-service.md +105 -0
- package/docs/reference/typescript-api/services/settings-store-service.md +194 -0
- package/docs/reference/typescript-api/services/shipping-method-service.md +95 -0
- package/docs/reference/typescript-api/services/slug-service.md +35 -0
- package/docs/reference/typescript-api/services/stock-level-service.md +62 -0
- package/docs/reference/typescript-api/services/stock-location-service.md +115 -0
- package/docs/reference/typescript-api/services/stock-movement-service.md +95 -0
- package/docs/reference/typescript-api/services/tag-service.md +71 -0
- package/docs/reference/typescript-api/services/tax-category-service.md +59 -0
- package/docs/reference/typescript-api/services/tax-rate-service.md +66 -0
- package/docs/reference/typescript-api/services/user-service.md +132 -0
- package/docs/reference/typescript-api/services/zone-service.md +77 -0
- package/docs/reference/typescript-api/settings-store/cleanup-orphaned-settings-store-entries-options.md +48 -0
- package/docs/reference/typescript-api/settings-store/cleanup-orphaned-settings-store-entries-result.md +41 -0
- package/docs/reference/typescript-api/settings-store/index.md +38 -0
- package/docs/reference/typescript-api/settings-store/orphaned-settings-store-entry.md +48 -0
- package/docs/reference/typescript-api/settings-store/set-settings-store-value-result.md +42 -0
- package/docs/reference/typescript-api/settings-store/settings-store-field-config.md +92 -0
- package/docs/reference/typescript-api/settings-store/settings-store-registration.md +36 -0
- package/docs/reference/typescript-api/settings-store/settings-store-scope-function.md +35 -0
- package/docs/reference/typescript-api/settings-store/settings-store-scopes.md +36 -0
- package/docs/reference/typescript-api/shipping/check-shipping-eligibility-checker-fn.md +27 -0
- package/docs/reference/typescript-api/shipping/default-shipping-line-assignment-strategy.md +33 -0
- package/docs/reference/typescript-api/shipping/index.md +5 -0
- package/docs/reference/typescript-api/shipping/shipping-calculator.md +121 -0
- package/docs/reference/typescript-api/shipping/shipping-eligibility-checker-config.md +39 -0
- package/docs/reference/typescript-api/shipping/shipping-eligibility-checker.md +60 -0
- package/docs/reference/typescript-api/shipping/shipping-line-assignment-strategy.md +75 -0
- package/docs/reference/typescript-api/shipping/shipping-options.md +63 -0
- package/docs/reference/typescript-api/shipping/should-run-check-fn.md +44 -0
- package/docs/reference/typescript-api/state-machine/fsm.md +66 -0
- package/docs/reference/typescript-api/state-machine/index.md +5 -0
- package/docs/reference/typescript-api/state-machine/state-machine-config.md +103 -0
- package/docs/reference/typescript-api/state-machine/transitions.md +43 -0
- package/docs/reference/typescript-api/tax/address-based-tax-zone-strategy.md +57 -0
- package/docs/reference/typescript-api/tax/default-tax-line-calculation-strategy.md +33 -0
- package/docs/reference/typescript-api/tax/default-tax-zone-strategy.md +35 -0
- package/docs/reference/typescript-api/tax/index.md +5 -0
- package/docs/reference/typescript-api/tax/tax-line-calculation-strategy.md +90 -0
- package/docs/reference/typescript-api/tax/tax-options.md +35 -0
- package/docs/reference/typescript-api/tax/tax-zone-strategy.md +54 -0
- package/docs/reference/typescript-api/telemetry/index.md +5 -0
- package/docs/reference/typescript-api/telemetry/instrument.md +47 -0
- package/docs/reference/typescript-api/telemetry/instrumentation-strategy.md +35 -0
- package/docs/reference/typescript-api/telemetry/wrapped-method-args.md +56 -0
- package/docs/reference/typescript-api/testing/create-error-result-guard.md +33 -0
- package/docs/reference/typescript-api/testing/create-test-environment.md +47 -0
- package/docs/reference/typescript-api/testing/error-result-guard.md +73 -0
- package/docs/reference/typescript-api/testing/get-superadmin-context.md +23 -0
- package/docs/reference/typescript-api/testing/index.md +5 -0
- package/docs/reference/typescript-api/testing/register-initializer.md +27 -0
- package/docs/reference/typescript-api/testing/simple-graph-qlclient.md +123 -0
- package/docs/reference/typescript-api/testing/test-config.md +30 -0
- package/docs/reference/typescript-api/testing/test-db-initializer.md +60 -0
- package/docs/reference/typescript-api/testing/test-environment.md +42 -0
- package/docs/reference/typescript-api/testing/test-server-options.md +47 -0
- package/docs/reference/typescript-api/testing/test-server.md +60 -0
- package/docs/reference/typescript-api/testing/testing-logger.md +140 -0
- package/docs/reference/typescript-api/worker/bootstrap-worker.md +76 -0
- package/docs/reference/typescript-api/worker/index.md +5 -0
- package/docs/reference/typescript-api/worker/vendure-worker.md +50 -0
- package/docs/reference/typescript-api/worker/worker-health-check-config.md +41 -0
- package/docs/user-guide/catalog/collections.md +27 -0
- package/docs/user-guide/catalog/facets.md +34 -0
- package/docs/user-guide/catalog/product-variants.png +0 -0
- package/docs/user-guide/catalog/products.md +35 -0
- package/docs/user-guide/catalog/screen-facet-add.webp +0 -0
- package/docs/user-guide/catalog/screen-facet-list.webp +0 -0
- package/docs/user-guide/catalog/screen-inventory.webp +0 -0
- package/docs/user-guide/customers/index.md +30 -0
- package/docs/user-guide/customers/screen-customer-group.webp +0 -0
- package/docs/user-guide/index.md +7 -0
- package/docs/user-guide/localization/index.md +42 -0
- package/docs/user-guide/localization/screen-ui-language.webp +0 -0
- package/docs/user-guide/orders/draft-orders.md +28 -0
- package/docs/user-guide/orders/order-state-diagram-for-admin.png +0 -0
- package/docs/user-guide/orders/orders.md +65 -0
- package/docs/user-guide/orders/screen-fulfillment-shipped.webp +0 -0
- package/docs/user-guide/orders/screen-fulfillment.webp +0 -0
- package/docs/user-guide/orders/screen-modification.webp +0 -0
- package/docs/user-guide/orders/screen-modify-button.webp +0 -0
- package/docs/user-guide/orders/screen-refund-button.webp +0 -0
- package/docs/user-guide/orders/screen-settle-payment.webp +0 -0
- package/docs/user-guide/promotions/index.md +44 -0
- package/docs/user-guide/settings/administrators-roles.md +34 -0
- package/docs/user-guide/settings/channels.md +18 -0
- package/docs/user-guide/settings/countries-zones.md +12 -0
- package/docs/user-guide/settings/global-settings.md +12 -0
- package/docs/user-guide/settings/payment-methods.md +32 -0
- package/docs/user-guide/settings/screen-shipping-test.webp +0 -0
- package/docs/user-guide/settings/screen-translations.webp +0 -0
- package/docs/user-guide/settings/shipping-methods.md +55 -0
- package/docs/user-guide/settings/taxes.md +32 -0
- package/package.json +32 -0
|
@@ -0,0 +1,1902 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Migrating from Admin UI
|
|
3
|
+
sidebar_position: 1
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Migrating from Admin UI
|
|
7
|
+
|
|
8
|
+
If you have existing extensions to the legacy Angular-based Admin UI, you will want to migrate to the new Dashboard to enjoy
|
|
9
|
+
an improved developer experience, many more customization options, and ongoing support from the Vendure team.
|
|
10
|
+
|
|
11
|
+
:::warning
|
|
12
|
+
The Angular Admin UI will not be maintained after **July 2026**. Until then, we will continue patching critical bugs and security issues.
|
|
13
|
+
Community contributions will always be merged and released.
|
|
14
|
+
:::
|
|
15
|
+
|
|
16
|
+
## Running In Parallel
|
|
17
|
+
|
|
18
|
+
A recommended approach to migrating is to run both the Admin UI _and_ the new Dashboard in parallel. This allows you to start building
|
|
19
|
+
new features right away with the new Dashboard while maintaining access to existing features that have not yet been migrated.
|
|
20
|
+
|
|
21
|
+
To do so, follow the instructions to [set up the Dashboard](/guides/extending-the-dashboard/getting-started/#installation--setup).
|
|
22
|
+
Both plugins can now be used simultaneously without any special configuration.
|
|
23
|
+
|
|
24
|
+
## AI-Assisted Migration
|
|
25
|
+
|
|
26
|
+
We highly recommend using AI tools such as Claude Code, Codex etc to assist with migrations from the legacy Angular-based UI extensions
|
|
27
|
+
to the new React-based Dashboard.
|
|
28
|
+
|
|
29
|
+
:::info
|
|
30
|
+
The results of AI-assisted migration are heavily dependent on the model that you use. We tested with
|
|
31
|
+
Claude Code using Sonnet 4.5 & Codex using gpt-5-codex
|
|
32
|
+
:::
|
|
33
|
+
|
|
34
|
+
In our testing, we were able to perform complete migrations quickly using the following approach:
|
|
35
|
+
|
|
36
|
+
1. Use the provided prompt or Claude skill and specify which plugin you wish to migrate (do 1 at a time)
|
|
37
|
+
2. Allow the AI tool to complete the migration
|
|
38
|
+
3. Manually clean up & fix any issues that remain
|
|
39
|
+
|
|
40
|
+
Using this approach we were able to migrate complete plugins involving list/details views, widgets, and custom field components
|
|
41
|
+
in around 20-30 minutes.
|
|
42
|
+
|
|
43
|
+
### Full Prompt
|
|
44
|
+
|
|
45
|
+
Give a prompt like this to your AI assistant and make sure to specify the plugin by path, i.e.:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
Migrate the plugin at @src/plugins/my-plugin/
|
|
49
|
+
to use the new dashboard.
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Then paste the following prompt in full:
|
|
53
|
+
|
|
54
|
+
<div style={{ width: '100%', height: '500px', overflow: 'auto', marginBottom: '20px' }}>
|
|
55
|
+
|
|
56
|
+
<!-- Note: the following code block should not be edited. It is auto-generated from the files in the
|
|
57
|
+
`.claude/skills/vendure-dashboard-migration` dir, by running the npm script `generate-migration-prompt` from
|
|
58
|
+
the `./docs` dir. -->
|
|
59
|
+
````md
|
|
60
|
+
## Instructions
|
|
61
|
+
|
|
62
|
+
1. If not explicitly stated by the user, find out which plugin they want to migrate.
|
|
63
|
+
2. Read and understand the overall rules for migration
|
|
64
|
+
- the "General" section below
|
|
65
|
+
- the "Common Tasks" section below
|
|
66
|
+
3. Check the tsconfig setup <tsconfig-setup>. This may or may not already be set up.
|
|
67
|
+
- the "TSConfig setup" section below
|
|
68
|
+
4. Identify each part of the Admin UI extensions that needs to be
|
|
69
|
+
migrated, and use the data from the appropriate sections to guide
|
|
70
|
+
the migration:
|
|
71
|
+
- the "Forms" section below
|
|
72
|
+
- the "Custom Field Inputs" section below
|
|
73
|
+
- the "List Pages" section below
|
|
74
|
+
- the "Detail Pages" section below
|
|
75
|
+
- the "Adding Nav Menu Items" section below
|
|
76
|
+
- the "Action Bar Items" section below
|
|
77
|
+
- the "Custom Detail Components" section below
|
|
78
|
+
- the "Page Tabs" section below
|
|
79
|
+
- the "Widgets" section below
|
|
80
|
+
5. Ensure you have followed the instructions marked "Important" for each section
|
|
81
|
+
|
|
82
|
+
## General
|
|
83
|
+
|
|
84
|
+
- For short we use "old" to refer to code written for the Angular Admin UI, and "new" for the React Dashboard
|
|
85
|
+
- old code is usually in a plugin's "ui" dir
|
|
86
|
+
- new code should be in a plugin's "dashboard" dir
|
|
87
|
+
- new code imports all components from `@vendure/dashboard`. It can also import the following as needed:
|
|
88
|
+
- hooks or anything else needed from `react`
|
|
89
|
+
- hooks etc from `@tanstack/react-query`
|
|
90
|
+
- `Link`, `useNavigate` etc from `@tanstack/react-router`
|
|
91
|
+
- `useForm` etc from `react-hook-form`
|
|
92
|
+
- `toast` from `sonner`
|
|
93
|
+
- icons from `lucide-react`
|
|
94
|
+
- for i18n: `Trans`, `useLingui` from `@lingui/react/macro`
|
|
95
|
+
- Default to the style conventions of the current project as much as possible (single vs double quotes,
|
|
96
|
+
indent size etc)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
## Directory Structure
|
|
100
|
+
Given as an example - projects may differ in conventions
|
|
101
|
+
|
|
102
|
+
### Old
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
- /path/to/plugin
|
|
106
|
+
- /ui
|
|
107
|
+
- providers.ts
|
|
108
|
+
- routes.ts
|
|
109
|
+
- /components
|
|
110
|
+
- /example
|
|
111
|
+
- example.component.ts
|
|
112
|
+
- example.component.html
|
|
113
|
+
- example.component.scss
|
|
114
|
+
- example.graphql.ts
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
### New
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
- /path/to/plugin
|
|
122
|
+
- /dashboard
|
|
123
|
+
- index.tsx
|
|
124
|
+
- /components
|
|
125
|
+
- example.tsx
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Registering extensions
|
|
129
|
+
|
|
130
|
+
### Old
|
|
131
|
+
|
|
132
|
+
```ts title="src/plugins/my-plugin/my.plugin.ts"
|
|
133
|
+
import * as path from 'path';
|
|
134
|
+
import { VendurePlugin } from '@vendure/core';
|
|
135
|
+
import { AdminUiExtension } from '@vendure/ui-devkit/compiler';
|
|
136
|
+
|
|
137
|
+
@VendurePlugin({
|
|
138
|
+
// ...
|
|
139
|
+
})
|
|
140
|
+
export class MyPlugin {
|
|
141
|
+
static ui: AdminUiExtension = {
|
|
142
|
+
id: 'my-plugin-ui',
|
|
143
|
+
extensionPath: path.join(__dirname, 'ui'),
|
|
144
|
+
routes: [{ route: 'my-plugin', filePath: 'routes.ts' }],
|
|
145
|
+
providers: ['providers.ts'],
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### New
|
|
151
|
+
|
|
152
|
+
```ts title="src/plugins/my-plugin/my.plugin.ts"
|
|
153
|
+
import { VendurePlugin } from '@vendure/core';
|
|
154
|
+
|
|
155
|
+
@VendurePlugin({
|
|
156
|
+
// ...
|
|
157
|
+
// Note that this needs to match the relative path to the
|
|
158
|
+
// index.tsx file from the plugin file
|
|
159
|
+
dashboard: '../dashboard/index.tsx',
|
|
160
|
+
})
|
|
161
|
+
export class MyPlugin {
|
|
162
|
+
// Do not remove any existing AdminUiExtension def
|
|
163
|
+
// to preserve backward compatibility
|
|
164
|
+
static ui: AdminUiExtension = { /* ... */ }
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Important:
|
|
169
|
+
- Ensure the `dashboard` path is correct relative to the locations of the plugin.ts file and the index.ts file
|
|
170
|
+
|
|
171
|
+
## Styling
|
|
172
|
+
|
|
173
|
+
### Old
|
|
174
|
+
|
|
175
|
+
custom design system based on Clarity UI
|
|
176
|
+
|
|
177
|
+
```html
|
|
178
|
+
<button class="button primary">Primary</button>
|
|
179
|
+
<button class="button secondary">Secondary</button>
|
|
180
|
+
<button class="button success">Success</button>
|
|
181
|
+
<button class="button warning">Warning</button>
|
|
182
|
+
<button class="button danger">Danger</button>
|
|
183
|
+
|
|
184
|
+
<button class="button-ghost">Ghost</button>
|
|
185
|
+
|
|
186
|
+
<a class="button-ghost" [routerLink]="['/extensions/my-plugin/my-custom-route']">
|
|
187
|
+
<clr-icon shape="arrow" dir="right"></clr-icon>
|
|
188
|
+
John Smith
|
|
189
|
+
</a>
|
|
190
|
+
|
|
191
|
+
<button class="button-small">Small</button>
|
|
192
|
+
|
|
193
|
+
<button class="button-small">
|
|
194
|
+
<clr-icon shape="layers"></clr-icon>
|
|
195
|
+
Assign to channel
|
|
196
|
+
</button>
|
|
197
|
+
|
|
198
|
+
<clr-icon shape="star" size="8"></clr-icon>
|
|
199
|
+
|
|
200
|
+
<img [src]="product.featuredAsset?.preview + '?preset=small'" alt="Product preview" />
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### New
|
|
204
|
+
|
|
205
|
+
tailwind + shadcn/ui. Shadcn components import from `@vendure/dashboard`
|
|
206
|
+
|
|
207
|
+
```tsx
|
|
208
|
+
import { Button, DetailPageButton, VendureImage } from '@vendure/dashboard';
|
|
209
|
+
import { Star } from 'lucide-react';
|
|
210
|
+
|
|
211
|
+
export function MyComponent() {
|
|
212
|
+
// non-exhaustive - all standard Shadcn props are available
|
|
213
|
+
return (
|
|
214
|
+
<Button variant="default">Primary</Button>
|
|
215
|
+
<Button variant="secondary">Secondary</Button>
|
|
216
|
+
<Button variant="outline">Outline</Button>
|
|
217
|
+
<Button variant="destructive">Danger</Button>
|
|
218
|
+
<Button variant="ghost">Ghost</Button>
|
|
219
|
+
|
|
220
|
+
<DetailPageButton id="123" label="John Smith" />
|
|
221
|
+
<DetailPageButton href="/affiliates/my-custom-route" label="John Smith" />
|
|
222
|
+
|
|
223
|
+
<Star />
|
|
224
|
+
|
|
225
|
+
<VendureImage
|
|
226
|
+
src={entity.product.featuredAsset}
|
|
227
|
+
alt={entity.product.name}
|
|
228
|
+
preset='small'
|
|
229
|
+
/>
|
|
230
|
+
)
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Important:
|
|
235
|
+
|
|
236
|
+
- When using `Badge`, prefer variant="secondary" unless especially important data
|
|
237
|
+
- Where possible avoid specific tailwind colours like `text-blue-600`. Instead use (where possible)
|
|
238
|
+
the Shadcn theme colours, eg:
|
|
239
|
+
```
|
|
240
|
+
--color-background
|
|
241
|
+
--color-foreground
|
|
242
|
+
--color-primary
|
|
243
|
+
--color-primary-foreground
|
|
244
|
+
--color-secondary
|
|
245
|
+
--color-secondary-foreground
|
|
246
|
+
--color-muted
|
|
247
|
+
--color-muted-foreground
|
|
248
|
+
--color-accent
|
|
249
|
+
--color-accent-foreground
|
|
250
|
+
--color-destructive
|
|
251
|
+
--color-destructive-foreground
|
|
252
|
+
--color-success
|
|
253
|
+
--color-success-foreground
|
|
254
|
+
```
|
|
255
|
+
- Buttons which link to detail pages should use `DetailPageButton`
|
|
256
|
+
|
|
257
|
+
## Data access
|
|
258
|
+
|
|
259
|
+
### Old
|
|
260
|
+
|
|
261
|
+
```ts
|
|
262
|
+
import { DataService } from '@vendure/admin-ui/core';
|
|
263
|
+
import { graphql } from "../gql";
|
|
264
|
+
|
|
265
|
+
export const GET_CUSTOMER_NAME = graphql(`
|
|
266
|
+
query GetCustomerName($id: ID!) {
|
|
267
|
+
customer(id: $id) {
|
|
268
|
+
id
|
|
269
|
+
firstName
|
|
270
|
+
lastName
|
|
271
|
+
addresses {
|
|
272
|
+
...AddressFragment
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
`);
|
|
277
|
+
|
|
278
|
+
this.dataService.query(GET_CUSTOMER_NAME, {
|
|
279
|
+
id: customerId,
|
|
280
|
+
}),
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### New
|
|
284
|
+
|
|
285
|
+
```ts
|
|
286
|
+
import { useQuery } from '@tanstack/react-query';
|
|
287
|
+
import { api } from '@vendure/dashboard';
|
|
288
|
+
import { graphql } from '@/gql';
|
|
289
|
+
|
|
290
|
+
const addressFragment = graphql(`
|
|
291
|
+
# ...
|
|
292
|
+
`);
|
|
293
|
+
|
|
294
|
+
const getCustomerNameDocument = graphql(`
|
|
295
|
+
query GetCustomerName($id: ID!) {
|
|
296
|
+
customer(id: $id) {
|
|
297
|
+
id
|
|
298
|
+
firstName
|
|
299
|
+
lastName
|
|
300
|
+
addresses {
|
|
301
|
+
...AddressFragment
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
`, [addressFragment]); // Fragments MUST be explicitly referenced
|
|
306
|
+
|
|
307
|
+
const { data, isLoading, error } = useQuery({
|
|
308
|
+
queryKey: ['customer-name', customerId],
|
|
309
|
+
queryFn: () => api.query(getCustomerNameDocument, { id: customerId }),
|
|
310
|
+
});
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
Note on graphql fragments: if common fragments are used across files, you may need
|
|
314
|
+
to extract them into a common-fragments.graphql.ts file, because with gql.tada they
|
|
315
|
+
*must* be explicitly referenced in every document that uses them.
|
|
316
|
+
|
|
317
|
+
## Common Tasks
|
|
318
|
+
|
|
319
|
+
### Formatting Dates, Currencies, and Numbers
|
|
320
|
+
|
|
321
|
+
```tsx
|
|
322
|
+
import {useLocalFormat} from '@vendure/dashboard';
|
|
323
|
+
// ...
|
|
324
|
+
// Intl API formatting tools
|
|
325
|
+
const {
|
|
326
|
+
formatCurrency,
|
|
327
|
+
formatNumber,
|
|
328
|
+
formatDate,
|
|
329
|
+
formatRelativeDate,
|
|
330
|
+
formatLanguageName,
|
|
331
|
+
formatRegionName,
|
|
332
|
+
formatCurrencyName,
|
|
333
|
+
toMajorUnits,
|
|
334
|
+
toMinorUnits,
|
|
335
|
+
} = useLocalFormat();
|
|
336
|
+
|
|
337
|
+
formatCurrency(value: number, currency: string, precision?: number)
|
|
338
|
+
formatCurrencyName(currencyCode: string, display: 'full' | 'symbol' | 'name' = 'full')
|
|
339
|
+
formatNumber(value: number) // human-readable
|
|
340
|
+
formatDate(value: string | Date, options?: Intl.DateTimeFormatOptions)
|
|
341
|
+
formatRelativeDate(value: string | Date, options?: Intl.RelativeTimeFormatOptions)
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### Links
|
|
345
|
+
|
|
346
|
+
Example link destinations:
|
|
347
|
+
- Customer detail | <Link to="/customers/$id" params={{ id }}>text</Link>
|
|
348
|
+
- Customer list | <Link to="/customers">text</Link>
|
|
349
|
+
- Order detail | <Link to="/orders/$id" params={{ id }}>text</Link>
|
|
350
|
+
|
|
351
|
+
Important: when linking to detail pages, prefer the `DetailPageButton`. If not in a table column,
|
|
352
|
+
add `className='border'`.
|
|
353
|
+
|
|
354
|
+
## TSConfig setup
|
|
355
|
+
|
|
356
|
+
If not already set up, we need to make sure we have configured tsconfig with:
|
|
357
|
+
|
|
358
|
+
1. jsx support. Usually create `tsconfig.dashboard.json` like this:
|
|
359
|
+
```json
|
|
360
|
+
{
|
|
361
|
+
"extends": "./tsconfig.json",
|
|
362
|
+
"compilerOptions": {
|
|
363
|
+
"composite": true,
|
|
364
|
+
"jsx": "react-jsx"
|
|
365
|
+
},
|
|
366
|
+
"include": [
|
|
367
|
+
"src/dashboard/**/*.ts",
|
|
368
|
+
"src/dashboard/**/*.tsx"
|
|
369
|
+
]
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
then reference it from the appropriate tsconfig.json
|
|
373
|
+
```
|
|
374
|
+
{
|
|
375
|
+
// ...etc
|
|
376
|
+
"references": [
|
|
377
|
+
{
|
|
378
|
+
"path": "./tsconfig.dashboard.json"
|
|
379
|
+
},
|
|
380
|
+
]
|
|
381
|
+
}
|
|
382
|
+
```
|
|
383
|
+
This may already be set up (check this). In an Nx-like monorepo
|
|
384
|
+
where each plugin is a separate project, this will need to be done
|
|
385
|
+
per-plugin.
|
|
386
|
+
2. Path mapping.
|
|
387
|
+
```json
|
|
388
|
+
"paths": {
|
|
389
|
+
// Import alias for the GraphQL types, this needs to point to
|
|
390
|
+
// the location specified in the vite.config.mts file as `gqlOutputPath`
|
|
391
|
+
// so will vary depending on project structure
|
|
392
|
+
"@/gql": ["./apps/server/src/gql/graphql.ts"],
|
|
393
|
+
// This line allows TypeScript to properly resolve internal
|
|
394
|
+
// Vendure Dashboard imports, which is necessary for
|
|
395
|
+
// type safety in your dashboard extensions.
|
|
396
|
+
// This path assumes a root-level tsconfig.json file.
|
|
397
|
+
// You may need to adjust it if your project structure is different.
|
|
398
|
+
"@/vdb/*": [
|
|
399
|
+
"./node_modules/@vendure/dashboard/src/lib/*"
|
|
400
|
+
}
|
|
401
|
+
```
|
|
402
|
+
In an Nx-like monorepo, this would be added to the tsconfig.base.json or
|
|
403
|
+
equivalent.
|
|
404
|
+
|
|
405
|
+
## Forms
|
|
406
|
+
|
|
407
|
+
### Old (Angular)
|
|
408
|
+
```html
|
|
409
|
+
<div class="form-grid">
|
|
410
|
+
<vdr-form-field label="Page title">
|
|
411
|
+
<input type="text" />
|
|
412
|
+
</vdr-form-field>
|
|
413
|
+
<vdr-form-field label="Select input">
|
|
414
|
+
<select>
|
|
415
|
+
<option>Option 1</option>
|
|
416
|
+
<option>Option 2</option>
|
|
417
|
+
</select>
|
|
418
|
+
</vdr-form-field>
|
|
419
|
+
<vdr-form-field label="Checkbox input">
|
|
420
|
+
<input type="checkbox" />
|
|
421
|
+
</vdr-form-field>
|
|
422
|
+
<vdr-form-field label="Textarea input">
|
|
423
|
+
<textarea></textarea>
|
|
424
|
+
</vdr-form-field>
|
|
425
|
+
<vdr-form-field label="Invalid with error">
|
|
426
|
+
<input type="text" [formControl]="invalidFormControl" />
|
|
427
|
+
</vdr-form-field>
|
|
428
|
+
<vdr-rich-text-editor
|
|
429
|
+
class="form-grid-span"
|
|
430
|
+
label="Description"
|
|
431
|
+
></vdr-rich-text-editor>
|
|
432
|
+
</div>
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
### New (React Dashboard)
|
|
436
|
+
```tsx
|
|
437
|
+
<PageBlock column="main" blockId="main-form">
|
|
438
|
+
<DetailFormGrid>
|
|
439
|
+
<FormFieldWrapper
|
|
440
|
+
control={form.control}
|
|
441
|
+
name="title"
|
|
442
|
+
label="Title"
|
|
443
|
+
render={({ field }) => <Input {...field} />}
|
|
444
|
+
/>
|
|
445
|
+
<FormFieldWrapper
|
|
446
|
+
control={form.control}
|
|
447
|
+
name="slug"
|
|
448
|
+
label="Slug"
|
|
449
|
+
render={({ field }) => <Input {...field} />}
|
|
450
|
+
/>
|
|
451
|
+
</DetailFormGrid>
|
|
452
|
+
<div className="space-y-6">
|
|
453
|
+
<FormFieldWrapper
|
|
454
|
+
control={form.control}
|
|
455
|
+
name="body"
|
|
456
|
+
label="Content"
|
|
457
|
+
render={({ field }) => (
|
|
458
|
+
<RichTextInput value={field.value ?? ''} onChange={field.onChange} />
|
|
459
|
+
)}
|
|
460
|
+
/>
|
|
461
|
+
</div>
|
|
462
|
+
</PageBlock>;
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
## Custom Field Inputs
|
|
466
|
+
|
|
467
|
+
### Old (Angular)
|
|
468
|
+
|
|
469
|
+
```ts title="src/plugins/common/ui/components/slider-form-input/slider-form-input.component.ts"
|
|
470
|
+
import { Component } from '@angular/core';
|
|
471
|
+
import { FormControl } from '@angular/forms';
|
|
472
|
+
import { IntCustomFieldConfig, SharedModule, FormInputComponent } from '@vendure/admin-ui/core';
|
|
473
|
+
|
|
474
|
+
@Component({
|
|
475
|
+
template: `
|
|
476
|
+
<input
|
|
477
|
+
type="range"
|
|
478
|
+
[min]="config.min || 0"
|
|
479
|
+
[max]="config.max || 100"
|
|
480
|
+
[formControl]="formControl" />
|
|
481
|
+
{{ formControl.value }}
|
|
482
|
+
`,
|
|
483
|
+
standalone: true,
|
|
484
|
+
imports: [SharedModule],
|
|
485
|
+
})
|
|
486
|
+
export class SliderControlComponent implements FormInputComponent<IntCustomFieldConfig> {
|
|
487
|
+
readonly: boolean;
|
|
488
|
+
config: IntCustomFieldConfig;
|
|
489
|
+
formControl: FormControl;
|
|
490
|
+
}
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
```ts title="src/plugins/common/ui/providers.ts"
|
|
494
|
+
import { registerFormInputComponent } from '@vendure/admin-ui/core';
|
|
495
|
+
import { SliderControlComponent } from './components/slider-form-input/slider-form-input.component';
|
|
496
|
+
|
|
497
|
+
export default [
|
|
498
|
+
registerFormInputComponent('slider-form-input', SliderControlComponent),
|
|
499
|
+
];
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
### New (React Dashboard)
|
|
503
|
+
|
|
504
|
+
```tsx title="src/plugins/my-plugin/dashboard/components/color-picker.tsx"
|
|
505
|
+
import { Button, Card, CardContent, cn, DashboardFormComponent, Input } from '@vendure/dashboard';
|
|
506
|
+
import { useState } from 'react';
|
|
507
|
+
import { useFormContext } from 'react-hook-form';
|
|
508
|
+
|
|
509
|
+
// By typing your component as DashboardFormComponent, the props will be correctly typed
|
|
510
|
+
export const ColorPickerComponent: DashboardFormComponent = ({ value, onChange, name }) => {
|
|
511
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
512
|
+
|
|
513
|
+
const { getFieldState } = useFormContext();
|
|
514
|
+
const error = getFieldState(name).error;
|
|
515
|
+
const colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FECA57', '#FF9FF3', '#54A0FF', '#5F27CD'];
|
|
516
|
+
|
|
517
|
+
return (
|
|
518
|
+
<div className="space-y-2">
|
|
519
|
+
<div className="flex items-center space-x-2">
|
|
520
|
+
<Button
|
|
521
|
+
type="button"
|
|
522
|
+
variant="outline"
|
|
523
|
+
size="icon"
|
|
524
|
+
className={cn('w-8 h-8 border-2 border-gray-300 p-0', error && 'border-red-500')}
|
|
525
|
+
style={{ backgroundColor: error ? 'transparent' : value || '#ffffff' }}
|
|
526
|
+
onClick={() => setIsOpen(!isOpen)}
|
|
527
|
+
/>
|
|
528
|
+
<Input value={value || ''} onChange={e => onChange(e.target.value)} placeholder="#ffffff" />
|
|
529
|
+
</div>
|
|
530
|
+
|
|
531
|
+
{isOpen && (
|
|
532
|
+
<Card>
|
|
533
|
+
<CardContent className="grid grid-cols-4 gap-2 p-2">
|
|
534
|
+
{colors.map(color => (
|
|
535
|
+
<Button
|
|
536
|
+
key={color}
|
|
537
|
+
type="button"
|
|
538
|
+
variant="outline"
|
|
539
|
+
size="icon"
|
|
540
|
+
className="w-8 h-8 border-2 border-gray-300 hover:border-gray-500 p-0"
|
|
541
|
+
style={{ backgroundColor: color }}
|
|
542
|
+
onClick={() => {
|
|
543
|
+
onChange(color);
|
|
544
|
+
setIsOpen(false);
|
|
545
|
+
}}
|
|
546
|
+
/>
|
|
547
|
+
))}
|
|
548
|
+
</CardContent>
|
|
549
|
+
</Card>
|
|
550
|
+
)}
|
|
551
|
+
</div>
|
|
552
|
+
);
|
|
553
|
+
};
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
```tsx title="src/plugins/my-plugin/dashboard/index.tsx"
|
|
557
|
+
import { defineDashboardExtension } from '@vendure/dashboard';
|
|
558
|
+
import { ColorPickerComponent } from './components/color-picker';
|
|
559
|
+
|
|
560
|
+
defineDashboardExtension({
|
|
561
|
+
customFormComponents: {
|
|
562
|
+
// Custom field components for custom fields
|
|
563
|
+
customFields: [
|
|
564
|
+
{
|
|
565
|
+
// The "id" is a global identifier for this custom component. We will
|
|
566
|
+
// reference it in the next step.
|
|
567
|
+
id: 'color-picker',
|
|
568
|
+
component: ColorPickerComponent,
|
|
569
|
+
},
|
|
570
|
+
],
|
|
571
|
+
},
|
|
572
|
+
// ... other extension properties
|
|
573
|
+
});
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
## List Pages
|
|
577
|
+
|
|
578
|
+
### Old (Angular)
|
|
579
|
+
```ts
|
|
580
|
+
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
|
581
|
+
import { TypedBaseListComponent, SharedModule } from '@vendure/admin-ui/core';
|
|
582
|
+
// This is the TypedDocumentNode generated by GraphQL Code Generator
|
|
583
|
+
import { graphql } from '../../gql';
|
|
584
|
+
|
|
585
|
+
const getReviewListDocument = graphql(`
|
|
586
|
+
query GetReviewList($options: ReviewListOptions) {
|
|
587
|
+
reviews(options: $options) {
|
|
588
|
+
items {
|
|
589
|
+
id
|
|
590
|
+
createdAt
|
|
591
|
+
updatedAt
|
|
592
|
+
title
|
|
593
|
+
rating
|
|
594
|
+
text
|
|
595
|
+
authorName
|
|
596
|
+
productId
|
|
597
|
+
}
|
|
598
|
+
totalItems
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
`);
|
|
602
|
+
|
|
603
|
+
@Component({
|
|
604
|
+
selector: 'review-list',
|
|
605
|
+
templateUrl: './review-list.component.html',
|
|
606
|
+
styleUrls: ['./review-list.component.scss'],
|
|
607
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
608
|
+
standalone: true,
|
|
609
|
+
imports: [SharedModule],
|
|
610
|
+
})
|
|
611
|
+
export class ReviewListComponent extends TypedBaseListComponent<typeof getReviewListDocument, 'reviews'> {
|
|
612
|
+
|
|
613
|
+
// Here we set up the filters that will be available
|
|
614
|
+
// to use in the data table
|
|
615
|
+
readonly filters = this.createFilterCollection()
|
|
616
|
+
.addIdFilter()
|
|
617
|
+
.addDateFilters()
|
|
618
|
+
.addFilter({
|
|
619
|
+
name: 'title',
|
|
620
|
+
type: {kind: 'text'},
|
|
621
|
+
label: 'Title',
|
|
622
|
+
filterField: 'title',
|
|
623
|
+
})
|
|
624
|
+
.addFilter({
|
|
625
|
+
name: 'rating',
|
|
626
|
+
type: {kind: 'number'},
|
|
627
|
+
label: 'Rating',
|
|
628
|
+
filterField: 'rating',
|
|
629
|
+
})
|
|
630
|
+
.addFilter({
|
|
631
|
+
name: 'authorName',
|
|
632
|
+
type: {kind: 'text'},
|
|
633
|
+
label: 'Author',
|
|
634
|
+
filterField: 'authorName',
|
|
635
|
+
})
|
|
636
|
+
.connectToRoute(this.route);
|
|
637
|
+
|
|
638
|
+
// Here we set up the sorting options that will be available
|
|
639
|
+
// to use in the data table
|
|
640
|
+
readonly sorts = this.createSortCollection()
|
|
641
|
+
.defaultSort('createdAt', 'DESC')
|
|
642
|
+
.addSort({name: 'createdAt'})
|
|
643
|
+
.addSort({name: 'updatedAt'})
|
|
644
|
+
.addSort({name: 'title'})
|
|
645
|
+
.addSort({name: 'rating'})
|
|
646
|
+
.addSort({name: 'authorName'})
|
|
647
|
+
.connectToRoute(this.route);
|
|
648
|
+
|
|
649
|
+
constructor() {
|
|
650
|
+
super();
|
|
651
|
+
super.configure({
|
|
652
|
+
document: getReviewListDocument,
|
|
653
|
+
getItems: data => data.reviews,
|
|
654
|
+
setVariables: (skip, take) => ({
|
|
655
|
+
options: {
|
|
656
|
+
skip,
|
|
657
|
+
take,
|
|
658
|
+
filter: {
|
|
659
|
+
title: {
|
|
660
|
+
contains: this.searchTermControl.value,
|
|
661
|
+
},
|
|
662
|
+
...this.filters.createFilterInput(),
|
|
663
|
+
},
|
|
664
|
+
sort: this.sorts.createSortInput(),
|
|
665
|
+
},
|
|
666
|
+
}),
|
|
667
|
+
refreshListOnChanges: [this.filters.valueChanges, this.sorts.valueChanges],
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
```html
|
|
674
|
+
<!-- optional if you want some buttons at the top -->
|
|
675
|
+
<vdr-page-block>
|
|
676
|
+
<vdr-action-bar>
|
|
677
|
+
<vdr-ab-left></vdr-ab-left>
|
|
678
|
+
<vdr-ab-right>
|
|
679
|
+
<a class="btn btn-primary" *vdrIfPermissions="['CreateReview']" [routerLink]="['./', 'create']">
|
|
680
|
+
<clr-icon shape="plus"></clr-icon>
|
|
681
|
+
Create a review
|
|
682
|
+
</a>
|
|
683
|
+
</vdr-ab-right>
|
|
684
|
+
</vdr-action-bar>
|
|
685
|
+
</vdr-page-block>
|
|
686
|
+
|
|
687
|
+
<!-- The data table -->
|
|
688
|
+
<vdr-data-table-2
|
|
689
|
+
id="review-list"
|
|
690
|
+
[items]="items$ | async"
|
|
691
|
+
[itemsPerPage]="itemsPerPage$ | async"
|
|
692
|
+
[totalItems]="totalItems$ | async"
|
|
693
|
+
[currentPage]="currentPage$ | async"
|
|
694
|
+
[filters]="filters"
|
|
695
|
+
(pageChange)="setPageNumber($event)"
|
|
696
|
+
(itemsPerPageChange)="setItemsPerPage($event)"
|
|
697
|
+
>
|
|
698
|
+
<!-- optional if you want to support bulk actions -->
|
|
699
|
+
<vdr-bulk-action-menu
|
|
700
|
+
locationId="review-list"
|
|
701
|
+
[hostComponent]="this"
|
|
702
|
+
[selectionManager]="selectionManager"
|
|
703
|
+
/>
|
|
704
|
+
|
|
705
|
+
<!-- Adds a search bar -->
|
|
706
|
+
<vdr-dt2-search
|
|
707
|
+
[searchTermControl]="searchTermControl"
|
|
708
|
+
searchTermPlaceholder="Filter by title"
|
|
709
|
+
/>
|
|
710
|
+
|
|
711
|
+
<!-- Here we define all the available columns -->
|
|
712
|
+
<vdr-dt2-column id="id" [heading]="'common.id' | translate" [hiddenByDefault]="true">
|
|
713
|
+
<ng-template let-review="item">
|
|
714
|
+
{{ review.id }}
|
|
715
|
+
</ng-template>
|
|
716
|
+
</vdr-dt2-column>
|
|
717
|
+
<vdr-dt2-column
|
|
718
|
+
id="created-at"
|
|
719
|
+
[heading]="'common.created-at' | translate"
|
|
720
|
+
[hiddenByDefault]="true"
|
|
721
|
+
[sort]="sorts.get('createdAt')"
|
|
722
|
+
>
|
|
723
|
+
<ng-template let-review="item">
|
|
724
|
+
{{ review.createdAt | localeDate : 'short' }}
|
|
725
|
+
</ng-template>
|
|
726
|
+
</vdr-dt2-column>
|
|
727
|
+
<vdr-dt2-column
|
|
728
|
+
id="updated-at"
|
|
729
|
+
[heading]="'common.updated-at' | translate"
|
|
730
|
+
[hiddenByDefault]="true"
|
|
731
|
+
[sort]="sorts.get('updatedAt')"
|
|
732
|
+
>
|
|
733
|
+
<ng-template let-review="item">
|
|
734
|
+
{{ review.updatedAt | localeDate : 'short' }}
|
|
735
|
+
</ng-template>
|
|
736
|
+
</vdr-dt2-column>
|
|
737
|
+
<vdr-dt2-column id="title" heading="Title" [optional]="false" [sort]="sorts.get('title')">
|
|
738
|
+
<ng-template let-review="item">
|
|
739
|
+
<a class="button-ghost" [routerLink]="['./', review.id]"
|
|
740
|
+
><span>{{ review.title }}</span>
|
|
741
|
+
<clr-icon shape="arrow right"></clr-icon>
|
|
742
|
+
</a>
|
|
743
|
+
</ng-template>
|
|
744
|
+
</vdr-dt2-column>
|
|
745
|
+
<vdr-dt2-column id="rating" heading="Rating" [sort]="sorts.get('rating')">
|
|
746
|
+
<ng-template let-review="item"><my-star-rating-component [rating]="review.rating" /></ng-template>
|
|
747
|
+
</vdr-dt2-column>
|
|
748
|
+
<vdr-dt2-column id="author" heading="Author" [sort]="sorts.get('authorName')">
|
|
749
|
+
<ng-template let-review="item">{{ review.authorName }}</ng-template>
|
|
750
|
+
</vdr-dt2-column>
|
|
751
|
+
</vdr-data-table-2>
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
```ts
|
|
755
|
+
import { registerRouteComponent } from '@vendure/admin-ui/core';
|
|
756
|
+
|
|
757
|
+
import { ReviewListComponent } from './components/review-list/review-list.component';
|
|
758
|
+
|
|
759
|
+
export default [
|
|
760
|
+
registerRouteComponent({
|
|
761
|
+
path: '',
|
|
762
|
+
component: ReviewListComponent,
|
|
763
|
+
breadcrumb: 'Product reviews',
|
|
764
|
+
}),
|
|
765
|
+
]
|
|
766
|
+
```
|
|
767
|
+
|
|
768
|
+
### New (React Dashboard)
|
|
769
|
+
|
|
770
|
+
```tsx
|
|
771
|
+
import {
|
|
772
|
+
Button,
|
|
773
|
+
DashboardRouteDefinition,
|
|
774
|
+
ListPage,
|
|
775
|
+
PageActionBarRight,
|
|
776
|
+
DetailPageButton,
|
|
777
|
+
} from '@vendure/dashboard';
|
|
778
|
+
import { Link } from '@tanstack/react-router';
|
|
779
|
+
import { PlusIcon } from 'lucide-react';
|
|
780
|
+
|
|
781
|
+
// This function is generated for you by the `vendureDashboardPlugin` in your Vite config.
|
|
782
|
+
// It uses gql-tada to generate TypeScript types which give you type safety as you write
|
|
783
|
+
// your queries and mutations.
|
|
784
|
+
import { graphql } from '@/gql';
|
|
785
|
+
|
|
786
|
+
// The fields you select here will be automatically used to generate the appropriate columns in the
|
|
787
|
+
// data table below.
|
|
788
|
+
const getArticleList = graphql(`
|
|
789
|
+
query GetArticles($options: ArticleListOptions) {
|
|
790
|
+
articles(options: $options) {
|
|
791
|
+
items {
|
|
792
|
+
id
|
|
793
|
+
createdAt
|
|
794
|
+
updatedAt
|
|
795
|
+
isPublished
|
|
796
|
+
title
|
|
797
|
+
slug
|
|
798
|
+
body
|
|
799
|
+
customFields
|
|
800
|
+
}
|
|
801
|
+
totalItems
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
`);
|
|
805
|
+
|
|
806
|
+
const deleteArticleDocument = graphql(`
|
|
807
|
+
mutation DeleteArticle($id: ID!) {
|
|
808
|
+
deleteArticle(id: $id) {
|
|
809
|
+
result
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
`);
|
|
813
|
+
|
|
814
|
+
export const articleList: DashboardRouteDefinition = {
|
|
815
|
+
navMenuItem: {
|
|
816
|
+
sectionId: 'catalog',
|
|
817
|
+
id: 'articles',
|
|
818
|
+
url: '/articles',
|
|
819
|
+
title: 'CMS Articles',
|
|
820
|
+
},
|
|
821
|
+
path: '/articles',
|
|
822
|
+
loader: () => ({
|
|
823
|
+
breadcrumb: 'Articles',
|
|
824
|
+
}),
|
|
825
|
+
component: route => (
|
|
826
|
+
<ListPage
|
|
827
|
+
pageId="article-list"
|
|
828
|
+
title="Articles"
|
|
829
|
+
listQuery={getArticleList}
|
|
830
|
+
deleteMutation={deleteArticleDocument}
|
|
831
|
+
route={route}
|
|
832
|
+
customizeColumns={{
|
|
833
|
+
title: {
|
|
834
|
+
cell: ({ row }) => {
|
|
835
|
+
const post = row.original;
|
|
836
|
+
return <DetailPageButton id={post.id} label={post.title} />;
|
|
837
|
+
},
|
|
838
|
+
},
|
|
839
|
+
}}
|
|
840
|
+
defaultVisibility={{
|
|
841
|
+
type: true,
|
|
842
|
+
summary: true,
|
|
843
|
+
state: true,
|
|
844
|
+
rating: true,
|
|
845
|
+
authorName: true,
|
|
846
|
+
authorLocation: true,
|
|
847
|
+
}}
|
|
848
|
+
defaultColumnOrder={[
|
|
849
|
+
'type',
|
|
850
|
+
'summary',
|
|
851
|
+
'authorName',
|
|
852
|
+
'authorLocation',
|
|
853
|
+
'rating',
|
|
854
|
+
]}
|
|
855
|
+
>
|
|
856
|
+
<PageActionBarRight>
|
|
857
|
+
<Button asChild>
|
|
858
|
+
<Link to="./new">
|
|
859
|
+
<PlusIcon className="mr-2 h-4 w-4" />
|
|
860
|
+
New article
|
|
861
|
+
</Link>
|
|
862
|
+
</Button>
|
|
863
|
+
</PageActionBarRight>
|
|
864
|
+
</ListPage>
|
|
865
|
+
),
|
|
866
|
+
};
|
|
867
|
+
```
|
|
868
|
+
|
|
869
|
+
Important:
|
|
870
|
+
- When using `defaultVisibility`, specify the specific visible ones with `true`. *Do not* mix
|
|
871
|
+
true and false values. It is implicit that any not specified will default to `false`.
|
|
872
|
+
- The `id`, `createdAt` and `updatedAt` never need to be specified in `customizeColumns`, defaultVisibility` or `defaultColumnOrder`.
|
|
873
|
+
They are handled correctly by default.
|
|
874
|
+
- By default the DataTable will handle column names based on the field name,
|
|
875
|
+
e.g. `authorName` -> `Author Name`, `rating` -> `Rating`, so an explicit cell header is
|
|
876
|
+
not needed unless the column header title must significantly differ from the field name.
|
|
877
|
+
- If a custom `cell` function needs to access fields _other_ than the one being rendered,
|
|
878
|
+
those other fields *must* be declared as dependencies:
|
|
879
|
+
```tsx
|
|
880
|
+
customizeColumns={{
|
|
881
|
+
name: {
|
|
882
|
+
// Note, we DO NOT need to declare "name" as a dependency here,
|
|
883
|
+
// since we are handling the `name` column already.
|
|
884
|
+
meta: { dependencies: ['reviewCount'] },
|
|
885
|
+
cell: ({ row }) => {
|
|
886
|
+
const { name, reviewCount } = row.original;
|
|
887
|
+
return <Badge variant="outline">{name} ({reviewCount})</Badge>
|
|
888
|
+
},
|
|
889
|
+
},
|
|
890
|
+
}}
|
|
891
|
+
```
|
|
892
|
+
|
|
893
|
+
## Detail Pages
|
|
894
|
+
|
|
895
|
+
### Old (Angular)
|
|
896
|
+
```ts
|
|
897
|
+
import { ResultOf } from '@graphql-typed-document-node/core';
|
|
898
|
+
import { ChangeDetectionStrategy, Component, OnInit, OnDestroy } from '@angular/core';
|
|
899
|
+
import { FormBuilder } from '@angular/forms';
|
|
900
|
+
import { TypedBaseDetailComponent, LanguageCode, NotificationService, SharedModule } from '@vendure/admin-ui/core';
|
|
901
|
+
|
|
902
|
+
// This is the TypedDocumentNode & type generated by GraphQL Code Generator
|
|
903
|
+
import { graphql } from '../../gql';
|
|
904
|
+
|
|
905
|
+
export const reviewDetailFragment = graphql(`
|
|
906
|
+
fragment ReviewDetail on ProductReview {
|
|
907
|
+
id
|
|
908
|
+
createdAt
|
|
909
|
+
updatedAt
|
|
910
|
+
title
|
|
911
|
+
rating
|
|
912
|
+
text
|
|
913
|
+
authorName
|
|
914
|
+
productId
|
|
915
|
+
}
|
|
916
|
+
`);
|
|
917
|
+
|
|
918
|
+
export const getReviewDetailDocument = graphql(`
|
|
919
|
+
query GetReviewDetail($id: ID!) {
|
|
920
|
+
review(id: $id) {
|
|
921
|
+
...ReviewDetail
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
`);
|
|
925
|
+
|
|
926
|
+
export const createReviewDocument = graphql(`
|
|
927
|
+
mutation CreateReview($input: CreateProductReviewInput!) {
|
|
928
|
+
createProductReview(input: $input) {
|
|
929
|
+
...ReviewDetail
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
`);
|
|
933
|
+
|
|
934
|
+
export const updateReviewDocument = graphql(`
|
|
935
|
+
mutation UpdateReview($input: UpdateProductReviewInput!) {
|
|
936
|
+
updateProductReview(input: $input) {
|
|
937
|
+
...ReviewDetail
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
`);
|
|
941
|
+
|
|
942
|
+
@Component({
|
|
943
|
+
selector: 'review-detail',
|
|
944
|
+
templateUrl: './review-detail.component.html',
|
|
945
|
+
styleUrls: ['./review-detail.component.scss'],
|
|
946
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
947
|
+
standalone: true,
|
|
948
|
+
imports: [SharedModule],
|
|
949
|
+
})
|
|
950
|
+
export class ReviewDetailComponent extends TypedBaseDetailComponent<typeof getReviewDetailDocument, 'review'> implements OnInit, OnDestroy {
|
|
951
|
+
detailForm = this.formBuilder.group({
|
|
952
|
+
title: [''],
|
|
953
|
+
rating: [1],
|
|
954
|
+
authorName: [''],
|
|
955
|
+
});
|
|
956
|
+
|
|
957
|
+
constructor(private formBuilder: FormBuilder, private notificationService: NotificationService) {
|
|
958
|
+
super();
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
ngOnInit() {
|
|
962
|
+
this.init();
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
ngOnDestroy() {
|
|
966
|
+
this.destroy();
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
create() {
|
|
970
|
+
const { title, rating, authorName } = this.detailForm.value;
|
|
971
|
+
if (!title || rating == null || !authorName) {
|
|
972
|
+
return;
|
|
973
|
+
}
|
|
974
|
+
this.dataService
|
|
975
|
+
.mutate(createReviewDocument, {
|
|
976
|
+
input: { title, rating, authorName },
|
|
977
|
+
})
|
|
978
|
+
.subscribe(({ createProductReview }) => {
|
|
979
|
+
if (createProductReview.id) {
|
|
980
|
+
this.notificationService.success('Review created');
|
|
981
|
+
this.router.navigate(['extensions', 'reviews', createProductReview.id]);
|
|
982
|
+
}
|
|
983
|
+
});
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
update() {
|
|
987
|
+
const { title, rating, authorName } = this.detailForm.value;
|
|
988
|
+
this.dataService
|
|
989
|
+
.mutate(updateReviewDocument, {
|
|
990
|
+
input: { id: this.id, title, rating, authorName },
|
|
991
|
+
})
|
|
992
|
+
.subscribe(() => {
|
|
993
|
+
this.notificationService.success('Review updated');
|
|
994
|
+
});
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
protected setFormValues(entity: NonNullable<ResultOf<typeof getReviewDetailDocument>['review']>, languageCode: LanguageCode): void {
|
|
998
|
+
this.detailForm.patchValue({
|
|
999
|
+
title: entity.name,
|
|
1000
|
+
rating: entity.rating,
|
|
1001
|
+
authorName: entity.authorName,
|
|
1002
|
+
productId: entity.productId,
|
|
1003
|
+
});
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
```
|
|
1007
|
+
|
|
1008
|
+
```html
|
|
1009
|
+
<vdr-page-block>
|
|
1010
|
+
<vdr-action-bar>
|
|
1011
|
+
<vdr-ab-left></vdr-ab-left>
|
|
1012
|
+
<vdr-ab-right>
|
|
1013
|
+
<button
|
|
1014
|
+
class="button primary"
|
|
1015
|
+
*ngIf="isNew$ | async; else updateButton"
|
|
1016
|
+
(click)="create()"
|
|
1017
|
+
[disabled]="detailForm.pristine || detailForm.invalid"
|
|
1018
|
+
>
|
|
1019
|
+
{{ 'common.create' | translate }}
|
|
1020
|
+
</button>
|
|
1021
|
+
<ng-template #updateButton>
|
|
1022
|
+
<button
|
|
1023
|
+
class="btn btn-primary"
|
|
1024
|
+
(click)="update()"
|
|
1025
|
+
[disabled]="detailForm.pristine || detailForm.invalid"
|
|
1026
|
+
>
|
|
1027
|
+
{{ 'common.update' | translate }}
|
|
1028
|
+
</button>
|
|
1029
|
+
</ng-template>
|
|
1030
|
+
</vdr-ab-right>
|
|
1031
|
+
</vdr-action-bar>
|
|
1032
|
+
</vdr-page-block>
|
|
1033
|
+
|
|
1034
|
+
<form class="form" [formGroup]="detailForm">
|
|
1035
|
+
<vdr-page-detail-layout>
|
|
1036
|
+
<!-- The sidebar is used for displaying "metadata" type information about the entity -->
|
|
1037
|
+
<vdr-page-detail-sidebar>
|
|
1038
|
+
<vdr-card *ngIf="entity$ | async as entity">
|
|
1039
|
+
<vdr-page-entity-info [entity]="entity" />
|
|
1040
|
+
</vdr-card>
|
|
1041
|
+
</vdr-page-detail-sidebar>
|
|
1042
|
+
|
|
1043
|
+
<!-- The main content area is used for displaying the entity's fields -->
|
|
1044
|
+
<vdr-page-block>
|
|
1045
|
+
<!-- The vdr-card is the container for grouping items together on a page -->
|
|
1046
|
+
<!-- it can also take an optional [title] property to display a title -->
|
|
1047
|
+
<vdr-card>
|
|
1048
|
+
<!-- the form-grid class is used to lay out the form fields -->
|
|
1049
|
+
<div class="form-grid">
|
|
1050
|
+
<vdr-form-field label="Title" for="title">
|
|
1051
|
+
<input id="title" type="text" formControlName="title" />
|
|
1052
|
+
</vdr-form-field>
|
|
1053
|
+
<vdr-form-field label="Rating" for="rating">
|
|
1054
|
+
<input id="rating" type="number" min="1" max="5" formControlName="rating" />
|
|
1055
|
+
</vdr-form-field>
|
|
1056
|
+
|
|
1057
|
+
<!-- etc -->
|
|
1058
|
+
</div>
|
|
1059
|
+
</vdr-card>
|
|
1060
|
+
</vdr-page-block>
|
|
1061
|
+
</vdr-page-detail-layout>
|
|
1062
|
+
</form>
|
|
1063
|
+
```
|
|
1064
|
+
|
|
1065
|
+
```ts
|
|
1066
|
+
import { registerRouteComponent } from '@vendure/admin-ui/core';
|
|
1067
|
+
|
|
1068
|
+
import { ReviewDetailComponent, getReviewDetailDocument } from './components/review-detail/review-detail.component';
|
|
1069
|
+
|
|
1070
|
+
export default [
|
|
1071
|
+
registerRouteComponent({
|
|
1072
|
+
path: ':id',
|
|
1073
|
+
component: ReviewDetailComponent,
|
|
1074
|
+
query: getReviewDetailDocument,
|
|
1075
|
+
entityKey: 'productReview',
|
|
1076
|
+
getBreadcrumbs: entity => [
|
|
1077
|
+
{
|
|
1078
|
+
label: 'Product reviews',
|
|
1079
|
+
link: ['/extensions', 'product-reviews'],
|
|
1080
|
+
},
|
|
1081
|
+
{
|
|
1082
|
+
label: `#${entity?.id} (${entity?.product.name})`,
|
|
1083
|
+
link: [],
|
|
1084
|
+
},
|
|
1085
|
+
],
|
|
1086
|
+
}),
|
|
1087
|
+
]
|
|
1088
|
+
```
|
|
1089
|
+
|
|
1090
|
+
### New (React Dashboard)
|
|
1091
|
+
|
|
1092
|
+
```tsx
|
|
1093
|
+
import {
|
|
1094
|
+
DashboardRouteDefinition,
|
|
1095
|
+
detailPageRouteLoader,
|
|
1096
|
+
useDetailPage,
|
|
1097
|
+
Page,
|
|
1098
|
+
PageTitle,
|
|
1099
|
+
PageActionBar,
|
|
1100
|
+
PageActionBarRight,
|
|
1101
|
+
PermissionGuard,
|
|
1102
|
+
Button,
|
|
1103
|
+
PageLayout,
|
|
1104
|
+
PageBlock,
|
|
1105
|
+
FormFieldWrapper,
|
|
1106
|
+
DetailFormGrid,
|
|
1107
|
+
Switch,
|
|
1108
|
+
Input,
|
|
1109
|
+
RichTextInput,
|
|
1110
|
+
CustomFieldsPageBlock,
|
|
1111
|
+
} from '@vendure/dashboard';
|
|
1112
|
+
import { AnyRoute, useNavigate } from '@tanstack/react-router';
|
|
1113
|
+
import { toast } from 'sonner';
|
|
1114
|
+
|
|
1115
|
+
import { graphql } from '@/gql';
|
|
1116
|
+
|
|
1117
|
+
const articleDetailDocument = graphql(`
|
|
1118
|
+
query GetArticleDetail($id: ID!) {
|
|
1119
|
+
article(id: $id) {
|
|
1120
|
+
id
|
|
1121
|
+
createdAt
|
|
1122
|
+
updatedAt
|
|
1123
|
+
isPublished
|
|
1124
|
+
title
|
|
1125
|
+
slug
|
|
1126
|
+
body
|
|
1127
|
+
customFields
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
`);
|
|
1131
|
+
|
|
1132
|
+
const createArticleDocument = graphql(`
|
|
1133
|
+
mutation CreateArticle($input: CreateArticleInput!) {
|
|
1134
|
+
createArticle(input: $input) {
|
|
1135
|
+
id
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
`);
|
|
1139
|
+
|
|
1140
|
+
const updateArticleDocument = graphql(`
|
|
1141
|
+
mutation UpdateArticle($input: UpdateArticleInput!) {
|
|
1142
|
+
updateArticle(input: $input) {
|
|
1143
|
+
id
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
`);
|
|
1147
|
+
|
|
1148
|
+
export const articleDetail: DashboardRouteDefinition = {
|
|
1149
|
+
path: '/articles/$id',
|
|
1150
|
+
loader: detailPageRouteLoader({
|
|
1151
|
+
queryDocument: articleDetailDocument,
|
|
1152
|
+
breadcrumb: (isNew, entity) => [
|
|
1153
|
+
{ path: '/articles', label: 'Articles' },
|
|
1154
|
+
isNew ? 'New article' : entity?.title,
|
|
1155
|
+
],
|
|
1156
|
+
}),
|
|
1157
|
+
component: route => {
|
|
1158
|
+
return <ArticleDetailPage route={route} />;
|
|
1159
|
+
},
|
|
1160
|
+
};
|
|
1161
|
+
|
|
1162
|
+
function ArticleDetailPage({ route }: { route: AnyRoute }) {
|
|
1163
|
+
const params = route.useParams();
|
|
1164
|
+
const navigate = useNavigate();
|
|
1165
|
+
const creatingNewEntity = params.id === 'new';
|
|
1166
|
+
|
|
1167
|
+
const { form, submitHandler, entity, isPending, resetForm, refreshEntity } = useDetailPage({
|
|
1168
|
+
queryDocument: articleDetailDocument,
|
|
1169
|
+
createDocument: createArticleDocument,
|
|
1170
|
+
updateDocument: updateArticleDocument,
|
|
1171
|
+
setValuesForUpdate: article => {
|
|
1172
|
+
return {
|
|
1173
|
+
id: article?.id ?? '',
|
|
1174
|
+
isPublished: article?.isPublished ?? false,
|
|
1175
|
+
title: article?.title ?? '',
|
|
1176
|
+
slug: article?.slug ?? '',
|
|
1177
|
+
body: article?.body ?? '',
|
|
1178
|
+
};
|
|
1179
|
+
},
|
|
1180
|
+
params: { id: params.id },
|
|
1181
|
+
onSuccess: async data => {
|
|
1182
|
+
toast.success('Successfully updated article');
|
|
1183
|
+
resetForm();
|
|
1184
|
+
if (creatingNewEntity) {
|
|
1185
|
+
await navigate({ to: `../$id`, params: { id: data.id } });
|
|
1186
|
+
}
|
|
1187
|
+
},
|
|
1188
|
+
onError: err => {
|
|
1189
|
+
toast.error('Failed to update article', {
|
|
1190
|
+
description: err instanceof Error ? err.message : 'Unknown error',
|
|
1191
|
+
});
|
|
1192
|
+
},
|
|
1193
|
+
});
|
|
1194
|
+
|
|
1195
|
+
return (
|
|
1196
|
+
<Page pageId="article-detail" form={form} submitHandler={submitHandler}>
|
|
1197
|
+
<PageTitle>{creatingNewEntity ? 'New article' : (entity?.title ?? '')}</PageTitle>
|
|
1198
|
+
<PageActionBar>
|
|
1199
|
+
<PageActionBarRight>
|
|
1200
|
+
<PermissionGuard requires={['UpdateProduct', 'UpdateCatalog']}>
|
|
1201
|
+
<Button
|
|
1202
|
+
type="submit"
|
|
1203
|
+
disabled={!form.formState.isDirty || !form.formState.isValid || isPending}
|
|
1204
|
+
>
|
|
1205
|
+
Update
|
|
1206
|
+
</Button>
|
|
1207
|
+
</PermissionGuard>
|
|
1208
|
+
</PageActionBarRight>
|
|
1209
|
+
</PageActionBar>
|
|
1210
|
+
<PageLayout>
|
|
1211
|
+
<PageBlock column="side" blockId="publish-status" title="Status" description="Current status of this article">
|
|
1212
|
+
<FormFieldWrapper
|
|
1213
|
+
control={form.control}
|
|
1214
|
+
name="isPublished"
|
|
1215
|
+
label="Is Published"
|
|
1216
|
+
render={({ field }) => (
|
|
1217
|
+
<Switch checked={field.value} onCheckedChange={field.onChange} />
|
|
1218
|
+
)}
|
|
1219
|
+
/>
|
|
1220
|
+
</PageBlock>
|
|
1221
|
+
<PageBlock column="main" blockId="main-form">
|
|
1222
|
+
<DetailFormGrid>
|
|
1223
|
+
<FormFieldWrapper
|
|
1224
|
+
control={form.control}
|
|
1225
|
+
name="title"
|
|
1226
|
+
label="Title"
|
|
1227
|
+
render={({ field }) => <Input {...field} />}
|
|
1228
|
+
/>
|
|
1229
|
+
<FormFieldWrapper
|
|
1230
|
+
control={form.control}
|
|
1231
|
+
name="slug"
|
|
1232
|
+
label="Slug"
|
|
1233
|
+
render={({ field }) => <Input {...field} />}
|
|
1234
|
+
/>
|
|
1235
|
+
</DetailFormGrid>
|
|
1236
|
+
<div className="space-y-6">
|
|
1237
|
+
<FormFieldWrapper
|
|
1238
|
+
control={form.control}
|
|
1239
|
+
name="body"
|
|
1240
|
+
label="Content"
|
|
1241
|
+
render={({ field }) => (
|
|
1242
|
+
<RichTextInput value={field.value ?? ''} onChange={field.onChange} />
|
|
1243
|
+
)}
|
|
1244
|
+
/>
|
|
1245
|
+
</div>
|
|
1246
|
+
</PageBlock>
|
|
1247
|
+
<CustomFieldsPageBlock column="main" entityType="Article" control={form.control} />
|
|
1248
|
+
</PageLayout>
|
|
1249
|
+
</Page>
|
|
1250
|
+
);
|
|
1251
|
+
}
|
|
1252
|
+
```
|
|
1253
|
+
|
|
1254
|
+
Important:
|
|
1255
|
+
- The PageBlock component should *never* contain any Card-like component, because it already
|
|
1256
|
+
renders like a card.
|
|
1257
|
+
- Use `refreshEntity` to trigger a manual reload of the entity data (e.g. after a mutation
|
|
1258
|
+
succeeds)
|
|
1259
|
+
- The `DetailFormGrid` has a built-in `mb-6`, but for components not wrapped in this,
|
|
1260
|
+
manually ensure there is a y gap of 6 (e.g. wrap in `<div className="space-y-6">`)
|
|
1261
|
+
|
|
1262
|
+
## Adding Nav Menu Items
|
|
1263
|
+
|
|
1264
|
+
### Old (Angular)
|
|
1265
|
+
```ts
|
|
1266
|
+
import { addNavMenuSection } from '@vendure/admin-ui/core';
|
|
1267
|
+
|
|
1268
|
+
export default [
|
|
1269
|
+
addNavMenuSection({
|
|
1270
|
+
id: 'greeter',
|
|
1271
|
+
label: 'My Extensions',
|
|
1272
|
+
items: [{
|
|
1273
|
+
id: 'greeter',
|
|
1274
|
+
label: 'Greeter',
|
|
1275
|
+
routerLink: ['/extensions/greet'],
|
|
1276
|
+
// Icon can be any of https://core.clarity.design/foundation/icons/shapes/
|
|
1277
|
+
icon: 'cursor-hand-open',
|
|
1278
|
+
}],
|
|
1279
|
+
},
|
|
1280
|
+
// Add this section before the "settings" section
|
|
1281
|
+
'settings'),
|
|
1282
|
+
];
|
|
1283
|
+
```
|
|
1284
|
+
|
|
1285
|
+
### New (React Dashboard)
|
|
1286
|
+
|
|
1287
|
+
```tsx
|
|
1288
|
+
import { defineDashboardExtension } from '@vendure/dashboard';
|
|
1289
|
+
|
|
1290
|
+
defineDashboardExtension({
|
|
1291
|
+
routes: [
|
|
1292
|
+
{
|
|
1293
|
+
path: '/my-custom-page',
|
|
1294
|
+
component: () => <div>My Custom Page</div>,
|
|
1295
|
+
navMenuItem: {
|
|
1296
|
+
// The section where this item should appear
|
|
1297
|
+
sectionId: 'catalog',
|
|
1298
|
+
// Unique identifier for this menu item
|
|
1299
|
+
id: 'my-custom-page',
|
|
1300
|
+
// Display text in the navigation
|
|
1301
|
+
title: 'My Custom Page',
|
|
1302
|
+
// Optional: URL if different from path
|
|
1303
|
+
url: '/my-custom-page',
|
|
1304
|
+
},
|
|
1305
|
+
},
|
|
1306
|
+
],
|
|
1307
|
+
});
|
|
1308
|
+
```
|
|
1309
|
+
|
|
1310
|
+
## Action Bar Items
|
|
1311
|
+
|
|
1312
|
+
### Old (Angular)
|
|
1313
|
+
```ts
|
|
1314
|
+
import { addActionBarItem } from '@vendure/admin-ui/core';
|
|
1315
|
+
|
|
1316
|
+
export default [
|
|
1317
|
+
addActionBarItem({
|
|
1318
|
+
id: 'print-invoice',
|
|
1319
|
+
locationId: 'order-detail',
|
|
1320
|
+
label: 'Print invoice',
|
|
1321
|
+
icon: 'printer',
|
|
1322
|
+
routerLink: route => {
|
|
1323
|
+
const id = route.snapshot.params.id;
|
|
1324
|
+
return ['./extensions/order-invoices', id];
|
|
1325
|
+
},
|
|
1326
|
+
requiresPermission: 'ReadOrder',
|
|
1327
|
+
}),
|
|
1328
|
+
];
|
|
1329
|
+
```
|
|
1330
|
+
|
|
1331
|
+
### New (React Dashboard)
|
|
1332
|
+
|
|
1333
|
+
```tsx
|
|
1334
|
+
import { Button, defineDashboardExtension } from '@vendure/dashboard';
|
|
1335
|
+
import { useState } from 'react';
|
|
1336
|
+
|
|
1337
|
+
defineDashboardExtension({
|
|
1338
|
+
actionBarItems: [
|
|
1339
|
+
{
|
|
1340
|
+
pageId: 'product-detail',
|
|
1341
|
+
component: ({ context }) => {
|
|
1342
|
+
const [count, setCount] = useState(0);
|
|
1343
|
+
return (
|
|
1344
|
+
<Button type="button" variant="secondary" onClick={() => setCount(x => x + 1)}>
|
|
1345
|
+
Counter: {count}
|
|
1346
|
+
</Button>
|
|
1347
|
+
);
|
|
1348
|
+
},
|
|
1349
|
+
},
|
|
1350
|
+
],
|
|
1351
|
+
});
|
|
1352
|
+
```
|
|
1353
|
+
|
|
1354
|
+
## Custom Detail Components
|
|
1355
|
+
|
|
1356
|
+
### Old (Angular)
|
|
1357
|
+
```ts title="src/plugins/cms/ui/components/product-info/product-info.component.ts"
|
|
1358
|
+
import { Component, OnInit } from '@angular/core';
|
|
1359
|
+
import { Observable, switchMap } from 'rxjs';
|
|
1360
|
+
import { FormGroup } from '@angular/forms';
|
|
1361
|
+
import { DataService, CustomDetailComponent, SharedModule } from '@vendure/admin-ui/core';
|
|
1362
|
+
import { CmsDataService } from '../../providers/cms-data.service';
|
|
1363
|
+
|
|
1364
|
+
@Component({
|
|
1365
|
+
template: `
|
|
1366
|
+
<vdr-card title="CMS Info">
|
|
1367
|
+
<pre>{{ extraInfo$ | async | json }}</pre>
|
|
1368
|
+
</vdr-card>`,
|
|
1369
|
+
standalone: true,
|
|
1370
|
+
providers: [CmsDataService],
|
|
1371
|
+
imports: [SharedModule],
|
|
1372
|
+
})
|
|
1373
|
+
export class ProductInfoComponent implements CustomDetailComponent, OnInit {
|
|
1374
|
+
// These two properties are provided by Vendure and will vary
|
|
1375
|
+
// depending on the particular detail page you are embedding this
|
|
1376
|
+
// component into. In this case, it will be a "product" entity.
|
|
1377
|
+
entity$: Observable<any>
|
|
1378
|
+
detailForm: FormGroup;
|
|
1379
|
+
|
|
1380
|
+
extraInfo$: Observable<any>;
|
|
1381
|
+
|
|
1382
|
+
constructor(private cmsDataService: CmsDataService) {
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
ngOnInit() {
|
|
1386
|
+
this.extraInfo$ = this.entity$.pipe(
|
|
1387
|
+
switchMap(entity => this.cmsDataService.getDataFor(entity.id))
|
|
1388
|
+
);
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
```
|
|
1392
|
+
|
|
1393
|
+
### New (React Dashboard)
|
|
1394
|
+
|
|
1395
|
+
```tsx title="src/plugins/my-plugin/dashboard/index.tsx"
|
|
1396
|
+
import { defineDashboardExtension } from '@vendure/dashboard';
|
|
1397
|
+
|
|
1398
|
+
defineDashboardExtension({
|
|
1399
|
+
pageBlocks: [
|
|
1400
|
+
{
|
|
1401
|
+
id: 'related-articles',
|
|
1402
|
+
title: 'Related Articles',
|
|
1403
|
+
location: {
|
|
1404
|
+
// This is the pageId of the page where this block will be
|
|
1405
|
+
pageId: 'product-detail',
|
|
1406
|
+
// can be "main" or "side"
|
|
1407
|
+
column: 'side',
|
|
1408
|
+
position: {
|
|
1409
|
+
// Blocks are positioned relative to existing blocks on
|
|
1410
|
+
// the page.
|
|
1411
|
+
blockId: 'facet-values',
|
|
1412
|
+
// Can be "before", "after" or "replace"
|
|
1413
|
+
// Here we'll place it after the `facet-values` block.
|
|
1414
|
+
order: 'after',
|
|
1415
|
+
},
|
|
1416
|
+
},
|
|
1417
|
+
component: ({ context }) => {
|
|
1418
|
+
// In the component, you can use the `context` prop to
|
|
1419
|
+
// access the entity and the form instance.
|
|
1420
|
+
return <div className="text-sm">Articles related to {context.entity.name}</div>;
|
|
1421
|
+
},
|
|
1422
|
+
},
|
|
1423
|
+
],
|
|
1424
|
+
});
|
|
1425
|
+
```
|
|
1426
|
+
|
|
1427
|
+
## Page Tabs
|
|
1428
|
+
|
|
1429
|
+
### Old (Angular)
|
|
1430
|
+
```ts
|
|
1431
|
+
import { registerPageTab } from '@vendure/admin-ui/core';
|
|
1432
|
+
|
|
1433
|
+
import { ReviewListComponent } from './components/review-list/review-list.component';
|
|
1434
|
+
|
|
1435
|
+
export default [
|
|
1436
|
+
registerPageTab({
|
|
1437
|
+
location: 'product-detail',
|
|
1438
|
+
tab: 'Reviews',
|
|
1439
|
+
route: 'reviews',
|
|
1440
|
+
tabIcon: 'star',
|
|
1441
|
+
component: ReviewListComponent,
|
|
1442
|
+
}),
|
|
1443
|
+
];
|
|
1444
|
+
```
|
|
1445
|
+
|
|
1446
|
+
### New (React Dashboard)
|
|
1447
|
+
|
|
1448
|
+
Page tabs are not supported by the Dashboard. Suggest alternative such as a new route.
|
|
1449
|
+
|
|
1450
|
+
## Widgets
|
|
1451
|
+
|
|
1452
|
+
### Old (Angular)
|
|
1453
|
+
```ts title="src/plugins/reviews/ui/components/reviews-widget/reviews-widget.component.ts"
|
|
1454
|
+
import { Component, OnInit } from '@angular/core';
|
|
1455
|
+
import { DataService, SharedModule } from '@vendure/admin-ui/core';
|
|
1456
|
+
import { Observable } from 'rxjs';
|
|
1457
|
+
|
|
1458
|
+
@Component({
|
|
1459
|
+
selector: 'reviews-widget',
|
|
1460
|
+
template: `
|
|
1461
|
+
<ul>
|
|
1462
|
+
<li *ngFor="let review of pendingReviews$ | async">
|
|
1463
|
+
<a [routerLink]="['/extensions', 'product-reviews', review.id]">{{ review.summary }}</a>
|
|
1464
|
+
<span class="rating">{{ review.rating }} / 5</span>
|
|
1465
|
+
</li>
|
|
1466
|
+
</ul>
|
|
1467
|
+
`,
|
|
1468
|
+
standalone: true,
|
|
1469
|
+
imports: [SharedModule],
|
|
1470
|
+
})
|
|
1471
|
+
export class ReviewsWidgetComponent implements OnInit {
|
|
1472
|
+
pendingReviews$: Observable<any[]>;
|
|
1473
|
+
|
|
1474
|
+
constructor(private dataService: DataService) {}
|
|
1475
|
+
|
|
1476
|
+
ngOnInit() {
|
|
1477
|
+
this.pendingReviews$ = this.dataService.query(gql`
|
|
1478
|
+
query GetAllReviews($options: ProductReviewListOptions) {
|
|
1479
|
+
productReviews(options: $options) {
|
|
1480
|
+
items {
|
|
1481
|
+
id
|
|
1482
|
+
createdAt
|
|
1483
|
+
authorName
|
|
1484
|
+
summary
|
|
1485
|
+
rating
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
}`, {
|
|
1489
|
+
options: {
|
|
1490
|
+
filter: { state: { eq: 'new' } },
|
|
1491
|
+
take: 10,
|
|
1492
|
+
},
|
|
1493
|
+
})
|
|
1494
|
+
.mapStream(data => data.productReviews.items);
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
```
|
|
1498
|
+
|
|
1499
|
+
```ts title="src/plugins/reviews/ui/providers.ts"
|
|
1500
|
+
import { registerDashboardWidget } from '@vendure/admin-ui/core';
|
|
1501
|
+
|
|
1502
|
+
export default [
|
|
1503
|
+
registerDashboardWidget('reviews', {
|
|
1504
|
+
title: 'Latest reviews',
|
|
1505
|
+
supportedWidths: [4, 6, 8, 12],
|
|
1506
|
+
requiresPermissions: ['ReadReview'],
|
|
1507
|
+
loadComponent: () =>
|
|
1508
|
+
import('./reviews-widget/reviews-widget.component').then(
|
|
1509
|
+
m => m.ReviewsWidgetComponent,
|
|
1510
|
+
),
|
|
1511
|
+
}),
|
|
1512
|
+
];
|
|
1513
|
+
```
|
|
1514
|
+
|
|
1515
|
+
### New (React Dashboard)
|
|
1516
|
+
|
|
1517
|
+
```tsx title="custom-widget.tsx"
|
|
1518
|
+
import { Badge, DashboardBaseWidget, useLocalFormat, useWidgetFilters } from '@vendure/dashboard';
|
|
1519
|
+
|
|
1520
|
+
export function CustomWidget() {
|
|
1521
|
+
const { dateRange } = useWidgetFilters();
|
|
1522
|
+
const { formatDate } = useLocalFormat();
|
|
1523
|
+
return (
|
|
1524
|
+
<DashboardBaseWidget id="custom-widget" title="Custom Widget" description="This is a custom widget">
|
|
1525
|
+
<div className="flex flex-wrap gap-1">
|
|
1526
|
+
<span>Displaying results from</span>
|
|
1527
|
+
<Badge variant="secondary">{formatDate(dateRange.from)}</Badge>
|
|
1528
|
+
<span>to</span>
|
|
1529
|
+
<Badge variant="secondary">{formatDate(dateRange.to)}</Badge>
|
|
1530
|
+
</div>
|
|
1531
|
+
</DashboardBaseWidget>
|
|
1532
|
+
);
|
|
1533
|
+
}
|
|
1534
|
+
```
|
|
1535
|
+
|
|
1536
|
+
```tsx title="index.tsx"
|
|
1537
|
+
import { defineDashboardExtension } from '@vendure/dashboard';
|
|
1538
|
+
|
|
1539
|
+
import { CustomWidget } from './custom-widget';
|
|
1540
|
+
|
|
1541
|
+
defineDashboardExtension({
|
|
1542
|
+
widgets: [
|
|
1543
|
+
{
|
|
1544
|
+
id: 'custom-widget',
|
|
1545
|
+
name: 'Custom Widget',
|
|
1546
|
+
component: CustomWidget,
|
|
1547
|
+
defaultSize: { w: 3, h: 3 },
|
|
1548
|
+
},
|
|
1549
|
+
],
|
|
1550
|
+
});
|
|
1551
|
+
```
|
|
1552
|
+
````
|
|
1553
|
+
|
|
1554
|
+
</div>
|
|
1555
|
+
|
|
1556
|
+
:::tip
|
|
1557
|
+
The full prompt is quite large, so it can make sense to first clear the current LLM context,
|
|
1558
|
+
e.g. with `/clear` in Claude Code or `/new` in Codex CLI
|
|
1559
|
+
:::
|
|
1560
|
+
|
|
1561
|
+
### Claude Skills
|
|
1562
|
+
|
|
1563
|
+
If you use Claude Code, you can use [Agent Skills](https://docs.claude.com/en/docs/agents-and-tools/agent-skills/overview) to set
|
|
1564
|
+
up a specialized skill for migrating plugins. This has the advantage that you do not need to continually paste in the full prompt,
|
|
1565
|
+
and it can also be potentially more token-efficient.
|
|
1566
|
+
|
|
1567
|
+
To set up a the skill, run this from the root of your project:
|
|
1568
|
+
|
|
1569
|
+
```
|
|
1570
|
+
npx degit vendure-ecommerce/vendure/.claude/skills#minor .claude/skills
|
|
1571
|
+
```
|
|
1572
|
+
|
|
1573
|
+
This command uses [degit](https://github.com/Rich-Harris/degit) to copy over the vendure-dashboard-migration skill to
|
|
1574
|
+
your local `./claude/skills` directory.
|
|
1575
|
+
|
|
1576
|
+
You can then have Claude Code use the skill with a prompt like:
|
|
1577
|
+
|
|
1578
|
+
```
|
|
1579
|
+
Use the vendure-dashboard-migration skill to migrate
|
|
1580
|
+
@src/plugins/my-plugin to use the dashboard
|
|
1581
|
+
```
|
|
1582
|
+
|
|
1583
|
+
:::note
|
|
1584
|
+
The individual files in the skill contain the exact same content as the full prompt above,
|
|
1585
|
+
but are more easily reused and can be more token-efficient
|
|
1586
|
+
:::
|
|
1587
|
+
|
|
1588
|
+
### Manual Cleanup
|
|
1589
|
+
|
|
1590
|
+
It is very likely you'll still need to do _some_ manual cleanup after an AI-assisted migration. You might run into
|
|
1591
|
+
things like:
|
|
1592
|
+
|
|
1593
|
+
- Non-optimum styling choices
|
|
1594
|
+
- Issues with the [tsconfig setup](/guides/extending-the-dashboard/getting-started/#installation--setup) not being perfectly implemented.
|
|
1595
|
+
- For more complex repo structures like a monorepo with plugins as separate libs, you may need to manually implement
|
|
1596
|
+
the initial setup of the config files.
|
|
1597
|
+
|
|
1598
|
+
## Manual Migration
|
|
1599
|
+
|
|
1600
|
+
If you would rather do a full manual migration, you should first follow the [Dashboard Getting Started guide](/guides/extending-the-dashboard/getting-started/)
|
|
1601
|
+
and the [Extending the Dashboard guide](http://localhost:3001/guides/extending-the-dashboard/extending-overview/).
|
|
1602
|
+
|
|
1603
|
+
The remainder of this document details specific features, and how they are now implemented in the new Dashboard.
|
|
1604
|
+
|
|
1605
|
+
### Forms
|
|
1606
|
+
|
|
1607
|
+
Forms in the Angular Admin UI used `vdr-form-field` components within a `form-grid` class. In the Dashboard, forms use `FormFieldWrapper` with react-hook-form, wrapped in either `DetailFormGrid` for grid layouts or div containers with `space-y-6` for vertical spacing.
|
|
1608
|
+
|
|
1609
|
+
| Admin UI | Dashboard | Imported From | Notes |
|
|
1610
|
+
|----------|-----------|---------------|-------|
|
|
1611
|
+
| `vdr-form-field` | `FormFieldWrapper` | `@vendure/dashboard` | Uses react-hook-form |
|
|
1612
|
+
| `form-grid` (class) | `DetailFormGrid` | `@vendure/dashboard` | For grid layouts |
|
|
1613
|
+
| `vdr-rich-text-editor` | `RichTextInput` | `@vendure/dashboard` | |
|
|
1614
|
+
| - | `Input` | `@vendure/dashboard` | Basic text input |
|
|
1615
|
+
| `FormGroup` | `useForm` | `react-hook-form` | Form state management |
|
|
1616
|
+
|
|
1617
|
+
```tsx
|
|
1618
|
+
<PageBlock column="main" blockId="main-form">
|
|
1619
|
+
<DetailFormGrid>
|
|
1620
|
+
<FormFieldWrapper
|
|
1621
|
+
control={form.control}
|
|
1622
|
+
name="title"
|
|
1623
|
+
label="Title"
|
|
1624
|
+
render={({ field }) => <Input {...field} />}
|
|
1625
|
+
/>
|
|
1626
|
+
</DetailFormGrid>
|
|
1627
|
+
<div className="space-y-6">
|
|
1628
|
+
<FormFieldWrapper
|
|
1629
|
+
control={form.control}
|
|
1630
|
+
name="body"
|
|
1631
|
+
label="Content"
|
|
1632
|
+
render={({ field }) => (
|
|
1633
|
+
<RichTextInput value={field.value ?? ''} onChange={field.onChange} />
|
|
1634
|
+
)}
|
|
1635
|
+
/>
|
|
1636
|
+
</div>
|
|
1637
|
+
</PageBlock>
|
|
1638
|
+
```
|
|
1639
|
+
|
|
1640
|
+
### Custom Field Inputs
|
|
1641
|
+
|
|
1642
|
+
Custom field inputs now use the `DashboardFormComponent` type and are registered via `customFormComponents.customFields` in the Dashboard extension definition. Components receive `value`, `onChange`, and `name` props, and can use `useFormContext()` to access field state and errors.
|
|
1643
|
+
|
|
1644
|
+
| Admin UI | Dashboard | Imported From | Notes |
|
|
1645
|
+
|----------|-----------|---------------|-------|
|
|
1646
|
+
| `FormInputComponent<T>` | `DashboardFormComponent` | `@vendure/dashboard` | Type for custom field components |
|
|
1647
|
+
| `registerFormInputComponent()` | `customFormComponents.customFields` | `@vendure/dashboard` | Registration method |
|
|
1648
|
+
| `formControl` (prop) | `value`, `onChange`, `name` (props) | - | Component receives these props |
|
|
1649
|
+
| - | `useFormContext()` | `react-hook-form` | Access field state and errors |
|
|
1650
|
+
|
|
1651
|
+
```tsx
|
|
1652
|
+
export const ColorPickerComponent: DashboardFormComponent = ({ value, onChange, name }) => {
|
|
1653
|
+
const { getFieldState } = useFormContext();
|
|
1654
|
+
const error = getFieldState(name).error;
|
|
1655
|
+
|
|
1656
|
+
return (
|
|
1657
|
+
<Input value={value || ''} onChange={e => onChange(e.target.value)} />
|
|
1658
|
+
);
|
|
1659
|
+
};
|
|
1660
|
+
|
|
1661
|
+
// Register in index.tsx
|
|
1662
|
+
defineDashboardExtension({
|
|
1663
|
+
customFormComponents: {
|
|
1664
|
+
customFields: [
|
|
1665
|
+
{ id: 'color-picker', component: ColorPickerComponent },
|
|
1666
|
+
],
|
|
1667
|
+
},
|
|
1668
|
+
});
|
|
1669
|
+
```
|
|
1670
|
+
|
|
1671
|
+
### List Pages
|
|
1672
|
+
|
|
1673
|
+
List pages migrate from `TypedBaseListComponent` to the `ListPage` component. The `ListPage` automatically generates columns from the GraphQL query fields. Use `customizeColumns` to customize specific columns (e.g., linking with `DetailPageButton`), `defaultVisibility` to control which columns show by default, and `defaultColumnOrder` to set column order.
|
|
1674
|
+
|
|
1675
|
+
| Admin UI | Dashboard | Imported From | Notes |
|
|
1676
|
+
|----------|-----------|---------------|-------|
|
|
1677
|
+
| `TypedBaseListComponent` | `ListPage` | `@vendure/dashboard` | Main list component |
|
|
1678
|
+
| `vdr-data-table-2` | `ListPage` | `@vendure/dashboard` | Auto-generates columns |
|
|
1679
|
+
| `vdr-dt2-column` | `customizeColumns` | - | Prop on `ListPage` |
|
|
1680
|
+
| `[hiddenByDefault]` | `defaultVisibility` | - | Prop on `ListPage` |
|
|
1681
|
+
| `registerRouteComponent()` | `DashboardRouteDefinition` | `@vendure/dashboard` | Route registration |
|
|
1682
|
+
| `[routerLink]` | `DetailPageButton` | `@vendure/dashboard` | For linking to detail pages |
|
|
1683
|
+
|
|
1684
|
+
```tsx
|
|
1685
|
+
export const articleList: DashboardRouteDefinition = {
|
|
1686
|
+
path: '/articles',
|
|
1687
|
+
component: route => (
|
|
1688
|
+
<ListPage
|
|
1689
|
+
pageId="article-list"
|
|
1690
|
+
title="Articles"
|
|
1691
|
+
listQuery={getArticleList}
|
|
1692
|
+
deleteMutation={deleteArticleDocument}
|
|
1693
|
+
route={route}
|
|
1694
|
+
customizeColumns={{
|
|
1695
|
+
title: {
|
|
1696
|
+
cell: ({ row }) => <DetailPageButton id={row.original.id} label={row.original.title} />,
|
|
1697
|
+
},
|
|
1698
|
+
}}
|
|
1699
|
+
defaultVisibility={{
|
|
1700
|
+
title: true,
|
|
1701
|
+
authorName: true,
|
|
1702
|
+
}}
|
|
1703
|
+
>
|
|
1704
|
+
<PageActionBarRight>
|
|
1705
|
+
<Button asChild>
|
|
1706
|
+
<Link to="./new"><PlusIcon /> New article</Link>
|
|
1707
|
+
</Button>
|
|
1708
|
+
</PageActionBarRight>
|
|
1709
|
+
</ListPage>
|
|
1710
|
+
),
|
|
1711
|
+
};
|
|
1712
|
+
```
|
|
1713
|
+
|
|
1714
|
+
**Important**: When using `defaultVisibility`, only specify visible columns with `true`. The `id`, `createdAt`, and `updatedAt` columns are handled automatically. If a custom `cell` function accesses fields other than the one being rendered, declare them in `meta.dependencies`.
|
|
1715
|
+
|
|
1716
|
+
### Detail Pages
|
|
1717
|
+
|
|
1718
|
+
Detail pages migrate from `TypedBaseDetailComponent` to the `useDetailPage` hook. The hook handles form initialization, entity loading, and mutations. Use `detailPageRouteLoader` for the route loader, and structure the page with `Page`, `PageActionBar`, `PageLayout`, `PageBlock`, and `DetailFormGrid` components.
|
|
1719
|
+
|
|
1720
|
+
| Admin UI | Dashboard | Imported From | Notes |
|
|
1721
|
+
|----------|-----------|---------------|-------|
|
|
1722
|
+
| `TypedBaseDetailComponent` | `useDetailPage()` | `@vendure/dashboard` | Hook for detail page logic |
|
|
1723
|
+
| `this.init()` | `useDetailPage()` | `@vendure/dashboard` | Automatic initialization |
|
|
1724
|
+
| `this.entity$` | `entity` | - | Returned from `useDetailPage` |
|
|
1725
|
+
| `FormBuilder` | `form` | - | Returned from `useDetailPage` |
|
|
1726
|
+
| `dataService.mutate()` | `submitHandler` | - | Returned from `useDetailPage` |
|
|
1727
|
+
| `vdr-page-detail-layout` | `PageLayout` | `@vendure/dashboard` | Layout component |
|
|
1728
|
+
| `vdr-page-block` | `PageBlock` | `@vendure/dashboard` | Content block |
|
|
1729
|
+
| `registerRouteComponent()` | `detailPageRouteLoader()` | `@vendure/dashboard` | Route loader helper |
|
|
1730
|
+
|
|
1731
|
+
```tsx
|
|
1732
|
+
export const articleDetail: DashboardRouteDefinition = {
|
|
1733
|
+
path: '/articles/$id',
|
|
1734
|
+
loader: detailPageRouteLoader({
|
|
1735
|
+
queryDocument: articleDetailDocument,
|
|
1736
|
+
breadcrumb: (isNew, entity) => [
|
|
1737
|
+
{ path: '/articles', label: 'Articles' },
|
|
1738
|
+
isNew ? 'New article' : entity?.title,
|
|
1739
|
+
],
|
|
1740
|
+
}),
|
|
1741
|
+
component: route => {
|
|
1742
|
+
const { form, submitHandler, entity, isPending, refreshEntity } = useDetailPage({
|
|
1743
|
+
queryDocument: articleDetailDocument,
|
|
1744
|
+
createDocument: createArticleDocument,
|
|
1745
|
+
updateDocument: updateArticleDocument,
|
|
1746
|
+
setValuesForUpdate: article => ({
|
|
1747
|
+
title: article?.title ?? '',
|
|
1748
|
+
slug: article?.slug ?? '',
|
|
1749
|
+
}),
|
|
1750
|
+
params: { id: route.useParams().id },
|
|
1751
|
+
onSuccess: async data => {
|
|
1752
|
+
toast.success('Successfully updated');
|
|
1753
|
+
},
|
|
1754
|
+
});
|
|
1755
|
+
|
|
1756
|
+
return (
|
|
1757
|
+
<Page pageId="article-detail" form={form} submitHandler={submitHandler}>
|
|
1758
|
+
<PageLayout>
|
|
1759
|
+
<PageBlock column="main" blockId="main-form">
|
|
1760
|
+
<DetailFormGrid>
|
|
1761
|
+
<FormFieldWrapper control={form.control} name="title" label="Title"
|
|
1762
|
+
render={({ field }) => <Input {...field} />} />
|
|
1763
|
+
</DetailFormGrid>
|
|
1764
|
+
</PageBlock>
|
|
1765
|
+
</PageLayout>
|
|
1766
|
+
</Page>
|
|
1767
|
+
);
|
|
1768
|
+
},
|
|
1769
|
+
};
|
|
1770
|
+
```
|
|
1771
|
+
|
|
1772
|
+
**Important**: `PageBlock` already renders as a card, so never nest Card components inside it. Use `refreshEntity` to manually reload entity data after mutations. Ensure vertical spacing of 6 units for components not in `DetailFormGrid`.
|
|
1773
|
+
|
|
1774
|
+
### Nav Menu Items
|
|
1775
|
+
|
|
1776
|
+
Nav menu items are now configured via the `navMenuItem` property on route definitions within the `routes` array. Specify `sectionId` (e.g., 'catalog'), unique `id`, and `title`.
|
|
1777
|
+
|
|
1778
|
+
| Admin UI | Dashboard | Imported From | Notes |
|
|
1779
|
+
|----------|-----------|---------------|-------|
|
|
1780
|
+
| `addNavMenuSection()` | `navMenuItem` | - | Defined on route in `routes` array |
|
|
1781
|
+
| `label` | `title` | - | Display text |
|
|
1782
|
+
| `routerLink` | `path` | - | Route path |
|
|
1783
|
+
| `icon` | - | - | Not supported in Dashboard |
|
|
1784
|
+
|
|
1785
|
+
```tsx
|
|
1786
|
+
defineDashboardExtension({
|
|
1787
|
+
routes: [
|
|
1788
|
+
{
|
|
1789
|
+
path: '/my-custom-page',
|
|
1790
|
+
component: () => <div>My Custom Page</div>,
|
|
1791
|
+
navMenuItem: {
|
|
1792
|
+
sectionId: 'catalog',
|
|
1793
|
+
id: 'my-custom-page',
|
|
1794
|
+
title: 'My Custom Page',
|
|
1795
|
+
},
|
|
1796
|
+
},
|
|
1797
|
+
],
|
|
1798
|
+
});
|
|
1799
|
+
```
|
|
1800
|
+
|
|
1801
|
+
### Action Bar Items
|
|
1802
|
+
|
|
1803
|
+
Action bar items migrate from `addActionBarItem` to the `actionBarItems` array in the Dashboard extension. Each item specifies a `pageId` and a `component` function that receives `context`.
|
|
1804
|
+
|
|
1805
|
+
| Admin UI | Dashboard | Imported From | Notes |
|
|
1806
|
+
|----------|-----------|---------------|-------|
|
|
1807
|
+
| `addActionBarItem()` | `actionBarItems` | - | Array in `defineDashboardExtension` |
|
|
1808
|
+
| `locationId` | `pageId` | - | Identifies target page |
|
|
1809
|
+
| `label` | - | - | Render button/component directly |
|
|
1810
|
+
| `icon` | - | `lucide-react` | Use icon components in button |
|
|
1811
|
+
| `routerLink` | `Link` / `useNavigate()` | `@tanstack/react-router` | For navigation |
|
|
1812
|
+
|
|
1813
|
+
```tsx
|
|
1814
|
+
defineDashboardExtension({
|
|
1815
|
+
actionBarItems: [
|
|
1816
|
+
{
|
|
1817
|
+
pageId: 'product-detail',
|
|
1818
|
+
component: ({ context }) => (
|
|
1819
|
+
<Button type="button" variant="secondary" onClick={() => handleAction()}>
|
|
1820
|
+
Custom Action
|
|
1821
|
+
</Button>
|
|
1822
|
+
),
|
|
1823
|
+
},
|
|
1824
|
+
],
|
|
1825
|
+
});
|
|
1826
|
+
```
|
|
1827
|
+
|
|
1828
|
+
### Custom Detail Components (Page Blocks)
|
|
1829
|
+
|
|
1830
|
+
Custom detail components (Angular `CustomDetailComponent`) are now implemented as page blocks via the `pageBlocks` array. Each block specifies `id`, `title`, `location` (pageId, column, position), and a `component` function that receives `context` with `entity` and form access.
|
|
1831
|
+
|
|
1832
|
+
| Admin UI | Dashboard | Imported From | Notes |
|
|
1833
|
+
|----------|-----------|---------------|-------|
|
|
1834
|
+
| `CustomDetailComponent` | `pageBlocks` | - | Array in `defineDashboardExtension` |
|
|
1835
|
+
| `entity$` (Observable) | `context.entity` | - | Available in component function |
|
|
1836
|
+
| `detailForm` | `context.form` | - | Available in component function |
|
|
1837
|
+
| `registerCustomDetailComponent()` | `pageBlocks[].location` | - | Positioning configuration |
|
|
1838
|
+
|
|
1839
|
+
```tsx
|
|
1840
|
+
defineDashboardExtension({
|
|
1841
|
+
pageBlocks: [
|
|
1842
|
+
{
|
|
1843
|
+
id: 'related-articles',
|
|
1844
|
+
title: 'Related Articles',
|
|
1845
|
+
location: {
|
|
1846
|
+
pageId: 'product-detail',
|
|
1847
|
+
column: 'side',
|
|
1848
|
+
position: { blockId: 'facet-values', order: 'after' },
|
|
1849
|
+
},
|
|
1850
|
+
component: ({ context }) => (
|
|
1851
|
+
<div>Articles related to {context.entity.name}</div>
|
|
1852
|
+
),
|
|
1853
|
+
},
|
|
1854
|
+
],
|
|
1855
|
+
});
|
|
1856
|
+
```
|
|
1857
|
+
|
|
1858
|
+
### Page Tabs
|
|
1859
|
+
|
|
1860
|
+
Page tabs (`registerPageTab`) are not supported in the Dashboard. Consider alternative approaches such as creating a new route or using page blocks.
|
|
1861
|
+
|
|
1862
|
+
| Admin UI | Dashboard | Imported From | Notes |
|
|
1863
|
+
|----------|-----------|---------------|-------|
|
|
1864
|
+
| `registerPageTab()` | - | - | Not supported; use routes or page blocks instead |
|
|
1865
|
+
|
|
1866
|
+
### Widgets
|
|
1867
|
+
|
|
1868
|
+
Dashboard widgets migrate from `registerDashboardWidget` to the `widgets` array. Each widget specifies `id`, `name`, `component`, and `defaultSize`. Widget components can use `useWidgetFilters()` and `useLocalFormat()` hooks, and should wrap content in `DashboardBaseWidget`.
|
|
1869
|
+
|
|
1870
|
+
| Admin UI | Dashboard | Imported From | Notes |
|
|
1871
|
+
|----------|-----------|---------------|-------|
|
|
1872
|
+
| `registerDashboardWidget()` | `widgets` | - | Array in `defineDashboardExtension` |
|
|
1873
|
+
| `title` | `name` | - | Widget display name |
|
|
1874
|
+
| `loadComponent` | `component` | - | Widget component function |
|
|
1875
|
+
| `supportedWidths` | `defaultSize` | - | Object with `w` and `h` properties |
|
|
1876
|
+
| - | `DashboardBaseWidget` | `@vendure/dashboard` | Wrapper component for widgets |
|
|
1877
|
+
| - | `useWidgetFilters()` | `@vendure/dashboard` | Access date range filters |
|
|
1878
|
+
| - | `useLocalFormat()` | `@vendure/dashboard` | Formatting utilities |
|
|
1879
|
+
|
|
1880
|
+
```tsx
|
|
1881
|
+
export function CustomWidget() {
|
|
1882
|
+
const { dateRange } = useWidgetFilters();
|
|
1883
|
+
const { formatDate } = useLocalFormat();
|
|
1884
|
+
return (
|
|
1885
|
+
<DashboardBaseWidget id="custom-widget" title="Custom Widget" description="Widget description">
|
|
1886
|
+
<div>
|
|
1887
|
+
<Badge variant="secondary">{formatDate(dateRange.from)}</Badge>
|
|
1888
|
+
to
|
|
1889
|
+
<Badge variant="secondary">{formatDate(dateRange.to)}</Badge>
|
|
1890
|
+
</div>
|
|
1891
|
+
</DashboardBaseWidget>
|
|
1892
|
+
);
|
|
1893
|
+
}
|
|
1894
|
+
|
|
1895
|
+
defineDashboardExtension({
|
|
1896
|
+
widgets: [
|
|
1897
|
+
{ id: 'custom-widget', name: 'Custom Widget', component: CustomWidget, defaultSize: { w: 3, h: 3 } },
|
|
1898
|
+
],
|
|
1899
|
+
});
|
|
1900
|
+
```
|
|
1901
|
+
|
|
1902
|
+
|