@griddo/ax 10.1.96 → 10.2.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 (201) hide show
  1. package/package.json +3 -2
  2. package/src/__mocks__/axios/Roles.ts +10 -0
  3. package/src/__mocks__/axios/UserList.ts +545 -0
  4. package/src/__mocks__/store/GenericStore.ts +25 -0
  5. package/src/__mocks__/store/Roles.ts +1050 -0
  6. package/src/__mocks__/store/SitesList.ts +7 -1
  7. package/src/__mocks__/store/UserList.ts +482 -0
  8. package/src/__mocks__/store/UsersCreate.ts +298 -0
  9. package/src/__tests__/components/Avatar/Avatar.test.tsx +49 -48
  10. package/src/__tests__/components/ConfigPanel/ConfigPanel.test.tsx +2 -0
  11. package/src/__tests__/components/ConfigPanel/Form/Form.test.tsx +2 -0
  12. package/src/__tests__/components/ConfigPanel/GlobalPageForm/GlobalPageForm.test.tsx +25 -0
  13. package/src/__tests__/components/Fields/Button/Button.test.tsx +2 -2
  14. package/src/__tests__/components/Fields/ImageField/ImageField.test.tsx +2 -0
  15. package/src/__tests__/components/Fields/IntegrationsField/IntegrationsField.test.tsx +44 -2
  16. package/src/__tests__/components/Fields/Tooltip/Tooltip.test.tsx +0 -1
  17. package/src/__tests__/components/Gallery/Gallery.test.tsx +4 -0
  18. package/src/__tests__/components/Gallery/GalleryPanel/DetailPanel/DetailPanel.test.tsx +14 -0
  19. package/src/__tests__/components/Gallery/GalleryPanel/GalleryPanel.test.tsx +2 -1
  20. package/src/__tests__/components/Lists/Lists.test.tsx +3 -3
  21. package/src/__tests__/components/Login/Login.test.tsx +1 -1
  22. package/src/__tests__/components/TableFilters/DateFilter/DateFilter.test.tsx +1 -1
  23. package/src/__tests__/components/TableFilters/NameFilter/NameFilter.test.tsx +1 -1
  24. package/src/__tests__/components/TableFilters/RoleFilter/RoleFilter.test.tsx +165 -0
  25. package/src/__tests__/components/TableFilters/StatusFilter/StatusFilter.test.tsx +2 -2
  26. package/src/__tests__/components/TableFilters/UsersFilter/UsersFilter.test.tsx +153 -0
  27. package/src/__tests__/components/Tabs/Tabs.test.tsx +1 -1
  28. package/src/__tests__/modules/Settings/Integrations/Integrations.test.tsx +6 -0
  29. package/src/__tests__/modules/Sites/Sites.test.tsx +2 -1
  30. package/src/__tests__/modules/Sites/SitesList/ListView/BulkHeader/BulkHeader.test.tsx +14 -5
  31. package/src/__tests__/modules/Sites/SitesList/SitesList.test.tsx +6 -4
  32. package/src/__tests__/modules/Users/Roles/BulkHeader/BulkHeader.test.tsx +158 -0
  33. package/src/__tests__/modules/Users/Roles/Roles.test.tsx +619 -0
  34. package/src/__tests__/modules/Users/UserCreate/SiteItem/RolesModal/RoleItem/RoleItem.test.tsx +107 -0
  35. package/src/__tests__/modules/Users/UserCreate/SiteItem/RolesModal/RolesModal.test.tsx +159 -0
  36. package/src/__tests__/modules/Users/UserCreate/SiteItem/SiteItem.test.tsx +175 -0
  37. package/src/__tests__/modules/Users/UserCreate/UserCreate.test.tsx +320 -0
  38. package/src/__tests__/modules/Users/UserList/UserItem/UserItem.test.tsx +417 -0
  39. package/src/__tests__/modules/Users/UserList/UserList.test.tsx +310 -0
  40. package/src/api/index.tsx +2 -0
  41. package/src/api/roles.tsx +77 -0
  42. package/src/api/users.tsx +22 -2
  43. package/src/components/ActionMenu/index.tsx +12 -6
  44. package/src/components/Avatar/index.tsx +5 -3
  45. package/src/components/Avatar/style.tsx +8 -9
  46. package/src/components/BulkSelectionOptions/index.tsx +19 -12
  47. package/src/components/BulkSelectionOptions/style.tsx +6 -11
  48. package/src/components/ConfigPanel/Form/index.tsx +24 -1
  49. package/src/components/ConfigPanel/GlobalPageForm/index.tsx +17 -4
  50. package/src/components/ElementsTooltip/index.tsx +1 -1
  51. package/src/components/Fields/IntegrationsField/index.tsx +5 -6
  52. package/src/components/Fields/RadioField/index.tsx +1 -1
  53. package/src/components/Fields/ReferenceField/AutoPanel/index.tsx +3 -3
  54. package/src/components/Fields/ReferenceField/ItemList/index.tsx +1 -1
  55. package/src/components/Fields/ReferenceField/ManualPanel/index.tsx +3 -3
  56. package/src/components/Fields/TagsField/index.tsx +4 -2
  57. package/src/components/Fields/TextField/index.tsx +3 -0
  58. package/src/components/Fields/UrlField/index.tsx +5 -5
  59. package/src/components/Gallery/GalleryPanel/DetailPanel/index.tsx +42 -15
  60. package/src/components/Gallery/GalleryPanel/GalleryDragAndDrop/index.tsx +1 -1
  61. package/src/components/Gallery/GalleryPanel/index.tsx +20 -5
  62. package/src/components/Gallery/index.tsx +12 -6
  63. package/src/components/Icon/index.tsx +9 -1
  64. package/src/components/MainWrapper/AppBar/atoms.tsx +2 -2
  65. package/src/components/MainWrapper/AppBar/index.tsx +12 -10
  66. package/src/components/MainWrapper/AppBar/style.tsx +2 -1
  67. package/src/components/Modal/style.tsx +2 -2
  68. package/src/components/Nav/index.tsx +12 -2
  69. package/src/components/PageFinder/index.tsx +2 -2
  70. package/src/components/SearchField/index.tsx +3 -8
  71. package/src/components/TableFilters/PermissionsFilter/index.tsx +50 -0
  72. package/src/{modules/Users/UserList/HeaderMenus/Name → components/TableFilters/PermissionsFilter}/style.tsx +6 -2
  73. package/src/components/TableFilters/RoleFilter/index.tsx +61 -0
  74. package/src/components/TableFilters/RoleFilter/style.tsx +28 -0
  75. package/src/components/TableFilters/UsersFilter/index.tsx +55 -0
  76. package/src/components/TableFilters/UsersFilter/style.tsx +31 -0
  77. package/src/components/TableFilters/index.tsx +6 -0
  78. package/src/components/TableList/TableItem/style.tsx +2 -2
  79. package/src/components/TableList/style.tsx +1 -1
  80. package/src/components/index.tsx +7 -1
  81. package/src/containers/App/actions.tsx +3 -3
  82. package/src/containers/PageEditor/actions.tsx +14 -20
  83. package/src/containers/Redirects/actions.tsx +1 -0
  84. package/src/containers/Sites/actions.tsx +22 -14
  85. package/src/containers/Sites/interfaces.tsx +3 -3
  86. package/src/containers/Sites/reducer.tsx +1 -1
  87. package/src/containers/StructuredData/actions.tsx +15 -3
  88. package/src/containers/Users/actions.tsx +160 -26
  89. package/src/containers/Users/constants.tsx +8 -10
  90. package/src/containers/Users/interfaces.tsx +25 -3
  91. package/src/containers/Users/reducer.tsx +24 -15
  92. package/src/guards/index.tsx +2 -1
  93. package/src/guards/restricted/index.tsx +21 -0
  94. package/src/hooks/index.tsx +3 -0
  95. package/src/hooks/users.tsx +38 -0
  96. package/src/modules/App/Routing/NavMenu/NavItem/index.tsx +10 -5
  97. package/src/modules/App/Routing/NavMenu/index.tsx +16 -7
  98. package/src/modules/App/Routing/PrivateRoute/index.tsx +13 -5
  99. package/src/modules/App/Routing/index.tsx +17 -6
  100. package/src/modules/Categories/CategoriesList/BulkHeader/TableHeader/style.tsx +1 -0
  101. package/src/modules/Categories/CategoriesList/BulkHeader/index.tsx +2 -10
  102. package/src/modules/Categories/CategoriesList/CategoryItem/index.tsx +27 -12
  103. package/src/modules/Categories/CategoriesList/CategoryItem/style.tsx +4 -2
  104. package/src/modules/Categories/CategoriesList/index.tsx +27 -8
  105. package/src/modules/Content/BulkHeader/index.tsx +7 -3
  106. package/src/modules/Content/PageImporter/index.tsx +1 -1
  107. package/src/modules/Content/PageItem/index.tsx +45 -31
  108. package/src/modules/Content/PageItem/style.tsx +2 -1
  109. package/src/modules/Content/index.tsx +22 -13
  110. package/src/modules/FramePreview/index.tsx +2 -2
  111. package/src/modules/GlobalEditor/index.tsx +68 -53
  112. package/src/modules/GlobalSettings/index.tsx +2 -0
  113. package/src/modules/Navigation/Defaults/BulkHeader/index.tsx +2 -10
  114. package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/DefaultsBrowser/index.tsx +9 -11
  115. package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/index.tsx +5 -1
  116. package/src/modules/Navigation/Defaults/DefaultsEditor/index.tsx +10 -5
  117. package/src/modules/Navigation/Defaults/Item/index.tsx +41 -27
  118. package/src/modules/Navigation/Defaults/Item/style.tsx +2 -1
  119. package/src/modules/Navigation/Defaults/index.tsx +29 -10
  120. package/src/modules/Navigation/Menus/List/Table/Header/index.tsx +7 -5
  121. package/src/modules/Navigation/Menus/List/Table/Item/index.tsx +10 -10
  122. package/src/modules/Navigation/Menus/List/Table/Item/style.tsx +2 -1
  123. package/src/modules/Navigation/Menus/List/index.tsx +6 -2
  124. package/src/modules/Navigation/Menus/index.tsx +12 -7
  125. package/src/modules/PageEditor/Editor/index.tsx +5 -1
  126. package/src/modules/PageEditor/PageBrowser/index.tsx +9 -3
  127. package/src/modules/PageEditor/index.tsx +67 -57
  128. package/src/modules/Redirects/index.tsx +97 -98
  129. package/src/modules/Settings/ContentTypes/DataPacks/AddModal/index.tsx +5 -1
  130. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/TemplateBrowser/index.tsx +8 -9
  131. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/index.tsx +7 -3
  132. package/src/modules/Settings/ContentTypes/DataPacks/Config/index.tsx +5 -1
  133. package/src/modules/Settings/ContentTypes/DataPacks/Item/index.tsx +5 -1
  134. package/src/modules/Settings/Integrations/BulkHeader/index.tsx +2 -17
  135. package/src/modules/Settings/Integrations/IntegrationForm/index.tsx +6 -2
  136. package/src/modules/Settings/Integrations/IntegrationItem/index.tsx +18 -8
  137. package/src/modules/Settings/Integrations/IntegrationItem/style.tsx +6 -3
  138. package/src/modules/Settings/Integrations/index.tsx +32 -7
  139. package/src/modules/Settings/Languages/LanguagePanel/index.tsx +6 -2
  140. package/src/modules/Settings/Languages/Table/Header/index.tsx +4 -2
  141. package/src/modules/Settings/Languages/Table/Item/index.tsx +19 -43
  142. package/src/modules/Settings/Languages/Table/Item/style.tsx +11 -54
  143. package/src/modules/Settings/Languages/index.tsx +2 -2
  144. package/src/modules/Settings/SeoAnalyticsSettings/Analytics/index.tsx +2 -4
  145. package/src/modules/Settings/SeoAnalyticsSettings/index.tsx +4 -2
  146. package/src/modules/Settings/Social/index.tsx +1 -1
  147. package/src/modules/Settings/index.tsx +17 -11
  148. package/src/modules/Sites/SitesList/GridView/GridSiteItem/index.tsx +31 -18
  149. package/src/modules/Sites/SitesList/ListView/BulkHeader/index.tsx +21 -12
  150. package/src/modules/Sites/SitesList/ListView/ListSiteItem/index.tsx +31 -18
  151. package/src/modules/Sites/SitesList/RecentSiteItem/index.tsx +1 -1
  152. package/src/modules/Sites/SitesList/index.tsx +16 -24
  153. package/src/modules/Sites/index.tsx +7 -3
  154. package/src/modules/StructuredData/Form/index.tsx +1 -1
  155. package/src/modules/StructuredData/StructuredDataList/BulkHeader/index.tsx +8 -5
  156. package/src/modules/StructuredData/StructuredDataList/ContentFilters/index.tsx +8 -5
  157. package/src/modules/StructuredData/StructuredDataList/GlobalPageItem/index.tsx +29 -15
  158. package/src/modules/StructuredData/StructuredDataList/StructuredDataItem/index.tsx +50 -19
  159. package/src/modules/StructuredData/StructuredDataList/index.tsx +9 -6
  160. package/src/modules/Users/Profile/index.tsx +16 -4
  161. package/src/modules/Users/Roles/BulkHeader/TableHeader/index.tsx +52 -0
  162. package/src/modules/Users/Roles/BulkHeader/TableHeader/style.tsx +43 -0
  163. package/src/modules/Users/Roles/BulkHeader/index.tsx +74 -0
  164. package/src/modules/Users/Roles/RoleItem/index.tsx +104 -0
  165. package/src/modules/Users/Roles/RoleItem/style.tsx +127 -0
  166. package/src/modules/Users/Roles/SideModal/index.tsx +81 -0
  167. package/src/modules/Users/Roles/SideModal/style.tsx +132 -0
  168. package/src/modules/Users/Roles/hooks.tsx +78 -0
  169. package/src/modules/Users/Roles/index.tsx +256 -0
  170. package/src/modules/Users/Roles/style.tsx +23 -0
  171. package/src/modules/Users/Roles/utils.tsx +12 -0
  172. package/src/modules/Users/UserCreate/OptionItem/index.tsx +45 -0
  173. package/src/modules/Users/UserCreate/OptionItem/style.tsx +48 -0
  174. package/src/modules/Users/UserCreate/SiteItem/RolesModal/RoleItem/index.tsx +48 -0
  175. package/src/modules/Users/UserCreate/SiteItem/RolesModal/RoleItem/style.tsx +42 -0
  176. package/src/modules/Users/UserCreate/SiteItem/RolesModal/index.tsx +140 -0
  177. package/src/modules/Users/UserCreate/SiteItem/RolesModal/style.tsx +94 -0
  178. package/src/modules/Users/UserCreate/SiteItem/index.tsx +103 -22
  179. package/src/modules/Users/UserCreate/SiteItem/style.tsx +49 -6
  180. package/src/modules/Users/UserCreate/index.tsx +278 -121
  181. package/src/modules/Users/UserCreate/style.tsx +71 -4
  182. package/src/modules/Users/UserEdit/index.tsx +71 -24
  183. package/src/modules/Users/UserForm/atoms.tsx +40 -8
  184. package/src/modules/Users/UserForm/index.tsx +335 -116
  185. package/src/modules/Users/UserForm/style.tsx +70 -6
  186. package/src/modules/Users/UserList/BulkHeader/TableHeader/index.tsx +61 -31
  187. package/src/modules/Users/UserList/BulkHeader/TableHeader/style.tsx +18 -4
  188. package/src/modules/Users/UserList/BulkHeader/index.tsx +10 -3
  189. package/src/modules/Users/UserList/UserItem/index.tsx +121 -38
  190. package/src/modules/Users/UserList/UserItem/style.tsx +32 -14
  191. package/src/modules/Users/UserList/hooks.tsx +13 -8
  192. package/src/modules/Users/UserList/index.tsx +67 -29
  193. package/src/modules/Users/UserList/utils.tsx +1 -1
  194. package/src/modules/Users/index.tsx +20 -3
  195. package/src/routes/index.tsx +9 -17
  196. package/src/routes/multisite.tsx +73 -8
  197. package/src/routes/site.tsx +96 -10
  198. package/src/types/index.tsx +42 -1
  199. package/tsconfig.paths.json +1 -0
  200. package/src/__tests__/components/Avatar/__snapshots__/Avatar.test.tsx.snap +0 -61
  201. package/src/modules/Users/UserList/HeaderMenus/Name/index.tsx +0 -55
@@ -0,0 +1,310 @@
1
+ import React from "react";
2
+ import axios from "axios";
3
+ import { ThemeProvider } from "styled-components";
4
+ import configureStore from "redux-mock-store";
5
+ import thunk from "redux-thunk";
6
+ import { Router } from "react-router-dom";
7
+ import { mock } from "jest-mock-extended";
8
+ import "@testing-library/jest-dom";
9
+ import { render, cleanup, screen, act, fireEvent } from "./../../../../../config/jest/test-utils";
10
+ import userEvent from "@testing-library/user-event";
11
+ import { createMemoryHistory } from "history";
12
+ import MockAdapter from "axios-mock-adapter";
13
+ import { Middleware } from "redux";
14
+
15
+ import { parseTheme } from "@ax/helpers";
16
+ import globalTheme from "@ax/themes/theme.json";
17
+ import UserList, { IUserListProps } from "./../../../../modules/Users/UserList";
18
+
19
+ import {
20
+ appStoreMock,
21
+ usersStoreMock,
22
+ usersSiteStoreMock,
23
+ sitesStoreGlobalMock,
24
+ sitesStoreMock,
25
+ } from "../../../../__mocks__/store/UserList";
26
+
27
+ import {
28
+ rolesResponse,
29
+ userResponse,
30
+ usersResponse,
31
+ deletedUserResponse,
32
+ removeUserResponse,
33
+ usersSiteResponse,
34
+ removeUserSiteResponse,
35
+ } from "./../../../../__mocks__/axios/UserList";
36
+
37
+ const middlewares: Middleware[] = [thunk];
38
+ const mockStore = configureStore(middlewares);
39
+
40
+ const defaultProps = mock<IUserListProps>();
41
+
42
+ const user = userEvent.setup();
43
+
44
+ const history = createMemoryHistory();
45
+
46
+ let mockedAxios: MockAdapter;
47
+
48
+ beforeAll(() => {
49
+ mockedAxios = new MockAdapter(axios);
50
+ window.HTMLElement.prototype.scrollIntoView = jest.fn();
51
+ });
52
+
53
+ afterEach(() => {
54
+ cleanup();
55
+ jest.clearAllMocks();
56
+ mockedAxios.reset();
57
+ });
58
+
59
+ describe("UserList module rendering", () => {
60
+ it("should render the componet with 3 global users", async () => {
61
+ const initialStore = {
62
+ users: usersStoreMock,
63
+ sites: sitesStoreGlobalMock,
64
+ app: appStoreMock,
65
+ };
66
+
67
+ const store = mockStore(initialStore);
68
+
69
+ mockedAxios.onGet(`undefined/site/global/roles`).reply(200, rolesResponse.data);
70
+ mockedAxios.onGet(`undefined/users`).reply(200, usersResponse.data);
71
+ mockedAxios.onGet(`undefined/sites?recentSitesNumber=0`).reply(200, {});
72
+
73
+ const Component = (
74
+ <Router history={history}>
75
+ <ThemeProvider theme={parseTheme(globalTheme)}>
76
+ <UserList {...defaultProps} />
77
+ </ThemeProvider>
78
+ </Router>
79
+ );
80
+
81
+ await act(async () => {
82
+ render(Component, { store });
83
+ });
84
+
85
+ expect(screen.getByTestId("users-wrapper")).toBeTruthy();
86
+ expect(screen.queryAllByTestId("user-item").length).toBe(3);
87
+ });
88
+
89
+ it("should render the componet with 2 site user", async () => {
90
+ const initialStore = {
91
+ users: usersSiteStoreMock,
92
+ sites: sitesStoreMock,
93
+ app: appStoreMock,
94
+ };
95
+
96
+ const initialState = { ...initialStore, ...defaultProps };
97
+ const store = mockStore(initialStore);
98
+
99
+ mockedAxios.onGet(`undefined/site/2/roles`).reply(200, rolesResponse.data);
100
+ mockedAxios.onGet(`undefined/site/2/users`).reply(200, usersSiteResponse.data);
101
+ mockedAxios.onGet(`undefined/sites?recentSitesNumber=0`).reply(200, {});
102
+
103
+ const Component = (
104
+ <Router history={history}>
105
+ <ThemeProvider theme={parseTheme(globalTheme)}>
106
+ <UserList {...initialState} />
107
+ </ThemeProvider>
108
+ </Router>
109
+ );
110
+
111
+ await act(async () => {
112
+ render(Component, { store });
113
+ });
114
+
115
+ expect(screen.getByTestId("users-wrapper")).toBeTruthy();
116
+ expect(screen.queryAllByTestId("user-item").length).toBe(2);
117
+ });
118
+
119
+ it("should render the componet with no users", async () => {
120
+ const initialStore = {
121
+ users: { users: [], roles: [] },
122
+ sites: sitesStoreGlobalMock,
123
+ app: appStoreMock,
124
+ };
125
+
126
+ const store = mockStore(initialStore);
127
+
128
+ mockedAxios.onGet(`undefined/site/global/roles`).reply(200, rolesResponse.data);
129
+ mockedAxios.onGet(`undefined/users`).reply(200, usersResponse.data);
130
+ mockedAxios.onGet(`undefined/sites?recentSitesNumber=0`).reply(200, {});
131
+
132
+ const Component = (
133
+ <Router history={history}>
134
+ <ThemeProvider theme={parseTheme(globalTheme)}>
135
+ <UserList {...defaultProps} />
136
+ </ThemeProvider>
137
+ </Router>
138
+ );
139
+
140
+ await act(async () => {
141
+ render(Component, { store });
142
+ });
143
+
144
+ expect(screen.getByTestId("users-wrapper")).toBeTruthy();
145
+ expect(screen.getByTestId("empty-wrapper")).toBeTruthy();
146
+ expect(screen.queryAllByTestId("user-item").length).toBe(0);
147
+ });
148
+ });
149
+
150
+ describe("UserList module events", () => {
151
+ it("should call action when user click on user", async () => {
152
+ const initialStore = {
153
+ users: usersStoreMock,
154
+ sites: sitesStoreGlobalMock,
155
+ app: appStoreMock,
156
+ };
157
+
158
+ const store = mockStore(initialStore);
159
+
160
+ mockedAxios.onGet(`undefined/site/global/roles`).reply(200, rolesResponse.data);
161
+ mockedAxios.onGet(`undefined/users`).reply(200, usersResponse.data);
162
+ mockedAxios.onGet(`undefined/user/171`).reply(200, userResponse.data);
163
+ mockedAxios.onGet(`undefined/sites?recentSitesNumber=0`).reply(200, {});
164
+
165
+ const Component = (
166
+ <Router history={history}>
167
+ <ThemeProvider theme={parseTheme(globalTheme)}>
168
+ <UserList {...defaultProps} />
169
+ </ThemeProvider>
170
+ </Router>
171
+ );
172
+
173
+ await act(async () => {
174
+ render(Component, { store });
175
+ });
176
+
177
+ const users = screen.queryAllByTestId("user-cell");
178
+ expect(users.length).toBe(3);
179
+
180
+ await act(async () => {
181
+ fireEvent.click(users[0]);
182
+ });
183
+
184
+ expect(store.getActions()).toContainEqual({
185
+ payload: { userForm: userResponse.data },
186
+ type: "users/SET_USER_FORM",
187
+ });
188
+ });
189
+
190
+ it("should delete an user with bulk", async () => {
191
+ const getMockStore = (actions: any[]) => {
192
+ const setUsers = actions.filter((action: any) => action.type === "users/SET_USERS");
193
+ if (setUsers.length >= 2) {
194
+ return {
195
+ users: { ...usersStoreMock, users: deletedUserResponse.data },
196
+ sites: sitesStoreGlobalMock,
197
+ app: appStoreMock,
198
+ };
199
+ } else {
200
+ return {
201
+ users: usersStoreMock,
202
+ sites: sitesStoreGlobalMock,
203
+ app: appStoreMock,
204
+ };
205
+ }
206
+ };
207
+
208
+ const store = mockStore(getMockStore);
209
+
210
+ mockedAxios.onGet(`undefined/site/global/roles`).reply(200, rolesResponse.data);
211
+ mockedAxios.onGet(`undefined/users`).reply(200, usersResponse.data);
212
+ mockedAxios.onGet(`undefined/users?order=dateCreated`).reply(200, deletedUserResponse.data);
213
+ mockedAxios.onDelete("undefined/user/bulk").reply(200, {});
214
+ mockedAxios.onGet(`undefined/sites?recentSitesNumber=0`).reply(200, {});
215
+
216
+ const Component = (
217
+ <Router history={history}>
218
+ <ThemeProvider theme={parseTheme(globalTheme)}>
219
+ <UserList {...defaultProps} />
220
+ </ThemeProvider>
221
+ </Router>
222
+ );
223
+
224
+ await act(async () => {
225
+ render(Component, { store });
226
+ });
227
+
228
+ expect(screen.queryByTestId("user-delete-bulk-modal")).toBeFalsy();
229
+
230
+ expect(screen.queryAllByTestId("user-item").length).toBe(3);
231
+
232
+ await user.click(screen.getByLabelText("Prueba Prueba"));
233
+ await user.click(screen.getByText("delete"));
234
+
235
+ expect(screen.getByTestId("user-delete-bulk-modal")).toBeTruthy();
236
+
237
+ await act(async () => {
238
+ fireEvent.click(screen.getByText("Delete Users"));
239
+ });
240
+
241
+ expect(screen.queryByTestId("user-delete-bulk-modal")).toBeFalsy();
242
+ expect(screen.queryAllByTestId("user-item").length).toBe(2);
243
+
244
+ expect(store.getActions()).toContainEqual({
245
+ payload: { users: deletedUserResponse.data },
246
+ type: "users/SET_USERS",
247
+ });
248
+ });
249
+
250
+ it("should remove an user from site with bulk", async () => {
251
+ const getMockStore = (actions: any[]) => {
252
+ const setUsers = actions.filter((action: any) => action.type === "users/SET_USERS");
253
+ if (setUsers.length >= 2) {
254
+ return {
255
+ users: { ...usersStoreMock, users: removeUserSiteResponse.data },
256
+ sites: sitesStoreMock,
257
+ app: appStoreMock,
258
+ };
259
+ } else {
260
+ return {
261
+ users: usersSiteStoreMock,
262
+ sites: sitesStoreMock,
263
+ app: appStoreMock,
264
+ };
265
+ }
266
+ };
267
+
268
+ const store = mockStore(getMockStore);
269
+
270
+ mockedAxios.onGet(`undefined/site/2/roles`).reply(200, rolesResponse.data);
271
+ mockedAxios.onGet(`undefined/site/2/users`).reply(200, usersSiteResponse.data);
272
+ mockedAxios.onGet(`undefined/site/2/users?order=dateCreated`).reply(200, removeUserSiteResponse.data);
273
+ mockedAxios.onPut("undefined/site/2/restrict").reply(200, {});
274
+ mockedAxios.onGet(`undefined/sites?recentSitesNumber=0`).reply(200, {});
275
+
276
+ const Component = (
277
+ <Router history={history}>
278
+ <ThemeProvider theme={parseTheme(globalTheme)}>
279
+ <UserList {...defaultProps} />
280
+ </ThemeProvider>
281
+ </Router>
282
+ );
283
+
284
+ await act(async () => {
285
+ render(Component, { store });
286
+ });
287
+
288
+ expect(screen.queryByTestId("user-delete-bulk-modal")).toBeFalsy();
289
+
290
+ expect(screen.queryAllByTestId("user-item").length).toBe(2);
291
+
292
+ await user.click(screen.getByLabelText("Admin"));
293
+ await user.click(screen.getByText("Remove from this site"));
294
+
295
+ expect(screen.getByTestId("user-delete-bulk-modal")).toBeTruthy();
296
+
297
+ await act(async () => {
298
+ const button = screen.getAllByText("Remove from this site");
299
+ fireEvent.click(button[1]);
300
+ });
301
+
302
+ expect(screen.queryByTestId("user-delete-bulk-modal")).toBeFalsy();
303
+ expect(screen.queryAllByTestId("user-item").length).toBe(1);
304
+
305
+ expect(store.getActions()).toContainEqual({
306
+ payload: { users: removeUserSiteResponse.data },
307
+ type: "users/SET_USERS",
308
+ });
309
+ });
310
+ });
package/src/api/index.tsx CHANGED
@@ -16,6 +16,7 @@ import users from "./users";
16
16
  import domains from "./domains";
17
17
  import redirects from "./redirects";
18
18
  import analytics from "./analytics";
19
+ import roles from "./roles";
19
20
  import integrations from "./integrations";
20
21
 
21
22
  export {
@@ -37,5 +38,6 @@ export {
37
38
  domains,
38
39
  redirects,
39
40
  analytics,
41
+ roles,
40
42
  integrations,
41
43
  };
@@ -0,0 +1,77 @@
1
+ import { IGetRoles, IActivateRole } from "@ax/types";
2
+ import { AxiosResponse } from "axios";
3
+ import { template } from "./config";
4
+ import { IServiceConfig, sendInitialRequest, sendRequest } from "./utils";
5
+
6
+ const SERVICES: { [key: string]: IServiceConfig } = {
7
+ GET_ROLES: {
8
+ ...template,
9
+ endpoint: "/roles",
10
+ method: "GET",
11
+ },
12
+ GET_SITE_ROLES: {
13
+ ...template,
14
+ endpoint: ["/site/", "/roles"],
15
+ method: "GET",
16
+ },
17
+ ACTIVATE_ROLE: {
18
+ ...template,
19
+ endpoint: ["/role/", "/site"],
20
+ method: "PUT",
21
+ },
22
+ ACTIVATE_ROLE_BULK: {
23
+ ...template,
24
+ endpoint: ["/site/", "/role/activate/bulk"],
25
+ method: "POST",
26
+ },
27
+ };
28
+
29
+ const getRoles = async (params: IGetRoles, token?: string): Promise<AxiosResponse> => {
30
+ const {
31
+ host,
32
+ endpoint: [prefix, suffix],
33
+ } = SERVICES.GET_SITE_ROLES;
34
+ const { siteId, order } = params;
35
+
36
+ const BASE_URL = `${host}${prefix}${siteId}${suffix}`;
37
+
38
+ SERVICES.GET_SITE_ROLES.dynamicUrl = order ? `${BASE_URL}/?order=${order}` : `${BASE_URL}`;
39
+
40
+ if (token) {
41
+ return sendInitialRequest(SERVICES.GET_SITE_ROLES, token);
42
+ } else {
43
+ return sendRequest(SERVICES.GET_SITE_ROLES);
44
+ }
45
+ };
46
+
47
+ const activateRole = async (params: IActivateRole): Promise<AxiosResponse> => {
48
+ const {
49
+ host,
50
+ endpoint: [prefix, suffix],
51
+ } = SERVICES.ACTIVATE_ROLE;
52
+ const { id, siteId, active } = params;
53
+
54
+ SERVICES.ACTIVATE_ROLE.dynamicUrl = `${host}${prefix}${id}${suffix}/${siteId}/activate`;
55
+ const data = { active };
56
+
57
+ return sendRequest(SERVICES.ACTIVATE_ROLE, { ...data });
58
+ };
59
+
60
+ const activateRolesBulk = async (params: IActivateRole): Promise<AxiosResponse> => {
61
+ const {
62
+ host,
63
+ endpoint: [prefix, suffix],
64
+ } = SERVICES.ACTIVATE_ROLE_BULK;
65
+ const { id, siteId, active } = params;
66
+
67
+ SERVICES.ACTIVATE_ROLE_BULK.dynamicUrl = `${host}${prefix}${siteId}${suffix}`;
68
+ const data = { active, roles: id };
69
+
70
+ return sendRequest(SERVICES.ACTIVATE_ROLE_BULK, { ...data });
71
+ };
72
+
73
+ export default {
74
+ getRoles,
75
+ activateRole,
76
+ activateRolesBulk,
77
+ };
package/src/api/users.tsx CHANGED
@@ -7,6 +7,11 @@ const SERVICES: { [key: string]: IServiceConfig } = {
7
7
  endpoint: "/users",
8
8
  method: "GET",
9
9
  },
10
+ GET_SITE_USERS: {
11
+ ...template,
12
+ endpoint: ["/site/", "/users"],
13
+ method: "GET",
14
+ },
10
15
  GET_USER: {
11
16
  ...template,
12
17
  endpoint: "/user/",
@@ -58,6 +63,20 @@ const getUsers = async (params: any) => {
58
63
  return sendRequest(SERVICES.GET_USERS);
59
64
  };
60
65
 
66
+ const getSiteUsers = async (params: any, siteID: number) => {
67
+ const { host, endpoint: [prefix, suffix], } = SERVICES.GET_SITE_USERS;
68
+
69
+ const { query, filterQuery } = params;
70
+
71
+ SERVICES.GET_SITE_USERS.dynamicUrl = `${host}${prefix}${siteID}${suffix}${filterQuery}`;
72
+
73
+ if (query && query.trim() !== "") {
74
+ SERVICES.GET_SITE_USERS.dynamicUrl = `${SERVICES.GET_USERS.dynamicUrl}${query}`;
75
+ }
76
+
77
+ return sendRequest(SERVICES.GET_SITE_USERS);
78
+ };
79
+
61
80
  const getUser = async (id: string | number, token?: string) => {
62
81
  const { host, endpoint } = SERVICES.GET_USER;
63
82
 
@@ -74,7 +93,7 @@ const updateUser = async (id: number, data: any) => {
74
93
  return sendRequest(SERVICES.UPDATE_USER, data);
75
94
  };
76
95
 
77
- const updatePassword = async (id: string, data: any) => {
96
+ const updatePassword = async (id: number, data: any) => {
78
97
  const {
79
98
  host,
80
99
  endpoint: [prefix, suffix],
@@ -113,6 +132,7 @@ const resendInvitation = async (id: number) => {
113
132
 
114
133
  export default {
115
134
  getUsers,
135
+ getSiteUsers,
116
136
  getUser,
117
137
  updateUser,
118
138
  updatePassword,
@@ -120,4 +140,4 @@ export default {
120
140
  deleteUser,
121
141
  deleteUserBulk,
122
142
  resendInvitation,
123
- };
143
+ };
@@ -7,6 +7,8 @@ import * as S from "./style";
7
7
  const ActionMenu = (props: IActionMenuProps): JSX.Element => {
8
8
  const { options, icon, className, tooltip } = props;
9
9
 
10
+ const filteredOptions = options.filter((option: IOption | undefined | null) => !!option);
11
+
10
12
  const MoreInfoButton = () => (
11
13
  <S.IconActionWrapper data-testid="more-info-button">
12
14
  <IconAction icon={icon} />
@@ -33,11 +35,15 @@ const ActionMenu = (props: IActionMenuProps): JSX.Element => {
33
35
 
34
36
  return options.length > 0 ? (
35
37
  <S.Wrapper className={className} data-testid="action-menu-wrapper">
36
- <Tooltip content={tooltip} hideOnClick>
37
- <FloatingMenu Button={MoreInfoButton}>
38
- <S.ActionMenu>{options.map((item: IOption) => ActionMenuItem(item))}</S.ActionMenu>
39
- </FloatingMenu>
40
- </Tooltip>
38
+ {filteredOptions.length > 0 && (
39
+ <Tooltip content={tooltip} hideOnClick>
40
+ <FloatingMenu Button={MoreInfoButton}>
41
+ <S.ActionMenu>
42
+ {filteredOptions.map((item: IOption | undefined | null) => item && ActionMenuItem(item))}
43
+ </S.ActionMenu>
44
+ </FloatingMenu>
45
+ </Tooltip>
46
+ )}
41
47
  </S.Wrapper>
42
48
  ) : (
43
49
  <></>
@@ -54,7 +60,7 @@ interface IOption {
54
60
  }
55
61
 
56
62
  export interface IActionMenuProps {
57
- options: IOption[];
63
+ options: (IOption | undefined | null)[];
58
64
  icon: string;
59
65
  className?: string;
60
66
  tooltip?: string;
@@ -1,13 +1,14 @@
1
1
  import React from "react";
2
2
  import { getInitials } from "@ax/helpers";
3
+
3
4
  import * as S from "./style";
4
5
 
5
6
  const Avatar = (props: IAvatarProps): JSX.Element => {
6
- const { image, name } = props;
7
+ const { image, name, size } = props;
7
8
 
8
9
  return (
9
- <S.AvatarWrapper data-testid="avatar-wrapper">
10
- <S.Avatar image={image} initials={getInitials(name)} data-testid="avatar" />
10
+ <S.AvatarWrapper data-testid="avatar-wrapper" size={size}>
11
+ <S.Avatar image={image} initials={getInitials(name)} data-testid="avatar" size={size} />
11
12
  </S.AvatarWrapper>
12
13
  );
13
14
  };
@@ -15,6 +16,7 @@ const Avatar = (props: IAvatarProps): JSX.Element => {
15
16
  export interface IAvatarProps {
16
17
  image?: string | null;
17
18
  name?: string;
19
+ size?: string;
18
20
  }
19
21
 
20
22
  export default Avatar;
@@ -1,16 +1,15 @@
1
1
  import styled from "styled-components";
2
2
 
3
- const AvatarWrapper = styled.div`
4
- width: 32px;
5
- height: 32px;
3
+ const AvatarWrapper = styled.div<{ size?: string }>`
4
+ width: ${(p) => (p.size === "s" ? " 24px" : "32px")};
5
+ height: ${(p) => (p.size === "s" ? " 24px" : "32px")};
6
6
  `;
7
7
 
8
- const Avatar = styled.div<{image?: string | null, initials: string}>`
8
+ const Avatar = styled.span<{ image?: string | null; initials: string; size?: string }>`
9
9
  border-radius: 50%;
10
- width: 32px;
11
- height: 32px;
12
- background: ${(p) => `url(${p.image})`},
13
- ${(p) => p.theme.colors.uiBackground03};
10
+ width: ${(p) => (p.size === "s" ? " 24px" : "32px")};
11
+ height: ${(p) => (p.size === "s" ? " 24px" : "32px")};
12
+ background: ${(p) => `url(${p.image})`}, ${(p) => p.theme.colors.uiBackground03};
14
13
  background-size: cover;
15
14
  background-repeat: no-repeat;
16
15
  background-position: center center;
@@ -25,4 +24,4 @@ const Avatar = styled.div<{image?: string | null, initials: string}>`
25
24
  }
26
25
  `;
27
26
 
28
- export { AvatarWrapper, Avatar };
27
+ export { AvatarWrapper, Avatar };
@@ -4,11 +4,13 @@ import { Button, CheckField, TableCounter } from "@ax/components";
4
4
 
5
5
  import * as S from "./style";
6
6
 
7
- const BulkSelectionOptions = (props: IBulkSelectionProps) => {
7
+ const BulkSelectionOptions = (props: IBulkSelectionProps): JSX.Element => {
8
8
  const { isScrolling, checkState, actions, selectItems, totalItems } = props;
9
9
 
10
+ const filteredActions = actions.filter((action: IBulkAction | undefined | null) => !!action);
11
+
10
12
  return (
11
- <S.BulkHeader data-testid="bulk-header-wrapper" isScrolling={isScrolling}>
13
+ <S.BulkHeader isScrolling={isScrolling} data-testid="bulk-header-wrapper">
12
14
  <S.BulkActionsWrapper>
13
15
  <S.SelectAllCheckField>
14
16
  <CheckField
@@ -23,11 +25,14 @@ const BulkSelectionOptions = (props: IBulkSelectionProps) => {
23
25
  />
24
26
  </S.SelectAllCheckField>
25
27
  <S.BulkActions>
26
- {actions.map((item: any) => (
27
- <Button key={item.text} type="button" buttonStyle="text" icon={item.icon} onClick={item.action}>
28
- {item.text}
29
- </Button>
30
- ))}
28
+ {filteredActions.map(
29
+ (item: IBulkAction | undefined | null) =>
30
+ item && (
31
+ <Button key={item.text} type="button" buttonStyle="text" icon={item.icon} onClick={item.action}>
32
+ {item.text}
33
+ </Button>
34
+ )
35
+ )}
31
36
  </S.BulkActions>
32
37
  <S.Counter>
33
38
  <TableCounter totalItems={totalItems} />
@@ -37,13 +42,15 @@ const BulkSelectionOptions = (props: IBulkSelectionProps) => {
37
42
  );
38
43
  };
39
44
 
45
+ interface IBulkAction {
46
+ icon?: string;
47
+ text: string;
48
+ action: () => void;
49
+ }
50
+
40
51
  interface IBulkSelectionProps {
41
52
  checkState: any;
42
- actions: {
43
- icon: string;
44
- text: string;
45
- action: () => void;
46
- }[];
53
+ actions: (IBulkAction | undefined | null)[];
47
54
  selectItems: () => void;
48
55
  totalItems: number;
49
56
  isScrolling?: boolean;
@@ -1,6 +1,6 @@
1
1
  import styled from "styled-components";
2
2
 
3
- const BulkHeader = styled.div<{isScrolling?: boolean}>`
3
+ const BulkHeader = styled.div<{ isScrolling?: boolean }>`
4
4
  width: 100%;
5
5
  display: flex;
6
6
  flex-direction: row;
@@ -17,15 +17,16 @@ const BulkActionsWrapper = styled.div`
17
17
  const BulkActions = styled.div`
18
18
  display: flex;
19
19
  margin-top: 2px;
20
+ min-height: 32px;
20
21
  button {
21
22
  margin-right: ${(p) => p.theme.spacing.xs};
22
23
  }
23
24
  `;
24
25
 
25
26
  const SelectAllCheckField = styled.span`
26
- width: ${(p) => p.theme.spacing.s};
27
- margin-right: ${(p) => p.theme.spacing.s};
28
- margin-left: ${(p) => p.theme.spacing.m};
27
+ width: ${(p) => p.theme.spacing.s};
28
+ margin-right: ${(p) => p.theme.spacing.s};
29
+ margin-left: ${(p) => p.theme.spacing.m};
29
30
  `;
30
31
 
31
32
  const Counter = styled.div`
@@ -34,10 +35,4 @@ const Counter = styled.div`
34
35
  align-items: center;
35
36
  `;
36
37
 
37
- export {
38
- BulkHeader,
39
- BulkActionsWrapper,
40
- BulkActions,
41
- SelectAllCheckField,
42
- Counter
43
- }
38
+ export { BulkHeader, BulkActionsWrapper, BulkActions, SelectAllCheckField, Counter };