@social-mail/social-mail-client 1.0.113 → 1.0.115

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 (230) hide show
  1. package/content/editor/edit.html +159 -0
  2. package/content/templates/plain/index.html +32 -0
  3. package/dist/admin/AdminAppIndex.pack.js +2605 -269
  4. package/dist/admin/AdminAppIndex.pack.js.map +1 -1
  5. package/dist/admin/AdminAppIndex.pack.min.js +258 -9
  6. package/dist/admin/AdminAppIndex.pack.min.js.map +1 -1
  7. package/dist/common/Sql.d.ts +1 -0
  8. package/dist/common/Sql.d.ts.map +1 -1
  9. package/dist/common/Sql.js.map +1 -1
  10. package/dist/common/commands/CommonCommands.d.ts +7 -0
  11. package/dist/common/commands/CommonCommands.d.ts.map +1 -1
  12. package/dist/common/commands/CommonCommands.js +10 -0
  13. package/dist/common/commands/CommonCommands.js.map +1 -1
  14. package/dist/common/controls/html/grapes-js/GrapesJSEditor.d.ts +19 -0
  15. package/dist/common/controls/html/grapes-js/GrapesJSEditor.d.ts.map +1 -0
  16. package/dist/common/controls/html/grapes-js/GrapesJSEditor.js +119 -0
  17. package/dist/common/controls/html/grapes-js/GrapesJSEditor.js.map +1 -0
  18. package/dist/common/controls/tree/FileTreeView.d.ts +16 -0
  19. package/dist/common/controls/tree/FileTreeView.d.ts.map +1 -0
  20. package/dist/common/controls/tree/FileTreeView.js +100 -0
  21. package/dist/common/controls/tree/FileTreeView.js.map +1 -0
  22. package/dist/common/controls/tree/TreeView.d.ts +4 -1
  23. package/dist/common/controls/tree/TreeView.d.ts.map +1 -1
  24. package/dist/common/controls/tree/TreeView.js +35 -17
  25. package/dist/common/controls/tree/TreeView.js.map +1 -1
  26. package/dist/common/pages/websites/edit/WebSiteFolderEditor.d.ts.map +1 -1
  27. package/dist/common/pages/websites/edit/WebSiteFolderEditor.js +2 -1
  28. package/dist/common/pages/websites/edit/WebSiteFolderEditor.js.map +1 -1
  29. package/dist/common/pages/websites/manage/ManageWebSitePage.d.ts +10 -0
  30. package/dist/common/pages/websites/manage/ManageWebSitePage.d.ts.map +1 -0
  31. package/dist/common/pages/websites/manage/ManageWebSitePage.js +45 -0
  32. package/dist/common/pages/websites/manage/ManageWebSitePage.js.map +1 -0
  33. package/dist/common/pages/websites/studio/WebSiteStudioPage.d.ts +24 -0
  34. package/dist/common/pages/websites/studio/WebSiteStudioPage.d.ts.map +1 -0
  35. package/dist/common/pages/websites/studio/WebSiteStudioPage.js +244 -0
  36. package/dist/common/pages/websites/studio/WebSiteStudioPage.js.map +1 -0
  37. package/dist/common/pages/websites/templates/ChooseWebSiteTemplatePage.d.ts +9 -0
  38. package/dist/common/pages/websites/templates/ChooseWebSiteTemplatePage.d.ts.map +1 -0
  39. package/dist/common/pages/websites/templates/ChooseWebSiteTemplatePage.js +59 -0
  40. package/dist/common/pages/websites/templates/ChooseWebSiteTemplatePage.js.map +1 -0
  41. package/dist/model/model.d.ts +9 -0
  42. package/dist/model/model.d.ts.map +1 -1
  43. package/dist/model/model.js +2 -1
  44. package/dist/model/model.js.map +1 -1
  45. package/dist/services/websites/WebSiteService.d.ts +1 -0
  46. package/dist/services/websites/WebSiteService.d.ts.map +1 -1
  47. package/dist/services/websites/WebSiteService.js +8 -1
  48. package/dist/services/websites/WebSiteService.js.map +1 -1
  49. package/dist/site-editor/blocks/Block.d.ts +6 -0
  50. package/dist/site-editor/blocks/Block.d.ts.map +1 -0
  51. package/dist/site-editor/blocks/Block.js +48 -0
  52. package/dist/site-editor/blocks/Block.js.map +1 -0
  53. package/dist/site-editor/blocks/ImageBlock.d.ts +2 -0
  54. package/dist/site-editor/blocks/ImageBlock.d.ts.map +1 -0
  55. package/dist/site-editor/blocks/ImageBlock.js +23 -0
  56. package/dist/site-editor/blocks/ImageBlock.js.map +1 -0
  57. package/dist/site-editor/blocks/WrapGrid.d.ts +2 -0
  58. package/dist/site-editor/blocks/WrapGrid.d.ts.map +1 -0
  59. package/dist/site-editor/blocks/WrapGrid.js +22 -0
  60. package/dist/site-editor/blocks/WrapGrid.js.map +1 -0
  61. package/dist/site-editor/commands/CodeCommand.d.ts +2 -0
  62. package/dist/site-editor/commands/CodeCommand.d.ts.map +1 -0
  63. package/dist/site-editor/commands/CodeCommand.js +51 -0
  64. package/dist/site-editor/commands/CodeCommand.js.map +1 -0
  65. package/dist/site-editor/commands/EditorCommand.d.ts +6 -0
  66. package/dist/site-editor/commands/EditorCommand.d.ts.map +1 -0
  67. package/dist/site-editor/commands/EditorCommand.js +52 -0
  68. package/dist/site-editor/commands/EditorCommand.js.map +1 -0
  69. package/dist/site-editor/commands/IEditorCommandParameter.d.ts +5 -0
  70. package/dist/site-editor/commands/IEditorCommandParameter.d.ts.map +1 -0
  71. package/dist/site-editor/commands/IEditorCommandParameter.js +9 -0
  72. package/dist/site-editor/commands/IEditorCommandParameter.js.map +1 -0
  73. package/dist/site-editor/components/Component.d.ts +5 -0
  74. package/dist/site-editor/components/Component.d.ts.map +1 -0
  75. package/dist/site-editor/components/Component.js +21 -0
  76. package/dist/site-editor/components/Component.js.map +1 -0
  77. package/dist/site-editor/components/ImageComponent.d.ts +1 -0
  78. package/dist/site-editor/components/ImageComponent.d.ts.map +1 -0
  79. package/dist/site-editor/components/ImageComponent.js +9 -0
  80. package/dist/site-editor/components/ImageComponent.js.map +1 -0
  81. package/dist/site-editor/drag-drop/DragDropHelper.d.ts +3 -0
  82. package/dist/site-editor/drag-drop/DragDropHelper.d.ts.map +1 -0
  83. package/dist/site-editor/drag-drop/DragDropHelper.js +117 -0
  84. package/dist/site-editor/drag-drop/DragDropHelper.js.map +1 -0
  85. package/dist/site-editor/editor/HtmlPageEditor.d.ts +43 -0
  86. package/dist/site-editor/editor/HtmlPageEditor.d.ts.map +1 -0
  87. package/dist/site-editor/editor/HtmlPageEditor.js +500 -0
  88. package/dist/site-editor/editor/HtmlPageEditor.js.map +1 -0
  89. package/dist/site-editor/properties/ColorEditor.d.ts +6 -0
  90. package/dist/site-editor/properties/ColorEditor.d.ts.map +1 -0
  91. package/dist/site-editor/properties/ColorEditor.js +46 -0
  92. package/dist/site-editor/properties/ColorEditor.js.map +1 -0
  93. package/dist/site-editor/properties/Properties.d.ts +2 -0
  94. package/dist/site-editor/properties/Properties.d.ts.map +1 -0
  95. package/dist/site-editor/properties/Properties.js +48 -0
  96. package/dist/site-editor/properties/Properties.js.map +1 -0
  97. package/dist/site-editor/properties/ThicknessEditor.d.ts +4 -0
  98. package/dist/site-editor/properties/ThicknessEditor.d.ts.map +1 -0
  99. package/dist/site-editor/properties/ThicknessEditor.js +15 -0
  100. package/dist/site-editor/properties/ThicknessEditor.js.map +1 -0
  101. package/dist/site-editor/styler/IStylerPair.d.ts +10 -0
  102. package/dist/site-editor/styler/IStylerPair.d.ts.map +1 -0
  103. package/dist/site-editor/styler/IStylerPair.js +9 -0
  104. package/dist/site-editor/styler/IStylerPair.js.map +1 -0
  105. package/dist/site-editor/styler/Styler.d.ts +170 -0
  106. package/dist/site-editor/styler/Styler.d.ts.map +1 -0
  107. package/dist/site-editor/styler/Styler.js +137 -0
  108. package/dist/site-editor/styler/Styler.js.map +1 -0
  109. package/dist/site-editor/styler/StylerSet.d.ts +8 -0
  110. package/dist/site-editor/styler/StylerSet.d.ts.map +1 -0
  111. package/dist/site-editor/styler/StylerSet.js +51 -0
  112. package/dist/site-editor/styler/StylerSet.js.map +1 -0
  113. package/dist/site-editor/styler/properties/border.d.ts +3 -0
  114. package/dist/site-editor/styler/properties/border.d.ts.map +1 -0
  115. package/dist/site-editor/styler/properties/border.js +38 -0
  116. package/dist/site-editor/styler/properties/border.js.map +1 -0
  117. package/dist/site-editor/styler/properties/boxShadow.d.ts +3 -0
  118. package/dist/site-editor/styler/properties/boxShadow.d.ts.map +1 -0
  119. package/dist/site-editor/styler/properties/boxShadow.js +24 -0
  120. package/dist/site-editor/styler/properties/boxShadow.js.map +1 -0
  121. package/dist/site-editor/styler/properties/color.d.ts +3 -0
  122. package/dist/site-editor/styler/properties/color.d.ts.map +1 -0
  123. package/dist/site-editor/styler/properties/color.js +93 -0
  124. package/dist/site-editor/styler/properties/color.js.map +1 -0
  125. package/dist/site-editor/styler/properties/cursor.d.ts +3 -0
  126. package/dist/site-editor/styler/properties/cursor.d.ts.map +1 -0
  127. package/dist/site-editor/styler/properties/cursor.js +20 -0
  128. package/dist/site-editor/styler/properties/cursor.js.map +1 -0
  129. package/dist/site-editor/styler/properties/filter.d.ts +3 -0
  130. package/dist/site-editor/styler/properties/filter.d.ts.map +1 -0
  131. package/dist/site-editor/styler/properties/filter.js +24 -0
  132. package/dist/site-editor/styler/properties/filter.js.map +1 -0
  133. package/dist/site-editor/styler/properties/layout.d.ts +3 -0
  134. package/dist/site-editor/styler/properties/layout.d.ts.map +1 -0
  135. package/dist/site-editor/styler/properties/layout.js +78 -0
  136. package/dist/site-editor/styler/properties/layout.js.map +1 -0
  137. package/dist/site-editor/toolbars/EditorToolbar.d.ts +3 -0
  138. package/dist/site-editor/toolbars/EditorToolbar.d.ts.map +1 -0
  139. package/dist/site-editor/toolbars/EditorToolbar.js +49 -0
  140. package/dist/site-editor/toolbars/EditorToolbar.js.map +1 -0
  141. package/dist/site-editor/toolbars/UndoRedoToolbar.d.ts +2 -0
  142. package/dist/site-editor/toolbars/UndoRedoToolbar.d.ts.map +1 -0
  143. package/dist/site-editor/toolbars/UndoRedoToolbar.js +40 -0
  144. package/dist/site-editor/toolbars/UndoRedoToolbar.js.map +1 -0
  145. package/dist/style/GlobalStyle.js +1 -1
  146. package/dist/tsconfig.tsbuildinfo +1 -1
  147. package/dist/web/AppIndex.pack.js +5188 -2832
  148. package/dist/web/AppIndex.pack.js.map +1 -1
  149. package/dist/web/AppIndex.pack.min.js +399 -150
  150. package/dist/web/AppIndex.pack.min.js.map +1 -1
  151. package/dist/web/drawer/AppDrawer.d.ts +1 -0
  152. package/dist/web/drawer/AppDrawer.d.ts.map +1 -1
  153. package/dist/web/drawer/AppDrawer.js +24 -4
  154. package/dist/web/drawer/AppDrawer.js.map +1 -1
  155. package/dist/web/page/files/FolderPage.d.ts.map +1 -1
  156. package/dist/web/page/files/FolderPage.js.map +1 -1
  157. package/dist/web/page/files/media/ChooseMediaPage.d.ts +24 -0
  158. package/dist/web/page/files/media/ChooseMediaPage.d.ts.map +1 -0
  159. package/dist/web/page/files/media/ChooseMediaPage.js +165 -0
  160. package/dist/web/page/files/media/ChooseMediaPage.js.map +1 -0
  161. package/dist/web/page/files/service/CloudFileService.d.ts +6 -3
  162. package/dist/web/page/files/service/CloudFileService.d.ts.map +1 -1
  163. package/dist/web/page/files/service/CloudFileService.js +34 -5
  164. package/dist/web/page/files/service/CloudFileService.js.map +1 -1
  165. package/node_modules/@web-atoms/core/dist/core/AtomList.d.ts.map +1 -1
  166. package/node_modules/@web-atoms/core/dist/core/AtomList.js +5 -3
  167. package/node_modules/@web-atoms/core/dist/core/AtomList.js.map +1 -1
  168. package/node_modules/@web-atoms/core/dist/services/FetchBuilder.d.ts +3 -0
  169. package/node_modules/@web-atoms/core/dist/services/FetchBuilder.d.ts.map +1 -1
  170. package/node_modules/@web-atoms/core/dist/services/FetchBuilder.js +10 -0
  171. package/node_modules/@web-atoms/core/dist/services/FetchBuilder.js.map +1 -1
  172. package/node_modules/@web-atoms/core/dist/style/styled.d.ts +2 -2
  173. package/node_modules/@web-atoms/core/dist/style/styled.d.ts.map +1 -1
  174. package/node_modules/@web-atoms/core/dist/style/styled.js.map +1 -1
  175. package/node_modules/@web-atoms/core/dist/tsconfig.tsbuildinfo +1 -1
  176. package/node_modules/@web-atoms/core/package.json +1 -1
  177. package/node_modules/@web-atoms/core/src/core/AtomList.ts +5 -3
  178. package/node_modules/@web-atoms/core/src/services/FetchBuilder.ts +13 -0
  179. package/node_modules/@web-atoms/core/src/style/styled.ts +3 -1
  180. package/node_modules/@web-atoms/web-controls/dist/basic/AtomChips.d.ts +1 -0
  181. package/node_modules/@web-atoms/web-controls/dist/basic/AtomChips.d.ts.map +1 -1
  182. package/node_modules/@web-atoms/web-controls/dist/basic/AtomChips.js +2 -0
  183. package/node_modules/@web-atoms/web-controls/dist/basic/AtomChips.js.map +1 -1
  184. package/node_modules/@web-atoms/web-controls/dist/basic/AtomRepeater.js +3 -0
  185. package/node_modules/@web-atoms/web-controls/dist/basic/AtomRepeater.js.map +1 -1
  186. package/node_modules/@web-atoms/web-controls/dist/tsconfig.tsbuildinfo +1 -1
  187. package/node_modules/@web-atoms/web-controls/package.json +2 -2
  188. package/node_modules/@web-atoms/web-controls/src/basic/AtomChips.tsx +4 -0
  189. package/node_modules/@web-atoms/web-controls/src/basic/AtomRepeater.tsx +3 -0
  190. package/package.json +3 -3
  191. package/src/common/Sql.ts +1 -0
  192. package/src/common/commands/CommonCommands.ts +12 -0
  193. package/src/common/controls/html/grapes-js/GrapesJSEditor.tsx +97 -0
  194. package/src/common/controls/tree/FileTreeView.tsx +74 -0
  195. package/src/common/controls/tree/TreeView.tsx +34 -12
  196. package/src/common/pages/websites/edit/WebSiteFolderEditor.tsx +2 -1
  197. package/src/common/pages/websites/manage/ManageWebSitePage.tsx +44 -0
  198. package/src/common/pages/websites/studio/WebSiteStudioPage.tsx +205 -0
  199. package/src/common/pages/websites/templates/ChooseWebSiteTemplatePage.tsx +38 -0
  200. package/src/model/model.ts +11 -0
  201. package/src/services/websites/WebSiteService.ts +8 -1
  202. package/src/site-editor/blocks/Block.tsx +38 -0
  203. package/src/site-editor/blocks/ImageBlock.tsx +14 -0
  204. package/src/site-editor/blocks/WrapGrid.tsx +11 -0
  205. package/src/site-editor/commands/CodeCommand.tsx +36 -0
  206. package/src/site-editor/commands/EditorCommand.tsx +42 -0
  207. package/src/site-editor/commands/IEditorCommandParameter.ts +5 -0
  208. package/src/site-editor/components/Component.tsx +9 -0
  209. package/src/site-editor/components/ImageComponent.tsx +0 -0
  210. package/src/site-editor/drag-drop/DragDropHelper.ts +141 -0
  211. package/src/site-editor/editor/HtmlPageEditor.tsx +497 -0
  212. package/src/site-editor/properties/ColorEditor.tsx +36 -0
  213. package/src/site-editor/properties/Properties.tsx +35 -0
  214. package/src/site-editor/properties/ThicknessEditor.tsx +5 -0
  215. package/src/site-editor/styler/IStylerPair.ts +9 -0
  216. package/src/site-editor/styler/Styler.ts +169 -0
  217. package/src/site-editor/styler/StylerSet.ts +42 -0
  218. package/src/site-editor/styler/properties/border.ts +30 -0
  219. package/src/site-editor/styler/properties/boxShadow.ts +14 -0
  220. package/src/site-editor/styler/properties/color.ts +82 -0
  221. package/src/site-editor/styler/properties/cursor.ts +49 -0
  222. package/src/site-editor/styler/properties/filter.ts +14 -0
  223. package/src/site-editor/styler/properties/layout.ts +72 -0
  224. package/src/site-editor/toolbars/EditorToolbar.tsx +40 -0
  225. package/src/site-editor/toolbars/UndoRedoToolbar.tsx +27 -0
  226. package/src/style/GlobalStyle.ts +1 -1
  227. package/src/web/drawer/AppDrawer.tsx +21 -4
  228. package/src/web/page/files/FolderPage.tsx +0 -1
  229. package/src/web/page/files/media/ChooseMediaPage.tsx +135 -0
  230. package/src/web/page/files/service/CloudFileService.ts +33 -8
@@ -0,0 +1,74 @@
1
+ import XNode from "@web-atoms/core/dist/core/XNode";
2
+ import { IAppFile } from "../../../model/model";
3
+ import TreeView from "./TreeView";
4
+ import { BindableProperty } from "@web-atoms/core/dist/core/BindableProperty";
5
+ import InjectProperty from "@web-atoms/core/dist/core/InjectProperty";
6
+ import CloudFileService from "../../../web/page/files/service/CloudFileService";
7
+ import Bind from "@web-atoms/core/dist/core/Bind";
8
+ import Action from "@web-atoms/core/dist/view-model/Action";
9
+
10
+
11
+ const getExtension = (name: string) => {
12
+ const index = name.lastIndexOf(".");
13
+ if (index === -1) {
14
+ return "dat";
15
+ }
16
+ return name.substring(index + 1);
17
+ };
18
+
19
+ export class FolderTreeView extends TreeView<IAppFile> {
20
+
21
+ @BindableProperty
22
+ public accept: string;
23
+
24
+ @BindableProperty
25
+ public folderId: number;
26
+
27
+ @InjectProperty
28
+ protected cloudFileService: CloudFileService;
29
+
30
+ constructor(app, e) {
31
+ super(app, e);
32
+
33
+ this.childrenProperty= (item) => item.children ??= [];
34
+ this.canSelect = (item) => item.isFolder;
35
+ this.isFolder = (item) => item.isFolder;
36
+ this.fileIconRenderer = (item) => <i
37
+ data-click-event="none"
38
+ class={`fiv-viv fiv-icon-${getExtension(item.name)}`}/>;
39
+ this.labelRenderer= (x) => <span
40
+ text={x.name}
41
+ title={x.name}/>;
42
+
43
+ this.render(<div folder={Bind.oneWayAsync((c, _, cancelToken) => this.loadFolder(this.folderId, this.accept, cancelToken ))}></div>);
44
+ }
45
+
46
+ @Action({ onEvent: "item-expanded"})
47
+ async onItemExpanded(item: IAppFile) {
48
+ await this.cloudFileService.expand(item);
49
+ }
50
+
51
+ protected async loadFolder(folder: number, accept: string, cancelToken) {
52
+ const f = await this.cloudFileService.getFolder(folder, cancelToken);
53
+ this.root = f;
54
+ this.selectedItem = f;
55
+ }
56
+
57
+ }
58
+
59
+ export class FileTreeView extends FolderTreeView {
60
+ constructor(app, e) {
61
+ super(app, e);
62
+ this.canSelect = (item) => !item.isFolder;
63
+ this.labelRenderer= (x) => <span
64
+ text={x.name}
65
+ title={x.name}
66
+ data-click-event={ x.isFolder ? "none": "select-item" } />;
67
+ }
68
+
69
+ protected async loadFolder(folder: number, accept: string, cancelToken) {
70
+ const f = await this.cloudFileService.root({ id: folder, cancelToken });
71
+ // f.children.remove(())
72
+ this.root = f;
73
+ }
74
+ }
@@ -103,7 +103,9 @@ export default class TreeView<T extends object = any> extends AtomControl {
103
103
 
104
104
  public labelRenderer: (item: T) => XNode;
105
105
 
106
- public collapseIconRenderer: (item: T) => XNode;
106
+ public fileIconRenderer: (item: T) => XNode;
107
+
108
+ public folderIconRenderer: (item: T) => XNode;
107
109
 
108
110
  public actionRenderer: (item: T) => XNode;
109
111
 
@@ -111,6 +113,12 @@ export default class TreeView<T extends object = any> extends AtomControl {
111
113
 
112
114
  public canSelect: (item: T) => boolean = (x) => true;
113
115
 
116
+ public isFolder: (item: T) => boolean = (x) => true;
117
+
118
+ async init() {
119
+ // do nothing
120
+ }
121
+
114
122
  onPropertyChanging(name: keyof TreeView, oldValue, newValue) {
115
123
  if (name === "selectedItem") {
116
124
  if (oldValue) {
@@ -131,7 +139,9 @@ export default class TreeView<T extends object = any> extends AtomControl {
131
139
  }
132
140
  const element = this.map.get(newValue);
133
141
  if (!element) {
134
- console.error(`Item not in the tree`);
142
+ if (this.root) {
143
+ console.error(`Item not in the tree`);
144
+ }
135
145
  return;
136
146
  }
137
147
  element.setAttribute("data-selected", "true");
@@ -155,14 +165,15 @@ export default class TreeView<T extends object = any> extends AtomControl {
155
165
  case "root":
156
166
  case "childrenProperty":
157
167
  case "labelRenderer":
158
- case "collapseIconRenderer":
168
+ case "folderIconRenderer":
169
+ case "fileIconRenderer":
159
170
  case "actionRenderer":
160
171
  const rootElement = this.element.firstElementChild as ITreeViewElement<T>;
161
172
  rootElement?.dispose();
162
173
  if (this.root
163
174
  && this.childrenProperty
164
175
  && this.labelRenderer
165
- && this.collapseIconRenderer) {
176
+ && this.folderIconRenderer) {
166
177
  this.element.innerHTML = "";
167
178
  this.createElement(this.root, void 0, -1);
168
179
  this.expand(this.root);
@@ -196,9 +207,12 @@ export default class TreeView<T extends object = any> extends AtomControl {
196
207
  title={item.label ?? item.name ?? item}
197
208
  text={item.label ?? item.name ?? item}
198
209
  />;
199
- this.collapseIconRenderer = (item) => <i
210
+ this.folderIconRenderer = (item) => <i
200
211
  data-click-event="expand-collapse-item"
201
212
  class="fas"/>;
213
+ this.fileIconRenderer = (item) => <i
214
+ data-element="icon"
215
+ data-click-event="none"/>;
202
216
  this.runAfterInit(() => {
203
217
  if (this.root && !this.element.firstElementChild) {
204
218
  if (this.childrenProperty) {
@@ -222,6 +236,8 @@ export default class TreeView<T extends object = any> extends AtomControl {
222
236
  const element = findTreeElement(ce.target as HTMLElement);
223
237
  this.expandElement(element);
224
238
  } );
239
+
240
+ this.runAfterInit(() => this.app.runAsync(() => this.init?.()));
225
241
  }
226
242
 
227
243
  protected expandElement(element: ITreeViewElement<any>, toggle = true) {
@@ -297,9 +313,19 @@ export default class TreeView<T extends object = any> extends AtomControl {
297
313
  };
298
314
 
299
315
  const actionElement = this.actionRenderer?.(item);
300
- const collapseElement = this.collapseIconRenderer(item);
316
+ const isFolder = this.isFolder?.(item) ?? true;
317
+ const iconElement = isFolder
318
+ ? this.folderIconRenderer(item)
319
+ : this.fileIconRenderer?.(item) ?? <i/>;
301
320
  const labelElement = this.labelRenderer(item);
302
321
 
322
+ if (iconElement) {
323
+ const a = iconElement.attributes ??= {};
324
+ a["data-element"] ??= isFolder ? "expand-collapse" : "file-icon";
325
+ a["data-click-event"] ??= "toggle-expand";
326
+ this.render(<div>{ iconElement }</div>, element, this);
327
+ }
328
+
303
329
  if (labelElement) {
304
330
  const a = labelElement.attributes ??= {};
305
331
  a["data-element"] = "label";
@@ -311,12 +337,6 @@ export default class TreeView<T extends object = any> extends AtomControl {
311
337
  (actionElement.attributes ??= {})["data-element"] = "action";
312
338
  this.render(<div>{ actionElement }</div>, element, this);
313
339
  }
314
- if (collapseElement) {
315
- const a = collapseElement.attributes ??= {};
316
- a["data-element"] = "expand-collapse";
317
- a["data-click-event"] = "toggle-expand";
318
- this.render(<div>{ collapseElement }</div>, element, this);
319
- }
320
340
 
321
341
  const header = document.createElement("div");
322
342
  header.setAttribute("data-element", "header");
@@ -379,3 +399,5 @@ export default class TreeView<T extends object = any> extends AtomControl {
379
399
  }
380
400
 
381
401
  }
402
+
403
+ delete TreeView.prototype.init;
@@ -19,7 +19,8 @@ export default class WebSiteFolderEditor extends PopupWindowPage {
19
19
  this.model = WebSiteFolder.create({
20
20
  folder: AppFile.create({
21
21
  name: "Web Site",
22
- isFolder: true
22
+ isFolder: true,
23
+ contentType: "application/site",
23
24
  }),
24
25
  isStatic: true
25
26
  });
@@ -0,0 +1,44 @@
1
+ import InjectProperty from "@web-atoms/core/dist/core/InjectProperty";
2
+ import { ContentPage } from "@web-atoms/web-controls/dist/mobile-app/MobileApp";
3
+ import WebSiteService from "../../../../services/websites/WebSiteService";
4
+ import { IWebSiteFolder, IWebSiteFolderVersion } from "../../../../model/model";
5
+ import XNode from "@web-atoms/core/dist/core/XNode";
6
+ import CommonCommands from "../../../commands/CommonCommands";
7
+
8
+ export default class ManageWebSitePage extends ContentPage {
9
+
10
+ parameters: { id: number };
11
+
12
+ @InjectProperty
13
+ private webSiteService: WebSiteService;
14
+
15
+ private model: IWebSiteFolder;
16
+
17
+ async init() {
18
+
19
+ this.model = await this.webSiteService.get(this.parameters.id);
20
+
21
+ this.renderer = <div>
22
+ <div>
23
+ {this.model.folder.name}
24
+ <a
25
+ data-click-event="route"
26
+ href={CommonCommands.editWebSite.displayRoute({ id: this.parameters.id })}>
27
+ <button
28
+ text="Edit"/>
29
+ </a>
30
+ <button
31
+ text="Preview"/>
32
+ </div>
33
+
34
+ <div>
35
+ <h5>Versions</h5>
36
+ <div>
37
+ { ... (this.model.versions ?? [] as IWebSiteFolderVersion[]).map((v) => <div>
38
+ {v.snapshotFolderID}
39
+ </div>)}
40
+ </div>
41
+ </div>
42
+ </div>;
43
+ }
44
+ }
@@ -0,0 +1,205 @@
1
+ import InjectProperty from "@web-atoms/core/dist/core/InjectProperty";
2
+ import { ContentPage } from "@web-atoms/web-controls/dist/mobile-app/MobileApp";
3
+ import CloudFileService from "../../../../web/page/files/service/CloudFileService";
4
+ import Bind from "@web-atoms/core/dist/core/Bind";
5
+ import XNode from "@web-atoms/core/dist/core/XNode";
6
+ import styled from "@web-atoms/core/dist/style/styled";
7
+ import Action from "@web-atoms/core/dist/view-model/Action";
8
+ import PageNavigator from "@web-atoms/web-controls/dist/PageNavigator";
9
+ import PopupButton, { MenuItem } from "@web-atoms/web-controls/dist/basic/PopupButton";
10
+ import UploadEvent from "@web-atoms/web-controls/dist/basic/UploadEvent";
11
+ import { IAppFile, AppFile } from "../../../../model/model";
12
+ import EditSharesPage from "../../../../web/page/files/shares/EditSharesPage";
13
+ import EditTemplatePage from "../../../../web/page/templates/EditTemplatePage";
14
+ import TreeView from "../../../controls/tree/TreeView";
15
+ import ChooseWebSiteTemplatePage from "../templates/ChooseWebSiteTemplatePage";
16
+ import FetchBuilder from "@web-atoms/core/dist/services/FetchBuilder";
17
+ import { FileTreeView } from "../../../controls/tree/FileTreeView";
18
+ import HtmlPageEditor from "../../../../site-editor/editor/HtmlPageEditor";
19
+
20
+ const css = styled.css `
21
+ display: grid;
22
+ grid-template-columns: 200px 1fr;
23
+ gap: 5px;
24
+ & .folder-tree {
25
+ grid-column: 1;
26
+ grid-row: 1;
27
+ }
28
+ & .file-list {
29
+ grid-row: 1;
30
+ grid-column: 2;
31
+ position: relative;
32
+ border: none;
33
+ overflow: auto;
34
+ justify-self: stretch;
35
+ align-self: stretch;
36
+ }
37
+ `.installLocal();
38
+
39
+ const getExtension = (name: string) => {
40
+ const index = name.lastIndexOf(".");
41
+ if (index === -1) {
42
+ return "dat";
43
+ }
44
+ return name.substring(index + 1);
45
+ };
46
+
47
+
48
+ export default class WebSiteStudioPage extends ContentPage {
49
+
50
+ public parameters: { id: number; templates?: boolean; };
51
+
52
+ public selectedFolder: IAppFile;
53
+
54
+ public root: IAppFile;
55
+
56
+ public search: string;
57
+
58
+ private version = 1;
59
+
60
+ private folderTree: TreeView;
61
+
62
+ @InjectProperty
63
+ private cloudFileService: CloudFileService;
64
+
65
+ async init() {
66
+ this.search = "";
67
+ this.root = await this.cloudFileService.root(this.parameters);
68
+ this.root.children ??= [];
69
+ this.root.children.remove((x) => x.contentType !== "text/html" && !x.isFolder);
70
+
71
+ await this.onItemExpanded(this.root);
72
+
73
+ if (!this.root.children?.length) {
74
+ await this.createIndexHtml();
75
+ return;
76
+ }
77
+
78
+ const indexHtml = this.root.children.find((x) => x.name === "index.html");
79
+ this.selectedFolder = indexHtml;
80
+
81
+ this.titleRenderer = () => <div data-layout="row">
82
+
83
+ <div text={Bind.oneWay(() => this.selectedFolder.name)}/>
84
+
85
+ <PopupButton
86
+ icon="fas fa-upload"
87
+ label="Upload"
88
+ data-layout="accent-icon-button"
89
+ alignment="bottomLeft"
90
+ popup={() => <div>
91
+ <MenuItem
92
+ icon="fas fa-upload"
93
+ data-extra={Bind.oneWay(() => JSON.stringify({ parentID: this.selectedFolder.appFileID }))}
94
+ { ... UploadEvent.AttachUploadAction({
95
+ multiple: true,
96
+ accept: "*/*"
97
+ })} label="Files"/>
98
+ <MenuItem
99
+ icon="fas fa-upload"
100
+ data-extra={Bind.oneWay(() => JSON.stringify({ parentID: this.selectedFolder.appFileID }))}
101
+ { ... UploadEvent.AttachUploadAction({
102
+ multiple: true,
103
+ folder: true,
104
+ accept: "*/*"
105
+ })} label="Folder"/>
106
+ </div>}
107
+ />
108
+
109
+ <span text="|"/>
110
+
111
+ <i
112
+ data-click-event="new-folder"
113
+ class="fas fa-plus"/>
114
+ <span
115
+ data-click-event="new-folder"
116
+ text="Folder"/>
117
+
118
+ <span text="|"/>
119
+
120
+ { this.parameters.templates && <div
121
+ data-layout="row"
122
+ style-display={Bind.oneWay(() => this.selectedFolder.appFileID > 0)}>
123
+ <i class="fas fa-plus" data-click-event="new-template"/>
124
+ <span
125
+ data-click-event="new-template"
126
+ text="New Template"/>
127
+ </div>}
128
+ </div>;
129
+
130
+ this.renderer = <div class={css}>
131
+ <FileTreeView
132
+ root={this.root}
133
+ class="folder-tree"
134
+ accept="text/html"
135
+ presenter={Bind.presenter((c) => this.folderTree = c)}
136
+ selectedItem={Bind.twoWaysImmediate(() => this.selectedFolder)}
137
+ />
138
+ <HtmlPageEditor
139
+ class="file-list"
140
+ folder={this.root}
141
+ htmlPage={Bind.oneWayAsync((s, e, cancelToken) => this.selectedFolder
142
+ ? FetchBuilder.get(this.selectedFolder.downloadUrl)
143
+ .cancelToken(cancelToken)
144
+ .responseAsText(true)
145
+ : void 0)}
146
+ />
147
+ </div>;
148
+ }
149
+
150
+ async createIndexHtml() {
151
+ await PageNavigator.pushPageForResultOrCancel(ChooseWebSiteTemplatePage, this.root);
152
+ await this.init();
153
+ }
154
+
155
+
156
+ @Action({ onEvent: "edit-shares"})
157
+ editShares(file: IAppFile) {
158
+ PageNavigator.pushPage(EditSharesPage, file);
159
+ }
160
+
161
+ @Action({ onEvent: "open-folder"})
162
+ openFolder(file: IAppFile) {
163
+ this.selectedFolder = file;
164
+ }
165
+
166
+ @Action({ onEvent: "new-folder"})
167
+ async newFolder() {
168
+ const name = prompt("Enter name of the folder");
169
+ if (!name) {
170
+ return;
171
+ }
172
+ const parentID = this.selectedFolder.appFileID;
173
+ const folder = await this.cloudFileService.createFolder({ name, parentID });
174
+ this.selectedFolder.children.add(folder);
175
+ }
176
+
177
+ @Action({ onEvent: "item-expanded"})
178
+ async onItemExpanded(folder: IAppFile) {
179
+ await this.cloudFileService.files({
180
+ search: "",
181
+ accept: "text/html",
182
+ folder,
183
+ cancelToken: null
184
+ });
185
+ }
186
+
187
+ @Action({ onEvent: "files-available"})
188
+ async onFilesUploaded() {
189
+ this.version++;
190
+ }
191
+
192
+ @Action({ onEvent: "new-template"})
193
+ async newTemplate() {
194
+ const parentID = this.selectedFolder.appFileID;
195
+ const file = await PageNavigator.pushPageForResult(EditTemplatePage, { file: AppFile.create({
196
+ parentID
197
+ })});
198
+ this.selectedFolder.children.add(file);
199
+ }
200
+
201
+ @Action({ onEvent: "open-template"})
202
+ async openTemplate(file: IAppFile) {
203
+ await PageNavigator.pushPageForResultOrCancel(EditTemplatePage, { file });
204
+ }
205
+ }
@@ -0,0 +1,38 @@
1
+ import { PopupWindowPage } from "@web-atoms/web-controls/dist/mobile-app/MobileApp";
2
+ import { IAppFile } from "../../../../model/model";
3
+ import XNode from "@web-atoms/core/dist/core/XNode";
4
+ import Action from "@web-atoms/core/dist/view-model/Action";
5
+ import { UMD } from "@web-atoms/core/dist/core/types";
6
+
7
+ export default class ChooseWebSiteTemplatePage extends PopupWindowPage {
8
+
9
+ parameters: IAppFile;
10
+
11
+ async init() {
12
+ this.renderer = <div>
13
+ <button
14
+ data-click-event="create-template"
15
+ text="Create"/>
16
+ </div>;
17
+ }
18
+
19
+ @Action({ onEvent: "create-template", close: true})
20
+ async createTemplate() {
21
+
22
+ // upload a simple html...
23
+ const path = UMD.resolvePath("@social-mail/social-mail-client/content/templates/plain/index.html");
24
+ const rs = await fetch(path);
25
+ const text = await rs.text();
26
+
27
+ // upload
28
+ await this.upload("index.html", text);
29
+ }
30
+
31
+ async upload(fileName: string, content: string) {
32
+ const url = `/api/upload?parentID=${this.parameters.appFileID}`;
33
+ const body = new FormData();
34
+ body.append(fileName, new Blob([content], { type: "text/html"}), fileName);
35
+ const rs = await fetch(url, { method: "POST", body });
36
+ }
37
+
38
+ }
@@ -43,6 +43,7 @@ export interface IAppFile extends IClrEntity {
43
43
  templates?: ICollection<IEmailTemplate>;
44
44
  userPins?: ICollection<IUserPin>;
45
45
  websiteFolder?: IWebSiteFolder;
46
+ websiteVersions?: ICollection<IWebSiteFolderVersion>;
46
47
  }
47
48
 
48
49
  export const AppFileContentDispositionArray = [{"label":"attachment","value":"attachment"},{"label":"inline","value":"inline"}];
@@ -623,6 +624,7 @@ export interface IWebSiteFolder extends IClrEntity {
623
624
  isStatic?: boolean;
624
625
  folder?: IAppFile;
625
626
  hosts?: ICollection<IWebSiteFolderHost>;
627
+ versions?: ICollection<IWebSiteFolderVersion>;
626
628
  }
627
629
 
628
630
  export const WebSiteFolder: IModel<IWebSiteFolder> = new Model<IWebSiteFolder>("WebSiteFolder", ["folderID"], { currentVersionID: 0,isStatic: false });
@@ -635,6 +637,15 @@ export interface IWebSiteFolderHost extends IClrEntity {
635
637
 
636
638
  export const WebSiteFolderHost: IModel<IWebSiteFolderHost> = new Model<IWebSiteFolderHost>("WebSiteFolderHost", ["host"], { });
637
639
 
640
+ export interface IWebSiteFolderVersion extends IClrEntity {
641
+ folderID?: number;
642
+ snapshotFolderID?: number;
643
+ websiteFolder?: IWebSiteFolder;
644
+ snapshotFolder?: IAppFile;
645
+ }
646
+
647
+ export const WebSiteFolderVersion: IModel<IWebSiteFolderVersion> = new Model<IWebSiteFolderVersion>("WebSiteFolderVersion", ["folderID","snapshotFolderID"], { });
648
+
638
649
  export interface ILoginSession extends IClrEntity {
639
650
  readonly sessionID?: number;
640
651
  userID?: number;
@@ -9,9 +9,16 @@ export default class WebSiteService {
9
9
  @Inject
10
10
  private entityService: EntityService;
11
11
 
12
+ async get(id) {
13
+ return this.entityService.query(WebSiteFolder)
14
+ .where({ id}, (p) => (x) => x.folderID === p.id)
15
+ .include((x) => [x.folder, x.hosts, x.versions])
16
+ .firstOrDefault();
17
+ }
18
+
12
19
  async list() {
13
20
  return this.entityService.query(WebSiteFolder)
14
- .include((x) => x.folder)
21
+ .include((x) => [x.folder, x.hosts])
15
22
  .toArray();
16
23
  }
17
24
 
@@ -0,0 +1,38 @@
1
+ import XNode from "@web-atoms/core/dist/core/XNode";
2
+ import type IEditorCommandParameter from "../commands/IEditorCommandParameter";
3
+ import { AtomControl } from "@web-atoms/core/dist/web/controls/AtomControl";
4
+ import type HtmlPageEditor from "../editor/HtmlPageEditor";
5
+ import styled from "@web-atoms/core/dist/style/styled";
6
+
7
+ styled.css `
8
+ padding: 5px;
9
+ cursor: pointer;
10
+ &:hover {
11
+ background-color: #00800080;
12
+ }
13
+ `.installGlobal("[data-html-editor-element=block]");
14
+
15
+
16
+ export function Block({
17
+ className,
18
+ title,
19
+ factory }: { className: string, title: string, factory:(doc: Document) => HTMLElement }) {
20
+
21
+ return () => {
22
+ return <i
23
+ data-html-editor-element="block"
24
+ class={className}
25
+ title={title}
26
+ draggable={true}
27
+ event-click={(e) => {
28
+ const editor = (AtomControl.from(e.target) as HtmlPageEditor);
29
+ editor.insertElement(factory(editor.htmlDocument));
30
+ }}
31
+ event-dragstart={(e: DragEvent) => {
32
+ const ne = factory((AtomControl.from(e.target) as HtmlPageEditor).htmlDocument);
33
+ e.dataTransfer.setDragImage(ne, 0, 0);
34
+ e.dataTransfer.setData("text/html", ne.outerHTML);
35
+ }}
36
+ />;
37
+ };
38
+ }
@@ -0,0 +1,14 @@
1
+ import XNode from "@web-atoms/core/dist/core/XNode";
2
+ import { Block } from "./Block";
3
+
4
+ const src = `data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAiIHZpZXdCb3g9IjAgMCAyNCAyNCIgc3R5bGU9ImZpbGw6IHJnYmEoMCwwLDAsMC4xNSk7IHRyYW5zZm9ybTogc2NhbGUoMC43NSkiPgogICAgICAgIDxwYXRoIGQ9Ik04LjUgMTMuNWwyLjUgMyAzLjUtNC41IDQuNSA2SDVtMTYgMVY1YTIgMiAwIDAgMC0yLTJINWMtMS4xIDAtMiAuOS0yIDJ2MTRjMCAxLjEuOSAyIDIgMmgxNGMxLjEgMCAyLS45IDItMnoiPjwvcGF0aD4KICAgICAgPC9zdmc+`;
5
+
6
+ export const ImageBlock = Block({
7
+ className: "fas fa-image",
8
+ title: "Add Image",
9
+ factory: (d) => {
10
+ const img = d.createElement("img");
11
+ img.setAttribute("src", src);
12
+ return img;
13
+ }
14
+ });
@@ -0,0 +1,11 @@
1
+ import { Block } from "./Block";
2
+
3
+ export const WrapGrid = Block({
4
+ className: "fa-duotone fa-grid-horizontal fa-rotate-90",
5
+ title: "Wrap Grid",
6
+ factory: (doc) => {
7
+ const e = doc.createElement("div");
8
+ e.setAttribute("styler-layout", "wrap-list");
9
+ return e;
10
+ }
11
+ });
@@ -0,0 +1,36 @@
1
+ import XNode from "@web-atoms/core/dist/core/XNode";
2
+ import { EditorCommand } from "./EditorCommand";
3
+ import { PopupWindowPage } from "@web-atoms/web-controls/dist/mobile-app/MobileApp";
4
+ import Bind from "@web-atoms/core/dist/core/Bind";
5
+ import PageNavigator from "@web-atoms/web-controls/dist/PageNavigator";
6
+
7
+ class CodeEditorWindow extends PopupWindowPage<string, string> {
8
+
9
+ async init() {
10
+ this.element.style.minWidth = "90%";
11
+ this.element.style.minHeight = "90%";
12
+
13
+ this.renderer = <div>
14
+ <textarea
15
+ data-position="absolute-fill"
16
+ value={Bind.twoWaysImmediate(() => this.parameters)}/>
17
+ </div>;
18
+
19
+ this.footerRenderer = () => <div data-layout="command-row">
20
+ <button
21
+ event-click={() => this.close(this.parameters)}
22
+ text="Save"/>
23
+ </div>;
24
+ }
25
+ }
26
+
27
+ export const CodeCommand = () => {
28
+ return <i
29
+ class="fa-solid fa-code"
30
+ event-click={EditorCommand.onClick(async (editor, e) => {
31
+ const text = await PageNavigator.pushPageForResult(CodeEditorWindow, editor.htmlPage);
32
+ editor.htmlPage = text;
33
+ editor.commit();
34
+ })}
35
+ />;
36
+ };