@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.
Files changed (234) hide show
  1. package/BaseEditor/commandHandlers/CloneElement.d.ts +1 -0
  2. package/BaseEditor/commandHandlers/CloneElement.js +17 -0
  3. package/BaseEditor/commandHandlers/CloneElement.js.map +1 -0
  4. package/BaseEditor/commandHandlers/index.js +2 -1
  5. package/BaseEditor/commandHandlers/index.js.map +1 -1
  6. package/BaseEditor/commands.d.ts +3 -0
  7. package/BaseEditor/commands.js +2 -0
  8. package/BaseEditor/commands.js.map +1 -1
  9. package/BaseEditor/defaultConfig/Content/AddressBar/usePreviewLink.js +4 -1
  10. package/BaseEditor/defaultConfig/Content/AddressBar/usePreviewLink.js.map +1 -1
  11. package/BaseEditor/defaultConfig/Content/Preview/DropZoneManager.js.map +1 -1
  12. package/BaseEditor/defaultConfig/Content/Preview/Iframe.d.ts +2 -2
  13. package/BaseEditor/defaultConfig/Content/Preview/Overlays/ElementOverlays.d.ts +2 -2
  14. package/BaseEditor/defaultConfig/DefaultEditorConfig.js +9 -0
  15. package/BaseEditor/defaultConfig/DefaultEditorConfig.js.map +1 -1
  16. package/BaseEditor/defaultConfig/DocumentStateEditor/DocumentStateEditor.d.ts +2 -2
  17. package/BaseEditor/defaultConfig/ElementInputRenderers.js +4 -0
  18. package/BaseEditor/defaultConfig/ElementInputRenderers.js.map +1 -1
  19. package/BaseEditor/defaultConfig/Sidebar/ElementActions/CloneElementAction.d.ts +2 -0
  20. package/BaseEditor/defaultConfig/Sidebar/ElementActions/CloneElementAction.js +25 -0
  21. package/BaseEditor/defaultConfig/Sidebar/ElementActions/CloneElementAction.js.map +1 -0
  22. package/BaseEditor/defaultConfig/Sidebar/ElementActions/DeleteElementAction.d.ts +2 -0
  23. package/BaseEditor/defaultConfig/Sidebar/ElementActions/DeleteElementAction.js +26 -0
  24. package/BaseEditor/defaultConfig/Sidebar/ElementActions/DeleteElementAction.js.map +1 -0
  25. package/BaseEditor/defaultConfig/Sidebar/ElementPreview.js +12 -2
  26. package/BaseEditor/defaultConfig/Sidebar/ElementPreview.js.map +1 -1
  27. package/BaseEditor/defaultConfig/Sidebar/ElementSettings/ElementInputs.js +1 -6
  28. package/BaseEditor/defaultConfig/Sidebar/ElementSettings/ElementInputs.js.map +1 -1
  29. package/BaseEditor/defaultConfig/Sidebar/ElementSettings/ElementSettings.js +11 -2
  30. package/BaseEditor/defaultConfig/Sidebar/ElementSettings/ElementSettings.js.map +1 -1
  31. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Background/BackgroundColor.d.ts +6 -2
  32. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Background/BackgroundImage.d.ts +6 -2
  33. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Background/BackgroundPosition.d.ts +6 -2
  34. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Background/BackgroundScaling.d.ts +6 -2
  35. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Border/BorderColor.d.ts +2 -2
  36. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Border/BorderRadius.d.ts +2 -2
  37. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Border/BorderStyle.d.ts +2 -2
  38. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Border/BorderWidth.d.ts +2 -2
  39. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Layout/Alignment.d.ts +6 -2
  40. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Layout/LengthWithUnitInput.d.ts +2 -2
  41. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/MarginPadding/Margin.d.ts +2 -2
  42. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/MarginPadding/Padding.d.ts +2 -2
  43. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Visibility/Visibility.d.ts +2 -2
  44. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/StyleProperties.js +7 -7
  45. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/StyleProperties.js.map +1 -1
  46. package/BaseEditor/defaultConfig/Toolbar/Navigator/Navigator.d.ts +2 -2
  47. package/DocumentEditor/DocumentEditor.d.ts +14 -5
  48. package/DocumentEditor/DocumentEditor.js +10 -6
  49. package/DocumentEditor/DocumentEditor.js.map +1 -1
  50. package/DocumentEditor/StateInspector.d.ts +4 -2
  51. package/Extension.js +7 -1
  52. package/Extension.js.map +1 -1
  53. package/ecommerce/components/ResourcePage.d.ts +6 -2
  54. package/ecommerce/components/ResourcesList.d.ts +4 -4
  55. package/ecommerce/components/ResourcesPicker.d.ts +9 -4
  56. package/editorSdk/CommandBus.js.map +1 -1
  57. package/editorSdk/utils/$cloneElement.d.ts +2 -0
  58. package/editorSdk/utils/$cloneElement.js +112 -0
  59. package/editorSdk/utils/$cloneElement.js.map +1 -0
  60. package/editorSdk/utils/index.d.ts +1 -0
  61. package/editorSdk/utils/index.js +1 -0
  62. package/features/experiments/ExperimentsGateway.d.ts +30 -0
  63. package/features/experiments/ExperimentsGateway.js +326 -0
  64. package/features/experiments/ExperimentsGateway.js.map +1 -0
  65. package/features/experiments/abstractions.d.ts +25 -0
  66. package/features/experiments/abstractions.js +5 -0
  67. package/features/experiments/abstractions.js.map +1 -0
  68. package/features/experiments/feature.d.ts +3 -0
  69. package/features/experiments/feature.js +17 -0
  70. package/features/experiments/feature.js.map +1 -0
  71. package/features/experiments/index.d.ts +3 -0
  72. package/features/experiments/index.js +2 -0
  73. package/features/experiments/types.d.ts +61 -0
  74. package/features/experiments/types.js +0 -0
  75. package/inputRenderers/ColorPickerInput.d.ts +3 -0
  76. package/inputRenderers/ColorPickerInput.js +29 -0
  77. package/inputRenderers/ColorPickerInput.js.map +1 -0
  78. package/inputRenderers/FileInput.js +93 -8
  79. package/inputRenderers/FileInput.js.map +1 -1
  80. package/inputRenderers/LexicalInput/LexicalEditor.js +15 -8
  81. package/inputRenderers/LexicalInput/LexicalEditor.js.map +1 -1
  82. package/inputRenderers/LexicalInput/TypographyDropDown.js +3 -2
  83. package/inputRenderers/LexicalInput/TypographyDropDown.js.map +1 -1
  84. package/inputRenderers/LexicalInput/wbStaticToolbar.css +72 -103
  85. package/modules/AbTesting.d.ts +2 -0
  86. package/modules/AbTesting.js +19 -0
  87. package/modules/AbTesting.js.map +1 -0
  88. package/package.json +28 -28
  89. package/presentation/components/LanguageCodeTag.js +5 -4
  90. package/presentation/components/LanguageCodeTag.js.map +1 -1
  91. package/presentation/experiments/ExperimentForm/ExperimentFormPresenter.d.ts +30 -0
  92. package/presentation/experiments/ExperimentForm/ExperimentFormPresenter.js +202 -0
  93. package/presentation/experiments/ExperimentForm/ExperimentFormPresenter.js.map +1 -0
  94. package/presentation/experiments/ExperimentForm/abstractions/ExperimentFormPresenter.d.ts +65 -0
  95. package/presentation/experiments/ExperimentForm/abstractions/ExperimentFormPresenter.js +5 -0
  96. package/presentation/experiments/ExperimentForm/abstractions/ExperimentFormPresenter.js.map +1 -0
  97. package/presentation/experiments/ExperimentForm/components/ExperimentFormView.d.ts +12 -0
  98. package/presentation/experiments/ExperimentForm/components/ExperimentFormView.js +149 -0
  99. package/presentation/experiments/ExperimentForm/components/ExperimentFormView.js.map +1 -0
  100. package/presentation/experiments/ExperimentForm/components/VariantSplitRow.d.ts +17 -0
  101. package/presentation/experiments/ExperimentForm/components/VariantSplitRow.js +122 -0
  102. package/presentation/experiments/ExperimentForm/components/VariantSplitRow.js.map +1 -0
  103. package/presentation/experiments/ExperimentForm/feature.d.ts +3 -0
  104. package/presentation/experiments/ExperimentForm/feature.js +17 -0
  105. package/presentation/experiments/ExperimentForm/feature.js.map +1 -0
  106. package/presentation/experiments/ExperimentForm/index.d.ts +3 -0
  107. package/presentation/experiments/ExperimentForm/index.js +3 -0
  108. package/presentation/experiments/ExperimentsEditor/ExperimentsEditorDataSource.d.ts +18 -0
  109. package/presentation/experiments/ExperimentsEditor/ExperimentsEditorDataSource.js +25 -0
  110. package/presentation/experiments/ExperimentsEditor/ExperimentsEditorDataSource.js.map +1 -0
  111. package/presentation/experiments/ExperimentsEditor/ExperimentsEditorPresenter.d.ts +67 -0
  112. package/presentation/experiments/ExperimentsEditor/ExperimentsEditorPresenter.js +224 -0
  113. package/presentation/experiments/ExperimentsEditor/ExperimentsEditorPresenter.js.map +1 -0
  114. package/presentation/experiments/ExperimentsEditor/abstractions/ExperimentsEditorDataSource.d.ts +10 -0
  115. package/presentation/experiments/ExperimentsEditor/abstractions/ExperimentsEditorDataSource.js +5 -0
  116. package/presentation/experiments/ExperimentsEditor/abstractions/ExperimentsEditorDataSource.js.map +1 -0
  117. package/presentation/experiments/ExperimentsEditor/abstractions/ExperimentsEditorPresenter.d.ts +58 -0
  118. package/presentation/experiments/ExperimentsEditor/abstractions/ExperimentsEditorPresenter.js +5 -0
  119. package/presentation/experiments/ExperimentsEditor/abstractions/ExperimentsEditorPresenter.js.map +1 -0
  120. package/presentation/experiments/ExperimentsEditor/components/ExperimentIndicator.d.ts +15 -0
  121. package/presentation/experiments/ExperimentsEditor/components/ExperimentIndicator.js +110 -0
  122. package/presentation/experiments/ExperimentsEditor/components/ExperimentIndicator.js.map +1 -0
  123. package/presentation/experiments/ExperimentsEditor/components/ExperimentPreviewToolbar.d.ts +9 -0
  124. package/presentation/experiments/ExperimentsEditor/components/ExperimentPreviewToolbar.js +178 -0
  125. package/presentation/experiments/ExperimentsEditor/components/ExperimentPreviewToolbar.js.map +1 -0
  126. package/presentation/experiments/ExperimentsEditor/components/ExperimentsButton.d.ts +11 -0
  127. package/presentation/experiments/ExperimentsEditor/components/ExperimentsButton.js +51 -0
  128. package/presentation/experiments/ExperimentsEditor/components/ExperimentsButton.js.map +1 -0
  129. package/presentation/experiments/ExperimentsEditor/components/ExperimentsSwitcher.d.ts +14 -0
  130. package/presentation/experiments/ExperimentsEditor/components/ExperimentsSwitcher.js +147 -0
  131. package/presentation/experiments/ExperimentsEditor/components/ExperimentsSwitcher.js.map +1 -0
  132. package/presentation/experiments/ExperimentsEditor/feature.d.ts +3 -0
  133. package/presentation/experiments/ExperimentsEditor/feature.js +21 -0
  134. package/presentation/experiments/ExperimentsEditor/feature.js.map +1 -0
  135. package/presentation/experiments/ExperimentsEditor/index.d.ts +4 -0
  136. package/presentation/experiments/ExperimentsEditor/index.js +3 -0
  137. package/presentation/experiments/ExperimentsManager/ExperimentsManagerPresenter.d.ts +39 -0
  138. package/presentation/experiments/ExperimentsManager/ExperimentsManagerPresenter.js +219 -0
  139. package/presentation/experiments/ExperimentsManager/ExperimentsManagerPresenter.js.map +1 -0
  140. package/presentation/experiments/ExperimentsManager/abstractions/ExperimentsManagerPresenter.d.ts +52 -0
  141. package/presentation/experiments/ExperimentsManager/abstractions/ExperimentsManagerPresenter.js +5 -0
  142. package/presentation/experiments/ExperimentsManager/abstractions/ExperimentsManagerPresenter.js.map +1 -0
  143. package/presentation/experiments/ExperimentsManager/components/ExperimentCard.d.ts +10 -0
  144. package/presentation/experiments/ExperimentsManager/components/ExperimentCard.js +296 -0
  145. package/presentation/experiments/ExperimentsManager/components/ExperimentCard.js.map +1 -0
  146. package/presentation/experiments/ExperimentsManager/components/ExperimentsDrawerView.d.ts +2 -0
  147. package/presentation/experiments/ExperimentsManager/components/ExperimentsDrawerView.js +92 -0
  148. package/presentation/experiments/ExperimentsManager/components/ExperimentsDrawerView.js.map +1 -0
  149. package/presentation/experiments/ExperimentsManager/components/ExperimentsEmptyState.d.ts +6 -0
  150. package/presentation/experiments/ExperimentsManager/components/ExperimentsEmptyState.js +103 -0
  151. package/presentation/experiments/ExperimentsManager/components/ExperimentsEmptyState.js.map +1 -0
  152. package/presentation/experiments/ExperimentsManager/components/ExperimentsListView.d.ts +9 -0
  153. package/presentation/experiments/ExperimentsManager/components/ExperimentsListView.js +58 -0
  154. package/presentation/experiments/ExperimentsManager/components/ExperimentsListView.js.map +1 -0
  155. package/presentation/experiments/ExperimentsManager/feature.d.ts +3 -0
  156. package/presentation/experiments/ExperimentsManager/feature.js +17 -0
  157. package/presentation/experiments/ExperimentsManager/feature.js.map +1 -0
  158. package/presentation/experiments/ExperimentsManager/index.d.ts +4 -0
  159. package/presentation/experiments/ExperimentsManager/index.js +3 -0
  160. package/presentation/experiments/VariantPageEditorConfig.d.ts +7 -0
  161. package/presentation/experiments/VariantPageEditorConfig.js +26 -0
  162. package/presentation/experiments/VariantPageEditorConfig.js.map +1 -0
  163. package/presentation/experiments/config/ExperimentsEditorConfig.d.ts +8 -0
  164. package/presentation/experiments/config/ExperimentsEditorConfig.js +21 -0
  165. package/presentation/experiments/config/ExperimentsEditorConfig.js.map +1 -0
  166. package/presentation/experiments/config/VariantAutoSave.d.ts +5 -0
  167. package/presentation/experiments/config/VariantAutoSave.js +41 -0
  168. package/presentation/experiments/config/VariantAutoSave.js.map +1 -0
  169. package/presentation/experiments/shared/variantColors.d.ts +11 -0
  170. package/presentation/experiments/shared/variantColors.js +13 -0
  171. package/presentation/experiments/shared/variantColors.js.map +1 -0
  172. package/presentation/experiments/shared/variantDocument.d.ts +16 -0
  173. package/presentation/experiments/shared/variantDocument.js +31 -0
  174. package/presentation/experiments/shared/variantDocument.js.map +1 -0
  175. package/presentation/navigation/Extension.js +9 -5
  176. package/presentation/navigation/Extension.js.map +1 -1
  177. package/presentation/navigation/NextjsConfig/NextjsConfigDialog.d.ts +2 -2
  178. package/presentation/navigation/StarterKitConfigDialog.js +1 -1
  179. package/presentation/navigation/StarterKitConfigDialog.js.map +1 -1
  180. package/presentation/pages/CreatePage/CreatePageDialog.d.ts +2 -2
  181. package/presentation/pages/CreatePage/CreatePagePresenter.js +1 -1
  182. package/presentation/pages/CreatePage/CreatePagePresenter.js.map +1 -1
  183. package/presentation/pages/CreatePage/WithLanguageSelector.js +3 -3
  184. package/presentation/pages/CreatePage/WithLanguageSelector.js.map +1 -1
  185. package/presentation/pages/CreatePage/feature.js +3 -3
  186. package/presentation/pages/CreatePage/feature.js.map +1 -1
  187. package/presentation/pages/PageEditor/PageEditor.experiments.d.ts +2 -0
  188. package/presentation/pages/PageEditor/PageEditor.experiments.js +54 -0
  189. package/presentation/pages/PageEditor/PageEditor.experiments.js.map +1 -0
  190. package/presentation/pages/PageEditor/PageEditorSurface.d.ts +15 -0
  191. package/presentation/pages/PageEditor/PageEditorSurface.js +63 -0
  192. package/presentation/pages/PageEditor/PageEditorSurface.js.map +1 -0
  193. package/presentation/pages/PageEditor/TopBar/PageSettingsDrawer.d.ts +2 -2
  194. package/presentation/pages/PageEditor/pageDocument.d.ts +4 -0
  195. package/presentation/pages/PageEditor/pageDocument.js +15 -0
  196. package/presentation/pages/PageEditor/pageDocument.js.map +1 -0
  197. package/presentation/pages/PageList/components/BulkActions/BulkActionDelete.d.ts +2 -2
  198. package/presentation/pages/PageList/components/BulkActions/BulkActionDuplicate.d.ts +2 -2
  199. package/presentation/pages/PageList/components/BulkActions/BulkActionMovePage.d.ts +2 -2
  200. package/presentation/pages/PageList/components/BulkActions/BulkActionPublish.d.ts +2 -2
  201. package/presentation/pages/PageList/components/BulkActions/BulkActionUnpublish.d.ts +2 -2
  202. package/presentation/pages/PageList/components/DocumentList.d.ts +2 -2
  203. package/presentation/pages/PageList/components/PagesList.js +2 -1
  204. package/presentation/pages/PageList/components/PagesList.js.map +1 -1
  205. package/presentation/pages/PageList/components/Table/Table.d.ts +2 -2
  206. package/presentation/pages/PageList/components/WbPagesBreadcrumbs.d.ts +9 -0
  207. package/presentation/pages/PageList/components/WbPagesBreadcrumbs.js +40 -0
  208. package/presentation/pages/PageList/components/WbPagesBreadcrumbs.js.map +1 -0
  209. package/presentation/pages/TranslatePage/TranslatePageConfig.d.ts +1 -1
  210. package/presentation/pages/TranslatePage/TranslatePageConfig.js +6 -2
  211. package/presentation/pages/TranslatePage/TranslatePageConfig.js.map +1 -1
  212. package/presentation/pages/TranslatePage/TranslatePageDialog.js +22 -10
  213. package/presentation/pages/TranslatePage/TranslatePageDialog.js.map +1 -1
  214. package/presentation/pages/TranslatePage/translatePageSchema.d.ts +1 -1
  215. package/presentation/pages/TranslatePage/translatePageSchema.js +1 -1
  216. package/presentation/pages/TranslatePage/translatePageSchema.js.map +1 -1
  217. package/presentation/pages/TrashBin/WbTrashBin.d.ts +2 -2
  218. package/presentation/redirects/RedirectList/components/BulkActionDelete.d.ts +2 -2
  219. package/presentation/redirects/RedirectList/components/BulkActionMove.d.ts +2 -2
  220. package/presentation/redirects/RedirectList/components/CreateRedirectDialog.d.ts +2 -2
  221. package/presentation/redirects/RedirectList/components/DocumentList.d.ts +2 -2
  222. package/presentation/redirects/RedirectList/components/EditRedirectDialog.d.ts +2 -2
  223. package/presentation/redirects/RedirectList/components/Table/Table.d.ts +2 -2
  224. package/shared/fileManagerItemToValue.d.ts +8 -9
  225. package/shared/fileManagerItemToValue.js +22 -7
  226. package/shared/fileManagerItemToValue.js.map +1 -1
  227. package/inputRenderers/LexicalInput/icons/list-ol.js +0 -20
  228. package/inputRenderers/LexicalInput/icons/list-ol.js.map +0 -1
  229. package/inputRenderers/LexicalInput/icons/list-ol.svg +0 -1
  230. package/inputRenderers/LexicalInput/icons/list-ul.js +0 -18
  231. package/inputRenderers/LexicalInput/icons/list-ul.js.map +0 -1
  232. package/inputRenderers/LexicalInput/icons/list-ul.svg +0 -1
  233. package/static/svg/list-ol.d64946f3.svg +0 -1
  234. package/static/svg/list-ul.1d54da3f.svg +0 -1
@@ -0,0 +1,147 @@
1
+ import react, { useState } from "react";
2
+ import { DropdownMenu } from "@webiny/admin-ui";
3
+ import { ReactComponent } from "@webiny/icons/science.svg";
4
+ import { ReactComponent as expand_more_svg_ReactComponent } from "@webiny/icons/expand_more.svg";
5
+ import { ReactComponent as public_svg_ReactComponent } from "@webiny/icons/public.svg";
6
+ import { ReactComponent as check_svg_ReactComponent } from "@webiny/icons/check.svg";
7
+ import { ReactComponent as tune_svg_ReactComponent } from "@webiny/icons/tune.svg";
8
+ const Dot = ({ color })=>/*#__PURE__*/ react.createElement("span", {
9
+ style: {
10
+ width: 8,
11
+ height: 8,
12
+ borderRadius: "50%",
13
+ background: color,
14
+ flexShrink: 0
15
+ }
16
+ });
17
+ const StatusBadge = ({ status })=>{
18
+ const active = "active" === status;
19
+ return /*#__PURE__*/ react.createElement("span", {
20
+ style: {
21
+ fontSize: 12,
22
+ fontWeight: 500,
23
+ color: active ? "#0f9d58" : "#6b7280",
24
+ background: active ? "#e6f4ea" : "#f2f2f2",
25
+ borderRadius: 6,
26
+ padding: "1px 8px",
27
+ whiteSpace: "nowrap"
28
+ }
29
+ }, active ? "Active" : "Inactive");
30
+ };
31
+ const Row = ({ title, subtitle, right, selected })=>/*#__PURE__*/ react.createElement("div", {
32
+ style: {
33
+ display: "flex",
34
+ alignItems: "center",
35
+ justifyContent: "space-between",
36
+ width: "100%",
37
+ gap: 8
38
+ }
39
+ }, /*#__PURE__*/ react.createElement("div", {
40
+ style: {
41
+ display: "flex",
42
+ flexDirection: "column"
43
+ }
44
+ }, /*#__PURE__*/ react.createElement("span", {
45
+ style: {
46
+ fontWeight: subtitle ? 600 : 400
47
+ }
48
+ }, title), subtitle ? /*#__PURE__*/ react.createElement("span", {
49
+ style: {
50
+ fontSize: 12,
51
+ color: "#6b7280"
52
+ }
53
+ }, subtitle) : null), /*#__PURE__*/ react.createElement("div", {
54
+ style: {
55
+ display: "flex",
56
+ alignItems: "center",
57
+ gap: 8
58
+ }
59
+ }, right, selected ? /*#__PURE__*/ react.createElement(check_svg_ReactComponent, {
60
+ style: {
61
+ width: 16,
62
+ height: 16,
63
+ color: "#e2572a"
64
+ }
65
+ }) : null));
66
+ const ExperimentsSwitcher = ({ experiments, selectedId, onSelect, onManage })=>{
67
+ const [open, setOpen] = useState(false);
68
+ const selected = experiments.find((e)=>e.id === selectedId) ?? null;
69
+ const label = selected ? selected.name : "Experiments";
70
+ const trigger = /*#__PURE__*/ react.createElement("button", {
71
+ type: "button",
72
+ style: {
73
+ display: "inline-flex",
74
+ alignItems: "center",
75
+ gap: 8,
76
+ border: "1px solid #f2c9ba",
77
+ color: "#e2572a",
78
+ background: "#fff",
79
+ borderRadius: 8,
80
+ padding: "6px 12px",
81
+ fontWeight: 600,
82
+ cursor: "pointer"
83
+ }
84
+ }, /*#__PURE__*/ react.createElement(ReactComponent, {
85
+ style: {
86
+ width: 18,
87
+ height: 18,
88
+ fill: "currentColor"
89
+ }
90
+ }), label, /*#__PURE__*/ react.createElement(expand_more_svg_ReactComponent, {
91
+ style: {
92
+ width: 16,
93
+ height: 16,
94
+ fill: "currentColor"
95
+ }
96
+ }));
97
+ return /*#__PURE__*/ react.createElement(DropdownMenu, {
98
+ open: open,
99
+ onOpenChange: setOpen,
100
+ trigger: trigger,
101
+ style: {
102
+ minWidth: 320
103
+ }
104
+ }, /*#__PURE__*/ react.createElement(DropdownMenu.Label, {
105
+ text: "Now viewing"
106
+ }), /*#__PURE__*/ react.createElement(DropdownMenu.Item, {
107
+ icon: /*#__PURE__*/ react.createElement(public_svg_ReactComponent, {
108
+ style: {
109
+ width: 18,
110
+ height: 18
111
+ }
112
+ }),
113
+ text: /*#__PURE__*/ react.createElement(Row, {
114
+ title: "Original page",
115
+ subtitle: "No experiment applied",
116
+ selected: null === selectedId
117
+ }),
118
+ onClick: ()=>onSelect(null)
119
+ }), /*#__PURE__*/ react.createElement(DropdownMenu.Separator, null), /*#__PURE__*/ react.createElement(DropdownMenu.Label, {
120
+ text: "Experiments"
121
+ }), experiments.map((experiment)=>/*#__PURE__*/ react.createElement(DropdownMenu.Item, {
122
+ key: experiment.id,
123
+ icon: /*#__PURE__*/ react.createElement(Dot, {
124
+ color: "active" === experiment.status ? "#10b981" : "#9ca3af"
125
+ }),
126
+ text: /*#__PURE__*/ react.createElement(Row, {
127
+ title: experiment.name,
128
+ right: /*#__PURE__*/ react.createElement(StatusBadge, {
129
+ status: experiment.status
130
+ }),
131
+ selected: selectedId === experiment.id
132
+ }),
133
+ onClick: ()=>onSelect(experiment.id)
134
+ })), /*#__PURE__*/ react.createElement(DropdownMenu.Separator, null), /*#__PURE__*/ react.createElement(DropdownMenu.Item, {
135
+ icon: /*#__PURE__*/ react.createElement(tune_svg_ReactComponent, {
136
+ style: {
137
+ width: 18,
138
+ height: 18
139
+ }
140
+ }),
141
+ text: "Manage experiments…",
142
+ onClick: onManage
143
+ }));
144
+ };
145
+ export { ExperimentsSwitcher };
146
+
147
+ //# sourceMappingURL=ExperimentsSwitcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presentation/experiments/ExperimentsEditor/components/ExperimentsSwitcher.js","sources":["../../../../../src/presentation/experiments/ExperimentsEditor/components/ExperimentsSwitcher.tsx"],"sourcesContent":["import React, { useState } from \"react\";\nimport { DropdownMenu } from \"@webiny/admin-ui\";\nimport { ReactComponent as ScienceIcon } from \"@webiny/icons/science.svg\";\nimport { ReactComponent as ChevronDownIcon } from \"@webiny/icons/expand_more.svg\";\nimport { ReactComponent as GlobeIcon } from \"@webiny/icons/public.svg\";\nimport { ReactComponent as CheckIcon } from \"@webiny/icons/check.svg\";\nimport { ReactComponent as TuneIcon } from \"@webiny/icons/tune.svg\";\n\nexport interface ExperimentItem {\n id: string;\n name: string;\n status: \"active\" | \"inactive\";\n}\n\ninterface Props {\n experiments: ExperimentItem[];\n selectedId: string | null;\n onSelect: (id: string | null) => void;\n onManage: () => void;\n}\n\nconst Dot = ({ color }: { color: string }) => (\n <span style={{ width: 8, height: 8, borderRadius: \"50%\", background: color, flexShrink: 0 }} />\n);\n\nconst StatusBadge = ({ status }: { status: ExperimentItem[\"status\"] }) => {\n const active = status === \"active\";\n return (\n <span\n style={{\n fontSize: 12,\n fontWeight: 500,\n color: active ? \"#0f9d58\" : \"#6b7280\",\n background: active ? \"#e6f4ea\" : \"#f2f2f2\",\n borderRadius: 6,\n padding: \"1px 8px\",\n whiteSpace: \"nowrap\"\n }}\n >\n {active ? \"Active\" : \"Inactive\"}\n </span>\n );\n};\n\ninterface RowProps {\n title: string;\n subtitle?: string;\n right?: React.ReactNode;\n selected: boolean;\n}\n\nconst Row = ({ title, subtitle, right, selected }: RowProps) => (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n width: \"100%\",\n gap: 8\n }}\n >\n <div style={{ display: \"flex\", flexDirection: \"column\" }}>\n <span style={{ fontWeight: subtitle ? 600 : 400 }}>{title}</span>\n {subtitle ? <span style={{ fontSize: 12, color: \"#6b7280\" }}>{subtitle}</span> : null}\n </div>\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 8 }}>\n {right}\n {selected ? <CheckIcon style={{ width: 16, height: 16, color: \"#e2572a\" }} /> : null}\n </div>\n </div>\n);\n\nexport const ExperimentsSwitcher = ({ experiments, selectedId, onSelect, onManage }: Props) => {\n const [open, setOpen] = useState(false);\n const selected = experiments.find(e => e.id === selectedId) ?? null;\n const label = selected ? selected.name : \"Experiments\";\n\n const trigger = (\n <button\n type=\"button\"\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 8,\n border: \"1px solid #f2c9ba\",\n color: \"#e2572a\",\n background: \"#fff\",\n borderRadius: 8,\n padding: \"6px 12px\",\n fontWeight: 600,\n cursor: \"pointer\"\n }}\n >\n <ScienceIcon style={{ width: 18, height: 18, fill: \"currentColor\" }} />\n {label}\n <ChevronDownIcon style={{ width: 16, height: 16, fill: \"currentColor\" }} />\n </button>\n );\n\n return (\n <DropdownMenu\n open={open}\n onOpenChange={setOpen}\n trigger={trigger}\n style={{ minWidth: 320 }}\n >\n <DropdownMenu.Label text=\"Now viewing\" />\n <DropdownMenu.Item\n icon={<GlobeIcon style={{ width: 18, height: 18 }} />}\n text={\n <Row\n title=\"Original page\"\n subtitle=\"No experiment applied\"\n selected={selectedId === null}\n />\n }\n onClick={() => onSelect(null)}\n />\n <DropdownMenu.Separator />\n <DropdownMenu.Label text=\"Experiments\" />\n {experiments.map(experiment => (\n <DropdownMenu.Item\n key={experiment.id}\n icon={<Dot color={experiment.status === \"active\" ? \"#10b981\" : \"#9ca3af\"} />}\n text={\n <Row\n title={experiment.name}\n right={<StatusBadge status={experiment.status} />}\n selected={selectedId === experiment.id}\n />\n }\n onClick={() => onSelect(experiment.id)}\n />\n ))}\n <DropdownMenu.Separator />\n <DropdownMenu.Item\n icon={<TuneIcon style={{ width: 18, height: 18 }} />}\n text=\"Manage experiments…\"\n onClick={onManage}\n />\n </DropdownMenu>\n );\n};\n"],"names":["Dot","color","StatusBadge","status","active","Row","title","subtitle","right","selected","CheckIcon","ExperimentsSwitcher","experiments","selectedId","onSelect","onManage","open","setOpen","useState","e","label","trigger","ScienceIcon","ChevronDownIcon","DropdownMenu","GlobeIcon","experiment","TuneIcon"],"mappings":";;;;;;;AAqBA,MAAMA,MAAM,CAAC,EAAEC,KAAK,EAAqB,iBACrC,oBAAC;QAAK,OAAO;YAAE,OAAO;YAAG,QAAQ;YAAG,cAAc;YAAO,YAAYA;YAAO,YAAY;QAAE;;AAG9F,MAAMC,cAAc,CAAC,EAAEC,MAAM,EAAwC;IACjE,MAAMC,SAASD,AAAW,aAAXA;IACf,OAAO,WAAP,GACI,oBAAC;QACG,OAAO;YACH,UAAU;YACV,YAAY;YACZ,OAAOC,SAAS,YAAY;YAC5B,YAAYA,SAAS,YAAY;YACjC,cAAc;YACd,SAAS;YACT,YAAY;QAChB;OAECA,SAAS,WAAW;AAGjC;AASA,MAAMC,MAAM,CAAC,EAAEC,KAAK,EAAEC,QAAQ,EAAEC,KAAK,EAAEC,QAAQ,EAAY,iBACvD,oBAAC;QACG,OAAO;YACH,SAAS;YACT,YAAY;YACZ,gBAAgB;YAChB,OAAO;YACP,KAAK;QACT;qBAEA,oBAAC;QAAI,OAAO;YAAE,SAAS;YAAQ,eAAe;QAAS;qBACnD,oBAAC;QAAK,OAAO;YAAE,YAAYF,WAAW,MAAM;QAAI;OAAID,QACnDC,WAAW,WAAXA,GAAW,oBAAC;QAAK,OAAO;YAAE,UAAU;YAAI,OAAO;QAAU;OAAIA,YAAmB,qBAErF,oBAAC;QAAI,OAAO;YAAE,SAAS;YAAQ,YAAY;YAAU,KAAK;QAAE;OACvDC,OACAC,WAAW,WAAXA,GAAW,oBAACC,0BAASA;QAAC,OAAO;YAAE,OAAO;YAAI,QAAQ;YAAI,OAAO;QAAU;SAAQ;AAKrF,MAAMC,sBAAsB,CAAC,EAAEC,WAAW,EAAEC,UAAU,EAAEC,QAAQ,EAAEC,QAAQ,EAAS;IACtF,MAAM,CAACC,MAAMC,QAAQ,GAAGC,SAAS;IACjC,MAAMT,WAAWG,YAAY,IAAI,CAACO,CAAAA,IAAKA,EAAE,EAAE,KAAKN,eAAe;IAC/D,MAAMO,QAAQX,WAAWA,SAAS,IAAI,GAAG;IAEzC,MAAMY,UAAU,WAAVA,GACF,oBAAC;QACG,MAAK;QACL,OAAO;YACH,SAAS;YACT,YAAY;YACZ,KAAK;YACL,QAAQ;YACR,OAAO;YACP,YAAY;YACZ,cAAc;YACd,SAAS;YACT,YAAY;YACZ,QAAQ;QACZ;qBAEA,oBAACC,gBAAWA;QAAC,OAAO;YAAE,OAAO;YAAI,QAAQ;YAAI,MAAM;QAAe;QACjEF,OAAAA,WAAAA,GACD,oBAACG,gCAAeA;QAAC,OAAO;YAAE,OAAO;YAAI,QAAQ;YAAI,MAAM;QAAe;;IAI9E,OAAO,WAAP,GACI,oBAACC,cAAYA;QACT,MAAMR;QACN,cAAcC;QACd,SAASI;QACT,OAAO;YAAE,UAAU;QAAI;qBAEvB,oBAACG,aAAa,KAAK;QAAC,MAAK;sBACzB,oBAACA,aAAa,IAAI;QACd,oBAAM,oBAACC,2BAASA;YAAC,OAAO;gBAAE,OAAO;gBAAI,QAAQ;YAAG;;QAChD,oBACI,oBAACpB,KAAGA;YACA,OAAM;YACN,UAAS;YACT,UAAUQ,AAAe,SAAfA;;QAGlB,SAAS,IAAMC,SAAS;sBAE5B,oBAACU,aAAa,SAAS,uBACvB,oBAACA,aAAa,KAAK;QAAC,MAAK;QACxBZ,YAAY,GAAG,CAACc,CAAAA,aAAAA,WAAAA,GACb,oBAACF,aAAa,IAAI;YACd,KAAKE,WAAW,EAAE;YAClB,oBAAM,oBAAC1B,KAAGA;gBAAC,OAAO0B,AAAsB,aAAtBA,WAAW,MAAM,GAAgB,YAAY;;YAC/D,oBACI,oBAACrB,KAAGA;gBACA,OAAOqB,WAAW,IAAI;gBACtB,qBAAO,oBAACxB,aAAWA;oBAAC,QAAQwB,WAAW,MAAM;;gBAC7C,UAAUb,eAAea,WAAW,EAAE;;YAG9C,SAAS,IAAMZ,SAASY,WAAW,EAAE;2BAG7C,oBAACF,aAAa,SAAS,uBACvB,oBAACA,aAAa,IAAI;QACd,oBAAM,oBAACG,yBAAQA;YAAC,OAAO;gBAAE,OAAO;gBAAI,QAAQ;YAAG;;QAC/C,MAAK;QACL,SAASZ;;AAIzB"}
@@ -0,0 +1,3 @@
1
+ export declare const ExperimentsEditorPresenterFeature: import("@webiny/feature/admin").FeatureDefinition<{
2
+ presenter: import("./index.js").IExperimentsEditorPresenter;
3
+ }, []>;
@@ -0,0 +1,21 @@
1
+ import { createFeature } from "@webiny/feature/admin";
2
+ import { ExperimentsFeature } from "../../../features/experiments/index.js";
3
+ import { ExperimentsEditorPresenter } from "./abstractions/ExperimentsEditorPresenter.js";
4
+ import { ExperimentsEditorPresenter as external_ExperimentsEditorPresenter_js_ExperimentsEditorPresenter } from "./ExperimentsEditorPresenter.js";
5
+ import { ExperimentsEditorDataSource } from "./ExperimentsEditorDataSource.js";
6
+ const ExperimentsEditorPresenterFeature = createFeature({
7
+ name: "WebsiteBuilder/ExperimentsEditorPresenter",
8
+ register (container) {
9
+ ExperimentsFeature.register(container);
10
+ container.register(ExperimentsEditorDataSource).inSingletonScope();
11
+ container.register(external_ExperimentsEditorPresenter_js_ExperimentsEditorPresenter).inSingletonScope();
12
+ },
13
+ resolve (container) {
14
+ return {
15
+ presenter: container.resolve(ExperimentsEditorPresenter)
16
+ };
17
+ }
18
+ });
19
+ export { ExperimentsEditorPresenterFeature };
20
+
21
+ //# sourceMappingURL=feature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presentation/experiments/ExperimentsEditor/feature.js","sources":["../../../../src/presentation/experiments/ExperimentsEditor/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/admin\";\nimport { ExperimentsFeature } from \"~/features/experiments/index.js\";\nimport { ExperimentsEditorPresenter as PresenterAbstraction } from \"./abstractions/ExperimentsEditorPresenter.js\";\nimport { ExperimentsEditorPresenter } from \"./ExperimentsEditorPresenter.js\";\nimport { ExperimentsEditorDataSource } from \"./ExperimentsEditorDataSource.js\";\n\nexport const ExperimentsEditorPresenterFeature = createFeature({\n name: \"WebsiteBuilder/ExperimentsEditorPresenter\",\n register(container) {\n ExperimentsFeature.register(container);\n container.register(ExperimentsEditorDataSource).inSingletonScope();\n container.register(ExperimentsEditorPresenter).inSingletonScope();\n },\n resolve(container) {\n return { presenter: container.resolve(PresenterAbstraction) };\n }\n});\n"],"names":["ExperimentsEditorPresenterFeature","createFeature","container","ExperimentsFeature","ExperimentsEditorDataSource","ExperimentsEditorPresenter","PresenterAbstraction"],"mappings":";;;;;AAMO,MAAMA,oCAAoCC,cAAc;IAC3D,MAAM;IACN,UAASC,SAAS;QACdC,mBAAmB,QAAQ,CAACD;QAC5BA,UAAU,QAAQ,CAACE,6BAA6B,gBAAgB;QAChEF,UAAU,QAAQ,CAACG,mEAA4B,gBAAgB;IACnE;IACA,SAAQH,SAAS;QACb,OAAO;YAAE,WAAWA,UAAU,OAAO,CAACI;QAAsB;IAChE;AACJ"}
@@ -0,0 +1,4 @@
1
+ export { ExperimentsEditorPresenter } from "./abstractions/ExperimentsEditorPresenter.js";
2
+ export type { IExperimentsEditorPresenter, IExperimentsEditorViewModel, VariantOption } from "./abstractions/ExperimentsEditorPresenter.js";
3
+ export { ExperimentsEditorDataSource } from "./abstractions/ExperimentsEditorDataSource.js";
4
+ export { ExperimentsEditorPresenterFeature } from "./feature.js";
@@ -0,0 +1,3 @@
1
+ export { ExperimentsEditorPresenter } from "./abstractions/ExperimentsEditorPresenter.js";
2
+ export { ExperimentsEditorDataSource } from "./abstractions/ExperimentsEditorDataSource.js";
3
+ export { ExperimentsEditorPresenterFeature } from "./feature.js";
@@ -0,0 +1,39 @@
1
+ import { ExperimentsGateway } from "../../../features/experiments/index.js";
2
+ import type { ExperimentDto } from "../../../features/experiments/index.js";
3
+ import type { NewExperimentPayload } from "../ExperimentForm/abstractions/ExperimentFormPresenter.js";
4
+ import { ExperimentsEditorPresenter } from "../ExperimentsEditor/index.js";
5
+ import { type IExperimentsManagerPresenter, type IExperimentsManagerViewModel } from "./abstractions/ExperimentsManagerPresenter.js";
6
+ /**
7
+ * Owns the manage drawer's view state (open/view/editTarget) and the per-experiment variant
8
+ * summaries the cards render. All domain actions are delegated to the editor hub presenter, which
9
+ * remains the single source of truth for the page's experiments and their lifecycle.
10
+ */
11
+ declare class ExperimentsManagerPresenterImpl implements IExperimentsManagerPresenter {
12
+ private readonly hub;
13
+ private readonly gateway;
14
+ private view;
15
+ private editInitial;
16
+ private variantsByExperiment;
17
+ private disposers;
18
+ constructor(hub: ExperimentsEditorPresenter.Interface, gateway: ExperimentsGateway.Interface);
19
+ private get experiments();
20
+ private get cards();
21
+ get vm(): IExperimentsManagerViewModel;
22
+ init(): void;
23
+ dispose(): void;
24
+ /** Load the variants for every listed experiment so the cards render as pure observers. */
25
+ private loadCardVariants;
26
+ showList(): void;
27
+ showCreate(): void;
28
+ startEdit(experiment: ExperimentDto): Promise<void>;
29
+ close(): void;
30
+ createExperiment(payload: NewExperimentPayload): Promise<void>;
31
+ updateExperiment(payload: NewExperimentPayload): Promise<void>;
32
+ activateExperiment(experiment: ExperimentDto): Promise<void>;
33
+ deactivateExperiment(experiment: ExperimentDto): Promise<void>;
34
+ deleteExperiment(experiment: ExperimentDto): Promise<void>;
35
+ }
36
+ export declare const ExperimentsManagerPresenter: typeof ExperimentsManagerPresenterImpl & {
37
+ __abstraction: import("@webiny/di").Abstraction<IExperimentsManagerPresenter>;
38
+ };
39
+ export {};
@@ -0,0 +1,219 @@
1
+ import { computed, makeAutoObservable, reaction, runInAction } from "mobx";
2
+ import slugify from "slugify";
3
+ import { ExperimentsGateway } from "../../../features/experiments/index.js";
4
+ import { bucketColor } from "../shared/variantColors.js";
5
+ import { ExperimentsEditorPresenter } from "../ExperimentsEditor/index.js";
6
+ import { ExperimentsManagerPresenter } from "./abstractions/ExperimentsManagerPresenter.js";
7
+ const BAND_COLORS = [
8
+ "#4f46e5",
9
+ "#0f9d58",
10
+ "#c2410c",
11
+ "#1f2937",
12
+ "#0891b2"
13
+ ];
14
+ const toKey = (value)=>slugify(value, {
15
+ lower: true,
16
+ strict: true
17
+ });
18
+ class ExperimentsManagerPresenterImpl {
19
+ constructor(hub, gateway){
20
+ this.hub = hub;
21
+ this.gateway = gateway;
22
+ this.view = "list";
23
+ this.editInitial = null;
24
+ this.variantsByExperiment = {};
25
+ this.disposers = [];
26
+ makeAutoObservable(this, {
27
+ vm: computed,
28
+ hub: false,
29
+ gateway: false
30
+ });
31
+ }
32
+ get experiments() {
33
+ return this.hub.vm.experiments;
34
+ }
35
+ get cards() {
36
+ return this.experiments.map((experiment)=>{
37
+ const variants = this.variantsByExperiment[experiment.id] ?? [];
38
+ const active = "running" === experiment.status;
39
+ const split = experiment.trafficSplit ?? {
40
+ control: 0,
41
+ variants: {}
42
+ };
43
+ const buckets = [
44
+ {
45
+ key: "control",
46
+ name: "Control",
47
+ weight: split.control ?? 0,
48
+ dot: bucketColor(true, 0),
49
+ band: BAND_COLORS[0],
50
+ isControl: true
51
+ },
52
+ ...variants.map((variant, index)=>({
53
+ key: variant.entryId,
54
+ name: variant.name,
55
+ weight: split.variants?.[variant.entryId] ?? 0,
56
+ dot: bucketColor(false, index),
57
+ band: BAND_COLORS[(index + 1) % BAND_COLORS.length],
58
+ isControl: false
59
+ }))
60
+ ];
61
+ return {
62
+ experiment,
63
+ active,
64
+ buckets,
65
+ variantCount: Object.keys(split.variants ?? {}).length
66
+ };
67
+ });
68
+ }
69
+ get vm() {
70
+ return {
71
+ open: this.hub.vm.drawerOpen,
72
+ view: this.view,
73
+ editTarget: this.hub.vm.editTarget,
74
+ editInitial: this.editInitial,
75
+ experiments: this.experiments,
76
+ pageEntryId: this.hub.vm.pageEntryId,
77
+ baselineRevisionId: this.hub.vm.baselineRevisionId,
78
+ cards: this.cards
79
+ };
80
+ }
81
+ init() {
82
+ this.disposers.push(reaction(()=>({
83
+ open: this.hub.vm.drawerOpen,
84
+ editTarget: this.hub.vm.editTarget
85
+ }), ({ open, editTarget })=>{
86
+ if (!open) return;
87
+ if (editTarget) this.startEdit(editTarget);
88
+ else runInAction(()=>{
89
+ this.view = "list";
90
+ this.editInitial = null;
91
+ });
92
+ }, {
93
+ fireImmediately: true
94
+ }));
95
+ this.disposers.push(reaction(()=>this.experiments.map((experiment)=>experiment.id), ()=>this.loadCardVariants(), {
96
+ fireImmediately: true
97
+ }));
98
+ }
99
+ dispose() {
100
+ this.disposers.forEach((dispose)=>dispose());
101
+ this.disposers = [];
102
+ }
103
+ loadCardVariants() {
104
+ for (const experiment of this.experiments)this.gateway.listVariants(experiment.id).then((list)=>{
105
+ runInAction(()=>{
106
+ this.variantsByExperiment = {
107
+ ...this.variantsByExperiment,
108
+ [experiment.id]: list
109
+ };
110
+ });
111
+ }).catch(()=>{
112
+ runInAction(()=>{
113
+ this.variantsByExperiment = {
114
+ ...this.variantsByExperiment,
115
+ [experiment.id]: []
116
+ };
117
+ });
118
+ });
119
+ }
120
+ showList() {
121
+ this.view = "list";
122
+ this.editInitial = null;
123
+ }
124
+ showCreate() {
125
+ this.view = "create";
126
+ }
127
+ async startEdit(experiment) {
128
+ const variants = await this.gateway.listVariants(experiment.id);
129
+ const split = experiment.trafficSplit ?? {
130
+ control: 100,
131
+ variants: {}
132
+ };
133
+ const buckets = [
134
+ {
135
+ id: "control",
136
+ isControl: true,
137
+ name: "Control",
138
+ key: "control",
139
+ keyEdited: true,
140
+ description: "",
141
+ weight: split.control ?? 0
142
+ },
143
+ ...variants.map((variant)=>({
144
+ id: variant.entryId,
145
+ isControl: false,
146
+ name: variant.name,
147
+ key: toKey(variant.name),
148
+ keyEdited: true,
149
+ description: "",
150
+ weight: split.variants?.[variant.entryId] ?? 0,
151
+ revisionId: variant.id
152
+ }))
153
+ ];
154
+ runInAction(()=>{
155
+ this.editInitial = {
156
+ name: experiment.name,
157
+ key: experiment.analytics?.experimentKey ?? "",
158
+ buckets
159
+ };
160
+ this.view = "edit";
161
+ });
162
+ }
163
+ close() {
164
+ this.hub.closeDrawer();
165
+ }
166
+ async createExperiment(payload) {
167
+ await this.hub.createExperiment(payload);
168
+ await this.hub.reload();
169
+ runInAction(()=>{
170
+ this.view = "list";
171
+ });
172
+ }
173
+ async updateExperiment(payload) {
174
+ const editTarget = this.hub.vm.editTarget;
175
+ if (!editTarget) return;
176
+ const variantSplit = {};
177
+ for (const variant of payload.variants)variantSplit[variant.id] = variant.weight;
178
+ await this.hub.updateExperiment(editTarget.id, {
179
+ name: payload.name,
180
+ analytics: {
181
+ provider: "posthog",
182
+ experimentKey: payload.key
183
+ },
184
+ trafficSplit: {
185
+ control: payload.control.weight,
186
+ variants: variantSplit
187
+ }
188
+ });
189
+ for (const variant of payload.variants)if (variant.revisionId) await this.hub.saveVariant(variant.revisionId, {
190
+ name: variant.name
191
+ });
192
+ await this.hub.reload();
193
+ runInAction(()=>{
194
+ this.view = "list";
195
+ });
196
+ }
197
+ async activateExperiment(experiment) {
198
+ await this.hub.activate(experiment.id);
199
+ await this.hub.reload();
200
+ }
201
+ async deactivateExperiment(experiment) {
202
+ await this.hub.deactivate(experiment.id);
203
+ await this.hub.reload();
204
+ }
205
+ async deleteExperiment(experiment) {
206
+ await this.hub.deleteExperiment(experiment.id);
207
+ await this.hub.reload();
208
+ }
209
+ }
210
+ const ExperimentsManagerPresenter_ExperimentsManagerPresenter = ExperimentsManagerPresenter.createImplementation({
211
+ implementation: ExperimentsManagerPresenterImpl,
212
+ dependencies: [
213
+ ExperimentsEditorPresenter,
214
+ ExperimentsGateway
215
+ ]
216
+ });
217
+ export { ExperimentsManagerPresenter_ExperimentsManagerPresenter as ExperimentsManagerPresenter };
218
+
219
+ //# sourceMappingURL=ExperimentsManagerPresenter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presentation/experiments/ExperimentsManager/ExperimentsManagerPresenter.js","sources":["../../../../src/presentation/experiments/ExperimentsManager/ExperimentsManagerPresenter.ts"],"sourcesContent":["import { makeAutoObservable, computed, reaction, runInAction, type IReactionDisposer } from \"mobx\";\nimport slugify from \"slugify\";\nimport { ExperimentsGateway } from \"~/features/experiments/index.js\";\nimport type { ExperimentDto, VariantDto } from \"~/features/experiments/index.js\";\nimport type {\n ExperimentFormInitial,\n NewExperimentPayload\n} from \"../ExperimentForm/abstractions/ExperimentFormPresenter.js\";\nimport { bucketColor } from \"../shared/variantColors.js\";\nimport { ExperimentsEditorPresenter } from \"../ExperimentsEditor/index.js\";\nimport {\n ExperimentsManagerPresenter as Abstraction,\n type ExperimentCardViewModel,\n type ExperimentsManagerView,\n type IExperimentsManagerPresenter,\n type IExperimentsManagerViewModel\n} from \"./abstractions/ExperimentsManagerPresenter.js\";\n\n// Decorative \"hero band\" colours for the mini page previews (unrelated to bucket dot colours).\nconst BAND_COLORS = [\"#4f46e5\", \"#0f9d58\", \"#c2410c\", \"#1f2937\", \"#0891b2\"];\n\nconst toKey = (value: string): string => slugify(value, { lower: true, strict: true });\n\n/**\n * Owns the manage drawer's view state (open/view/editTarget) and the per-experiment variant\n * summaries the cards render. All domain actions are delegated to the editor hub presenter, which\n * remains the single source of truth for the page's experiments and their lifecycle.\n */\nclass ExperimentsManagerPresenterImpl implements IExperimentsManagerPresenter {\n private view: ExperimentsManagerView = \"list\";\n private editInitial: ExperimentFormInitial | null = null;\n // Variants keyed by experiment id, loaded for the listed experiments so cards need no fetching.\n private variantsByExperiment: Record<string, VariantDto[]> = {};\n private disposers: IReactionDisposer[] = [];\n\n constructor(\n private readonly hub: ExperimentsEditorPresenter.Interface,\n // Read-only variant listing for card summaries and the edit form; all mutations go via the hub.\n private readonly gateway: ExperimentsGateway.Interface\n ) {\n makeAutoObservable<this, \"hub\" | \"gateway\">(this, {\n vm: computed,\n hub: false,\n gateway: false\n });\n }\n\n private get experiments(): ExperimentDto[] {\n return this.hub.vm.experiments;\n }\n\n private get cards(): ExperimentCardViewModel[] {\n return this.experiments.map(experiment => {\n const variants = this.variantsByExperiment[experiment.id] ?? [];\n const active = experiment.status === \"running\";\n const split = experiment.trafficSplit ?? { control: 0, variants: {} };\n\n const buckets = [\n {\n key: \"control\",\n name: \"Control\",\n weight: split.control ?? 0,\n dot: bucketColor(true, 0),\n band: BAND_COLORS[0],\n isControl: true\n },\n ...variants.map((variant, index) => ({\n key: variant.entryId,\n name: variant.name,\n weight: split.variants?.[variant.entryId] ?? 0,\n dot: bucketColor(false, index),\n band: BAND_COLORS[(index + 1) % BAND_COLORS.length],\n isControl: false\n }))\n ];\n\n return {\n experiment,\n active,\n buckets,\n variantCount: Object.keys(split.variants ?? {}).length\n };\n });\n }\n\n get vm(): IExperimentsManagerViewModel {\n return {\n open: this.hub.vm.drawerOpen,\n view: this.view,\n editTarget: this.hub.vm.editTarget,\n editInitial: this.editInitial,\n experiments: this.experiments,\n pageEntryId: this.hub.vm.pageEntryId,\n baselineRevisionId: this.hub.vm.baselineRevisionId,\n cards: this.cards\n };\n }\n\n init(): void {\n // Reset the drawer whenever it opens: jump straight to editing when asked, otherwise the\n // list. Mirrors the old drawer's open effect, now reading the hub's drawer state.\n this.disposers.push(\n reaction(\n () => ({ open: this.hub.vm.drawerOpen, editTarget: this.hub.vm.editTarget }),\n ({ open, editTarget }) => {\n if (!open) {\n return;\n }\n if (editTarget) {\n this.startEdit(editTarget);\n } else {\n runInAction(() => {\n this.view = \"list\";\n this.editInitial = null;\n });\n }\n },\n { fireImmediately: true }\n )\n );\n\n // Load per-experiment variant summaries for the cards whenever the experiment set changes.\n this.disposers.push(\n reaction(\n () => this.experiments.map(experiment => experiment.id),\n () => this.loadCardVariants(),\n { fireImmediately: true }\n )\n );\n }\n\n dispose(): void {\n this.disposers.forEach(dispose => dispose());\n this.disposers = [];\n }\n\n /** Load the variants for every listed experiment so the cards render as pure observers. */\n private loadCardVariants(): void {\n for (const experiment of this.experiments) {\n this.gateway\n .listVariants(experiment.id)\n .then(list => {\n runInAction(() => {\n this.variantsByExperiment = {\n ...this.variantsByExperiment,\n [experiment.id]: list\n };\n });\n })\n .catch(() => {\n runInAction(() => {\n this.variantsByExperiment = {\n ...this.variantsByExperiment,\n [experiment.id]: []\n };\n });\n });\n }\n }\n\n showList(): void {\n this.view = \"list\";\n this.editInitial = null;\n }\n\n showCreate(): void {\n this.view = \"create\";\n }\n\n async startEdit(experiment: ExperimentDto): Promise<void> {\n const variants = await this.gateway.listVariants(experiment.id);\n const split = experiment.trafficSplit ?? { control: 100, variants: {} };\n const buckets = [\n {\n id: \"control\",\n isControl: true,\n name: \"Control\",\n key: \"control\",\n keyEdited: true,\n description: \"\",\n weight: split.control ?? 0\n },\n ...variants.map(variant => ({\n id: variant.entryId,\n isControl: false,\n name: variant.name,\n key: toKey(variant.name),\n keyEdited: true,\n description: \"\",\n weight: split.variants?.[variant.entryId] ?? 0,\n revisionId: variant.id\n }))\n ];\n runInAction(() => {\n this.editInitial = {\n name: experiment.name,\n key: (experiment.analytics?.experimentKey as string | undefined) ?? \"\",\n buckets\n };\n this.view = \"edit\";\n });\n }\n\n close(): void {\n this.hub.closeDrawer();\n }\n\n async createExperiment(payload: NewExperimentPayload): Promise<void> {\n await this.hub.createExperiment(payload);\n await this.hub.reload();\n runInAction(() => {\n this.view = \"list\";\n });\n }\n\n async updateExperiment(payload: NewExperimentPayload): Promise<void> {\n const editTarget = this.hub.vm.editTarget;\n if (!editTarget) {\n return;\n }\n const variantSplit: Record<string, number> = {};\n for (const variant of payload.variants) {\n variantSplit[variant.id] = variant.weight;\n }\n await this.hub.updateExperiment(editTarget.id, {\n name: payload.name,\n analytics: { provider: \"posthog\", experimentKey: payload.key },\n trafficSplit: { control: payload.control.weight, variants: variantSplit }\n });\n for (const variant of payload.variants) {\n if (variant.revisionId) {\n await this.hub.saveVariant(variant.revisionId, { name: variant.name });\n }\n }\n await this.hub.reload();\n runInAction(() => {\n this.view = \"list\";\n });\n }\n\n async activateExperiment(experiment: ExperimentDto): Promise<void> {\n await this.hub.activate(experiment.id);\n await this.hub.reload();\n }\n\n async deactivateExperiment(experiment: ExperimentDto): Promise<void> {\n await this.hub.deactivate(experiment.id);\n await this.hub.reload();\n }\n\n async deleteExperiment(experiment: ExperimentDto): Promise<void> {\n await this.hub.deleteExperiment(experiment.id);\n await this.hub.reload();\n }\n}\n\nexport const ExperimentsManagerPresenter = Abstraction.createImplementation({\n implementation: ExperimentsManagerPresenterImpl,\n dependencies: [ExperimentsEditorPresenter, ExperimentsGateway]\n});\n"],"names":["BAND_COLORS","toKey","value","slugify","ExperimentsManagerPresenterImpl","hub","gateway","makeAutoObservable","computed","experiment","variants","active","split","buckets","bucketColor","variant","index","Object","reaction","open","editTarget","runInAction","dispose","list","payload","variantSplit","ExperimentsManagerPresenter","Abstraction","ExperimentsEditorPresenter","ExperimentsGateway"],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import type { ExperimentDto } from "../../../../features/experiments/index.js";
2
+ import type { ExperimentFormInitial, NewExperimentPayload } from "../../ExperimentForm/abstractions/ExperimentFormPresenter.js";
3
+ /** Which view the drawer is currently showing. */
4
+ export type ExperimentsManagerView = "list" | "create" | "edit";
5
+ /** A single bucket (control or variant) summarised for a card's thumbnails/traffic bar/legend. */
6
+ export interface ExperimentCardBucket {
7
+ key: string;
8
+ name: string;
9
+ weight: number;
10
+ dot: string;
11
+ band: string;
12
+ isControl: boolean;
13
+ }
14
+ /** Per-experiment summary used to render a card without any per-card data loading. */
15
+ export interface ExperimentCardViewModel {
16
+ experiment: ExperimentDto;
17
+ active: boolean;
18
+ buckets: ExperimentCardBucket[];
19
+ variantCount: number;
20
+ }
21
+ export interface IExperimentsManagerViewModel {
22
+ open: boolean;
23
+ view: ExperimentsManagerView;
24
+ editTarget: ExperimentDto | null;
25
+ editInitial: ExperimentFormInitial | null;
26
+ experiments: ExperimentDto[];
27
+ pageEntryId: string;
28
+ baselineRevisionId: string;
29
+ cards: ExperimentCardViewModel[];
30
+ }
31
+ export interface IExperimentsManagerPresenter {
32
+ readonly vm: IExperimentsManagerViewModel;
33
+ init(): void;
34
+ dispose(): void;
35
+ showList(): void;
36
+ showCreate(): void;
37
+ startEdit(experiment: ExperimentDto): Promise<void>;
38
+ close(): void;
39
+ createExperiment(payload: NewExperimentPayload): Promise<void>;
40
+ updateExperiment(payload: NewExperimentPayload): Promise<void>;
41
+ activateExperiment(experiment: ExperimentDto): Promise<void>;
42
+ deactivateExperiment(experiment: ExperimentDto): Promise<void>;
43
+ deleteExperiment(experiment: ExperimentDto): Promise<void>;
44
+ }
45
+ export declare const ExperimentsManagerPresenter: import("@webiny/di").Abstraction<IExperimentsManagerPresenter>;
46
+ export declare namespace ExperimentsManagerPresenter {
47
+ type Interface = IExperimentsManagerPresenter;
48
+ type ViewModel = IExperimentsManagerViewModel;
49
+ type View = ExperimentsManagerView;
50
+ type Card = ExperimentCardViewModel;
51
+ type CardBucket = ExperimentCardBucket;
52
+ }
@@ -0,0 +1,5 @@
1
+ import { createAbstraction } from "@webiny/feature/admin";
2
+ const ExperimentsManagerPresenter = createAbstraction("WebsiteBuilder/ExperimentsManager/Presenter");
3
+ export { ExperimentsManagerPresenter };
4
+
5
+ //# sourceMappingURL=ExperimentsManagerPresenter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presentation/experiments/ExperimentsManager/abstractions/ExperimentsManagerPresenter.js","sources":["../../../../../src/presentation/experiments/ExperimentsManager/abstractions/ExperimentsManagerPresenter.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/admin\";\nimport type { ExperimentDto } from \"~/features/experiments/index.js\";\nimport type {\n ExperimentFormInitial,\n NewExperimentPayload\n} from \"../../ExperimentForm/abstractions/ExperimentFormPresenter.js\";\n\n/** Which view the drawer is currently showing. */\nexport type ExperimentsManagerView = \"list\" | \"create\" | \"edit\";\n\n/** A single bucket (control or variant) summarised for a card's thumbnails/traffic bar/legend. */\nexport interface ExperimentCardBucket {\n key: string;\n name: string;\n weight: number;\n dot: string;\n band: string;\n isControl: boolean;\n}\n\n/** Per-experiment summary used to render a card without any per-card data loading. */\nexport interface ExperimentCardViewModel {\n experiment: ExperimentDto;\n active: boolean;\n buckets: ExperimentCardBucket[];\n variantCount: number;\n}\n\nexport interface IExperimentsManagerViewModel {\n // Drawer visibility (driven by the hub presenter's manage/edit entry points).\n open: boolean;\n // Which sub-view the drawer is showing.\n view: ExperimentsManagerView;\n // The experiment being edited (null in list/create views).\n editTarget: ExperimentDto | null;\n // Initial form values for the edit view (null until loaded).\n editInitial: ExperimentFormInitial | null;\n // The page's experiments (mirrored from the hub presenter).\n experiments: ExperimentDto[];\n pageEntryId: string;\n baselineRevisionId: string;\n // Card summaries (variant thumbnails/traffic/legend), one per listed experiment.\n cards: ExperimentCardViewModel[];\n}\n\nexport interface IExperimentsManagerPresenter {\n readonly vm: IExperimentsManagerViewModel;\n init(): void;\n dispose(): void;\n showList(): void;\n showCreate(): void;\n startEdit(experiment: ExperimentDto): Promise<void>;\n close(): void;\n createExperiment(payload: NewExperimentPayload): Promise<void>;\n updateExperiment(payload: NewExperimentPayload): Promise<void>;\n activateExperiment(experiment: ExperimentDto): Promise<void>;\n deactivateExperiment(experiment: ExperimentDto): Promise<void>;\n deleteExperiment(experiment: ExperimentDto): Promise<void>;\n}\n\nexport const ExperimentsManagerPresenter = createAbstraction<IExperimentsManagerPresenter>(\n \"WebsiteBuilder/ExperimentsManager/Presenter\"\n);\n\nexport namespace ExperimentsManagerPresenter {\n export type Interface = IExperimentsManagerPresenter;\n export type ViewModel = IExperimentsManagerViewModel;\n export type View = ExperimentsManagerView;\n export type Card = ExperimentCardViewModel;\n export type CardBucket = ExperimentCardBucket;\n}\n"],"names":["ExperimentsManagerPresenter","createAbstraction"],"mappings":";AA4DO,MAAMA,8BAA8BC,kBACvC"}
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ import type { ExperimentCardViewModel, IExperimentsManagerPresenter } from "../abstractions/ExperimentsManagerPresenter.js";
3
+ interface Props {
4
+ presenter: IExperimentsManagerPresenter;
5
+ card: ExperimentCardViewModel;
6
+ }
7
+ export declare const ExperimentCard: (({ presenter, card }: Props) => React.JSX.Element) & React.NamedExoticComponent<Props> & {
8
+ readonly type: ({ presenter, card }: Props) => React.JSX.Element;
9
+ };
10
+ export {};