@webiny/app-website-builder 6.6.0-alpha.0 → 6.6.0-alpha.1
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/BaseEditor/commandHandlers/CloneElement.d.ts +1 -0
- package/BaseEditor/commandHandlers/CloneElement.js +17 -0
- package/BaseEditor/commandHandlers/CloneElement.js.map +1 -0
- package/BaseEditor/commandHandlers/index.js +2 -1
- package/BaseEditor/commandHandlers/index.js.map +1 -1
- package/BaseEditor/commands.d.ts +3 -0
- package/BaseEditor/commands.js +2 -0
- package/BaseEditor/commands.js.map +1 -1
- package/BaseEditor/defaultConfig/Content/AddressBar/usePreviewLink.js +4 -1
- package/BaseEditor/defaultConfig/Content/AddressBar/usePreviewLink.js.map +1 -1
- package/BaseEditor/defaultConfig/Content/Preview/DropZoneManager.js.map +1 -1
- package/BaseEditor/defaultConfig/Content/Preview/Iframe.d.ts +2 -2
- package/BaseEditor/defaultConfig/Content/Preview/Overlays/ElementOverlays.d.ts +2 -2
- package/BaseEditor/defaultConfig/DefaultEditorConfig.js +9 -0
- package/BaseEditor/defaultConfig/DefaultEditorConfig.js.map +1 -1
- package/BaseEditor/defaultConfig/DocumentStateEditor/DocumentStateEditor.d.ts +2 -2
- package/BaseEditor/defaultConfig/ElementInputRenderers.js +4 -0
- package/BaseEditor/defaultConfig/ElementInputRenderers.js.map +1 -1
- package/BaseEditor/defaultConfig/Sidebar/ElementActions/CloneElementAction.d.ts +2 -0
- package/BaseEditor/defaultConfig/Sidebar/ElementActions/CloneElementAction.js +25 -0
- package/BaseEditor/defaultConfig/Sidebar/ElementActions/CloneElementAction.js.map +1 -0
- package/BaseEditor/defaultConfig/Sidebar/ElementActions/DeleteElementAction.d.ts +2 -0
- package/BaseEditor/defaultConfig/Sidebar/ElementActions/DeleteElementAction.js +26 -0
- package/BaseEditor/defaultConfig/Sidebar/ElementActions/DeleteElementAction.js.map +1 -0
- package/BaseEditor/defaultConfig/Sidebar/ElementPreview.js +12 -2
- package/BaseEditor/defaultConfig/Sidebar/ElementPreview.js.map +1 -1
- package/BaseEditor/defaultConfig/Sidebar/ElementSettings/ElementInputs.js +1 -6
- package/BaseEditor/defaultConfig/Sidebar/ElementSettings/ElementInputs.js.map +1 -1
- package/BaseEditor/defaultConfig/Sidebar/ElementSettings/ElementSettings.js +11 -2
- package/BaseEditor/defaultConfig/Sidebar/ElementSettings/ElementSettings.js.map +1 -1
- package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Background/BackgroundColor.d.ts +6 -2
- package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Background/BackgroundImage.d.ts +6 -2
- package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Background/BackgroundPosition.d.ts +6 -2
- package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Background/BackgroundScaling.d.ts +6 -2
- package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Border/BorderColor.d.ts +2 -2
- package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Border/BorderRadius.d.ts +2 -2
- package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Border/BorderStyle.d.ts +2 -2
- package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Border/BorderWidth.d.ts +2 -2
- package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Layout/Alignment.d.ts +6 -2
- package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Layout/LengthWithUnitInput.d.ts +2 -2
- package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/MarginPadding/Margin.d.ts +2 -2
- package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/MarginPadding/Padding.d.ts +2 -2
- package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Visibility/Visibility.d.ts +2 -2
- package/BaseEditor/defaultConfig/Sidebar/StyleSettings/StyleProperties.js +7 -7
- package/BaseEditor/defaultConfig/Sidebar/StyleSettings/StyleProperties.js.map +1 -1
- package/BaseEditor/defaultConfig/Toolbar/Navigator/Navigator.d.ts +2 -2
- package/DocumentEditor/DocumentEditor.d.ts +14 -5
- package/DocumentEditor/DocumentEditor.js +10 -6
- package/DocumentEditor/DocumentEditor.js.map +1 -1
- package/DocumentEditor/StateInspector.d.ts +4 -2
- package/Extension.js +7 -1
- package/Extension.js.map +1 -1
- package/ecommerce/components/ResourcePage.d.ts +6 -2
- package/ecommerce/components/ResourcesList.d.ts +4 -4
- package/ecommerce/components/ResourcesPicker.d.ts +9 -4
- package/editorSdk/CommandBus.js.map +1 -1
- package/editorSdk/utils/$cloneElement.d.ts +2 -0
- package/editorSdk/utils/$cloneElement.js +112 -0
- package/editorSdk/utils/$cloneElement.js.map +1 -0
- package/editorSdk/utils/index.d.ts +1 -0
- package/editorSdk/utils/index.js +1 -0
- package/features/experiments/ExperimentsGateway.d.ts +30 -0
- package/features/experiments/ExperimentsGateway.js +326 -0
- package/features/experiments/ExperimentsGateway.js.map +1 -0
- package/features/experiments/abstractions.d.ts +25 -0
- package/features/experiments/abstractions.js +5 -0
- package/features/experiments/abstractions.js.map +1 -0
- package/features/experiments/feature.d.ts +3 -0
- package/features/experiments/feature.js +17 -0
- package/features/experiments/feature.js.map +1 -0
- package/features/experiments/index.d.ts +3 -0
- package/features/experiments/index.js +2 -0
- package/features/experiments/types.d.ts +61 -0
- package/features/experiments/types.js +0 -0
- package/inputRenderers/ColorPickerInput.d.ts +3 -0
- package/inputRenderers/ColorPickerInput.js +29 -0
- package/inputRenderers/ColorPickerInput.js.map +1 -0
- package/inputRenderers/FileInput.js +93 -8
- package/inputRenderers/FileInput.js.map +1 -1
- package/inputRenderers/LexicalInput/LexicalEditor.js +15 -8
- package/inputRenderers/LexicalInput/LexicalEditor.js.map +1 -1
- package/inputRenderers/LexicalInput/TypographyDropDown.js +3 -2
- package/inputRenderers/LexicalInput/TypographyDropDown.js.map +1 -1
- package/inputRenderers/LexicalInput/wbStaticToolbar.css +72 -103
- package/modules/AbTesting.d.ts +2 -0
- package/modules/AbTesting.js +19 -0
- package/modules/AbTesting.js.map +1 -0
- package/package.json +28 -28
- package/presentation/components/LanguageCodeTag.js +5 -4
- package/presentation/components/LanguageCodeTag.js.map +1 -1
- package/presentation/experiments/ExperimentForm/ExperimentFormPresenter.d.ts +30 -0
- package/presentation/experiments/ExperimentForm/ExperimentFormPresenter.js +202 -0
- package/presentation/experiments/ExperimentForm/ExperimentFormPresenter.js.map +1 -0
- package/presentation/experiments/ExperimentForm/abstractions/ExperimentFormPresenter.d.ts +65 -0
- package/presentation/experiments/ExperimentForm/abstractions/ExperimentFormPresenter.js +5 -0
- package/presentation/experiments/ExperimentForm/abstractions/ExperimentFormPresenter.js.map +1 -0
- package/presentation/experiments/ExperimentForm/components/ExperimentFormView.d.ts +12 -0
- package/presentation/experiments/ExperimentForm/components/ExperimentFormView.js +149 -0
- package/presentation/experiments/ExperimentForm/components/ExperimentFormView.js.map +1 -0
- package/presentation/experiments/ExperimentForm/components/VariantSplitRow.d.ts +17 -0
- package/presentation/experiments/ExperimentForm/components/VariantSplitRow.js +122 -0
- package/presentation/experiments/ExperimentForm/components/VariantSplitRow.js.map +1 -0
- package/presentation/experiments/ExperimentForm/feature.d.ts +3 -0
- package/presentation/experiments/ExperimentForm/feature.js +17 -0
- package/presentation/experiments/ExperimentForm/feature.js.map +1 -0
- package/presentation/experiments/ExperimentForm/index.d.ts +3 -0
- package/presentation/experiments/ExperimentForm/index.js +3 -0
- package/presentation/experiments/ExperimentsEditor/ExperimentsEditorDataSource.d.ts +18 -0
- package/presentation/experiments/ExperimentsEditor/ExperimentsEditorDataSource.js +25 -0
- package/presentation/experiments/ExperimentsEditor/ExperimentsEditorDataSource.js.map +1 -0
- package/presentation/experiments/ExperimentsEditor/ExperimentsEditorPresenter.d.ts +67 -0
- package/presentation/experiments/ExperimentsEditor/ExperimentsEditorPresenter.js +224 -0
- package/presentation/experiments/ExperimentsEditor/ExperimentsEditorPresenter.js.map +1 -0
- package/presentation/experiments/ExperimentsEditor/abstractions/ExperimentsEditorDataSource.d.ts +10 -0
- package/presentation/experiments/ExperimentsEditor/abstractions/ExperimentsEditorDataSource.js +5 -0
- package/presentation/experiments/ExperimentsEditor/abstractions/ExperimentsEditorDataSource.js.map +1 -0
- package/presentation/experiments/ExperimentsEditor/abstractions/ExperimentsEditorPresenter.d.ts +58 -0
- package/presentation/experiments/ExperimentsEditor/abstractions/ExperimentsEditorPresenter.js +5 -0
- package/presentation/experiments/ExperimentsEditor/abstractions/ExperimentsEditorPresenter.js.map +1 -0
- package/presentation/experiments/ExperimentsEditor/components/ExperimentIndicator.d.ts +15 -0
- package/presentation/experiments/ExperimentsEditor/components/ExperimentIndicator.js +110 -0
- package/presentation/experiments/ExperimentsEditor/components/ExperimentIndicator.js.map +1 -0
- package/presentation/experiments/ExperimentsEditor/components/ExperimentPreviewToolbar.d.ts +9 -0
- package/presentation/experiments/ExperimentsEditor/components/ExperimentPreviewToolbar.js +178 -0
- package/presentation/experiments/ExperimentsEditor/components/ExperimentPreviewToolbar.js.map +1 -0
- package/presentation/experiments/ExperimentsEditor/components/ExperimentsButton.d.ts +11 -0
- package/presentation/experiments/ExperimentsEditor/components/ExperimentsButton.js +51 -0
- package/presentation/experiments/ExperimentsEditor/components/ExperimentsButton.js.map +1 -0
- package/presentation/experiments/ExperimentsEditor/components/ExperimentsSwitcher.d.ts +14 -0
- package/presentation/experiments/ExperimentsEditor/components/ExperimentsSwitcher.js +147 -0
- package/presentation/experiments/ExperimentsEditor/components/ExperimentsSwitcher.js.map +1 -0
- package/presentation/experiments/ExperimentsEditor/feature.d.ts +3 -0
- package/presentation/experiments/ExperimentsEditor/feature.js +21 -0
- package/presentation/experiments/ExperimentsEditor/feature.js.map +1 -0
- package/presentation/experiments/ExperimentsEditor/index.d.ts +4 -0
- package/presentation/experiments/ExperimentsEditor/index.js +3 -0
- package/presentation/experiments/ExperimentsManager/ExperimentsManagerPresenter.d.ts +39 -0
- package/presentation/experiments/ExperimentsManager/ExperimentsManagerPresenter.js +219 -0
- package/presentation/experiments/ExperimentsManager/ExperimentsManagerPresenter.js.map +1 -0
- package/presentation/experiments/ExperimentsManager/abstractions/ExperimentsManagerPresenter.d.ts +52 -0
- package/presentation/experiments/ExperimentsManager/abstractions/ExperimentsManagerPresenter.js +5 -0
- package/presentation/experiments/ExperimentsManager/abstractions/ExperimentsManagerPresenter.js.map +1 -0
- package/presentation/experiments/ExperimentsManager/components/ExperimentCard.d.ts +10 -0
- package/presentation/experiments/ExperimentsManager/components/ExperimentCard.js +296 -0
- package/presentation/experiments/ExperimentsManager/components/ExperimentCard.js.map +1 -0
- package/presentation/experiments/ExperimentsManager/components/ExperimentsDrawerView.d.ts +2 -0
- package/presentation/experiments/ExperimentsManager/components/ExperimentsDrawerView.js +92 -0
- package/presentation/experiments/ExperimentsManager/components/ExperimentsDrawerView.js.map +1 -0
- package/presentation/experiments/ExperimentsManager/components/ExperimentsEmptyState.d.ts +6 -0
- package/presentation/experiments/ExperimentsManager/components/ExperimentsEmptyState.js +103 -0
- package/presentation/experiments/ExperimentsManager/components/ExperimentsEmptyState.js.map +1 -0
- package/presentation/experiments/ExperimentsManager/components/ExperimentsListView.d.ts +9 -0
- package/presentation/experiments/ExperimentsManager/components/ExperimentsListView.js +58 -0
- package/presentation/experiments/ExperimentsManager/components/ExperimentsListView.js.map +1 -0
- package/presentation/experiments/ExperimentsManager/feature.d.ts +3 -0
- package/presentation/experiments/ExperimentsManager/feature.js +17 -0
- package/presentation/experiments/ExperimentsManager/feature.js.map +1 -0
- package/presentation/experiments/ExperimentsManager/index.d.ts +4 -0
- package/presentation/experiments/ExperimentsManager/index.js +3 -0
- package/presentation/experiments/VariantPageEditorConfig.d.ts +7 -0
- package/presentation/experiments/VariantPageEditorConfig.js +26 -0
- package/presentation/experiments/VariantPageEditorConfig.js.map +1 -0
- package/presentation/experiments/config/ExperimentsEditorConfig.d.ts +8 -0
- package/presentation/experiments/config/ExperimentsEditorConfig.js +21 -0
- package/presentation/experiments/config/ExperimentsEditorConfig.js.map +1 -0
- package/presentation/experiments/config/VariantAutoSave.d.ts +5 -0
- package/presentation/experiments/config/VariantAutoSave.js +41 -0
- package/presentation/experiments/config/VariantAutoSave.js.map +1 -0
- package/presentation/experiments/shared/variantColors.d.ts +11 -0
- package/presentation/experiments/shared/variantColors.js +13 -0
- package/presentation/experiments/shared/variantColors.js.map +1 -0
- package/presentation/experiments/shared/variantDocument.d.ts +16 -0
- package/presentation/experiments/shared/variantDocument.js +31 -0
- package/presentation/experiments/shared/variantDocument.js.map +1 -0
- package/presentation/navigation/Extension.js +9 -5
- package/presentation/navigation/Extension.js.map +1 -1
- package/presentation/navigation/NextjsConfig/NextjsConfigDialog.d.ts +2 -2
- package/presentation/navigation/StarterKitConfigDialog.js +1 -1
- package/presentation/navigation/StarterKitConfigDialog.js.map +1 -1
- package/presentation/pages/CreatePage/CreatePageDialog.d.ts +2 -2
- package/presentation/pages/CreatePage/CreatePagePresenter.js +1 -1
- package/presentation/pages/CreatePage/CreatePagePresenter.js.map +1 -1
- package/presentation/pages/CreatePage/WithLanguageSelector.js +3 -3
- package/presentation/pages/CreatePage/WithLanguageSelector.js.map +1 -1
- package/presentation/pages/CreatePage/feature.js +3 -3
- package/presentation/pages/CreatePage/feature.js.map +1 -1
- package/presentation/pages/PageEditor/PageEditor.experiments.d.ts +2 -0
- package/presentation/pages/PageEditor/PageEditor.experiments.js +54 -0
- package/presentation/pages/PageEditor/PageEditor.experiments.js.map +1 -0
- package/presentation/pages/PageEditor/PageEditorSurface.d.ts +15 -0
- package/presentation/pages/PageEditor/PageEditorSurface.js +63 -0
- package/presentation/pages/PageEditor/PageEditorSurface.js.map +1 -0
- package/presentation/pages/PageEditor/TopBar/PageSettingsDrawer.d.ts +2 -2
- package/presentation/pages/PageEditor/pageDocument.d.ts +4 -0
- package/presentation/pages/PageEditor/pageDocument.js +15 -0
- package/presentation/pages/PageEditor/pageDocument.js.map +1 -0
- package/presentation/pages/PageList/components/BulkActions/BulkActionDelete.d.ts +2 -2
- package/presentation/pages/PageList/components/BulkActions/BulkActionDuplicate.d.ts +2 -2
- package/presentation/pages/PageList/components/BulkActions/BulkActionMovePage.d.ts +2 -2
- package/presentation/pages/PageList/components/BulkActions/BulkActionPublish.d.ts +2 -2
- package/presentation/pages/PageList/components/BulkActions/BulkActionUnpublish.d.ts +2 -2
- package/presentation/pages/PageList/components/DocumentList.d.ts +2 -2
- package/presentation/pages/PageList/components/PagesList.js +2 -1
- package/presentation/pages/PageList/components/PagesList.js.map +1 -1
- package/presentation/pages/PageList/components/Table/Table.d.ts +2 -2
- package/presentation/pages/PageList/components/WbPagesBreadcrumbs.d.ts +9 -0
- package/presentation/pages/PageList/components/WbPagesBreadcrumbs.js +40 -0
- package/presentation/pages/PageList/components/WbPagesBreadcrumbs.js.map +1 -0
- package/presentation/pages/TranslatePage/TranslatePageConfig.d.ts +1 -1
- package/presentation/pages/TranslatePage/TranslatePageConfig.js +6 -2
- package/presentation/pages/TranslatePage/TranslatePageConfig.js.map +1 -1
- package/presentation/pages/TranslatePage/TranslatePageDialog.js +22 -10
- package/presentation/pages/TranslatePage/TranslatePageDialog.js.map +1 -1
- package/presentation/pages/TranslatePage/translatePageSchema.d.ts +1 -1
- package/presentation/pages/TranslatePage/translatePageSchema.js +1 -1
- package/presentation/pages/TranslatePage/translatePageSchema.js.map +1 -1
- package/presentation/pages/TrashBin/WbTrashBin.d.ts +2 -2
- package/presentation/redirects/RedirectList/components/BulkActionDelete.d.ts +2 -2
- package/presentation/redirects/RedirectList/components/BulkActionMove.d.ts +2 -2
- package/presentation/redirects/RedirectList/components/CreateRedirectDialog.d.ts +2 -2
- package/presentation/redirects/RedirectList/components/DocumentList.d.ts +2 -2
- package/presentation/redirects/RedirectList/components/EditRedirectDialog.d.ts +2 -2
- package/presentation/redirects/RedirectList/components/Table/Table.d.ts +2 -2
- package/shared/fileManagerItemToValue.d.ts +8 -9
- package/shared/fileManagerItemToValue.js +22 -7
- package/shared/fileManagerItemToValue.js.map +1 -1
- package/inputRenderers/LexicalInput/icons/list-ol.js +0 -20
- package/inputRenderers/LexicalInput/icons/list-ol.js.map +0 -1
- package/inputRenderers/LexicalInput/icons/list-ol.svg +0 -1
- package/inputRenderers/LexicalInput/icons/list-ul.js +0 -18
- package/inputRenderers/LexicalInput/icons/list-ul.js.map +0 -1
- package/inputRenderers/LexicalInput/icons/list-ul.svg +0 -1
- package/static/svg/list-ol.d64946f3.svg +0 -1
- package/static/svg/list-ul.1d54da3f.svg +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webiny/app-website-builder",
|
|
3
|
-
"version": "6.6.0-alpha.
|
|
3
|
+
"version": "6.6.0-alpha.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./index.js",
|
|
@@ -16,38 +16,38 @@
|
|
|
16
16
|
"@emotion/css": "11.13.5",
|
|
17
17
|
"@emotion/react": "11.14.0",
|
|
18
18
|
"@emotion/styled": "11.14.1",
|
|
19
|
-
"@lexical/utils": "0.
|
|
19
|
+
"@lexical/utils": "0.49.0",
|
|
20
20
|
"@monaco-editor/react": "4.7.0",
|
|
21
21
|
"@types/react": "18.3.31",
|
|
22
|
-
"@webiny/admin-ui": "6.6.0-alpha.
|
|
23
|
-
"@webiny/app": "6.6.0-alpha.
|
|
24
|
-
"@webiny/app-aco": "6.6.0-alpha.
|
|
25
|
-
"@webiny/app-admin": "6.6.0-alpha.
|
|
26
|
-
"@webiny/app-headless-cms-common": "6.6.0-alpha.
|
|
27
|
-
"@webiny/app-utils": "6.6.0-alpha.
|
|
28
|
-
"@webiny/di": "1.0
|
|
29
|
-
"@webiny/feature": "6.6.0-alpha.
|
|
30
|
-
"@webiny/form": "6.6.0-alpha.
|
|
31
|
-
"@webiny/icons": "6.6.0-alpha.
|
|
32
|
-
"@webiny/languages": "6.6.0-alpha.
|
|
33
|
-
"@webiny/lexical-converter": "6.6.0-alpha.
|
|
34
|
-
"@webiny/lexical-editor": "6.6.0-alpha.
|
|
35
|
-
"@webiny/lexical-nodes": "6.6.0-alpha.
|
|
36
|
-
"@webiny/lexical-theme": "6.6.0-alpha.
|
|
37
|
-
"@webiny/react-composition": "6.6.0-alpha.
|
|
38
|
-
"@webiny/react-properties": "6.6.0-alpha.
|
|
39
|
-
"@webiny/utils": "6.6.0-alpha.
|
|
40
|
-
"@webiny/validation": "6.6.0-alpha.
|
|
41
|
-
"@webiny/website-builder-sdk": "6.6.0-alpha.
|
|
22
|
+
"@webiny/admin-ui": "6.6.0-alpha.1",
|
|
23
|
+
"@webiny/app": "6.6.0-alpha.1",
|
|
24
|
+
"@webiny/app-aco": "6.6.0-alpha.1",
|
|
25
|
+
"@webiny/app-admin": "6.6.0-alpha.1",
|
|
26
|
+
"@webiny/app-headless-cms-common": "6.6.0-alpha.1",
|
|
27
|
+
"@webiny/app-utils": "6.6.0-alpha.1",
|
|
28
|
+
"@webiny/di": "1.1.0",
|
|
29
|
+
"@webiny/feature": "6.6.0-alpha.1",
|
|
30
|
+
"@webiny/form": "6.6.0-alpha.1",
|
|
31
|
+
"@webiny/icons": "6.6.0-alpha.1",
|
|
32
|
+
"@webiny/languages": "6.6.0-alpha.1",
|
|
33
|
+
"@webiny/lexical-converter": "6.6.0-alpha.1",
|
|
34
|
+
"@webiny/lexical-editor": "6.6.0-alpha.1",
|
|
35
|
+
"@webiny/lexical-nodes": "6.6.0-alpha.1",
|
|
36
|
+
"@webiny/lexical-theme": "6.6.0-alpha.1",
|
|
37
|
+
"@webiny/react-composition": "6.6.0-alpha.1",
|
|
38
|
+
"@webiny/react-properties": "6.6.0-alpha.1",
|
|
39
|
+
"@webiny/utils": "6.6.0-alpha.1",
|
|
40
|
+
"@webiny/validation": "6.6.0-alpha.1",
|
|
41
|
+
"@webiny/website-builder-sdk": "6.6.0-alpha.1",
|
|
42
42
|
"classnames": "2.5.1",
|
|
43
43
|
"deep-equal": "2.2.3",
|
|
44
44
|
"graphql": "16.14.2",
|
|
45
45
|
"is-hotkey": "0.2.0",
|
|
46
46
|
"lodash": "4.18.1",
|
|
47
|
-
"markdown-to-jsx": "9.
|
|
47
|
+
"markdown-to-jsx": "9.10.2",
|
|
48
48
|
"matcher": "6.0.0",
|
|
49
|
-
"mobx": "
|
|
50
|
-
"mobx-react-lite": "
|
|
49
|
+
"mobx": "7.0.3",
|
|
50
|
+
"mobx-react-lite": "5.0.3",
|
|
51
51
|
"pluralize": "8.0.0",
|
|
52
52
|
"radix-ui": "1.6.7",
|
|
53
53
|
"react": "18.3.1",
|
|
@@ -60,11 +60,11 @@
|
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@types/deep-equal": "1.0.4",
|
|
62
62
|
"@types/is-hotkey": "0.1.10",
|
|
63
|
-
"@webiny/build-tools": "6.6.0-alpha.
|
|
64
|
-
"execa": "10.0.
|
|
63
|
+
"@webiny/build-tools": "6.6.0-alpha.1",
|
|
64
|
+
"execa": "10.0.1",
|
|
65
65
|
"rimraf": "6.1.3",
|
|
66
66
|
"typescript": "7.0.2",
|
|
67
|
-
"vitest": "4.1.
|
|
67
|
+
"vitest": "4.1.11"
|
|
68
68
|
},
|
|
69
69
|
"publishConfig": {
|
|
70
70
|
"access": "public"
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import react from "react";
|
|
2
2
|
import { Tag } from "@webiny/admin-ui";
|
|
3
|
-
import {
|
|
3
|
+
import { useFeatureFlags } from "@webiny/app-admin";
|
|
4
4
|
const LanguageCodeTag = ({ code, className })=>{
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
const featureFlags = useFeatureFlags();
|
|
6
|
+
if (!code || !featureFlags.isEnabled("multiTenancy")) return null;
|
|
7
|
+
return /*#__PURE__*/ react.createElement("div", {
|
|
7
8
|
className: "flex justify-center items-center"
|
|
8
9
|
}, /*#__PURE__*/ react.createElement(Tag, {
|
|
9
10
|
variant: "neutral-muted",
|
|
10
11
|
content: code,
|
|
11
12
|
className: className
|
|
12
|
-
}))
|
|
13
|
+
}));
|
|
13
14
|
};
|
|
14
15
|
export { LanguageCodeTag };
|
|
15
16
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presentation/components/LanguageCodeTag.js","sources":["../../../src/presentation/components/LanguageCodeTag.tsx"],"sourcesContent":["import React from \"react\";\nimport { Tag } from \"@webiny/admin-ui\";\nimport {
|
|
1
|
+
{"version":3,"file":"presentation/components/LanguageCodeTag.js","sources":["../../../src/presentation/components/LanguageCodeTag.tsx"],"sourcesContent":["import React from \"react\";\nimport { Tag } from \"@webiny/admin-ui\";\nimport { useFeatureFlags } from \"@webiny/app-admin\";\n\nexport interface LanguageCodeProps {\n code: string | undefined;\n className?: string;\n}\n\nexport const LanguageCodeTag = ({ code, className }: LanguageCodeProps) => {\n const featureFlags = useFeatureFlags();\n\n if (!code || !featureFlags.isEnabled(\"multiTenancy\")) {\n return null;\n }\n\n return (\n <div className={\"flex justify-center items-center\"}>\n <Tag variant={\"neutral-muted\"} content={code} className={className} />\n </div>\n );\n};\n"],"names":["LanguageCodeTag","code","className","featureFlags","useFeatureFlags","Tag"],"mappings":";;;AASO,MAAMA,kBAAkB,CAAC,EAAEC,IAAI,EAAEC,SAAS,EAAqB;IAClE,MAAMC,eAAeC;IAErB,IAAI,CAACH,QAAQ,CAACE,aAAa,SAAS,CAAC,iBACjC,OAAO;IAGX,OAAO,WAAP,GACI,oBAAC;QAAI,WAAW;qBACZ,oBAACE,KAAGA;QAAC,SAAS;QAAiB,SAASJ;QAAM,WAAWC;;AAGrE"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type ExperimentFormInitial, type IExperimentFormPresenter, type IExperimentFormViewModel, type NewExperimentPayload } from "./abstractions/ExperimentFormPresenter.js";
|
|
2
|
+
declare class ExperimentFormPresenterImpl implements IExperimentFormPresenter {
|
|
3
|
+
private _name;
|
|
4
|
+
private _key;
|
|
5
|
+
private _keyEdited;
|
|
6
|
+
private _buckets;
|
|
7
|
+
private _submitLabel;
|
|
8
|
+
private _allowStructureChange;
|
|
9
|
+
private _onSubmit;
|
|
10
|
+
constructor();
|
|
11
|
+
get vm(): IExperimentFormViewModel;
|
|
12
|
+
init(initial: ExperimentFormInitial | undefined, options: {
|
|
13
|
+
submitLabel: string;
|
|
14
|
+
allowStructureChange: boolean;
|
|
15
|
+
onSubmit: (payload: NewExperimentPayload) => void;
|
|
16
|
+
}): void;
|
|
17
|
+
setName(value: string): void;
|
|
18
|
+
setKey(value: string): void;
|
|
19
|
+
addVariant(): void;
|
|
20
|
+
removeVariant(index: number): void;
|
|
21
|
+
changeWeight(index: number, value: number): void;
|
|
22
|
+
changeName(index: number, value: string): void;
|
|
23
|
+
changeKey(index: number, value: string): void;
|
|
24
|
+
changeDescription(index: number, value: string): void;
|
|
25
|
+
submit(): void;
|
|
26
|
+
}
|
|
27
|
+
export declare const ExperimentFormPresenter: typeof ExperimentFormPresenterImpl & {
|
|
28
|
+
__abstraction: import("@webiny/di").Abstraction<IExperimentFormPresenter>;
|
|
29
|
+
};
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { computed, makeAutoObservable } from "mobx";
|
|
2
|
+
import slugify from "slugify";
|
|
3
|
+
import { ExperimentFormPresenter } from "./abstractions/ExperimentFormPresenter.js";
|
|
4
|
+
const toKey = (value)=>slugify(value, {
|
|
5
|
+
lower: true,
|
|
6
|
+
strict: true
|
|
7
|
+
});
|
|
8
|
+
const defaultBuckets = ()=>[
|
|
9
|
+
{
|
|
10
|
+
id: "control",
|
|
11
|
+
isControl: true,
|
|
12
|
+
name: "Control",
|
|
13
|
+
key: "control",
|
|
14
|
+
keyEdited: false,
|
|
15
|
+
description: "",
|
|
16
|
+
weight: 50
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
id: crypto.randomUUID(),
|
|
20
|
+
isControl: false,
|
|
21
|
+
name: "Variant B",
|
|
22
|
+
key: "variant-b",
|
|
23
|
+
keyEdited: false,
|
|
24
|
+
description: "",
|
|
25
|
+
weight: 50
|
|
26
|
+
}
|
|
27
|
+
];
|
|
28
|
+
const evenSplit = (buckets)=>{
|
|
29
|
+
const n = buckets.length;
|
|
30
|
+
const each = Math.floor(100 / n);
|
|
31
|
+
const next = buckets.map((b)=>({
|
|
32
|
+
...b,
|
|
33
|
+
weight: each
|
|
34
|
+
}));
|
|
35
|
+
let used = each * n;
|
|
36
|
+
let i = 0;
|
|
37
|
+
while(used < 100){
|
|
38
|
+
next[i % n].weight += 1;
|
|
39
|
+
used++;
|
|
40
|
+
i++;
|
|
41
|
+
}
|
|
42
|
+
return next;
|
|
43
|
+
};
|
|
44
|
+
const rebalance = (buckets, index, rawValue)=>{
|
|
45
|
+
const value = Math.max(0, Math.min(100, Math.round(rawValue)));
|
|
46
|
+
const next = buckets.map((b)=>({
|
|
47
|
+
...b
|
|
48
|
+
}));
|
|
49
|
+
next[index].weight = value;
|
|
50
|
+
const others = next.map((b, i)=>({
|
|
51
|
+
b,
|
|
52
|
+
i
|
|
53
|
+
})).filter((x)=>x.i !== index);
|
|
54
|
+
if (0 === others.length) {
|
|
55
|
+
next[index].weight = 100;
|
|
56
|
+
return next;
|
|
57
|
+
}
|
|
58
|
+
const remaining = 100 - value;
|
|
59
|
+
const sumOthers = others.reduce((sum, x)=>sum + x.b.weight, 0);
|
|
60
|
+
if (sumOthers <= 0) {
|
|
61
|
+
const each = Math.floor(remaining / others.length);
|
|
62
|
+
others.forEach((x)=>next[x.i].weight = each);
|
|
63
|
+
let used = each * others.length;
|
|
64
|
+
let k = 0;
|
|
65
|
+
while(used < remaining){
|
|
66
|
+
next[others[k % others.length].i].weight += 1;
|
|
67
|
+
used++;
|
|
68
|
+
k++;
|
|
69
|
+
}
|
|
70
|
+
} else {
|
|
71
|
+
let allocated = 0;
|
|
72
|
+
others.forEach((x)=>{
|
|
73
|
+
const w = Math.max(0, Math.round(x.b.weight / sumOthers * remaining));
|
|
74
|
+
next[x.i].weight = w;
|
|
75
|
+
allocated += w;
|
|
76
|
+
});
|
|
77
|
+
const drift = remaining - allocated;
|
|
78
|
+
if (0 !== drift) {
|
|
79
|
+
const largest = others.reduce((a, b)=>next[a.i].weight >= next[b.i].weight ? a : b);
|
|
80
|
+
next[largest.i].weight = Math.max(0, next[largest.i].weight + drift);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return next;
|
|
84
|
+
};
|
|
85
|
+
class ExperimentFormPresenterImpl {
|
|
86
|
+
constructor(){
|
|
87
|
+
this._name = "";
|
|
88
|
+
this._key = "";
|
|
89
|
+
this._keyEdited = false;
|
|
90
|
+
this._buckets = defaultBuckets();
|
|
91
|
+
this._submitLabel = "Create experiment";
|
|
92
|
+
this._allowStructureChange = true;
|
|
93
|
+
this._onSubmit = ()=>{};
|
|
94
|
+
makeAutoObservable(this, {
|
|
95
|
+
vm: computed
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
get vm() {
|
|
99
|
+
const total = this._buckets.reduce((sum, b)=>sum + b.weight, 0);
|
|
100
|
+
const variantCount = this._buckets.filter((b)=>!b.isControl).length;
|
|
101
|
+
const canSubmit = this._name.trim().length > 0 && this._key.trim().length > 0;
|
|
102
|
+
return {
|
|
103
|
+
name: this._name,
|
|
104
|
+
key: this._key,
|
|
105
|
+
buckets: this._buckets,
|
|
106
|
+
total,
|
|
107
|
+
variantCount,
|
|
108
|
+
canSubmit,
|
|
109
|
+
submitLabel: this._submitLabel,
|
|
110
|
+
allowStructureChange: this._allowStructureChange
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
init(initial, options) {
|
|
114
|
+
this._name = initial?.name ?? "";
|
|
115
|
+
this._key = initial?.key ?? "";
|
|
116
|
+
this._keyEdited = Boolean(initial?.key);
|
|
117
|
+
this._buckets = initial?.buckets ?? defaultBuckets();
|
|
118
|
+
this._submitLabel = options.submitLabel;
|
|
119
|
+
this._allowStructureChange = options.allowStructureChange;
|
|
120
|
+
this._onSubmit = options.onSubmit;
|
|
121
|
+
}
|
|
122
|
+
setName(value) {
|
|
123
|
+
this._name = value;
|
|
124
|
+
if (!this._keyEdited) this._key = toKey(value);
|
|
125
|
+
}
|
|
126
|
+
setKey(value) {
|
|
127
|
+
this._keyEdited = true;
|
|
128
|
+
this._key = value;
|
|
129
|
+
}
|
|
130
|
+
addVariant() {
|
|
131
|
+
const count = this._buckets.filter((b)=>!b.isControl).length;
|
|
132
|
+
const variantName = `Variant ${String.fromCharCode(66 + count)}`;
|
|
133
|
+
this._buckets = evenSplit([
|
|
134
|
+
...this._buckets,
|
|
135
|
+
{
|
|
136
|
+
id: crypto.randomUUID(),
|
|
137
|
+
isControl: false,
|
|
138
|
+
weight: 0,
|
|
139
|
+
name: variantName,
|
|
140
|
+
key: toKey(variantName),
|
|
141
|
+
keyEdited: false,
|
|
142
|
+
description: ""
|
|
143
|
+
}
|
|
144
|
+
]);
|
|
145
|
+
}
|
|
146
|
+
removeVariant(index) {
|
|
147
|
+
this._buckets = evenSplit(this._buckets.filter((_, i)=>i !== index));
|
|
148
|
+
}
|
|
149
|
+
changeWeight(index, value) {
|
|
150
|
+
this._buckets = rebalance(this._buckets, index, value);
|
|
151
|
+
}
|
|
152
|
+
changeName(index, value) {
|
|
153
|
+
this._buckets = this._buckets.map((b, i)=>i === index ? {
|
|
154
|
+
...b,
|
|
155
|
+
name: value,
|
|
156
|
+
key: b.keyEdited ? b.key : toKey(value)
|
|
157
|
+
} : b);
|
|
158
|
+
}
|
|
159
|
+
changeKey(index, value) {
|
|
160
|
+
this._buckets = this._buckets.map((b, i)=>i === index ? {
|
|
161
|
+
...b,
|
|
162
|
+
key: value,
|
|
163
|
+
keyEdited: true
|
|
164
|
+
} : b);
|
|
165
|
+
}
|
|
166
|
+
changeDescription(index, value) {
|
|
167
|
+
this._buckets = this._buckets.map((b, i)=>i === index ? {
|
|
168
|
+
...b,
|
|
169
|
+
description: value
|
|
170
|
+
} : b);
|
|
171
|
+
}
|
|
172
|
+
submit() {
|
|
173
|
+
const canSubmit = this._name.trim().length > 0 && this._key.trim().length > 0;
|
|
174
|
+
if (!canSubmit) return;
|
|
175
|
+
const control = this._buckets.find((b)=>b.isControl);
|
|
176
|
+
const variants = this._buckets.filter((b)=>!b.isControl).map((b)=>({
|
|
177
|
+
id: b.id,
|
|
178
|
+
revisionId: b.revisionId,
|
|
179
|
+
name: b.name,
|
|
180
|
+
key: b.key,
|
|
181
|
+
description: b.description,
|
|
182
|
+
weight: b.weight
|
|
183
|
+
}));
|
|
184
|
+
this._onSubmit({
|
|
185
|
+
name: this._name.trim(),
|
|
186
|
+
key: this._key.trim(),
|
|
187
|
+
control: {
|
|
188
|
+
key: control.key,
|
|
189
|
+
description: control.description,
|
|
190
|
+
weight: control.weight
|
|
191
|
+
},
|
|
192
|
+
variants
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
const ExperimentFormPresenter_ExperimentFormPresenter = ExperimentFormPresenter.createImplementation({
|
|
197
|
+
implementation: ExperimentFormPresenterImpl,
|
|
198
|
+
dependencies: []
|
|
199
|
+
});
|
|
200
|
+
export { ExperimentFormPresenter_ExperimentFormPresenter as ExperimentFormPresenter };
|
|
201
|
+
|
|
202
|
+
//# sourceMappingURL=ExperimentFormPresenter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presentation/experiments/ExperimentForm/ExperimentFormPresenter.js","sources":["../../../../src/presentation/experiments/ExperimentForm/ExperimentFormPresenter.ts"],"sourcesContent":["import { computed, makeAutoObservable } from \"mobx\";\nimport slugify from \"slugify\";\nimport {\n ExperimentFormPresenter as Abstraction,\n type ExperimentFormInitial,\n type FormBucket,\n type IExperimentFormPresenter,\n type IExperimentFormViewModel,\n type NewExperimentPayload\n} from \"./abstractions/ExperimentFormPresenter.js\";\n\nconst toKey = (value: string): string => slugify(value, { lower: true, strict: true });\n\nconst defaultBuckets = (): FormBucket[] => [\n {\n id: \"control\",\n isControl: true,\n name: \"Control\",\n key: \"control\",\n keyEdited: false,\n description: \"\",\n weight: 50\n },\n {\n id: crypto.randomUUID(),\n isControl: false,\n name: \"Variant B\",\n key: \"variant-b\",\n keyEdited: false,\n description: \"\",\n weight: 50\n }\n];\n\n/** Even split summing to 100, with any remainder distributed from the first bucket. */\nconst evenSplit = (buckets: FormBucket[]): FormBucket[] => {\n const n = buckets.length;\n const each = Math.floor(100 / n);\n const next = buckets.map(b => ({ ...b, weight: each }));\n let used = each * n;\n let i = 0;\n while (used < 100) {\n next[i % n].weight += 1;\n used++;\n i++;\n }\n return next;\n};\n\n/** Set one bucket's weight and auto-balance the rest (proportionally) so the total stays 100. */\nconst rebalance = (buckets: FormBucket[], index: number, rawValue: number): FormBucket[] => {\n const value = Math.max(0, Math.min(100, Math.round(rawValue)));\n const next = buckets.map(b => ({ ...b }));\n next[index].weight = value;\n\n const others = next.map((b, i) => ({ b, i })).filter(x => x.i !== index);\n if (others.length === 0) {\n next[index].weight = 100;\n return next;\n }\n\n const remaining = 100 - value;\n const sumOthers = others.reduce((sum, x) => sum + x.b.weight, 0);\n\n if (sumOthers <= 0) {\n const each = Math.floor(remaining / others.length);\n others.forEach(x => (next[x.i].weight = each));\n let used = each * others.length;\n let k = 0;\n while (used < remaining) {\n next[others[k % others.length].i].weight += 1;\n used++;\n k++;\n }\n } else {\n let allocated = 0;\n others.forEach(x => {\n const w = Math.max(0, Math.round((x.b.weight / sumOthers) * remaining));\n next[x.i].weight = w;\n allocated += w;\n });\n const drift = remaining - allocated;\n if (drift !== 0) {\n const largest = others.reduce((a, b) => (next[a.i].weight >= next[b.i].weight ? a : b));\n next[largest.i].weight = Math.max(0, next[largest.i].weight + drift);\n }\n }\n\n return next;\n};\n\nclass ExperimentFormPresenterImpl implements IExperimentFormPresenter {\n private _name = \"\";\n private _key = \"\";\n private _keyEdited = false;\n private _buckets: FormBucket[] = defaultBuckets();\n private _submitLabel = \"Create experiment\";\n private _allowStructureChange = true;\n private _onSubmit: (payload: NewExperimentPayload) => void = () => {\n return;\n };\n\n public constructor() {\n makeAutoObservable(this, { vm: computed });\n }\n\n public get vm(): IExperimentFormViewModel {\n const total = this._buckets.reduce((sum, b) => sum + b.weight, 0);\n const variantCount = this._buckets.filter(b => !b.isControl).length;\n const canSubmit = this._name.trim().length > 0 && this._key.trim().length > 0;\n\n return {\n name: this._name,\n key: this._key,\n buckets: this._buckets,\n total,\n variantCount,\n canSubmit,\n submitLabel: this._submitLabel,\n allowStructureChange: this._allowStructureChange\n };\n }\n\n public init(\n initial: ExperimentFormInitial | undefined,\n options: {\n submitLabel: string;\n allowStructureChange: boolean;\n onSubmit: (payload: NewExperimentPayload) => void;\n }\n ): void {\n this._name = initial?.name ?? \"\";\n this._key = initial?.key ?? \"\";\n this._keyEdited = Boolean(initial?.key);\n this._buckets = initial?.buckets ?? defaultBuckets();\n this._submitLabel = options.submitLabel;\n this._allowStructureChange = options.allowStructureChange;\n this._onSubmit = options.onSubmit;\n }\n\n public setName(value: string): void {\n this._name = value;\n if (!this._keyEdited) {\n this._key = toKey(value);\n }\n }\n\n public setKey(value: string): void {\n this._keyEdited = true;\n this._key = value;\n }\n\n public addVariant(): void {\n const count = this._buckets.filter(b => !b.isControl).length;\n const variantName = `Variant ${String.fromCharCode(66 + count)}`;\n this._buckets = evenSplit([\n ...this._buckets,\n {\n id: crypto.randomUUID(),\n isControl: false,\n weight: 0,\n name: variantName,\n key: toKey(variantName),\n keyEdited: false,\n description: \"\"\n }\n ]);\n }\n\n public removeVariant(index: number): void {\n this._buckets = evenSplit(this._buckets.filter((_, i) => i !== index));\n }\n\n public changeWeight(index: number, value: number): void {\n this._buckets = rebalance(this._buckets, index, value);\n }\n\n public changeName(index: number, value: string): void {\n this._buckets = this._buckets.map((b, i) =>\n i === index ? { ...b, name: value, key: b.keyEdited ? b.key : toKey(value) } : b\n );\n }\n\n public changeKey(index: number, value: string): void {\n this._buckets = this._buckets.map((b, i) =>\n i === index ? { ...b, key: value, keyEdited: true } : b\n );\n }\n\n public changeDescription(index: number, value: string): void {\n this._buckets = this._buckets.map((b, i) =>\n i === index ? { ...b, description: value } : b\n );\n }\n\n public submit(): void {\n const canSubmit = this._name.trim().length > 0 && this._key.trim().length > 0;\n if (!canSubmit) {\n return;\n }\n const control = this._buckets.find(b => b.isControl)!;\n const variants = this._buckets\n .filter(b => !b.isControl)\n .map(b => ({\n id: b.id,\n revisionId: b.revisionId,\n name: b.name,\n key: b.key,\n description: b.description,\n weight: b.weight\n }));\n\n this._onSubmit({\n name: this._name.trim(),\n key: this._key.trim(),\n control: { key: control.key, description: control.description, weight: control.weight },\n variants\n });\n }\n}\n\nexport const ExperimentFormPresenter = Abstraction.createImplementation({\n implementation: ExperimentFormPresenterImpl,\n dependencies: []\n});\n"],"names":["toKey","value","slugify","defaultBuckets","crypto","evenSplit","buckets","n","each","Math","next","b","used","i","rebalance","index","rawValue","others","x","remaining","sumOthers","sum","k","allocated","w","drift","largest","a","ExperimentFormPresenterImpl","makeAutoObservable","computed","total","variantCount","canSubmit","initial","options","Boolean","count","variantName","String","_","control","variants","ExperimentFormPresenter","Abstraction"],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/** A single form row: the control or a variant, with its traffic weight and analytics key. */
|
|
2
|
+
export interface FormBucket {
|
|
3
|
+
id: string;
|
|
4
|
+
isControl: boolean;
|
|
5
|
+
name: string;
|
|
6
|
+
key: string;
|
|
7
|
+
keyEdited: boolean;
|
|
8
|
+
description: string;
|
|
9
|
+
weight: number;
|
|
10
|
+
revisionId?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ExperimentFormInitial {
|
|
13
|
+
name: string;
|
|
14
|
+
key: string;
|
|
15
|
+
buckets: FormBucket[];
|
|
16
|
+
}
|
|
17
|
+
export interface NewExperimentPayload {
|
|
18
|
+
name: string;
|
|
19
|
+
key: string;
|
|
20
|
+
control: {
|
|
21
|
+
key: string;
|
|
22
|
+
description: string;
|
|
23
|
+
weight: number;
|
|
24
|
+
};
|
|
25
|
+
variants: Array<{
|
|
26
|
+
id: string;
|
|
27
|
+
revisionId?: string;
|
|
28
|
+
name: string;
|
|
29
|
+
key: string;
|
|
30
|
+
description: string;
|
|
31
|
+
weight: number;
|
|
32
|
+
}>;
|
|
33
|
+
}
|
|
34
|
+
export interface IExperimentFormViewModel {
|
|
35
|
+
name: string;
|
|
36
|
+
key: string;
|
|
37
|
+
buckets: FormBucket[];
|
|
38
|
+
total: number;
|
|
39
|
+
variantCount: number;
|
|
40
|
+
canSubmit: boolean;
|
|
41
|
+
submitLabel: string;
|
|
42
|
+
allowStructureChange: boolean;
|
|
43
|
+
}
|
|
44
|
+
export interface IExperimentFormPresenter {
|
|
45
|
+
vm: IExperimentFormViewModel;
|
|
46
|
+
init(initial: ExperimentFormInitial | undefined, options: {
|
|
47
|
+
submitLabel: string;
|
|
48
|
+
allowStructureChange: boolean;
|
|
49
|
+
onSubmit: (payload: NewExperimentPayload) => void;
|
|
50
|
+
}): void;
|
|
51
|
+
setName(value: string): void;
|
|
52
|
+
setKey(value: string): void;
|
|
53
|
+
addVariant(): void;
|
|
54
|
+
removeVariant(index: number): void;
|
|
55
|
+
changeWeight(index: number, value: number): void;
|
|
56
|
+
changeName(index: number, value: string): void;
|
|
57
|
+
changeKey(index: number, value: string): void;
|
|
58
|
+
changeDescription(index: number, value: string): void;
|
|
59
|
+
submit(): void;
|
|
60
|
+
}
|
|
61
|
+
export declare const ExperimentFormPresenter: import("@webiny/di").Abstraction<IExperimentFormPresenter>;
|
|
62
|
+
export declare namespace ExperimentFormPresenter {
|
|
63
|
+
type Interface = IExperimentFormPresenter;
|
|
64
|
+
type ViewModel = IExperimentFormViewModel;
|
|
65
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presentation/experiments/ExperimentForm/abstractions/ExperimentFormPresenter.js","sources":["../../../../../src/presentation/experiments/ExperimentForm/abstractions/ExperimentFormPresenter.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/admin\";\n\n/** A single form row: the control or a variant, with its traffic weight and analytics key. */\nexport interface FormBucket {\n id: string;\n isControl: boolean;\n name: string;\n key: string;\n keyEdited: boolean;\n description: string;\n weight: number;\n // CMS revision id of an existing variant (edit mode); absent for control and new variants.\n revisionId?: string;\n}\n\nexport interface ExperimentFormInitial {\n name: string;\n key: string;\n buckets: FormBucket[];\n}\n\nexport interface NewExperimentPayload {\n name: string;\n key: string;\n control: { key: string; description: string; weight: number };\n variants: Array<{\n id: string;\n revisionId?: string;\n name: string;\n key: string;\n description: string;\n weight: number;\n }>;\n}\n\nexport interface IExperimentFormViewModel {\n name: string;\n key: string;\n buckets: FormBucket[];\n total: number;\n variantCount: number;\n canSubmit: boolean;\n submitLabel: string;\n allowStructureChange: boolean;\n}\n\nexport interface IExperimentFormPresenter {\n vm: IExperimentFormViewModel;\n init(\n initial: ExperimentFormInitial | undefined,\n options: {\n submitLabel: string;\n allowStructureChange: boolean;\n onSubmit: (payload: NewExperimentPayload) => void;\n }\n ): void;\n setName(value: string): void;\n setKey(value: string): void;\n addVariant(): void;\n removeVariant(index: number): void;\n changeWeight(index: number, value: number): void;\n changeName(index: number, value: string): void;\n changeKey(index: number, value: string): void;\n changeDescription(index: number, value: string): void;\n submit(): void;\n}\n\nexport const ExperimentFormPresenter =\n createAbstraction<IExperimentFormPresenter>(\"ExperimentFormPresenter\");\n\nexport namespace ExperimentFormPresenter {\n export type Interface = IExperimentFormPresenter;\n export type ViewModel = IExperimentFormViewModel;\n}\n"],"names":["ExperimentFormPresenter","createAbstraction"],"mappings":";AAmEO,MAAMA,0BACTC,kBAA4C"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { ExperimentFormInitial, NewExperimentPayload } from "../abstractions/ExperimentFormPresenter.js";
|
|
3
|
+
interface Props {
|
|
4
|
+
onCancel: () => void;
|
|
5
|
+
onSubmit: (payload: NewExperimentPayload) => void;
|
|
6
|
+
initial?: ExperimentFormInitial;
|
|
7
|
+
submitLabel?: string;
|
|
8
|
+
/** When false, variants can't be added/removed (used when editing an existing experiment). */
|
|
9
|
+
allowStructureChange?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare const ExperimentFormView: (props: Props) => React.JSX.Element;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import react, { useMemo } from "react";
|
|
2
|
+
import { observer } from "mobx-react-lite";
|
|
3
|
+
import { DiContainerProvider, useContainer, useFeature } from "@webiny/app";
|
|
4
|
+
import { Button, Input, Text } from "@webiny/admin-ui";
|
|
5
|
+
import { ReactComponent } from "@webiny/icons/add.svg";
|
|
6
|
+
import { ReactComponent as info_svg_ReactComponent } from "@webiny/icons/info.svg";
|
|
7
|
+
import { ReactComponent as close_svg_ReactComponent } from "@webiny/icons/close.svg";
|
|
8
|
+
import { VariantSplitRow } from "./VariantSplitRow.js";
|
|
9
|
+
import { ExperimentFormPresenterFeature } from "../feature.js";
|
|
10
|
+
const ExperimentFormView_ExperimentFormViewInner = observer(function({ onCancel, onSubmit, initial, submitLabel = "Create experiment", allowStructureChange = true }) {
|
|
11
|
+
const { presenter } = useFeature(ExperimentFormPresenterFeature);
|
|
12
|
+
useMemo(()=>{
|
|
13
|
+
presenter.init(initial, {
|
|
14
|
+
submitLabel,
|
|
15
|
+
allowStructureChange,
|
|
16
|
+
onSubmit
|
|
17
|
+
});
|
|
18
|
+
}, [
|
|
19
|
+
presenter
|
|
20
|
+
]);
|
|
21
|
+
const { vm } = presenter;
|
|
22
|
+
return /*#__PURE__*/ react.createElement("div", {
|
|
23
|
+
style: {
|
|
24
|
+
display: "flex",
|
|
25
|
+
flexDirection: "column",
|
|
26
|
+
height: "100%"
|
|
27
|
+
}
|
|
28
|
+
}, /*#__PURE__*/ react.createElement("div", {
|
|
29
|
+
style: {
|
|
30
|
+
flex: 1,
|
|
31
|
+
overflowY: "auto",
|
|
32
|
+
padding: 24
|
|
33
|
+
}
|
|
34
|
+
}, /*#__PURE__*/ react.createElement("div", {
|
|
35
|
+
style: {
|
|
36
|
+
marginBottom: 20
|
|
37
|
+
}
|
|
38
|
+
}, /*#__PURE__*/ react.createElement(Input, {
|
|
39
|
+
label: "Experiment name",
|
|
40
|
+
value: vm.name,
|
|
41
|
+
onChange: (value)=>presenter.setName(value),
|
|
42
|
+
placeholder: "e.g. Homepage CTA test"
|
|
43
|
+
})), /*#__PURE__*/ react.createElement("div", {
|
|
44
|
+
style: {
|
|
45
|
+
marginBottom: 12
|
|
46
|
+
}
|
|
47
|
+
}, /*#__PURE__*/ react.createElement(Input, {
|
|
48
|
+
label: "Experiment key",
|
|
49
|
+
value: vm.key,
|
|
50
|
+
onChange: (value)=>presenter.setKey(value),
|
|
51
|
+
placeholder: "homepage-cta-test"
|
|
52
|
+
})), /*#__PURE__*/ react.createElement("div", {
|
|
53
|
+
style: {
|
|
54
|
+
display: "flex",
|
|
55
|
+
gap: 8,
|
|
56
|
+
background: "#f5f5f5",
|
|
57
|
+
borderRadius: 8,
|
|
58
|
+
padding: 12,
|
|
59
|
+
marginBottom: 28
|
|
60
|
+
}
|
|
61
|
+
}, /*#__PURE__*/ react.createElement(info_svg_ReactComponent, {
|
|
62
|
+
style: {
|
|
63
|
+
width: 18,
|
|
64
|
+
height: 18,
|
|
65
|
+
flexShrink: 0,
|
|
66
|
+
marginTop: 2
|
|
67
|
+
}
|
|
68
|
+
}), /*#__PURE__*/ react.createElement(Text, {
|
|
69
|
+
size: "sm"
|
|
70
|
+
}, "This key is the identifier reported to your analytics platform to track this experiment. Auto-generated from the name — edit it to override.")), /*#__PURE__*/ react.createElement("div", {
|
|
71
|
+
style: {
|
|
72
|
+
display: "flex",
|
|
73
|
+
alignItems: "center",
|
|
74
|
+
justifyContent: "space-between",
|
|
75
|
+
marginBottom: 4
|
|
76
|
+
}
|
|
77
|
+
}, /*#__PURE__*/ react.createElement(Text, null, "Variants & traffic split"), /*#__PURE__*/ react.createElement("span", {
|
|
78
|
+
style: {
|
|
79
|
+
fontSize: 13,
|
|
80
|
+
fontWeight: 600,
|
|
81
|
+
color: 100 === vm.total ? "#0f9d58" : "#d93025"
|
|
82
|
+
}
|
|
83
|
+
}, "Total ", vm.total, "%")), /*#__PURE__*/ react.createElement("div", {
|
|
84
|
+
style: {
|
|
85
|
+
marginBottom: 16
|
|
86
|
+
}
|
|
87
|
+
}, /*#__PURE__*/ react.createElement(Text, {
|
|
88
|
+
size: "sm"
|
|
89
|
+
}, "Each variant is an independent copy of the page. Sliders auto-balance to 100%.")), vm.buckets.map((bucket, index)=>/*#__PURE__*/ react.createElement(VariantSplitRow, {
|
|
90
|
+
key: bucket.id,
|
|
91
|
+
name: bucket.name,
|
|
92
|
+
variantKey: bucket.key,
|
|
93
|
+
description: bucket.description,
|
|
94
|
+
isControl: bucket.isControl,
|
|
95
|
+
weight: bucket.weight,
|
|
96
|
+
variantIndex: vm.buckets.slice(0, index).filter((b)=>!b.isControl).length,
|
|
97
|
+
onNameChange: (value)=>presenter.changeName(index, value),
|
|
98
|
+
onKeyChange: (value)=>presenter.changeKey(index, value),
|
|
99
|
+
onDescriptionChange: (value)=>presenter.changeDescription(index, value),
|
|
100
|
+
onChange: (value)=>presenter.changeWeight(index, value),
|
|
101
|
+
onRemove: bucket.isControl || !vm.allowStructureChange || vm.variantCount <= 1 ? void 0 : ()=>presenter.removeVariant(index),
|
|
102
|
+
removeIcon: /*#__PURE__*/ react.createElement(close_svg_ReactComponent, {
|
|
103
|
+
style: {
|
|
104
|
+
width: 14,
|
|
105
|
+
height: 14
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
})), vm.allowStructureChange ? /*#__PURE__*/ react.createElement("div", {
|
|
109
|
+
style: {
|
|
110
|
+
marginTop: 8
|
|
111
|
+
}
|
|
112
|
+
}, /*#__PURE__*/ react.createElement(Button, {
|
|
113
|
+
variant: "tertiary",
|
|
114
|
+
icon: /*#__PURE__*/ react.createElement(ReactComponent, null),
|
|
115
|
+
text: "Add variant",
|
|
116
|
+
onClick: ()=>presenter.addVariant()
|
|
117
|
+
})) : null), /*#__PURE__*/ react.createElement("div", {
|
|
118
|
+
style: {
|
|
119
|
+
display: "flex",
|
|
120
|
+
justifyContent: "flex-end",
|
|
121
|
+
gap: 12,
|
|
122
|
+
padding: 16,
|
|
123
|
+
borderTop: "1px solid #eee"
|
|
124
|
+
}
|
|
125
|
+
}, /*#__PURE__*/ react.createElement(Button, {
|
|
126
|
+
variant: "secondary",
|
|
127
|
+
text: "Cancel",
|
|
128
|
+
onClick: onCancel
|
|
129
|
+
}), /*#__PURE__*/ react.createElement(Button, {
|
|
130
|
+
variant: "primary",
|
|
131
|
+
text: vm.submitLabel,
|
|
132
|
+
disabled: !vm.canSubmit,
|
|
133
|
+
onClick: ()=>presenter.submit()
|
|
134
|
+
})));
|
|
135
|
+
});
|
|
136
|
+
const ExperimentFormView = (props)=>{
|
|
137
|
+
const container = useContainer();
|
|
138
|
+
const scopedContainer = useMemo(()=>{
|
|
139
|
+
const child = container.createChildContainer();
|
|
140
|
+
ExperimentFormPresenterFeature.register(child);
|
|
141
|
+
return child;
|
|
142
|
+
}, []);
|
|
143
|
+
return /*#__PURE__*/ react.createElement(DiContainerProvider, {
|
|
144
|
+
container: scopedContainer
|
|
145
|
+
}, /*#__PURE__*/ react.createElement(ExperimentFormView_ExperimentFormViewInner, props));
|
|
146
|
+
};
|
|
147
|
+
export { ExperimentFormView };
|
|
148
|
+
|
|
149
|
+
//# sourceMappingURL=ExperimentFormView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presentation/experiments/ExperimentForm/components/ExperimentFormView.js","sources":["../../../../../src/presentation/experiments/ExperimentForm/components/ExperimentFormView.tsx"],"sourcesContent":["import React, { useMemo } from \"react\";\nimport { observer } from \"mobx-react-lite\";\nimport { DiContainerProvider, useContainer, useFeature } from \"@webiny/app\";\nimport { Button, Input, Text } from \"@webiny/admin-ui\";\nimport { ReactComponent as AddIcon } from \"@webiny/icons/add.svg\";\nimport { ReactComponent as InfoIcon } from \"@webiny/icons/info.svg\";\nimport { ReactComponent as CloseIcon } from \"@webiny/icons/close.svg\";\nimport { VariantSplitRow } from \"./VariantSplitRow.js\";\nimport { ExperimentFormPresenterFeature } from \"../feature.js\";\nimport type {\n ExperimentFormInitial,\n NewExperimentPayload\n} from \"../abstractions/ExperimentFormPresenter.js\";\n\ninterface Props {\n onCancel: () => void;\n onSubmit: (payload: NewExperimentPayload) => void;\n initial?: ExperimentFormInitial;\n submitLabel?: string;\n /** When false, variants can't be added/removed (used when editing an existing experiment). */\n allowStructureChange?: boolean;\n}\n\nconst ExperimentFormViewInner = observer(function ExperimentFormViewInner({\n onCancel,\n onSubmit,\n initial,\n submitLabel = \"Create experiment\",\n allowStructureChange = true\n}: Props) {\n const { presenter } = useFeature(ExperimentFormPresenterFeature);\n\n useMemo(() => {\n presenter.init(initial, { submitLabel, allowStructureChange, onSubmit });\n }, [presenter]);\n\n const { vm } = presenter;\n\n return (\n <div style={{ display: \"flex\", flexDirection: \"column\", height: \"100%\" }}>\n <div style={{ flex: 1, overflowY: \"auto\", padding: 24 }}>\n <div style={{ marginBottom: 20 }}>\n <Input\n label=\"Experiment name\"\n value={vm.name}\n onChange={value => presenter.setName(value)}\n placeholder=\"e.g. Homepage CTA test\"\n />\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <Input\n label=\"Experiment key\"\n value={vm.key}\n onChange={value => presenter.setKey(value)}\n placeholder=\"homepage-cta-test\"\n />\n </div>\n\n <div\n style={{\n display: \"flex\",\n gap: 8,\n background: \"#f5f5f5\",\n borderRadius: 8,\n padding: 12,\n marginBottom: 28\n }}\n >\n <InfoIcon style={{ width: 18, height: 18, flexShrink: 0, marginTop: 2 }} />\n <Text size=\"sm\">\n This key is the identifier reported to your analytics platform to track this\n experiment. Auto-generated from the name — edit it to override.\n </Text>\n </div>\n\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n marginBottom: 4\n }}\n >\n <Text>Variants & traffic split</Text>\n <span\n style={{\n fontSize: 13,\n fontWeight: 600,\n color: vm.total === 100 ? \"#0f9d58\" : \"#d93025\"\n }}\n >\n Total {vm.total}%\n </span>\n </div>\n <div style={{ marginBottom: 16 }}>\n <Text size=\"sm\">\n Each variant is an independent copy of the page. Sliders auto-balance to\n 100%.\n </Text>\n </div>\n\n {vm.buckets.map((bucket, index) => (\n <VariantSplitRow\n key={bucket.id}\n name={bucket.name}\n variantKey={bucket.key}\n description={bucket.description}\n isControl={bucket.isControl}\n weight={bucket.weight}\n variantIndex={vm.buckets.slice(0, index).filter(b => !b.isControl).length}\n onNameChange={value => presenter.changeName(index, value)}\n onKeyChange={value => presenter.changeKey(index, value)}\n onDescriptionChange={value => presenter.changeDescription(index, value)}\n onChange={value => presenter.changeWeight(index, value)}\n onRemove={\n bucket.isControl || !vm.allowStructureChange || vm.variantCount <= 1\n ? undefined\n : () => presenter.removeVariant(index)\n }\n removeIcon={<CloseIcon style={{ width: 14, height: 14 }} />}\n />\n ))}\n\n {vm.allowStructureChange ? (\n <div style={{ marginTop: 8 }}>\n <Button\n variant=\"tertiary\"\n icon={<AddIcon />}\n text=\"Add variant\"\n onClick={() => presenter.addVariant()}\n />\n </div>\n ) : null}\n </div>\n\n <div\n style={{\n display: \"flex\",\n justifyContent: \"flex-end\",\n gap: 12,\n padding: 16,\n borderTop: \"1px solid #eee\"\n }}\n >\n <Button variant=\"secondary\" text=\"Cancel\" onClick={onCancel} />\n <Button\n variant=\"primary\"\n text={vm.submitLabel}\n disabled={!vm.canSubmit}\n onClick={() => presenter.submit()}\n />\n </div>\n </div>\n );\n});\n\nexport const ExperimentFormView = (props: Props) => {\n const container = useContainer();\n\n const scopedContainer = useMemo(() => {\n const child = container.createChildContainer();\n ExperimentFormPresenterFeature.register(child);\n return child;\n }, []);\n\n return (\n <DiContainerProvider container={scopedContainer}>\n <ExperimentFormViewInner {...props} />\n </DiContainerProvider>\n );\n};\n"],"names":["ExperimentFormViewInner","observer","onCancel","onSubmit","initial","submitLabel","allowStructureChange","presenter","useFeature","ExperimentFormPresenterFeature","useMemo","vm","Input","value","InfoIcon","Text","bucket","index","VariantSplitRow","b","undefined","CloseIcon","Button","AddIcon","ExperimentFormView","props","container","useContainer","scopedContainer","child","DiContainerProvider"],"mappings":"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"}
|