create-nextblock 0.12.9 → 0.12.12
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/docker-template/.dockerignore +23 -23
- package/docker-template/.env.docker.example +69 -69
- package/docker-template/docker/db/init/99-jwt.sql +6 -6
- package/docker-template/docker/db/init/99-roles.sql +25 -25
- package/docker-template/docker/kong/kong.yml +112 -112
- package/docker-template/scripts/docker-setup.mjs +310 -310
- package/libs/db/tsconfig.lib.json +3 -3
- package/libs/editor/tsconfig.lib.json +3 -3
- package/libs/ui/tsconfig.lib.json +3 -3
- package/libs/utils/tsconfig.json +3 -3
- package/package.json +1 -1
- package/project.json +19 -19
- package/templates/nextblock-template/.browserslistrc +11 -11
- package/templates/nextblock-template/.dockerignore +23 -23
- package/templates/nextblock-template/README.md +34 -34
- package/templates/nextblock-template/app/(auth-pages)/layout.tsx +9 -9
- package/templates/nextblock-template/app/(auth-pages)/post-sign-in/page.tsx +27 -27
- package/templates/nextblock-template/app/(auth-pages)/sign-up/SignUpForm.tsx +141 -141
- package/templates/nextblock-template/app/(auth-pages)/sign-up/page.tsx +46 -46
- package/templates/nextblock-template/app/(auth-pages)/two-factor/actions.ts +91 -91
- package/templates/nextblock-template/app/(auth-pages)/two-factor/components/TwoFactorForm.tsx +123 -123
- package/templates/nextblock-template/app/(auth-pages)/two-factor/page.tsx +51 -51
- package/templates/nextblock-template/app/ToasterProvider.tsx +17 -17
- package/templates/nextblock-template/app/[slug]/pageClientActions.ts +7 -7
- package/templates/nextblock-template/app/actions/consent.ts +57 -57
- package/templates/nextblock-template/app/actions/interactions.test.ts +301 -301
- package/templates/nextblock-template/app/actions/interactions.ts +373 -373
- package/templates/nextblock-template/app/actions/postActions.ts +146 -146
- package/templates/nextblock-template/app/actions/twoFactorEmail.ts +22 -22
- package/templates/nextblock-template/app/api/ai/cortex/build-widget/route.ts +153 -153
- package/templates/nextblock-template/app/api/ai/generate-blocks/route.ts +96 -96
- package/templates/nextblock-template/app/api/ai/global-agent/route.ts +964 -964
- package/templates/nextblock-template/app/api/brand/email-logo/route.ts +48 -48
- package/templates/nextblock-template/app/api/cms/check-updates/route.ts +44 -44
- package/templates/nextblock-template/app/api/cms/full-backup/export/route.ts +33 -33
- package/templates/nextblock-template/app/api/cms/full-backup/restore/route.ts +63 -63
- package/templates/nextblock-template/app/api/cron/reset-sandbox/route.ts +3490 -3490
- package/templates/nextblock-template/app/api/cron/reset-sandbox/sandboxResetSql.ts +5597 -5597
- package/templates/nextblock-template/app/api/cron/sync-currencies/route.ts +39 -39
- package/templates/nextblock-template/app/api/custom-blocks/db-relations/route.ts +92 -92
- package/templates/nextblock-template/app/api/custom-blocks/editor-definitions/route.ts +43 -43
- package/templates/nextblock-template/app/api/media/library/route.ts +69 -69
- package/templates/nextblock-template/app/api/media/r2-presigned/route.ts +53 -53
- package/templates/nextblock-template/app/api/media/record/route.ts +160 -160
- package/templates/nextblock-template/app/api/search/route.ts +43 -43
- package/templates/nextblock-template/app/article/[slug]/PostClientContent.tsx +441 -441
- package/templates/nextblock-template/app/auth/callback/route.ts +31 -31
- package/templates/nextblock-template/app/cart/page.tsx +7 -7
- package/templates/nextblock-template/app/cms/blocks/components/CustomBlockEditorPreview.tsx +160 -160
- package/templates/nextblock-template/app/cms/blocks/components/MediaLibraryModal.tsx +149 -149
- package/templates/nextblock-template/app/cms/blocks/editors/DynamicCustomBlockEditor.tsx +167 -167
- package/templates/nextblock-template/app/cms/blocks/editors/ImageBlockEditor.tsx +29 -29
- package/templates/nextblock-template/app/cms/blocks/editors/TextBlockEditor.tsx +90 -90
- package/templates/nextblock-template/app/cms/components/ConnectGitHubButton.tsx +122 -122
- package/templates/nextblock-template/app/cms/components/CortexAiPageContext.tsx +58 -58
- package/templates/nextblock-template/app/cms/components/FeatureImageField.tsx +244 -244
- package/templates/nextblock-template/app/cms/components/FeedbackModal.tsx +36 -36
- package/templates/nextblock-template/app/cms/components/SystemAlertsBanner.tsx +112 -112
- package/templates/nextblock-template/app/cms/components/TwoFactorReminderBanner.tsx +45 -45
- package/templates/nextblock-template/app/cms/components/github-connect-actions.ts +102 -102
- package/templates/nextblock-template/app/cms/components/system-alerts-actions.ts +31 -31
- package/templates/nextblock-template/app/cms/custom-blocks/[id]/edit/page.tsx +66 -66
- package/templates/nextblock-template/app/cms/custom-blocks/actions.ts +519 -519
- package/templates/nextblock-template/app/cms/custom-blocks/components/BlockComposer.tsx +1522 -1522
- package/templates/nextblock-template/app/cms/custom-blocks/components/BlocksLibraryTransferControls.tsx +256 -256
- package/templates/nextblock-template/app/cms/custom-blocks/components/DBRelationSelect.tsx +384 -384
- package/templates/nextblock-template/app/cms/custom-blocks/components/ImageR2Picker.tsx +221 -221
- package/templates/nextblock-template/app/cms/custom-blocks/new/page.tsx +12 -12
- package/templates/nextblock-template/app/cms/custom-blocks/page.tsx +438 -438
- package/templates/nextblock-template/app/cms/dashboard/actions.ts +228 -228
- package/templates/nextblock-template/app/cms/dashboard/components/DashboardOnboarding.tsx +130 -130
- package/templates/nextblock-template/app/cms/import-export/ContentTransferControls.tsx +431 -391
- package/templates/nextblock-template/app/cms/import-export/actions.ts +226 -226
- package/templates/nextblock-template/app/cms/interactions/InteractionsModerationClient.tsx +408 -408
- package/templates/nextblock-template/app/cms/interactions/page.tsx +51 -51
- package/templates/nextblock-template/app/cms/layout.tsx +73 -73
- package/templates/nextblock-template/app/cms/media/components/FolderNavigator.tsx +273 -273
- package/templates/nextblock-template/app/cms/media/components/FolderTree.tsx +122 -122
- package/templates/nextblock-template/app/cms/media/components/MediaEditForm.tsx +26 -26
- package/templates/nextblock-template/app/cms/media/components/MediaGridClient.tsx +69 -69
- package/templates/nextblock-template/app/cms/media/components/MediaPickerDialog.tsx +149 -158
- package/templates/nextblock-template/app/cms/media/components/MediaUploadForm.tsx +101 -101
- package/templates/nextblock-template/app/cms/navigation/components/NavigationMenuDnd.tsx +3 -3
- package/templates/nextblock-template/app/cms/pages/page.tsx +18 -17
- package/templates/nextblock-template/app/cms/posts/page.tsx +19 -18
- package/templates/nextblock-template/app/cms/products/[id]/edit/page.tsx +12 -0
- package/templates/nextblock-template/app/cms/products/attributes/page.tsx +12 -12
- package/templates/nextblock-template/app/cms/products/categories/page.tsx +12 -12
- package/templates/nextblock-template/app/cms/products/inventory/page.tsx +13 -13
- package/templates/nextblock-template/app/cms/products/new/page.tsx +135 -135
- package/templates/nextblock-template/app/cms/products/page.tsx +39 -27
- package/templates/nextblock-template/app/cms/products/productFormData.ts +133 -133
- package/templates/nextblock-template/app/cms/products/settings/page.tsx +5 -5
- package/templates/nextblock-template/app/cms/promotions/PromotionsWorkspace.tsx +456 -456
- package/templates/nextblock-template/app/cms/promotions/actions.ts +115 -115
- package/templates/nextblock-template/app/cms/promotions/page.tsx +31 -31
- package/templates/nextblock-template/app/cms/revisions/service.ts +19 -19
- package/templates/nextblock-template/app/cms/revisions/utils.ts +132 -132
- package/templates/nextblock-template/app/cms/settings/backup-restore/BackupRestoreWorkspace.tsx +1004 -1004
- package/templates/nextblock-template/app/cms/settings/backup-restore/page.tsx +29 -29
- package/templates/nextblock-template/app/cms/settings/bot-protection/actions.ts +93 -93
- package/templates/nextblock-template/app/cms/settings/bot-protection/components/BotProtectionForm.tsx +129 -129
- package/templates/nextblock-template/app/cms/settings/bot-protection/page.tsx +24 -24
- package/templates/nextblock-template/app/cms/settings/cortex-ai/SandboxCortexAiSettingsClient.tsx +497 -497
- package/templates/nextblock-template/app/cms/settings/cortex-ai/StoredCortexAiSettingsClient.tsx +410 -410
- package/templates/nextblock-template/app/cms/settings/cortex-ai/actions.ts +246 -246
- package/templates/nextblock-template/app/cms/settings/cortex-ai/page.tsx +80 -80
- package/templates/nextblock-template/app/cms/settings/currencies/actions.ts +331 -331
- package/templates/nextblock-template/app/cms/settings/currencies/page.tsx +494 -494
- package/templates/nextblock-template/app/cms/settings/email/actions.ts +64 -64
- package/templates/nextblock-template/app/cms/settings/email/components/EmailForm.tsx +181 -181
- package/templates/nextblock-template/app/cms/settings/email/page.tsx +28 -28
- package/templates/nextblock-template/app/cms/settings/extra-translations/ExtraTranslationsWorkspace.tsx +767 -767
- package/templates/nextblock-template/app/cms/settings/extra-translations/page.tsx +93 -93
- package/templates/nextblock-template/app/cms/settings/google-analytics/actions.ts +60 -60
- package/templates/nextblock-template/app/cms/settings/google-analytics/components/GoogleAnalyticsForm.tsx +129 -129
- package/templates/nextblock-template/app/cms/settings/google-analytics/page.tsx +26 -26
- package/templates/nextblock-template/app/cms/settings/languages/actions.ts +16 -16
- package/templates/nextblock-template/app/cms/settings/logos/[id]/edit/page.tsx +7 -7
- package/templates/nextblock-template/app/cms/settings/logos/components/BrandingSettingsForm.tsx +339 -339
- package/templates/nextblock-template/app/cms/settings/logos/components/DeleteLogoButton.tsx +21 -21
- package/templates/nextblock-template/app/cms/settings/logos/components/LogoForm.tsx +20 -20
- package/templates/nextblock-template/app/cms/settings/logos/components/SetActiveLogoButton.tsx +42 -42
- package/templates/nextblock-template/app/cms/settings/logos/components/SiteSeoSettingsForm.tsx +133 -133
- package/templates/nextblock-template/app/cms/settings/logos/new/page.tsx +8 -8
- package/templates/nextblock-template/app/cms/settings/packages/package-card.tsx +122 -122
- package/templates/nextblock-template/app/cms/settings/privacy/actions.ts +52 -52
- package/templates/nextblock-template/app/cms/settings/privacy/components/PrivacyForm.tsx +148 -148
- package/templates/nextblock-template/app/cms/settings/privacy/page.tsx +27 -27
- package/templates/nextblock-template/app/cms/settings/registration/actions.ts +44 -44
- package/templates/nextblock-template/app/cms/settings/registration/components/RegistrationForm.tsx +65 -65
- package/templates/nextblock-template/app/cms/settings/registration/page.tsx +27 -27
- package/templates/nextblock-template/app/cms/settings/security/actions.ts +284 -284
- package/templates/nextblock-template/app/cms/settings/security/components/SecurityPanel.tsx +522 -522
- package/templates/nextblock-template/app/cms/settings/security/page.tsx +33 -33
- package/templates/nextblock-template/app/cms/settings/taxes/page.tsx +21 -21
- package/templates/nextblock-template/app/cms/shipping/page.tsx +20 -20
- package/templates/nextblock-template/app/cms/users/actions.ts +222 -222
- package/templates/nextblock-template/app/cms/users/components/DeleteUserButton.tsx +12 -12
- package/templates/nextblock-template/app/cms/users/components/UserForm.tsx +44 -44
- package/templates/nextblock-template/app/lib/site-settings.ts +105 -105
- package/templates/nextblock-template/app/lib/sitemap-utils.ts +253 -253
- package/templates/nextblock-template/app/profile/ProfileAccountSidebar.tsx +73 -73
- package/templates/nextblock-template/app/profile/ProfilePageHeader.tsx +16 -16
- package/templates/nextblock-template/app/profile/ProfilePageMissingState.tsx +9 -9
- package/templates/nextblock-template/app/profile/account-data.ts +37 -37
- package/templates/nextblock-template/app/profile/account-links.ts +22 -22
- package/templates/nextblock-template/app/profile/account-types.ts +11 -11
- package/templates/nextblock-template/app/profile/orders/CustomerOrdersPageClient.tsx +124 -124
- package/templates/nextblock-template/app/profile/orders/[id]/CustomerOrderDetailPageClient.tsx +79 -79
- package/templates/nextblock-template/app/profile/orders/[id]/page.tsx +32 -32
- package/templates/nextblock-template/app/profile/orders/page.tsx +19 -19
- package/templates/nextblock-template/app/profile/page.tsx +42 -42
- package/templates/nextblock-template/app/profile/password/PasswordSettingsPageClient.tsx +128 -128
- package/templates/nextblock-template/app/profile/password/actions.ts +59 -59
- package/templates/nextblock-template/app/profile/password/page.tsx +27 -27
- package/templates/nextblock-template/app/setup/SetupWizard.tsx +678 -678
- package/templates/nextblock-template/app/setup/layout.tsx +13 -13
- package/templates/nextblock-template/app/setup/page.tsx +111 -111
- package/templates/nextblock-template/app/sitemap.ts +130 -130
- package/templates/nextblock-template/components/CartDrawerLoader.tsx +7 -7
- package/templates/nextblock-template/components/DeferredCartDrawer.tsx +23 -23
- package/templates/nextblock-template/components/DeferredGoogleAnalytics.tsx +70 -70
- package/templates/nextblock-template/components/DeferredGoogleTagManager.tsx +70 -70
- package/templates/nextblock-template/components/DeferredSpeedInsights.tsx +69 -69
- package/templates/nextblock-template/components/FeatureImageHero.tsx +47 -47
- package/templates/nextblock-template/components/FooterNavigation.tsx +32 -32
- package/templates/nextblock-template/components/GitHubLoginButton.tsx +15 -15
- package/templates/nextblock-template/components/HtmlScriptExecutor.tsx +47 -47
- package/templates/nextblock-template/components/LanguageSwitcher.tsx +2 -2
- package/templates/nextblock-template/components/PostCommentsSection.tsx +369 -369
- package/templates/nextblock-template/components/ProductReviewsSection.tsx +419 -419
- package/templates/nextblock-template/components/PublicEnvBootstrap.tsx +30 -30
- package/templates/nextblock-template/components/ResponsiveNav.tsx +14 -14
- package/templates/nextblock-template/components/auth/AuthBotProtection.tsx +182 -182
- package/templates/nextblock-template/components/blocks/PostCardSkeleton.tsx +12 -12
- package/templates/nextblock-template/components/blocks/PostsGridBlock.tsx +12 -12
- package/templates/nextblock-template/components/blocks/ecommerceRendererLoaders.ts +23 -23
- package/templates/nextblock-template/components/blocks/renderers/FormBlockRenderer.tsx +249 -249
- package/templates/nextblock-template/components/blocks/types.ts +7 -7
- package/templates/nextblock-template/components/env-var-warning.tsx +3 -3
- package/templates/nextblock-template/components/form-message.tsx +32 -32
- package/templates/nextblock-template/components/privacy/ConsentBanner.tsx +170 -170
- package/templates/nextblock-template/components/privacy/ConsentGatedAnalytics.tsx +70 -70
- package/templates/nextblock-template/components/renderers/CachedDynamicLayoutEngine.tsx +28 -28
- package/templates/nextblock-template/components/renderers/DynamicLayoutEngine.test.tsx +166 -166
- package/templates/nextblock-template/components/renderers/DynamicLayoutEngine.tsx +464 -464
- package/templates/nextblock-template/components/submit-button.tsx +23 -23
- package/templates/nextblock-template/components/theme-switcher.tsx +8 -8
- package/templates/nextblock-template/components/visual-editing/DeferredVisualEditing.tsx +21 -21
- package/templates/nextblock-template/context/AuthContext.tsx +23 -23
- package/templates/nextblock-template/context/LanguageContext.tsx +16 -16
- package/templates/nextblock-template/context/language-rest-client.ts +32 -32
- package/templates/nextblock-template/docker/db/init/99-jwt.sql +6 -6
- package/templates/nextblock-template/docker/db/init/99-roles.sql +25 -25
- package/templates/nextblock-template/docker/kong/kong.yml +112 -112
- package/templates/nextblock-template/docs/01-PROJECT-OVERVIEW.md +94 -94
- package/templates/nextblock-template/docs/02-ECOMMERCE-CAPABILITIES.md +364 -364
- package/templates/nextblock-template/docs/03-CMS-AND-EDITOR.md +202 -202
- package/templates/nextblock-template/docs/04-DATABASE-AND-AUTH.md +246 -246
- package/templates/nextblock-template/docs/06-CLI-AND-SCAFFOLDING.md +176 -176
- package/templates/nextblock-template/docs/07-BLOCK-SDK-AND-EXTENSIBILITY.md +146 -146
- package/templates/nextblock-template/docs/08-NEXTBLOCK-CORTEX-AI-ARCHITECTURE.md +1319 -1319
- package/templates/nextblock-template/docs/10-CUSTOM-BLOCKS.md +222 -222
- package/templates/nextblock-template/docs/11-SELF-HOSTED-DOCKER.md +173 -173
- package/templates/nextblock-template/docs/12-VERCEL-DEPLOYMENT.md +170 -170
- package/templates/nextblock-template/docs/13-STAYING-UP-TO-DATE.md +151 -151
- package/templates/nextblock-template/docs/README.md +39 -39
- package/templates/nextblock-template/docs/TECHNICAL_SPECIFICATION.md +12505 -12505
- package/templates/nextblock-template/hooks/use-hotkeys.ts +21 -21
- package/templates/nextblock-template/hooks/useGlobalSearch.ts +101 -101
- package/templates/nextblock-template/index.d.ts +7 -7
- package/templates/nextblock-template/lib/app-secrets.ts +39 -39
- package/templates/nextblock-template/lib/auth/cookies.ts +47 -47
- package/templates/nextblock-template/lib/auth/crypto.ts +45 -45
- package/templates/nextblock-template/lib/auth/trustedDevices.ts +92 -92
- package/templates/nextblock-template/lib/auth/twoFactor.ts +208 -208
- package/templates/nextblock-template/lib/auth-redirects.ts +46 -46
- package/templates/nextblock-template/lib/blocks/README.md +13 -13
- package/templates/nextblock-template/lib/blocks/blockRegistry.ts +6 -6
- package/templates/nextblock-template/lib/blocks/blockTypes.ts +18 -18
- package/templates/nextblock-template/lib/botProtection/verify.ts +134 -134
- package/templates/nextblock-template/lib/cms-transfer/csv.test.ts +100 -77
- package/templates/nextblock-template/lib/cms-transfer/csv.ts +403 -399
- package/templates/nextblock-template/lib/cms-transfer/server.ts +2243 -2243
- package/templates/nextblock-template/lib/cms-transfer/types.ts +145 -145
- package/templates/nextblock-template/lib/config/email-settings.ts +217 -217
- package/templates/nextblock-template/lib/custom-block-definitions.ts +87 -87
- package/templates/nextblock-template/lib/custom-block-r2-upload-shared.ts +178 -178
- package/templates/nextblock-template/lib/custom-block-r2-upload.test.ts +140 -140
- package/templates/nextblock-template/lib/custom-block-r2-upload.ts +88 -88
- package/templates/nextblock-template/lib/custom-block-relation-registry.ts +256 -256
- package/templates/nextblock-template/lib/custom-block-relations.test.ts +227 -227
- package/templates/nextblock-template/lib/custom-block-relations.ts +279 -279
- package/templates/nextblock-template/lib/custom-block-safelist.ts +14 -14
- package/templates/nextblock-template/lib/editor/dynamic-extension-core.test.ts +172 -172
- package/templates/nextblock-template/lib/editor/dynamic-extension-core.ts +213 -213
- package/templates/nextblock-template/lib/editor/dynamic-extension-loader.ts +22 -22
- package/templates/nextblock-template/lib/editor/dynamic-extensions.tsx +193 -193
- package/templates/nextblock-template/lib/email/branding-format.test.ts +133 -133
- package/templates/nextblock-template/lib/email/branding-format.ts +123 -123
- package/templates/nextblock-template/lib/email/branding.ts +76 -76
- package/templates/nextblock-template/lib/full-backup/manifest.test.ts +121 -121
- package/templates/nextblock-template/lib/full-backup/manifest.ts +206 -206
- package/templates/nextblock-template/lib/full-backup/server.ts +743 -743
- package/templates/nextblock-template/lib/logos/active-logo.ts +53 -53
- package/templates/nextblock-template/lib/media/resolveMediaUrl.ts +54 -54
- package/templates/nextblock-template/lib/onboarding/actions.ts +31 -31
- package/templates/nextblock-template/lib/onboarding/status.ts +222 -222
- package/templates/nextblock-template/lib/posts/readTime.ts +60 -60
- package/templates/nextblock-template/lib/privacy/consent-client.ts +57 -57
- package/templates/nextblock-template/lib/privacy/contact-emails.ts +64 -64
- package/templates/nextblock-template/lib/privacy/settings.ts +115 -115
- package/templates/nextblock-template/lib/privacy/types.ts +69 -69
- package/templates/nextblock-template/lib/promotions/server.test.ts +74 -74
- package/templates/nextblock-template/lib/promotions/server.ts +741 -741
- package/templates/nextblock-template/lib/resolve-block-relations.test.ts +142 -142
- package/templates/nextblock-template/lib/resolve-block-relations.ts +255 -255
- package/templates/nextblock-template/lib/search/server.ts +585 -585
- package/templates/nextblock-template/lib/search/types.ts +27 -27
- package/templates/nextblock-template/lib/setup/actions.ts +460 -460
- package/templates/nextblock-template/lib/setup/env-status.ts +125 -125
- package/templates/nextblock-template/lib/setup/env-write.ts +111 -111
- package/templates/nextblock-template/lib/setup/migrations-bundle.ts +37 -37
- package/templates/nextblock-template/lib/setup/provisioning.ts +59 -59
- package/templates/nextblock-template/lib/setup/schema-apply.ts +408 -408
- package/templates/nextblock-template/lib/setup/system-config.ts +105 -105
- package/templates/nextblock-template/lib/setup/types.ts +18 -18
- package/templates/nextblock-template/lib/site-url.ts +48 -48
- package/templates/nextblock-template/lib/storage/provider.ts +66 -66
- package/templates/nextblock-template/lib/storage/supabase-storage.ts +103 -103
- package/templates/nextblock-template/lib/updates/check-upstream.ts +441 -441
- package/templates/nextblock-template/lib/updates/github-device.ts +206 -206
- package/templates/nextblock-template/lib/updates/repo-identity.ts +56 -56
- package/templates/nextblock-template/package.json +1 -1
- package/templates/nextblock-template/postcss.config.js +6 -6
- package/templates/nextblock-template/scripts/backup.js +115 -115
- package/templates/nextblock-template/scripts/docker-setup.mjs +310 -310
- package/templates/nextblock-template/scripts/restore.js +385 -385
- package/templates/nextblock-template/scripts/verify-cortex-ai-build-widget.tsx +98 -98
- package/templates/nextblock-template/scripts/verify-cortex-ai-generate-blocks.ts +62 -62
- package/templates/nextblock-template/scripts/verify-cortex-ai-global-tools.ts +537 -537
- package/templates/nextblock-template/scripts/verify-cortex-ai-routing.ts +58 -58
- package/templates/nextblock-template/scripts/verify-custom-block-definitions.ts +188 -188
- package/templates/nextblock-template/scripts/verify-dynamic-custom-block-extensions.ts +123 -123
- package/templates/nextblock-template/scripts/verify-dynamic-layout-engine.tsx +133 -133
- package/templates/nextblock-template/scripts/verify-milestone-2-custom-blocks.ts +65 -65
- package/templates/nextblock-template/tailwind.config.js +25 -25
- package/templates/nextblock-template/tools/build-migrate.mjs +209 -209
- package/templates/nextblock-template/tools/configure-supabase-auth.js +282 -282
- package/templates/nextblock-template/types/jsdom.d.ts +6 -6
- package/tsconfig.base.json +3 -3
- package/templates/nextblock-template/tsconfig.tsbuildinfo +0 -1
|
@@ -22,14 +22,14 @@ import {
|
|
|
22
22
|
DropdownMenuSeparator,
|
|
23
23
|
} from "@nextblock-cms/ui";
|
|
24
24
|
// deletePost server action is now used by DeletePostButtonClient
|
|
25
|
-
import type { Database } from "@nextblock-cms/db";
|
|
26
|
-
import { getActiveLanguagesServerSide } from "@nextblock-cms/db/server";
|
|
27
|
-
import { resolveMediaUrl } from "../../../lib/media/resolveMediaUrl";
|
|
28
|
-
|
|
29
|
-
type Post = Database['public']['Tables']['posts']['Row'] & { feature_image_url?: string | null };
|
|
30
|
-
import LanguageFilterSelect from "../components/LanguageFilterSelect";
|
|
31
|
-
import DeletePostButtonClient from "./components/DeletePostButtonClient"; // Import the new client component
|
|
32
|
-
import { ContentTransferControls } from "../import-export/ContentTransferControls";
|
|
25
|
+
import type { Database } from "@nextblock-cms/db";
|
|
26
|
+
import { getActiveLanguagesServerSide } from "@nextblock-cms/db/server";
|
|
27
|
+
import { resolveMediaUrl } from "../../../lib/media/resolveMediaUrl";
|
|
28
|
+
|
|
29
|
+
type Post = Database['public']['Tables']['posts']['Row'] & { feature_image_url?: string | null };
|
|
30
|
+
import LanguageFilterSelect from "../components/LanguageFilterSelect";
|
|
31
|
+
import DeletePostButtonClient from "./components/DeletePostButtonClient"; // Import the new client component
|
|
32
|
+
import { ContentTransferControls } from "../import-export/ContentTransferControls";
|
|
33
33
|
|
|
34
34
|
async function getPostsWithDetails(filterLanguageId?: number): Promise<{ post: Post; languageCode: string }[]> {
|
|
35
35
|
const supabase = createClient();
|
|
@@ -82,16 +82,17 @@ export default async function CmsPostsListPage(props: CmsPostsListPageProps) {
|
|
|
82
82
|
return (
|
|
83
83
|
<div className="w-full">
|
|
84
84
|
<div className="flex justify-between items-center mb-6 flex-wrap gap-4">
|
|
85
|
-
<h1 className="text-2xl font-semibold">Manage Posts</h1>
|
|
86
|
-
<div className="flex items-center gap-3">
|
|
87
|
-
<ContentTransferControls
|
|
88
|
-
contentType="posts"
|
|
89
|
-
label="Posts"
|
|
90
|
-
languageId={filterLangId}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
85
|
+
<h1 className="text-2xl font-semibold">Manage Posts</h1>
|
|
86
|
+
<div className="flex items-center gap-3">
|
|
87
|
+
<ContentTransferControls
|
|
88
|
+
contentType="posts"
|
|
89
|
+
label="Posts"
|
|
90
|
+
languageId={filterLangId}
|
|
91
|
+
hasContent={postsWithDetails.length > 0}
|
|
92
|
+
/>
|
|
93
|
+
<LanguageFilterSelect
|
|
94
|
+
allLanguages={allLanguages}
|
|
95
|
+
currentFilterLangId={filterLangId}
|
|
95
96
|
basePath="/cms/posts"
|
|
96
97
|
/>
|
|
97
98
|
<Button variant="default" asChild>
|
|
@@ -157,9 +157,21 @@ export default async function EditProductPage({
|
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
+
// Product drafts persist prices in major units (dollars, the ProductForm
|
|
161
|
+
// value shape), but ProductForm re-divides the top-level price/sale_price by
|
|
162
|
+
// 100 because it expects a raw product row (minor units/cents). Convert the
|
|
163
|
+
// draft's dollars back to cents so the form shows the saved amount instead of
|
|
164
|
+
// 1/100th of it (e.g. an imported $29.50 draft otherwise renders as $0.30).
|
|
165
|
+
// The prices maps and variant prices are already in the dollar shape the form
|
|
166
|
+
// consumes directly, so only these two scalars need converting.
|
|
167
|
+
const draftDollarsToStoredCents = (value: unknown) =>
|
|
168
|
+
typeof value === 'number' && Number.isFinite(value) ? Math.round(value * 100) : value;
|
|
169
|
+
|
|
160
170
|
normalizedInitialData = {
|
|
161
171
|
...meta,
|
|
162
172
|
id: product.id,
|
|
173
|
+
price: draftDollarsToStoredCents(meta.price),
|
|
174
|
+
sale_price: draftDollarsToStoredCents(meta.sale_price),
|
|
163
175
|
product_media: hydratedProductMedia,
|
|
164
176
|
category_ids: meta.category_ids ?? assignedCategories.map((c: any) => c.id),
|
|
165
177
|
};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { redirect } from 'next/navigation';
|
|
2
|
-
import { verifyPackageOnline } from '@nextblock-cms/db/server';
|
|
3
|
-
import { AttributeManagementPage as AttributeManagementPageUI } from '@nextblock-cms/ecommerce/server';
|
|
4
|
-
|
|
5
|
-
export default async function AttributeManagementPage() {
|
|
6
|
-
const isOnline = await verifyPackageOnline('ecommerce');
|
|
7
|
-
if (!isOnline) {
|
|
8
|
-
redirect('/cms/settings/packages');
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
return <AttributeManagementPageUI />;
|
|
12
|
-
}
|
|
1
|
+
import { redirect } from 'next/navigation';
|
|
2
|
+
import { verifyPackageOnline } from '@nextblock-cms/db/server';
|
|
3
|
+
import { AttributeManagementPage as AttributeManagementPageUI } from '@nextblock-cms/ecommerce/server';
|
|
4
|
+
|
|
5
|
+
export default async function AttributeManagementPage() {
|
|
6
|
+
const isOnline = await verifyPackageOnline('ecommerce');
|
|
7
|
+
if (!isOnline) {
|
|
8
|
+
redirect('/cms/settings/packages');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return <AttributeManagementPageUI />;
|
|
12
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { redirect } from 'next/navigation';
|
|
2
|
-
import { verifyPackageOnline } from '@nextblock-cms/db/server';
|
|
3
|
-
import { CategoryManagementPage as CategoryManagementPageUI } from '@nextblock-cms/ecommerce/server';
|
|
4
|
-
|
|
5
|
-
export default async function CategoryManagementPage() {
|
|
6
|
-
const isOnline = await verifyPackageOnline('ecommerce');
|
|
7
|
-
if (!isOnline) {
|
|
8
|
-
redirect('/cms/settings/packages');
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
return <CategoryManagementPageUI />;
|
|
12
|
-
}
|
|
1
|
+
import { redirect } from 'next/navigation';
|
|
2
|
+
import { verifyPackageOnline } from '@nextblock-cms/db/server';
|
|
3
|
+
import { CategoryManagementPage as CategoryManagementPageUI } from '@nextblock-cms/ecommerce/server';
|
|
4
|
+
|
|
5
|
+
export default async function CategoryManagementPage() {
|
|
6
|
+
const isOnline = await verifyPackageOnline('ecommerce');
|
|
7
|
+
if (!isOnline) {
|
|
8
|
+
redirect('/cms/settings/packages');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return <CategoryManagementPageUI />;
|
|
12
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { verifyPackageOnline } from '@nextblock-cms/db/server';
|
|
2
|
-
import { InventoryPage as InventoryPageUI } from '@nextblock-cms/ecommerce/server';
|
|
3
|
-
import { redirect } from 'next/navigation';
|
|
4
|
-
|
|
5
|
-
export default async function InventoryPage() {
|
|
6
|
-
const isOnline = await verifyPackageOnline('ecommerce');
|
|
7
|
-
|
|
8
|
-
if (!isOnline) {
|
|
9
|
-
redirect('/cms/settings/packages');
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
return <InventoryPageUI />;
|
|
13
|
-
}
|
|
1
|
+
import { verifyPackageOnline } from '@nextblock-cms/db/server';
|
|
2
|
+
import { InventoryPage as InventoryPageUI } from '@nextblock-cms/ecommerce/server';
|
|
3
|
+
import { redirect } from 'next/navigation';
|
|
4
|
+
|
|
5
|
+
export default async function InventoryPage() {
|
|
6
|
+
const isOnline = await verifyPackageOnline('ecommerce');
|
|
7
|
+
|
|
8
|
+
if (!isOnline) {
|
|
9
|
+
redirect('/cms/settings/packages');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return <InventoryPageUI />;
|
|
13
|
+
}
|
|
@@ -1,143 +1,143 @@
|
|
|
1
|
-
import { verifyPackageOnline } from '@nextblock-cms/db/server';
|
|
2
|
-
import { redirect } from 'next/navigation';
|
|
3
|
-
import { getActiveLanguagesServerSide } from '@nextblock-cms/db/server';
|
|
4
|
-
import { createClient } from '@nextblock-cms/db/server';
|
|
5
|
-
import Link from 'next/link';
|
|
6
|
-
import {
|
|
7
|
-
createProductAction,
|
|
8
|
-
getGlobalProductAttributes,
|
|
9
|
-
getEnabledPaymentProviders,
|
|
10
|
-
getProduct,
|
|
11
|
-
getStoreConfigStatus,
|
|
12
|
-
normalizeCurrencyRecord,
|
|
13
|
-
getCategoriesWithCount,
|
|
14
|
-
} from '@nextblock-cms/ecommerce/server';
|
|
15
|
-
import { ArrowLeft } from 'lucide-react';
|
|
16
|
-
import { Badge, Button } from '@nextblock-cms/ui';
|
|
17
|
-
import ProductFormClientShell from '../ProductFormClientShell';
|
|
18
|
-
import {
|
|
19
|
-
buildGlobalAttributesForForm,
|
|
20
|
-
buildProductFormInitialData,
|
|
21
|
-
buildTranslationSourceInitialData,
|
|
22
|
-
} from '../productFormData';
|
|
1
|
+
import { verifyPackageOnline } from '@nextblock-cms/db/server';
|
|
2
|
+
import { redirect } from 'next/navigation';
|
|
3
|
+
import { getActiveLanguagesServerSide } from '@nextblock-cms/db/server';
|
|
4
|
+
import { createClient } from '@nextblock-cms/db/server';
|
|
5
|
+
import Link from 'next/link';
|
|
6
|
+
import {
|
|
7
|
+
createProductAction,
|
|
8
|
+
getGlobalProductAttributes,
|
|
9
|
+
getEnabledPaymentProviders,
|
|
10
|
+
getProduct,
|
|
11
|
+
getStoreConfigStatus,
|
|
12
|
+
normalizeCurrencyRecord,
|
|
13
|
+
getCategoriesWithCount,
|
|
14
|
+
} from '@nextblock-cms/ecommerce/server';
|
|
15
|
+
import { ArrowLeft } from 'lucide-react';
|
|
16
|
+
import { Badge, Button } from '@nextblock-cms/ui';
|
|
17
|
+
import ProductFormClientShell from '../ProductFormClientShell';
|
|
18
|
+
import {
|
|
19
|
+
buildGlobalAttributesForForm,
|
|
20
|
+
buildProductFormInitialData,
|
|
21
|
+
buildTranslationSourceInitialData,
|
|
22
|
+
} from '../productFormData';
|
|
23
23
|
|
|
24
|
-
export default async function NewProductPage({
|
|
25
|
-
searchParams
|
|
26
|
-
}: {
|
|
27
|
-
searchParams: Promise<{ from_group?: string; target_lang_id?: string }>
|
|
28
|
-
}) {
|
|
29
|
-
const [
|
|
30
|
-
isOnline,
|
|
31
|
-
languages,
|
|
32
|
-
enabledProviders,
|
|
33
|
-
configStatus,
|
|
34
|
-
globalAttributesRaw,
|
|
35
|
-
currenciesResult,
|
|
36
|
-
categories,
|
|
37
|
-
{ from_group, target_lang_id },
|
|
38
|
-
] = await Promise.all([
|
|
39
|
-
verifyPackageOnline('ecommerce'),
|
|
40
|
-
getActiveLanguagesServerSide(),
|
|
41
|
-
getEnabledPaymentProviders(),
|
|
42
|
-
getStoreConfigStatus(),
|
|
43
|
-
getGlobalProductAttributes(),
|
|
44
|
-
createClient()
|
|
45
|
-
.from('currencies')
|
|
46
|
-
.select(
|
|
47
|
-
'code, symbol, exchange_rate, is_default, is_active, auto_sync_product_prices, auto_update_exchange_rate, exchange_rate_source, exchange_rate_updated_at, rounding_mode, rounding_increment, rounding_charm_amount'
|
|
48
|
-
)
|
|
49
|
-
.eq('is_active', true)
|
|
50
|
-
.order('code', { ascending: true }),
|
|
51
|
-
getCategoriesWithCount(),
|
|
52
|
-
searchParams,
|
|
53
|
-
]);
|
|
54
|
-
|
|
55
|
-
if (!isOnline) {
|
|
56
|
-
redirect('/cms/settings/packages');
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
let initialData = null;
|
|
60
|
-
if (from_group) {
|
|
61
|
-
try {
|
|
62
|
-
const supabase = createClient();
|
|
24
|
+
export default async function NewProductPage({
|
|
25
|
+
searchParams
|
|
26
|
+
}: {
|
|
27
|
+
searchParams: Promise<{ from_group?: string; target_lang_id?: string }>
|
|
28
|
+
}) {
|
|
29
|
+
const [
|
|
30
|
+
isOnline,
|
|
31
|
+
languages,
|
|
32
|
+
enabledProviders,
|
|
33
|
+
configStatus,
|
|
34
|
+
globalAttributesRaw,
|
|
35
|
+
currenciesResult,
|
|
36
|
+
categories,
|
|
37
|
+
{ from_group, target_lang_id },
|
|
38
|
+
] = await Promise.all([
|
|
39
|
+
verifyPackageOnline('ecommerce'),
|
|
40
|
+
getActiveLanguagesServerSide(),
|
|
41
|
+
getEnabledPaymentProviders(),
|
|
42
|
+
getStoreConfigStatus(),
|
|
43
|
+
getGlobalProductAttributes(),
|
|
44
|
+
createClient()
|
|
45
|
+
.from('currencies')
|
|
46
|
+
.select(
|
|
47
|
+
'code, symbol, exchange_rate, is_default, is_active, auto_sync_product_prices, auto_update_exchange_rate, exchange_rate_source, exchange_rate_updated_at, rounding_mode, rounding_increment, rounding_charm_amount'
|
|
48
|
+
)
|
|
49
|
+
.eq('is_active', true)
|
|
50
|
+
.order('code', { ascending: true }),
|
|
51
|
+
getCategoriesWithCount(),
|
|
52
|
+
searchParams,
|
|
53
|
+
]);
|
|
54
|
+
|
|
55
|
+
if (!isOnline) {
|
|
56
|
+
redirect('/cms/settings/packages');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let initialData = null;
|
|
60
|
+
if (from_group) {
|
|
61
|
+
try {
|
|
62
|
+
const supabase = createClient();
|
|
63
63
|
const { data: groupProducts } = await supabase
|
|
64
64
|
.from('products')
|
|
65
65
|
.select('id')
|
|
66
66
|
.eq('translation_group_id', from_group)
|
|
67
67
|
.limit(1);
|
|
68
68
|
|
|
69
|
-
if (groupProducts && groupProducts[0]) {
|
|
70
|
-
const { data: sourceProduct, error: fetchError } = await getProduct(supabase, groupProducts[0].id);
|
|
71
|
-
if (sourceProduct && !fetchError) {
|
|
72
|
-
initialData = buildTranslationSourceInitialData(
|
|
73
|
-
sourceProduct,
|
|
74
|
-
from_group,
|
|
75
|
-
target_lang_id
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
} catch (e) {
|
|
80
|
-
console.error('Error pre-filling translation data:', e);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const targetLanguageId = target_lang_id ? Number.parseInt(target_lang_id, 10) : undefined;
|
|
85
|
-
const targetLanguage =
|
|
86
|
-
Number.isFinite(targetLanguageId)
|
|
87
|
-
? languages.find((language) => language.id === targetLanguageId)
|
|
88
|
-
: null;
|
|
89
|
-
const globalAttributes = buildGlobalAttributesForForm(globalAttributesRaw || []);
|
|
90
|
-
const currencies = (currenciesResult.data ?? []).map((currency) =>
|
|
91
|
-
normalizeCurrencyRecord(currency)
|
|
92
|
-
);
|
|
93
|
-
const normalizedInitialData = buildProductFormInitialData(
|
|
94
|
-
initialData,
|
|
95
|
-
languages,
|
|
96
|
-
targetLanguageId
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
return (
|
|
100
|
-
<div className="space-y-8 w-full max-w-[1400px] mx-auto px-6 py-8">
|
|
101
|
-
<div className="flex justify-between items-start flex-wrap gap-4 w-full">
|
|
102
|
-
<div className="flex items-start gap-3">
|
|
103
|
-
<Button variant="outline" size="icon" aria-label="Back to products" asChild>
|
|
104
|
-
<Link href="/cms/products">
|
|
105
|
-
<ArrowLeft className="h-4 w-4" />
|
|
106
|
-
</Link>
|
|
107
|
-
</Button>
|
|
108
|
-
<div className="space-y-2">
|
|
109
|
-
<div className="flex items-center gap-2 flex-wrap">
|
|
110
|
-
<h1 className="text-2xl font-bold">
|
|
111
|
-
{targetLanguage ? `Create ${targetLanguage.name} Translation` : 'Create Product'}
|
|
112
|
-
</h1>
|
|
113
|
-
{targetLanguage ? (
|
|
114
|
-
<Badge variant="secondary">
|
|
115
|
-
{targetLanguage.code.toUpperCase()}
|
|
116
|
-
</Badge>
|
|
117
|
-
) : null}
|
|
118
|
-
</div>
|
|
119
|
-
<p className="text-sm text-muted-foreground max-w-3xl">
|
|
120
|
-
{targetLanguage
|
|
121
|
-
? 'We prefilled this draft from the source product so you can localize the content and fine-tune pricing, media, and variations faster.'
|
|
122
|
-
: 'Build a catalog-ready product with structured information, media, pricing, inventory, and optional variations.'}
|
|
123
|
-
</p>
|
|
124
|
-
</div>
|
|
125
|
-
</div>
|
|
126
|
-
</div>
|
|
127
|
-
|
|
128
|
-
<ProductFormClientShell
|
|
129
|
-
availableLanguagesProp={languages}
|
|
130
|
-
globalAttributesProp={globalAttributes}
|
|
131
|
-
currenciesProp={currencies}
|
|
132
|
-
translationGroupId={from_group}
|
|
133
|
-
targetLanguageId={target_lang_id}
|
|
134
|
-
initialData={normalizedInitialData}
|
|
135
|
-
enabledProviders={enabledProviders}
|
|
136
|
-
configStatus={configStatus}
|
|
137
|
-
createAction={createProductAction}
|
|
138
|
-
availableCategoriesProp={categories}
|
|
139
|
-
/>
|
|
140
|
-
</div>
|
|
141
|
-
);
|
|
142
|
-
}
|
|
69
|
+
if (groupProducts && groupProducts[0]) {
|
|
70
|
+
const { data: sourceProduct, error: fetchError } = await getProduct(supabase, groupProducts[0].id);
|
|
71
|
+
if (sourceProduct && !fetchError) {
|
|
72
|
+
initialData = buildTranslationSourceInitialData(
|
|
73
|
+
sourceProduct,
|
|
74
|
+
from_group,
|
|
75
|
+
target_lang_id
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
} catch (e) {
|
|
80
|
+
console.error('Error pre-filling translation data:', e);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const targetLanguageId = target_lang_id ? Number.parseInt(target_lang_id, 10) : undefined;
|
|
85
|
+
const targetLanguage =
|
|
86
|
+
Number.isFinite(targetLanguageId)
|
|
87
|
+
? languages.find((language) => language.id === targetLanguageId)
|
|
88
|
+
: null;
|
|
89
|
+
const globalAttributes = buildGlobalAttributesForForm(globalAttributesRaw || []);
|
|
90
|
+
const currencies = (currenciesResult.data ?? []).map((currency) =>
|
|
91
|
+
normalizeCurrencyRecord(currency)
|
|
92
|
+
);
|
|
93
|
+
const normalizedInitialData = buildProductFormInitialData(
|
|
94
|
+
initialData,
|
|
95
|
+
languages,
|
|
96
|
+
targetLanguageId
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<div className="space-y-8 w-full max-w-[1400px] mx-auto px-6 py-8">
|
|
101
|
+
<div className="flex justify-between items-start flex-wrap gap-4 w-full">
|
|
102
|
+
<div className="flex items-start gap-3">
|
|
103
|
+
<Button variant="outline" size="icon" aria-label="Back to products" asChild>
|
|
104
|
+
<Link href="/cms/products">
|
|
105
|
+
<ArrowLeft className="h-4 w-4" />
|
|
106
|
+
</Link>
|
|
107
|
+
</Button>
|
|
108
|
+
<div className="space-y-2">
|
|
109
|
+
<div className="flex items-center gap-2 flex-wrap">
|
|
110
|
+
<h1 className="text-2xl font-bold">
|
|
111
|
+
{targetLanguage ? `Create ${targetLanguage.name} Translation` : 'Create Product'}
|
|
112
|
+
</h1>
|
|
113
|
+
{targetLanguage ? (
|
|
114
|
+
<Badge variant="secondary">
|
|
115
|
+
{targetLanguage.code.toUpperCase()}
|
|
116
|
+
</Badge>
|
|
117
|
+
) : null}
|
|
118
|
+
</div>
|
|
119
|
+
<p className="text-sm text-muted-foreground max-w-3xl">
|
|
120
|
+
{targetLanguage
|
|
121
|
+
? 'We prefilled this draft from the source product so you can localize the content and fine-tune pricing, media, and variations faster.'
|
|
122
|
+
: 'Build a catalog-ready product with structured information, media, pricing, inventory, and optional variations.'}
|
|
123
|
+
</p>
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
|
|
128
|
+
<ProductFormClientShell
|
|
129
|
+
availableLanguagesProp={languages}
|
|
130
|
+
globalAttributesProp={globalAttributes}
|
|
131
|
+
currenciesProp={currencies}
|
|
132
|
+
translationGroupId={from_group}
|
|
133
|
+
targetLanguageId={target_lang_id}
|
|
134
|
+
initialData={normalizedInitialData}
|
|
135
|
+
enabledProviders={enabledProviders}
|
|
136
|
+
configStatus={configStatus}
|
|
137
|
+
createAction={createProductAction}
|
|
138
|
+
availableCategoriesProp={categories}
|
|
139
|
+
/>
|
|
140
|
+
</div>
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
143
|
|
|
@@ -2,9 +2,9 @@ import { ProductsPage as ProductsPageUI } from '@nextblock-cms/ecommerce/server'
|
|
|
2
2
|
import { verifyPackageOnline } from '@nextblock-cms/db/server';
|
|
3
3
|
import { redirect } from 'next/navigation';
|
|
4
4
|
|
|
5
|
-
import { getActiveLanguagesServerSide } from '@nextblock-cms/db/server';
|
|
6
|
-
import LanguageFilterSelect from '../components/LanguageFilterSelect';
|
|
7
|
-
import { ContentTransferControls } from '../import-export/ContentTransferControls';
|
|
5
|
+
import { getActiveLanguagesServerSide, getServiceRoleSupabaseClient } from '@nextblock-cms/db/server';
|
|
6
|
+
import LanguageFilterSelect from '../components/LanguageFilterSelect';
|
|
7
|
+
import { ContentTransferControls } from '../import-export/ContentTransferControls';
|
|
8
8
|
|
|
9
9
|
export default async function ProductsPage({ searchParams }: { searchParams: Promise<{ lang?: string }> }) {
|
|
10
10
|
const isOnline = await verifyPackageOnline('ecommerce');
|
|
@@ -13,30 +13,42 @@ export default async function ProductsPage({ searchParams }: { searchParams: Pro
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
const resolvedSearchParams = await searchParams;
|
|
16
|
-
const allLanguages = await getActiveLanguagesServerSide();
|
|
17
|
-
const selectedLangId = resolvedSearchParams?.lang ? parseInt(resolvedSearchParams.lang, 10) : undefined;
|
|
18
|
-
const isValidLangId = selectedLangId
|
|
19
|
-
? allLanguages.some((language) => language.id === selectedLangId)
|
|
20
|
-
: true;
|
|
21
|
-
const filterLangId = isValidLangId ? selectedLangId : undefined;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
16
|
+
const allLanguages = await getActiveLanguagesServerSide();
|
|
17
|
+
const selectedLangId = resolvedSearchParams?.lang ? parseInt(resolvedSearchParams.lang, 10) : undefined;
|
|
18
|
+
const isValidLangId = selectedLangId
|
|
19
|
+
? allLanguages.some((language) => language.id === selectedLangId)
|
|
20
|
+
: true;
|
|
21
|
+
const filterLangId = isValidLangId ? selectedLangId : undefined;
|
|
22
|
+
|
|
23
|
+
// Cheap existence check so the Export button can disable when there is nothing
|
|
24
|
+
// to export. Filtered by language to match what the export action produces.
|
|
25
|
+
const supabase = getServiceRoleSupabaseClient();
|
|
26
|
+
let productCountQuery = supabase
|
|
27
|
+
.from('products')
|
|
28
|
+
.select('id', { count: 'exact', head: true });
|
|
29
|
+
if (filterLangId) {
|
|
30
|
+
productCountQuery = productCountQuery.eq('language_id', filterLangId);
|
|
31
|
+
}
|
|
32
|
+
const { count: productCount } = await productCountQuery;
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<ProductsPageUI
|
|
36
|
+
searchParams={resolvedSearchParams}
|
|
37
|
+
transferControlsNode={
|
|
38
|
+
<ContentTransferControls
|
|
39
|
+
contentType="products"
|
|
40
|
+
label="Products"
|
|
41
|
+
languageId={filterLangId}
|
|
42
|
+
hasContent={(productCount ?? 0) > 0}
|
|
43
|
+
/>
|
|
44
|
+
}
|
|
45
|
+
languageFilterNode={
|
|
46
|
+
<LanguageFilterSelect
|
|
47
|
+
allLanguages={allLanguages}
|
|
48
|
+
currentFilterLangId={filterLangId}
|
|
49
|
+
basePath="/cms/products"
|
|
50
|
+
/>
|
|
51
|
+
}
|
|
40
52
|
/>
|
|
41
53
|
);
|
|
42
54
|
}
|