@griddo/ax 11.4.23 → 11.4.24

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 (36) hide show
  1. package/package.json +4 -4
  2. package/src/__tests__/components/Fields/ComponentContainer/ComponentContainer.test.tsx +10 -52
  3. package/src/components/ActionMenu/index.tsx +3 -2
  4. package/src/components/Fields/CheckField/style.tsx +16 -16
  5. package/src/components/Fields/ComponentArray/MixableComponentArray/index.tsx +65 -49
  6. package/src/components/Fields/ComponentArray/SameComponentArray/index.tsx +89 -69
  7. package/src/components/Fields/ComponentContainer/index.tsx +11 -11
  8. package/src/components/Fields/ComponentContainer/style.tsx +12 -4
  9. package/src/components/Fields/ReferenceField/ItemList/Item/index.tsx +19 -9
  10. package/src/components/Fields/ReferenceField/ItemList/Item/style.tsx +24 -13
  11. package/src/components/Fields/ReferenceField/ItemList/index.tsx +59 -41
  12. package/src/containers/StructuredData/actions.tsx +1 -1
  13. package/src/modules/Categories/CategoriesList/CategoryItem/index.tsx +71 -43
  14. package/src/modules/Categories/CategoriesList/CategoryItem/style.tsx +9 -1
  15. package/src/modules/Categories/CategoriesList/CategoryNav/index.tsx +0 -1
  16. package/src/modules/Categories/CategoriesList/CategoryPanel/index.tsx +1 -0
  17. package/src/modules/Categories/CategoriesList/helpers.tsx +135 -94
  18. package/src/modules/Categories/CategoriesList/index.tsx +153 -157
  19. package/src/modules/Categories/CategoriesList/style.tsx +0 -3
  20. package/src/modules/FileDrive/FolderTree/MenuItem/index.tsx +83 -0
  21. package/src/modules/FileDrive/FolderTree/MenuItem/style.tsx +69 -0
  22. package/src/modules/FileDrive/FolderTree/MenuList/index.tsx +26 -0
  23. package/src/modules/FileDrive/FolderTree/index.tsx +12 -58
  24. package/src/modules/FileDrive/FolderTree/style.tsx +6 -27
  25. package/src/modules/Forms/FormCategoriesList/CategoryItem/index.tsx +11 -17
  26. package/src/modules/Forms/FormCategoriesList/CategoryItem/style.tsx +4 -1
  27. package/src/modules/Forms/FormCategoriesList/index.tsx +68 -53
  28. package/src/modules/Navigation/Menus/List/Table/Item/index.tsx +45 -16
  29. package/src/modules/Navigation/Menus/List/Table/Item/style.tsx +8 -3
  30. package/src/modules/Navigation/Menus/List/Table/helpers.tsx +132 -74
  31. package/src/modules/Navigation/Menus/List/Table/index.tsx +119 -86
  32. package/src/modules/Settings/Integrations/IntegrationItem/index.tsx +11 -11
  33. package/src/modules/Settings/Integrations/IntegrationItem/style.tsx +9 -1
  34. package/src/modules/Settings/Integrations/index.tsx +59 -56
  35. package/src/types/index.tsx +4 -5
  36. package/src/modules/FileDrive/FolderTree/utils.tsx +0 -91
@@ -1,5 +1,6 @@
1
1
  import React, { useState } from "react";
2
2
  import { connect } from "react-redux";
3
+ import { AnimateLayoutChanges, useSortable } from "@dnd-kit/sortable";
3
4
 
4
5
  import { structuredDataActions } from "@ax/containers/StructuredData";
5
6
  import { useModal, usePermission } from "@ax/hooks";
@@ -25,11 +26,12 @@ const CategoryItem = (props: ICategoryItemProps): JSX.Element => {
25
26
  toggleToast,
26
27
  getContents,
27
28
  currentSiteID,
28
- dragHandleProps,
29
- icon,
30
29
  deleteCategoryGroup,
31
30
  hoverCheck,
32
- isDragging,
31
+ depth,
32
+ indentationWidth,
33
+ collapsed,
34
+ onCollapse,
33
35
  } = props;
34
36
 
35
37
  const { isOpen, toggleModal } = useModal();
@@ -49,6 +51,15 @@ const CategoryItem = (props: ICategoryItemProps): JSX.Element => {
49
51
  const allowedToEditTaxonomy = currentSiteID ? allowedToEditSiteCategory : allowedToEditGlobalCategory;
50
52
  const allowedToDeleteTaxonomy = currentSiteID ? allowedToDeleteSiteCategory : allowedToDeleteGlobalCategory;
51
53
 
54
+ const animateLayoutChanges: AnimateLayoutChanges = ({ isSorting, wasDragging }) =>
55
+ isSorting || wasDragging ? false : true;
56
+
57
+ const { attributes, isDragging, listeners, setDraggableNodeRef, setDroppableNodeRef, transform, transition } =
58
+ useSortable({
59
+ id: category.id,
60
+ animateLayoutChanges,
61
+ });
62
+
52
63
  const { locale } = lang;
53
64
  const { dataLanguages = [], content } = category;
54
65
  const isGroup = category.type === "group";
@@ -189,40 +200,56 @@ const CategoryItem = (props: ICategoryItemProps): JSX.Element => {
189
200
 
190
201
  return (
191
202
  <>
192
- <S.CategoryRow role="rowgroup" selected={isSelected} onClick={handleClick} {...dragHandleProps}>
193
- <S.HandleCell>
194
- <S.IconWrapperDrag role="cell">
195
- <Icon name="drag" size="16" />
196
- </S.IconWrapperDrag>
197
- <S.IconWrapper>{icon}</S.IconWrapper>
198
- </S.HandleCell>
199
- <S.CheckCell role="cell" onClick={handleCheckClick}>
200
- <CheckField name="check" value={category.id} checked={isSelected || hoverCheck} onChange={handleOnChange} />
201
- </S.CheckCell>
202
- <S.NameCell role="cell" clickable={allowedToEditTaxonomy} isGroup={isGroup}>
203
- {isGroup && (
204
- <S.FolderWrapper>
205
- <Icon name="project" size="24" />
206
- </S.FolderWrapper>
207
- )}
208
- <div>{content?.title || ""}</div>
209
- </S.NameCell>
210
- <S.CodeCell role="cell" clickable={allowedToEditTaxonomy}>
211
- {isCategory(category) && category.content ? category.content.code : ""}
212
- </S.CodeCell>
213
- <S.SelectableCell role="cell">
214
- <Tag
215
- type="square"
216
- color={selectable ? "" : "#FFD4C7"}
217
- text={selectable ? "Yes" : "No"}
218
- textColor={selectable ? "" : "#20224C"}
219
- />
220
- </S.SelectableCell>
221
- <S.TransCell role="cell">{translations}</S.TransCell>
222
- <S.ActionsCell role="cell">
223
- <S.StyledActionMenu icon="more" options={menuOptions} tooltip="Actions" />
224
- </S.ActionsCell>
225
- </S.CategoryRow>
203
+ <S.Wrapper identationWidth={isDragging ? indentationWidth : indentationWidth * depth} ref={setDroppableNodeRef}>
204
+ <S.CategoryRow
205
+ selected={isSelected}
206
+ onClick={handleClick}
207
+ ref={setDraggableNodeRef}
208
+ cssTransform={transform}
209
+ transition={transition}
210
+ {...listeners}
211
+ {...attributes}
212
+ >
213
+ <S.HandleCell>
214
+ <S.IconWrapperDrag role="cell">
215
+ <Icon name="drag" size="16" />
216
+ </S.IconWrapperDrag>
217
+ <S.IconWrapper onClick={handleCheckClick}>
218
+ {onCollapse && (
219
+ <div onClick={onCollapse} role="button" tabIndex={0} onKeyDown={onCollapse}>
220
+ {collapsed ? <Icon name="UpArrow" /> : <Icon name="DownArrow" />}
221
+ </div>
222
+ )}
223
+ </S.IconWrapper>
224
+ </S.HandleCell>
225
+ <S.CheckCell role="cell" onClick={handleCheckClick}>
226
+ <CheckField name="check" value={category.id} checked={isSelected || hoverCheck} onChange={handleOnChange} />
227
+ </S.CheckCell>
228
+ <S.NameCell role="cell" clickable={allowedToEditTaxonomy} isGroup={isGroup}>
229
+ {isGroup && (
230
+ <S.FolderWrapper>
231
+ <Icon name="project" size="24" />
232
+ </S.FolderWrapper>
233
+ )}
234
+ <div>{content?.title || ""}</div>
235
+ </S.NameCell>
236
+ <S.CodeCell role="cell" clickable={allowedToEditTaxonomy}>
237
+ {isCategory(category) && category.content ? category.content.code : ""}
238
+ </S.CodeCell>
239
+ <S.SelectableCell role="cell">
240
+ <Tag
241
+ type="square"
242
+ color={selectable ? "" : "#FFD4C7"}
243
+ text={selectable ? "Yes" : "No"}
244
+ textColor={selectable ? "" : "#20224C"}
245
+ />
246
+ </S.SelectableCell>
247
+ <S.TransCell role="cell">{translations}</S.TransCell>
248
+ <S.ActionsCell role="cell">
249
+ <S.StyledActionMenu icon="more" options={menuOptions} tooltip="Actions" />
250
+ </S.ActionsCell>
251
+ </S.CategoryRow>
252
+ </S.Wrapper>
226
253
  {isOpen && (
227
254
  <CategoryPanel
228
255
  isOpen={isOpen}
@@ -261,14 +288,15 @@ interface IProps {
261
288
  lang: { locale: string; id: number | null };
262
289
  isTranslatable: boolean;
263
290
  isSelected: boolean;
264
- onChange: (e: any) => void;
265
- toggleToast(state: any): void;
266
- getContents(dataId: string): void;
291
+ onChange: (item: ICheck) => void;
292
+ toggleToast: (state: string) => void;
293
+ getContents: (dataId: string) => void;
267
294
  currentSiteID: number | null;
268
- icon: JSX.Element;
269
- dragHandleProps?: any;
270
295
  hoverCheck?: boolean;
271
- isDragging: boolean;
296
+ depth: number;
297
+ indentationWidth: number;
298
+ collapsed: boolean;
299
+ onCollapse?: () => void;
272
300
  }
273
301
 
274
302
  interface IDispatchProps {
@@ -1,8 +1,13 @@
1
1
  import styled from "styled-components";
2
+ import { CSS, Transform } from "@dnd-kit/utilities";
2
3
 
3
4
  import { Cell, Row } from "@ax/components/TableList/TableItem/style";
4
5
  import { ActionMenu } from "@ax/components";
5
6
 
7
+ const Wrapper = styled.div<{ identationWidth: number }>`
8
+ padding-left: ${(p) => `${p.identationWidth}px`};
9
+ `;
10
+
6
11
  const CheckCell = styled(Cell)`
7
12
  padding-left: 0;
8
13
  padding-right: 0;
@@ -53,7 +58,9 @@ const StyledActionMenu = styled(ActionMenu)`
53
58
  margin-left: auto;
54
59
  `;
55
60
 
56
- const CategoryRow = styled(Row)`
61
+ const CategoryRow = styled(Row)<{ cssTransform: Transform | null; transition?: string }>`
62
+ transform: ${(p) => CSS.Transform.toString(p.cssTransform)};
63
+ transition: ${(p) => p.transition};
57
64
  &:hover {
58
65
  ${StyledActionMenu} {
59
66
  opacity: 1;
@@ -103,6 +110,7 @@ const FolderWrapper = styled.div`
103
110
  `;
104
111
 
105
112
  export {
113
+ Wrapper,
106
114
  CheckCell,
107
115
  NameCell,
108
116
  ActionsCell,
@@ -2,7 +2,6 @@ import React from "react";
2
2
 
3
3
  import { IDataPack, IStructuredData } from "@ax/types";
4
4
  import { SubNav } from "@ax/components";
5
- import { sortBy } from "@ax/helpers";
6
5
  import NavItem from "./NavItem";
7
6
 
8
7
  const CategoryNav = (props: IProps): JSX.Element => {
@@ -78,6 +78,7 @@ const CategoryPanel = (props: IProps): JSX.Element => {
78
78
  }
79
79
 
80
80
  toggleModal();
81
+ setForm(initState);
81
82
  };
82
83
 
83
84
  const editItemAction = async () => {
@@ -1,116 +1,157 @@
1
- import { ItemId, TreeData, TreeItem } from "@atlaskit/tree";
2
- import { isEmptyObj } from "@ax/helpers";
3
1
  import { ICategoryGroup, IStructuredDataCategory } from "@ax/types";
2
+ import type { UniqueIdentifier } from "@dnd-kit/core";
3
+ import { arrayMove } from "@dnd-kit/sortable";
4
4
 
5
- const normalizeItems = (itemList: (IStructuredDataCategory | ICategoryGroup)[], tree: TreeData) => {
6
- const normalized: TreeData = {
7
- rootId: "root",
8
- items: {
9
- root: {
10
- id: "root",
11
- children: [],
12
- hasChildren: true,
13
- isExpanded: true,
14
- isChildrenLoading: false,
15
- },
16
- },
17
- };
18
-
19
- const previousItems: (IStructuredDataCategory | ICategoryGroup)[] = [];
20
- if (!isEmptyObj(tree.items)) {
21
- previousItems.push(...formatTree(tree));
22
- }
5
+ const flatten = (items: TreeItem[], parentId: UniqueIdentifier | null = null, depth = 0): FlattenedItem[] => {
6
+ return items.reduce<FlattenedItem[]>((acc, item, index) => {
7
+ return [...acc, { ...item, parentId, depth, index }, ...flatten(item.children || [], item.id, depth + 1)];
8
+ }, []);
9
+ };
23
10
 
24
- const isItemExpanded = (item: IStructuredDataCategory | ICategoryGroup) => {
25
- if (!item) return true;
26
- return item.isExpanded;
27
- };
28
-
29
- const getElement = (
30
- item: IStructuredDataCategory | ICategoryGroup,
31
- previousItems: IStructuredDataCategory | ICategoryGroup
32
- ) => {
33
- normalized.items[item.id] = {
34
- ...item,
35
- children: [],
36
- isExpanded: isItemExpanded(previousItems),
37
- };
38
- if (item.children && item.children.length > 0) {
39
- item.children.forEach((child: IStructuredDataCategory | ICategoryGroup, index: number) => {
40
- normalized.items[item.id].children.push(child.id);
41
- getElement(child, previousItems?.children[index]);
42
- });
43
- }
44
- };
11
+ const flattenTree = (items: TreeItem[]): FlattenedItem[] => {
12
+ return flatten(items);
13
+ };
45
14
 
46
- itemList.forEach((item: IStructuredDataCategory | ICategoryGroup, index: number) => {
47
- normalized.items.root.children.push(item.id);
48
- getElement(item, previousItems[index]);
49
- });
15
+ const buildTree = (flattenedItems: FlattenedItem[]): TreeItem[] => {
16
+ const root = { id: 0, children: [] };
17
+ const nodes: Record<string, Partial<TreeItem>> = { [root.id]: root };
18
+ const items = flattenedItems.map((item) => ({ ...item, children: [] })) as FlattenedItem[];
50
19
 
51
- return normalized;
52
- };
20
+ for (const item of items) {
21
+ const { id, children } = item;
22
+ const parentId = item.parentId ?? root.id;
23
+ const parent = nodes[parentId] ?? findItem(items, parentId);
53
24
 
54
- const getElementsFromTree = (tree: TreeData): TreeItem[] => {
55
- const { items } = tree;
56
- const elements: TreeItem[] = [];
57
- for (const item of Object.values(items)) {
58
- elements.push(item);
25
+ nodes[id] = { id, children };
26
+ parent.children && parent.children.push(item);
59
27
  }
60
- return elements;
61
- };
62
28
 
63
- const getChild = (child: ItemId, elements: any[]): IStructuredDataCategory | ICategoryGroup => {
64
- const element = elements.find((element: IStructuredDataCategory | ICategoryGroup) => element.id === child);
65
- const children = element?.children.map((child: ItemId) => getChild(child, elements));
66
- return { ...element, children };
29
+ return root.children;
67
30
  };
68
31
 
69
- const formatTree = (tree: TreeData) => {
70
- const elements: TreeItem[] = getElementsFromTree(tree);
32
+ const findItem = (items: FlattenedItem[], itemId: UniqueIdentifier) => {
33
+ return items.find(({ id }) => id === itemId);
34
+ };
71
35
 
72
- const root: any = elements.find((element: TreeItem) => element.id === "root");
73
- const formattedTree = root.children.map((child: ItemId) => {
74
- return getChild(child, elements);
36
+ function getDragDepth(offset: number, indentationWidth: number) {
37
+ return Math.round(offset / indentationWidth);
38
+ }
39
+
40
+ export function getProjection(
41
+ items: FlattenedItem[],
42
+ activeId: UniqueIdentifier,
43
+ overId: UniqueIdentifier,
44
+ dragOffset: number,
45
+ indentationWidth: number
46
+ ) {
47
+ const overItemIndex = items.findIndex(({ id }) => id === overId);
48
+ const activeItemIndex = items.findIndex(({ id }) => id === activeId);
49
+ const activeItem = items[activeItemIndex];
50
+ const newItems = arrayMove(items, activeItemIndex, overItemIndex);
51
+ const previousItem = newItems[overItemIndex - 1];
52
+ const nextItem = newItems[overItemIndex + 1];
53
+ const dragDepth = getDragDepth(dragOffset, indentationWidth);
54
+ const projectedDepth = activeItem.depth + dragDepth;
55
+ const maxDepth = getMaxDepth({
56
+ previousItem,
75
57
  });
58
+ const minDepth = getMinDepth({ nextItem });
59
+ let depth = projectedDepth;
76
60
 
77
- return formattedTree;
78
- };
61
+ if (projectedDepth >= maxDepth) {
62
+ depth = maxDepth;
63
+ } else if (projectedDepth < minDepth) {
64
+ depth = minDepth;
65
+ }
79
66
 
80
- const formatItem = (item: any, tree: TreeData) => {
81
- const elements = getElementsFromTree(tree);
67
+ return { depth, maxDepth, minDepth, parentId: getParentId() };
82
68
 
83
- const formattedItem = {
84
- ...item,
85
- children: item.children.map((child: ItemId) => getChild(child, elements)),
86
- };
69
+ function getParentId() {
70
+ if (depth === 0 || !previousItem) {
71
+ return null;
72
+ }
87
73
 
88
- return formattedItem;
89
- };
74
+ if (depth === previousItem.depth) {
75
+ return previousItem.parentId;
76
+ }
90
77
 
91
- const findChild = (tree: TreeData, child: ItemId) => {
92
- const elements: any[] = getElementsFromTree(tree);
93
- return elements.find((element) => element.id === parseInt(child as string));
94
- };
78
+ if (depth > previousItem.depth) {
79
+ return previousItem.id;
80
+ }
95
81
 
96
- const findChildByIndex = (tree: TreeData, parentId: ItemId, index: number) => {
97
- const elements: any[] = getElementsFromTree(tree);
98
- const parent = elements.find((element) =>
99
- parentId === "root" ? element.id === parentId : element.id === parseInt(parentId as string)
100
- );
101
- const elementID = parent && parent.children[index] ? parent.children[index] : null;
102
- return elementID ? elements.find((element) => element.id === elementID) : undefined;
103
- };
82
+ const newParent = newItems
83
+ .slice(0, overItemIndex)
84
+ .reverse()
85
+ .find((item) => item.depth === depth)?.parentId;
86
+
87
+ return newParent ?? null;
88
+ }
89
+ }
104
90
 
105
- const getIDsFromTree = (dataContent: (IStructuredDataCategory | ICategoryGroup)[]): number[] => {
106
- return dataContent.reduce((acc: number[], current) => {
107
- acc.push(current.id);
108
- const children = getIDsFromTree(current.children || []);
109
- if (children.length) {
110
- acc = [...acc, ...children];
91
+ function getMinDepth({ nextItem }: { nextItem: FlattenedItem }) {
92
+ if (nextItem) {
93
+ return nextItem.depth;
94
+ }
95
+
96
+ return 0;
97
+ }
98
+
99
+ function getMaxDepth({ previousItem }: { previousItem: FlattenedItem }) {
100
+ if (previousItem) {
101
+ return previousItem.depth + 1;
102
+ }
103
+
104
+ return 0;
105
+ }
106
+
107
+ const removeChildrenOf = (items: FlattenedItem[], ids: UniqueIdentifier[]) => {
108
+ const excludeParentIds = [...ids];
109
+
110
+ return items.filter((item) => {
111
+ if (item.parentId && excludeParentIds.includes(item.parentId)) {
112
+ if (item.children && item.children.length) {
113
+ excludeParentIds.push(item.id);
114
+ }
115
+ return false;
111
116
  }
112
- return acc;
113
- }, []);
117
+
118
+ return true;
119
+ });
114
120
  };
115
121
 
116
- export { normalizeItems, formatItem, findChild, findChildByIndex, getElementsFromTree, getIDsFromTree };
122
+ export function setProperty<T extends keyof TreeItem>(
123
+ items: TreeItem[],
124
+ id: UniqueIdentifier,
125
+ property: T,
126
+ setter: (value: TreeItem[T]) => TreeItem[T]
127
+ ) {
128
+ for (const item of items) {
129
+ if (item.id === id) {
130
+ item[property] = setter(item[property]);
131
+ continue;
132
+ }
133
+
134
+ if (item.children && item.children.length) {
135
+ item.children = setProperty(item.children || [], id, property, setter);
136
+ }
137
+ }
138
+
139
+ return [...items];
140
+ }
141
+
142
+ interface FlattenedCategory extends IStructuredDataCategory {
143
+ parentId: UniqueIdentifier | null;
144
+ depth: number;
145
+ index: number;
146
+ }
147
+
148
+ interface FlattenedGroup extends ICategoryGroup {
149
+ parentId: UniqueIdentifier | null;
150
+ depth: number;
151
+ index: number;
152
+ }
153
+
154
+ type TreeItem = IStructuredDataCategory | ICategoryGroup;
155
+ export type FlattenedItem = FlattenedCategory | FlattenedGroup;
156
+
157
+ export { flattenTree, buildTree, removeChildrenOf };