@elementor/editor-site-navigation 0.1.0 → 0.2.1
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/CHANGELOG.md +11 -0
- package/dist/index.d.ts +7 -1
- package/dist/index.js +111 -32
- package/dist/index.mjs +106 -43
- package/package.json +7 -7
- package/src/__tests__/icons-map.test.tsx +33 -0
- package/src/components/top-bar/__tests__/add-new-page.test.tsx +94 -0
- package/src/components/top-bar/__tests__/recently-edited.test.tsx +1 -3
- package/src/components/top-bar/chip-doc-type.tsx +5 -36
- package/src/components/top-bar/indicator.tsx +14 -1
- package/src/components/top-bar/posts-list.tsx +28 -2
- package/src/components/top-bar/recently-edited.tsx +4 -2
- package/src/hooks/__tests__/use-create-page.test.ts +43 -0
- package/src/hooks/__tests__/use-recent-posts.test.ts +42 -0
- package/src/hooks/use-create-page.ts +42 -0
- package/src/hooks/use-recent-posts.ts +4 -3
- package/src/icons-map.ts +35 -0
- package/src/index.ts +2 -0
- package/src/types.ts +0 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Change Log
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
|
+
|
|
6
|
+
## [0.2.1](https://github.com/elementor/elementor-packages/compare/v0.2.0...v0.2.1) (2023-05-11)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* **editor-app-bar:** make save options button disabled in site-settings [ED-10221] ([#30](https://github.com/elementor/elementor-packages/issues/30)) ([1991096](https://github.com/elementor/elementor-packages/commit/1991096115efeae7bc3648e4889899b85d7328d6))
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -5,6 +5,10 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
8
12
|
var __copyProps = (to, from, except, desc) => {
|
|
9
13
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
14
|
for (let key of __getOwnPropNames(from))
|
|
@@ -21,49 +25,73 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
21
25
|
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
26
|
mod
|
|
23
27
|
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
|
+
extendIconsMap: () => extendIconsMap
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(src_exports);
|
|
36
|
+
|
|
37
|
+
// src/icons-map.ts
|
|
38
|
+
var import_icons = require("@elementor/icons");
|
|
39
|
+
var initialIconsMap = {
|
|
40
|
+
page: import_icons.PageTemplateIcon,
|
|
41
|
+
section: import_icons.SectionTemplateIcon,
|
|
42
|
+
container: import_icons.ContainerTemplateIcon,
|
|
43
|
+
"wp-page": import_icons.PageTypeIcon,
|
|
44
|
+
"wp-post": import_icons.PostTypeIcon
|
|
45
|
+
};
|
|
46
|
+
var iconsMap = { ...initialIconsMap };
|
|
47
|
+
function extendIconsMap(additionalIcons) {
|
|
48
|
+
Object.assign(iconsMap, additionalIcons);
|
|
49
|
+
}
|
|
50
|
+
function getIconsMap() {
|
|
51
|
+
return iconsMap;
|
|
52
|
+
}
|
|
24
53
|
|
|
25
54
|
// src/components/top-bar/recently-edited.tsx
|
|
26
55
|
var React4 = __toESM(require("react"));
|
|
27
56
|
var import_ui4 = require("@elementor/ui");
|
|
28
|
-
var
|
|
57
|
+
var import_icons4 = require("@elementor/icons");
|
|
29
58
|
var import_editor_documents = require("@elementor/editor-documents");
|
|
30
59
|
|
|
31
60
|
// src/components/top-bar/indicator.tsx
|
|
32
61
|
var React = __toESM(require("react"));
|
|
33
62
|
var import_ui = require("@elementor/ui");
|
|
34
63
|
function Indicator({ title, status }) {
|
|
35
|
-
return /* @__PURE__ */ React.createElement(
|
|
64
|
+
return /* @__PURE__ */ React.createElement(Tooltip, { title }, /* @__PURE__ */ React.createElement(import_ui.Stack, { direction: "row", alignItems: "center", spacing: 2 }, /* @__PURE__ */ React.createElement(import_ui.Typography, { variant: "body2", sx: { maxWidth: "120px" }, noWrap: true }, title), status.value !== "publish" && /* @__PURE__ */ React.createElement(import_ui.Typography, { variant: "body2", sx: { fontStyle: "italic" } }, "(", status.label, ")")));
|
|
65
|
+
}
|
|
66
|
+
function Tooltip(props) {
|
|
67
|
+
return /* @__PURE__ */ React.createElement(
|
|
68
|
+
import_ui.Tooltip,
|
|
69
|
+
{
|
|
70
|
+
PopperProps: {
|
|
71
|
+
sx: {
|
|
72
|
+
"&.MuiTooltip-popper .MuiTooltip-tooltip.MuiTooltip-tooltipPlacementBottom": {
|
|
73
|
+
mt: 7
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
...props
|
|
78
|
+
}
|
|
79
|
+
);
|
|
36
80
|
}
|
|
37
81
|
|
|
38
82
|
// src/components/top-bar/posts-list.tsx
|
|
39
|
-
var React3 = __toESM(require("react"));
|
|
40
83
|
var import_ui3 = require("@elementor/ui");
|
|
84
|
+
var React3 = __toESM(require("react"));
|
|
41
85
|
var import_i18n = require("@wordpress/i18n");
|
|
42
86
|
|
|
43
87
|
// src/components/top-bar/chip-doc-type.tsx
|
|
44
|
-
var
|
|
88
|
+
var import_icons2 = require("@elementor/icons");
|
|
45
89
|
var import_ui2 = require("@elementor/ui");
|
|
46
90
|
var React2 = __toESM(require("react"));
|
|
47
|
-
var
|
|
48
|
-
header: import_icons.HeaderTemplateIcon,
|
|
49
|
-
footer: import_icons.FooterTemplateIcon,
|
|
50
|
-
"single-post": import_icons.PostTypeIcon,
|
|
51
|
-
"single-page": import_icons.PageTypeIcon,
|
|
52
|
-
popup: import_icons.PopupTemplateIcon,
|
|
53
|
-
archive: import_icons.ArchiveTemplateIcon,
|
|
54
|
-
"search-results": import_icons.SearchResultsTemplateIcon,
|
|
55
|
-
"loop-item": import_icons.LoopItemTemplateIcon,
|
|
56
|
-
"error-404": import_icons.Error404TemplateIcon,
|
|
57
|
-
"landing-page": import_icons.LandingPageTemplateIcon,
|
|
58
|
-
page: import_icons.PageTemplateIcon,
|
|
59
|
-
section: import_icons.SectionTemplateIcon,
|
|
60
|
-
container: import_icons.ContainerTemplateIcon,
|
|
61
|
-
"wp-page": import_icons.PageTypeIcon,
|
|
62
|
-
"wp-post": import_icons.PostTypeIcon
|
|
63
|
-
};
|
|
91
|
+
var iconsMap2 = getIconsMap();
|
|
64
92
|
function DocTypeChip({ postType, docType, label }) {
|
|
65
93
|
const color = "elementor_library" === postType ? "global" : "primary";
|
|
66
|
-
const Icon =
|
|
94
|
+
const Icon = iconsMap2[docType] || import_icons2.PostTypeIcon;
|
|
67
95
|
return /* @__PURE__ */ React2.createElement(
|
|
68
96
|
import_ui2.Chip,
|
|
69
97
|
{
|
|
@@ -76,28 +104,73 @@ function DocTypeChip({ postType, docType, label }) {
|
|
|
76
104
|
);
|
|
77
105
|
}
|
|
78
106
|
|
|
107
|
+
// src/hooks/use-create-page.ts
|
|
108
|
+
var import_api_fetch = __toESM(require("@wordpress/api-fetch"));
|
|
109
|
+
var import_react = require("react");
|
|
110
|
+
var endpointPath = "/elementor/v1/site-navigation/add-new-post";
|
|
111
|
+
function useCreatePage({ onCreated: onCreated2 }) {
|
|
112
|
+
const [isLoading, setIsLoading] = (0, import_react.useState)(false);
|
|
113
|
+
return {
|
|
114
|
+
create: () => {
|
|
115
|
+
setIsLoading(true);
|
|
116
|
+
addNewPage().then((newPost) => newPost).then((newPost) => {
|
|
117
|
+
setIsLoading(false);
|
|
118
|
+
onCreated2(newPost.edit_url);
|
|
119
|
+
}).catch(() => {
|
|
120
|
+
setIsLoading(false);
|
|
121
|
+
});
|
|
122
|
+
},
|
|
123
|
+
isLoading
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
async function addNewPage() {
|
|
127
|
+
return await (0, import_api_fetch.default)({
|
|
128
|
+
path: endpointPath,
|
|
129
|
+
method: "POST",
|
|
130
|
+
data: { post_type: "page" }
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
79
134
|
// src/components/top-bar/posts-list.tsx
|
|
135
|
+
var import_icons3 = require("@elementor/icons");
|
|
80
136
|
function PostsList({ recentPosts }) {
|
|
137
|
+
const { create, isLoading } = useCreatePage({ onCreated });
|
|
81
138
|
return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(import_ui3.ListSubheader, { sx: { fontSize: 12, fontStyle: "italic", pl: 4 }, component: "div", id: "nested-list-subheader" }, (0, import_i18n.__)("Recent", "elementor")), recentPosts.length ? recentPosts.map(({ title, edit_url: editUrl, type, id }) => /* @__PURE__ */ React3.createElement(
|
|
82
139
|
import_ui3.MenuItem,
|
|
83
140
|
{
|
|
141
|
+
dense: true,
|
|
84
142
|
key: id,
|
|
85
143
|
component: "a",
|
|
86
144
|
href: editUrl
|
|
87
145
|
},
|
|
88
146
|
title,
|
|
89
147
|
/* @__PURE__ */ React3.createElement(DocTypeChip, { postType: type.post_type, docType: type.doc_type, label: type.label })
|
|
90
|
-
)) : /* @__PURE__ */ React3.createElement(import_ui3.Typography, { variant: "caption", sx: { color: "grey.500", fontStyle: "italic", p: 4 }, component: "div", "aria-label": void 0 }, (0, import_i18n.__)("There are no other pages or templates on this site yet.", "elementor")))
|
|
148
|
+
)) : /* @__PURE__ */ React3.createElement(import_ui3.Typography, { variant: "caption", sx: { color: "grey.500", fontStyle: "italic", p: 4 }, component: "div", "aria-label": void 0 }, (0, import_i18n.__)("There are no other pages or templates on this site yet.", "elementor")), /* @__PURE__ */ React3.createElement(import_ui3.Divider, null), /* @__PURE__ */ React3.createElement(
|
|
149
|
+
import_ui3.MenuItem,
|
|
150
|
+
{
|
|
151
|
+
dense: true,
|
|
152
|
+
size: "small",
|
|
153
|
+
color: "inherit",
|
|
154
|
+
component: "div",
|
|
155
|
+
onClick: create
|
|
156
|
+
},
|
|
157
|
+
/* @__PURE__ */ React3.createElement(import_ui3.ListItemIcon, null, isLoading ? /* @__PURE__ */ React3.createElement(import_ui3.CircularProgress, null) : /* @__PURE__ */ React3.createElement(import_icons3.PlusIcon, null)),
|
|
158
|
+
(0, import_i18n.__)("Add new page", "elementor")
|
|
159
|
+
));
|
|
160
|
+
}
|
|
161
|
+
function onCreated(url) {
|
|
162
|
+
window.location.href = url;
|
|
91
163
|
}
|
|
92
164
|
|
|
93
165
|
// src/hooks/use-recent-posts.ts
|
|
94
|
-
var
|
|
95
|
-
var
|
|
166
|
+
var import_react2 = require("react");
|
|
167
|
+
var import_api_fetch2 = __toESM(require("@wordpress/api-fetch"));
|
|
96
168
|
var import_url = require("@wordpress/url");
|
|
169
|
+
var endpointPath2 = "/elementor/v1/site-navigation/recent-posts";
|
|
97
170
|
function useRecentPosts(documentId) {
|
|
98
|
-
const [recentPosts, setRecentPosts] = (0,
|
|
99
|
-
const [isLoading, setIsLoading] = (0,
|
|
100
|
-
(0,
|
|
171
|
+
const [recentPosts, setRecentPosts] = (0, import_react2.useState)([]);
|
|
172
|
+
const [isLoading, setIsLoading] = (0, import_react2.useState)(false);
|
|
173
|
+
(0, import_react2.useEffect)(() => {
|
|
101
174
|
if (documentId) {
|
|
102
175
|
setIsLoading(true);
|
|
103
176
|
fetchRecentlyEditedPosts(documentId).then((posts) => {
|
|
@@ -116,8 +189,8 @@ async function fetchRecentlyEditedPosts(documentId) {
|
|
|
116
189
|
posts_per_page: 5,
|
|
117
190
|
post__not_in: documentId
|
|
118
191
|
};
|
|
119
|
-
return await (0,
|
|
120
|
-
path: (0, import_url.addQueryArgs)(
|
|
192
|
+
return await (0, import_api_fetch2.default)({
|
|
193
|
+
path: (0, import_url.addQueryArgs)(endpointPath2, queryParams)
|
|
121
194
|
}).then((response) => response).catch(() => []);
|
|
122
195
|
}
|
|
123
196
|
|
|
@@ -138,7 +211,8 @@ function RecentlyEdited() {
|
|
|
138
211
|
import_ui4.Button,
|
|
139
212
|
{
|
|
140
213
|
color: "inherit",
|
|
141
|
-
|
|
214
|
+
size: "small",
|
|
215
|
+
endIcon: /* @__PURE__ */ React4.createElement(import_icons4.ChevronDownIcon, { fontSize: "small" }),
|
|
142
216
|
...(0, import_ui4.bindTrigger)(popupState)
|
|
143
217
|
},
|
|
144
218
|
/* @__PURE__ */ React4.createElement(
|
|
@@ -151,7 +225,8 @@ function RecentlyEdited() {
|
|
|
151
225
|
), /* @__PURE__ */ React4.createElement(
|
|
152
226
|
import_ui4.Menu,
|
|
153
227
|
{
|
|
154
|
-
|
|
228
|
+
MenuListProps: { component: "div" },
|
|
229
|
+
PaperProps: { sx: { mt: 4, minWidth: 314 } },
|
|
155
230
|
...(0, import_ui4.bindMenu)(popupState)
|
|
156
231
|
},
|
|
157
232
|
/* @__PURE__ */ React4.createElement(PostsList, { recentPosts })
|
|
@@ -172,3 +247,7 @@ function registerTopBarMenuItems() {
|
|
|
172
247
|
|
|
173
248
|
// src/index.ts
|
|
174
249
|
init();
|
|
250
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
251
|
+
0 && (module.exports = {
|
|
252
|
+
extendIconsMap
|
|
253
|
+
});
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,26 @@
|
|
|
1
|
+
// src/icons-map.ts
|
|
2
|
+
import {
|
|
3
|
+
PostTypeIcon,
|
|
4
|
+
PageTypeIcon,
|
|
5
|
+
PageTemplateIcon,
|
|
6
|
+
SectionTemplateIcon,
|
|
7
|
+
ContainerTemplateIcon
|
|
8
|
+
} from "@elementor/icons";
|
|
9
|
+
var initialIconsMap = {
|
|
10
|
+
page: PageTemplateIcon,
|
|
11
|
+
section: SectionTemplateIcon,
|
|
12
|
+
container: ContainerTemplateIcon,
|
|
13
|
+
"wp-page": PageTypeIcon,
|
|
14
|
+
"wp-post": PostTypeIcon
|
|
15
|
+
};
|
|
16
|
+
var iconsMap = { ...initialIconsMap };
|
|
17
|
+
function extendIconsMap(additionalIcons) {
|
|
18
|
+
Object.assign(iconsMap, additionalIcons);
|
|
19
|
+
}
|
|
20
|
+
function getIconsMap() {
|
|
21
|
+
return iconsMap;
|
|
22
|
+
}
|
|
23
|
+
|
|
1
24
|
// src/components/top-bar/recently-edited.tsx
|
|
2
25
|
import * as React4 from "react";
|
|
3
26
|
import {
|
|
@@ -13,58 +36,48 @@ import { useActiveDocument, useHostDocument } from "@elementor/editor-documents"
|
|
|
13
36
|
|
|
14
37
|
// src/components/top-bar/indicator.tsx
|
|
15
38
|
import * as React from "react";
|
|
16
|
-
import {
|
|
39
|
+
import { Typography, Stack, Tooltip as BaseTooltip } from "@elementor/ui";
|
|
17
40
|
function Indicator({ title, status }) {
|
|
18
41
|
return /* @__PURE__ */ React.createElement(Tooltip, { title }, /* @__PURE__ */ React.createElement(Stack, { direction: "row", alignItems: "center", spacing: 2 }, /* @__PURE__ */ React.createElement(Typography, { variant: "body2", sx: { maxWidth: "120px" }, noWrap: true }, title), status.value !== "publish" && /* @__PURE__ */ React.createElement(Typography, { variant: "body2", sx: { fontStyle: "italic" } }, "(", status.label, ")")));
|
|
19
42
|
}
|
|
43
|
+
function Tooltip(props) {
|
|
44
|
+
return /* @__PURE__ */ React.createElement(
|
|
45
|
+
BaseTooltip,
|
|
46
|
+
{
|
|
47
|
+
PopperProps: {
|
|
48
|
+
sx: {
|
|
49
|
+
"&.MuiTooltip-popper .MuiTooltip-tooltip.MuiTooltip-tooltipPlacementBottom": {
|
|
50
|
+
mt: 7
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
...props
|
|
55
|
+
}
|
|
56
|
+
);
|
|
57
|
+
}
|
|
20
58
|
|
|
21
59
|
// src/components/top-bar/posts-list.tsx
|
|
22
|
-
import * as React3 from "react";
|
|
23
60
|
import {
|
|
61
|
+
Divider,
|
|
24
62
|
MenuItem,
|
|
63
|
+
ListItemIcon,
|
|
25
64
|
ListSubheader,
|
|
26
|
-
Typography as Typography2
|
|
65
|
+
Typography as Typography2,
|
|
66
|
+
CircularProgress
|
|
27
67
|
} from "@elementor/ui";
|
|
68
|
+
import * as React3 from "react";
|
|
28
69
|
import { __ } from "@wordpress/i18n";
|
|
29
70
|
|
|
30
71
|
// src/components/top-bar/chip-doc-type.tsx
|
|
31
72
|
import {
|
|
32
|
-
|
|
33
|
-
HeaderTemplateIcon,
|
|
34
|
-
FooterTemplateIcon,
|
|
35
|
-
PostTypeIcon,
|
|
36
|
-
PageTypeIcon,
|
|
37
|
-
PopupTemplateIcon,
|
|
38
|
-
SearchResultsTemplateIcon,
|
|
39
|
-
Error404TemplateIcon,
|
|
40
|
-
LoopItemTemplateIcon,
|
|
41
|
-
LandingPageTemplateIcon,
|
|
42
|
-
PageTemplateIcon,
|
|
43
|
-
SectionTemplateIcon,
|
|
44
|
-
ContainerTemplateIcon
|
|
73
|
+
PostTypeIcon as PostTypeIcon2
|
|
45
74
|
} from "@elementor/icons";
|
|
46
75
|
import { Chip } from "@elementor/ui";
|
|
47
76
|
import * as React2 from "react";
|
|
48
|
-
var
|
|
49
|
-
header: HeaderTemplateIcon,
|
|
50
|
-
footer: FooterTemplateIcon,
|
|
51
|
-
"single-post": PostTypeIcon,
|
|
52
|
-
"single-page": PageTypeIcon,
|
|
53
|
-
popup: PopupTemplateIcon,
|
|
54
|
-
archive: ArchiveTemplateIcon,
|
|
55
|
-
"search-results": SearchResultsTemplateIcon,
|
|
56
|
-
"loop-item": LoopItemTemplateIcon,
|
|
57
|
-
"error-404": Error404TemplateIcon,
|
|
58
|
-
"landing-page": LandingPageTemplateIcon,
|
|
59
|
-
page: PageTemplateIcon,
|
|
60
|
-
section: SectionTemplateIcon,
|
|
61
|
-
container: ContainerTemplateIcon,
|
|
62
|
-
"wp-page": PageTypeIcon,
|
|
63
|
-
"wp-post": PostTypeIcon
|
|
64
|
-
};
|
|
77
|
+
var iconsMap2 = getIconsMap();
|
|
65
78
|
function DocTypeChip({ postType, docType, label }) {
|
|
66
79
|
const color = "elementor_library" === postType ? "global" : "primary";
|
|
67
|
-
const Icon =
|
|
80
|
+
const Icon = iconsMap2[docType] || PostTypeIcon2;
|
|
68
81
|
return /* @__PURE__ */ React2.createElement(
|
|
69
82
|
Chip,
|
|
70
83
|
{
|
|
@@ -77,27 +90,72 @@ function DocTypeChip({ postType, docType, label }) {
|
|
|
77
90
|
);
|
|
78
91
|
}
|
|
79
92
|
|
|
93
|
+
// src/hooks/use-create-page.ts
|
|
94
|
+
import apiFetch from "@wordpress/api-fetch";
|
|
95
|
+
import { useState } from "react";
|
|
96
|
+
var endpointPath = "/elementor/v1/site-navigation/add-new-post";
|
|
97
|
+
function useCreatePage({ onCreated: onCreated2 }) {
|
|
98
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
99
|
+
return {
|
|
100
|
+
create: () => {
|
|
101
|
+
setIsLoading(true);
|
|
102
|
+
addNewPage().then((newPost) => newPost).then((newPost) => {
|
|
103
|
+
setIsLoading(false);
|
|
104
|
+
onCreated2(newPost.edit_url);
|
|
105
|
+
}).catch(() => {
|
|
106
|
+
setIsLoading(false);
|
|
107
|
+
});
|
|
108
|
+
},
|
|
109
|
+
isLoading
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
async function addNewPage() {
|
|
113
|
+
return await apiFetch({
|
|
114
|
+
path: endpointPath,
|
|
115
|
+
method: "POST",
|
|
116
|
+
data: { post_type: "page" }
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
80
120
|
// src/components/top-bar/posts-list.tsx
|
|
121
|
+
import { PlusIcon } from "@elementor/icons";
|
|
81
122
|
function PostsList({ recentPosts }) {
|
|
123
|
+
const { create, isLoading } = useCreatePage({ onCreated });
|
|
82
124
|
return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(ListSubheader, { sx: { fontSize: 12, fontStyle: "italic", pl: 4 }, component: "div", id: "nested-list-subheader" }, __("Recent", "elementor")), recentPosts.length ? recentPosts.map(({ title, edit_url: editUrl, type, id }) => /* @__PURE__ */ React3.createElement(
|
|
83
125
|
MenuItem,
|
|
84
126
|
{
|
|
127
|
+
dense: true,
|
|
85
128
|
key: id,
|
|
86
129
|
component: "a",
|
|
87
130
|
href: editUrl
|
|
88
131
|
},
|
|
89
132
|
title,
|
|
90
133
|
/* @__PURE__ */ React3.createElement(DocTypeChip, { postType: type.post_type, docType: type.doc_type, label: type.label })
|
|
91
|
-
)) : /* @__PURE__ */ React3.createElement(Typography2, { variant: "caption", sx: { color: "grey.500", fontStyle: "italic", p: 4 }, component: "div", "aria-label": void 0 }, __("There are no other pages or templates on this site yet.", "elementor")))
|
|
134
|
+
)) : /* @__PURE__ */ React3.createElement(Typography2, { variant: "caption", sx: { color: "grey.500", fontStyle: "italic", p: 4 }, component: "div", "aria-label": void 0 }, __("There are no other pages or templates on this site yet.", "elementor")), /* @__PURE__ */ React3.createElement(Divider, null), /* @__PURE__ */ React3.createElement(
|
|
135
|
+
MenuItem,
|
|
136
|
+
{
|
|
137
|
+
dense: true,
|
|
138
|
+
size: "small",
|
|
139
|
+
color: "inherit",
|
|
140
|
+
component: "div",
|
|
141
|
+
onClick: create
|
|
142
|
+
},
|
|
143
|
+
/* @__PURE__ */ React3.createElement(ListItemIcon, null, isLoading ? /* @__PURE__ */ React3.createElement(CircularProgress, null) : /* @__PURE__ */ React3.createElement(PlusIcon, null)),
|
|
144
|
+
__("Add new page", "elementor")
|
|
145
|
+
));
|
|
146
|
+
}
|
|
147
|
+
function onCreated(url) {
|
|
148
|
+
window.location.href = url;
|
|
92
149
|
}
|
|
93
150
|
|
|
94
151
|
// src/hooks/use-recent-posts.ts
|
|
95
|
-
import { useEffect, useState } from "react";
|
|
96
|
-
import
|
|
152
|
+
import { useEffect, useState as useState2 } from "react";
|
|
153
|
+
import apiFetch2 from "@wordpress/api-fetch";
|
|
97
154
|
import { addQueryArgs } from "@wordpress/url";
|
|
155
|
+
var endpointPath2 = "/elementor/v1/site-navigation/recent-posts";
|
|
98
156
|
function useRecentPosts(documentId) {
|
|
99
|
-
const [recentPosts, setRecentPosts] =
|
|
100
|
-
const [isLoading, setIsLoading] =
|
|
157
|
+
const [recentPosts, setRecentPosts] = useState2([]);
|
|
158
|
+
const [isLoading, setIsLoading] = useState2(false);
|
|
101
159
|
useEffect(() => {
|
|
102
160
|
if (documentId) {
|
|
103
161
|
setIsLoading(true);
|
|
@@ -117,8 +175,8 @@ async function fetchRecentlyEditedPosts(documentId) {
|
|
|
117
175
|
posts_per_page: 5,
|
|
118
176
|
post__not_in: documentId
|
|
119
177
|
};
|
|
120
|
-
return await
|
|
121
|
-
path: addQueryArgs(
|
|
178
|
+
return await apiFetch2({
|
|
179
|
+
path: addQueryArgs(endpointPath2, queryParams)
|
|
122
180
|
}).then((response) => response).catch(() => []);
|
|
123
181
|
}
|
|
124
182
|
|
|
@@ -139,7 +197,8 @@ function RecentlyEdited() {
|
|
|
139
197
|
Button,
|
|
140
198
|
{
|
|
141
199
|
color: "inherit",
|
|
142
|
-
|
|
200
|
+
size: "small",
|
|
201
|
+
endIcon: /* @__PURE__ */ React4.createElement(ChevronDownIcon, { fontSize: "small" }),
|
|
143
202
|
...bindTrigger(popupState)
|
|
144
203
|
},
|
|
145
204
|
/* @__PURE__ */ React4.createElement(
|
|
@@ -152,7 +211,8 @@ function RecentlyEdited() {
|
|
|
152
211
|
), /* @__PURE__ */ React4.createElement(
|
|
153
212
|
Menu,
|
|
154
213
|
{
|
|
155
|
-
|
|
214
|
+
MenuListProps: { component: "div" },
|
|
215
|
+
PaperProps: { sx: { mt: 4, minWidth: 314 } },
|
|
156
216
|
...bindMenu(popupState)
|
|
157
217
|
},
|
|
158
218
|
/* @__PURE__ */ React4.createElement(PostsList, { recentPosts })
|
|
@@ -173,3 +233,6 @@ function registerTopBarMenuItems() {
|
|
|
173
233
|
|
|
174
234
|
// src/index.ts
|
|
175
235
|
init();
|
|
236
|
+
export {
|
|
237
|
+
extendIconsMap
|
|
238
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementor/editor-site-navigation",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "Elementor Team",
|
|
6
6
|
"homepage": "https://elementor.com/",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"repository": {
|
|
20
20
|
"type": "git",
|
|
21
21
|
"url": "https://github.com/elementor/elementor-packages.git",
|
|
22
|
-
"directory": "packages/editor-site-navigation"
|
|
22
|
+
"directory": "packages/core/editor-site-navigation"
|
|
23
23
|
},
|
|
24
24
|
"bugs": {
|
|
25
25
|
"url": "https://github.com/elementor/elementor-packages/issues"
|
|
@@ -32,10 +32,10 @@
|
|
|
32
32
|
"dev": "tsup src/index.ts --format esm --clean"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@elementor/editor-app-bar": "^0.1
|
|
36
|
-
"@elementor/editor-documents": "^0.
|
|
37
|
-
"@elementor/icons": "^0.1
|
|
38
|
-
"@elementor/ui": "^1.4.
|
|
35
|
+
"@elementor/editor-app-bar": "^0.2.1",
|
|
36
|
+
"@elementor/editor-documents": "^0.2.0",
|
|
37
|
+
"@elementor/icons": "^0.2.1",
|
|
38
|
+
"@elementor/ui": "^1.4.50",
|
|
39
39
|
"@wordpress/api-fetch": "^6.27.0",
|
|
40
40
|
"@wordpress/i18n": "^4.31.0",
|
|
41
41
|
"@wordpress/url": "^3.31.0"
|
|
@@ -46,5 +46,5 @@
|
|
|
46
46
|
"elementor": {
|
|
47
47
|
"type": "extension"
|
|
48
48
|
},
|
|
49
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "3559bb26178072f23c08caab4114671a76bb9eb6"
|
|
50
50
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { getIconsMap, extendIconsMap, resetIconsMap } from '../icons-map';
|
|
3
|
+
|
|
4
|
+
describe( '@elementor/site-navigation - iconsMap', () => {
|
|
5
|
+
afterEach( () => {
|
|
6
|
+
resetIconsMap();
|
|
7
|
+
} );
|
|
8
|
+
|
|
9
|
+
it( 'should override existing icons', async () => {
|
|
10
|
+
// Arrange.
|
|
11
|
+
const initialIcons = getIconsMap();
|
|
12
|
+
const addedIcons = {
|
|
13
|
+
'added-icon': () => <div>added-icon</div>,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// Act - add icons.
|
|
17
|
+
extendIconsMap( addedIcons );
|
|
18
|
+
|
|
19
|
+
// Assert - should be initial and added.
|
|
20
|
+
expect( getIconsMap() ).toEqual( { ...initialIcons, ...addedIcons } );
|
|
21
|
+
|
|
22
|
+
// Arrange.
|
|
23
|
+
const overrideIcons = {
|
|
24
|
+
'added-icon': () => <div>override-icon</div>,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// Act - override exits icons.
|
|
28
|
+
extendIconsMap( overrideIcons );
|
|
29
|
+
|
|
30
|
+
// Assert - should override exits icons.
|
|
31
|
+
expect( getIconsMap() ).toEqual( { ...initialIcons, ...overrideIcons } );
|
|
32
|
+
} );
|
|
33
|
+
} );
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { render } from '@testing-library/react';
|
|
3
|
+
import { useHostDocument, useActiveDocument } from '@elementor/editor-documents';
|
|
4
|
+
import RecentlyEdited from '../recently-edited';
|
|
5
|
+
import { createMockDocument } from 'test-utils';
|
|
6
|
+
import useRecentPosts, { Post } from '../../../hooks/use-recent-posts';
|
|
7
|
+
import useCreatePage from '../../../hooks/use-create-page';
|
|
8
|
+
|
|
9
|
+
jest.mock( '@elementor/editor-documents', () => ( {
|
|
10
|
+
useActiveDocument: jest.fn(),
|
|
11
|
+
useHostDocument: jest.fn(),
|
|
12
|
+
} ) );
|
|
13
|
+
|
|
14
|
+
jest.mock( '../../../hooks/use-recent-posts', () => (
|
|
15
|
+
{
|
|
16
|
+
default: jest.fn( () => ( { isLoading: false, recentPosts: [] } ) ),
|
|
17
|
+
__esModule: true,
|
|
18
|
+
}
|
|
19
|
+
) );
|
|
20
|
+
jest.mock( '../../../hooks/use-create-page', () => (
|
|
21
|
+
{
|
|
22
|
+
default: jest.fn( () => ( { create: jest.fn(), isLoading: false } ) ),
|
|
23
|
+
__esModule: true,
|
|
24
|
+
}
|
|
25
|
+
) );
|
|
26
|
+
|
|
27
|
+
describe( '@elementor/recently-edited - Top bar add new page', () => {
|
|
28
|
+
beforeEach( () => {
|
|
29
|
+
jest.mocked( useActiveDocument ).mockImplementation( () =>
|
|
30
|
+
createMockDocument( { id: 1, title: 'Active Document' } )
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
jest.mocked( useHostDocument ).mockImplementation( () =>
|
|
34
|
+
createMockDocument( { id: 2, title: 'Host Document' } )
|
|
35
|
+
);
|
|
36
|
+
} );
|
|
37
|
+
|
|
38
|
+
it( 'should render add new page button', () => {
|
|
39
|
+
// Arrange.
|
|
40
|
+
mockActiveDocument();
|
|
41
|
+
|
|
42
|
+
const isLoading = false;
|
|
43
|
+
const recentPosts: Post[] = [];
|
|
44
|
+
|
|
45
|
+
jest.mocked( useRecentPosts ).mockReturnValue( { isLoading, recentPosts } );
|
|
46
|
+
|
|
47
|
+
const { getByText, getAllByRole } = render( <RecentlyEdited /> );
|
|
48
|
+
|
|
49
|
+
// Act.
|
|
50
|
+
const buttons = getAllByRole( 'button' );
|
|
51
|
+
buttons[ 0 ].click(); // Opens the recently edited menu
|
|
52
|
+
|
|
53
|
+
// Assert.
|
|
54
|
+
const label = getByText( 'Add new page', { exact: false } );
|
|
55
|
+
expect( label ).toBeInTheDocument();
|
|
56
|
+
} );
|
|
57
|
+
|
|
58
|
+
it( 'should trigger create page hook on click', () => {
|
|
59
|
+
// Arrange.
|
|
60
|
+
mockActiveDocument();
|
|
61
|
+
|
|
62
|
+
const isLoading = false;
|
|
63
|
+
const recentPosts: Post[] = [];
|
|
64
|
+
const create = jest.fn();
|
|
65
|
+
|
|
66
|
+
jest.mocked( useRecentPosts ).mockReturnValue( { isLoading, recentPosts } );
|
|
67
|
+
jest.mocked( useCreatePage ).mockReturnValue( { isLoading, create } );
|
|
68
|
+
|
|
69
|
+
const { getByText, getAllByRole } = render( <RecentlyEdited /> );
|
|
70
|
+
|
|
71
|
+
// Act.
|
|
72
|
+
const buttons = getAllByRole( 'button' );
|
|
73
|
+
buttons[ 0 ].click(); // Opens the recently edited menu
|
|
74
|
+
|
|
75
|
+
const addNewPage = getByText( 'Add new page', { exact: false } );
|
|
76
|
+
addNewPage.click();
|
|
77
|
+
|
|
78
|
+
// Assert.
|
|
79
|
+
expect( create ).toHaveBeenCalledTimes( 1 );
|
|
80
|
+
} );
|
|
81
|
+
} );
|
|
82
|
+
|
|
83
|
+
function mockActiveDocument() {
|
|
84
|
+
jest.mocked( useActiveDocument ).mockImplementation( () =>
|
|
85
|
+
createMockDocument( {
|
|
86
|
+
id: 1,
|
|
87
|
+
title: 'Header',
|
|
88
|
+
type: {
|
|
89
|
+
value: 'header',
|
|
90
|
+
label: 'Header',
|
|
91
|
+
},
|
|
92
|
+
} )
|
|
93
|
+
);
|
|
94
|
+
}
|
|
@@ -17,7 +17,7 @@ jest.mock( '../../../hooks/use-recent-posts', () => (
|
|
|
17
17
|
}
|
|
18
18
|
) );
|
|
19
19
|
|
|
20
|
-
describe( '@elementor/
|
|
20
|
+
describe( '@elementor/recently-edited - Top bar Recently Edited', () => {
|
|
21
21
|
beforeEach( () => {
|
|
22
22
|
jest.mocked( useActiveDocument ).mockImplementation( () =>
|
|
23
23
|
createMockDocument( { id: 1, title: 'Active Document' } )
|
|
@@ -173,8 +173,6 @@ describe( '@elementor/editor-site-navigation - Top bar Recently Edited', () => {
|
|
|
173
173
|
const label = getByText( 'Recent' );
|
|
174
174
|
expect( label ).toBeInTheDocument();
|
|
175
175
|
|
|
176
|
-
const menuItems = getAllByRole( 'menuitem' );
|
|
177
|
-
expect( menuItems ).toHaveLength( 1 );
|
|
178
176
|
expect( getByText( 'Test post' ) ).toBeInTheDocument();
|
|
179
177
|
} );
|
|
180
178
|
} );
|
|
@@ -1,52 +1,21 @@
|
|
|
1
1
|
import {
|
|
2
|
-
ArchiveTemplateIcon,
|
|
3
|
-
HeaderTemplateIcon,
|
|
4
|
-
FooterTemplateIcon,
|
|
5
2
|
PostTypeIcon,
|
|
6
|
-
PageTypeIcon,
|
|
7
|
-
PopupTemplateIcon,
|
|
8
|
-
SearchResultsTemplateIcon,
|
|
9
|
-
Error404TemplateIcon,
|
|
10
|
-
LoopItemTemplateIcon,
|
|
11
|
-
LandingPageTemplateIcon,
|
|
12
|
-
PageTemplateIcon,
|
|
13
|
-
SectionTemplateIcon,
|
|
14
|
-
ContainerTemplateIcon,
|
|
15
3
|
} from '@elementor/icons';
|
|
16
4
|
import { Chip } from '@elementor/ui';
|
|
17
|
-
import { DocType } from '../../types';
|
|
18
5
|
import * as React from 'react';
|
|
6
|
+
import { getIconsMap } from '../../icons-map';
|
|
19
7
|
|
|
20
|
-
|
|
21
|
-
[key in DocType]: React.ElementType;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const iconsDocType: DocTypes = {
|
|
25
|
-
header: HeaderTemplateIcon,
|
|
26
|
-
footer: FooterTemplateIcon,
|
|
27
|
-
'single-post': PostTypeIcon,
|
|
28
|
-
'single-page': PageTypeIcon,
|
|
29
|
-
popup: PopupTemplateIcon,
|
|
30
|
-
archive: ArchiveTemplateIcon,
|
|
31
|
-
'search-results': SearchResultsTemplateIcon,
|
|
32
|
-
'loop-item': LoopItemTemplateIcon,
|
|
33
|
-
'error-404': Error404TemplateIcon,
|
|
34
|
-
'landing-page': LandingPageTemplateIcon,
|
|
35
|
-
page: PageTemplateIcon,
|
|
36
|
-
section: SectionTemplateIcon,
|
|
37
|
-
container: ContainerTemplateIcon,
|
|
38
|
-
'wp-page': PageTypeIcon,
|
|
39
|
-
'wp-post': PostTypeIcon,
|
|
40
|
-
};
|
|
8
|
+
const iconsMap = getIconsMap();
|
|
41
9
|
|
|
42
10
|
export type Props = {
|
|
43
11
|
postType: string;
|
|
44
|
-
docType:
|
|
12
|
+
docType: string;
|
|
45
13
|
label: string;
|
|
46
14
|
};
|
|
15
|
+
|
|
47
16
|
export default function DocTypeChip( { postType, docType, label }: Props ) {
|
|
48
17
|
const color = 'elementor_library' === postType ? 'global' : 'primary';
|
|
49
|
-
const Icon =
|
|
18
|
+
const Icon = iconsMap[ docType ] || PostTypeIcon;
|
|
50
19
|
|
|
51
20
|
return (
|
|
52
21
|
<Chip
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { Typography, Stack, Tooltip as BaseTooltip, TooltipProps } from '@elementor/ui';
|
|
3
3
|
import { Document } from '@elementor/editor-documents';
|
|
4
4
|
|
|
5
5
|
type Props = {
|
|
@@ -23,3 +23,16 @@ export default function Indicator( { title, status }: Props ) {
|
|
|
23
23
|
</Tooltip>
|
|
24
24
|
);
|
|
25
25
|
}
|
|
26
|
+
|
|
27
|
+
function Tooltip( props: TooltipProps ) {
|
|
28
|
+
return <BaseTooltip
|
|
29
|
+
PopperProps={ {
|
|
30
|
+
sx: {
|
|
31
|
+
'&.MuiTooltip-popper .MuiTooltip-tooltip.MuiTooltip-tooltipPlacementBottom': {
|
|
32
|
+
mt: 7,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
} }
|
|
36
|
+
{ ...props }
|
|
37
|
+
/>;
|
|
38
|
+
}
|
|
@@ -1,19 +1,26 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
1
|
import {
|
|
2
|
+
Divider,
|
|
3
3
|
MenuItem,
|
|
4
|
+
ListItemIcon,
|
|
4
5
|
ListSubheader,
|
|
5
6
|
Typography,
|
|
7
|
+
CircularProgress,
|
|
6
8
|
} from '@elementor/ui';
|
|
7
9
|
|
|
10
|
+
import * as React from 'react';
|
|
8
11
|
import { __ } from '@wordpress/i18n';
|
|
9
|
-
import DocTypeChip, { Props } from '
|
|
12
|
+
import DocTypeChip, { Props } from './chip-doc-type';
|
|
10
13
|
import { Post } from '../../hooks/use-recent-posts';
|
|
14
|
+
import useCreatePage from '../../hooks/use-create-page';
|
|
15
|
+
import { PlusIcon } from '@elementor/icons';
|
|
11
16
|
|
|
12
17
|
export type RecentPostsProps = {
|
|
13
18
|
recentPosts: Post[];
|
|
14
19
|
};
|
|
15
20
|
|
|
16
21
|
export default function PostsList( { recentPosts }: RecentPostsProps ) {
|
|
22
|
+
const { create, isLoading } = useCreatePage( { onCreated } );
|
|
23
|
+
|
|
17
24
|
return (
|
|
18
25
|
<>
|
|
19
26
|
<ListSubheader sx={ { fontSize: 12, fontStyle: 'italic', pl: 4 } } component="div" id="nested-list-subheader">
|
|
@@ -23,6 +30,7 @@ export default function PostsList( { recentPosts }: RecentPostsProps ) {
|
|
|
23
30
|
{ recentPosts.length
|
|
24
31
|
? ( recentPosts.map( ( { title, edit_url: editUrl, type, id } ) => (
|
|
25
32
|
<MenuItem
|
|
33
|
+
dense
|
|
26
34
|
key={ id }
|
|
27
35
|
component="a"
|
|
28
36
|
href={ editUrl }
|
|
@@ -36,6 +44,24 @@ export default function PostsList( { recentPosts }: RecentPostsProps ) {
|
|
|
36
44
|
</Typography>
|
|
37
45
|
)
|
|
38
46
|
}
|
|
47
|
+
<Divider />
|
|
48
|
+
<MenuItem
|
|
49
|
+
dense
|
|
50
|
+
size="small"
|
|
51
|
+
color="inherit"
|
|
52
|
+
component="div"
|
|
53
|
+
onClick={ create }
|
|
54
|
+
>
|
|
55
|
+
<ListItemIcon>
|
|
56
|
+
{ isLoading ? <CircularProgress /> : <PlusIcon /> }
|
|
57
|
+
</ListItemIcon>
|
|
58
|
+
|
|
59
|
+
{ __( 'Add new page', 'elementor' ) }
|
|
60
|
+
</MenuItem>
|
|
39
61
|
</>
|
|
40
62
|
);
|
|
41
63
|
}
|
|
64
|
+
|
|
65
|
+
function onCreated( url: string ) {
|
|
66
|
+
window.location.href = url;
|
|
67
|
+
}
|
|
@@ -35,7 +35,8 @@ export default function RecentlyEdited() {
|
|
|
35
35
|
<Box sx={ { cursor: 'default' } }>
|
|
36
36
|
<Button
|
|
37
37
|
color="inherit"
|
|
38
|
-
|
|
38
|
+
size="small"
|
|
39
|
+
endIcon={ <ChevronDownIcon fontSize="small" /> }
|
|
39
40
|
{ ...bindTrigger( popupState ) }
|
|
40
41
|
>
|
|
41
42
|
<Indicator
|
|
@@ -45,7 +46,8 @@ export default function RecentlyEdited() {
|
|
|
45
46
|
</Button>
|
|
46
47
|
|
|
47
48
|
<Menu
|
|
48
|
-
|
|
49
|
+
MenuListProps={ { component: 'div' } }
|
|
50
|
+
PaperProps={ { sx: { mt: 4, minWidth: 314 } } }
|
|
49
51
|
{ ...bindMenu( popupState ) }
|
|
50
52
|
>
|
|
51
53
|
<PostsList recentPosts={ recentPosts } />
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { renderHook } from '@testing-library/react-hooks';
|
|
2
|
+
import { waitFor } from '@testing-library/react';
|
|
3
|
+
import apiFetch from '@wordpress/api-fetch';
|
|
4
|
+
import useCreatePage, { endpointPath } from '../use-create-page';
|
|
5
|
+
|
|
6
|
+
// Mock apiFetch to return a promise that resolves to an empty array.
|
|
7
|
+
jest.mock( '@wordpress/api-fetch' );
|
|
8
|
+
|
|
9
|
+
describe( '@elementor/recently-edited/use-page', () => {
|
|
10
|
+
beforeEach( () => {
|
|
11
|
+
jest.mocked( apiFetch ).mockImplementation( () => Promise.resolve( [] ) );
|
|
12
|
+
} );
|
|
13
|
+
|
|
14
|
+
afterEach( () => {
|
|
15
|
+
jest.clearAllMocks();
|
|
16
|
+
} );
|
|
17
|
+
|
|
18
|
+
it( 'should run useCreatePage hook', async () => {
|
|
19
|
+
// Arrange.
|
|
20
|
+
const onCreated = jest.fn();
|
|
21
|
+
const { result } = renderHook( () => useCreatePage( { onCreated } ) );
|
|
22
|
+
const newPost = {
|
|
23
|
+
id: 1,
|
|
24
|
+
edit_url: 'editurl.com',
|
|
25
|
+
};
|
|
26
|
+
jest.mocked( apiFetch ).mockImplementation( () => Promise.resolve( newPost ) );
|
|
27
|
+
|
|
28
|
+
const { create } = result.current;
|
|
29
|
+
|
|
30
|
+
// Act.
|
|
31
|
+
create();
|
|
32
|
+
|
|
33
|
+
// Assert.
|
|
34
|
+
await waitFor( () => {
|
|
35
|
+
expect( apiFetch ).toHaveBeenCalledWith( {
|
|
36
|
+
data: { post_type: 'page' },
|
|
37
|
+
method: 'POST',
|
|
38
|
+
path: endpointPath,
|
|
39
|
+
} );
|
|
40
|
+
expect( apiFetch ).toHaveBeenCalledTimes( 1 );
|
|
41
|
+
} );
|
|
42
|
+
} );
|
|
43
|
+
} );
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { waitFor } from '@testing-library/react';
|
|
2
|
+
import { renderHook } from '@testing-library/react-hooks';
|
|
3
|
+
import apiFetch from '@wordpress/api-fetch';
|
|
4
|
+
import useRecentPosts, { endpointPath } from '../use-recent-posts';
|
|
5
|
+
|
|
6
|
+
// Mock apiFetch to return a promise that resolves to an empty array.
|
|
7
|
+
jest.mock( '@wordpress/api-fetch' );
|
|
8
|
+
|
|
9
|
+
describe( 'useRecentPosts', () => {
|
|
10
|
+
beforeEach( () => {
|
|
11
|
+
jest.mocked( apiFetch ).mockImplementation( () => Promise.resolve( [] ) );
|
|
12
|
+
} );
|
|
13
|
+
|
|
14
|
+
afterEach( () => {
|
|
15
|
+
jest.clearAllMocks();
|
|
16
|
+
} );
|
|
17
|
+
|
|
18
|
+
it( 'should return an array of posts when the request succeeds', async () => {
|
|
19
|
+
const posts = [
|
|
20
|
+
{
|
|
21
|
+
id: 1,
|
|
22
|
+
title: 'Post 1',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: 2,
|
|
26
|
+
title: 'Post 2',
|
|
27
|
+
},
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
jest.mocked( apiFetch ).mockImplementation( () => Promise.resolve( posts ) );
|
|
31
|
+
|
|
32
|
+
const { result } = renderHook( () => useRecentPosts( 1 ) );
|
|
33
|
+
|
|
34
|
+
await waitFor( () => {
|
|
35
|
+
expect( apiFetch ).toHaveBeenCalledWith( {
|
|
36
|
+
path: endpointPath + '?posts_per_page=5&post__not_in=1',
|
|
37
|
+
} );
|
|
38
|
+
|
|
39
|
+
expect( result.current.recentPosts ).toBe( posts );
|
|
40
|
+
} );
|
|
41
|
+
} );
|
|
42
|
+
} );
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import apiFetch from '@wordpress/api-fetch';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
|
|
4
|
+
export interface NewPost {
|
|
5
|
+
id: number,
|
|
6
|
+
edit_url: string,
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type Args = {
|
|
10
|
+
onCreated: ( url : string ) => void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const endpointPath = '/elementor/v1/site-navigation/add-new-post';
|
|
14
|
+
|
|
15
|
+
export default function useCreatePage( { onCreated }: Args ) {
|
|
16
|
+
const [ isLoading, setIsLoading ] = useState( false );
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
create: () => {
|
|
20
|
+
setIsLoading( true );
|
|
21
|
+
|
|
22
|
+
addNewPage()
|
|
23
|
+
.then( ( newPost ) => newPost as NewPost )
|
|
24
|
+
.then( ( newPost ) => {
|
|
25
|
+
setIsLoading( false );
|
|
26
|
+
onCreated( newPost.edit_url );
|
|
27
|
+
} )
|
|
28
|
+
.catch( () => {
|
|
29
|
+
setIsLoading( false );
|
|
30
|
+
} );
|
|
31
|
+
},
|
|
32
|
+
isLoading,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function addNewPage() {
|
|
37
|
+
return await apiFetch( {
|
|
38
|
+
path: endpointPath,
|
|
39
|
+
method: 'POST',
|
|
40
|
+
data: { post_type: 'page' },
|
|
41
|
+
} );
|
|
42
|
+
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { useEffect, useState } from 'react';
|
|
2
|
-
import { DocType } from '../types';
|
|
3
2
|
import apiFetch from '@wordpress/api-fetch';
|
|
4
3
|
import { addQueryArgs } from '@wordpress/url';
|
|
5
4
|
|
|
@@ -9,12 +8,14 @@ export interface Post {
|
|
|
9
8
|
edit_url: string,
|
|
10
9
|
type: {
|
|
11
10
|
post_type: string,
|
|
12
|
-
doc_type:
|
|
11
|
+
doc_type: string,
|
|
13
12
|
label: string,
|
|
14
13
|
},
|
|
15
14
|
date_modified: number,
|
|
16
15
|
}
|
|
17
16
|
|
|
17
|
+
export const endpointPath = '/elementor/v1/site-navigation/recent-posts';
|
|
18
|
+
|
|
18
19
|
export default function useRecentPosts( documentId?: number ) {
|
|
19
20
|
const [ recentPosts, setRecentPosts ] = useState<Post[]>( [] );
|
|
20
21
|
const [ isLoading, setIsLoading ] = useState( false );
|
|
@@ -43,7 +44,7 @@ async function fetchRecentlyEditedPosts( documentId: number ) {
|
|
|
43
44
|
};
|
|
44
45
|
|
|
45
46
|
return await apiFetch( {
|
|
46
|
-
path: addQueryArgs(
|
|
47
|
+
path: addQueryArgs( endpointPath, queryParams ),
|
|
47
48
|
} ).then( ( response ) => response as Post[] )
|
|
48
49
|
.catch( () => [] );
|
|
49
50
|
}
|
package/src/icons-map.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PostTypeIcon,
|
|
3
|
+
PageTypeIcon,
|
|
4
|
+
PageTemplateIcon,
|
|
5
|
+
SectionTemplateIcon,
|
|
6
|
+
ContainerTemplateIcon,
|
|
7
|
+
} from '@elementor/icons';
|
|
8
|
+
|
|
9
|
+
import * as React from 'react';
|
|
10
|
+
|
|
11
|
+
type IconsMap = {
|
|
12
|
+
[key: string]: React.ElementType;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const initialIconsMap: IconsMap = {
|
|
16
|
+
page: PageTemplateIcon,
|
|
17
|
+
section: SectionTemplateIcon,
|
|
18
|
+
container: ContainerTemplateIcon,
|
|
19
|
+
'wp-page': PageTypeIcon,
|
|
20
|
+
'wp-post': PostTypeIcon,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
let iconsMap = { ...initialIconsMap };
|
|
24
|
+
|
|
25
|
+
export function extendIconsMap( additionalIcons: IconsMap ) {
|
|
26
|
+
Object.assign( iconsMap, additionalIcons );
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function getIconsMap() {
|
|
30
|
+
return iconsMap;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function resetIconsMap() {
|
|
34
|
+
iconsMap = { ...initialIconsMap };
|
|
35
|
+
}
|
package/src/index.ts
CHANGED
package/src/types.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export type DocType = 'header' | 'footer' | 'single-post' | 'single-page' | 'popup' | 'archive' | 'search-results' | 'loop-item' | 'error-404' | 'landing-page' | 'page' | 'section' | 'container' | 'wp-page' | 'wp-post';
|