@griddo/ax 10.7.3 → 10.7.5

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": "10.7.3",
4
+ "version": "10.7.5",
5
5
  "authors": [
6
6
  "Álvaro Sánchez' <alvaro.sanches@secuoyas.com>",
7
7
  "Carlos Torres <carlos.torres@secuoyas.com>",
@@ -68,8 +68,8 @@
68
68
  "@types/styled-components": "^5.1.25",
69
69
  "@types/uuid": "^8.3.1",
70
70
  "@types/webpack-env": "^1.14.1",
71
- "@typescript-eslint/eslint-plugin": "^4.25.0",
72
- "@typescript-eslint/parser": "^4.25.0",
71
+ "@typescript-eslint/eslint-plugin": "^5.45.0",
72
+ "@typescript-eslint/parser": "^6.0.0",
73
73
  "add": "^2.0.6",
74
74
  "axios": "0.19.0",
75
75
  "babel-eslint": "10.0.3",
@@ -127,7 +127,7 @@
127
127
  "react-dev-utils": "^11.0.4",
128
128
  "react-dom": "*",
129
129
  "react-draft-wysiwyg": "^1.14.5",
130
- "react-error-boundary": "^4.0.13",
130
+ "react-error-boundary": "4.0.13",
131
131
  "react-frame-component": "^5.2.1",
132
132
  "react-froala-wysiwyg": "^3.2.7",
133
133
  "react-redux": "^7.2.8",
@@ -172,14 +172,10 @@
172
172
  "@types/redux-mock-store": "^1.0.3",
173
173
  "axios-mock-adapter": "^1.21.2",
174
174
  "babel-jest": "^27.5.1",
175
- "eslint": "^6.1.0",
176
- "eslint-config-prettier": "^8.3.0",
177
- "eslint-config-react-app": "^5.0.2",
175
+ "eslint": "^8.0.0",
178
176
  "eslint-loader": "^4.0.2",
179
- "eslint-plugin-flowtype": "^5.7.2",
180
177
  "eslint-plugin-import": "^2.23.4",
181
178
  "eslint-plugin-jsx-a11y": "6.2.3",
182
- "eslint-plugin-prettier": "^3.4.0",
183
179
  "eslint-plugin-react": "7.14.3",
184
180
  "eslint-plugin-react-hooks": "^4.2.0",
185
181
  "jest": "^27.5.1",
@@ -233,5 +229,5 @@
233
229
  "publishConfig": {
234
230
  "access": "public"
235
231
  },
236
- "gitHead": "e4765708d342635b3d58af6605256d90671d2ef3"
232
+ "gitHead": "ca217179ef41baa77477ed501255237aef123fa0"
237
233
  }
@@ -117,6 +117,9 @@ const initialStore = {
117
117
  sites: {
118
118
  themeElements: null,
119
119
  },
120
+ pageEditor: {
121
+ scrollEditorID: null,
122
+ },
120
123
  };
121
124
 
122
125
  const store = mockStore(initialStore);
@@ -193,6 +193,7 @@ export interface IBrowserProps {
193
193
  setSelectedContentAction: any;
194
194
  deleteModuleAction(editorID: number[]): void;
195
195
  duplicateModuleAction(editorID: number[]): number;
196
+ setScrollEditorIDAction(editorID: number | null): void;
196
197
  };
197
198
  }
198
199
 
@@ -20,6 +20,7 @@ const BrowserContent = (props: IProps) => {
20
20
  selectEditorID,
21
21
  moduleActions,
22
22
  renderer,
23
+ selectHoverEditorID,
23
24
  } = props;
24
25
 
25
26
  const API_URL = process.env.REACT_APP_API_ENDPOINT;
@@ -31,6 +32,7 @@ const BrowserContent = (props: IProps) => {
31
32
  builderSSR.onRenderBody(ssrHelpers);
32
33
  }
33
34
  }, []);
35
+
34
36
  useEffect(useInstanceExternalAssets, [useInstanceExternalAssets]);
35
37
 
36
38
  return (
@@ -46,6 +48,7 @@ const BrowserContent = (props: IProps) => {
46
48
  instance={INSTANCE}
47
49
  siteId={siteID}
48
50
  moduleActions={moduleActions}
51
+ selectHoverEditorID={selectHoverEditorID}
49
52
  >
50
53
  <Preview
51
54
  isPage={isPage}
@@ -79,6 +82,7 @@ interface IProps {
79
82
  parentComponent: string | undefined | null,
80
83
  e: React.SyntheticEvent
81
84
  ): void;
85
+ selectHoverEditorID?(editorID: number): void;
82
86
  moduleActions?: {
83
87
  deleteModuleAction(editorID: number): void;
84
88
  duplicateModuleAction(editorID: number): void;
@@ -30,6 +30,7 @@ const Field = (props: IFieldProps): JSX.Element => {
30
30
  template,
31
31
  setHistoryPush,
32
32
  languages,
33
+ scrollEditorID,
33
34
  } = props;
34
35
  const isGroup = field.type === "FieldGroup";
35
36
  const isCollapsed = isGroup && field.collapsed;
@@ -83,6 +84,7 @@ const Field = (props: IFieldProps): JSX.Element => {
83
84
  template={template}
84
85
  setHistoryPush={setHistoryPush}
85
86
  languages={languages}
87
+ scrollEditorID={scrollEditorID}
86
88
  />
87
89
  );
88
90
  };
@@ -113,6 +115,7 @@ export interface IFieldProps {
113
115
  template: any;
114
116
  setHistoryPush?: (path: string, isEditor: boolean) => void;
115
117
  languages?: ILanguage[];
118
+ scrollEditorID: number | null;
116
119
  }
117
120
 
118
121
  export default Field;
@@ -30,6 +30,7 @@ export const TemplateManager = (props: IProps): JSX.Element => {
30
30
  setHistoryPush,
31
31
  lang,
32
32
  themeElements,
33
+ scrollEditorID,
33
34
  } = props;
34
35
 
35
36
  const isConfig = selectedTab === "config";
@@ -124,6 +125,7 @@ export const TemplateManager = (props: IProps): JSX.Element => {
124
125
  setHistoryPush={setHistoryPush}
125
126
  lang={lang}
126
127
  readonly={readonly}
128
+ scrollEditorID={scrollEditorID}
127
129
  />
128
130
  );
129
131
  })}
@@ -153,12 +155,14 @@ interface IProps {
153
155
  setHistoryPush?: (path: string, isEditor: boolean) => void;
154
156
  lang: number;
155
157
  themeElements: IThemeElements | null;
158
+ scrollEditorID: number | null;
156
159
  }
157
160
 
158
161
  const mapStateToProps = (state: IRootState) => ({
159
162
  activatedPacks: state.dataPacks.activated,
160
163
  availableDataPacks: state.dataPacks.available,
161
164
  themeElements: state.sites.themeElements,
165
+ scrollEditorID: state.pageEditor.scrollEditorID,
162
166
  });
163
167
 
164
168
  export default connect(mapStateToProps)(TemplateManager);
@@ -47,6 +47,7 @@ const PageConnectedField = (props: any) => {
47
47
  languages,
48
48
  isReadOnly,
49
49
  themeElements,
50
+ scrollEditorID,
50
51
  } = props;
51
52
 
52
53
  const isTemplate = field.type === "template";
@@ -204,6 +205,7 @@ const PageConnectedField = (props: any) => {
204
205
  template={template}
205
206
  setHistoryPush={setHistoryPush}
206
207
  languages={languages}
208
+ scrollEditorID={scrollEditorID}
207
209
  />
208
210
  );
209
211
  };
@@ -223,6 +225,7 @@ const mapStateToProps = (state: IRootState) => ({
223
225
  template: state.pageEditor.template,
224
226
  languages: state.sites.currentSiteLanguages,
225
227
  themeElements: state.sites.themeElements,
228
+ scrollEditorID: state.pageEditor.scrollEditorID,
226
229
  });
227
230
 
228
231
  const mapDispatchToProps = {
@@ -82,4 +82,5 @@ export interface IFieldContainerProps {
82
82
  template?: any;
83
83
  setHistoryPush?: (path: string, isEditor: boolean) => void;
84
84
  languages?: ILanguage[];
85
+ scrollEditorID?: number | null;
85
86
  }
@@ -33,6 +33,7 @@ const MixableComponentArray = (props: IMixableComponentArrayProps): JSX.Element
33
33
  availableDataPacks,
34
34
  template,
35
35
  setHistoryPush,
36
+ scrollEditorID,
36
37
  } = props;
37
38
 
38
39
  const {
@@ -61,6 +62,8 @@ const MixableComponentArray = (props: IMixableComponentArrayProps): JSX.Element
61
62
  field
62
63
  );
63
64
 
65
+ const selectedID = parseInt(localStorage.getItem("selectedID") || "0");
66
+
64
67
  const { isOpen, toggleModal } = useModal();
65
68
  const [isBulkOpen, setIsBulkOpen] = useState(false);
66
69
  const [draggingId, setDraggingId] = useState<number | null>(null);
@@ -129,6 +132,7 @@ const MixableComponentArray = (props: IMixableComponentArrayProps): JSX.Element
129
132
  const isDraggingSelected = selectedItems.all.includes(draggingId);
130
133
  const isGhosting = isItemSelected && !!draggingId && draggingId !== editorID && isDraggingSelected;
131
134
  const isMultiDragging = selectedItems.all.length > 1 && draggingId === editorID;
135
+ const isActive = scrollEditorID === editorID;
132
136
 
133
137
  return (
134
138
  <Draggable draggableId={`${editorID}`} index={i} key={editorID}>
@@ -160,7 +164,10 @@ const MixableComponentArray = (props: IMixableComponentArrayProps): JSX.Element
160
164
  toggleToast={toggleToast}
161
165
  isMultiDragging={snapshot.isDragging && isMultiDragging}
162
166
  draggingCount={selectedItems.all.length}
163
- className={`${isGhosting ? "ghosting" : ""} ${snapshot.isDragging && isMultiDragging ? "dragging" : ""}`}
167
+ isActive={selectedID === editorID}
168
+ className={`${isGhosting ? "ghosting" : ""} ${snapshot.isDragging && isMultiDragging ? "dragging" : ""} ${
169
+ isActive ? "active" : ""
170
+ }`}
164
171
  />
165
172
  )}
166
173
  </Draggable>
@@ -337,6 +344,7 @@ export interface IMixableComponentArrayProps {
337
344
  availableDataPacks: Record<string, any>[];
338
345
  template: any;
339
346
  setHistoryPush?: (path: string, isEditor: boolean) => void;
347
+ scrollEditorID: number | null;
340
348
  }
341
349
 
342
350
  export default MixableComponentArray;
@@ -41,6 +41,7 @@ const ComponentContainer = (props: IComponentContainerProps): JSX.Element => {
41
41
  className,
42
42
  isMultiDragging = false,
43
43
  draggingCount = 0,
44
+ isActive = false,
44
45
  } = props;
45
46
 
46
47
  const { addComponentAction, deleteModuleAction, duplicateModuleAction, copyModuleAction, replaceModuleAction } =
@@ -177,6 +178,7 @@ const ComponentContainer = (props: IComponentContainerProps): JSX.Element => {
177
178
  className={`editorId-${editorID} ${className}`}
178
179
  onClick={handleClick}
179
180
  ref={innerRef}
181
+ isActive={isActive}
180
182
  data-testid="component-container"
181
183
  {...provided?.draggableProps}
182
184
  {...dragProps}
@@ -257,6 +259,7 @@ export interface IComponentContainerProps {
257
259
  className?: string;
258
260
  isMultiDragging?: boolean;
259
261
  draggingCount?: number;
262
+ isActive?: boolean;
260
263
  }
261
264
 
262
265
  export default ComponentContainer;
@@ -24,14 +24,14 @@ const HiddenButtonsWrapper = styled.span`
24
24
  opacity: 0;
25
25
  `;
26
26
 
27
- const Component = styled.span<{ disabled?: boolean }>`
27
+ const Component = styled.span<{ disabled?: boolean; isActive: boolean }>`
28
28
  color: ${(p) => p.theme.color.textHighEmphasis};
29
29
  position: relative;
30
30
  display: flex;
31
31
  align-items: center;
32
32
  width: 100%;
33
33
  background: ${(p) => p.theme.color.uiBackground02};
34
- border: 1px solid transparent;
34
+ border: 1px solid ${(p) => (p.isActive ? p.theme.color.interactive01 : "transparent")};
35
35
  margin-bottom: ${(p) => p.theme.spacing.xs};
36
36
  padding: calc(${(p) => p.theme.spacing.xs} - 1px) ${(p) => p.theme.spacing.xs};
37
37
  border-radius: ${(p) => p.theme.radii.s};
@@ -41,8 +41,9 @@ const Component = styled.span<{ disabled?: boolean }>`
41
41
  cursor: ${(p) => (p.disabled ? `default` : `pointer`)};
42
42
  min-height: 48px;
43
43
 
44
- &:hover {
45
- border: 1px solid ${(p) => p.theme.color.overlayHoverPrimary};
44
+ &:hover,
45
+ &.active {
46
+ border: 1px solid ${(p) => (p.isActive ? p.theme.color.interactive01 : p.theme.color.overlayHoverPrimary)};
46
47
  cursor: pointer;
47
48
  &:before {
48
49
  content: "";
@@ -69,6 +69,7 @@ import {
69
69
  SET_IS_IA_TRANSLATED,
70
70
  SET_LAST_TIMEOUT,
71
71
  RESET_PAGE_EDITOR_STORE,
72
+ SET_SCROLL_EDITOR_ID,
72
73
  } from "./constants";
73
74
 
74
75
  import {
@@ -111,6 +112,7 @@ import {
111
112
  ISetIsIATranslated,
112
113
  ISetLastTimeout,
113
114
  IResetPageEditorStore,
115
+ ISetScrollEditorID,
114
116
  } from "./interfaces";
115
117
 
116
118
  const { setIsLoading, setIsSaving, handleError } = appActions;
@@ -220,6 +222,10 @@ function resetPageEditorStore(): IResetPageEditorStore {
220
222
  return { type: RESET_PAGE_EDITOR_STORE };
221
223
  }
222
224
 
225
+ function setScrollEditorID(scrollEditorID: number | null): ISetScrollEditorID {
226
+ return { type: SET_SCROLL_EDITOR_ID, payload: { scrollEditorID } };
227
+ }
228
+
223
229
  function setTranslatedParent(): (dispatch: Dispatch, getState: any) => void {
224
230
  return async (dispatch, getState) => {
225
231
  try {
@@ -1088,7 +1094,9 @@ function setSelectedContent(editorID: number): (dispatch: Dispatch, getState: an
1088
1094
  "*"
1089
1095
  );
1090
1096
 
1091
- localStorage.setItem("selectedID", `${editorID}`);
1097
+ if (editorID > 0) {
1098
+ localStorage.setItem("selectedID", `${editorID}`);
1099
+ }
1092
1100
 
1093
1101
  dispatch(setIsLoading(true));
1094
1102
  const {
@@ -1535,4 +1543,5 @@ export {
1535
1543
  getPageTranslation,
1536
1544
  setIsTranslated,
1537
1545
  schedulePublication,
1546
+ setScrollEditorID,
1538
1547
  };
@@ -23,6 +23,7 @@ export const SET_COPY_MODULE = `${NAME}/SET_COPY_MODULE`;
23
23
  export const SET_IS_IA_TRANSLATED = `${NAME}/SET_IS_IA_TRANSLATED`;
24
24
  export const SET_LAST_TIMEOUT = `${NAME}/SET_LAST_TIMEOUT`;
25
25
  export const RESET_PAGE_EDITOR_STORE = `${NAME}/RESET_PAGE_EDITOR_STORE`;
26
+ export const SET_SCROLL_EDITOR_ID = `${NAME}/SET_SCROLL_EDITOR_ID`;
26
27
 
27
28
  export const INITIAL_TEMPLATE = "BasicTemplate";
28
29
  export const MULTIMEDIA_COMPONENTS = ["LinkableImage", "Video"];
@@ -22,6 +22,7 @@ import {
22
22
  SET_IS_IA_TRANSLATED,
23
23
  SET_LAST_TIMEOUT,
24
24
  RESET_PAGE_EDITOR_STORE,
25
+ SET_SCROLL_EDITOR_ID,
25
26
  } from "./constants";
26
27
  import { IBreadcrumbItem, ISchema, IPage, IErrorItem, IUserEditing } from "@ax/types";
27
28
 
@@ -139,6 +140,11 @@ export interface IResetPageEditorStore {
139
140
  type: typeof RESET_PAGE_EDITOR_STORE;
140
141
  }
141
142
 
143
+ export interface ISetScrollEditorID {
144
+ type: typeof SET_SCROLL_EDITOR_ID;
145
+ payload: { scrollEditorID: number | null };
146
+ }
147
+
142
148
  export interface IFieldProps {
143
149
  id: number;
144
150
  key: string;
@@ -25,6 +25,7 @@ import {
25
25
  SET_IS_IA_TRANSLATED,
26
26
  SET_LAST_TIMEOUT,
27
27
  RESET_PAGE_EDITOR_STORE,
28
+ SET_SCROLL_EDITOR_ID,
28
29
  } from "./constants";
29
30
 
30
31
  import { PageEditorActionsCreators } from "./interfaces";
@@ -52,6 +53,7 @@ export interface IPageEditorState {
52
53
  moduleCopy: { date: Date; elements: IModule[] } | null;
53
54
  isIATranslated: boolean;
54
55
  lastTimeout: NodeJS.Timeout | null;
56
+ scrollEditorID: number | null;
55
57
  }
56
58
 
57
59
  export const initialState = {
@@ -77,6 +79,7 @@ export const initialState = {
77
79
  moduleCopy: null,
78
80
  isIATranslated: false,
79
81
  lastTimeout: null,
82
+ scrollEditorID: null,
80
83
  };
81
84
 
82
85
  export function reducer(state = initialState, action: any): IPageEditorState {
@@ -104,6 +107,7 @@ export function reducer(state = initialState, action: any): IPageEditorState {
104
107
  case SET_COPY_MODULE:
105
108
  case SET_IS_IA_TRANSLATED:
106
109
  case SET_LAST_TIMEOUT:
110
+ case SET_SCROLL_EDITOR_ID:
107
111
  return { ...state, ...action.payload };
108
112
  case RESET_PAGE_EDITOR_STORE:
109
113
  return { ...initialState, moduleCopy: state.moduleCopy };
@@ -77,7 +77,7 @@ const getTemplateDisplayName = (template: string) => {
77
77
  const getMenuItems = (type: string): { fields: any[] } | undefined => schemas.menuItems[type];
78
78
 
79
79
  const filterByCategory = (options: any, category: string) =>
80
- options.filter((option: any) => allSchemas[option].category === category);
80
+ options.filter((option: any) => allSchemas[option]?.category === category);
81
81
 
82
82
  const getModuleCategories = (moduleList: string[]): ModuleCategoryInfo[] => {
83
83
  const categories: string[] = [];
@@ -89,12 +89,13 @@ const getModuleCategories = (moduleList: string[]): ModuleCategoryInfo[] => {
89
89
  };
90
90
 
91
91
  moduleList.forEach((module) => {
92
- const categoryValue = getSchema(module).category;
92
+ const categoryValue = getSchema(module)?.category;
93
+ if (categoryValue) {
94
+ const foundCategory = moduleCategories.find((category: ModuleCategoryInfo) => category.value === categoryValue);
93
95
 
94
- const foundCategory = moduleCategories.find((category: ModuleCategoryInfo) => category.value === categoryValue);
95
-
96
- if (foundCategory) {
97
- categories.push(foundCategory);
96
+ if (foundCategory) {
97
+ categories.push(foundCategory);
98
+ }
98
99
  }
99
100
  });
100
101
 
@@ -4,6 +4,7 @@ const useOnMessageReceivedFromIframe = (actions?: {
4
4
  setSelectedContentAction: any;
5
5
  deleteModuleAction(editorID: number[]): void;
6
6
  duplicateModuleAction(editorID: number[]): number;
7
+ setScrollEditorIDAction(editorID: number | null): void;
7
8
  }): void => {
8
9
  const onMessageReceivedFromIframe = useCallback(
9
10
  (ev: MessageEvent<{ type: string; message: string }>) => {
@@ -21,6 +22,9 @@ const useOnMessageReceivedFromIframe = (actions?: {
21
22
  const duplicatedEditorID = actions?.duplicateModuleAction([parseInt(ev.data.message)]);
22
23
  actions?.setSelectedContentAction(duplicatedEditorID);
23
24
  }
25
+ if (ev.data.type === "module-scroll") {
26
+ actions?.setScrollEditorIDAction(parseInt(ev.data.message));
27
+ }
24
28
  },
25
29
  [actions]
26
30
  );
@@ -52,6 +52,9 @@ const FramePreview = (props: IProps) => {
52
52
  }
53
53
  };
54
54
 
55
+ const selectHoverEditorID = (editorID: number) =>
56
+ window.parent.postMessage({ type: "module-scroll", message: editorID }, "*");
57
+
55
58
  const globalTheme = getDefaultTheme();
56
59
  const theme = currentSiteInfo ? currentSiteInfo.theme : globalTheme;
57
60
  const langs = currentSiteInfo ? siteLangs : globalLangs;
@@ -62,10 +65,12 @@ const FramePreview = (props: IProps) => {
62
65
  setSelectedContent && setSelectedContent(0);
63
66
  deleteModule([editorID]);
64
67
  };
68
+
65
69
  const duplicateModuleSelected = (editorID: number) => {
66
70
  window.parent.postMessage({ type: "module-duplicate", message: editorID }, "*");
67
71
  duplicateModule([editorID]);
68
72
  };
73
+
69
74
  const moduleActions = {
70
75
  deleteModuleAction: deleteModuleSelected,
71
76
  duplicateModuleAction: duplicateModuleSelected,
@@ -90,6 +95,7 @@ const FramePreview = (props: IProps) => {
90
95
  pageLanguages={pageLanguages}
91
96
  moduleActions={moduleActions}
92
97
  renderer={isPreview === "true" ? "preview" : "editor"}
98
+ selectHoverEditorID={selectHoverEditorID}
93
99
  />
94
100
  </S.Wrapper>
95
101
  );
@@ -18,6 +18,7 @@ const PageBrowser = (props: IProps) => {
18
18
  browserRef,
19
19
  deleteModule,
20
20
  duplicateModule,
21
+ setScrollEditorID,
21
22
  } = props;
22
23
 
23
24
  const slugWithSlash = slug ? (slug.startsWith("/") ? slug : `/${slug}`) : "";
@@ -28,6 +29,7 @@ const PageBrowser = (props: IProps) => {
28
29
  deleteModuleAction: deleteModule,
29
30
  duplicateModuleAction: duplicateModule,
30
31
  setSelectedContentAction: setSelectedContent,
32
+ setScrollEditorIDAction: setScrollEditorID,
31
33
  };
32
34
 
33
35
  return (
@@ -67,6 +69,7 @@ interface IPageBrowserDispatchProps {
67
69
  browserRef?: any;
68
70
  deleteModule(editorID: number[]): void;
69
71
  duplicateModule(editorID: number[]): number;
72
+ setScrollEditorID(editorID: number | null): void;
70
73
  }
71
74
 
72
75
  type IProps = IPageBrowserStateProps & IPageBrowserDispatchProps;
@@ -84,6 +87,7 @@ const mapDispatchToProps = {
84
87
  setSelectedContent: pageEditorActions.setSelectedContent,
85
88
  deleteModule: pageEditorActions.deleteModule,
86
89
  duplicateModule: pageEditorActions.duplicateModule,
90
+ setScrollEditorID: pageEditorActions.setScrollEditorID,
87
91
  };
88
92
 
89
93
  export default connect(mapStateToProps, mapDispatchToProps)(PageBrowser);
@@ -19,6 +19,7 @@ const PageBrowser = (props: IProps) => {
19
19
  browserRef,
20
20
  deleteModule,
21
21
  duplicateModule,
22
+ setScrollEditorID,
22
23
  } = props;
23
24
 
24
25
  if (!currentSiteInfo) {
@@ -36,6 +37,7 @@ const PageBrowser = (props: IProps) => {
36
37
  deleteModuleAction: deleteModule,
37
38
  duplicateModuleAction: duplicateModule,
38
39
  setSelectedContentAction: setSelectedContent,
40
+ setScrollEditorIDAction: setScrollEditorID,
39
41
  };
40
42
 
41
43
  return (
@@ -77,6 +79,7 @@ interface IPageBrowserDispatchProps {
77
79
  browserRef?: any;
78
80
  deleteModule(editorID: number[]): void;
79
81
  duplicateModule(editorID: number[]): number;
82
+ setScrollEditorID(editorID: number | null): void;
80
83
  }
81
84
 
82
85
  type IProps = IPageBrowserStateProps & IPageBrowserDispatchProps;
@@ -94,6 +97,7 @@ const mapDispatchToProps = {
94
97
  setSelectedContent: pageEditorActions.setSelectedContent,
95
98
  deleteModule: pageEditorActions.deleteModule,
96
99
  duplicateModule: pageEditorActions.duplicateModule,
100
+ setScrollEditorID: pageEditorActions.setScrollEditorID,
97
101
  };
98
102
 
99
103
  export default connect(mapStateToProps, mapDispatchToProps)(PageBrowser);
@@ -77,6 +77,11 @@ export default {
77
77
  type: "TagsField",
78
78
  key: "metaKeywords",
79
79
  },
80
+ {
81
+ title: "Canonical URL",
82
+ type: "TextField",
83
+ key: "canonicalURL",
84
+ },
80
85
  {
81
86
  title: "Meta robots index",
82
87
  type: "RadioGroup",
@@ -155,8 +160,8 @@ export default {
155
160
  type: "AnalyticsField",
156
161
  key: "dimensions",
157
162
  collapsed: true,
158
- }
159
- ]
163
+ },
164
+ ],
160
165
  },
161
166
  {
162
167
  title: "Social Media",