simple-module-pagebuilder 0.0.7__tar.gz → 0.0.9__tar.gz
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.
- simple_module_pagebuilder-0.0.7/README.md → simple_module_pagebuilder-0.0.9/PKG-INFO +82 -0
- simple_module_pagebuilder-0.0.7/PKG-INFO → simple_module_pagebuilder-0.0.9/README.md +58 -23
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/package.json +2 -2
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/boot.py +20 -2
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/ConfirmDialog.tsx +14 -6
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/DiffSummary.tsx +15 -6
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/NewPageDialog.tsx +22 -23
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/NoteDialog.tsx +12 -5
- simple_module_pagebuilder-0.0.9/pagebuilder/components/PageBoard.tsx +162 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/PageBoardCard.tsx +31 -22
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/PageListFilters.tsx +12 -8
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/PageListRow.tsx +12 -11
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/ScheduledBadge.tsx +6 -1
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/StatusBadge.tsx +6 -4
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/TranslatePageDialog.tsx +22 -17
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/blocks/Button.tsx +20 -20
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/blocks/Columns.tsx +5 -4
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/blocks/Heading.tsx +14 -14
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/blocks/Image.test.tsx +10 -1
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/blocks/Image.tsx +19 -14
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/blocks/MediaPicker.tsx +16 -12
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/blocks/Spacer.tsx +7 -6
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/blocks/Text.tsx +12 -12
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/editor/BlockOutline.tsx +5 -3
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/editor/NarrowCanvas.tsx +14 -7
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/editor/PageActions.tsx +12 -12
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/editor/PageEditorToolbar.tsx +25 -23
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/editor/PageInspectorDrawer.tsx +18 -2
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/editor/PageSettingsPanel.tsx +19 -15
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/editor/RevisionHistoryPanel.tsx +33 -14
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/editor/SchedulePanel.tsx +9 -7
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/editor/SeoPreview.tsx +8 -7
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/editor/SeoSettingsPanel.tsx +24 -18
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/editor/TranslationsPanel.tsx +24 -12
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/layoutPuckConfig.tsx +10 -2
- simple_module_pagebuilder-0.0.9/pagebuilder/components/localizeConfig.test.ts +94 -0
- simple_module_pagebuilder-0.0.9/pagebuilder/components/localizeConfig.ts +113 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/media/MediaFilters.tsx +12 -7
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/media/MediaFolderSidebar.tsx +11 -6
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/media/MediaGrid.tsx +12 -8
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/media/MediaHeader.tsx +5 -2
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/media/MediaUploadQueue.tsx +11 -5
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/media/MediaUsageList.tsx +13 -5
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/puckConfig.test.tsx +23 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/puckConfig.tsx +7 -5
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/snapshots/ImportPlanSummary.tsx +21 -13
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/snapshots/SnapshotList.tsx +14 -15
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/snapshots/UploadBundleDialog.tsx +10 -10
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/snapshots/planSummary.ts +45 -20
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgetCatalog.ts +13 -5
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/accordion-widget.tsx +8 -5
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/alert-widget.tsx +9 -8
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/app-store-badges-widget.tsx +29 -14
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/article-cards-widget.tsx +20 -16
- simple_module_pagebuilder-0.0.9/pagebuilder/components/widgets/call-to-action-widget.tsx +86 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/carousel-widget.tsx +12 -7
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/centered-hero-widget.tsx +11 -7
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/colored-action-list-widget.tsx +11 -10
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/column-widget.tsx +14 -13
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/contact-cards-widget.tsx +16 -12
- simple_module_pagebuilder-0.0.9/pagebuilder/components/widgets/contact-form-widget.tsx +75 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/container-widget.tsx +20 -19
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/definition-list-widget.tsx +31 -12
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/divider-widget.tsx +16 -11
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/eyebrow-section-widget.tsx +5 -4
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/faq-widget.tsx +15 -15
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/feature-card-widget.tsx +9 -8
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/feature-cards-render.tsx +7 -3
- simple_module_pagebuilder-0.0.9/pagebuilder/components/widgets/feature-cards-widget.tsx +139 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/feature-grid-widget.tsx +18 -11
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/feature-showcase-widget.tsx +16 -12
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/gallery-widget.tsx +16 -15
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/grid-widget.tsx +12 -11
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/hero-widget.tsx +28 -28
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/html-widget.tsx +6 -5
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/iframe-widget.tsx +8 -7
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/leaderboard-widget.tsx +22 -15
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/list-widget.tsx +6 -5
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/logo-cloud-widget.tsx +12 -11
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/markdown-widget.tsx +9 -8
- simple_module_pagebuilder-0.0.9/pagebuilder/components/widgets/media-object-widget.tsx +180 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/newsletter-widget.tsx +11 -10
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/page-header-widget.tsx +17 -16
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/prose-section-widget.tsx +12 -11
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/quote-widget.tsx +8 -7
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/row-widget.tsx +14 -13
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/section-intro-widget.tsx +13 -12
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/signup-banner-widget.tsx +6 -5
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/simple-action-list-widget.tsx +7 -6
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/site-footer-widget.tsx +22 -12
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/site-header-nav.tsx +9 -2
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/site-header-widget.tsx +48 -24
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/social-banner-widget.tsx +11 -7
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/stats-widget.tsx +15 -11
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/steps-widget.tsx +21 -20
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/story-cards-widget.tsx +20 -16
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/table-widget.tsx +8 -5
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/tabs-widget.tsx +12 -8
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/tags-widget.tsx +12 -9
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/testimonial-widget.tsx +11 -7
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/timeline-widget.tsx +22 -22
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/under-construction-widget.tsx +3 -2
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/video-widget.tsx +13 -12
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/welcome-widget.tsx +5 -4
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/endpoints/api/media_detail.py +10 -3
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/endpoints/content_views.py +1 -1
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/endpoints/public_views.py +20 -5
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/endpoints/seo.py +9 -2
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/endpoints/views.py +1 -1
- simple_module_pagebuilder-0.0.9/pagebuilder/fields/checkbox-field.tsx +57 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/fields/file-picker/file-gallery.tsx +12 -6
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/fields/file-picker/image-picker-field.tsx +11 -7
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/hooks/useAutosave.ts +4 -1
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/hooks/useEditorForm.ts +4 -2
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/hooks/useMediaDetail.ts +2 -1
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/hooks/useMediaUploads.ts +5 -1
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/hooks/usePageRevisions.ts +4 -2
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/hooks/usePageSchedule.ts +8 -6
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/hooks/usePageWorkflow.ts +13 -11
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/hooks/useSnapshots.ts +5 -3
- simple_module_pagebuilder-0.0.9/pagebuilder/locales/en.json +1375 -0
- simple_module_pagebuilder-0.0.9/pagebuilder/media_files.py +259 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/media_service.py +24 -10
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/media_usage.py +14 -8
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/models/_layout.py +3 -3
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/models/_media.py +15 -4
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/models/_page.py +21 -13
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/models/_redirect.py +7 -4
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/models/_snapshot.py +6 -5
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/module.py +40 -1
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/pages/ContentImportReview.tsx +42 -32
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/pages/ContentSnapshots.tsx +21 -13
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/pages/LayoutEditor.tsx +43 -30
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/pages/MediaDetail.tsx +36 -28
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/pages/MediaLibrary.tsx +16 -14
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/pages/PageEditor.tsx +11 -4
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/pages/PageList.tsx +35 -29
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/pages/PendingReview.tsx +26 -26
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/pages/Trash.tsx +33 -27
- simple_module_pagebuilder-0.0.9/pagebuilder/scheduler.py +158 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/security.py +19 -4
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/service/_trash.py +15 -5
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/service/_workflow.py +29 -14
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/snapshots/apply.py +1 -1
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/snapshots/assets.py +10 -11
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/snapshots/blobs.py +16 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/snapshots/capture.py +13 -5
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/snapshots/media_match.py +4 -3
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/snapshots/service.py +2 -3
- simple_module_pagebuilder-0.0.9/pagebuilder/tenancy.py +198 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/utils/editorSnapshot.ts +18 -5
- simple_module_pagebuilder-0.0.9/pagebuilder/utils/i18n.test.ts +137 -0
- simple_module_pagebuilder-0.0.9/pagebuilder/utils/i18n.ts +180 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/utils/mediaApi.ts +10 -2
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/utils/request.ts +16 -4
- simple_module_pagebuilder-0.0.9/pagebuilder/utils/slugify.test.ts +46 -0
- simple_module_pagebuilder-0.0.9/pagebuilder/utils/slugify.ts +52 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pyproject.toml +11 -11
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/conftest.py +35 -24
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/db_fixture.py +6 -11
- simple_module_pagebuilder-0.0.9/tests/pg_support.py +54 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/snapshot_fixture.py +7 -14
- simple_module_pagebuilder-0.0.9/tests/tenant_app.py +64 -0
- simple_module_pagebuilder-0.0.9/tests/tenant_fixture.py +42 -0
- simple_module_pagebuilder-0.0.9/tests/test_i18n.py +77 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_image_processing.py +9 -22
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_media_files.py +14 -18
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_media_security.py +3 -15
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_public_viewer.py +18 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_scheduled_publish.py +3 -11
- simple_module_pagebuilder-0.0.9/tests/test_scheduler_stop.py +81 -0
- simple_module_pagebuilder-0.0.9/tests/test_scheduler_tenancy.py +114 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_snapshot_apply.py +1 -1
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_snapshot_apply_media.py +1 -1
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_snapshot_capture.py +2 -2
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_snapshot_media_match.py +1 -1
- simple_module_pagebuilder-0.0.9/tests/test_tenancy_blobs.py +42 -0
- simple_module_pagebuilder-0.0.9/tests/test_tenancy_core.py +177 -0
- simple_module_pagebuilder-0.0.9/tests/test_tenancy_isolation.py +85 -0
- simple_module_pagebuilder-0.0.9/tests/test_tenancy_media.py +245 -0
- simple_module_pagebuilder-0.0.9/tests/test_tenancy_public.py +125 -0
- simple_module_pagebuilder-0.0.9/tests/test_tenancy_routes.py +64 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tsconfig.json +1 -0
- simple_module_pagebuilder-0.0.7/pagebuilder/components/PageBoard.tsx +0 -127
- simple_module_pagebuilder-0.0.7/pagebuilder/components/widgets/call-to-action-widget.tsx +0 -83
- simple_module_pagebuilder-0.0.7/pagebuilder/components/widgets/contact-form-widget.tsx +0 -69
- simple_module_pagebuilder-0.0.7/pagebuilder/components/widgets/feature-cards-widget.tsx +0 -133
- simple_module_pagebuilder-0.0.7/pagebuilder/components/widgets/media-object-widget.tsx +0 -180
- simple_module_pagebuilder-0.0.7/pagebuilder/fields/checkbox-field.tsx +0 -22
- simple_module_pagebuilder-0.0.7/pagebuilder/media_files.py +0 -128
- simple_module_pagebuilder-0.0.7/pagebuilder/scheduler.py +0 -92
- simple_module_pagebuilder-0.0.7/pagebuilder/utils/slugify.ts +0 -9
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/.gitignore +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/__init__.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/board.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/blockRegistry.test.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/blockRegistry.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/lazyBlock.tsx +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/media/types.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/migrateContent.test.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/migrateContent.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/snapshots/planSummary.test.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgetCatalog.test.tsx +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/_internal/accent-text.tsx +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/_internal/disclosure-chevron.tsx +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/_internal/eyebrow-split-section.tsx +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/_internal/link-arrow.tsx +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/_internal/rich-text.tsx +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/_internal/solid-icons.tsx +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/_shared/background-media.tsx +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/_shared/content-media.tsx +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/_shared/cta-button.tsx +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/_shared/empty-placeholder.tsx +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/_shared/eyebrow-text.tsx +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/_shared/heading.tsx +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/_shared/image-srcset.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/_shared/index.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/_shared/mask.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/_shared/section.tsx +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/_shared/social-icon.tsx +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/_shared/text-link.tsx +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/article-cards-render.tsx +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/call-to-action-render.tsx +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/call-to-action-styles.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/contact-form-render.tsx +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/divider-widget.test.tsx +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/faq-render.tsx +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/feature-cards-styles.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/hero-widget-props.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/media-object-layout.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/media-object-render.tsx +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/media-object-text.tsx +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/timeline-layout.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/components/widgets/timeline-render.tsx +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/contracts/__init__.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/contracts/events.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/contracts/schemas/__init__.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/contracts/schemas/_layout.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/contracts/schemas/_media.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/contracts/schemas/_pages.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/contracts/schemas/_snapshots.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/conversion/blocks-to-html.test.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/conversion/blocks-to-html.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/conversion/index.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/conversion/types.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/deps.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/diff.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/endpoints/__init__.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/endpoints/api/__init__.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/endpoints/api/_deps.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/endpoints/api/layout.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/endpoints/api/pages.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/endpoints/api/revisions.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/endpoints/api/snapshots.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/endpoints/api/uploads.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/endpoints/api/workflow.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/fields/file-picker/index.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/fields/file-picker/types.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/fields/index.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/fields/media-adapter.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/hooks/useIsNarrow.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/hooks/usePendingDialog.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/layout_service.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/locales.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/media_images.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/media_queries.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/models/__init__.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/models/_base.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/pages/PublicPage.tsx +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/permissions.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/public_claims.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/py.typed +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/redirects.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/service/__init__.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/service/_common.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/service/_revisions.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/service/_translations.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/services.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/settings.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/snapshots/__init__.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/snapshots/archive.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/snapshots/format.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/snapshots/pages.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/snapshots/plan.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/snapshots/validate.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/static/widgets-base.css +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/translation/apply.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/translation/extract.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/translation/index.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/translation/translatable-fields.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/translation/translation.test.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/utils/api.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/utils/blockOutline.test.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/utils/blockOutline.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/utils/datetime.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/utils/decorative-image.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/utils/locale.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/utils/markdown.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/utils/measure.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/utils/mediaFormat.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/utils/pagesApi.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/utils/parse-list.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/utils/request.test.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/utils/snapshotsApi.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/utils/types.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/pagebuilder/utils/widgetUtils.ts +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/locale_fixture.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/page_helpers.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_admin_list_view.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_approval_workflow.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_auth_gating.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_csrf.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_draft_preview.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_hreflang_and_sitemap.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_media_detail.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_media_usage_escaping.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_module.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_multilingual.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_page_templates.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_page_translations.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_pages_api.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_pages_search.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_public_claims.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_public_routes.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_public_view_headers.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_redirects.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_revision_notes_and_diff.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_revisions_api.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_seo_meta.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_settings_source.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_site_layout.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_sitemap_robots.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_snapshot_archive.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_snapshot_assets.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_snapshot_blobs.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_snapshot_models.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_snapshot_multilingual.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_snapshot_page_payload.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_snapshot_plan.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_snapshot_validate.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_snapshot_views.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_snapshots_api.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_trash.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_trash_preconditions.py +0 -0
- {simple_module_pagebuilder-0.0.7 → simple_module_pagebuilder-0.0.9}/tests/test_uploads_api.py +0 -0
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: simple_module_pagebuilder
|
|
3
|
+
Version: 0.0.9
|
|
4
|
+
Summary: Drag-and-drop visual page builder for simple_module apps
|
|
5
|
+
Project-URL: Repository, https://github.com/antosubash/simple_module_python_modules
|
|
6
|
+
Author-email: Anto Subash <antosubash@live.com>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Keywords: cms,pagebuilder,puck,simple-module
|
|
9
|
+
Requires-Python: >=3.12
|
|
10
|
+
Requires-Dist: pillow>=10.0
|
|
11
|
+
Requires-Dist: pydantic-settings>=2.0
|
|
12
|
+
Requires-Dist: simple-module-core<0.1,>=0.0.35
|
|
13
|
+
Requires-Dist: simple-module-db<0.1,>=0.0.35
|
|
14
|
+
Requires-Dist: simple-module-hosting<0.1,>=0.0.35
|
|
15
|
+
Requires-Dist: simple-module-inertia<0.1,>=0.0.35
|
|
16
|
+
Requires-Dist: simple-module-settings<0.1,>=0.0.35
|
|
17
|
+
Requires-Dist: sqlalchemy>=2.0
|
|
18
|
+
Requires-Dist: sqlmodel>=0.0.21
|
|
19
|
+
Provides-Extra: dev
|
|
20
|
+
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
|
|
21
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
22
|
+
Requires-Dist: simple-module-test<0.1,>=0.0.35; extra == 'dev'
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
1
25
|
# simple_module_pagebuilder
|
|
2
26
|
|
|
3
27
|
Drag-and-drop visual page builder for [simple_module](https://github.com/antosubash/simple_module_python)
|
|
@@ -221,6 +245,64 @@ Its breadcrumb parent is the parent's own counterpart, so a trail never crosses
|
|
|
221
245
|
languages. A page's own language is fixed for its lifetime — moving one would
|
|
222
246
|
strand its slug and orphan the redirect pointing at it.
|
|
223
247
|
|
|
248
|
+
## The editor's language
|
|
249
|
+
|
|
250
|
+
Separate from the page's. The section above is about what the *site*
|
|
251
|
+
publishes; this is about what the *editor* speaks, and the two are configured
|
|
252
|
+
in different places — `content_locales` for one, the host's
|
|
253
|
+
`SM_I18N_SUPPORTED_LOCALES` for the other.
|
|
254
|
+
|
|
255
|
+
Every editor string lives in `pagebuilder/locales/en.json`, registered by
|
|
256
|
+
`PagebuilderModule.locale_dirs()` under the `pagebuilder` namespace, so a key
|
|
257
|
+
reads `pagebuilder.<section>.<name>` in the merged catalogue the host ships to
|
|
258
|
+
the browser. Add a language by adding `pagebuilder/locales/<tag>.json` with the
|
|
259
|
+
same shape; the framework's `SM013`–`SM016` diagnostics report a file that has
|
|
260
|
+
drifted from the default.
|
|
261
|
+
|
|
262
|
+
The frontend derives its key tree from that JSON at compile time —
|
|
263
|
+
`pagebuilder/utils/i18n.ts` — rather than from the framework's generated
|
|
264
|
+
`keys`, which only carries the namespaces of modules that live in the
|
|
265
|
+
framework's own monorepo. The upshot is that `tsc` rejects a key the catalogue
|
|
266
|
+
does not define, and `pagebuilder/utils/i18n.test.ts` rejects an entry nothing
|
|
267
|
+
references, a plural missing a form, and a placeholder nothing fills.
|
|
268
|
+
|
|
269
|
+
**Block labels are keys, resolved at the screen.** A Puck config is a
|
|
270
|
+
module-scope constant — the palette is assembled before the app has rendered
|
|
271
|
+
anything — so a block cannot call a hook where its labels are written. What it
|
|
272
|
+
holds instead is the key, and `components/localizeConfig.ts` resolves the whole
|
|
273
|
+
assembled config once inside `PageEditor` and `LayoutEditor`: component labels,
|
|
274
|
+
field labels (including the ones nested in an `array` or `object` field),
|
|
275
|
+
select options, category titles and the viewport switcher. Because it walks the
|
|
276
|
+
*assembled* config, a block another module registered is localized on the same
|
|
277
|
+
pass, provided that module's labels are catalogue keys too.
|
|
278
|
+
|
|
279
|
+
`defaultProps` stay literal on purpose. They are the seed *content* a block is
|
|
280
|
+
inserted with and are then saved into the document, so translating them at
|
|
281
|
+
render time would rewrite what a visitor is served in whatever language the
|
|
282
|
+
author happened to be working in.
|
|
283
|
+
|
|
284
|
+
## Multi-tenancy
|
|
285
|
+
|
|
286
|
+
Every pagebuilder table is tenant-owned (the framework's `MultiTenantMixin`),
|
|
287
|
+
so one host can run several sites. Slugs, redirects, media filenames and the
|
|
288
|
+
one-pending-import rule are unique **per tenant**, and each tenant has its own
|
|
289
|
+
site layout, media directory (`<media_root>/<tenant>/`) and snapshot blob store.
|
|
290
|
+
|
|
291
|
+
Which tenant a request acts for depends on the host:
|
|
292
|
+
|
|
293
|
+
- **Single-tenant** (`multi_tenant` off) — everything is tenant `"default"`,
|
|
294
|
+
where the migration also files every row that predates tenancy. A host that
|
|
295
|
+
pins `default_tenant` to anything else is refused at startup.
|
|
296
|
+
- **Multi-tenant** (`multi_tenant` on) — the tenant the framework resolved.
|
|
297
|
+
With the `tenants` module, anonymous visitors are resolved by subdomain
|
|
298
|
+
(`subdomain_base`); members by their membership. A public page, sitemap or
|
|
299
|
+
media request with no tenant answers 404 — the same as an unknown slug — and
|
|
300
|
+
an editor with no tenant gets 403. Custom domains are not supported yet.
|
|
301
|
+
|
|
302
|
+
The scheduler publishes due pages tenant by tenant, each in its own session.
|
|
303
|
+
Requires framework `0.0.35` or later, and the host migration that adds
|
|
304
|
+
`tenant_id` (`make migration` picks it up like any other model change).
|
|
305
|
+
|
|
224
306
|
## Content snapshots
|
|
225
307
|
|
|
226
308
|
**Content › Import / Export** captures the site as a restore point. Every entry
|
|
@@ -1,26 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.5
|
|
2
|
-
Name: simple_module_pagebuilder
|
|
3
|
-
Version: 0.0.7
|
|
4
|
-
Summary: Drag-and-drop visual page builder for simple_module apps
|
|
5
|
-
Project-URL: Repository, https://github.com/antosubash/simple_module_python_modules
|
|
6
|
-
Author-email: Anto Subash <antosubash@live.com>
|
|
7
|
-
License-Expression: MIT
|
|
8
|
-
Keywords: cms,pagebuilder,puck,simple-module
|
|
9
|
-
Requires-Python: >=3.12
|
|
10
|
-
Requires-Dist: pillow>=10.0
|
|
11
|
-
Requires-Dist: pydantic-settings>=2.0
|
|
12
|
-
Requires-Dist: simple-module-core<0.1,>=0.0.25
|
|
13
|
-
Requires-Dist: simple-module-db<0.1,>=0.0.25
|
|
14
|
-
Requires-Dist: simple-module-hosting<0.1,>=0.0.25
|
|
15
|
-
Requires-Dist: simple-module-settings<0.1,>=0.0.25
|
|
16
|
-
Requires-Dist: sqlalchemy>=2.0
|
|
17
|
-
Requires-Dist: sqlmodel>=0.0.21
|
|
18
|
-
Provides-Extra: dev
|
|
19
|
-
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
|
|
20
|
-
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
21
|
-
Requires-Dist: simple-module-test<0.1,>=0.0.25; extra == 'dev'
|
|
22
|
-
Description-Content-Type: text/markdown
|
|
23
|
-
|
|
24
1
|
# simple_module_pagebuilder
|
|
25
2
|
|
|
26
3
|
Drag-and-drop visual page builder for [simple_module](https://github.com/antosubash/simple_module_python)
|
|
@@ -244,6 +221,64 @@ Its breadcrumb parent is the parent's own counterpart, so a trail never crosses
|
|
|
244
221
|
languages. A page's own language is fixed for its lifetime — moving one would
|
|
245
222
|
strand its slug and orphan the redirect pointing at it.
|
|
246
223
|
|
|
224
|
+
## The editor's language
|
|
225
|
+
|
|
226
|
+
Separate from the page's. The section above is about what the *site*
|
|
227
|
+
publishes; this is about what the *editor* speaks, and the two are configured
|
|
228
|
+
in different places — `content_locales` for one, the host's
|
|
229
|
+
`SM_I18N_SUPPORTED_LOCALES` for the other.
|
|
230
|
+
|
|
231
|
+
Every editor string lives in `pagebuilder/locales/en.json`, registered by
|
|
232
|
+
`PagebuilderModule.locale_dirs()` under the `pagebuilder` namespace, so a key
|
|
233
|
+
reads `pagebuilder.<section>.<name>` in the merged catalogue the host ships to
|
|
234
|
+
the browser. Add a language by adding `pagebuilder/locales/<tag>.json` with the
|
|
235
|
+
same shape; the framework's `SM013`–`SM016` diagnostics report a file that has
|
|
236
|
+
drifted from the default.
|
|
237
|
+
|
|
238
|
+
The frontend derives its key tree from that JSON at compile time —
|
|
239
|
+
`pagebuilder/utils/i18n.ts` — rather than from the framework's generated
|
|
240
|
+
`keys`, which only carries the namespaces of modules that live in the
|
|
241
|
+
framework's own monorepo. The upshot is that `tsc` rejects a key the catalogue
|
|
242
|
+
does not define, and `pagebuilder/utils/i18n.test.ts` rejects an entry nothing
|
|
243
|
+
references, a plural missing a form, and a placeholder nothing fills.
|
|
244
|
+
|
|
245
|
+
**Block labels are keys, resolved at the screen.** A Puck config is a
|
|
246
|
+
module-scope constant — the palette is assembled before the app has rendered
|
|
247
|
+
anything — so a block cannot call a hook where its labels are written. What it
|
|
248
|
+
holds instead is the key, and `components/localizeConfig.ts` resolves the whole
|
|
249
|
+
assembled config once inside `PageEditor` and `LayoutEditor`: component labels,
|
|
250
|
+
field labels (including the ones nested in an `array` or `object` field),
|
|
251
|
+
select options, category titles and the viewport switcher. Because it walks the
|
|
252
|
+
*assembled* config, a block another module registered is localized on the same
|
|
253
|
+
pass, provided that module's labels are catalogue keys too.
|
|
254
|
+
|
|
255
|
+
`defaultProps` stay literal on purpose. They are the seed *content* a block is
|
|
256
|
+
inserted with and are then saved into the document, so translating them at
|
|
257
|
+
render time would rewrite what a visitor is served in whatever language the
|
|
258
|
+
author happened to be working in.
|
|
259
|
+
|
|
260
|
+
## Multi-tenancy
|
|
261
|
+
|
|
262
|
+
Every pagebuilder table is tenant-owned (the framework's `MultiTenantMixin`),
|
|
263
|
+
so one host can run several sites. Slugs, redirects, media filenames and the
|
|
264
|
+
one-pending-import rule are unique **per tenant**, and each tenant has its own
|
|
265
|
+
site layout, media directory (`<media_root>/<tenant>/`) and snapshot blob store.
|
|
266
|
+
|
|
267
|
+
Which tenant a request acts for depends on the host:
|
|
268
|
+
|
|
269
|
+
- **Single-tenant** (`multi_tenant` off) — everything is tenant `"default"`,
|
|
270
|
+
where the migration also files every row that predates tenancy. A host that
|
|
271
|
+
pins `default_tenant` to anything else is refused at startup.
|
|
272
|
+
- **Multi-tenant** (`multi_tenant` on) — the tenant the framework resolved.
|
|
273
|
+
With the `tenants` module, anonymous visitors are resolved by subdomain
|
|
274
|
+
(`subdomain_base`); members by their membership. A public page, sitemap or
|
|
275
|
+
media request with no tenant answers 404 — the same as an unknown slug — and
|
|
276
|
+
an editor with no tenant gets 403. Custom domains are not supported yet.
|
|
277
|
+
|
|
278
|
+
The scheduler publishes due pages tenant by tenant, each in its own session.
|
|
279
|
+
Requires framework `0.0.35` or later, and the host migration that adds
|
|
280
|
+
`tenant_id` (`make migration` picks it up like any other model change).
|
|
281
|
+
|
|
247
282
|
## Content snapshots
|
|
248
283
|
|
|
249
284
|
**Content › Import / Export** captures the site as a restore point. Every entry
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simple-module-py/pagebuilder",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Frontend assets for the PageBuilder module",
|
|
6
6
|
"peerDependencies": {
|
|
7
7
|
"react": "^19.0.0",
|
|
8
8
|
"react-dom": "^19.0.0",
|
|
9
|
-
"@inertiajs/react": "^
|
|
9
|
+
"@inertiajs/react": "^3.7.0",
|
|
10
10
|
"@simple-module-py/ui": "*"
|
|
11
11
|
},
|
|
12
12
|
"devDependencies": {
|
|
@@ -28,8 +28,15 @@ import logging
|
|
|
28
28
|
from fastapi import FastAPI
|
|
29
29
|
|
|
30
30
|
from pagebuilder import locales
|
|
31
|
-
from pagebuilder.media_files import
|
|
31
|
+
from pagebuilder.media_files import (
|
|
32
|
+
MediaFiles,
|
|
33
|
+
adopt_legacy_files,
|
|
34
|
+
is_generated_media_name,
|
|
35
|
+
resolve_media_root,
|
|
36
|
+
warn_on_orphaned_media,
|
|
37
|
+
)
|
|
32
38
|
from pagebuilder.settings import PagebuilderSettings
|
|
39
|
+
from pagebuilder.snapshots.blobs import BLOBS_DIR, is_digest
|
|
33
40
|
|
|
34
41
|
_log = logging.getLogger("simple_module.pagebuilder")
|
|
35
42
|
|
|
@@ -126,10 +133,21 @@ def mount_public_routers(app: FastAPI, settings: PagebuilderSettings) -> None:
|
|
|
126
133
|
|
|
127
134
|
|
|
128
135
|
async def mount_media(app: FastAPI, settings: PagebuilderSettings) -> None:
|
|
129
|
-
"""Serve uploaded files from ``{media_url_prefix}/{filename}``.
|
|
136
|
+
"""Serve uploaded files from ``{media_url_prefix}/{tenant_id}/{filename}``.
|
|
137
|
+
|
|
138
|
+
Files (and snapshot blobs) written before per-tenant storage sit directly
|
|
139
|
+
under their root; they are moved into the default tenant's directory
|
|
140
|
+
first, so the orphan scan below and every later read find them (#38).
|
|
141
|
+
"""
|
|
130
142
|
media_root = resolve_media_root(settings.media_root)
|
|
131
143
|
media_root.mkdir(parents=True, exist_ok=True)
|
|
132
144
|
_log.info("pagebuilder.media_root: %s", media_root)
|
|
145
|
+
adopt_legacy_files(media_root, accept=is_generated_media_name)
|
|
146
|
+
adopt_legacy_files(
|
|
147
|
+
resolve_media_root(settings.snapshot_root) / BLOBS_DIR,
|
|
148
|
+
accept=is_digest,
|
|
149
|
+
label="snapshot_blobs",
|
|
150
|
+
)
|
|
133
151
|
app.mount(
|
|
134
152
|
settings.media_url_prefix,
|
|
135
153
|
MediaFiles(directory=media_root),
|
|
@@ -14,6 +14,7 @@ import { Label } from '@simple-module-py/ui/components/ui/label';
|
|
|
14
14
|
import { type ReactNode, useState } from 'react';
|
|
15
15
|
|
|
16
16
|
import { usePendingDialog } from '../hooks/usePendingDialog';
|
|
17
|
+
import { keys, useT } from '../utils/i18n';
|
|
17
18
|
|
|
18
19
|
/** How much a confirmation is allowed to cost the person clicking it.
|
|
19
20
|
*
|
|
@@ -49,7 +50,7 @@ export function ConfirmDialog({
|
|
|
49
50
|
trigger,
|
|
50
51
|
title,
|
|
51
52
|
description,
|
|
52
|
-
confirmLabel
|
|
53
|
+
confirmLabel,
|
|
53
54
|
destructive = false,
|
|
54
55
|
level,
|
|
55
56
|
confirmPhrase,
|
|
@@ -72,6 +73,8 @@ export function ConfirmDialog({
|
|
|
72
73
|
/** Rejecting keeps the dialog open and surfaces the message. */
|
|
73
74
|
onConfirm: () => Promise<unknown>;
|
|
74
75
|
}) {
|
|
76
|
+
const { t } = useT();
|
|
77
|
+
const label = confirmLabel ?? t(keys.pagebuilder.confirm.confirm);
|
|
75
78
|
const [typed, setTyped] = useState('');
|
|
76
79
|
|
|
77
80
|
const resolvedLevel: ConfirmLevel = level ?? (destructive ? 'medium' : 'low');
|
|
@@ -87,8 +90,9 @@ export function ConfirmDialog({
|
|
|
87
90
|
// phrase, because reopening must not inherit the one typed last time: that
|
|
88
91
|
// would put a second delete one click from confirmed, which is the exact
|
|
89
92
|
// property this level exists to remove.
|
|
90
|
-
const { open, pending, error, change, run } = usePendingDialog(
|
|
91
|
-
|
|
93
|
+
const { open, pending, error, change, run } = usePendingDialog(
|
|
94
|
+
t(keys.pagebuilder.confirm.failed, { action: label }),
|
|
95
|
+
() => setTyped(''),
|
|
92
96
|
);
|
|
93
97
|
|
|
94
98
|
return (
|
|
@@ -103,7 +107,9 @@ export function ConfirmDialog({
|
|
|
103
107
|
{needsPhrase && (
|
|
104
108
|
<div className="grid gap-2 py-2">
|
|
105
109
|
<Label htmlFor={CONFIRM_PHRASE_INPUT}>
|
|
106
|
-
|
|
110
|
+
{t(keys.pagebuilder.confirm.type_prefix)}{' '}
|
|
111
|
+
<code className="font-mono font-semibold">{confirmPhrase}</code>{' '}
|
|
112
|
+
{t(keys.pagebuilder.confirm.type_suffix)}
|
|
107
113
|
</Label>
|
|
108
114
|
<Input
|
|
109
115
|
id={CONFIRM_PHRASE_INPUT}
|
|
@@ -116,7 +122,9 @@ export function ConfirmDialog({
|
|
|
116
122
|
)}
|
|
117
123
|
{error && <p className="text-sm text-destructive">{error}</p>}
|
|
118
124
|
<AlertDialogFooter>
|
|
119
|
-
<AlertDialogCancel disabled={pending}>
|
|
125
|
+
<AlertDialogCancel disabled={pending}>
|
|
126
|
+
{t(keys.pagebuilder.confirm.cancel)}
|
|
127
|
+
</AlertDialogCancel>
|
|
120
128
|
<AlertDialogAction
|
|
121
129
|
disabled={pending || !unlocked}
|
|
122
130
|
className={
|
|
@@ -129,7 +137,7 @@ export function ConfirmDialog({
|
|
|
129
137
|
void run(onConfirm);
|
|
130
138
|
}}
|
|
131
139
|
>
|
|
132
|
-
{pending ?
|
|
140
|
+
{pending ? t(keys.pagebuilder.confirm.working) : label}
|
|
133
141
|
</AlertDialogAction>
|
|
134
142
|
</AlertDialogFooter>
|
|
135
143
|
</AlertDialogContent>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
2
|
import type { RevisionDiff } from '../utils/api';
|
|
3
|
+
import { keys, useT } from '../utils/i18n';
|
|
3
4
|
|
|
4
5
|
interface Props {
|
|
5
6
|
diff: RevisionDiff;
|
|
@@ -23,6 +24,7 @@ function renderValue(value: unknown): string {
|
|
|
23
24
|
* both sides can move together.
|
|
24
25
|
*/
|
|
25
26
|
export function DiffSummary({ diff }: Props): React.JSX.Element {
|
|
27
|
+
const { t } = useT();
|
|
26
28
|
const { metadata, blocks } = diff;
|
|
27
29
|
const metaKeys = Object.keys(metadata);
|
|
28
30
|
const totalChanges =
|
|
@@ -34,7 +36,7 @@ export function DiffSummary({ diff }: Props): React.JSX.Element {
|
|
|
34
36
|
className="mt-3 rounded border bg-card p-3 text-xs text-muted-foreground"
|
|
35
37
|
data-testid="diff-summary"
|
|
36
38
|
>
|
|
37
|
-
|
|
39
|
+
{t(keys.pagebuilder.diff.no_changes)}
|
|
38
40
|
</div>
|
|
39
41
|
);
|
|
40
42
|
}
|
|
@@ -43,7 +45,7 @@ export function DiffSummary({ diff }: Props): React.JSX.Element {
|
|
|
43
45
|
<div className="mt-3 space-y-2 rounded border bg-card p-3 text-xs" data-testid="diff-summary">
|
|
44
46
|
{metaKeys.length > 0 && (
|
|
45
47
|
<div>
|
|
46
|
-
<div className="font-semibold">
|
|
48
|
+
<div className="font-semibold">{t(keys.pagebuilder.diff.metadata)}</div>
|
|
47
49
|
<ul className="ml-3 list-disc">
|
|
48
50
|
{metaKeys.map((key) => (
|
|
49
51
|
<li key={key}>
|
|
@@ -59,7 +61,9 @@ export function DiffSummary({ diff }: Props): React.JSX.Element {
|
|
|
59
61
|
)}
|
|
60
62
|
{blocks.added.length > 0 && (
|
|
61
63
|
<div>
|
|
62
|
-
<div className="font-semibold text-green-700">
|
|
64
|
+
<div className="font-semibold text-green-700">
|
|
65
|
+
{t(keys.pagebuilder.diff.added, { count: blocks.added.length })}
|
|
66
|
+
</div>
|
|
63
67
|
<ul className="ml-3 list-disc">
|
|
64
68
|
{blocks.added.map((b) => (
|
|
65
69
|
<li key={b.id}>
|
|
@@ -72,7 +76,9 @@ export function DiffSummary({ diff }: Props): React.JSX.Element {
|
|
|
72
76
|
)}
|
|
73
77
|
{blocks.removed.length > 0 && (
|
|
74
78
|
<div>
|
|
75
|
-
<div className="font-semibold text-red-700">
|
|
79
|
+
<div className="font-semibold text-red-700">
|
|
80
|
+
{t(keys.pagebuilder.diff.removed, { count: blocks.removed.length })}
|
|
81
|
+
</div>
|
|
76
82
|
<ul className="ml-3 list-disc">
|
|
77
83
|
{blocks.removed.map((b) => (
|
|
78
84
|
<li key={b.id}>
|
|
@@ -85,7 +91,9 @@ export function DiffSummary({ diff }: Props): React.JSX.Element {
|
|
|
85
91
|
)}
|
|
86
92
|
{blocks.changed.length > 0 && (
|
|
87
93
|
<div>
|
|
88
|
-
<div className="font-semibold text-amber-700">
|
|
94
|
+
<div className="font-semibold text-amber-700">
|
|
95
|
+
{t(keys.pagebuilder.diff.changed, { count: blocks.changed.length })}
|
|
96
|
+
</div>
|
|
89
97
|
<ul className="ml-3 list-disc">
|
|
90
98
|
{blocks.changed.map((b) => (
|
|
91
99
|
<li key={b.id}>
|
|
@@ -94,7 +102,8 @@ export function DiffSummary({ diff }: Props): React.JSX.Element {
|
|
|
94
102
|
{b.type_before && (
|
|
95
103
|
<span className="text-muted-foreground">
|
|
96
104
|
{' '}
|
|
97
|
-
|
|
105
|
+
{t(keys.pagebuilder.diff.was)}{' '}
|
|
106
|
+
<span className="font-mono">{b.type_before}</span>
|
|
98
107
|
</span>
|
|
99
108
|
)}
|
|
100
109
|
{b.fields.length > 0 && <span>: {b.fields.join(', ')}</span>}
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
import { useEffect, useState } from 'react';
|
|
19
19
|
|
|
20
20
|
import type { PageRead } from '../utils/api';
|
|
21
|
+
import { keys, useT } from '../utils/i18n';
|
|
21
22
|
import { localeLabel, localePrefix } from '../utils/locale';
|
|
22
23
|
import { createPage, listPages, listTemplates } from '../utils/pagesApi';
|
|
23
24
|
import { slugify } from '../utils/slugify';
|
|
@@ -55,6 +56,7 @@ export function NewPageDialog({
|
|
|
55
56
|
locales = ['en'],
|
|
56
57
|
defaultLocale = 'en',
|
|
57
58
|
}: Props) {
|
|
59
|
+
const { t } = useT();
|
|
58
60
|
const [open, setOpen] = useState(false);
|
|
59
61
|
const [title, setTitle] = useState('');
|
|
60
62
|
// Null until the author edits it: while it is null the slug tracks the title,
|
|
@@ -124,7 +126,7 @@ export function NewPageDialog({
|
|
|
124
126
|
return (
|
|
125
127
|
<Dialog open={open} onOpenChange={reset}>
|
|
126
128
|
<DialogTrigger asChild>
|
|
127
|
-
<Button type="button">
|
|
129
|
+
<Button type="button">{t(keys.pagebuilder.new_page.trigger)}</Button>
|
|
128
130
|
</DialogTrigger>
|
|
129
131
|
<DialogContent>
|
|
130
132
|
<form
|
|
@@ -134,28 +136,26 @@ export function NewPageDialog({
|
|
|
134
136
|
}}
|
|
135
137
|
>
|
|
136
138
|
<DialogHeader>
|
|
137
|
-
<DialogTitle>
|
|
138
|
-
<DialogDescription>
|
|
139
|
-
A few fields, all changeable later except the language. Creating opens the editor.
|
|
140
|
-
</DialogDescription>
|
|
139
|
+
<DialogTitle>{t(keys.pagebuilder.new_page.title)}</DialogTitle>
|
|
140
|
+
<DialogDescription>{t(keys.pagebuilder.new_page.description)}</DialogDescription>
|
|
141
141
|
</DialogHeader>
|
|
142
142
|
|
|
143
143
|
<div className="grid gap-4 py-4">
|
|
144
144
|
<div className="grid gap-2">
|
|
145
|
-
<Label htmlFor={TITLE_ID}>
|
|
145
|
+
<Label htmlFor={TITLE_ID}>{t(keys.pagebuilder.new_page.title_label)}</Label>
|
|
146
146
|
<Input
|
|
147
147
|
id={TITLE_ID}
|
|
148
148
|
value={title}
|
|
149
149
|
autoFocus
|
|
150
150
|
disabled={pending}
|
|
151
|
-
placeholder=
|
|
151
|
+
placeholder={t(keys.pagebuilder.new_page.title_placeholder)}
|
|
152
152
|
onChange={(e) => setTitle(e.target.value)}
|
|
153
153
|
/>
|
|
154
154
|
</div>
|
|
155
155
|
|
|
156
156
|
{locales.length > 1 && (
|
|
157
157
|
<div className="grid gap-2">
|
|
158
|
-
<Label htmlFor={LOCALE_ID}>
|
|
158
|
+
<Label htmlFor={LOCALE_ID}>{t(keys.pagebuilder.new_page.language_label)}</Label>
|
|
159
159
|
<NativeSelect
|
|
160
160
|
id={LOCALE_ID}
|
|
161
161
|
value={locale}
|
|
@@ -176,14 +176,13 @@ export function NewPageDialog({
|
|
|
176
176
|
))}
|
|
177
177
|
</NativeSelect>
|
|
178
178
|
<p className="text-xs text-muted-foreground">
|
|
179
|
-
|
|
180
|
-
translation from the editor's Languages tab.
|
|
179
|
+
{t(keys.pagebuilder.new_page.language_help)}
|
|
181
180
|
</p>
|
|
182
181
|
</div>
|
|
183
182
|
)}
|
|
184
183
|
|
|
185
184
|
<div className="grid gap-2">
|
|
186
|
-
<Label htmlFor={SLUG_ID}>
|
|
185
|
+
<Label htmlFor={SLUG_ID}>{t(keys.pagebuilder.new_page.url_label)}</Label>
|
|
187
186
|
<div className="flex items-center gap-1">
|
|
188
187
|
<span className="text-sm text-muted-foreground">
|
|
189
188
|
{localePrefix(locale, defaultLocale)}
|
|
@@ -199,16 +198,16 @@ export function NewPageDialog({
|
|
|
199
198
|
</div>
|
|
200
199
|
|
|
201
200
|
<div className="grid gap-2">
|
|
202
|
-
<Label htmlFor={START_ID}>
|
|
201
|
+
<Label htmlFor={START_ID}>{t(keys.pagebuilder.new_page.start_label)}</Label>
|
|
203
202
|
<NativeSelect
|
|
204
203
|
id={START_ID}
|
|
205
204
|
value={startFrom}
|
|
206
205
|
disabled={pending}
|
|
207
206
|
onChange={(e) => setStartFrom(e.target.value)}
|
|
208
207
|
>
|
|
209
|
-
<option value={BLANK}>
|
|
208
|
+
<option value={BLANK}>{t(keys.pagebuilder.new_page.start_blank)}</option>
|
|
210
209
|
{templates.length > 0 && (
|
|
211
|
-
<NativeSelectOptGroup label=
|
|
210
|
+
<NativeSelectOptGroup label={t(keys.pagebuilder.new_page.start_templates)}>
|
|
212
211
|
{templates.map((t) => (
|
|
213
212
|
<option key={t.id} value={String(t.id)}>
|
|
214
213
|
{t.title}
|
|
@@ -217,7 +216,7 @@ export function NewPageDialog({
|
|
|
217
216
|
</NativeSelectOptGroup>
|
|
218
217
|
)}
|
|
219
218
|
{copyable.length > 0 && (
|
|
220
|
-
<NativeSelectOptGroup label=
|
|
219
|
+
<NativeSelectOptGroup label={t(keys.pagebuilder.new_page.start_copy)}>
|
|
221
220
|
{copyable.map((p) => (
|
|
222
221
|
<option key={p.id} value={String(p.id)}>
|
|
223
222
|
{p.title}
|
|
@@ -227,20 +226,19 @@ export function NewPageDialog({
|
|
|
227
226
|
)}
|
|
228
227
|
</NativeSelect>
|
|
229
228
|
<p className="text-xs text-muted-foreground">
|
|
230
|
-
|
|
231
|
-
developer.
|
|
229
|
+
{t(keys.pagebuilder.new_page.start_help)}
|
|
232
230
|
</p>
|
|
233
231
|
</div>
|
|
234
232
|
|
|
235
233
|
<div className="grid gap-2">
|
|
236
|
-
<Label htmlFor={PARENT_ID}>
|
|
234
|
+
<Label htmlFor={PARENT_ID}>{t(keys.pagebuilder.new_page.parent_label)}</Label>
|
|
237
235
|
<NativeSelect
|
|
238
236
|
id={PARENT_ID}
|
|
239
237
|
value={parentId}
|
|
240
238
|
disabled={pending}
|
|
241
239
|
onChange={(e) => setParentId(e.target.value)}
|
|
242
240
|
>
|
|
243
|
-
<option value="">
|
|
241
|
+
<option value="">{t(keys.pagebuilder.new_page.parent_none)}</option>
|
|
244
242
|
{pages
|
|
245
243
|
.filter((p) => p.locale === locale)
|
|
246
244
|
.map((p) => (
|
|
@@ -250,8 +248,7 @@ export function NewPageDialog({
|
|
|
250
248
|
))}
|
|
251
249
|
</NativeSelect>
|
|
252
250
|
<p className="text-xs text-muted-foreground">
|
|
253
|
-
|
|
254
|
-
breadcrumb that crosses languages sends a reader out of theirs.
|
|
251
|
+
{t(keys.pagebuilder.new_page.parent_help)}
|
|
255
252
|
</p>
|
|
256
253
|
</div>
|
|
257
254
|
|
|
@@ -260,10 +257,12 @@ export function NewPageDialog({
|
|
|
260
257
|
|
|
261
258
|
<DialogFooter>
|
|
262
259
|
<Button type="button" variant="outline" disabled={pending} onClick={() => reset(false)}>
|
|
263
|
-
|
|
260
|
+
{t(keys.pagebuilder.new_page.cancel)}
|
|
264
261
|
</Button>
|
|
265
262
|
<Button type="submit" disabled={pending || !title.trim() || !slug}>
|
|
266
|
-
{pending
|
|
263
|
+
{pending
|
|
264
|
+
? t(keys.pagebuilder.new_page.creating)
|
|
265
|
+
: t(keys.pagebuilder.new_page.create)}
|
|
267
266
|
</Button>
|
|
268
267
|
</DialogFooter>
|
|
269
268
|
</form>
|
|
@@ -13,6 +13,7 @@ import { Textarea } from '@simple-module-py/ui/components/ui/textarea';
|
|
|
13
13
|
import { type ReactNode, useId, useState } from 'react';
|
|
14
14
|
|
|
15
15
|
import { usePendingDialog } from '../hooks/usePendingDialog';
|
|
16
|
+
import { keys, useT } from '../utils/i18n';
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* Collect a note — a rejection reason, a publish message — before running an
|
|
@@ -47,13 +48,15 @@ export function NoteDialog({
|
|
|
47
48
|
/** Rejecting keeps the dialog open and surfaces the message. */
|
|
48
49
|
onSubmit: (note: string) => Promise<unknown>;
|
|
49
50
|
}) {
|
|
51
|
+
const { t } = useT();
|
|
50
52
|
const fieldId = useId();
|
|
51
53
|
const [note, setNote] = useState('');
|
|
52
54
|
// The open/pending/error lifecycle is shared with ConfirmDialog — see the
|
|
53
55
|
// hook. The note clears on every close path so a reopened dialog starts
|
|
54
56
|
// blank rather than carrying a half-typed message.
|
|
55
|
-
const { open, pending, error, change, run } = usePendingDialog(
|
|
56
|
-
|
|
57
|
+
const { open, pending, error, change, run } = usePendingDialog(
|
|
58
|
+
t(keys.pagebuilder.confirm.failed, { action: submitLabel }),
|
|
59
|
+
() => setNote(''),
|
|
57
60
|
);
|
|
58
61
|
|
|
59
62
|
const submit = () => {
|
|
@@ -79,7 +82,11 @@ export function NoteDialog({
|
|
|
79
82
|
<div className="grid gap-2 py-4">
|
|
80
83
|
<Label htmlFor={fieldId}>
|
|
81
84
|
{label}
|
|
82
|
-
{!required &&
|
|
85
|
+
{!required && (
|
|
86
|
+
<span className="ml-1 text-muted-foreground">
|
|
87
|
+
{t(keys.pagebuilder.confirm.optional)}
|
|
88
|
+
</span>
|
|
89
|
+
)}
|
|
83
90
|
</Label>
|
|
84
91
|
<Textarea
|
|
85
92
|
id={fieldId}
|
|
@@ -99,14 +106,14 @@ export function NoteDialog({
|
|
|
99
106
|
disabled={pending}
|
|
100
107
|
onClick={() => change(false)}
|
|
101
108
|
>
|
|
102
|
-
|
|
109
|
+
{t(keys.pagebuilder.confirm.cancel)}
|
|
103
110
|
</Button>
|
|
104
111
|
<Button
|
|
105
112
|
type="submit"
|
|
106
113
|
variant={destructive ? 'destructive' : 'default'}
|
|
107
114
|
disabled={pending || (required && !note.trim())}
|
|
108
115
|
>
|
|
109
|
-
{pending ?
|
|
116
|
+
{pending ? t(keys.pagebuilder.confirm.working) : submitLabel}
|
|
110
117
|
</Button>
|
|
111
118
|
</DialogFooter>
|
|
112
119
|
</form>
|