@griddo/ax 10.4.7 → 10.4.8

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 (45) hide show
  1. package/package.json +2 -2
  2. package/src/__tests__/components/Browser/Browser.test.tsx +4 -4
  3. package/src/__tests__/components/Fields/ComponentArray/MixableComponentArray/MixableComponentArray.test.tsx +39 -7
  4. package/src/__tests__/components/Fields/ComponentArray/MixableComponentArray/PasteModuleButton/PasteModuleButton.test.tsx +8 -8
  5. package/src/__tests__/components/Fields/ComponentContainer/ComponentContainer.test.tsx +28 -16
  6. package/src/components/Browser/index.tsx +5 -5
  7. package/src/components/BulkSelectionOptions/style.tsx +1 -0
  8. package/src/components/ConfigPanel/Header/index.tsx +8 -4
  9. package/src/components/Fields/AsyncCheckGroup/style.tsx +3 -0
  10. package/src/components/Fields/CheckField/index.tsx +4 -1
  11. package/src/components/Fields/CheckField/style.tsx +19 -3
  12. package/src/components/Fields/CheckGroup/index.tsx +3 -2
  13. package/src/components/Fields/CheckGroup/style.tsx +3 -0
  14. package/src/components/Fields/ComponentArray/MixableComponentArray/BulkHeader/index.tsx +47 -0
  15. package/src/components/Fields/ComponentArray/MixableComponentArray/BulkHeader/style.tsx +44 -0
  16. package/src/components/Fields/ComponentArray/MixableComponentArray/PasteModuleButton/index.tsx +31 -12
  17. package/src/components/Fields/ComponentArray/MixableComponentArray/index.tsx +153 -59
  18. package/src/components/Fields/ComponentArray/SameComponentArray/index.tsx +1 -1
  19. package/src/components/Fields/ComponentArray/helpers.tsx +45 -4
  20. package/src/components/Fields/ComponentContainer/EmptyContainer/index.tsx +2 -2
  21. package/src/components/Fields/ComponentContainer/index.tsx +68 -33
  22. package/src/components/Fields/ComponentContainer/style.tsx +78 -11
  23. package/src/components/Fields/ReferenceField/Context/index.tsx +1 -1
  24. package/src/components/MainWrapper/AppBar/atoms.tsx +5 -8
  25. package/src/components/SideModal/SideModalOption/index.tsx +5 -3
  26. package/src/containers/Navigation/Defaults/actions.tsx +86 -55
  27. package/src/containers/Navigation/Defaults/interfaces.tsx +2 -2
  28. package/src/containers/Navigation/Defaults/reducer.tsx +3 -3
  29. package/src/containers/PageEditor/actions.tsx +142 -109
  30. package/src/containers/PageEditor/interfaces.tsx +1 -1
  31. package/src/containers/PageEditor/reducer.tsx +2 -2
  32. package/src/containers/PageEditor/utils.tsx +1 -1
  33. package/src/containers/Settings/DataPacks/actions.tsx +7 -2
  34. package/src/forms/elements.tsx +20 -14
  35. package/src/hooks/bulk.tsx +57 -2
  36. package/src/hooks/iframe.ts +5 -5
  37. package/src/modules/Content/index.tsx +10 -1
  38. package/src/modules/FramePreview/index.tsx +4 -4
  39. package/src/modules/GlobalEditor/Editor/index.tsx +6 -6
  40. package/src/modules/GlobalEditor/PageBrowser/index.tsx +2 -2
  41. package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/index.tsx +6 -6
  42. package/src/modules/PageEditor/Editor/index.tsx +7 -7
  43. package/src/modules/PageEditor/PageBrowser/index.tsx +2 -2
  44. package/src/modules/Users/UserForm/index.tsx +52 -34
  45. package/src/types/index.tsx +1 -0
@@ -1,14 +1,14 @@
1
- import React from "react";
2
- import differenceInSeconds from "date-fns/differenceInSeconds";
3
- import { DragDropContext, Droppable, Draggable, DropResult } from "react-beautiful-dnd";
1
+ import React, { useEffect, useState } from "react";
2
+ import { DragDropContext, Droppable, Draggable, DropResult, BeforeCapture } from "react-beautiful-dnd";
4
3
 
5
- import { IModule } from "@ax/types";
6
- import { ComponentContainer, SideModal } from "@ax/components";
7
- import { useModal } from "@ax/hooks";
4
+ import { IModule, INotification, ISchemaField } from "@ax/types";
5
+ import { ComponentContainer, SideModal, Toast } from "@ax/components";
6
+ import { useBulkSelection, useModal, useToast } from "@ax/hooks";
8
7
 
9
- import { getComponentProps, containerToComponentArray, getTypefromKey } from "../helpers";
8
+ import { getComponentProps, containerToComponentArray, getTypefromKey, getModulesToPaste } from "../helpers";
10
9
  import AddItemButton from "./AddItemButton";
11
10
  import PasteModuleButton from "./PasteModuleButton";
11
+ import BulkHeader from "./BulkHeader";
12
12
 
13
13
  import * as S from "./style";
14
14
 
@@ -35,36 +35,45 @@ const MixableComponentArray = (props: IMixableComponentArrayProps): JSX.Element
35
35
  setHistoryPush,
36
36
  } = props;
37
37
 
38
- const moduleCopyComponent = moduleCopy?.element.component;
38
+ const {
39
+ addModuleAction,
40
+ addComponentAction,
41
+ deleteModuleAction,
42
+ replaceElementsInCollectionAction,
43
+ pasteModuleAction,
44
+ setNotificationAction,
45
+ copyModuleAction,
46
+ duplicateModuleAction,
47
+ } = actions || {};
39
48
 
40
- const availableDataPackModule = availableDataPacks?.reduce((prev: any, curr: any) => {
41
- const packModule = curr.modules.find((module: any) => module.id === moduleCopyComponent);
42
- return prev || packModule;
43
- }, null);
49
+ // fix for old not array values
50
+ const fixedValue = Array.isArray(value) ? value : containerToComponentArray(value);
51
+ const componentIDs: number[] = fixedValue.map((element: any) => element.editorID);
44
52
 
45
- const isModuleCopyUnavailable =
46
- availableDataPackModule &&
47
- !whiteList.includes(moduleCopyComponent) &&
48
- !!availableDataPackModule?.sectionList[template.component]?.includes(field.key);
53
+ const { modulesToPaste, unavailableModules } = getModulesToPaste(
54
+ moduleCopy,
55
+ whiteList,
56
+ availableDataPacks,
57
+ template,
58
+ field
59
+ );
49
60
 
50
61
  const type = getTypefromKey(objKey);
51
62
  const { contentType = type } = field;
52
63
  const { isOpen, toggleModal } = useModal();
64
+ const [isBulkOpen, setIsBulkOpen] = useState(false);
65
+ const [draggingId, setDraggingId] = useState<number | null>(null);
66
+ const { isVisible, toggleToast, setIsVisible, state: toastState } = useToast();
53
67
 
54
- let addModuleAction: any;
55
- let addComponentAction: any;
56
- let deleteModuleAction: any;
57
- let replaceElementsInCollectionAction: any;
58
-
59
- if (actions) {
60
- addModuleAction = actions.addModuleAction;
61
- addComponentAction = actions.addComponentAction;
62
- deleteModuleAction = actions.deleteModuleAction;
63
- replaceElementsInCollectionAction = actions.replaceElementsInCollectionAction;
64
- }
68
+ const { resetBulkSelection, selectedItems, isSelected, checkState, addToBulkSelection, selectAllItems } =
69
+ useBulkSelection(componentIDs);
65
70
 
66
- // fix for old not array values
67
- const fixedValue = Array.isArray(value) ? value : containerToComponentArray(value);
71
+ useEffect(() => {
72
+ if (selectedItems.all.length) {
73
+ setIsBulkOpen(true);
74
+ }
75
+ // eslint-disable-next-line react-hooks/exhaustive-deps
76
+ }, [selectedItems.all]);
68
77
 
69
78
  const getText = (name: string, index: number) => {
70
79
  return fixedValue.length > 1 ? `#${index + 1} ${name}` : name;
@@ -73,7 +82,8 @@ const MixableComponentArray = (props: IMixableComponentArrayProps): JSX.Element
73
82
  const isComponentModule = contentType === "components";
74
83
  const isModuleArr = contentType === "modules";
75
84
 
76
- const handleAddModule = (moduleType: string) => addModuleAction(moduleType, objKey, editorID, isComponentModule);
85
+ const handleAddModule = (moduleType: string) =>
86
+ addModuleAction && addModuleAction(moduleType, objKey, editorID, isComponentModule);
77
87
 
78
88
  const handleAddComponent = (componentType: string) => addComponentAction && addComponentAction(componentType, objKey);
79
89
 
@@ -81,27 +91,23 @@ const MixableComponentArray = (props: IMixableComponentArrayProps): JSX.Element
81
91
 
82
92
  const handleModuleReplace = (moduleType: string) => {
83
93
  const { modules } = selectedContent;
84
- if (isModuleArr) {
85
- const currentModule = modules[0];
86
- deleteModuleAction(currentModule?.editorID, contentType);
94
+ if (isModuleArr && deleteModuleAction && modules?.length > 0) {
95
+ const currentModule: IModule = modules[0];
96
+ deleteModuleAction([currentModule.editorID], contentType);
87
97
  handleAddModule(moduleType);
88
98
  } else {
89
- replaceElementsInCollectionAction(moduleType);
99
+ replaceElementsInCollectionAction && replaceElementsInCollectionAction(moduleType);
90
100
  }
91
101
  };
92
102
 
93
- const getTimeSinceModuleCopy = (moduleCopy: { date: string; element: Record<string, any> }) =>
94
- differenceInSeconds(new Date(), new Date(moduleCopy.date));
103
+ const selectItems = () => (checkState.isAllSelected ? resetBulkSelection() : selectAllItems());
95
104
 
96
105
  const showAddItemButton = (!maxItems || fixedValue.length < maxItems) && !disabled;
97
- const eightHoursInSeconds = 8 * 60 * 60;
98
106
 
99
- const showPasteModuleButton: boolean =
107
+ const showPasteModuleButton =
100
108
  showAddItemButton &&
101
109
  (isModuleArr || objKey === "componentModules") &&
102
- !!moduleCopy &&
103
- getTimeSinceModuleCopy(moduleCopy) < eightHoursInSeconds &&
104
- (whiteList.includes(moduleCopyComponent) || isModuleCopyUnavailable);
110
+ (modulesToPaste.length > 0 || unavailableModules.length > 0);
105
111
 
106
112
  const canReplace = maxItems === 1 && whiteList.length > 1;
107
113
  const displayReplaceSideModal = fixedValue.length > 0 && canReplace;
@@ -110,7 +116,7 @@ const MixableComponentArray = (props: IMixableComponentArrayProps): JSX.Element
110
116
  const Asterisk = () => (mandatory ? <S.Asterisk>*</S.Asterisk> : null);
111
117
 
112
118
  const ComponentList = React.memo(function ComponentList({ components }: any) {
113
- return components.map((element: any, i: number) => {
119
+ return components.map((element: IModule, i: number) => {
114
120
  const { editorID } = element;
115
121
  const { moduleTitle, isModuleDeactivated, componentTitle, displayName, isModule } = getComponentProps(
116
122
  element,
@@ -118,9 +124,14 @@ const MixableComponentArray = (props: IMixableComponentArrayProps): JSX.Element
118
124
  isModuleArr
119
125
  );
120
126
  const text = getText(componentTitle || displayName, i);
127
+ const isItemSelected = isSelected(editorID);
128
+ const isDraggingSelected = selectedItems.all.includes(draggingId);
129
+ const isGhosting = isItemSelected && !!draggingId && draggingId !== editorID && isDraggingSelected;
130
+ const isMultiDragging = selectedItems.all.length > 1 && draggingId === editorID;
131
+
121
132
  return (
122
133
  <Draggable draggableId={`${editorID}`} index={i} key={editorID}>
123
- {(provided) => (
134
+ {(provided, snapshot) => (
124
135
  <ComponentContainer
125
136
  actionReplace={toggleModal}
126
137
  canReplace={canReplace}
@@ -142,6 +153,13 @@ const MixableComponentArray = (props: IMixableComponentArrayProps): JSX.Element
142
153
  innerRef={provided.innerRef}
143
154
  provided={provided}
144
155
  isModule={isModule}
156
+ isSelected={isItemSelected}
157
+ onChange={addToBulkSelection}
158
+ hasMenu={selectedItems.all.length > 0}
159
+ toggleToast={toggleToast}
160
+ isMultiDragging={snapshot.isDragging && isMultiDragging}
161
+ draggingCount={selectedItems.all.length}
162
+ className={`${isGhosting ? "ghosting" : ""} ${snapshot.isDragging && isMultiDragging ? "dragging" : ""}`}
145
163
  />
146
164
  )}
147
165
  </Draggable>
@@ -150,17 +168,69 @@ const MixableComponentArray = (props: IMixableComponentArrayProps): JSX.Element
150
168
  });
151
169
 
152
170
  const onDragEnd = (result: DropResult) => {
153
- const { moveModuleAction } = actions;
171
+ const { moveModuleAction } = actions || {};
154
172
 
155
- if (!result.destination) {
173
+ if (!moveModuleAction || !result.destination || result.destination.index === result.source.index) {
174
+ setDraggingId(null);
156
175
  return;
157
176
  }
158
177
 
159
- if (result.destination.index === result.source.index) {
160
- return;
178
+ if (selectedItems.all.length > 0 && selectedItems.all.includes(parseInt(result.draggableId))) {
179
+ moveModuleAction(selectedItems.all, selectedContent, result.destination.index, objKey);
180
+ } else {
181
+ moveModuleAction([parseInt(result.draggableId)], selectedContent, result.destination.index, objKey);
182
+ }
183
+
184
+ setDraggingId(null);
185
+ };
186
+
187
+ const onBeforeCapture = (start: BeforeCapture) => setDraggingId(parseInt(start.draggableId));
188
+
189
+ const handleCopy = () => {
190
+ const isCopied = copyModuleAction && copyModuleAction(selectedItems.all);
191
+ isCopied &&
192
+ toggleToast(`${selectedItems.all.length} module${selectedItems.all.length > 1 ? "s" : ""} copied to clipboard`);
193
+ };
194
+
195
+ const handleDuplicate = () => {
196
+ if (maxItems && maxItems - fixedValue.length < selectedItems.all.length) {
197
+ const notification: INotification = {
198
+ type: "error",
199
+ text: "Unable to duplicate modules: The destination area has a limit on the number of modules allowed. Please adjust the selection accordingly.",
200
+ };
201
+ setNotificationAction && setNotificationAction(notification);
202
+ } else {
203
+ duplicateModuleAction && duplicateModuleAction(selectedItems.all, objKey);
204
+ resetBulkSelection();
161
205
  }
206
+ };
162
207
 
163
- moveModuleAction(parseInt(result.draggableId), selectedContent, result.destination.index, objKey);
208
+ const handleDelete = () => {
209
+ deleteModuleAction && deleteModuleAction(selectedItems.all, objKey);
210
+ resetBulkSelection();
211
+ };
212
+
213
+ const bulkActions = [
214
+ {
215
+ icon: "copy",
216
+ text: "copy",
217
+ action: handleCopy,
218
+ },
219
+ {
220
+ icon: "duplicate",
221
+ text: "duplicate",
222
+ action: handleDuplicate,
223
+ },
224
+ {
225
+ icon: "delete",
226
+ text: "delete",
227
+ action: handleDelete,
228
+ },
229
+ ];
230
+
231
+ const toggleBulk = () => {
232
+ setIsBulkOpen(false);
233
+ resetBulkSelection();
164
234
  };
165
235
 
166
236
  return (
@@ -169,16 +239,28 @@ const MixableComponentArray = (props: IMixableComponentArrayProps): JSX.Element
169
239
  {title} <Asterisk />
170
240
  </S.Title>
171
241
  <S.ItemRow>
172
- <S.Subtitle>{fixedValue && fixedValue.length} items</S.Subtitle>
242
+ {isBulkOpen ? (
243
+ <BulkHeader
244
+ selectItems={selectItems}
245
+ checkState={checkState}
246
+ totalItems={selectedItems.all.length}
247
+ toggleBulk={toggleBulk}
248
+ actions={bulkActions}
249
+ />
250
+ ) : (
251
+ <S.Subtitle>{fixedValue?.length || 0} items</S.Subtitle>
252
+ )}
173
253
  <S.ActionsWrapper data-testid="mixableComponentWrapper">
174
- {showPasteModuleButton && (
254
+ {showPasteModuleButton && pasteModuleAction && (
175
255
  <PasteModuleButton
176
256
  editorID={editorID}
177
- isModuleCopyUnavailable={isModuleCopyUnavailable}
178
- pasteModule={actions.pasteModuleAction}
179
- setNotification={actions.setNotificationAction}
257
+ isModuleCopyUnavailable={unavailableModules.length > 0}
258
+ pasteModule={pasteModuleAction}
259
+ setNotification={setNotificationAction}
180
260
  setHistoryPush={setHistoryPush}
181
261
  arrayKey={objKey}
262
+ modulesToPaste={modulesToPaste}
263
+ slots={maxItems ? maxItems - fixedValue.length : null}
182
264
  />
183
265
  )}
184
266
  {showAddItemButton && !disabled && (
@@ -195,7 +277,7 @@ const MixableComponentArray = (props: IMixableComponentArrayProps): JSX.Element
195
277
  </S.ActionsWrapper>
196
278
  </S.ItemRow>
197
279
  {fixedValue && (
198
- <DragDropContext onDragEnd={onDragEnd}>
280
+ <DragDropContext onDragEnd={onDragEnd} onBeforeCapture={onBeforeCapture}>
199
281
  <Droppable droppableId="list">
200
282
  {(provided) => (
201
283
  <div ref={provided.innerRef} {...provided.droppableProps}>
@@ -218,27 +300,39 @@ const MixableComponentArray = (props: IMixableComponentArrayProps): JSX.Element
218
300
  showSearch
219
301
  />
220
302
  )}
303
+ {isVisible && <Toast message={toastState} setIsVisible={setIsVisible} />}
221
304
  </S.Wrapper>
222
305
  );
223
306
  };
224
307
 
225
308
  export interface IMixableComponentArrayProps {
226
- maxItems: number;
309
+ maxItems?: number;
227
310
  title: string;
228
- whiteList: any[];
311
+ whiteList: string[];
229
312
  value?: IModule[];
230
313
  selectedContent: any;
231
314
  editorID: number;
232
315
  goTo: (editorID: string) => void;
233
- actions: any;
316
+ actions?: {
317
+ addComponentAction: (componentType: any, key?: string) => void;
318
+ addModuleAction: (moduleType: string, key: string, selectedID: number, isComponentModule?: boolean) => void;
319
+ deleteModuleAction: (editorID: number[], key?: string) => void;
320
+ duplicateModuleAction: (editorID: number[], key?: string) => number;
321
+ copyModuleAction: (editorID: number[]) => boolean;
322
+ replaceElementsInCollectionAction: (newValue: string, reference?: string) => void;
323
+ moveModuleAction: (moduleID: number[], selectedContent: any, newIndex: number, key: string) => void;
324
+ pasteModuleAction: (editorID: number, key: string, modulesToPaste: IModule[]) => Promise<{ error?: INotification }>;
325
+ setNotificationAction: (notification: INotification) => void;
326
+ replaceModuleAction: (module: any, parent: any, objKey: string) => void;
327
+ };
234
328
  categories?: any;
235
329
  disabled?: boolean;
236
330
  activatedModules: string[];
237
331
  objKey: string;
238
- field: any;
332
+ field: ISchemaField;
239
333
  mandatory?: boolean;
240
334
  theme: string;
241
- moduleCopy: { date: string; element: Record<string, any> } | null;
335
+ moduleCopy: { date: Date; elements: IModule[] } | null;
242
336
  availableDataPacks: Record<string, any>[];
243
337
  template: any;
244
338
  setHistoryPush?: (path: string, isEditor: boolean) => void;
@@ -69,7 +69,7 @@ const SameComponentArray = (props: ISameComponentArrayProps): JSX.Element => {
69
69
  return;
70
70
  }
71
71
 
72
- moveModuleAction(parseInt(result.draggableId), selectedContent, result.destination.index, objKey);
72
+ moveModuleAction([parseInt(result.draggableId)], selectedContent, result.destination.index, objKey);
73
73
  };
74
74
 
75
75
  const ComponentList = React.memo(function ComponentList({ components }: any) {
@@ -1,5 +1,6 @@
1
+ import differenceInSeconds from "date-fns/differenceInSeconds";
1
2
  import { getSchema, getDisplayName, getSchemaType, isComponentEmpty } from "@ax/helpers";
2
- import { IComponent } from "@ax/types";
3
+ import { IComponent, IModule, ISchemaField } from "@ax/types";
3
4
 
4
5
  const getComponentTitle = (component: string, title: any) => {
5
6
  if (!title) return;
@@ -13,7 +14,7 @@ const getComponentTitle = (component: string, title: any) => {
13
14
  return defaultTitle === title ? displayName : title;
14
15
  };
15
16
 
16
- const getComponentProps = (element: any, activatedModules: string[], isModuleArr: boolean) => {
17
+ const getComponentProps = (element: IModule, activatedModules: string[], isModuleArr: boolean) => {
17
18
  const { component } = element;
18
19
  const schemaType = getSchemaType(component);
19
20
  const displayName = getDisplayName(component);
@@ -27,7 +28,7 @@ const getComponentProps = (element: any, activatedModules: string[], isModuleArr
27
28
  };
28
29
 
29
30
  const containerToComponentArray = (value?: Record<string, IComponent>): IComponent[] =>
30
- value ? Object.values(value).filter((item: IComponent) => !isComponentEmpty(item)): [];
31
+ value ? Object.values(value).filter((item: IComponent) => !isComponentEmpty(item)) : [];
31
32
 
32
33
  const getTypefromKey = (key: string) => {
33
34
  switch (key) {
@@ -41,4 +42,44 @@ const getTypefromKey = (key: string) => {
41
42
  }
42
43
  };
43
44
 
44
- export { getComponentTitle, getComponentProps, containerToComponentArray, getTypefromKey };
45
+ const getTimeSinceModuleCopy = (moduleCopy: { date: Date; elements: IModule[] }) =>
46
+ differenceInSeconds(new Date(), new Date(moduleCopy.date));
47
+
48
+ const getModulesToPaste = (
49
+ moduleCopy: { date: Date; elements: IModule[] } | null,
50
+ whiteList: string[],
51
+ availableDataPacks: Record<string, any>[],
52
+ template: any,
53
+ field: ISchemaField
54
+ ) => {
55
+ const modulesToPaste: IModule[] = [];
56
+ const unavailableModules: IModule[] = [];
57
+ const eightHoursInSeconds = 8 * 60 * 60;
58
+
59
+ if (moduleCopy && getTimeSinceModuleCopy(moduleCopy) < eightHoursInSeconds) {
60
+ moduleCopy.elements.forEach((element) => {
61
+ const { component } = element;
62
+
63
+ const availableDataPackModule = availableDataPacks?.reduce((prev: any, curr: any) => {
64
+ const packModule = curr.modules.find((module: any) => module.id === component);
65
+ return prev || packModule;
66
+ }, null);
67
+
68
+ if (
69
+ availableDataPackModule &&
70
+ !whiteList.includes(component) &&
71
+ !!availableDataPackModule?.sectionList[template.component]?.includes(field.key)
72
+ ) {
73
+ unavailableModules.push(element);
74
+ }
75
+
76
+ if (whiteList.includes(component)) {
77
+ modulesToPaste.push(element);
78
+ }
79
+ });
80
+ }
81
+
82
+ return { modulesToPaste, unavailableModules };
83
+ };
84
+
85
+ export { getComponentTitle, getComponentProps, containerToComponentArray, getTypefromKey, getModulesToPaste };
@@ -33,11 +33,11 @@ const EmptyContainer = (props: IProps) => {
33
33
  interface IProps {
34
34
  hasMultipleOptions: boolean | undefined;
35
35
  whiteList: any[] | undefined;
36
- goTo?: any;
36
+ goTo: () => void;
37
37
  componentOptions: any;
38
38
  title?: string;
39
39
  categories?: any;
40
- handleAdd: any;
40
+ handleAdd: (option: any) => void;
41
41
  theme: string;
42
42
  }
43
43
 
@@ -1,9 +1,10 @@
1
1
  import React from "react";
2
2
  import { DraggableProvided } from "react-beautiful-dnd";
3
3
 
4
- import { useModal, useToast } from "@ax/hooks";
4
+ import { useModal } from "@ax/hooks";
5
5
  import { isEmptyContainer, getDisplayName, trimText } from "@ax/helpers";
6
- import { Icon, SideModal, Toast } from "@ax/components";
6
+ import { CheckField, Icon, SideModal } from "@ax/components";
7
+ import { ICheck } from "@ax/types";
7
8
  import EmptyContainer from "./EmptyContainer";
8
9
  import { ArrayContainerButtons, ContainerButtons } from "./atoms";
9
10
 
@@ -33,19 +34,19 @@ const ComponentContainer = (props: IComponentContainerProps): JSX.Element => {
33
34
  innerRef,
34
35
  provided,
35
36
  isModule,
37
+ isSelected,
38
+ onChange,
39
+ hasMenu = true,
40
+ toggleToast,
41
+ className,
42
+ isMultiDragging = false,
43
+ draggingCount = 0,
36
44
  } = props;
37
45
 
38
- const { isVisible, toggleToast, setIsVisible } = useToast();
46
+ const { addComponentAction, deleteModuleAction, duplicateModuleAction, copyModuleAction, replaceModuleAction } =
47
+ actions || {};
39
48
 
40
- let deleteModuleAction: any;
41
- let duplicateModuleAction: any;
42
- let copyModuleAction: any;
43
-
44
- if (actions) {
45
- deleteModuleAction = actions.deleteModuleAction;
46
- duplicateModuleAction = actions.duplicateModuleAction;
47
- copyModuleAction = actions.copyModuleAction;
48
- }
49
+ const { isOpen, toggleModal } = useModal();
49
50
 
50
51
  const whiteListFirstItem: any = whiteList && whiteList[0];
51
52
  const hasMultipleOptions: boolean | undefined = whiteList && whiteList.length > 1;
@@ -66,21 +67,21 @@ const ComponentContainer = (props: IComponentContainerProps): JSX.Element => {
66
67
  componentID = currentComponent.componentID;
67
68
  }
68
69
 
69
- const { isOpen, toggleModal } = useModal();
70
-
71
- const handleEmptyContainerClick = () => actions.addComponentAction && actions.addComponentAction(value);
72
-
73
70
  const handleClick = () => {
74
71
  if (!disabled) {
75
72
  goTo(componentID);
76
73
  }
77
74
  };
78
75
 
79
- const removeItem = () => deleteModuleAction(editorID, parentKey);
80
- const duplicateItem = () => parentKey && duplicateModuleAction(editorID, parentKey);
76
+ const handleCheckClick = (e: React.MouseEvent<HTMLDivElement>) => e.stopPropagation();
77
+
78
+ const removeItem = () => deleteModuleAction && deleteModuleAction([editorID], parentKey);
79
+
80
+ const duplicateItem = () => parentKey && duplicateModuleAction && duplicateModuleAction([editorID], parentKey);
81
+
81
82
  const copyItem = () => {
82
- const isCopied = copyModuleAction(editorID);
83
- isCopied && toggleToast();
83
+ const isCopied = copyModuleAction && copyModuleAction([editorID]);
84
+ isCopied && toggleToast && toggleToast("1 module copied to clipboard");
84
85
  };
85
86
 
86
87
  const copyOpt = {
@@ -124,16 +125,38 @@ const ComponentContainer = (props: IComponentContainerProps): JSX.Element => {
124
125
 
125
126
  const actionMenuIcon = "more";
126
127
 
127
- const handleOptionClick = (option: any) => actions.addComponentAction(option);
128
+ const handleEmptyContainerClick = () => {
129
+ if (addComponentAction) addComponentAction(value);
130
+ };
131
+
132
+ const handleOptionClick = (option: any) => {
133
+ if (addComponentAction) addComponentAction(option);
134
+ };
128
135
 
129
136
  const compoundKey = parentKey ? `${parentKey}.${objKey}` : objKey;
130
- const handleReplace = (option: any) => actions.replaceModuleAction(option, selectedContent, compoundKey);
137
+ const handleReplace = (option: any) =>
138
+ compoundKey && replaceModuleAction && replaceModuleAction(option, selectedContent, compoundKey);
131
139
 
132
140
  const arrayContainerButtonsProps = {
133
141
  options: actionArrayMenuOptions,
134
142
  icon: actionMenuIcon,
135
143
  };
136
144
 
145
+ const handleChange = (value: ICheck) => onChange && onChange(value);
146
+
147
+ const textComponents = isMultiDragging ? (
148
+ <S.LabelDrag>
149
+ Dragging <span>{draggingCount}</span> modules
150
+ </S.LabelDrag>
151
+ ) : (
152
+ <>
153
+ <S.Label containerInfo={containerInfo} disabled={disabled}>
154
+ {trimText(containerText, 25)}
155
+ </S.Label>
156
+ {moduleTitle && <S.Title disabled={disabled}>{trimText(moduleTitle, 25)}</S.Title>}
157
+ </>
158
+ );
159
+
137
160
  return isEmpty ? (
138
161
  <EmptyContainer
139
162
  whiteList={whiteList}
@@ -149,7 +172,7 @@ const ComponentContainer = (props: IComponentContainerProps): JSX.Element => {
149
172
  <>
150
173
  <S.Component
151
174
  disabled={disabled}
152
- className={`editorId-${editorID}`}
175
+ className={`editorId-${editorID} ${className}`}
153
176
  onClick={handleClick}
154
177
  ref={innerRef}
155
178
  data-testid="component-container"
@@ -162,18 +185,18 @@ const ComponentContainer = (props: IComponentContainerProps): JSX.Element => {
162
185
  </S.IconHandleWrapper>
163
186
  </S.HandleWrapper>
164
187
  )}
188
+ {isArray && !isMultiDragging && arrayLength > 1 && (
189
+ <S.CheckWrapper onClick={handleCheckClick}>
190
+ <CheckField name="check" value={editorID} checked={isSelected} onChange={handleChange} light={true} />
191
+ </S.CheckWrapper>
192
+ )}
165
193
  {containerInfo && !disabled && (
166
194
  <S.IconWrapper data-testid="icon-wrapper">
167
195
  <Icon name={containerText} />
168
196
  </S.IconWrapper>
169
197
  )}
170
- <S.Text>
171
- <S.Label containerInfo={containerInfo} disabled={disabled}>
172
- {trimText(containerText, 35)}
173
- </S.Label>
174
- {moduleTitle && <S.Title disabled={disabled}>{trimText(moduleTitle, 35)}</S.Title>}
175
- </S.Text>
176
- {isArray && !disabled && <ArrayContainerButtons {...arrayContainerButtonsProps} />}
198
+ <S.Text>{textComponents}</S.Text>
199
+ {isArray && !disabled && !hasMenu && <ArrayContainerButtons {...arrayContainerButtonsProps} />}
177
200
  {!isArray && !disabled && hasMultipleOptions && (
178
201
  <ContainerButtons options={actionMenuOptions} icon={actionMenuIcon} />
179
202
  )}
@@ -191,7 +214,6 @@ const ComponentContainer = (props: IComponentContainerProps): JSX.Element => {
191
214
  theme={theme}
192
215
  />
193
216
  )}
194
- {isVisible && <Toast message="1 module copied to clipboard" setIsVisible={setIsVisible} />}
195
217
  </>
196
218
  );
197
219
  };
@@ -199,7 +221,7 @@ const ComponentContainer = (props: IComponentContainerProps): JSX.Element => {
199
221
  export interface IComponentContainerProps {
200
222
  text: string;
201
223
  editorID: number;
202
- whiteList: any[] | undefined;
224
+ whiteList: string[] | undefined;
203
225
  categories?: any[];
204
226
  goTo: any;
205
227
  isArray?: boolean | undefined;
@@ -208,7 +230,13 @@ export interface IComponentContainerProps {
208
230
  moduleTitle?: string;
209
231
  selectedContent?: any;
210
232
  objKey?: string;
211
- actions: any;
233
+ actions?: {
234
+ addComponentAction: (componentType: any, key?: string) => void;
235
+ deleteModuleAction: (editorID: number[], key?: string) => void;
236
+ duplicateModuleAction: (editorID: number[], key?: string) => number;
237
+ copyModuleAction: (editorID: number[]) => boolean;
238
+ replaceModuleAction: (module: any, parent: any, objKey: string) => void;
239
+ };
212
240
  disabled?: boolean;
213
241
  canDuplicate?: boolean;
214
242
  parentKey?: string;
@@ -219,6 +247,13 @@ export interface IComponentContainerProps {
219
247
  innerRef?: any;
220
248
  provided?: DraggableProvided;
221
249
  isModule?: boolean;
250
+ isSelected?: boolean;
251
+ onChange?: (value: ICheck) => void;
252
+ hasMenu?: boolean;
253
+ toggleToast?: (state: string) => void;
254
+ className?: string;
255
+ isMultiDragging?: boolean;
256
+ draggingCount?: number;
222
257
  }
223
258
 
224
259
  export default ComponentContainer;