@griddo/ax 10.2.25 → 10.3.0

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 (94) hide show
  1. package/package.json +2 -2
  2. package/public/img/icons/excel.png +0 -0
  3. package/public/img/icons/pdf.png +0 -0
  4. package/public/img/icons/word.png +0 -0
  5. package/public/img/icons/zip.png +0 -0
  6. package/src/GlobalStore.tsx +3 -0
  7. package/src/__mocks__/store/GenericStore.ts +3 -0
  8. package/src/__tests__/components/Fields/FileField/FileField.test.tsx +34 -8
  9. package/src/__tests__/components/Gallery/GalleryPanel/GalleryDragAndDrop/GalleryDragAndDrop.test.tsx +1 -1
  10. package/src/api/files.tsx +171 -1
  11. package/src/api/users.tsx +5 -2
  12. package/src/components/ActionMenu/index.tsx +5 -13
  13. package/src/components/BackFolder/index.tsx +28 -0
  14. package/src/components/BackFolder/style.tsx +33 -0
  15. package/src/components/BulkSelectionOptions/index.tsx +4 -8
  16. package/src/components/Button/index.tsx +8 -3
  17. package/src/components/Button/style.tsx +5 -3
  18. package/src/components/ElementsTooltip/index.tsx +22 -7
  19. package/src/components/ElementsTooltip/style.tsx +2 -2
  20. package/src/components/Fields/FileField/index.tsx +7 -7
  21. package/src/components/Fields/TextField/index.tsx +3 -0
  22. package/src/components/FileGallery/FolderItem/index.tsx +39 -0
  23. package/src/components/FileGallery/FolderItem/style.tsx +31 -0
  24. package/src/components/FileGallery/GalleryPanel/DetailPanel/index.tsx +164 -0
  25. package/src/components/FileGallery/GalleryPanel/DetailPanel/style.tsx +113 -0
  26. package/src/components/FileGallery/GalleryPanel/index.tsx +42 -0
  27. package/src/components/FileGallery/GalleryPanel/style.tsx +7 -0
  28. package/src/components/FileGallery/GridItem/index.tsx +47 -0
  29. package/src/components/FileGallery/GridItem/style.tsx +51 -0
  30. package/src/components/FileGallery/index.tsx +304 -0
  31. package/src/components/FileGallery/style.tsx +173 -0
  32. package/src/components/FileGallery/utils.tsx +19 -0
  33. package/src/components/Gallery/GalleryPanel/GalleryDragAndDrop/index.tsx +4 -6
  34. package/src/components/Icon/components/Back.js +10 -0
  35. package/src/components/Icon/components/ClosePanel.js +12 -0
  36. package/src/components/Icon/components/NewFolder.js +10 -0
  37. package/src/components/Icon/components/OpenPanel.js +12 -0
  38. package/src/components/Icon/svgs/Back.svg +3 -0
  39. package/src/components/Icon/svgs/Close_panel.svg +3 -0
  40. package/src/components/Icon/svgs/New-folder.svg +3 -0
  41. package/src/components/Icon/svgs/Open_panel.svg +3 -0
  42. package/src/components/Modal/index.tsx +7 -5
  43. package/src/components/Modal/style.tsx +6 -6
  44. package/src/components/ProgressBar/index.tsx +3 -2
  45. package/src/components/ProgressBar/style.tsx +5 -3
  46. package/src/components/TableList/index.tsx +3 -2
  47. package/src/components/TableList/style.tsx +4 -0
  48. package/src/components/Toast/style.tsx +2 -2
  49. package/src/components/index.tsx +4 -0
  50. package/src/containers/FileDrive/actions.tsx +386 -0
  51. package/src/containers/FileDrive/constants.tsx +24 -0
  52. package/src/containers/FileDrive/index.tsx +7 -0
  53. package/src/containers/FileDrive/interfaces.tsx +59 -0
  54. package/src/containers/FileDrive/reducer.tsx +57 -0
  55. package/src/containers/FileDrive/utils.tsx +37 -0
  56. package/src/containers/Gallery/actions.tsx +1 -1
  57. package/src/containers/Gallery/interfaces.tsx +1 -1
  58. package/src/helpers/index.tsx +2 -0
  59. package/src/helpers/objects.tsx +6 -0
  60. package/src/modules/FileDrive/Breadcrumb/index.tsx +42 -0
  61. package/src/modules/FileDrive/Breadcrumb/style.tsx +18 -0
  62. package/src/modules/FileDrive/BulkGridHeader/GridHeader/index.tsx +37 -0
  63. package/src/modules/FileDrive/BulkGridHeader/GridHeader/style.tsx +19 -0
  64. package/src/modules/FileDrive/BulkGridHeader/index.tsx +35 -0
  65. package/src/modules/FileDrive/BulkGridHeader/style.tsx +17 -0
  66. package/src/modules/FileDrive/BulkListHeader/TableHeader/index.tsx +42 -0
  67. package/src/modules/FileDrive/BulkListHeader/TableHeader/style.tsx +53 -0
  68. package/src/modules/FileDrive/BulkListHeader/index.tsx +35 -0
  69. package/src/modules/FileDrive/BulkListHeader/style.tsx +17 -0
  70. package/src/modules/FileDrive/FileDragAndDrop/index.tsx +249 -0
  71. package/src/{components/Fields/FileField → modules/FileDrive}/FileDragAndDrop/style.tsx +50 -9
  72. package/src/modules/FileDrive/FileModal/DetailPanel/index.tsx +170 -0
  73. package/src/modules/FileDrive/FileModal/DetailPanel/style.tsx +81 -0
  74. package/src/modules/FileDrive/FileModal/index.tsx +129 -0
  75. package/src/modules/FileDrive/FileModal/style.tsx +112 -0
  76. package/src/modules/FileDrive/FolderItem/index.tsx +180 -0
  77. package/src/modules/FileDrive/FolderItem/style.tsx +39 -0
  78. package/src/modules/FileDrive/FolderTree/index.tsx +108 -0
  79. package/src/modules/FileDrive/FolderTree/style.tsx +69 -0
  80. package/src/modules/FileDrive/FolderTree/utils.tsx +91 -0
  81. package/src/modules/FileDrive/GridItem/index.tsx +167 -0
  82. package/src/modules/FileDrive/GridItem/style.tsx +76 -0
  83. package/src/modules/FileDrive/ListItem/index.tsx +180 -0
  84. package/src/modules/FileDrive/ListItem/style.tsx +88 -0
  85. package/src/modules/FileDrive/atoms.tsx +173 -0
  86. package/src/modules/FileDrive/helpers.tsx +19 -0
  87. package/src/modules/FileDrive/index.tsx +670 -0
  88. package/src/modules/FileDrive/style.tsx +145 -0
  89. package/src/modules/Sites/SitesList/index.tsx +0 -3
  90. package/src/routes/multisite.tsx +9 -0
  91. package/src/routes/site.tsx +9 -0
  92. package/src/types/index.tsx +63 -0
  93. package/src/components/Fields/FileField/FileDragAndDrop/index.tsx +0 -188
  94. package/src/components/Fields/FileField/store.tsx +0 -61
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@griddo/ax",
3
3
  "description": "Griddo Author Experience",
4
- "version": "10.2.25",
4
+ "version": "10.3.0",
5
5
  "authors": [
6
6
  "Álvaro Sánchez' <alvaro.sanches@secuoyas.com>",
7
7
  "Carlos Torres <carlos.torres@secuoyas.com>",
@@ -230,5 +230,5 @@
230
230
  "publishConfig": {
231
231
  "access": "public"
232
232
  },
233
- "gitHead": "648778151f4d044e09a409274b508dd0ae401825"
233
+ "gitHead": "f7da8e919f51b1c424f27d00d78954ec837e84f0"
234
234
  }
Binary file
Binary file
Binary file
Binary file
@@ -20,6 +20,7 @@ import { domainsReducer, domainsInitialState } from "./containers/Domains/reduce
20
20
  import { redirectsReducer, redirectsInitialState } from "./containers/Redirects/reducer";
21
21
  import { analyticsReducer, analyticsInitialState } from "./containers/Analytics/reducer";
22
22
  import { integrationsReducer, integrationsInitialState } from "./containers/Integrations/reducer";
23
+ import { fileDriveReducer, fileDriveInitialState } from "./containers/FileDrive/reducer";
23
24
  import { LOGOUT } from "./containers/App/constants";
24
25
 
25
26
  import { IRootState } from "@ax/types";
@@ -54,6 +55,7 @@ export class GlobalStore {
54
55
  redirects: redirectsReducer as Reducer<any, Action<any>>,
55
56
  analytics: analyticsReducer as Reducer<any, Action<any>>,
56
57
  integrations: integrationsReducer as Reducer<any, Action<any>>,
58
+ fileDrive: fileDriveReducer as Reducer<any, Action<any>>,
57
59
  });
58
60
 
59
61
  const rootReducer = (state: IRootState | undefined, action: any) => {
@@ -75,6 +77,7 @@ export class GlobalStore {
75
77
  redirects: redirectsInitialState,
76
78
  analytics: analyticsInitialState,
77
79
  integrations: integrationsInitialState,
80
+ fileDrive: fileDriveInitialState,
78
81
  };
79
82
  }
80
83
 
@@ -22,4 +22,7 @@ export const defaultStore = {
22
22
  currentPermissions: [],
23
23
  roles: [],
24
24
  },
25
+ app: {
26
+ isLoading: false,
27
+ }
25
28
  };
@@ -3,14 +3,38 @@ import { ThemeProvider } from "styled-components";
3
3
  import { parseTheme } from "@ax/helpers";
4
4
  import globalTheme from "@ax/themes/theme.json";
5
5
  import { mock } from "jest-mock-extended";
6
- import { render, screen, cleanup } from "@testing-library/react";
6
+ import { render, screen, cleanup } from "../../../../../config/jest/test-utils";
7
7
  import FileField, { IFileFieldProps } from "@ax/components/Fields/FileField";
8
8
  import { act } from "react-dom/test-utils";
9
+ import thunk from "redux-thunk";
10
+ import configureStore from "redux-mock-store";
11
+
12
+ import { defaultStore } from "./../../../../__mocks__/store/GenericStore";
9
13
 
10
14
  afterEach(cleanup);
11
15
 
12
16
  const defaultProps = mock<IFileFieldProps>();
13
17
 
18
+ const initialStore = {
19
+ ...defaultStore,
20
+ fileDrive: {
21
+ currentFolderContent: null,
22
+ currentFolderID: null,
23
+ breadcrumb: [],
24
+ foldersTree: [],
25
+ isUploading: false,
26
+ isSuccess: false,
27
+ isError: false,
28
+ errorMsg: "",
29
+ displayMode: "grid",
30
+ },
31
+ };
32
+
33
+ const middlewares = [thunk];
34
+ const mockStore = configureStore(middlewares);
35
+
36
+ const store = mockStore(initialStore);
37
+
14
38
  describe("FileField component rendering", () => {
15
39
  it("should render the component", () => {
16
40
  defaultProps.value.url = "google.es";
@@ -18,7 +42,8 @@ describe("FileField component rendering", () => {
18
42
  render(
19
43
  <ThemeProvider theme={parseTheme(globalTheme)}>
20
44
  <FileField {...defaultProps} />
21
- </ThemeProvider>
45
+ </ThemeProvider>,
46
+ { store }
22
47
  );
23
48
 
24
49
  const fileDataWrapper = screen.getByTestId("file-data-wrapper");
@@ -32,7 +57,8 @@ describe("FileField component rendering", () => {
32
57
  render(
33
58
  <ThemeProvider theme={parseTheme(globalTheme)}>
34
59
  <FileField {...defaultProps} />
35
- </ThemeProvider>
60
+ </ThemeProvider>,
61
+ { store }
36
62
  );
37
63
 
38
64
  const fileDataWrapper = screen.getByTestId("file-data-wrapper");
@@ -49,7 +75,7 @@ describe("onClick events", () => {
49
75
  </ThemeProvider>
50
76
  );
51
77
 
52
- const { rerender } = render(Component);
78
+ const { rerender } = render(Component, {store});
53
79
 
54
80
  const fileButton = screen.getByTestId("field-icon-wrapper");
55
81
  act(() => fileButton.click());
@@ -67,14 +93,14 @@ describe("onClick events", () => {
67
93
  </ThemeProvider>
68
94
  );
69
95
 
70
- const { rerender } = render(Component);
96
+ const { rerender } = render(Component, { store });
71
97
 
72
98
  const fileButton = screen.getByTestId("field-icon-wrapper");
73
99
  act(() => fileButton.click());
74
100
 
75
101
  rerender(Component);
76
102
 
77
- const fileDragAndDropWrapper = screen.queryByTestId("file-drag-and-drop-wrapper");
103
+ const fileDragAndDropWrapper = screen.queryByTestId("file-gallery-wrapper");
78
104
  expect(fileDragAndDropWrapper).toBeFalsy();
79
105
  });
80
106
 
@@ -90,7 +116,7 @@ describe("onClick events", () => {
90
116
  const windowOpen = window.open;
91
117
  (window as any).open = () => ({ focus: () => null });
92
118
 
93
- const { rerender } = render(Component);
119
+ const { rerender } = render(Component, {store});
94
120
 
95
121
  const spyWindowOpen = jest.spyOn(window, "open");
96
122
 
@@ -119,7 +145,7 @@ describe("onClick events", () => {
119
145
  </ThemeProvider>
120
146
  );
121
147
 
122
- const { rerender } = render(Component);
148
+ const { rerender } = render(Component, {store});
123
149
 
124
150
  const floatingMenu = screen.getAllByTestId("icon-action-component");
125
151
 
@@ -157,7 +157,7 @@ describe("GalleryDragAndDrop component actions", () => {
157
157
  const buttonTry = screen.getByText(/TRY AGAIN/i);
158
158
  fireEvent.click(buttonTry);
159
159
  expect(store.getActions()).toContainEqual({
160
- payload: { errorMsg: "", inDropZone: false, isError: false, isUploading: false },
160
+ payload: { errorMsg: "", isError: false, isUploading: false },
161
161
  type: "gallery/SET_UPLOAD_ERROR",
162
162
  });
163
163
  });
package/src/api/files.tsx CHANGED
@@ -1,3 +1,5 @@
1
+ import { IGetFolderParams } from "@ax/types";
2
+ import { encodeData } from "@ax/helpers";
1
3
  import { template } from "./config";
2
4
  import { IServiceConfig, sendRequest } from "./utils";
3
5
 
@@ -7,10 +9,178 @@ const SERVICES: { [key: string]: IServiceConfig } = {
7
9
  endpoint: "/files",
8
10
  method: "POST",
9
11
  },
12
+ GET_FOLDER_CONTENT: {
13
+ ...template,
14
+ endpoint: ["/site/", "/folders"],
15
+ method: "GET",
16
+ },
17
+ GET_FOLDERS_TREE: {
18
+ ...template,
19
+ endpoint: ["/site/", "/folders/tree"],
20
+ method: "GET",
21
+ },
22
+ CREATE_FOLDER: {
23
+ ...template,
24
+ endpoint: "/folder",
25
+ method: "POST",
26
+ },
27
+ UPDATE_FOLDER: {
28
+ ...template,
29
+ endpoint: "/folder/",
30
+ method: "PUT",
31
+ },
32
+ DELETE_FOLDER: {
33
+ ...template,
34
+ endpoint: "/folders/",
35
+ method: "DELETE",
36
+ },
37
+ UPDATE_FILE: {
38
+ ...template,
39
+ endpoint: "/files/",
40
+ method: "PUT",
41
+ },
42
+ DELETE_FILE: {
43
+ ...template,
44
+ endpoint: "/files/",
45
+ method: "DELETE",
46
+ },
47
+ DELETE_FILES_BULK: {
48
+ ...template,
49
+ endpoint: "/files/bulk",
50
+ method: "DELETE",
51
+ },
52
+ MOVE_FILE: {
53
+ ...template,
54
+ endpoint: ["/files/", "/folder/"],
55
+ method: "PUT",
56
+ },
57
+ MOVE_FILES_BULK: {
58
+ ...template,
59
+ endpoint: "/files/bulk/folder/",
60
+ method: "PUT",
61
+ },
62
+ REPLACE_FILE: {
63
+ ...template,
64
+ endpoint: ["/files/", "/replace"],
65
+ method: "PUT",
66
+ },
10
67
  };
11
68
 
12
69
  const uploadFile = async (data: FormData) => {
13
70
  return sendRequest(SERVICES.UPLOAD_FILE, data as any);
14
71
  };
15
72
 
16
- export default { uploadFile };
73
+ const getFolderContent = async (params: IGetFolderParams) => {
74
+ const {
75
+ host,
76
+ endpoint: [prefix, suffix],
77
+ } = SERVICES.GET_FOLDER_CONTENT;
78
+
79
+ const { siteID, folderID, search, filter, order } = params;
80
+
81
+ const data = {
82
+ ...(folderID && { folder: folderID }),
83
+ ...(search && { search }),
84
+ ...(order && { order }),
85
+ ...(filter && { filterType: filter }),
86
+ };
87
+
88
+ const queryParams = encodeData(data);
89
+ const query = queryParams.length ? `?${queryParams}` : "";
90
+
91
+ SERVICES.GET_FOLDER_CONTENT.dynamicUrl = `${host}${prefix}${siteID}${suffix}${query}`;
92
+
93
+ return sendRequest(SERVICES.GET_FOLDER_CONTENT);
94
+ };
95
+
96
+ const getFoldersTree = async (siteID: number | "global") => {
97
+ const {
98
+ host,
99
+ endpoint: [prefix, suffix],
100
+ } = SERVICES.GET_FOLDERS_TREE;
101
+
102
+ SERVICES.GET_FOLDERS_TREE.dynamicUrl = `${host}${prefix}${siteID}${suffix}`;
103
+
104
+ return sendRequest(SERVICES.GET_FOLDERS_TREE);
105
+ };
106
+
107
+ const createFolder = async (data: { folderName: string; site: number | "global"; parentId?: number }) => {
108
+ return sendRequest(SERVICES.CREATE_FOLDER, data);
109
+ };
110
+
111
+ const updateFolder = async (folderID: number, data: { parentId: number; folderName: string }) => {
112
+ const { host, endpoint } = SERVICES.UPDATE_FOLDER;
113
+ SERVICES.UPDATE_FOLDER.dynamicUrl = `${host}${endpoint}${folderID}`;
114
+
115
+ return sendRequest(SERVICES.UPDATE_FOLDER, data);
116
+ };
117
+
118
+ const deleteFolder = async (folderID: number) => {
119
+ const { host, endpoint } = SERVICES.DELETE_FOLDER;
120
+ SERVICES.DELETE_FOLDER.dynamicUrl = `${host}${endpoint}${folderID}`;
121
+
122
+ return sendRequest(SERVICES.DELETE_FOLDER);
123
+ };
124
+
125
+ const updateFile = async (fileID: number, data: { title: string; alt: string; tags: string[] }) => {
126
+ const { host, endpoint } = SERVICES.UPDATE_FILE;
127
+ SERVICES.UPDATE_FILE.dynamicUrl = `${host}${endpoint}${fileID}`;
128
+
129
+ return sendRequest(SERVICES.UPDATE_FILE, data);
130
+ };
131
+
132
+ const deleteFile = async (fileID: number) => {
133
+ const { host, endpoint } = SERVICES.DELETE_FILE;
134
+ SERVICES.DELETE_FILE.dynamicUrl = `${host}${endpoint}${fileID}`;
135
+
136
+ return sendRequest(SERVICES.DELETE_FILE);
137
+ };
138
+
139
+ const deleteFilesBulk = async (ids: number[]) => sendRequest(SERVICES.DELETE_FILES_BULK, { ids });
140
+
141
+ const moveFile = async (fileID: number, folderID: number) => {
142
+ const {
143
+ host,
144
+ endpoint: [prefix, suffix],
145
+ } = SERVICES.MOVE_FILE;
146
+
147
+ SERVICES.MOVE_FILE.dynamicUrl = `${host}${prefix}${fileID}${suffix}${folderID}`;
148
+
149
+ return sendRequest(SERVICES.MOVE_FILE);
150
+ };
151
+
152
+ const moveFilesBulk = async (ids: number[], folderID: number) => {
153
+ const { host, endpoint } = SERVICES.MOVE_FILES_BULK;
154
+
155
+ SERVICES.MOVE_FILES_BULK.dynamicUrl = `${host}${endpoint}${folderID}`;
156
+
157
+ return sendRequest(SERVICES.MOVE_FILES_BULK, { ids });
158
+ };
159
+
160
+ const replaceFile = async (data: FormData, fileID: number, keepUrl: boolean) => {
161
+ const {
162
+ host,
163
+ endpoint: [prefix, suffix],
164
+ } = SERVICES.REPLACE_FILE;
165
+
166
+ const query = keepUrl ? "?keepUrl=on" : "";
167
+
168
+ SERVICES.REPLACE_FILE.dynamicUrl = `${host}${prefix}${fileID}${suffix}${query}`;
169
+
170
+ return sendRequest(SERVICES.REPLACE_FILE, data as any);
171
+ };
172
+
173
+ export default {
174
+ uploadFile,
175
+ getFolderContent,
176
+ getFoldersTree,
177
+ createFolder,
178
+ updateFolder,
179
+ deleteFolder,
180
+ updateFile,
181
+ deleteFile,
182
+ deleteFilesBulk,
183
+ moveFile,
184
+ moveFilesBulk,
185
+ replaceFile,
186
+ };
package/src/api/users.tsx CHANGED
@@ -64,14 +64,17 @@ const getUsers = async (params: any) => {
64
64
  };
65
65
 
66
66
  const getSiteUsers = async (params: any, siteID: number) => {
67
- const { host, endpoint: [prefix, suffix], } = SERVICES.GET_SITE_USERS;
67
+ const {
68
+ host,
69
+ endpoint: [prefix, suffix],
70
+ } = SERVICES.GET_SITE_USERS;
68
71
 
69
72
  const { query, filterQuery } = params;
70
73
 
71
74
  SERVICES.GET_SITE_USERS.dynamicUrl = `${host}${prefix}${siteID}${suffix}${filterQuery}`;
72
75
 
73
76
  if (query && query.trim() !== "") {
74
- SERVICES.GET_SITE_USERS.dynamicUrl = `${SERVICES.GET_USERS.dynamicUrl}${query}`;
77
+ SERVICES.GET_SITE_USERS.dynamicUrl = `${SERVICES.GET_SITE_USERS.dynamicUrl}${query}`;
75
78
  }
76
79
 
77
80
  return sendRequest(SERVICES.GET_SITE_USERS);
@@ -1,13 +1,14 @@
1
1
  import React from "react";
2
2
 
3
3
  import { FloatingMenu, Icon, IconAction, Tooltip } from "@ax/components";
4
+ import { IActionMenuOption } from "@ax/types";
4
5
 
5
6
  import * as S from "./style";
6
7
 
7
8
  const ActionMenu = (props: IActionMenuProps): JSX.Element => {
8
9
  const { options, icon, className, tooltip } = props;
9
10
 
10
- const filteredOptions = options.filter((option: IOption | undefined | null) => !!option);
11
+ const filteredOptions = options.filter((option: IActionMenuOption | undefined | null) => !!option);
11
12
 
12
13
  const MoreInfoButton = () => (
13
14
  <S.IconActionWrapper data-testid="more-info-button">
@@ -15,7 +16,7 @@ const ActionMenu = (props: IActionMenuProps): JSX.Element => {
15
16
  </S.IconActionWrapper>
16
17
  );
17
18
 
18
- const ActionMenuItem = (item: IOption) => (
19
+ const ActionMenuItem = (item: IActionMenuOption) => (
19
20
  <S.ActionItem
20
21
  key={item.icon}
21
22
  onClick={item.action}
@@ -39,7 +40,7 @@ const ActionMenu = (props: IActionMenuProps): JSX.Element => {
39
40
  <Tooltip content={tooltip} hideOnClick>
40
41
  <FloatingMenu Button={MoreInfoButton}>
41
42
  <S.ActionMenu>
42
- {filteredOptions.map((item: IOption | undefined | null) => item && ActionMenuItem(item))}
43
+ {filteredOptions.map((item: IActionMenuOption | undefined | null) => item && ActionMenuItem(item))}
43
44
  </S.ActionMenu>
44
45
  </FloatingMenu>
45
46
  </Tooltip>
@@ -50,17 +51,8 @@ const ActionMenu = (props: IActionMenuProps): JSX.Element => {
50
51
  );
51
52
  };
52
53
 
53
- interface IOption {
54
- label: string;
55
- action: any;
56
- icon: string;
57
- disabled?: boolean;
58
- helpText?: string | null;
59
- color?: boolean;
60
- }
61
-
62
54
  export interface IActionMenuProps {
63
- options: (IOption | undefined | null)[];
55
+ options: (IActionMenuOption | undefined | null)[];
64
56
  icon: string;
65
57
  className?: string;
66
58
  tooltip?: string;
@@ -0,0 +1,28 @@
1
+ import React from "react";
2
+
3
+ import Icon from "../Icon";
4
+ import * as S from "./style";
5
+
6
+ const BackFolder = (props: IBackFolderProps): JSX.Element => {
7
+ const { onClick, size } = props;
8
+
9
+ const iconSize = size === "S" ? "16" : "24";
10
+
11
+ return (
12
+ <S.FolderBack onClick={onClick} size={size}>
13
+ <S.BackIconWrapper>
14
+ <Icon name="project"/>
15
+ </S.BackIconWrapper>
16
+ <S.BackIconWrapper>
17
+ <Icon name="back" />
18
+ </S.BackIconWrapper>
19
+ </S.FolderBack>
20
+ );
21
+ };
22
+
23
+ export interface IBackFolderProps {
24
+ onClick: () => void;
25
+ size?: "S"|"M";
26
+ }
27
+
28
+ export default BackFolder;
@@ -0,0 +1,33 @@
1
+ import styled from "styled-components";
2
+
3
+ const FolderBack = styled.div<{ size?: "S" | "M" }>`
4
+ position: relative;
5
+ background-color: ${(p) => p.theme.color.uiBackground02};
6
+ border: ${(p) => `1px solid ${p.theme.color.uiLine}`};
7
+ border-radius: ${(p) => p.theme.radii.s};
8
+ display: flex;
9
+ justify-content: space-between;
10
+ align-items: center;
11
+ width: 84px;
12
+ height: ${(p) => p.size === "S" ? "40px" : "64px"};
13
+ cursor: pointer;
14
+ padding: ${(p) => `0 ${p.theme.spacing.s}`};
15
+ margin-right: ${(p) => p.size === "S" ? p.theme.spacing.xxs : p.theme.spacing.s};
16
+ &:hover {
17
+ background-color: ${(p) => p.theme.color.overlayHoverPrimary};
18
+ }
19
+ `;
20
+
21
+ const BackIconWrapper = styled.div`
22
+ width: 24px;
23
+ height: 24px;
24
+ &:last-child {
25
+ svg {
26
+ path {
27
+ fill: ${(p) => p.theme.color.iconHighEmphasis};
28
+ }
29
+ }
30
+ }
31
+ `;
32
+
33
+ export { FolderBack, BackIconWrapper }
@@ -1,16 +1,17 @@
1
1
  import React from "react";
2
2
 
3
3
  import { Button, CheckField, TableCounter } from "@ax/components";
4
+ import { IBulkAction } from "@ax/types";
4
5
 
5
6
  import * as S from "./style";
6
7
 
7
8
  const BulkSelectionOptions = (props: IBulkSelectionProps): JSX.Element => {
8
- const { isScrolling, checkState, actions, selectItems, totalItems } = props;
9
+ const { isScrolling, checkState, actions, selectItems, totalItems, className } = props;
9
10
 
10
11
  const filteredActions = actions.filter((action: IBulkAction | undefined | null) => !!action);
11
12
 
12
13
  return (
13
- <S.BulkHeader isScrolling={isScrolling} data-testid="bulk-header-wrapper">
14
+ <S.BulkHeader isScrolling={isScrolling} data-testid="bulk-header-wrapper" className={className}>
14
15
  <S.BulkActionsWrapper>
15
16
  <S.SelectAllCheckField>
16
17
  <CheckField
@@ -42,18 +43,13 @@ const BulkSelectionOptions = (props: IBulkSelectionProps): JSX.Element => {
42
43
  );
43
44
  };
44
45
 
45
- interface IBulkAction {
46
- icon?: string;
47
- text: string;
48
- action: () => void;
49
- }
50
-
51
46
  interface IBulkSelectionProps {
52
47
  checkState: any;
53
48
  actions: (IBulkAction | undefined | null)[];
54
49
  selectItems: () => void;
55
50
  totalItems: number;
56
51
  isScrolling?: boolean;
52
+ className?: string;
57
53
  }
58
54
 
59
55
  export default BulkSelectionOptions;
@@ -10,7 +10,9 @@ enum buttonStyles {
10
10
  INVERSE = "lineInverse",
11
11
  }
12
12
 
13
- const Button = ({ children, type, disabled, icon, buttonStyle, onClick, className, loader }: IButtonProps): JSX.Element => {
13
+ const Button = (props: IButtonProps): JSX.Element => {
14
+ const { children, type, disabled, icon, buttonStyle, onClick, className, loader, backIcon } = props;
15
+
14
16
  const handleOnClick = (e: React.MouseEvent<HTMLButtonElement>) => {
15
17
  if (onClick !== undefined) {
16
18
  e.preventDefault();
@@ -18,12 +20,14 @@ const Button = ({ children, type, disabled, icon, buttonStyle, onClick, classNam
18
20
  }
19
21
  };
20
22
 
21
- let iconWrapper = icon ? <Icon name={icon} /> : loader ? <Loader name={loader} /> : undefined;
23
+ let iconWrapper = icon ? <Icon name={icon} /> : loader ? <Loader name={loader} /> : <></>;
24
+ let iconBackWrapper = backIcon ? <Icon name={backIcon} /> : <></>;
22
25
 
23
26
  const buttonContent = (
24
- <S.Label icon={icon || loader}>
27
+ <S.Label icon={icon || loader} backIcon={backIcon}>
25
28
  {iconWrapper}
26
29
  <span>{children}</span>
30
+ {iconBackWrapper}
27
31
  </S.Label>
28
32
  );
29
33
 
@@ -80,6 +84,7 @@ export interface IButtonProps {
80
84
  disabled?: boolean;
81
85
  buttonStyle?: "solid" | "text" | "line" | "lineInverse" | undefined; // TODO: investigar si podemos hacer esto más elegante y aprovechar el enum buttonStyles
82
86
  className?: string;
87
+ backIcon?: string;
83
88
  }
84
89
 
85
90
  export default Button;
@@ -94,8 +94,8 @@ export const TextButton = styled((props) => <Button {...props} />)`
94
94
 
95
95
  export const LineButton = styled((props) => <Button {...props} />)<{ isInverse: boolean | undefined }>`
96
96
  background-color: ${(p) => (p.isInverse ? p.theme.color.uiMainMenuBackground : p.theme.color.interactiveBackground)};
97
- border: 1px solid ${(p) => (p.isInverse ? "#fff" : p.theme.color.interactive01)};
98
- color: ${(p) => (p.isInverse ? "#fff" : p.theme.color.interactive01)};
97
+ border: 1px solid ${(p) => (p.isInverse ? p.theme.color.interactiveInverse : p.theme.color.interactive01)};
98
+ color: ${(p) => (p.isInverse ? p.theme.color.interactiveInverse : p.theme.color.interactive01)};
99
99
  :hover:before {
100
100
  background-color: ${(p) => (p.isInverse ? p.theme.color.uiMainMenuBackground : p.theme.color.overlayHoverPrimary)};
101
101
  }
@@ -123,11 +123,13 @@ export const LineButton = styled((props) => <Button {...props} />)<{ isInverse:
123
123
  }
124
124
  `;
125
125
 
126
- export const Label = styled.span<{ icon: string | undefined }>`
126
+ export const Label = styled.span<{ icon?: string; backIcon?: string }>`
127
127
  outline: none;
128
128
  position: relative;
129
129
  z-index: 1;
130
130
  span {
131
131
  padding-left: ${(p) => (p.icon ? `calc(${p.theme.spacing.s} + ${p.theme.spacing.xxs})` : `0`)};
132
+ padding-right: ${(p) => (p.backIcon ? p.theme.spacing.xxs : `0`)};
132
133
  }
134
+ padding-right: ${(p) => (p.backIcon ? p.theme.spacing.s : `0`)};
133
135
  `;
@@ -4,7 +4,17 @@ import { trimText } from "@ax/helpers";
4
4
  import * as S from "./style";
5
5
 
6
6
  const ElementsTooltip = (props: IElementsTooltipProps): JSX.Element => {
7
- const { elements, maxChar, defaultElements = 1, colors, rounded = false, elementsPerRow = 1 } = props;
7
+ const {
8
+ elements,
9
+ maxChar,
10
+ defaultElements = 1,
11
+ colors,
12
+ rounded = false,
13
+ elementsPerRow = 1,
14
+ defaultColor,
15
+ prefix = "",
16
+ size = "S",
17
+ } = props;
8
18
 
9
19
  if (!elements) return <></>;
10
20
 
@@ -21,26 +31,28 @@ const ElementsTooltip = (props: IElementsTooltipProps): JSX.Element => {
21
31
  return (
22
32
  <S.Wrapper data-testid="elements-wrapper">
23
33
  {visibleElements.map((fullElement, idx) => {
24
- const element = maxChar ? trimText(fullElement, maxChar) : fullElement;
25
- const color = colors && colors[element] ? colors[element] : undefined;
34
+ const element = defaultElements === 1 && maxChar ? trimText(fullElement, maxChar) : fullElement;
35
+ const color = defaultColor ? defaultColor : colors && colors[element] ? colors[element] : undefined;
26
36
 
27
37
  return (
28
- <S.Element data-testid="element" key={idx} color={color} rounded={rounded}>
38
+ <S.Element data-testid="element" key={idx} color={color} rounded={rounded} size={size}>
39
+ {prefix}
29
40
  {element}
30
41
  </S.Element>
31
42
  );
32
43
  })}
33
44
  {remainingElements > 0 && (
34
- <S.Element data-testid="remaining-element" rounded={rounded}>
45
+ <S.Element data-testid="remaining-element" rounded={rounded} size={size}>
35
46
  +{remainingElements}
36
47
  <S.Tooltip>
37
48
  {elementsRows.map((row, idx) => {
38
49
  return (
39
50
  <S.Row data-testid="row-element" key={idx}>
40
51
  {row.map((element, idx) => {
41
- const color = colors && colors[element] ? colors[element] : undefined;
52
+ const color = defaultColor ? defaultColor : colors && colors[element] ? colors[element] : undefined;
42
53
  return (
43
- <S.Element data-testid="div-element" key={idx} color={color} rounded={rounded}>
54
+ <S.Element data-testid="div-element" key={idx} color={color} rounded={rounded} size={size}>
55
+ {prefix}
44
56
  {element}
45
57
  </S.Element>
46
58
  );
@@ -62,6 +74,9 @@ export interface IElementsTooltipProps {
62
74
  colors?: any;
63
75
  rounded?: boolean;
64
76
  elementsPerRow?: number;
77
+ defaultColor?: string;
78
+ prefix?: string;
79
+ size?: "S" | "M";
65
80
  }
66
81
 
67
82
  export default ElementsTooltip;
@@ -17,9 +17,9 @@ const Tooltip = styled.div`
17
17
  border-radius: ${(p) => p.theme.radii.s};
18
18
  `;
19
19
 
20
- const Element = styled.div<{ color?: string; rounded: boolean }>`
20
+ const Element = styled.div<{ color?: string; rounded: boolean; size: "S" | "M" }>`
21
21
  position: relative;
22
- ${(p) => p.theme.textStyle.uiXS};
22
+ ${(p) => (p.size === "M" ? p.theme.textStyle.uiS : p.theme.textStyle.uiXS)};
23
23
  ${(p) => p.theme.colors.textMediumEmphasis};
24
24
  padding: ${(p) => p.theme.spacing.xxs} ${(p) => p.theme.spacing.xs};
25
25
  margin: calc(${(p) => p.theme.spacing.xxs} / 2);