@social-mail/social-mail-client 1.9.55 → 1.9.57
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/dist/admin/AdminAppIndex.pack.global.css +1 -1
- package/dist/admin/AdminAppIndex.pack.global.css.map +1 -1
- package/dist/admin/AdminAppIndex.pack.js +92 -48
- package/dist/admin/AdminAppIndex.pack.js.map +1 -1
- package/dist/admin/AdminAppIndex.pack.min.js +1 -1
- package/dist/admin/AdminAppIndex.pack.min.js.map +1 -1
- package/dist/common/commands/CommonCommands.d.ts.map +1 -1
- package/dist/common/commands/CommonCommands.js.map +1 -1
- package/dist/common/controls/tree/TreeView.d.ts +1 -0
- package/dist/common/controls/tree/TreeView.d.ts.map +1 -1
- package/dist/common/controls/tree/TreeView.global.css +1 -1
- package/dist/common/controls/tree/TreeView.global.css.map +1 -1
- package/dist/common/controls/tree/TreeView.js +7 -1
- package/dist/common/controls/tree/TreeView.js.map +1 -1
- package/dist/common/pages/files/service/CloudFileService.d.ts +4 -0
- package/dist/common/pages/files/service/CloudFileService.d.ts.map +1 -1
- package/dist/common/pages/files/service/CloudFileService.js +41 -3
- package/dist/common/pages/files/service/CloudFileService.js.map +1 -1
- package/dist/site-editor-app/SiteEditorApp.pack.global.css +1 -1
- package/dist/site-editor-app/SiteEditorApp.pack.global.css.map +1 -1
- package/dist/site-editor-app/SiteEditorApp.pack.js +152 -65
- package/dist/site-editor-app/SiteEditorApp.pack.js.map +1 -1
- package/dist/site-editor-app/SiteEditorApp.pack.min.js +1 -1
- package/dist/site-editor-app/SiteEditorApp.pack.min.js.map +1 -1
- package/dist/site-editor-app/commands/SiteEditorCommands.d.ts +1 -0
- package/dist/site-editor-app/commands/SiteEditorCommands.d.ts.map +1 -1
- package/dist/site-editor-app/commands/SiteEditorCommands.js +2 -2
- package/dist/site-editor-app/commands/SiteEditorCommands.js.map +1 -1
- package/dist/site-editor-app/pages/websites/studio/WebSiteStudioPage.d.ts +2 -0
- package/dist/site-editor-app/pages/websites/studio/WebSiteStudioPage.d.ts.map +1 -1
- package/dist/site-editor-app/pages/websites/studio/WebSiteStudioPage.js +58 -15
- package/dist/site-editor-app/pages/websites/studio/WebSiteStudioPage.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/web/AppIndex.pack.global.css +1 -1
- package/dist/web/AppIndex.pack.global.css.map +1 -1
- package/dist/web/AppIndex.pack.js +92 -48
- package/dist/web/AppIndex.pack.js.map +1 -1
- package/dist/web/AppIndex.pack.min.js +1 -1
- package/dist/web/AppIndex.pack.min.js.map +1 -1
- package/package.json +1 -1
- package/src/common/commands/CommonCommands.ts +0 -14
- package/src/common/controls/tree/TreeView.global.css +6 -1
- package/src/common/controls/tree/TreeView.tsx +10 -1
- package/src/common/pages/files/service/CloudFileService.ts +50 -1
- package/src/site-editor-app/commands/SiteEditorCommands.ts +2 -2
- package/src/site-editor-app/pages/websites/studio/WebSiteStudioPage.tsx +60 -33
package/package.json
CHANGED
|
@@ -43,20 +43,6 @@ export default class CommonCommands extends Commands {
|
|
|
43
43
|
openPage: () => import("../pages/websites/detail/WebSiteDetail")
|
|
44
44
|
});
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
// static manageWebSite = Command.create({
|
|
48
|
-
// route: "/studio/manage/{id}",
|
|
49
|
-
// routeOrder: 100,
|
|
50
|
-
// openPage: () => import("../pages/websites/manage/ManageWebSitePage")
|
|
51
|
-
// });
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
// static editWebSite = Command.create({
|
|
55
|
-
// route: "/studio/edit/{id}",
|
|
56
|
-
// routeOrder: 100,
|
|
57
|
-
// openPage: () => import("../pages/websites/studio/WebSiteStudioPage")
|
|
58
|
-
// });
|
|
59
|
-
|
|
60
46
|
static changePassword = Command.create({
|
|
61
47
|
route: "/user/change-password",
|
|
62
48
|
pushPage: () => import("../pages/user/change-password/ChangePasswordPage")
|
|
@@ -10,6 +10,11 @@
|
|
|
10
10
|
align-items: center;
|
|
11
11
|
color: green;
|
|
12
12
|
|
|
13
|
+
& > [data-layout=container] {
|
|
14
|
+
grid-row: 2;
|
|
15
|
+
grid-column: 1 / span 3;
|
|
16
|
+
}
|
|
17
|
+
|
|
13
18
|
& > [data-element=action] {
|
|
14
19
|
grid-row: 1;
|
|
15
20
|
grid-column: 3;
|
|
@@ -21,7 +26,7 @@
|
|
|
21
26
|
}
|
|
22
27
|
}
|
|
23
28
|
|
|
24
|
-
&:hover
|
|
29
|
+
&:hover:not(:has([data-layout=tree-view-item]:hover)){
|
|
25
30
|
background-color: var(--hover-color);
|
|
26
31
|
color: var(--hover-text-color);
|
|
27
32
|
& > [data-element=action] {
|
|
@@ -11,6 +11,7 @@ import "./TreeView.global.css";
|
|
|
11
11
|
|
|
12
12
|
interface ITreeViewElement<T> extends HTMLDivElement, IDisposable {
|
|
13
13
|
parentItem: T;
|
|
14
|
+
childrenContainer: HTMLElement;
|
|
14
15
|
dataItem: T;
|
|
15
16
|
}
|
|
16
17
|
|
|
@@ -231,6 +232,7 @@ export default class TreeView<T extends object = any> extends AtomControl {
|
|
|
231
232
|
}
|
|
232
233
|
|
|
233
234
|
protected createElement(item: T, parentItem?: T, insertIndex = -1) {
|
|
235
|
+
|
|
234
236
|
const element = document.createElement("div") as ITreeViewElement<T>;
|
|
235
237
|
element.setAttribute("data-layout", "tree-view-item");
|
|
236
238
|
|
|
@@ -243,6 +245,10 @@ export default class TreeView<T extends object = any> extends AtomControl {
|
|
|
243
245
|
throw new Error("Children array must not be empty");
|
|
244
246
|
}
|
|
245
247
|
|
|
248
|
+
const childContainer = document.createElement("div");
|
|
249
|
+
childContainer.setAttribute("data-layout", "container");
|
|
250
|
+
element.childrenContainer = childContainer;
|
|
251
|
+
|
|
246
252
|
const watcher = children.watch((target, event, index, child) => {
|
|
247
253
|
if (event === "add") {
|
|
248
254
|
// set parent in the
|
|
@@ -312,6 +318,7 @@ export default class TreeView<T extends object = any> extends AtomControl {
|
|
|
312
318
|
const header = document.createElement("div");
|
|
313
319
|
header.setAttribute("data-element", "header");
|
|
314
320
|
element.appendChild(header);
|
|
321
|
+
element.appendChild(childContainer);
|
|
315
322
|
|
|
316
323
|
const parentElement = this.map.get(parentItem);
|
|
317
324
|
let last = parentElement;
|
|
@@ -323,8 +330,10 @@ export default class TreeView<T extends object = any> extends AtomControl {
|
|
|
323
330
|
}
|
|
324
331
|
if (insertIndex >= 1) {
|
|
325
332
|
last = this.map.get(siblings[insertIndex - 1]);
|
|
333
|
+
last.insertAdjacentElement("afterend", element);
|
|
334
|
+
} else {
|
|
335
|
+
parentElement.childrenContainer.insertAdjacentElement("beforeend", element);
|
|
326
336
|
}
|
|
327
|
-
last.insertAdjacentElement("afterend", element);
|
|
328
337
|
const pad = Number(parentElement.getAttribute("data-pad") ?? "0") + 10;
|
|
329
338
|
element.setAttribute("data-pad", `${pad}`);
|
|
330
339
|
element.style.paddingLeft = `${pad}px`;
|
|
@@ -8,6 +8,8 @@ import { Sql } from "../../../../common/Sql";
|
|
|
8
8
|
import SocialMailApp from "../../../../common/SocialMailApp";
|
|
9
9
|
import LocalFileService from "../../../../services/files/LocalFileService";
|
|
10
10
|
import Query from "@web-atoms/entity/dist/services/Query";
|
|
11
|
+
import { CacheTTL } from "../../../cache/CacheTTL";
|
|
12
|
+
import CacheVersions from "../../../cache/CacheVersions";
|
|
11
13
|
|
|
12
14
|
const hideActivityIndicator = true;
|
|
13
15
|
|
|
@@ -132,6 +134,49 @@ export default class CloudFileService {
|
|
|
132
134
|
return folder;
|
|
133
135
|
}
|
|
134
136
|
|
|
137
|
+
async webRoot({ id, cancelToken = null}) {
|
|
138
|
+
|
|
139
|
+
const root = await this.entityService.query(AppFile)
|
|
140
|
+
.where({ id }, (p) => (x) => x.appFileID === p.id)
|
|
141
|
+
.firstOrDefault( {
|
|
142
|
+
cacheSeconds: CacheTTL.seconds.oneHour,
|
|
143
|
+
cacheVersion: CacheVersions.site,
|
|
144
|
+
cancelToken
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
const path = root.path + "%";
|
|
148
|
+
|
|
149
|
+
const files = await this.entityService.query(AppFile)
|
|
150
|
+
.where({ path }, (p) => (x) => Sql.text.like(x.path, p.path)
|
|
151
|
+
&& x.isDeleted === false
|
|
152
|
+
&& (x.contentType === "text/html" || x.isFolder === true)
|
|
153
|
+
)
|
|
154
|
+
.include((x) => x.creator)
|
|
155
|
+
.include((x) => x.children)
|
|
156
|
+
.toArray({ cancelToken });
|
|
157
|
+
|
|
158
|
+
root.children = [];
|
|
159
|
+
for (const file of files) {
|
|
160
|
+
if (file.parentID === id) {
|
|
161
|
+
root.children.push(file);
|
|
162
|
+
file.parent = root;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
root.children?.sort((a, b) =>
|
|
167
|
+
a.isFolder && b.isFolder
|
|
168
|
+
? a.name.localeCompare(b.name)
|
|
169
|
+
: (a.isFolder
|
|
170
|
+
? Number.MIN_SAFE_INTEGER
|
|
171
|
+
: (b.isFolder
|
|
172
|
+
? Number.MAX_SAFE_INTEGER
|
|
173
|
+
: a.name.localeCompare(b.name)
|
|
174
|
+
)
|
|
175
|
+
)
|
|
176
|
+
);
|
|
177
|
+
return root;
|
|
178
|
+
}
|
|
179
|
+
|
|
135
180
|
async root({ id, templates = false, cancelToken = null}) {
|
|
136
181
|
|
|
137
182
|
let root: IAppFile;
|
|
@@ -387,7 +432,11 @@ export default class CloudFileService {
|
|
|
387
432
|
}
|
|
388
433
|
|
|
389
434
|
getFilePath(root: IAppFile, selectedFile: IAppFile) {
|
|
390
|
-
const
|
|
435
|
+
const all = selectedFile.path.split("/") as any[];
|
|
436
|
+
while(all[0] !== root.appFileID) {
|
|
437
|
+
all.splice(0, 1);
|
|
438
|
+
}
|
|
439
|
+
const segments = all.slice(1);
|
|
391
440
|
let path = "";
|
|
392
441
|
for (const iterator of segments) {
|
|
393
442
|
if (selectedFile.appFileID === iterator) {
|
|
@@ -14,8 +14,8 @@ export default class SiteEditorCommands extends CommonCommands {
|
|
|
14
14
|
});
|
|
15
15
|
|
|
16
16
|
static editWebSite = Command.create({
|
|
17
|
-
route: "/social-mail/studio/edit/{id}",
|
|
18
|
-
routeOrder:
|
|
17
|
+
route: "/social-mail/studio/edit/{id}/{*page}",
|
|
18
|
+
routeOrder: 1000,
|
|
19
19
|
openPage: () => import("../pages/websites/studio/WebSiteStudioPage")
|
|
20
20
|
});
|
|
21
21
|
|
|
@@ -37,10 +37,12 @@ import StudioToolBar from "./tool-bar/StudioToolBar";
|
|
|
37
37
|
import BasicShapes from "../../../../site-editor/tools/basic/BasicShapes";
|
|
38
38
|
import StudioLayers from "./layers/StudioLayers";
|
|
39
39
|
import Designs from "../../../../site-editor/tools/designs/Designs";
|
|
40
|
+
import SiteEditorCommands from "../../../commands/SiteEditorCommands";
|
|
41
|
+
import Loader from "../../../../common/controls/Loader";
|
|
40
42
|
|
|
41
43
|
export default class WebSiteStudioPage extends ContentPage {
|
|
42
44
|
|
|
43
|
-
public parameters: { id: number; templates?: boolean; };
|
|
45
|
+
public parameters: { id: number; templates?: boolean; page?: string; };
|
|
44
46
|
|
|
45
47
|
public selectedFile: IAppFile;
|
|
46
48
|
|
|
@@ -72,8 +74,13 @@ export default class WebSiteStudioPage extends ContentPage {
|
|
|
72
74
|
private htmlEditor: HtmlPageEditor;
|
|
73
75
|
|
|
74
76
|
async init() {
|
|
77
|
+
|
|
78
|
+
this.renderer = <div>
|
|
79
|
+
<Loader/>
|
|
80
|
+
</div>;
|
|
81
|
+
|
|
75
82
|
this.search = "";
|
|
76
|
-
this.root = await this.cloudFileService.
|
|
83
|
+
this.root = await this.cloudFileService.webRoot(this.parameters);
|
|
77
84
|
|
|
78
85
|
// find parent...
|
|
79
86
|
this.element.dispatchEvent(new CustomEvent("iconClick", { bubbles: true}));
|
|
@@ -97,8 +104,29 @@ export default class WebSiteStudioPage extends ContentPage {
|
|
|
97
104
|
return;
|
|
98
105
|
}
|
|
99
106
|
|
|
100
|
-
|
|
101
|
-
this.
|
|
107
|
+
|
|
108
|
+
if (this.parameters?.page) {
|
|
109
|
+
// find page...
|
|
110
|
+
|
|
111
|
+
let { page } = this.parameters;
|
|
112
|
+
while(page.startsWith("/")) {
|
|
113
|
+
page = page.substring(1);
|
|
114
|
+
}
|
|
115
|
+
let segments = page.split("/");
|
|
116
|
+
const finalPage = segments.pop();
|
|
117
|
+
let root = this.root;
|
|
118
|
+
while(segments.length) {
|
|
119
|
+
const [first, ... all] = segments;
|
|
120
|
+
segments = all;
|
|
121
|
+
root = root.children.find((x) => x.name === first);
|
|
122
|
+
}
|
|
123
|
+
const finalFile = root.children.find((x) => x.name === finalPage);
|
|
124
|
+
this.selectedFile = finalFile;
|
|
125
|
+
|
|
126
|
+
} else {
|
|
127
|
+
const indexHtml = this.root.children.find((x) => x.name === "index.html");
|
|
128
|
+
this.selectedFile = indexHtml;
|
|
129
|
+
}
|
|
102
130
|
|
|
103
131
|
const domain = this.webSite.channelDomains?.[0]?.domain?.domain;
|
|
104
132
|
const infoEmail = domain ? `info@${domain.name}` : void 0;
|
|
@@ -106,6 +134,8 @@ export default class WebSiteStudioPage extends ContentPage {
|
|
|
106
134
|
|
|
107
135
|
// const baseUrl = apiPath(`/api/site/draft/${this.root.appFileID}/`);
|
|
108
136
|
|
|
137
|
+
const htmlFile = await this.downloadHtml(this.selectedFile, this.cancelToken);
|
|
138
|
+
|
|
109
139
|
this.titleRenderer = () => <div data-layout="row">
|
|
110
140
|
|
|
111
141
|
<div text={this.root.name}/>
|
|
@@ -183,8 +213,9 @@ export default class WebSiteStudioPage extends ContentPage {
|
|
|
183
213
|
root={this.root}
|
|
184
214
|
class="folder-tree"
|
|
185
215
|
accept="text/html"
|
|
216
|
+
event-select-item={(c) => this.changeFile()}
|
|
186
217
|
presenter={Bind.presenter((c) => this.folderTree = c)}
|
|
187
|
-
selectedItem={
|
|
218
|
+
selectedItem={this.selectedFile}
|
|
188
219
|
menuActions={(x: IAppFile) => !x.isFolder
|
|
189
220
|
? ( /\.(htm|html)$/i.test(x.name)
|
|
190
221
|
? [
|
|
@@ -235,14 +266,12 @@ export default class WebSiteStudioPage extends ContentPage {
|
|
|
235
266
|
/>
|
|
236
267
|
<WebSitePageEditor
|
|
237
268
|
class="file-list"
|
|
238
|
-
selectedFile={
|
|
239
|
-
baseUrl={
|
|
269
|
+
selectedFile={this.selectedFile}
|
|
270
|
+
baseUrl={apiPath(`${this.root.url}${this.cloudFileService.getFilePath(this.root, this.selectedFile)}`)}
|
|
240
271
|
folder={this.root}
|
|
241
272
|
presenter={Bind.presenter((c) => this.htmlEditor = c)}
|
|
242
273
|
event-html-page-changed={(ce: CustomEvent<string>) => this.modified = true}
|
|
243
|
-
htmlPage={
|
|
244
|
-
? this.downloadHtml(this.selectedFile, cancelToken)
|
|
245
|
-
: void 0)}
|
|
274
|
+
htmlPage={htmlFile}
|
|
246
275
|
/>
|
|
247
276
|
</div>;
|
|
248
277
|
|
|
@@ -253,6 +282,11 @@ export default class WebSiteStudioPage extends ContentPage {
|
|
|
253
282
|
</div>;
|
|
254
283
|
}
|
|
255
284
|
|
|
285
|
+
changeFile(file = this.folderTree.selectedItem as IAppFile) {
|
|
286
|
+
const folder = this.cloudFileService.getFilePath(this.root, file) ?? "";
|
|
287
|
+
SiteEditorCommands.editWebSite.dispatch({ id: this.parameters.id, page: folder + file.name });
|
|
288
|
+
}
|
|
289
|
+
|
|
256
290
|
@Action({ onEvent: "keydown"})
|
|
257
291
|
onKeyDown(d, e: KeyboardEvent) {
|
|
258
292
|
if(e.ctrlKey || e.metaKey) {
|
|
@@ -271,28 +305,6 @@ export default class WebSiteStudioPage extends ContentPage {
|
|
|
271
305
|
.asText(true);
|
|
272
306
|
this.pageContent = text;
|
|
273
307
|
return text;
|
|
274
|
-
// const parser = new DOMParser();
|
|
275
|
-
// const doc = parser.parseFromString(text, "text/html");
|
|
276
|
-
// const injects = Array.from(doc.documentElement.querySelectorAll("inject")) as HTMLElement[];
|
|
277
|
-
// for (const e of injects) {
|
|
278
|
-
// let src = e.getAttribute("src");
|
|
279
|
-
// if(src.startsWith("/")) {
|
|
280
|
-
// src = src.substring(1);
|
|
281
|
-
// } else {
|
|
282
|
-
// // will do it later
|
|
283
|
-
// }
|
|
284
|
-
// const injectedFile = await this.cloudFileService.children(this.root.appFileID, src)
|
|
285
|
-
// .firstOrDefault();
|
|
286
|
-
// text = await FetchBuilder.get(injectedFile.downloadUrl).asText();
|
|
287
|
-
// const dom = parser.parseFromString(text, "text/html");
|
|
288
|
-
// const children = Array.from(dom.body.children);
|
|
289
|
-
// e.innerHTML = "";
|
|
290
|
-
// for (const iterator of children) {
|
|
291
|
-
// iterator.setAttribute("contentEditable", "false");
|
|
292
|
-
// e.appendChild(iterator);
|
|
293
|
-
// }
|
|
294
|
-
// }
|
|
295
|
-
// return doc.documentElement.outerHTML;
|
|
296
308
|
}
|
|
297
309
|
|
|
298
310
|
async createIndexHtml() {
|
|
@@ -371,6 +383,21 @@ export default class WebSiteStudioPage extends ContentPage {
|
|
|
371
383
|
async duplicateHtml(file: IAppFile) {
|
|
372
384
|
let { name } = file;
|
|
373
385
|
name = name.replace(/(\.[^\.]+)$/, (ext) => " Copy" + ext);
|
|
386
|
+
|
|
387
|
+
name = name.replace(/\.html$/, "");
|
|
388
|
+
|
|
389
|
+
name = prompt("Name of the file", name);
|
|
390
|
+
if (!name) {
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
name = name + ".html";
|
|
395
|
+
|
|
396
|
+
// check if name already exists...
|
|
397
|
+
if(this.root.children.find((f) => f.name === name)) {
|
|
398
|
+
throw new Error("File with same name already exists");
|
|
399
|
+
}
|
|
400
|
+
|
|
374
401
|
file = await this.cloudFileService.save({ ... file,
|
|
375
402
|
appFileID: void 0,
|
|
376
403
|
children: void 0,
|
|
@@ -378,7 +405,7 @@ export default class WebSiteStudioPage extends ContentPage {
|
|
|
378
405
|
name
|
|
379
406
|
});
|
|
380
407
|
this.root.children.add(file);
|
|
381
|
-
this.
|
|
408
|
+
this.changeFile(file);
|
|
382
409
|
}
|
|
383
410
|
|
|
384
411
|
@Action({ onEvent: "file-history"})
|