@griddo/ax 11.10.9 → 11.10.11-rc.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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@griddo/ax",
3
3
  "description": "Griddo Author Experience",
4
- "version": "11.10.9",
4
+ "version": "11.10.11-rc.0",
5
5
  "authors": [
6
6
  "Álvaro Sánchez' <alvaro.sanches@secuoyas.com>",
7
7
  "Diego M. Béjar <diego.bejar@secuoyas.com>",
@@ -144,7 +144,7 @@
144
144
  "styled-system": "5.1.5",
145
145
  "terser-webpack-plugin": "1.4.1",
146
146
  "ts-pnp": "1.1.4",
147
- "typescript": "4.9.5",
147
+ "typescript": "5.9.3",
148
148
  "url-loader": "4.1.1",
149
149
  "uuid": "8.3.2",
150
150
  "webpack": "4.47.0",
@@ -225,5 +225,5 @@
225
225
  "publishConfig": {
226
226
  "access": "public"
227
227
  },
228
- "gitHead": "32171f05ac5a14855b99acf6fab5cd0c731a1e06"
228
+ "gitHead": "e3fdee4be8b2129da8b54ca6a9fc7e6bddc2ad80"
229
229
  }
@@ -284,10 +284,7 @@ describe("SideModal component events", () => {
284
284
  <SideModal {...defaultProps} />
285
285
  </ThemeProvider>
286
286
  );
287
- const filterButton = screen.getByTestId("icon-search-wrapper");
288
287
 
289
- expect(filterButton).toBeTruthy();
290
- fireEvent.click(filterButton);
291
288
  const searchFieldWrapper = screen.getByTestId("search-field-wrapper");
292
289
  expect(searchFieldWrapper).toBeTruthy();
293
290
  const input = screen.getByTestId("search-input");
@@ -9,7 +9,14 @@ const MenuItem = (props: IMenuItemProps): JSX.Element => {
9
9
  const handleOnClick = (e: React.MouseEvent<HTMLLIElement>) => {
10
10
  if (onClick !== undefined && !disabled) {
11
11
  e.preventDefault();
12
- onClick(e);
12
+ onClick();
13
+ }
14
+ };
15
+
16
+ const handleOnKeyDown = (e: React.KeyboardEvent<HTMLLIElement>) => {
17
+ if (e.key === "Enter" && onClick !== undefined && !disabled) {
18
+ e.preventDefault();
19
+ onClick();
13
20
  }
14
21
  };
15
22
 
@@ -25,6 +32,9 @@ const MenuItem = (props: IMenuItemProps): JSX.Element => {
25
32
  onlyOnHover={(extendedAction && extendedAction.onlyOnHover) ?? true}
26
33
  data-testid="menu-subitem"
27
34
  disabled={disabled}
35
+ tabIndex={0}
36
+ onKeyDown={handleOnKeyDown}
37
+ role="button"
28
38
  >
29
39
  <div>{children}</div>
30
40
  {extendedAction && (
@@ -40,7 +50,7 @@ const MenuItem = (props: IMenuItemProps): JSX.Element => {
40
50
 
41
51
  export interface IMenuItemProps {
42
52
  children: JSX.Element | string;
43
- onClick?: (e: React.MouseEvent<HTMLLIElement>) => void;
53
+ onClick?: () => void;
44
54
  extendedAction?: { icon: string; action?: () => void; onlyOnHover?: boolean } | null;
45
55
  className?: string;
46
56
  disabled?: boolean;
@@ -1,5 +1,5 @@
1
1
  import { Icon } from "@ax/components";
2
- import React, { useEffect, useState } from "react";
2
+ import React, { useEffect, useRef, useState } from "react";
3
3
  import { Select } from "../Fields";
4
4
 
5
5
  import * as S from "./style";
@@ -22,6 +22,14 @@ const SearchField = (props: ISearchFieldProps): JSX.Element => {
22
22
  const [isOpen, setIsOpen] = useState(value && value.trim() !== "" ? true : false);
23
23
  const [inputValue, setInputValue] = useState(value || "");
24
24
  const [selectValue, setSelectValue] = useState<string>("");
25
+ const inputRef = useRef<HTMLInputElement | null>(null);
26
+ const showField = isOpen || !closeOnInactive;
27
+
28
+ useEffect(() => {
29
+ if (focus && showField && inputRef.current) {
30
+ inputRef.current.focus();
31
+ }
32
+ }, [focus, showField]);
25
33
 
26
34
  useEffect(() => {
27
35
  if (value !== inputValue) {
@@ -66,8 +74,6 @@ const SearchField = (props: ISearchFieldProps): JSX.Element => {
66
74
  onFilterChange && onFilterChange(value);
67
75
  };
68
76
 
69
- const showField = isOpen || !closeOnInactive;
70
-
71
77
  return (
72
78
  <S.Wrapper data-testid="search-field-wrapper">
73
79
  {showField ? (
@@ -97,8 +103,7 @@ const SearchField = (props: ISearchFieldProps): JSX.Element => {
97
103
  disabled={disabled}
98
104
  data-testid="search-input"
99
105
  small={small}
100
- // eslint-disable-next-line jsx-a11y/no-autofocus
101
- autoFocus={focus && showField}
106
+ ref={inputRef}
102
107
  inputSize={size}
103
108
  name="searchInput"
104
109
  />
@@ -29,6 +29,12 @@ const SideModalOption = (props: IProps) => {
29
29
  }
30
30
  };
31
31
 
32
+ const handleKeyDown = (e: React.KeyboardEvent) => {
33
+ if (e.key === "Enter") {
34
+ setOption();
35
+ }
36
+ };
37
+
32
38
  const defaultTag = option.tag ? (
33
39
  <S.TagWrapper data-testid="side-modal-option-tag">
34
40
  <Tag text={option.tag} type="square" />
@@ -36,7 +42,7 @@ const SideModalOption = (props: IProps) => {
36
42
  ) : null;
37
43
 
38
44
  return (
39
- <S.Item onClick={setOption} data-testid="side-modal-option">
45
+ <S.Item onClick={setOption} tabIndex={0} onKeyDown={handleKeyDown} role="button" data-testid="side-modal-option">
40
46
  <S.Thumbnail data-testid="side-modal-option-img" {...thumbnailProps} />
41
47
  {label}
42
48
  {defaultTag}
@@ -37,6 +37,22 @@ const SideModal = (props: ISideModalProps): JSX.Element | null => {
37
37
  const [searchQuery, setSearchQuery] = useState("");
38
38
  const node = useRef<HTMLDivElement | null>(null);
39
39
 
40
+ useEffect(() => {
41
+ const handleKeyPress = (event: KeyboardEvent) => {
42
+ if (event.key === "Escape") {
43
+ toggleModal();
44
+ }
45
+ };
46
+
47
+ if (isOpen) {
48
+ document.addEventListener("keydown", handleKeyPress);
49
+ }
50
+
51
+ return () => {
52
+ document.removeEventListener("keydown", handleKeyPress);
53
+ };
54
+ }, [isOpen, toggleModal]);
55
+
40
56
  useEffect(() => {
41
57
  if (componentOptions) {
42
58
  for (const key in componentOptions) {
@@ -143,32 +159,39 @@ const SideModal = (props: ISideModalProps): JSX.Element | null => {
143
159
  });
144
160
 
145
161
  return createPortal(
146
- <>
147
- <S.Wrapper ref={node} optionsType={optionsType} isOpen={isOpen} data-testid="side-modal">
148
- <S.Header>
149
- <S.Title data-testid="side-modal-title">{optionsType}</S.Title>
150
- {showSearch && optionsType !== "components" && (
151
- <S.SearchWrapper>
152
- <SearchField onChange={setSearchQuery} closeOnInactive={true} small={!filters} value={searchQuery} />
153
- </S.SearchWrapper>
154
- )}
155
- {!showSearch && (
162
+ <S.Wrapper ref={node} optionsType={optionsType} isOpen={isOpen} data-testid="side-modal">
163
+ {isOpen && (
164
+ <>
165
+ <S.Header>
166
+ <S.Title data-testid="side-modal-title">{optionsType}</S.Title>
156
167
  <S.ButtonWrapper data-testid="side-modal-close-button">
157
168
  <IconAction icon="close" onClick={handleCloseModal} />
158
169
  </S.ButtonWrapper>
159
- )}
160
- </S.Header>
161
- <S.ColumnsWrapper>
162
- {(filters || featuredFilters) && (
170
+ </S.Header>
171
+ <S.ColumnsWrapper>
172
+ {(filters || featuredFilters) && (
173
+ <S.FilterContent>
174
+ {featuredFilters && <S.FeaturedWrapper>{featuredFilters}</S.FeaturedWrapper>}
175
+ {filters && <div>{filters}</div>}
176
+ </S.FilterContent>
177
+ )}
163
178
  <S.Content>
164
- {featuredFilters && <S.FeaturedWrapper>{featuredFilters}</S.FeaturedWrapper>}
165
- {filters && <div>{filters}</div>}
179
+ {showSearch && optionsType !== "components" && (
180
+ <S.SearchWrapper>
181
+ <SearchField
182
+ onChange={setSearchQuery}
183
+ value={searchQuery}
184
+ searchOnEnter={false}
185
+ placeholder="Search"
186
+ />
187
+ </S.SearchWrapper>
188
+ )}
189
+ {filteredOptions}
166
190
  </S.Content>
167
- )}
168
- <S.Content>{filteredOptions}</S.Content>
169
- </S.ColumnsWrapper>
170
- </S.Wrapper>
171
- </>,
191
+ </S.ColumnsWrapper>
192
+ </>
193
+ )}
194
+ </S.Wrapper>,
172
195
  document.body
173
196
  );
174
197
  };
@@ -18,9 +18,22 @@ const Header = styled.div`
18
18
  }
19
19
  `;
20
20
 
21
+ const FilterContent = styled.div`
22
+ list-style: none;
23
+ padding: ${(p) => p.theme.spacing.s};
24
+ height: ${(p) => `calc(100vh - ${p.theme.spacing.xl})`};
25
+ width: ${(p) => `calc(${p.theme.spacing.xl} * 3)`};
26
+ overflow: auto;
27
+ border-right: 1px solid ${(p) => p.theme.colors.uiLine};
28
+ &:last-child {
29
+ border-right: 0;
30
+ width: ${(p) => `calc(${p.theme.spacing.xl} * 4)`};
31
+ }
32
+ `;
33
+
21
34
  const Content = styled.div`
22
35
  list-style: none;
23
- padding: ${(p) => p.theme.spacing.m};
36
+ padding: ${(p) => `${p.theme.spacing.s} ${p.theme.spacing.m}`};
24
37
  height: ${(p) => `calc(100vh - ${p.theme.spacing.xl})`};
25
38
  width: ${(p) => `calc(${p.theme.spacing.xl} * 3)`};
26
39
  overflow: auto;
@@ -43,20 +56,6 @@ const Wrapper = styled.div<{ optionsType?: string; isOpen: boolean }>`
43
56
  box-shadow: ${(p) =>
44
57
  p.optionsType && placeRight.includes(p.optionsType) ? p.theme.shadow.rightPanel : p.theme.shadow.leftPanel};
45
58
  transition: all 0.5s ease-in-out;
46
-
47
- &.form-fields {
48
- margin-top: ${(p) => p.theme.spacing.xl};
49
-
50
- ${Header} {
51
- padding: ${(p) => `${p.theme.spacing.s} ${p.theme.spacing.s} 0`};
52
- background-color: transparent;
53
- border-bottom: none;
54
- }
55
-
56
- ${Content} {
57
- padding: ${(p) => p.theme.spacing.s};
58
- }
59
- }
60
59
  `;
61
60
 
62
61
  const Title = styled.h6`
@@ -78,7 +77,7 @@ const FeaturedWrapper = styled.div`
78
77
 
79
78
  const SearchWrapper = styled.div`
80
79
  width: 100%;
81
- margin-left: ${(p) => p.theme.spacing.s};
80
+ margin-bottom: ${(p) => p.theme.spacing.s};
82
81
  `;
83
82
 
84
83
  const Link = styled.div<{ active: boolean }>`
@@ -116,6 +115,7 @@ const ClosedFloatingButtonWrapper = styled.div`
116
115
 
117
116
  export {
118
117
  Wrapper,
118
+ FilterContent,
119
119
  Content,
120
120
  Header,
121
121
  Title,
@@ -622,18 +622,30 @@ function updatePageStatus(
622
622
  const validIds = ids.filter((id) => !pagesWithErrors.includes(id));
623
623
  if (!validIds.length) return false;
624
624
 
625
- const response = await pages.setPageStatus(status, validIds);
626
- const isUpdatingFromPageEditor = isReqOk(response.status) && !updatedFromList;
627
- if (isUpdatingFromPageEditor) {
628
- const currentPageID = ids[0];
629
- const updatedContent = await pages.getPageInfo(currentPageID);
630
- const mappedData = parseData(updatedContent.data, true);
631
- const { pageContent } = generateEditorIDs({ ...mappedData, header, footer });
632
- dispatch(setEditorContent(pageContent));
633
- dispatch(setCurrentPageStatus(status));
634
- }
635
- dispatch(setIsSaving(false));
636
- return true;
625
+ const responseActions = {
626
+ handleSuccess: async () => {
627
+ if (!updatedFromList) {
628
+ const currentPageID = ids[0];
629
+ const updatedContent = await pages.getPageInfo(currentPageID);
630
+ const mappedData = parseData(updatedContent.data, true);
631
+ const { pageContent } = generateEditorIDs({ ...mappedData, header, footer });
632
+ dispatch(setEditorContent(pageContent));
633
+ dispatch(setCurrentPageStatus(status));
634
+ }
635
+ },
636
+ handleError: (response: any) => {
637
+ const {
638
+ data: { message },
639
+ } = response;
640
+ const isMultiple = Array.isArray(message) && message.length > 1;
641
+ const msg = isMultiple ? `This action failed due to ${message.length} errors.` : undefined;
642
+ appActions.handleError(response, isMultiple, msg)(dispatch);
643
+ },
644
+ };
645
+
646
+ const callback = async () => await pages.setPageStatus(status, validIds);
647
+
648
+ return await handleRequest(callback, responseActions, [setIsSaving])(dispatch);
637
649
  } catch (e) {
638
650
  dispatch(setIsSaving(false));
639
651
  console.log(e); // TODO: capturar error bien