@elementor/editor-site-navigation 0.3.0 → 0.4.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 +23 -0
- package/dist/index.js +110 -98
- package/dist/index.mjs +105 -97
- package/package.json +4 -4
- package/src/components/top-bar/__tests__/add-new-page.test.tsx +13 -5
- package/src/components/top-bar/__tests__/recently-edited.test.tsx +91 -1
- package/src/components/top-bar/create-post-list-item.tsx +26 -0
- package/src/components/top-bar/post-list-item.tsx +26 -0
- package/src/components/top-bar/recently-edited.tsx +27 -3
- package/src/hooks/__tests__/use-create-page.test.ts +1 -2
- package/src/hooks/use-create-page.ts +3 -13
- package/src/hooks/use-reverse-html-entities.ts +14 -0
- package/src/init.ts +1 -1
- package/src/components/top-bar/posts-list.tsx +0 -67
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,29 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [0.4.1](https://github.com/elementor/elementor-packages/compare/@elementor/editor-site-navigation@0.4.0...@elementor/editor-site-navigation@0.4.1) (2023-05-23)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* **site-navigation:** render special chars [ED-10809] ([#42](https://github.com/elementor/elementor-packages/issues/42)) ([a276cf3](https://github.com/elementor/elementor-packages/commit/a276cf36e4f428da3b109f0bcd4e83ca3501e793))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# [0.4.0](https://github.com/elementor/elementor-packages/compare/@elementor/editor-site-navigation@0.3.0...@elementor/editor-site-navigation@0.4.0) (2023-05-21)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
* **editor-site-navigation:** change post without refresh [ED-10713] ([#39](https://github.com/elementor/elementor-packages/issues/39)) ([b72e82f](https://github.com/elementor/elementor-packages/commit/b72e82f9adb9c1237300cbf603f33f268f9f0400))
|
|
23
|
+
* **locations:** change api to support props for slots [ED-10730] ([#38](https://github.com/elementor/elementor-packages/issues/38)) ([44bec3c](https://github.com/elementor/elementor-packages/commit/44bec3cda1020037ba7105c6f05ce4baa8e3b376))
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
6
29
|
# 0.3.0 (2023-05-16)
|
|
7
30
|
|
|
8
31
|
|
package/dist/index.js
CHANGED
|
@@ -52,10 +52,10 @@ function getIconsMap() {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
// src/components/top-bar/recently-edited.tsx
|
|
55
|
-
var
|
|
56
|
-
var
|
|
55
|
+
var React5 = __toESM(require("react"));
|
|
56
|
+
var import_ui5 = require("@elementor/ui");
|
|
57
57
|
var import_icons4 = require("@elementor/icons");
|
|
58
|
-
var
|
|
58
|
+
var import_editor_documents3 = require("@elementor/editor-documents");
|
|
59
59
|
|
|
60
60
|
// src/components/top-bar/indicator.tsx
|
|
61
61
|
var React = __toESM(require("react"));
|
|
@@ -79,10 +79,40 @@ function Tooltip(props) {
|
|
|
79
79
|
);
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
// src/
|
|
83
|
-
var
|
|
84
|
-
var
|
|
85
|
-
var
|
|
82
|
+
// src/hooks/use-recent-posts.ts
|
|
83
|
+
var import_react = require("react");
|
|
84
|
+
var import_api_fetch = __toESM(require("@wordpress/api-fetch"));
|
|
85
|
+
var import_url = require("@wordpress/url");
|
|
86
|
+
var endpointPath = "/elementor/v1/site-navigation/recent-posts";
|
|
87
|
+
function useRecentPosts(documentId) {
|
|
88
|
+
const [recentPosts, setRecentPosts] = (0, import_react.useState)([]);
|
|
89
|
+
const [isLoading, setIsLoading] = (0, import_react.useState)(false);
|
|
90
|
+
(0, import_react.useEffect)(() => {
|
|
91
|
+
if (documentId) {
|
|
92
|
+
setIsLoading(true);
|
|
93
|
+
fetchRecentlyEditedPosts(documentId).then((posts) => {
|
|
94
|
+
setRecentPosts(posts);
|
|
95
|
+
setIsLoading(false);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}, [documentId]);
|
|
99
|
+
return {
|
|
100
|
+
isLoading,
|
|
101
|
+
recentPosts
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
async function fetchRecentlyEditedPosts(documentId) {
|
|
105
|
+
const queryParams = {
|
|
106
|
+
posts_per_page: 5,
|
|
107
|
+
post__not_in: documentId
|
|
108
|
+
};
|
|
109
|
+
return await (0, import_api_fetch.default)({
|
|
110
|
+
path: (0, import_url.addQueryArgs)(endpointPath, queryParams)
|
|
111
|
+
}).then((response) => response).catch(() => []);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// src/components/top-bar/recently-edited.tsx
|
|
115
|
+
var import_i18n2 = require("@wordpress/i18n");
|
|
86
116
|
|
|
87
117
|
// src/components/top-bar/chip-doc-type.tsx
|
|
88
118
|
var import_icons2 = require("@elementor/icons");
|
|
@@ -104,132 +134,114 @@ function DocTypeChip({ postType, docType, label }) {
|
|
|
104
134
|
);
|
|
105
135
|
}
|
|
106
136
|
|
|
137
|
+
// src/components/top-bar/post-list-item.tsx
|
|
138
|
+
var import_ui3 = require("@elementor/ui");
|
|
139
|
+
var React3 = __toESM(require("react"));
|
|
140
|
+
var import_editor_documents = require("@elementor/editor-documents");
|
|
141
|
+
|
|
142
|
+
// src/hooks/use-reverse-html-entities.ts
|
|
143
|
+
var import_react2 = require("react");
|
|
144
|
+
function useReverseHtmlEntities(escapedHTML = "") {
|
|
145
|
+
return (0, import_react2.useMemo)(() => {
|
|
146
|
+
const textarea = document.createElement("textarea");
|
|
147
|
+
textarea.innerHTML = escapedHTML;
|
|
148
|
+
const { value } = textarea;
|
|
149
|
+
textarea.remove();
|
|
150
|
+
return value;
|
|
151
|
+
}, [escapedHTML]);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// src/components/top-bar/post-list-item.tsx
|
|
155
|
+
function PostListItem({ post, closePopup }) {
|
|
156
|
+
const navigateToDocument = (0, import_editor_documents.useNavigateToDocument)();
|
|
157
|
+
const postTitle = useReverseHtmlEntities(post.title);
|
|
158
|
+
return /* @__PURE__ */ React3.createElement(import_ui3.MenuItem, { dense: true, sx: { width: "100%" }, onClick: () => {
|
|
159
|
+
closePopup();
|
|
160
|
+
navigateToDocument(post.id);
|
|
161
|
+
} }, postTitle, /* @__PURE__ */ React3.createElement(DocTypeChip, { postType: post.type.post_type, docType: post.type.doc_type, label: post.type.label }));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// src/components/top-bar/create-post-list-item.tsx
|
|
165
|
+
var import_ui4 = require("@elementor/ui");
|
|
166
|
+
var React4 = __toESM(require("react"));
|
|
167
|
+
|
|
107
168
|
// src/hooks/use-create-page.ts
|
|
108
|
-
var
|
|
109
|
-
var
|
|
110
|
-
var
|
|
111
|
-
function useCreatePage(
|
|
112
|
-
const [isLoading, setIsLoading] = (0,
|
|
169
|
+
var import_api_fetch2 = __toESM(require("@wordpress/api-fetch"));
|
|
170
|
+
var import_react3 = require("react");
|
|
171
|
+
var endpointPath2 = "/elementor/v1/site-navigation/add-new-post";
|
|
172
|
+
function useCreatePage() {
|
|
173
|
+
const [isLoading, setIsLoading] = (0, import_react3.useState)(false);
|
|
113
174
|
return {
|
|
114
175
|
create: () => {
|
|
115
176
|
setIsLoading(true);
|
|
116
|
-
addNewPage().then((newPost) => newPost).
|
|
117
|
-
setIsLoading(false);
|
|
118
|
-
onCreated2(newPost.edit_url);
|
|
119
|
-
}).catch(() => {
|
|
120
|
-
setIsLoading(false);
|
|
121
|
-
});
|
|
177
|
+
return addNewPage().then((newPost) => newPost).finally(() => setIsLoading(false));
|
|
122
178
|
},
|
|
123
179
|
isLoading
|
|
124
180
|
};
|
|
125
181
|
}
|
|
126
182
|
async function addNewPage() {
|
|
127
|
-
return await (0,
|
|
128
|
-
path:
|
|
183
|
+
return await (0, import_api_fetch2.default)({
|
|
184
|
+
path: endpointPath2,
|
|
129
185
|
method: "POST",
|
|
130
186
|
data: { post_type: "page" }
|
|
131
187
|
});
|
|
132
188
|
}
|
|
133
189
|
|
|
134
|
-
// src/components/top-bar/
|
|
190
|
+
// src/components/top-bar/create-post-list-item.tsx
|
|
135
191
|
var import_icons3 = require("@elementor/icons");
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
title,
|
|
147
|
-
/* @__PURE__ */ React3.createElement(DocTypeChip, { postType: type.post_type, docType: type.doc_type, label: type.label })
|
|
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;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// src/hooks/use-recent-posts.ts
|
|
166
|
-
var import_react2 = require("react");
|
|
167
|
-
var import_api_fetch2 = __toESM(require("@wordpress/api-fetch"));
|
|
168
|
-
var import_url = require("@wordpress/url");
|
|
169
|
-
var endpointPath2 = "/elementor/v1/site-navigation/recent-posts";
|
|
170
|
-
function useRecentPosts(documentId) {
|
|
171
|
-
const [recentPosts, setRecentPosts] = (0, import_react2.useState)([]);
|
|
172
|
-
const [isLoading, setIsLoading] = (0, import_react2.useState)(false);
|
|
173
|
-
(0, import_react2.useEffect)(() => {
|
|
174
|
-
if (documentId) {
|
|
175
|
-
setIsLoading(true);
|
|
176
|
-
fetchRecentlyEditedPosts(documentId).then((posts) => {
|
|
177
|
-
setRecentPosts(posts);
|
|
178
|
-
setIsLoading(false);
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
}, [documentId]);
|
|
182
|
-
return {
|
|
183
|
-
isLoading,
|
|
184
|
-
recentPosts
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
async function fetchRecentlyEditedPosts(documentId) {
|
|
188
|
-
const queryParams = {
|
|
189
|
-
posts_per_page: 5,
|
|
190
|
-
post__not_in: documentId
|
|
191
|
-
};
|
|
192
|
-
return await (0, import_api_fetch2.default)({
|
|
193
|
-
path: (0, import_url.addQueryArgs)(endpointPath2, queryParams)
|
|
194
|
-
}).then((response) => response).catch(() => []);
|
|
192
|
+
var import_i18n = require("@wordpress/i18n");
|
|
193
|
+
var import_editor_documents2 = require("@elementor/editor-documents");
|
|
194
|
+
function CreatePostListItem({ closePopup }) {
|
|
195
|
+
const { create, isLoading } = useCreatePage();
|
|
196
|
+
const navigateToDocument = (0, import_editor_documents2.useNavigateToDocument)();
|
|
197
|
+
return /* @__PURE__ */ React4.createElement(import_ui4.MenuItem, { dense: true, size: "small", color: "inherit", component: "div", onClick: async () => {
|
|
198
|
+
const { id } = await create();
|
|
199
|
+
closePopup();
|
|
200
|
+
navigateToDocument(id);
|
|
201
|
+
} }, /* @__PURE__ */ React4.createElement(import_ui4.ListItemIcon, null, isLoading ? /* @__PURE__ */ React4.createElement(import_ui4.CircularProgress, null) : /* @__PURE__ */ React4.createElement(import_icons3.PlusIcon, null)), (0, import_i18n.__)("Add new page", "elementor"));
|
|
195
202
|
}
|
|
196
203
|
|
|
197
204
|
// src/components/top-bar/recently-edited.tsx
|
|
198
205
|
function RecentlyEdited() {
|
|
199
|
-
const activeDocument = (0,
|
|
200
|
-
const hostDocument = (0,
|
|
201
|
-
const
|
|
202
|
-
const { recentPosts } = useRecentPosts(
|
|
203
|
-
const popupState = (0,
|
|
206
|
+
const activeDocument = (0, import_editor_documents3.useActiveDocument)();
|
|
207
|
+
const hostDocument = (0, import_editor_documents3.useHostDocument)();
|
|
208
|
+
const document2 = activeDocument && activeDocument.type.value !== "kit" ? activeDocument : hostDocument;
|
|
209
|
+
const { recentPosts } = useRecentPosts(document2?.id);
|
|
210
|
+
const popupState = (0, import_ui5.usePopupState)({
|
|
204
211
|
variant: "popover",
|
|
205
212
|
popupId: "elementor-v2-top-bar-recently-edited"
|
|
206
213
|
});
|
|
207
|
-
|
|
214
|
+
const documentTitle = useReverseHtmlEntities(document2?.title);
|
|
215
|
+
if (!document2) {
|
|
208
216
|
return null;
|
|
209
217
|
}
|
|
210
|
-
return /* @__PURE__ */
|
|
211
|
-
|
|
218
|
+
return /* @__PURE__ */ React5.createElement(import_ui5.Box, { sx: { cursor: "default" } }, /* @__PURE__ */ React5.createElement(
|
|
219
|
+
import_ui5.Button,
|
|
212
220
|
{
|
|
213
221
|
color: "inherit",
|
|
214
222
|
size: "small",
|
|
215
|
-
endIcon: /* @__PURE__ */
|
|
216
|
-
...(0,
|
|
223
|
+
endIcon: /* @__PURE__ */ React5.createElement(import_icons4.ChevronDownIcon, { fontSize: "small" }),
|
|
224
|
+
...(0, import_ui5.bindTrigger)(popupState)
|
|
217
225
|
},
|
|
218
|
-
/* @__PURE__ */
|
|
226
|
+
/* @__PURE__ */ React5.createElement(
|
|
219
227
|
Indicator,
|
|
220
228
|
{
|
|
221
|
-
title:
|
|
222
|
-
status:
|
|
229
|
+
title: documentTitle,
|
|
230
|
+
status: document2.status
|
|
223
231
|
}
|
|
224
232
|
)
|
|
225
|
-
), /* @__PURE__ */
|
|
226
|
-
|
|
233
|
+
), /* @__PURE__ */ React5.createElement(
|
|
234
|
+
import_ui5.Menu,
|
|
227
235
|
{
|
|
228
236
|
MenuListProps: { component: "div" },
|
|
229
237
|
PaperProps: { sx: { mt: 4, minWidth: 314 } },
|
|
230
|
-
...(0,
|
|
238
|
+
...(0, import_ui5.bindMenu)(popupState)
|
|
231
239
|
},
|
|
232
|
-
/* @__PURE__ */
|
|
240
|
+
/* @__PURE__ */ React5.createElement(import_ui5.ListSubheader, { sx: { fontSize: 12, fontStyle: "italic", pl: 4 }, component: "div", id: "nested-list-subheader" }, (0, import_i18n2.__)("Recent", "elementor")),
|
|
241
|
+
recentPosts.map((post) => /* @__PURE__ */ React5.createElement(PostListItem, { key: post.id, post, closePopup: popupState.close })),
|
|
242
|
+
recentPosts.length === 0 && /* @__PURE__ */ React5.createElement(import_ui5.Typography, { variant: "caption", sx: { color: "grey.500", fontStyle: "italic", p: 4 }, component: "div", "aria-label": void 0 }, (0, import_i18n2.__)("There are no other pages or templates on this site yet.", "elementor")),
|
|
243
|
+
/* @__PURE__ */ React5.createElement(import_ui5.Divider, null),
|
|
244
|
+
/* @__PURE__ */ React5.createElement(CreatePostListItem, { closePopup: popupState.close })
|
|
233
245
|
));
|
|
234
246
|
}
|
|
235
247
|
|
|
@@ -240,7 +252,7 @@ function init() {
|
|
|
240
252
|
}
|
|
241
253
|
function registerTopBarMenuItems() {
|
|
242
254
|
(0, import_editor_app_bar.injectIntoPageIndication)({
|
|
243
|
-
|
|
255
|
+
id: "document-recently-edited",
|
|
244
256
|
filler: RecentlyEdited
|
|
245
257
|
});
|
|
246
258
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -22,14 +22,17 @@ function getIconsMap() {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
// src/components/top-bar/recently-edited.tsx
|
|
25
|
-
import * as
|
|
25
|
+
import * as React5 from "react";
|
|
26
26
|
import {
|
|
27
27
|
bindMenu,
|
|
28
28
|
usePopupState,
|
|
29
29
|
bindTrigger,
|
|
30
30
|
Menu,
|
|
31
31
|
Button,
|
|
32
|
-
Box
|
|
32
|
+
Box,
|
|
33
|
+
ListSubheader,
|
|
34
|
+
Typography as Typography2,
|
|
35
|
+
Divider
|
|
33
36
|
} from "@elementor/ui";
|
|
34
37
|
import { ChevronDownIcon } from "@elementor/icons";
|
|
35
38
|
import { useActiveDocument, useHostDocument } from "@elementor/editor-documents";
|
|
@@ -56,17 +59,40 @@ function Tooltip(props) {
|
|
|
56
59
|
);
|
|
57
60
|
}
|
|
58
61
|
|
|
59
|
-
// src/
|
|
60
|
-
import {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
62
|
+
// src/hooks/use-recent-posts.ts
|
|
63
|
+
import { useEffect, useState } from "react";
|
|
64
|
+
import apiFetch from "@wordpress/api-fetch";
|
|
65
|
+
import { addQueryArgs } from "@wordpress/url";
|
|
66
|
+
var endpointPath = "/elementor/v1/site-navigation/recent-posts";
|
|
67
|
+
function useRecentPosts(documentId) {
|
|
68
|
+
const [recentPosts, setRecentPosts] = useState([]);
|
|
69
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
if (documentId) {
|
|
72
|
+
setIsLoading(true);
|
|
73
|
+
fetchRecentlyEditedPosts(documentId).then((posts) => {
|
|
74
|
+
setRecentPosts(posts);
|
|
75
|
+
setIsLoading(false);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}, [documentId]);
|
|
79
|
+
return {
|
|
80
|
+
isLoading,
|
|
81
|
+
recentPosts
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
async function fetchRecentlyEditedPosts(documentId) {
|
|
85
|
+
const queryParams = {
|
|
86
|
+
posts_per_page: 5,
|
|
87
|
+
post__not_in: documentId
|
|
88
|
+
};
|
|
89
|
+
return await apiFetch({
|
|
90
|
+
path: addQueryArgs(endpointPath, queryParams)
|
|
91
|
+
}).then((response) => response).catch(() => []);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// src/components/top-bar/recently-edited.tsx
|
|
95
|
+
import { __ as __2 } from "@wordpress/i18n";
|
|
70
96
|
|
|
71
97
|
// src/components/top-bar/chip-doc-type.tsx
|
|
72
98
|
import {
|
|
@@ -90,132 +116,114 @@ function DocTypeChip({ postType, docType, label }) {
|
|
|
90
116
|
);
|
|
91
117
|
}
|
|
92
118
|
|
|
119
|
+
// src/components/top-bar/post-list-item.tsx
|
|
120
|
+
import { MenuItem } from "@elementor/ui";
|
|
121
|
+
import * as React3 from "react";
|
|
122
|
+
import { useNavigateToDocument } from "@elementor/editor-documents";
|
|
123
|
+
|
|
124
|
+
// src/hooks/use-reverse-html-entities.ts
|
|
125
|
+
import { useMemo } from "react";
|
|
126
|
+
function useReverseHtmlEntities(escapedHTML = "") {
|
|
127
|
+
return useMemo(() => {
|
|
128
|
+
const textarea = document.createElement("textarea");
|
|
129
|
+
textarea.innerHTML = escapedHTML;
|
|
130
|
+
const { value } = textarea;
|
|
131
|
+
textarea.remove();
|
|
132
|
+
return value;
|
|
133
|
+
}, [escapedHTML]);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// src/components/top-bar/post-list-item.tsx
|
|
137
|
+
function PostListItem({ post, closePopup }) {
|
|
138
|
+
const navigateToDocument = useNavigateToDocument();
|
|
139
|
+
const postTitle = useReverseHtmlEntities(post.title);
|
|
140
|
+
return /* @__PURE__ */ React3.createElement(MenuItem, { dense: true, sx: { width: "100%" }, onClick: () => {
|
|
141
|
+
closePopup();
|
|
142
|
+
navigateToDocument(post.id);
|
|
143
|
+
} }, postTitle, /* @__PURE__ */ React3.createElement(DocTypeChip, { postType: post.type.post_type, docType: post.type.doc_type, label: post.type.label }));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// src/components/top-bar/create-post-list-item.tsx
|
|
147
|
+
import { CircularProgress, ListItemIcon, MenuItem as MenuItem2 } from "@elementor/ui";
|
|
148
|
+
import * as React4 from "react";
|
|
149
|
+
|
|
93
150
|
// src/hooks/use-create-page.ts
|
|
94
|
-
import
|
|
95
|
-
import { useState } from "react";
|
|
96
|
-
var
|
|
97
|
-
function useCreatePage(
|
|
98
|
-
const [isLoading, setIsLoading] =
|
|
151
|
+
import apiFetch2 from "@wordpress/api-fetch";
|
|
152
|
+
import { useState as useState2 } from "react";
|
|
153
|
+
var endpointPath2 = "/elementor/v1/site-navigation/add-new-post";
|
|
154
|
+
function useCreatePage() {
|
|
155
|
+
const [isLoading, setIsLoading] = useState2(false);
|
|
99
156
|
return {
|
|
100
157
|
create: () => {
|
|
101
158
|
setIsLoading(true);
|
|
102
|
-
addNewPage().then((newPost) => newPost).
|
|
103
|
-
setIsLoading(false);
|
|
104
|
-
onCreated2(newPost.edit_url);
|
|
105
|
-
}).catch(() => {
|
|
106
|
-
setIsLoading(false);
|
|
107
|
-
});
|
|
159
|
+
return addNewPage().then((newPost) => newPost).finally(() => setIsLoading(false));
|
|
108
160
|
},
|
|
109
161
|
isLoading
|
|
110
162
|
};
|
|
111
163
|
}
|
|
112
164
|
async function addNewPage() {
|
|
113
|
-
return await
|
|
114
|
-
path:
|
|
165
|
+
return await apiFetch2({
|
|
166
|
+
path: endpointPath2,
|
|
115
167
|
method: "POST",
|
|
116
168
|
data: { post_type: "page" }
|
|
117
169
|
});
|
|
118
170
|
}
|
|
119
171
|
|
|
120
|
-
// src/components/top-bar/
|
|
172
|
+
// src/components/top-bar/create-post-list-item.tsx
|
|
121
173
|
import { PlusIcon } from "@elementor/icons";
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
title,
|
|
133
|
-
/* @__PURE__ */ React3.createElement(DocTypeChip, { postType: type.post_type, docType: type.doc_type, label: type.label })
|
|
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;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// src/hooks/use-recent-posts.ts
|
|
152
|
-
import { useEffect, useState as useState2 } from "react";
|
|
153
|
-
import apiFetch2 from "@wordpress/api-fetch";
|
|
154
|
-
import { addQueryArgs } from "@wordpress/url";
|
|
155
|
-
var endpointPath2 = "/elementor/v1/site-navigation/recent-posts";
|
|
156
|
-
function useRecentPosts(documentId) {
|
|
157
|
-
const [recentPosts, setRecentPosts] = useState2([]);
|
|
158
|
-
const [isLoading, setIsLoading] = useState2(false);
|
|
159
|
-
useEffect(() => {
|
|
160
|
-
if (documentId) {
|
|
161
|
-
setIsLoading(true);
|
|
162
|
-
fetchRecentlyEditedPosts(documentId).then((posts) => {
|
|
163
|
-
setRecentPosts(posts);
|
|
164
|
-
setIsLoading(false);
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
}, [documentId]);
|
|
168
|
-
return {
|
|
169
|
-
isLoading,
|
|
170
|
-
recentPosts
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
async function fetchRecentlyEditedPosts(documentId) {
|
|
174
|
-
const queryParams = {
|
|
175
|
-
posts_per_page: 5,
|
|
176
|
-
post__not_in: documentId
|
|
177
|
-
};
|
|
178
|
-
return await apiFetch2({
|
|
179
|
-
path: addQueryArgs(endpointPath2, queryParams)
|
|
180
|
-
}).then((response) => response).catch(() => []);
|
|
174
|
+
import { __ } from "@wordpress/i18n";
|
|
175
|
+
import { useNavigateToDocument as useNavigateToDocument2 } from "@elementor/editor-documents";
|
|
176
|
+
function CreatePostListItem({ closePopup }) {
|
|
177
|
+
const { create, isLoading } = useCreatePage();
|
|
178
|
+
const navigateToDocument = useNavigateToDocument2();
|
|
179
|
+
return /* @__PURE__ */ React4.createElement(MenuItem2, { dense: true, size: "small", color: "inherit", component: "div", onClick: async () => {
|
|
180
|
+
const { id } = await create();
|
|
181
|
+
closePopup();
|
|
182
|
+
navigateToDocument(id);
|
|
183
|
+
} }, /* @__PURE__ */ React4.createElement(ListItemIcon, null, isLoading ? /* @__PURE__ */ React4.createElement(CircularProgress, null) : /* @__PURE__ */ React4.createElement(PlusIcon, null)), __("Add new page", "elementor"));
|
|
181
184
|
}
|
|
182
185
|
|
|
183
186
|
// src/components/top-bar/recently-edited.tsx
|
|
184
187
|
function RecentlyEdited() {
|
|
185
188
|
const activeDocument = useActiveDocument();
|
|
186
189
|
const hostDocument = useHostDocument();
|
|
187
|
-
const
|
|
188
|
-
const { recentPosts } = useRecentPosts(
|
|
190
|
+
const document2 = activeDocument && activeDocument.type.value !== "kit" ? activeDocument : hostDocument;
|
|
191
|
+
const { recentPosts } = useRecentPosts(document2?.id);
|
|
189
192
|
const popupState = usePopupState({
|
|
190
193
|
variant: "popover",
|
|
191
194
|
popupId: "elementor-v2-top-bar-recently-edited"
|
|
192
195
|
});
|
|
193
|
-
|
|
196
|
+
const documentTitle = useReverseHtmlEntities(document2?.title);
|
|
197
|
+
if (!document2) {
|
|
194
198
|
return null;
|
|
195
199
|
}
|
|
196
|
-
return /* @__PURE__ */
|
|
200
|
+
return /* @__PURE__ */ React5.createElement(Box, { sx: { cursor: "default" } }, /* @__PURE__ */ React5.createElement(
|
|
197
201
|
Button,
|
|
198
202
|
{
|
|
199
203
|
color: "inherit",
|
|
200
204
|
size: "small",
|
|
201
|
-
endIcon: /* @__PURE__ */
|
|
205
|
+
endIcon: /* @__PURE__ */ React5.createElement(ChevronDownIcon, { fontSize: "small" }),
|
|
202
206
|
...bindTrigger(popupState)
|
|
203
207
|
},
|
|
204
|
-
/* @__PURE__ */
|
|
208
|
+
/* @__PURE__ */ React5.createElement(
|
|
205
209
|
Indicator,
|
|
206
210
|
{
|
|
207
|
-
title:
|
|
208
|
-
status:
|
|
211
|
+
title: documentTitle,
|
|
212
|
+
status: document2.status
|
|
209
213
|
}
|
|
210
214
|
)
|
|
211
|
-
), /* @__PURE__ */
|
|
215
|
+
), /* @__PURE__ */ React5.createElement(
|
|
212
216
|
Menu,
|
|
213
217
|
{
|
|
214
218
|
MenuListProps: { component: "div" },
|
|
215
219
|
PaperProps: { sx: { mt: 4, minWidth: 314 } },
|
|
216
220
|
...bindMenu(popupState)
|
|
217
221
|
},
|
|
218
|
-
/* @__PURE__ */
|
|
222
|
+
/* @__PURE__ */ React5.createElement(ListSubheader, { sx: { fontSize: 12, fontStyle: "italic", pl: 4 }, component: "div", id: "nested-list-subheader" }, __2("Recent", "elementor")),
|
|
223
|
+
recentPosts.map((post) => /* @__PURE__ */ React5.createElement(PostListItem, { key: post.id, post, closePopup: popupState.close })),
|
|
224
|
+
recentPosts.length === 0 && /* @__PURE__ */ React5.createElement(Typography2, { variant: "caption", sx: { color: "grey.500", fontStyle: "italic", p: 4 }, component: "div", "aria-label": void 0 }, __2("There are no other pages or templates on this site yet.", "elementor")),
|
|
225
|
+
/* @__PURE__ */ React5.createElement(Divider, null),
|
|
226
|
+
/* @__PURE__ */ React5.createElement(CreatePostListItem, { closePopup: popupState.close })
|
|
219
227
|
));
|
|
220
228
|
}
|
|
221
229
|
|
|
@@ -226,7 +234,7 @@ function init() {
|
|
|
226
234
|
}
|
|
227
235
|
function registerTopBarMenuItems() {
|
|
228
236
|
injectIntoPageIndication({
|
|
229
|
-
|
|
237
|
+
id: "document-recently-edited",
|
|
230
238
|
filler: RecentlyEdited
|
|
231
239
|
});
|
|
232
240
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementor/editor-site-navigation",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "Elementor Team",
|
|
6
6
|
"homepage": "https://elementor.com/",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"dev": "tsup src/index.ts --format esm --clean"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@elementor/editor-app-bar": "^0.
|
|
36
|
-
"@elementor/editor-documents": "^0.
|
|
35
|
+
"@elementor/editor-app-bar": "^0.4.0",
|
|
36
|
+
"@elementor/editor-documents": "^0.4.0",
|
|
37
37
|
"@elementor/icons": "^0.2.1",
|
|
38
38
|
"@elementor/ui": "^1.4.50",
|
|
39
39
|
"@wordpress/api-fetch": "^6.27.0",
|
|
@@ -46,5 +46,5 @@
|
|
|
46
46
|
"elementor": {
|
|
47
47
|
"type": "extension"
|
|
48
48
|
},
|
|
49
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "6efee223232dba6482843cca5a00ebecd19d3890"
|
|
50
50
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { render } from '@testing-library/react';
|
|
3
|
-
import { useHostDocument, useActiveDocument } from '@elementor/editor-documents';
|
|
2
|
+
import { render, waitFor } from '@testing-library/react';
|
|
3
|
+
import { useHostDocument, useActiveDocument, useNavigateToDocument } from '@elementor/editor-documents';
|
|
4
4
|
import RecentlyEdited from '../recently-edited';
|
|
5
5
|
import { createMockDocument } from 'test-utils';
|
|
6
6
|
import useRecentPosts, { Post } from '../../../hooks/use-recent-posts';
|
|
@@ -9,6 +9,7 @@ import useCreatePage from '../../../hooks/use-create-page';
|
|
|
9
9
|
jest.mock( '@elementor/editor-documents', () => ( {
|
|
10
10
|
useActiveDocument: jest.fn(),
|
|
11
11
|
useHostDocument: jest.fn(),
|
|
12
|
+
useNavigateToDocument: jest.fn(),
|
|
12
13
|
} ) );
|
|
13
14
|
|
|
14
15
|
jest.mock( '../../../hooks/use-recent-posts', () => (
|
|
@@ -55,16 +56,18 @@ describe( '@elementor/recently-edited - Top bar add new page', () => {
|
|
|
55
56
|
expect( label ).toBeInTheDocument();
|
|
56
57
|
} );
|
|
57
58
|
|
|
58
|
-
it( 'should trigger create page hook on click', () => {
|
|
59
|
+
it( 'should trigger create page hook on click', async () => {
|
|
59
60
|
// Arrange.
|
|
60
61
|
mockActiveDocument();
|
|
61
62
|
|
|
62
63
|
const isLoading = false;
|
|
63
64
|
const recentPosts: Post[] = [];
|
|
64
|
-
const create = jest.fn();
|
|
65
|
+
const create = jest.fn().mockReturnValue( Promise.resolve( { id: 123 } ) );
|
|
66
|
+
const navigateToDocument = jest.fn();
|
|
65
67
|
|
|
66
68
|
jest.mocked( useRecentPosts ).mockReturnValue( { isLoading, recentPosts } );
|
|
67
69
|
jest.mocked( useCreatePage ).mockReturnValue( { isLoading, create } );
|
|
70
|
+
jest.mocked( useNavigateToDocument ).mockReturnValue( navigateToDocument );
|
|
68
71
|
|
|
69
72
|
const { getByText, getAllByRole } = render( <RecentlyEdited /> );
|
|
70
73
|
|
|
@@ -76,7 +79,12 @@ describe( '@elementor/recently-edited - Top bar add new page', () => {
|
|
|
76
79
|
addNewPage.click();
|
|
77
80
|
|
|
78
81
|
// Assert.
|
|
79
|
-
|
|
82
|
+
await waitFor( () => {
|
|
83
|
+
expect( create ).toHaveBeenCalledTimes( 1 );
|
|
84
|
+
|
|
85
|
+
expect( navigateToDocument ).toHaveBeenCalledTimes( 1 );
|
|
86
|
+
expect( navigateToDocument ).toHaveBeenCalledWith( 123 );
|
|
87
|
+
} );
|
|
80
88
|
} );
|
|
81
89
|
} );
|
|
82
90
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { render } from '@testing-library/react';
|
|
3
|
-
import { useHostDocument, useActiveDocument } from '@elementor/editor-documents';
|
|
3
|
+
import { useHostDocument, useActiveDocument, useNavigateToDocument } from '@elementor/editor-documents';
|
|
4
4
|
import RecentlyEdited from '../recently-edited';
|
|
5
5
|
import { createMockDocument } from 'test-utils';
|
|
6
6
|
import useRecentPosts, { Post } from '../../../hooks/use-recent-posts';
|
|
@@ -8,6 +8,7 @@ import useRecentPosts, { Post } from '../../../hooks/use-recent-posts';
|
|
|
8
8
|
jest.mock( '@elementor/editor-documents', () => ( {
|
|
9
9
|
useActiveDocument: jest.fn(),
|
|
10
10
|
useHostDocument: jest.fn(),
|
|
11
|
+
useNavigateToDocument: jest.fn(),
|
|
11
12
|
} ) );
|
|
12
13
|
|
|
13
14
|
jest.mock( '../../../hooks/use-recent-posts', () => (
|
|
@@ -175,4 +176,93 @@ describe( '@elementor/recently-edited - Top bar Recently Edited', () => {
|
|
|
175
176
|
|
|
176
177
|
expect( getByText( 'Test post' ) ).toBeInTheDocument();
|
|
177
178
|
} );
|
|
179
|
+
|
|
180
|
+
it( 'should render titles with HTML entities', () => {
|
|
181
|
+
// Arrange.
|
|
182
|
+
jest.mocked( useActiveDocument ).mockImplementation( () =>
|
|
183
|
+
createMockDocument( {
|
|
184
|
+
id: 1,
|
|
185
|
+
title: 'Header title with special char ¥',
|
|
186
|
+
type: {
|
|
187
|
+
value: 'header',
|
|
188
|
+
label: 'Header',
|
|
189
|
+
},
|
|
190
|
+
} )
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
const isLoading = false;
|
|
194
|
+
const recentPosts: Post[] = [
|
|
195
|
+
{
|
|
196
|
+
id: 1,
|
|
197
|
+
title: 'Post title with <h1>HTML</h1>',
|
|
198
|
+
edit_url: 'some_url',
|
|
199
|
+
type: {
|
|
200
|
+
post_type: 'post',
|
|
201
|
+
doc_type: 'wp-post',
|
|
202
|
+
label: 'Post',
|
|
203
|
+
},
|
|
204
|
+
date_modified: 123,
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
id: 2,
|
|
208
|
+
title: 'Post title with <HTML entities>',
|
|
209
|
+
edit_url: 'some_url_2',
|
|
210
|
+
type: {
|
|
211
|
+
post_type: 'post',
|
|
212
|
+
doc_type: 'wp-post',
|
|
213
|
+
label: 'Post 2',
|
|
214
|
+
},
|
|
215
|
+
date_modified: 1234,
|
|
216
|
+
},
|
|
217
|
+
];
|
|
218
|
+
|
|
219
|
+
jest.mocked( useRecentPosts ).mockReturnValue( { isLoading, recentPosts } );
|
|
220
|
+
|
|
221
|
+
// Act.
|
|
222
|
+
const { getByText, getByRole } = render( <RecentlyEdited /> );
|
|
223
|
+
|
|
224
|
+
// Assert - the document title should be rendered with the HTML entity.
|
|
225
|
+
expect( getByText( 'Header title with special char ¥' ) ).toBeInTheDocument();
|
|
226
|
+
|
|
227
|
+
// Open the posts list.
|
|
228
|
+
getByRole( 'button' ).click();
|
|
229
|
+
|
|
230
|
+
// Assert - the post title should be rendered with the HTML entity.
|
|
231
|
+
expect( getByText( 'Post title with <h1>HTML</h1>' ) ).toBeInTheDocument();
|
|
232
|
+
expect( getByText( 'Post title with <HTML entities>' ) ).toBeInTheDocument();
|
|
233
|
+
} );
|
|
234
|
+
|
|
235
|
+
it( 'should navigate to document on click', () => {
|
|
236
|
+
// Arrange.
|
|
237
|
+
const navigateToDocument = jest.fn();
|
|
238
|
+
|
|
239
|
+
jest.mocked( useNavigateToDocument ).mockReturnValue( navigateToDocument );
|
|
240
|
+
|
|
241
|
+
jest.mocked( useRecentPosts ).mockReturnValue( {
|
|
242
|
+
isLoading: false,
|
|
243
|
+
recentPosts: [ {
|
|
244
|
+
id: 123,
|
|
245
|
+
title: 'Test post',
|
|
246
|
+
edit_url: 'some_url',
|
|
247
|
+
type: {
|
|
248
|
+
post_type: 'post',
|
|
249
|
+
doc_type: 'wp-post',
|
|
250
|
+
label: 'Post',
|
|
251
|
+
},
|
|
252
|
+
date_modified: 123,
|
|
253
|
+
} ],
|
|
254
|
+
} );
|
|
255
|
+
|
|
256
|
+
const { getByText, getByRole } = render( <RecentlyEdited /> );
|
|
257
|
+
|
|
258
|
+
// Open the posts list.
|
|
259
|
+
getByRole( 'button' ).click();
|
|
260
|
+
|
|
261
|
+
// Act.
|
|
262
|
+
getByText( 'Test post' ).click();
|
|
263
|
+
|
|
264
|
+
// Assert.
|
|
265
|
+
expect( navigateToDocument ).toHaveBeenCalledTimes( 1 );
|
|
266
|
+
expect( navigateToDocument ).toHaveBeenCalledWith( 123 );
|
|
267
|
+
} );
|
|
178
268
|
} );
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { CircularProgress, ListItemIcon, MenuItem } from '@elementor/ui';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import useCreatePage from '../../hooks/use-create-page';
|
|
4
|
+
import { PlusIcon } from '@elementor/icons';
|
|
5
|
+
import { __ } from '@wordpress/i18n';
|
|
6
|
+
import { useNavigateToDocument } from '@elementor/editor-documents';
|
|
7
|
+
|
|
8
|
+
export function CreatePostListItem( { closePopup }: { closePopup: () => void } ) {
|
|
9
|
+
const { create, isLoading } = useCreatePage();
|
|
10
|
+
const navigateToDocument = useNavigateToDocument();
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<MenuItem dense size="small" color="inherit" component="div" onClick={ async () => {
|
|
14
|
+
const { id } = await create();
|
|
15
|
+
|
|
16
|
+
closePopup();
|
|
17
|
+
navigateToDocument( id );
|
|
18
|
+
} }>
|
|
19
|
+
<ListItemIcon>
|
|
20
|
+
{ isLoading ? <CircularProgress /> : <PlusIcon /> }
|
|
21
|
+
</ListItemIcon>
|
|
22
|
+
|
|
23
|
+
{ __( 'Add new page', 'elementor' ) }
|
|
24
|
+
</MenuItem>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import DocTypeChip from './chip-doc-type';
|
|
2
|
+
import { MenuItem, MenuItemProps } from '@elementor/ui';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { Post } from '../../hooks/use-recent-posts';
|
|
5
|
+
import { useNavigateToDocument } from '@elementor/editor-documents';
|
|
6
|
+
import { useReverseHtmlEntities } from '../../hooks/use-reverse-html-entities';
|
|
7
|
+
|
|
8
|
+
type Props = MenuItemProps & {
|
|
9
|
+
post: Post;
|
|
10
|
+
closePopup: () => void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function PostListItem( { post, closePopup }: Props ) {
|
|
14
|
+
const navigateToDocument = useNavigateToDocument();
|
|
15
|
+
const postTitle = useReverseHtmlEntities( post.title );
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<MenuItem dense sx={ { width: '100%' } } onClick={ () => {
|
|
19
|
+
closePopup();
|
|
20
|
+
navigateToDocument( post.id );
|
|
21
|
+
} }>
|
|
22
|
+
{ postTitle }
|
|
23
|
+
<DocTypeChip postType={ post.type.post_type } docType={ post.type.doc_type } label={ post.type.label } />
|
|
24
|
+
</MenuItem>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
@@ -6,12 +6,18 @@ import {
|
|
|
6
6
|
Menu,
|
|
7
7
|
Button,
|
|
8
8
|
Box,
|
|
9
|
+
ListSubheader,
|
|
10
|
+
Typography,
|
|
11
|
+
Divider,
|
|
9
12
|
} from '@elementor/ui';
|
|
10
13
|
import { ChevronDownIcon } from '@elementor/icons';
|
|
11
14
|
import { useActiveDocument, useHostDocument } from '@elementor/editor-documents';
|
|
12
15
|
import Indicator from './indicator';
|
|
13
|
-
import PostsList from './posts-list';
|
|
14
16
|
import useRecentPosts from '../../hooks/use-recent-posts';
|
|
17
|
+
import { __ } from '@wordpress/i18n';
|
|
18
|
+
import { PostListItem } from './post-list-item';
|
|
19
|
+
import { CreatePostListItem } from './create-post-list-item';
|
|
20
|
+
import { useReverseHtmlEntities } from '../../hooks/use-reverse-html-entities';
|
|
15
21
|
|
|
16
22
|
export default function RecentlyEdited() {
|
|
17
23
|
const activeDocument = useActiveDocument();
|
|
@@ -27,6 +33,8 @@ export default function RecentlyEdited() {
|
|
|
27
33
|
popupId: 'elementor-v2-top-bar-recently-edited',
|
|
28
34
|
} );
|
|
29
35
|
|
|
36
|
+
const documentTitle = useReverseHtmlEntities( document?.title );
|
|
37
|
+
|
|
30
38
|
if ( ! document ) {
|
|
31
39
|
return null;
|
|
32
40
|
}
|
|
@@ -40,7 +48,7 @@ export default function RecentlyEdited() {
|
|
|
40
48
|
{ ...bindTrigger( popupState ) }
|
|
41
49
|
>
|
|
42
50
|
<Indicator
|
|
43
|
-
title={
|
|
51
|
+
title={ documentTitle }
|
|
44
52
|
status={ document.status }
|
|
45
53
|
/>
|
|
46
54
|
</Button>
|
|
@@ -50,7 +58,23 @@ export default function RecentlyEdited() {
|
|
|
50
58
|
PaperProps={ { sx: { mt: 4, minWidth: 314 } } }
|
|
51
59
|
{ ...bindMenu( popupState ) }
|
|
52
60
|
>
|
|
53
|
-
<
|
|
61
|
+
<ListSubheader sx={ { fontSize: 12, fontStyle: 'italic', pl: 4 } } component="div" id="nested-list-subheader">
|
|
62
|
+
{ __( 'Recent', 'elementor' ) }
|
|
63
|
+
</ListSubheader>
|
|
64
|
+
|
|
65
|
+
{ recentPosts.map( ( post ) => (
|
|
66
|
+
<PostListItem key={ post.id } post={ post } closePopup={ popupState.close } />
|
|
67
|
+
) ) }
|
|
68
|
+
|
|
69
|
+
{ recentPosts.length === 0 && (
|
|
70
|
+
<Typography variant="caption" sx={ { color: 'grey.500', fontStyle: 'italic', p: 4 } } component="div" aria-label={ undefined }>
|
|
71
|
+
{ __( 'There are no other pages or templates on this site yet.', 'elementor' ) }
|
|
72
|
+
</Typography>
|
|
73
|
+
) }
|
|
74
|
+
|
|
75
|
+
<Divider />
|
|
76
|
+
|
|
77
|
+
<CreatePostListItem closePopup={ popupState.close } />
|
|
54
78
|
</Menu>
|
|
55
79
|
</Box>
|
|
56
80
|
);
|
|
@@ -17,8 +17,7 @@ describe( '@elementor/recently-edited/use-page', () => {
|
|
|
17
17
|
|
|
18
18
|
it( 'should run useCreatePage hook', async () => {
|
|
19
19
|
// Arrange.
|
|
20
|
-
const
|
|
21
|
-
const { result } = renderHook( () => useCreatePage( { onCreated } ) );
|
|
20
|
+
const { result } = renderHook( useCreatePage );
|
|
22
21
|
const newPost = {
|
|
23
22
|
id: 1,
|
|
24
23
|
edit_url: 'editurl.com',
|
|
@@ -6,28 +6,18 @@ export interface NewPost {
|
|
|
6
6
|
edit_url: string,
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
export type Args = {
|
|
10
|
-
onCreated: ( url : string ) => void;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
9
|
export const endpointPath = '/elementor/v1/site-navigation/add-new-post';
|
|
14
10
|
|
|
15
|
-
export default function useCreatePage(
|
|
11
|
+
export default function useCreatePage() {
|
|
16
12
|
const [ isLoading, setIsLoading ] = useState( false );
|
|
17
13
|
|
|
18
14
|
return {
|
|
19
15
|
create: () => {
|
|
20
16
|
setIsLoading( true );
|
|
21
17
|
|
|
22
|
-
addNewPage()
|
|
18
|
+
return addNewPage()
|
|
23
19
|
.then( ( newPost ) => newPost as NewPost )
|
|
24
|
-
.
|
|
25
|
-
setIsLoading( false );
|
|
26
|
-
onCreated( newPost.edit_url );
|
|
27
|
-
} )
|
|
28
|
-
.catch( () => {
|
|
29
|
-
setIsLoading( false );
|
|
30
|
-
} );
|
|
20
|
+
.finally( () => setIsLoading( false ) );
|
|
31
21
|
},
|
|
32
22
|
isLoading,
|
|
33
23
|
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
|
|
3
|
+
export function useReverseHtmlEntities( escapedHTML = '' ) {
|
|
4
|
+
return useMemo( () => {
|
|
5
|
+
const textarea = document.createElement( 'textarea' );
|
|
6
|
+
textarea.innerHTML = escapedHTML;
|
|
7
|
+
|
|
8
|
+
const { value } = textarea;
|
|
9
|
+
|
|
10
|
+
textarea.remove();
|
|
11
|
+
|
|
12
|
+
return value;
|
|
13
|
+
}, [ escapedHTML ] );
|
|
14
|
+
}
|
package/src/init.ts
CHANGED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Divider,
|
|
3
|
-
MenuItem,
|
|
4
|
-
ListItemIcon,
|
|
5
|
-
ListSubheader,
|
|
6
|
-
Typography,
|
|
7
|
-
CircularProgress,
|
|
8
|
-
} from '@elementor/ui';
|
|
9
|
-
|
|
10
|
-
import * as React from 'react';
|
|
11
|
-
import { __ } from '@wordpress/i18n';
|
|
12
|
-
import DocTypeChip, { Props } from './chip-doc-type';
|
|
13
|
-
import { Post } from '../../hooks/use-recent-posts';
|
|
14
|
-
import useCreatePage from '../../hooks/use-create-page';
|
|
15
|
-
import { PlusIcon } from '@elementor/icons';
|
|
16
|
-
|
|
17
|
-
export type RecentPostsProps = {
|
|
18
|
-
recentPosts: Post[];
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export default function PostsList( { recentPosts }: RecentPostsProps ) {
|
|
22
|
-
const { create, isLoading } = useCreatePage( { onCreated } );
|
|
23
|
-
|
|
24
|
-
return (
|
|
25
|
-
<>
|
|
26
|
-
<ListSubheader sx={ { fontSize: 12, fontStyle: 'italic', pl: 4 } } component="div" id="nested-list-subheader">
|
|
27
|
-
{ __( 'Recent', 'elementor' ) }
|
|
28
|
-
</ListSubheader>
|
|
29
|
-
|
|
30
|
-
{ recentPosts.length
|
|
31
|
-
? ( recentPosts.map( ( { title, edit_url: editUrl, type, id } ) => (
|
|
32
|
-
<MenuItem
|
|
33
|
-
dense
|
|
34
|
-
key={ id }
|
|
35
|
-
component="a"
|
|
36
|
-
href={ editUrl }
|
|
37
|
-
>
|
|
38
|
-
{ title }
|
|
39
|
-
<DocTypeChip postType={ type.post_type } docType={ type.doc_type as Props['docType'] } label={ type.label } />
|
|
40
|
-
</MenuItem>
|
|
41
|
-
) ) ) : (
|
|
42
|
-
<Typography variant="caption" sx={ { color: 'grey.500', fontStyle: 'italic', p: 4 } } component="div" aria-label={ undefined }>
|
|
43
|
-
{ __( 'There are no other pages or templates on this site yet.', 'elementor' ) }
|
|
44
|
-
</Typography>
|
|
45
|
-
)
|
|
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>
|
|
61
|
-
</>
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function onCreated( url: string ) {
|
|
66
|
-
window.location.href = url;
|
|
67
|
-
}
|