@social-mail/social-mail-client 1.0.21 → 1.0.23
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.js +11 -0
- 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/controls/html/InlineHtmlEditorWithToolbar.js +85 -7
- package/dist/common/controls/html/InlineHtmlEditorWithToolbar.js.map +1 -1
- package/dist/services/files/LocalFileService.js +11 -0
- package/dist/services/files/LocalFileService.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/web/AppIndex.pack.js +451 -394
- package/dist/web/AppIndex.pack.js.map +1 -1
- package/dist/web/AppIndex.pack.min.js +46 -34
- package/dist/web/AppIndex.pack.min.js.map +1 -1
- package/dist/web/page/mails/ComposeMailPage.js +1 -1
- package/dist/web/page/mails/ComposeMailPage.js.map +1 -1
- package/dist/web/page/mails/MailsPage.js +1 -1
- package/dist/web/page/mails/MailsPage.js.map +1 -1
- package/node_modules/@web-atoms/web-controls/dist/html-editor/InlineHtmlEditor.d.ts +1 -1
- package/node_modules/@web-atoms/web-controls/dist/html-editor/InlineHtmlEditor.d.ts.map +1 -1
- package/node_modules/@web-atoms/web-controls/dist/html-editor/InlineHtmlEditor.js +29 -2
- package/node_modules/@web-atoms/web-controls/dist/html-editor/InlineHtmlEditor.js.map +1 -1
- package/node_modules/@web-atoms/web-controls/dist/tsconfig.tsbuildinfo +1 -1
- package/node_modules/@web-atoms/web-controls/package.json +1 -1
- package/node_modules/@web-atoms/web-controls/src/html-editor/InlineHtmlEditor.tsx +37 -2
- package/package.json +2 -2
- package/src/common/controls/html/InlineHtmlEditorWithToolbar.tsx +78 -3
- package/src/services/files/LocalFileService.tsx +5 -0
- package/src/web/page/mails/ComposeMailPage.tsx +1 -1
- package/src/web/page/mails/MailsPage.tsx +1 -1
|
@@ -11,6 +11,18 @@ import styled from "@web-atoms/core/dist/style/styled";
|
|
|
11
11
|
|
|
12
12
|
styled.css `
|
|
13
13
|
|
|
14
|
+
& > [data-element=editor] {
|
|
15
|
+
|
|
16
|
+
padding: var(--spacing, 5px);
|
|
17
|
+
border: solid 1px lightgray;
|
|
18
|
+
border-radius: var(--spacing, 5px);
|
|
19
|
+
margin: var(--spacing, 5px);
|
|
20
|
+
|
|
21
|
+
& > * {
|
|
22
|
+
outline: none;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
14
26
|
& > [data-element=toolbar] {
|
|
15
27
|
flex-direction: column;
|
|
16
28
|
align-items: center;
|
|
@@ -207,13 +219,35 @@ export default class InlineHtmlEditor extends AtomControl {
|
|
|
207
219
|
this.bindEvent(this.editor, "blur", () => this.saveSelection(), void 0, true);
|
|
208
220
|
this.bindEvent(this.editor, "input", (e: InputEvent) => this.onContentInput(e));
|
|
209
221
|
this.bindEvent(this.editor, "keydown", (e: KeyboardEvent) => this.updateQueryCommand());
|
|
210
|
-
this.bindEvent(this.editor, "click", (e:
|
|
222
|
+
this.bindEvent(this.editor, "click", (e: MouseEvent) => this.updateQueryCommand(e));
|
|
211
223
|
this.bindEvent(this.editor, "paste", (e: ClipboardEvent) => this.onPasteEvent(e));
|
|
212
224
|
this.bindEvent(this.editor, "cut", () => this.onContentInput());
|
|
213
225
|
this.bindEvent(this.editor, "drop", (e: DragEvent) => this.onDrop(e));
|
|
214
226
|
}
|
|
215
227
|
|
|
216
|
-
protected updateQueryCommand() {
|
|
228
|
+
protected updateQueryCommand(e?: Event) {
|
|
229
|
+
if (e?.type === "click") {
|
|
230
|
+
if (!this.editor.textContent) {
|
|
231
|
+
let first = this.editor.firstElementChild;
|
|
232
|
+
if(!first) {
|
|
233
|
+
first = document.createElement("div");
|
|
234
|
+
first.innerHTML = "<p><br/></p>";
|
|
235
|
+
this.editor.appendChild(first);
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
if (!first.lastChild) {
|
|
239
|
+
first.innerHTML = "<p></br></b>";
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
// const selection = window.getSelection();
|
|
243
|
+
// selection.removeAllRanges();
|
|
244
|
+
// const range = document.createRange();
|
|
245
|
+
// // find editable...
|
|
246
|
+
// range.setEndAfter(first.lastChild);
|
|
247
|
+
// range.setStartAfter(first.lastChild);
|
|
248
|
+
// selection.addRange(range);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
217
251
|
this.version++;
|
|
218
252
|
}
|
|
219
253
|
|
|
@@ -238,6 +272,7 @@ export default class InlineHtmlEditor extends AtomControl {
|
|
|
238
272
|
protected onPasteEvent(e: ClipboardEvent) {
|
|
239
273
|
// tslint:disable-next-line: no-console
|
|
240
274
|
if (!e.clipboardData.types.find((x) => x === "text/html")) {
|
|
275
|
+
this.onContentInput();
|
|
241
276
|
return;
|
|
242
277
|
}
|
|
243
278
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@social-mail/social-mail-client",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.23",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"@web-atoms/font-awesome": "^1.0.37",
|
|
20
20
|
"@web-atoms/hybrid-clr": "^1.0.21",
|
|
21
21
|
"@web-atoms/module-loader": "^2.1.32",
|
|
22
|
-
"@web-atoms/web-controls": "^2.3.
|
|
22
|
+
"@web-atoms/web-controls": "^2.3.254",
|
|
23
23
|
"reflect-metadata": "^0.1.13"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
@@ -16,12 +16,15 @@ import NumberedList from "@web-atoms/web-controls/dist/html-editor/commands/Numb
|
|
|
16
16
|
import UnorderedList from "@web-atoms/web-controls/dist/html-editor/commands/UnorderedList";
|
|
17
17
|
import IndentLess from "@web-atoms/web-controls/dist/html-editor/commands/IndentLess";
|
|
18
18
|
import IndentMore from "@web-atoms/web-controls/dist/html-editor/commands/IndentMore";
|
|
19
|
-
import AttachImage from "@web-atoms/web-controls/dist/html-editor/commands/AttachImage";
|
|
20
19
|
import AttachFile from "@web-atoms/web-controls/dist/html-editor/commands/AttachFile";
|
|
21
20
|
import AddLink from "@web-atoms/web-controls/dist/html-editor/commands/AddLink";
|
|
22
21
|
import Unlink from "@web-atoms/web-controls/dist/html-editor/commands/Unlink";
|
|
23
22
|
import RemoveFormat from "@web-atoms/web-controls/dist/html-editor/commands/RemoveFormat";
|
|
24
23
|
import Source from "@web-atoms/web-controls/dist/html-editor/commands/Source";
|
|
24
|
+
import UploadEvent from "@web-atoms/web-controls/dist/basic/UploadEvent";
|
|
25
|
+
import LocalFileService, { IUploadedFile, UploadedFiles } from "../../../services/files/LocalFileService";
|
|
26
|
+
import { AtomControl } from "@web-atoms/core/dist/web/controls/AtomControl";
|
|
27
|
+
import InjectProperty from "@web-atoms/core/dist/core/InjectProperty";
|
|
25
28
|
|
|
26
29
|
const link = document.createElement("link");
|
|
27
30
|
link.href = "https://cdn.jsdelivr.net/npm/remixicon@2.5.0/fonts/remixicon.css";
|
|
@@ -33,7 +36,79 @@ link.onload = () => {
|
|
|
33
36
|
};
|
|
34
37
|
document.head.appendChild(link);
|
|
35
38
|
|
|
36
|
-
|
|
39
|
+
const onAttachImage = async (ce: UploadedFiles) => {
|
|
40
|
+
const c = AtomControl.from(ce.target) as any;
|
|
41
|
+
// create data url...
|
|
42
|
+
if(!ce.detail?.files?.length) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const file = ce.detail.files[0];
|
|
46
|
+
|
|
47
|
+
c.executeCommand("insertHTML", void 0, `<div><img data-content="data-url" data-content-id=${file.appFileID} src="${file.url}" style='max-height: 700px;'/></div>`);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
function AttachImage({
|
|
51
|
+
accept = "image/*",
|
|
52
|
+
maxSize = 1024*1024*5,
|
|
53
|
+
authorize = true,
|
|
54
|
+
capture = null as string,
|
|
55
|
+
ariaLabel = "upload"
|
|
56
|
+
}) {
|
|
57
|
+
return <button
|
|
58
|
+
title="Insert Image"
|
|
59
|
+
class="command"
|
|
60
|
+
{ ... UploadEvent.AttachUploadAction({
|
|
61
|
+
accept,
|
|
62
|
+
forceType: true,
|
|
63
|
+
maxSize,
|
|
64
|
+
authorize,
|
|
65
|
+
capture,
|
|
66
|
+
multiple: false,
|
|
67
|
+
ariaLabel,
|
|
68
|
+
"event-files-available": onAttachImage as any
|
|
69
|
+
})}
|
|
70
|
+
>
|
|
71
|
+
<i class="ri-image-add-fill" />
|
|
72
|
+
</button>;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export class MailHtmlEditor extends InlineHtmlEditor {
|
|
76
|
+
|
|
77
|
+
public files: IUploadedFile[];
|
|
78
|
+
|
|
79
|
+
@InjectProperty
|
|
80
|
+
private localFileService: LocalFileService;
|
|
81
|
+
|
|
82
|
+
protected onPasteEvent(e: ClipboardEvent): void {
|
|
83
|
+
if (e.clipboardData.files.length) {
|
|
84
|
+
e.preventDefault();
|
|
85
|
+
e.stopPropagation();
|
|
86
|
+
this.app.runAsync(async() => {
|
|
87
|
+
const files = await this.localFileService.uploadWithProgress(Array.from(e.clipboardData.files));
|
|
88
|
+
for (const file of files) {
|
|
89
|
+
this.executeCommand("insertHTML", void 0, `<div><img data-content="data-url" data-content-id=${file.appFileID} src="${file.url}" style='max-height: 700px;'/></div>`);
|
|
90
|
+
}
|
|
91
|
+
this.element.dispatchEvent(new CustomEvent("filesAvailable", { detail: { files, extra: "none" }, bubbles: true }));
|
|
92
|
+
});
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
super.onPasteEvent(e);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
protected preCreate(): void {
|
|
99
|
+
super.preCreate();
|
|
100
|
+
this.sanitizeHtml = (node) => {
|
|
101
|
+
const images = Array.from(node.querySelectorAll(`img[data-content-id]`));
|
|
102
|
+
for (const image of images) {
|
|
103
|
+
image.setAttribute("src", `cid:${image.getAttribute("data-content-id")}`);
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export default function InlineHtmlEditorWithToolbar(a: Partial<MailHtmlEditor> & { presenter?: any}) {
|
|
37
112
|
const toolbar = () => <div>
|
|
38
113
|
<Toolbar>
|
|
39
114
|
<Bold/>
|
|
@@ -66,7 +141,7 @@ export default function InlineHtmlEditorWithToolbar(a: Partial<InlineHtmlEditor>
|
|
|
66
141
|
<Source/>
|
|
67
142
|
</Toolbar>
|
|
68
143
|
</div>;
|
|
69
|
-
return <
|
|
144
|
+
return <MailHtmlEditor
|
|
70
145
|
{ ... a}
|
|
71
146
|
toolbar={toolbar}
|
|
72
147
|
/>;
|
|
@@ -79,6 +79,11 @@ export default class LocalFileService {
|
|
|
79
79
|
});
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
async uploadWithProgress(files: File[]) {
|
|
83
|
+
const detail = await FileUploadWindow.showModal<{ files: IUploadedFile[]}>({ parameters: { files, extra: "" }});
|
|
84
|
+
return detail.files;
|
|
85
|
+
}
|
|
86
|
+
|
|
82
87
|
async upload(files: File[]) {
|
|
83
88
|
return files.map((file) => {
|
|
84
89
|
const uploadFile: IFileUpload = {
|
|
@@ -43,7 +43,7 @@ export default class ComposeMailPage extends PopupWindowPage {
|
|
|
43
43
|
this.model = this.parameters.model ?? Email.create({
|
|
44
44
|
subject: this.parameters.subject ?? "",
|
|
45
45
|
textBody: "",
|
|
46
|
-
htmlBody: `<div contentEditable="true"
|
|
46
|
+
htmlBody: `<div contentEditable="true"><p><br/><br/><br/><br/><br/></p></div>`,
|
|
47
47
|
recipients: [],
|
|
48
48
|
attachments: []
|
|
49
49
|
});
|
|
@@ -50,7 +50,7 @@ export default class MailsPage extends MasterDetailPage {
|
|
|
50
50
|
data-list-selection="default"
|
|
51
51
|
data-items-updated-event="mails-available"
|
|
52
52
|
data-selection-updated-event="mail-selected"
|
|
53
|
-
selectedItem={Bind.
|
|
53
|
+
selectedItem={Bind.twoWays(() => this.selectedThread)}
|
|
54
54
|
selectOnClick={true}
|
|
55
55
|
items={this.mails}
|
|
56
56
|
{ ... InfiniteRepeater.pagedItems((start) => (c, e, cancelToken) => this.mailService.list({
|