@social-mail/social-mail-client 1.2.33 → 1.2.35

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.
Files changed (95) hide show
  1. package/content/modules/monaco/monaco.html +57 -5
  2. package/dist/admin/AdminAppIndex.pack.js +336 -150
  3. package/dist/admin/AdminAppIndex.pack.js.map +1 -1
  4. package/dist/admin/AdminAppIndex.pack.min.js +7 -7
  5. package/dist/admin/AdminAppIndex.pack.min.js.map +1 -1
  6. package/dist/code-editor/CodeEditorPage.d.ts +1 -0
  7. package/dist/code-editor/CodeEditorPage.d.ts.map +1 -1
  8. package/dist/code-editor/CodeEditorPage.js +12 -18
  9. package/dist/code-editor/CodeEditorPage.js.map +1 -1
  10. package/dist/code-editor/CodeSnippetPage.d.ts +19 -0
  11. package/dist/code-editor/CodeSnippetPage.d.ts.map +1 -0
  12. package/dist/code-editor/CodeSnippetPage.js +98 -0
  13. package/dist/code-editor/CodeSnippetPage.js.map +1 -0
  14. package/dist/code-editor/ICodeSnippet.d.ts +6 -0
  15. package/dist/code-editor/ICodeSnippet.d.ts.map +1 -0
  16. package/dist/code-editor/ICodeSnippet.js +9 -0
  17. package/dist/code-editor/ICodeSnippet.js.map +1 -0
  18. package/dist/code-editor/MonacoService.d.ts +20 -0
  19. package/dist/code-editor/MonacoService.d.ts.map +1 -0
  20. package/dist/code-editor/MonacoService.js +120 -0
  21. package/dist/code-editor/MonacoService.js.map +1 -0
  22. package/dist/code-editor/MonaoEditor.d.ts +0 -19
  23. package/dist/code-editor/MonaoEditor.d.ts.map +1 -1
  24. package/dist/code-editor/MonaoEditor.js +3 -111
  25. package/dist/code-editor/MonaoEditor.js.map +1 -1
  26. package/dist/public/channel/BlogService.d.ts +15 -0
  27. package/dist/public/channel/BlogService.d.ts.map +1 -0
  28. package/dist/public/channel/BlogService.js +69 -0
  29. package/dist/public/channel/BlogService.js.map +1 -0
  30. package/dist/public/channel/ChannelView.d.ts +13 -0
  31. package/dist/public/channel/ChannelView.d.ts.map +1 -0
  32. package/dist/public/channel/ChannelView.js +80 -0
  33. package/dist/public/channel/ChannelView.js.map +1 -0
  34. package/dist/public/channel/ChannelView.pack.js +17831 -0
  35. package/dist/public/channel/ChannelView.pack.js.map +1 -0
  36. package/dist/public/channel/ChannelView.pack.min.js +576 -0
  37. package/dist/public/channel/ChannelView.pack.min.js.map +1 -0
  38. package/dist/public/channel/channelViewStyle.d.ts +2 -0
  39. package/dist/public/channel/channelViewStyle.d.ts.map +1 -0
  40. package/dist/public/channel/channelViewStyle.js +53 -0
  41. package/dist/public/channel/channelViewStyle.js.map +1 -0
  42. package/dist/services/email/EmailContentDownloader.d.ts +6 -0
  43. package/dist/services/email/EmailContentDownloader.d.ts.map +1 -0
  44. package/dist/services/email/EmailContentDownloader.js +44 -0
  45. package/dist/services/email/EmailContentDownloader.js.map +1 -0
  46. package/dist/site-editor/editor/SelectedElement.d.ts +1 -0
  47. package/dist/site-editor/editor/SelectedElement.d.ts.map +1 -1
  48. package/dist/site-editor/editor/SelectedElement.js +11 -1
  49. package/dist/site-editor/editor/SelectedElement.js.map +1 -1
  50. package/dist/site-editor/editor/WebSitePageEditor.d.ts.map +1 -1
  51. package/dist/site-editor/editor/WebSitePageEditor.js.map +1 -1
  52. package/dist/site-editor/properties/Properties.d.ts.map +1 -1
  53. package/dist/site-editor/properties/Properties.js +5 -3
  54. package/dist/site-editor/properties/Properties.js.map +1 -1
  55. package/dist/site-editor/properties/controls/PropertyEditor.d.ts +6 -0
  56. package/dist/site-editor/properties/controls/PropertyEditor.d.ts.map +1 -1
  57. package/dist/site-editor/properties/controls/PropertyEditor.js +21 -3
  58. package/dist/site-editor/properties/controls/PropertyEditor.js.map +1 -1
  59. package/dist/site-editor/properties/groups/AttributeEditor.d.ts +2 -0
  60. package/dist/site-editor/properties/groups/AttributeEditor.d.ts.map +1 -0
  61. package/dist/site-editor/properties/groups/AttributeEditor.js +34 -0
  62. package/dist/site-editor/properties/groups/AttributeEditor.js.map +1 -0
  63. package/dist/tsconfig.tsbuildinfo +1 -1
  64. package/dist/web/AppIndex.pack.js +420 -234
  65. package/dist/web/AppIndex.pack.js.map +1 -1
  66. package/dist/web/AppIndex.pack.min.js +8 -8
  67. package/dist/web/AppIndex.pack.min.js.map +1 -1
  68. package/dist/web/page/mails/mini-compose/Insert.d.ts.map +1 -1
  69. package/dist/web/page/mails/mini-compose/Insert.js +16 -3
  70. package/dist/web/page/mails/mini-compose/Insert.js.map +1 -1
  71. package/dist/web/page/mails/mini-compose/MiniComposeBox.d.ts.map +1 -1
  72. package/dist/web/page/mails/mini-compose/MiniComposeBox.js +8 -0
  73. package/dist/web/page/mails/mini-compose/MiniComposeBox.js.map +1 -1
  74. package/dist/web/page/mails/service/ConversationService.js +1 -1
  75. package/dist/web/page/mails/service/ConversationService.js.map +1 -1
  76. package/index.js +7 -1
  77. package/package.json +1 -1
  78. package/src/code-editor/CodeEditorPage.tsx +14 -8
  79. package/src/code-editor/CodeSnippetPage.tsx +78 -0
  80. package/src/code-editor/ICodeSnippet.ts +5 -0
  81. package/src/code-editor/MonacoService.ts +112 -0
  82. package/src/code-editor/MonaoEditor.tsx +89 -112
  83. package/src/monaco.d.ts +9124 -0
  84. package/src/public/channel/BlogService.ts +50 -0
  85. package/src/public/channel/ChannelView.tsx +76 -0
  86. package/src/public/channel/channelViewStyle.ts +42 -0
  87. package/src/services/email/EmailContentDownloader.ts +33 -0
  88. package/src/site-editor/editor/SelectedElement.tsx +12 -1
  89. package/src/site-editor/editor/WebSitePageEditor.tsx +0 -2
  90. package/src/site-editor/properties/Properties.tsx +2 -1
  91. package/src/site-editor/properties/controls/PropertyEditor.tsx +16 -3
  92. package/src/site-editor/properties/groups/AttributeEditor.tsx +20 -0
  93. package/src/web/page/mails/mini-compose/Insert.tsx +11 -1
  94. package/src/web/page/mails/mini-compose/MiniComposeBox.tsx +5 -0
  95. package/src/web/page/mails/service/ConversationService.tsx +1 -1
@@ -0,0 +1,50 @@
1
+ import DISingleton from "@web-atoms/core/dist/di/DISingleton";
2
+ import { Inject } from "@web-atoms/core/dist/di/Inject";
3
+ import EntityService from "../../services/EntityService";
4
+ import { Email, Mailbox } from "../../model/model";
5
+ import { Sql } from "../../common/Sql";
6
+ import TaskManager from "@web-atoms/entity/dist/models/TaskManager";
7
+ import EmailContentDownloader from "../../services/email/EmailContentDownloader";
8
+
9
+ @DISingleton()
10
+ export default class BlogService {
11
+
12
+ @Inject
13
+ entityService: EntityService;
14
+
15
+ @Inject
16
+ downloader: EmailContentDownloader;
17
+
18
+ async getEmails({
19
+ channelID = 0,
20
+ search = "",
21
+ start = 0,
22
+ size = 10,
23
+ cancelToken
24
+ }) {
25
+ let q = this.entityService.query(Email, "channelEmails", channelID);
26
+ if (search) {
27
+ q = q.where({ search }, (p) => (x) => Sql.text.includes(x.textBody, p.search));
28
+ }
29
+ const emails = await q
30
+ .include((x) => [x.attachments])
31
+ .toPagedList({ start, size, cancelToken });
32
+
33
+ const tasks = [];
34
+
35
+ for (const iterator of emails.items) {
36
+ if (!iterator.htmlBody) {
37
+ tasks.push(this.downloader.download(iterator));
38
+ }
39
+ }
40
+ await Promise.all(tasks);
41
+ return emails;
42
+ }
43
+
44
+ async getChannelID(emailAddress: any) {
45
+ const c = await this.entityService.query(Mailbox, "channels", emailAddress)
46
+ .firstOrDefault();
47
+ return c.mailboxID;
48
+ }
49
+
50
+ }
@@ -0,0 +1,76 @@
1
+ import { AtomControl } from "@web-atoms/core/dist/web/controls/AtomControl";
2
+ import "../../style/GlobalStyle";
3
+ import InjectProperty from "@web-atoms/core/dist/core/InjectProperty";
4
+ import EntityService from "../../services/EntityService";
5
+ import XNode from "@web-atoms/core/dist/core/XNode";
6
+ import { channelViewStyle } from "./channelViewStyle";
7
+ import Bind from "@web-atoms/core/dist/core/Bind";
8
+ import AtomRepeater from "@web-atoms/web-controls/dist/basic/AtomRepeater";
9
+ import { IEmail } from "../../model/model";
10
+ import InfiniteRepeater from "../../common/controls/repeater/InfiniteRepeater";
11
+ import BlogService from "./BlogService";
12
+ import Pack from "@web-atoms/core/dist/Pack";
13
+ import { renderMail } from "../../web/page/mails/service/ConversationService";
14
+
15
+ @Pack
16
+ export default class ChannelView extends AtomControl {
17
+
18
+ @InjectProperty
19
+ blogService: BlogService;
20
+
21
+ search = "";
22
+
23
+ channelID = 0;
24
+
25
+ mails = [] as IEmail[];
26
+
27
+ constructor(app, e = document.createElement("section")) {
28
+ super(app, e);
29
+ this.runAfterInit(() => this.app.runAsync(() => this.init()));
30
+ }
31
+
32
+ async init() {
33
+
34
+ const { channelID, emailAddress } = (window as any).socialMail ?? {};
35
+
36
+ this.channelID = channelID || (await this.blogService.getChannelID(emailAddress));
37
+
38
+ this.renderer = <div data-layout="flex-center">
39
+ <span text="..."/>
40
+ </div>;
41
+
42
+ this.element.className = channelViewStyle;
43
+ this.renderer = <section>
44
+ <header>
45
+ <input
46
+ placeholder="Search..."
47
+ value={Bind.twoWaysImmediate(() => this.search)}/>
48
+ </header>
49
+ <section>
50
+ <AtomRepeater
51
+ items={this.mails}
52
+ { ... InfiniteRepeater.pagedItems((start) =>
53
+ (c, e, cancelToken) =>
54
+ this.blogService.getEmails({
55
+ channelID: this.channelID,
56
+ start,
57
+ search: this.search,
58
+ cancelToken
59
+ })
60
+ )}
61
+ itemRenderer={(email: IEmail) => {
62
+ return <div>
63
+ <div { ... renderMail({ email })}></div>
64
+ </div>;
65
+ }}
66
+ />
67
+ </section>
68
+ <aside>
69
+ <AtomRepeater
70
+ />
71
+ </aside>
72
+ <footer></footer>
73
+ </section>;
74
+ }
75
+
76
+ }
@@ -0,0 +1,42 @@
1
+ import styled from "@web-atoms/core/dist/style/styled";
2
+
3
+ export const channelViewStyle = styled.css `
4
+
5
+ display: flex;
6
+ flex-direction: column;
7
+ gap: 5px;
8
+
9
+ & > header, & > footer {
10
+ display: flex;
11
+ flex-direction: row;
12
+ flex-wrap: wrap;
13
+ gap: 10px;
14
+ padding: 10px;
15
+ background: #FAFAFA;
16
+ }
17
+
18
+ @media (min-width: 900px) {
19
+ display: grid;
20
+ grid-template-columns: 1fr auto;
21
+ grid-template-rows: auto 1fr auto;
22
+ gap: 5px;
23
+
24
+ & > header {
25
+ grid-row: 1;
26
+ grid-column: 1 / span 2;
27
+ }
28
+ & > section {
29
+ grid-row: 2;
30
+ grid-column: 1;
31
+ }
32
+ & > aside {
33
+ grid-row: 2;
34
+ grid-column: 2;
35
+ }
36
+ & > footer {
37
+ grid-row: 3;
38
+ grid-column: 1 / span 2;
39
+ }
40
+ }
41
+
42
+ `.installLocal();
@@ -0,0 +1,33 @@
1
+ import DISingleton from "@web-atoms/core/dist/di/DISingleton";
2
+ import TaskManager from "@web-atoms/entity/dist/models/TaskManager";
3
+ import { IEmail } from "../../model/model";
4
+ import FetchBuilder from "@web-atoms/core/dist/services/FetchBuilder";
5
+
6
+ @DISingleton({})
7
+ export default class EmailContentDownloader extends TaskManager {
8
+
9
+ async download(email: IEmail) {
10
+ if (email.htmlBody) {
11
+ return email.htmlBody;
12
+ }
13
+
14
+ const cache = await window.caches.open("email-content-cache");
15
+
16
+ const cacheKey = new URL(email.htmlBodyUrl, location.href);
17
+
18
+ const content = await cache.match(cacheKey);
19
+
20
+ if (content) {
21
+ return email.htmlBody = await content.text();
22
+ }
23
+
24
+ const text = await FetchBuilder.get(email.htmlBodyUrl).responseAsText();
25
+ await cache.put(cacheKey, new Response(text, {
26
+ headers: {
27
+ "cache-control": "public, max-age=86000"
28
+ }
29
+ }));
30
+ return email.htmlBody = text;
31
+ }
32
+
33
+ }
@@ -33,15 +33,25 @@ export class SelectedElement {
33
33
  private cachedStyle: CSSStyleDeclaration;
34
34
  private cachedParentStyle: CSSStyleDeclaration;
35
35
 
36
+ private empty = {
37
+ setAttribute(n,v) {
38
+ this[n] = v;
39
+ },
40
+ getAttribute(n) {
41
+ return this[n];
42
+ }
43
+ };
44
+
36
45
  constructor(private editor: HtmlPageEditor) {
37
46
  this.name = "";
38
47
  this.isImage = false;
39
- this.mo = new MutationObserver(() => {
48
+ this.mo = new MutationObserver((changes) => {
40
49
  AtomBinder.refreshValue(this, "element");
41
50
  this.cachedStyle = null;
42
51
  this.cachedParentStyle = null;
43
52
  AtomBinder.refreshValue(this, "currentStyle");
44
53
  AtomBinder.refreshValue(this, "parentStyle");
54
+ AtomBinder.refreshValue(this, "attributes");
45
55
  for (const iterator of this.styles.values()) {
46
56
  AtomBinder.refreshValue(iterator, "value");
47
57
  AtomBinder.refreshValue(iterator, "custom");
@@ -116,6 +126,7 @@ export class SelectedElement {
116
126
  this.cachedParentStyle = null;
117
127
  AtomBinder.refreshValue(this, "currentStyle");
118
128
  AtomBinder.refreshValue(this, "parentStyle");
129
+ AtomBinder.refreshValue(this, "attributes");
119
130
  this.mo.observe(e, { attributes: true });
120
131
  }
121
132
  e = this.e;
@@ -6,9 +6,7 @@ import PageNavigator from "@web-atoms/web-controls/dist/PageNavigator";
6
6
  import { StylerSet } from "../styler/StylerSet";
7
7
  import InjectProperty from "@web-atoms/core/dist/core/InjectProperty";
8
8
  import CloudFileService from "../../web/page/files/service/CloudFileService";
9
- import FetchBuilder from "@web-atoms/core/dist/services/FetchBuilder";
10
9
  import Action from "@web-atoms/core/dist/view-model/Action";
11
- import MonacoEditor from "../../code-editor/MonaoEditor";
12
10
  import CodeEditorPage from "../../code-editor/CodeEditorPage";
13
11
 
14
12
  export default class WebSitePageEditor extends HtmlPageEditor {
@@ -7,12 +7,13 @@ import SizeGroupEditor from "./groups/SizeGroupEditor";
7
7
  import SpaceGroupEditor from "./groups/SpaceGroupEditor";
8
8
  import PositionGroupEditor from "./groups/PositionGroupEditor";
9
9
  import BackgroundGroupEditor from "./groups/BackgroundGroupEditor";
10
+ import AttributeEditor from "./groups/AttributeEditor";
10
11
 
11
12
  export default function Properties() {
12
13
 
13
14
  return <div
14
15
  data-layout="vertical-flex-stretch-items">
15
-
16
+ <AttributeEditor/>
16
17
  <LayoutEditor/>
17
18
  <SizeGroupEditor/>
18
19
  <BorderGroupEditor/>
@@ -74,14 +74,16 @@ export const BindStyleCustom = AtomControl.registerProperty("data-style-property
74
74
  }
75
75
 
76
76
 
77
- `.installGlobal("[data-element=expander-property-editor]")
77
+ `.installGlobal("[data-element=expander-property-editor]");
78
78
 
79
- function PropertyEditor({ label = void 0, custom = void 0, ... a }, ... nodes: XNode[]) {
79
+ function PropertyEditor({
80
+ label = void 0,
81
+ custom = void 0, ... a }, ... nodes: XNode[]) {
80
82
  if (!label && nodes.length === 1) {
81
83
  return nodes[0];
82
84
  }
83
85
  for (const iterator of nodes) {
84
- (iterator.attributes ??= {})["data-element"] = "editor";
86
+ (iterator.attributes ??= {})["data-element"] ??= "editor";
85
87
  }
86
88
  return <div
87
89
  data-element="property-editor"
@@ -132,3 +134,14 @@ export function NumberProperty({ label, property, ... a }: { label?: string, pro
132
134
  </PropertyEditor>;
133
135
  }
134
136
 
137
+ export function TextProperty({ label, property, attributeName, ... a }: { label?: string, attributeName?: string, property?: StylerProperty, [key: string]: any}) {
138
+ return <PropertyEditor
139
+ label={label} { ... a}>
140
+ <input
141
+ type="text" data-element="custom"
142
+ { ... BindStyleValue(attributeName ?? property.key)}
143
+ data-flex="stretch-full"
144
+ />
145
+ </PropertyEditor>;
146
+ }
147
+
@@ -0,0 +1,20 @@
1
+ import XNode from "@web-atoms/core/dist/core/XNode";
2
+ import { BindEditor, BindStyleValue, ExpanderPropertyEditor, TextProperty } from "../controls/PropertyEditor";
3
+
4
+ export default function AttributeEditor() {
5
+ return <ExpanderPropertyEditor
6
+ isExpanded={true}
7
+ label="Attributes">
8
+ <TextProperty
9
+ label="Link"
10
+ style-display={BindEditor.oneWay((x) => x.selection.name === "a")}
11
+ attributeName="href"/>
12
+ <TextProperty
13
+ label="Target"
14
+ style-display={BindEditor.oneWay((x) => x.selection.name === "a")}
15
+ attributeName="target"/>
16
+ <TextProperty
17
+ label="Tool Tip"
18
+ attributeName="title"/>
19
+ </ExpanderPropertyEditor>;
20
+ }
@@ -1,9 +1,11 @@
1
1
  import Bind from "@web-atoms/core/dist/core/Bind";
2
2
  import XNode from "@web-atoms/core/dist/core/XNode";
3
3
  import { IPopupOptions } from "@web-atoms/core/dist/web/services/PopupService";
4
+ import PageNavigator from "@web-atoms/web-controls/dist/PageNavigator";
4
5
  import PopupButton, { MenuItem } from "@web-atoms/web-controls/dist/basic/PopupButton";
5
6
  import UploadEvent from "@web-atoms/web-controls/dist/basic/UploadEvent";
6
- import AtomHtmlEditor from "@web-atoms/web-controls/dist/html-editor/AtomHtmlEditor";
7
+ import CodeSnippetPage from "../../../../code-editor/CodeSnippetPage";
8
+ import type { MailHtmlEditor } from "../../../../common/controls/html/InlineHtmlEditorWithToolbar";
7
9
 
8
10
  export default function Insert({ alignment = "above" as IPopupOptions["alignment"]}) {
9
11
  return <PopupButton
@@ -22,6 +24,14 @@ export default function Insert({ alignment = "above" as IPopupOptions["alignment
22
24
  label="Numbered List"
23
25
  event-click={Bind.event((editor: any) => editor.executeCommand("insertOrderedList"))}
24
26
  />
27
+ <MenuItem
28
+ icon="ri-list-ordered"
29
+ label="Insert Code"
30
+ event-click={Bind.event(async (editor: MailHtmlEditor) => {
31
+ const code = await PageNavigator.pushPageForResult(CodeSnippetPage);
32
+ (editor as any).executeCommand("insertHTML", void 0, `<pre style="margin: 5px; border: solid 1px lightgray; padding: 10px; border-radius: 10px;" contentEditable="true" spellcheck="false">${code}</pre><br/><p contentEditable="true"></p>`);
33
+ })}
34
+ />
25
35
  <MenuItem
26
36
  { ... UploadEvent.AttachUploadAction({
27
37
  accept: "image/*",
@@ -205,13 +205,18 @@ export default class MiniComposeBox extends AtomControl {
205
205
  return;
206
206
  }
207
207
  }
208
+ const { html , text } = this.editor.htmlTextContent;
209
+ this.draft.htmlBody = html;
210
+ this.draft.textBody = text;
208
211
 
209
212
  this.draft.status = "scheduled";
210
213
  this.draft.dateSent = DateTime.now.add(TimeSpan.fromSeconds(30));
211
214
  await this.mailService.send(this.draft);
212
215
  this.draft ??= Email.create({
216
+ htmlBody: `<div contentEditable="true"><p></p><br/></div>`,
213
217
  attachments: []
214
218
  });
219
+ this.editor.htmlContent = this.draft.htmlBody;
215
220
  }
216
221
 
217
222
  @Action({})
@@ -55,7 +55,7 @@ export const renderMail = AtomControl.registerProperty("data-html", "html", (c,
55
55
  // e.appendChild(msg);
56
56
  const shadow = e.attachShadow({ mode: "open" });
57
57
  shadow.appendChild(msg);
58
- if (!thread.timeRead) {
58
+ if (!thread.timeRead && thread.mailboxID) {
59
59
  const timeRead = DateTime.now;
60
60
  thread.timeRead = timeRead;
61
61
  const control = AtomControl.from(e);