@social-mail/social-mail-client 1.2.252 → 1.2.254

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 (169) hide show
  1. package/dist/admin/AdminAppIndex.pack.js +715 -79
  2. package/dist/admin/AdminAppIndex.pack.js.map +1 -1
  3. package/dist/admin/AdminAppIndex.pack.min.js +22 -16
  4. package/dist/admin/AdminAppIndex.pack.min.js.map +1 -1
  5. package/dist/code-editor/CodeEditorPage.d.ts +1 -3
  6. package/dist/code-editor/CodeEditorPage.d.ts.map +1 -1
  7. package/dist/code-editor/CodeEditorPage.js +5 -4
  8. package/dist/code-editor/CodeEditorPage.js.map +1 -1
  9. package/dist/common/controls/Loader.d.ts +2 -0
  10. package/dist/common/controls/Loader.d.ts.map +1 -0
  11. package/dist/common/controls/Loader.js +21 -0
  12. package/dist/common/controls/Loader.js.map +1 -0
  13. package/dist/common/controls/collection-editor/CollectionEditorEx.js +18 -8
  14. package/dist/common/controls/collection-editor/CollectionEditorEx.js.map +1 -1
  15. package/dist/common/controls/reference-editor/ReferenceEditor.d.ts.map +1 -1
  16. package/dist/common/controls/reference-editor/ReferenceEditor.js.map +1 -1
  17. package/dist/common/fileUrl.d.ts +14 -1
  18. package/dist/common/fileUrl.d.ts.map +1 -1
  19. package/dist/common/fileUrl.js +24 -5
  20. package/dist/common/fileUrl.js.map +1 -1
  21. package/dist/common/pages/stores/products/EditProductDetailPage.d.ts +4 -3
  22. package/dist/common/pages/stores/products/EditProductDetailPage.d.ts.map +1 -1
  23. package/dist/common/pages/stores/products/EditProductDetailPage.js +21 -5
  24. package/dist/common/pages/stores/products/EditProductDetailPage.js.map +1 -1
  25. package/dist/common/pages/stores/products/ProductEditor.d.ts +10 -1
  26. package/dist/common/pages/stores/products/ProductEditor.d.ts.map +1 -1
  27. package/dist/common/pages/stores/products/ProductEditor.js +176 -27
  28. package/dist/common/pages/stores/products/ProductEditor.js.map +1 -1
  29. package/dist/common/pages/stores/products/html/Offsers.d.ts +2 -0
  30. package/dist/common/pages/stores/products/html/Offsers.d.ts.map +1 -0
  31. package/dist/common/pages/stores/products/html/Offsers.js +20 -0
  32. package/dist/common/pages/stores/products/html/Offsers.js.map +1 -0
  33. package/dist/common/pages/stores/products/html/ProductHtmlEditor.d.ts +9 -0
  34. package/dist/common/pages/stores/products/html/ProductHtmlEditor.d.ts.map +1 -0
  35. package/dist/common/pages/stores/products/html/ProductHtmlEditor.js +64 -0
  36. package/dist/common/pages/stores/products/html/ProductHtmlEditor.js.map +1 -0
  37. package/dist/common/pages/stores/products/html/ProductHtmlEditorPage.d.ts +21 -0
  38. package/dist/common/pages/stores/products/html/ProductHtmlEditorPage.d.ts.map +1 -0
  39. package/dist/common/pages/stores/products/html/ProductHtmlEditorPage.js +138 -0
  40. package/dist/common/pages/stores/products/html/ProductHtmlEditorPage.js.map +1 -0
  41. package/dist/common/pages/stores/products/html/Specifications.d.ts +2 -0
  42. package/dist/common/pages/stores/products/html/Specifications.d.ts.map +1 -0
  43. package/dist/common/pages/stores/products/html/Specifications.js +22 -0
  44. package/dist/common/pages/stores/products/html/Specifications.js.map +1 -0
  45. package/dist/common/pages/websites/studio/WebSiteStudioPage.js +1 -1
  46. package/dist/common/pages/websites/studio/WebSiteStudioPage.js.map +1 -1
  47. package/dist/model/model.d.ts +21 -2
  48. package/dist/model/model.d.ts.map +1 -1
  49. package/dist/model/model.js +90 -11
  50. package/dist/model/model.js.map +1 -1
  51. package/dist/public/channel/ChannelView.pack.js +107 -16
  52. package/dist/public/channel/ChannelView.pack.js.map +1 -1
  53. package/dist/public/channel/ChannelView.pack.min.js +3 -3
  54. package/dist/public/channel/ChannelView.pack.min.js.map +1 -1
  55. package/dist/public/store/Store.pack.js +10729 -10631
  56. package/dist/public/store/Store.pack.js.map +1 -1
  57. package/dist/public/store/Store.pack.min.js +149 -288
  58. package/dist/public/store/Store.pack.min.js.map +1 -1
  59. package/dist/public/store/StoreApp.d.ts +1 -0
  60. package/dist/public/store/StoreApp.d.ts.map +1 -1
  61. package/dist/public/store/StoreApp.js +2 -2
  62. package/dist/public/store/StoreApp.js.map +1 -1
  63. package/dist/public/store/StoreApp.pack.js +33 -10
  64. package/dist/public/store/StoreApp.pack.js.map +1 -1
  65. package/dist/public/store/StoreApp.pack.min.js +8 -4
  66. package/dist/public/store/StoreApp.pack.min.js.map +1 -1
  67. package/dist/public/store/StoreItemDetailView.d.ts +13 -2
  68. package/dist/public/store/StoreItemDetailView.d.ts.map +1 -1
  69. package/dist/public/store/StoreItemDetailView.js +147 -7
  70. package/dist/public/store/StoreItemDetailView.js.map +1 -1
  71. package/dist/public/store/StoreItemListView.d.ts +2 -2
  72. package/dist/public/store/StoreItemListView.d.ts.map +1 -1
  73. package/dist/public/store/StoreItemListView.js +11 -9
  74. package/dist/public/store/StoreItemListView.js.map +1 -1
  75. package/dist/public/store/styles/common.d.ts +2 -0
  76. package/dist/public/store/styles/common.d.ts.map +1 -0
  77. package/dist/public/store/styles/common.js +18 -0
  78. package/dist/public/store/styles/common.js.map +1 -0
  79. package/dist/services/store/StoreItemService.d.ts +5 -0
  80. package/dist/services/store/StoreItemService.d.ts.map +1 -1
  81. package/dist/services/store/StoreItemService.js +66 -4
  82. package/dist/services/store/StoreItemService.js.map +1 -1
  83. package/dist/site-editor/editor/HtmlPageEditor.d.ts +1 -0
  84. package/dist/site-editor/editor/HtmlPageEditor.d.ts.map +1 -1
  85. package/dist/site-editor/editor/HtmlPageEditor.js +1 -0
  86. package/dist/site-editor/editor/HtmlPageEditor.js.map +1 -1
  87. package/dist/site-editor/editor/WebSitePageEditor.js +1 -1
  88. package/dist/site-editor/editor/WebSitePageEditor.js.map +1 -1
  89. package/dist/tsconfig.tsbuildinfo +1 -1
  90. package/dist/web/AppIndex.pack.js +715 -79
  91. package/dist/web/AppIndex.pack.js.map +1 -1
  92. package/dist/web/AppIndex.pack.min.js +22 -16
  93. package/dist/web/AppIndex.pack.min.js.map +1 -1
  94. package/dist/web/page/files/media/ChooseMediaPage.d.ts.map +1 -1
  95. package/dist/web/page/files/media/ChooseMediaPage.js +5 -1
  96. package/dist/web/page/files/media/ChooseMediaPage.js.map +1 -1
  97. package/dist/web/page/files/service/CloudFileService.d.ts +2 -1
  98. package/dist/web/page/files/service/CloudFileService.d.ts.map +1 -1
  99. package/dist/web/page/files/service/CloudFileService.js +5 -2
  100. package/dist/web/page/files/service/CloudFileService.js.map +1 -1
  101. package/node_modules/@web-atoms/core/dist/services/MockNavigationService.js.map +1 -1
  102. package/node_modules/@web-atoms/core/dist/tsconfig.tsbuildinfo +1 -1
  103. package/node_modules/@web-atoms/core/dist/web/controls/AtomControl.js +7 -3
  104. package/node_modules/@web-atoms/core/dist/web/controls/AtomControl.js.map +1 -1
  105. package/node_modules/@web-atoms/core/package.json +1 -1
  106. package/node_modules/@web-atoms/core/src/web/controls/AtomControl.ts +8 -2
  107. package/node_modules/@web-atoms/email-dom/dist/DomToString.js +10 -2
  108. package/node_modules/@web-atoms/email-dom/dist/DomToString.js.map +1 -1
  109. package/node_modules/@web-atoms/email-dom/dist/core/IXStyle.js.map +1 -1
  110. package/node_modules/@web-atoms/email-dom/dist/dom/Bold.js.map +1 -1
  111. package/node_modules/@web-atoms/email-dom/dist/dom/Button.js.map +1 -1
  112. package/node_modules/@web-atoms/email-dom/dist/dom/Cell.js.map +1 -1
  113. package/node_modules/@web-atoms/email-dom/dist/dom/Div.js.map +1 -1
  114. package/node_modules/@web-atoms/email-dom/dist/dom/EllipsisText.js.map +1 -1
  115. package/node_modules/@web-atoms/email-dom/dist/dom/Email.js.map +1 -1
  116. package/node_modules/@web-atoms/email-dom/dist/dom/EmailFooter.js.map +1 -1
  117. package/node_modules/@web-atoms/email-dom/dist/dom/FloatingBox.js.map +1 -1
  118. package/node_modules/@web-atoms/email-dom/dist/dom/HeaderBox.js.map +1 -1
  119. package/node_modules/@web-atoms/email-dom/dist/dom/Hr.js.map +1 -1
  120. package/node_modules/@web-atoms/email-dom/dist/dom/Image.js.map +1 -1
  121. package/node_modules/@web-atoms/email-dom/dist/dom/InlineDiv.js.map +1 -1
  122. package/node_modules/@web-atoms/email-dom/dist/dom/Link.js.map +1 -1
  123. package/node_modules/@web-atoms/email-dom/dist/dom/Pre.js.map +1 -1
  124. package/node_modules/@web-atoms/email-dom/dist/dom/Row.js.map +1 -1
  125. package/node_modules/@web-atoms/email-dom/dist/dom/Span.js.map +1 -1
  126. package/node_modules/@web-atoms/email-dom/dist/dom/StyleHelper.js.map +1 -1
  127. package/node_modules/@web-atoms/email-dom/dist/dom/Table.js.map +1 -1
  128. package/node_modules/@web-atoms/email-dom/dist/dom/TextBox.js.map +1 -1
  129. package/node_modules/@web-atoms/email-dom/dist/style/IEmailElementStyle.js.map +1 -1
  130. package/node_modules/@web-atoms/email-dom/dist/style/mergeStyle.js.map +1 -1
  131. package/node_modules/@web-atoms/email-dom/dist/tsconfig.tsbuildinfo +1 -1
  132. package/node_modules/@web-atoms/email-dom/package.json +1 -1
  133. package/node_modules/@web-atoms/email-dom/src/DomToString.tsx +10 -4
  134. package/node_modules/@web-atoms/web-controls/dist/basic/PinchZoomView.d.ts.map +1 -1
  135. package/node_modules/@web-atoms/web-controls/dist/basic/PinchZoomView.js +1 -0
  136. package/node_modules/@web-atoms/web-controls/dist/basic/PinchZoomView.js.map +1 -1
  137. package/node_modules/@web-atoms/web-controls/dist/basic/styles/pinch-zoom-view-style.js +1 -0
  138. package/node_modules/@web-atoms/web-controls/dist/basic/styles/pinch-zoom-view-style.js.map +1 -1
  139. package/node_modules/@web-atoms/web-controls/dist/mobile-app/MobileApp.d.ts.map +1 -1
  140. package/node_modules/@web-atoms/web-controls/dist/mobile-app/MobileApp.js +2 -4
  141. package/node_modules/@web-atoms/web-controls/dist/mobile-app/MobileApp.js.map +1 -1
  142. package/node_modules/@web-atoms/web-controls/dist/tsconfig.tsbuildinfo +1 -1
  143. package/node_modules/@web-atoms/web-controls/package.json +1 -1
  144. package/node_modules/@web-atoms/web-controls/src/basic/PinchZoomView.tsx +1 -0
  145. package/node_modules/@web-atoms/web-controls/src/basic/styles/pinch-zoom-view-style.ts +1 -0
  146. package/node_modules/@web-atoms/web-controls/src/mobile-app/MobileApp.tsx +6 -2
  147. package/package.json +4 -4
  148. package/src/code-editor/CodeEditorPage.tsx +4 -6
  149. package/src/common/controls/Loader.tsx +9 -0
  150. package/src/common/controls/collection-editor/CollectionEditorEx.tsx +27 -13
  151. package/src/common/controls/reference-editor/ReferenceEditor.tsx +1 -0
  152. package/src/common/fileUrl.ts +17 -5
  153. package/src/common/pages/stores/products/EditProductDetailPage.tsx +11 -2
  154. package/src/common/pages/stores/products/ProductEditor.tsx +179 -33
  155. package/src/common/pages/stores/products/html/Offsers.tsx +9 -0
  156. package/src/common/pages/stores/products/html/ProductHtmlEditor.tsx +37 -0
  157. package/src/common/pages/stores/products/html/ProductHtmlEditorPage.tsx +131 -0
  158. package/src/common/pages/stores/products/html/Specifications.tsx +41 -0
  159. package/src/common/pages/websites/studio/WebSiteStudioPage.tsx +1 -1
  160. package/src/model/model.ts +35 -8
  161. package/src/public/store/StoreApp.tsx +1 -0
  162. package/src/public/store/StoreItemDetailView.tsx +160 -3
  163. package/src/public/store/StoreItemListView.tsx +6 -6
  164. package/src/public/store/styles/common.ts +7 -0
  165. package/src/services/store/StoreItemService.ts +68 -2
  166. package/src/site-editor/editor/HtmlPageEditor.tsx +2 -0
  167. package/src/site-editor/editor/WebSitePageEditor.tsx +1 -1
  168. package/src/web/page/files/media/ChooseMediaPage.tsx +5 -1
  169. package/src/web/page/files/service/CloudFileService.ts +7 -3
@@ -9,9 +9,21 @@ export const imageUrl = (site: IAppFile, file: IAppFile, size?: number) => {
9
9
  return apiPath(`/api/site/asset/webp(${size})/${site.appFileID}/${file.appFileID}/${file.fileContentID}/${name}.${size}.webp`);
10
10
  };
11
11
 
12
- export const srcSetUrl = (site: IAppFile, file: IAppFile) => {
13
- const small = imageUrl(site, file, 480) + " 640w";
14
- const medium = imageUrl(site, file, 720) + " 1024w";
15
- const large = imageUrl(site, file) + " 1256w";
12
+ export const srcSetUrl = (site: IAppFile, file: IAppFile, imgUrlFunc = imageUrl) => {
13
+ const small = imgUrlFunc(site, file, 480) + " 640w";
14
+ const medium = imgUrlFunc(site, file, 720) + " 1024w";
15
+ const large = imgUrlFunc(site, file) + " 1256w";
16
16
  return `${small},${medium},${large}`;
17
- };
17
+ };
18
+
19
+ export const signedImageUrl = ({ fileID = 0, appFileID = fileID, fileContentID = void 0, signed = void 0 }, size?: number) => {
20
+ return apiPath(`/api/signed/webp(${size})/${appFileID}/${fileContentID}/${signed}/file.${size}.webp`);
21
+ };
22
+
23
+ export const signedUrl = ({ fileID = 0, appFileID = fileID, fileContentID = void 0, signed = void 0 }) => {
24
+ return apiPath(`/api/signed/download/${appFileID}/${fileContentID}/${signed}/file.dat`);
25
+ };
26
+
27
+ export const storeFileUrl = (rootFolderID, file: IAppFile, type = "download", name = file.name ) => {
28
+ return apiPath(`/api/store/file/${type}/${rootFolderID}/${file.appFileID}/${file.fileContentID}/${name}`);
29
+ };
@@ -2,7 +2,7 @@ import XNode from "@web-atoms/core/dist/core/XNode";
2
2
  import Form from "@web-atoms/web-controls/dist/basic/Form";
3
3
  import { ContentPage } from "@web-atoms/web-controls/dist/mobile-app/MobileApp";
4
4
  import CollectionEditor from "../../../controls/collection-editor/CollectionEditor";
5
- import { IStoreItem, IStoreItemFolder, IStoreItemPrice, IStoreItemTag, StoreItem, StoreItemItemTypeArray } from "../../../../model/model";
5
+ import { IStoreItem, IStoreItemFolder, IStoreItemPrice, IStoreItemTag, IStoreMediaFile, StoreItem, StoreItemItemTypeArray } from "../../../../model/model";
6
6
  import StoreItemService from "../../../../services/store/StoreItemService";
7
7
  import InjectProperty from "@web-atoms/core/dist/core/InjectProperty";
8
8
  import FormField from "@web-atoms/web-controls/dist/basic/FormField";
@@ -21,8 +21,11 @@ import TagChips from "../../../controls/tags/TagChips";
21
21
  import { DateFormats } from "../../../date/DateFormats";
22
22
  import FolderViewControl from "../../../folder-view/FolderViewControl";
23
23
  import ProductEditor from "./ProductEditor";
24
+ import MasterDetailPage from "@web-atoms/web-controls/dist/mobile-app/MasterDetailPage";
25
+ import ProductHtmlEditor from "./html/ProductHtmlEditorPage";
26
+ import PageNavigator from "@web-atoms/web-controls/dist/PageNavigator";
24
27
 
25
- export default class EditProductDetailPage extends ContentPage<Partial<IStoreItem>> {
28
+ export default class EditProductDetailPage extends MasterDetailPage<Partial<IStoreItem>> {
26
29
 
27
30
  model: IStoreItem = null;
28
31
 
@@ -83,4 +86,10 @@ export default class EditProductDetailPage extends ContentPage<Partial<IStoreIte
83
86
  await this.init();
84
87
  }
85
88
 
89
+ @Action({ onEvent: "editMediaFile"})
90
+ async editMediaFile(file: IStoreMediaFile) {
91
+ const item = this.model;
92
+ // this.openDetail(ProductHtmlEditor, { item, file });
93
+ await PageNavigator.pushPageForResult(ProductHtmlEditor, { item, file });
94
+ }
86
95
  }
@@ -1,5 +1,5 @@
1
1
  import { AtomControl } from "@web-atoms/core/dist/web/controls/AtomControl";
2
- import { IStoreItem, IStoreItemFolder, IStoreItemPrice, StoreItem, StoreItemItemTypeArray } from "../../../../model/model";
2
+ import { IStoreItem, IStoreItemFolder, IStoreItemPrice, IStoreMediaFile, IStorePriceAddOn, StoreItem, StoreItemItemTypeArray, StoreMediaFile, StorePriceAddOn } from "../../../../model/model";
3
3
  import Bind from "@web-atoms/core/dist/core/Bind";
4
4
  import XNode from "@web-atoms/core/dist/core/XNode";
5
5
  import Query from "@web-atoms/entity/dist/services/Query";
@@ -7,7 +7,7 @@ import Form from "@web-atoms/web-controls/dist/basic/Form";
7
7
  import FormField from "@web-atoms/web-controls/dist/basic/FormField";
8
8
  import Select from "@web-atoms/web-controls/dist/basic/Select";
9
9
  import { Sql } from "../../../Sql";
10
- import { SaveIconTextButton } from "../../../controls/buttons/IconButton";
10
+ import { SaveIconTextButton, UploadIconTextButton } from "../../../controls/buttons/IconButton";
11
11
  import CollectionEditorEx from "../../../controls/collection-editor/CollectionEditorEx";
12
12
  import ReferenceEditor from "../../../controls/reference-editor/ReferenceEditor";
13
13
  import TagChips from "../../../controls/tags/TagChips";
@@ -16,19 +16,48 @@ import FolderViewControl from "../../../folder-view/FolderViewControl";
16
16
  import EditItemFolderPage from "../folders/EditItemFolderPage";
17
17
  import EditItemPricePage from "./prices/EditItemPricePage";
18
18
  import { BindableProperty } from "@web-atoms/core/dist/core/BindableProperty";
19
+ import { FilesDragDrop } from "../../../controls/drag-drop/FilesDragDrop";
20
+ import UploadEvent from "@web-atoms/web-controls/dist/basic/UploadEvent";
21
+ import Action from "@web-atoms/core/dist/view-model/Action";
22
+ import { signedImageUrl } from "../../../fileUrl";
23
+ import InjectProperty from "@web-atoms/core/dist/core/InjectProperty";
24
+ import EntityService from "../../../../services/EntityService";
25
+ import StoreItemService from "../../../../services/store/StoreItemService";
26
+ import { InlinePopupButton } from "@web-atoms/web-controls/dist/basic/InlinePopup";
27
+ import { MenuItem } from "@web-atoms/web-controls/dist/basic/PopupButton";
28
+ import MasterDetailPage from "@web-atoms/web-controls/dist/mobile-app/MasterDetailPage";
29
+ import ProductHtmlEditor from "./html/ProductHtmlEditorPage";
30
+ import { Offers } from "./html/Offsers";
31
+ import { Specifications } from "./html/Specifications";
19
32
 
20
33
  export default class ProductEditor extends AtomControl {
21
34
 
35
+ @BindableProperty
36
+ productID: number = null;
37
+
22
38
  @BindableProperty
23
39
  model: IStoreItem = null;
24
40
 
41
+ @InjectProperty
42
+ storeItemService: StoreItemService;
43
+
25
44
  onPropertyChanged(name: string): void {
26
45
  super.onPropertyChanged(name);
27
46
  switch(name) {
28
47
  case "model":
29
48
  this.app.runAsync(() => this.init());
30
49
  break;
50
+ case "productID":
51
+ this.app.runAsync(() => this.loadProduct());
52
+ break;
53
+ }
54
+ }
55
+
56
+ async loadProduct() {
57
+ if (!this.productID) {
58
+ return;
31
59
  }
60
+ this.model = await this.storeItemService.get(this.productID);
32
61
  }
33
62
 
34
63
  async init() {
@@ -70,41 +99,10 @@ export default class ProductEditor extends AtomControl {
70
99
  value={Bind.twoWaysImmediate(() => this.model.description)}/>
71
100
  </FormField>
72
101
  </div>
73
- <CollectionEditorEx
74
- label="Prices"
75
- model={this.model}
76
- field={(x) => x.storeItemPrices}
77
- addPage={EditItemPricePage}
78
- itemRenderer={(item: IStoreItemPrice) => <div>
79
- <div text={item.currency}/>
80
- <div text={item.amount }/>
81
- <div
82
- title={DateFormats.withWeekDayAndTime(item.startDate)}
83
- text={DateFormats.relative.short(item.startDate)}/>
84
- { item.endDate
85
- ? <div
86
- title={DateFormats.withWeekDayAndTime(item.endDate)}
87
- text={DateFormats.relative.short(item.endDate)}/>
88
- : <div/>
89
- }
90
- {/* <Switch
91
- checked={item.active}
92
- /> */}
93
- </div>}
94
- />
95
102
  <TagChips
96
103
  softDeleteProperty={Bind.oneWay(() => this.model.storeItemID > 0)}
97
104
  items={Bind.twoWaysImmediate(() => this.model.storeItemTags)}
98
105
  />
99
- <details
100
- data-border="frame"
101
- open={true}>
102
- <summary text="Files"/>
103
- <FolderViewControl
104
- root={Bind.oneWay(() => this.model.fileFolder)}
105
- />
106
- </details>
107
-
108
106
  <CollectionEditorEx
109
107
  style-display={Bind.oneWay(() => this.model.storeItemID > 0, false)}
110
108
  label="Sizes"
@@ -142,7 +140,155 @@ export default class ProductEditor extends AtomControl {
142
140
  }}
143
141
  itemRenderer={(item: IStoreItem) => <div><a text={item.name}></a></div>}
144
142
  />
143
+ <CollectionEditorEx
144
+ label="Prices"
145
+ model={this.model}
146
+ field={(x) => x.storeItemPrices}
147
+ addPage={EditItemPricePage}
148
+ itemRenderer={(item: IStoreItemPrice) => <div>
149
+ <div text={item.currency}/>
150
+ <div text={item.amount }/>
151
+ <div
152
+ title={DateFormats.withWeekDayAndTime(item.startDate)}
153
+ text={DateFormats.relative.short(item.startDate)}/>
154
+ { item.endDate
155
+ ? <div
156
+ title={DateFormats.withWeekDayAndTime(item.endDate)}
157
+ text={DateFormats.relative.short(item.endDate)}/>
158
+ : <div/>
159
+ }
160
+ <CollectionEditorEx
161
+ label="Add Ons"
162
+ model={item}
163
+ field={(x) => x.addons}
164
+ itemFactory={() => StorePriceAddOn.create({
165
+ price: item,
166
+ priceID: item.priceID,
167
+ addOnItemID: null,
168
+ addOnItem: null,
169
+ inclusive: false,
170
+ print: true
171
+ })}
172
+ saveAfterAdd={false}
173
+ itemRenderer={(x: IStorePriceAddOn) => <div>
174
+ <ReferenceEditor
175
+ model={x}
176
+ field={(a) => a.addOnItem}
177
+ searchQuery={(q: Query<IStoreItem>, search) => (search
178
+ ? q.where({ search: search + "%" }, (p) => (i) => Sql.text.iLike(i.name, p.search))
179
+ : q)}
180
+ suggestionRenderer={(i: IStoreItem) => <div><label text={i.name}/></div>}
181
+ itemRenderer={(a: IStoreItem) => <div>
182
+ <label text={a.name}/>
183
+ </div>}
184
+ />
185
+ </div>}
186
+ />
187
+ {/* <Switch
188
+ checked={item.active}
189
+ /> */}
190
+ </div>}
191
+ />
192
+ <details
193
+ data-border="frame">
194
+ <summary text="Files"/>
195
+ <FolderViewControl
196
+ root={Bind.oneWay(() => this.model.fileFolder)}
197
+ />
198
+ </details>
199
+
200
+ <CollectionEditorEx
201
+ style-display={Bind.oneWay(() => this.model.storeItemID > 0, false)}
202
+ label="Media"
203
+ layout="flex-wrap"
204
+ model={this.model}
205
+ field={(x) => x.mediaFiles}
206
+ footer={() => <div data-layout="row">
207
+ <UploadIconTextButton
208
+ { ... UploadEvent.AttachUploadAction({
209
+ uploadEvent: "files-uploaded",
210
+ extra: Bind.oneWay(() => JSON.stringify({
211
+ parentID: this.model.folderID
212
+ }))
213
+ })}
214
+ />
215
+ <InlinePopupButton
216
+ icon="fas fa-plus"
217
+ label="Add Html"
218
+ popup={() => <div>
219
+ <MenuItem
220
+ data-click-event="add-offer"
221
+ label="Add Offers"/>
222
+ <MenuItem
223
+ data-click-event="add-specifications"
224
+ label="Add Specifications"/>
225
+ </div>} ></InlinePopupButton>
226
+ </div>}
227
+ itemRenderer={(item: IStoreMediaFile) => <div>
228
+ { item.isPreview
229
+ ? <img
230
+ src={this.mediaFileUrl(item)}
231
+ />
232
+ : <button
233
+ data-click-event="edit-media-file"
234
+ data-layout="link"
235
+ text={item.title}
236
+ />
237
+ }
238
+ </div>}
239
+ { ... FilesDragDrop({
240
+ uploadEvent: "files-uploaded",
241
+ extra: Bind.oneWay(() => JSON.stringify({
242
+ parentID: this.model.folderID
243
+ }))
244
+ })}
245
+ />
145
246
 
146
247
  </div>;
147
248
  }
249
+ mediaFileUrl(item: IStoreMediaFile) {
250
+ if (item.appFile) {
251
+ return `/api/files/webp(200)/${item.appFileID}/${item.appFile.fileContentID}/${item.appFile.name}.webp`;
252
+ }
253
+ return signedImageUrl(item, 200);
254
+ }
255
+
256
+ @Action({ onEvent: "files-uploaded"})
257
+ async onFilesUploaded({ files }) {
258
+ this.model.mediaFiles ??= [];
259
+ for (const appFile of files) {
260
+ this.model.mediaFiles.add(StoreMediaFile.create({
261
+ appFile,
262
+ appFileID: appFile.appFileID
263
+ }));
264
+ }
265
+ }
266
+
267
+ @Action({ onEvent: ["add-offer", "add-specifications"]})
268
+ async onAddHtmlFile(data, e: Event) {
269
+ let title = "";
270
+ let template: () => string;
271
+ switch(e.type) {
272
+ case "addOffer":
273
+ title = "offer.html";
274
+ template = Offers;
275
+ break;
276
+ case "addSpecifications":
277
+ title = "specs.html";
278
+ template = Specifications;
279
+ break;
280
+ default:
281
+ return;
282
+ }
283
+
284
+ // create empty file...
285
+ const file = await this.storeItemService.getOrCreateMediaFile(this.model, title, template);
286
+ // this.openDetail(ProductHtmlEditor, { item: this.model, file });
287
+ this.element.dispatchEvent(new CustomEvent("editMediaFile", {
288
+ detail: file,
289
+ bubbles: true
290
+ }));
291
+
292
+ }
293
+
148
294
  }
@@ -0,0 +1,9 @@
1
+ import XNode from "@web-atoms/core/dist/core/XNode";
2
+ import DomToString from "@web-atoms/email-dom/dist/DomToString";
3
+
4
+ export const Offers = () => DomToString(<main>
5
+ <section styler-layout="column">
6
+ </section>
7
+ <section styler-layout="column">
8
+ </section>
9
+ </main>);
@@ -0,0 +1,37 @@
1
+ import { BindableProperty } from "@web-atoms/core/dist/core/BindableProperty";
2
+ import InjectProperty from "@web-atoms/core/dist/core/InjectProperty";
3
+ import PageNavigator from "@web-atoms/web-controls/dist/PageNavigator";
4
+ import { IAppFile } from "../../../../../model/model";
5
+ import HtmlPageEditor from "../../../../../site-editor/editor/HtmlPageEditor";
6
+ import ChooseMediaPage from "../../../../../web/page/files/media/ChooseMediaPage";
7
+ import CloudFileService from "../../../../../web/page/files/service/CloudFileService";
8
+ import { imageUrl, srcSetUrl, storeFileUrl } from "../../../../fileUrl";
9
+
10
+ export default class ProductHtmlEditor extends HtmlPageEditor {
11
+
12
+ @BindableProperty
13
+ public folder: IAppFile = null;
14
+
15
+ @InjectProperty
16
+ private cloudFileService: CloudFileService;
17
+
18
+ async changeImage() {
19
+ const files: { file: IAppFile, size: number}[] = await PageNavigator.pushPageForResult(ChooseMediaPage, {
20
+ folder: this.folder,
21
+ accept: "image/*",
22
+ multiple: true,
23
+ selected: this.selection.element
24
+ });
25
+ const images = files.map(({ file, size}) => {
26
+ const src = storeFileUrl(this.folder.appFileID, file, `webp(${size})`, `${file.name}.${size}.webp`);
27
+ const srcset = srcSetUrl(this.folder, file, (folder, f, s) => storeFileUrl(this.folder.appFileID, file, `webp(${s})`, `${file.name}.${s}.webp`));
28
+ return { src, "data-src-set": srcset };
29
+ });
30
+ await this.insertImage( ... images);
31
+ }
32
+
33
+ protected async setStylerSheet() {
34
+ // do nothing
35
+ }
36
+
37
+ }
@@ -0,0 +1,131 @@
1
+ import { ContentPage } from "@web-atoms/web-controls/dist/mobile-app/MobileApp";
2
+ import { IStoreItem, IStoreMediaFile } from "../../../../../model/model";
3
+ import XNode from "@web-atoms/core/dist/core/XNode";
4
+ import Bind from "@web-atoms/core/dist/core/Bind";
5
+ import Loader from "../../../../controls/Loader";
6
+ import { signedUrl } from "../../../../fileUrl";
7
+ import FetchBuilder from "@web-atoms/core/dist/services/FetchBuilder";
8
+ import HtmlPageEditor from "../../../../../site-editor/editor/HtmlPageEditor";
9
+ import ProductHtmlEditor from "./ProductHtmlEditor";
10
+ import { StylerSet } from "../../../../../site-editor/styler/StylerSet";
11
+ import PageNavigator from "@web-atoms/web-controls/dist/PageNavigator";
12
+ import CodeEditorPage from "../../../../../code-editor/CodeEditorPage";
13
+ import Action from "@web-atoms/core/dist/view-model/Action";
14
+ import { SaveIconTextButton } from "../../../../controls/buttons/IconButton";
15
+ import InjectProperty from "@web-atoms/core/dist/core/InjectProperty";
16
+ import CloudFileService from "../../../../../web/page/files/service/CloudFileService";
17
+ import EntityService from "../../../../../services/EntityService";
18
+
19
+ const wrap = (styleText, body) => `
20
+ <!DOCTYPE html>
21
+ <html>
22
+ <style styler-style-sheet="styler-style-sheet">
23
+ ${styleText}
24
+ </style>
25
+ <body>
26
+ ${body}
27
+ </body>
28
+ </html>
29
+ `;
30
+
31
+ export default class ProductHtmlEditorPage extends ContentPage<{ item: IStoreItem, file: IStoreMediaFile }> {
32
+
33
+ storeItem: IStoreItem;
34
+
35
+ mediaFile: IStoreMediaFile;
36
+ html: string;
37
+ htmlEditor: HtmlPageEditor;
38
+ pageContent: string;
39
+
40
+ @InjectProperty
41
+ private cloudFileService: CloudFileService;
42
+ private originalHtml: string;
43
+
44
+ async init() {
45
+
46
+ this.renderer = <div>
47
+ <Loader/>
48
+ </div>;
49
+
50
+ this.storeItem = this.parameters.item;
51
+ this.mediaFile = this.parameters.file;
52
+
53
+ const htmlMain = this.mediaFile.fileContentID
54
+ ? await FetchBuilder.get(signedUrl(this.mediaFile)).responseAsText()
55
+ : "<main>Content</main>";
56
+
57
+ this.originalHtml = htmlMain;
58
+
59
+ const css = StylerSet.instance.toString();
60
+
61
+ this.html = wrap(css, htmlMain);
62
+
63
+ this.renderer = <div>
64
+ <ProductHtmlEditor
65
+ data-position="absolute-fill"
66
+ folder={this.storeItem.store.folder}
67
+ presenter={Bind.presenter((c) => this.htmlEditor = c)}
68
+ event-html-page-changed={(ce: CustomEvent<string>) => this.pageContent = ce.detail}
69
+ htmlPage={this.html}
70
+ />
71
+ </div>;
72
+
73
+ this.footerRenderer = () => <div
74
+ data-layout="header-row"
75
+ style-display={Bind.oneWay(() => this.pageContent !== this.html)}>
76
+ <SaveIconTextButton
77
+ event-click={() => this.savePage()}
78
+ text="Save"
79
+ />
80
+ <SaveIconTextButton
81
+ event-click={() => this.savePage(true)}
82
+ text="Save and Close"
83
+ />
84
+ </div>;
85
+
86
+ }
87
+
88
+ @Action({})
89
+ async savePage(close = false) {
90
+ if (!this.htmlEditor.lastCommittedBody) {
91
+ if (close) {
92
+ this.close(this.mediaFile);
93
+ }
94
+ return;
95
+ }
96
+ const { fileContentID } = await this.cloudFileService.saveFile({
97
+ appFileID: this.mediaFile.appFileID,
98
+ content: new File([this.htmlEditor.lastCommittedBody], this.parameters.file.title, { type: "text/html" })
99
+ });
100
+
101
+ this.mediaFile.fileContentID = fileContentID;
102
+ const es = this.resolve(EntityService);
103
+ await es.save(this.mediaFile, (c) => c);
104
+ if (close) {
105
+ this.close(this.mediaFile);
106
+ }
107
+ }
108
+
109
+ @Action({ onEvent: "edit-code"})
110
+ async editCode() {
111
+ const content = await PageNavigator.pushPageForResult(CodeEditorPage, {
112
+ fileName: this.parameters.file.title,
113
+ content: this.htmlEditor.lastCommittedHtml ?? this.htmlEditor.htmlPage
114
+ });
115
+ this.pageContent = content;
116
+ this.htmlEditor.htmlPage = content;
117
+ }
118
+
119
+ protected hide(): void {
120
+ this.pageContent = this.htmlEditor?.lastCommittedHtml ?? this.htmlEditor?.htmlPage;
121
+ super.hide();
122
+ }
123
+
124
+ protected show(): void {
125
+ super.show();
126
+ if (this.pageContent) {
127
+ setTimeout(() => this.htmlEditor.htmlPage = this.pageContent, 400);
128
+ }
129
+ }
130
+
131
+ }
@@ -0,0 +1,41 @@
1
+ import XNode from "@web-atoms/core/dist/core/XNode";
2
+ import DomToString from "@web-atoms/email-dom/dist/DomToString";
3
+
4
+ export const Specifications = () => DomToString(<main>
5
+ <section styler-layout="columns-2">
6
+ <table>
7
+ <thead>
8
+ <tr>
9
+ <th colspan={2}>Spec 1</th>
10
+ </tr>
11
+ </thead>
12
+ <tbody>
13
+ <tr>
14
+ <td>Size</td>
15
+ <td>Medium</td>
16
+ </tr>
17
+ <tr>
18
+ <td>Color</td>
19
+ <td>Transparent</td>
20
+ </tr>
21
+ </tbody>
22
+ </table>
23
+ <table>
24
+ <thead>
25
+ <tr>
26
+ <th colspan={2}>Spec 1</th>
27
+ </tr>
28
+ </thead>
29
+ <tbody>
30
+ <tr>
31
+ <td>Size</td>
32
+ <td>Medium</td>
33
+ </tr>
34
+ <tr>
35
+ <td>Color</td>
36
+ <td>Transparent</td>
37
+ </tr>
38
+ </tbody>
39
+ </table>
40
+ </section>
41
+ </main>);
@@ -242,7 +242,7 @@ export default class WebSiteStudioPage extends ContentPage {
242
242
  @Action({ onEvent: "edit-code"})
243
243
  async editCode() {
244
244
  const content = await PageNavigator.pushPageForResult(CodeEditorPage, {
245
- file: this.selectedFile,
245
+ fileName: this.selectedFile.name,
246
246
  content: this.htmlEditor.lastCommittedHtml ?? this.htmlEditor.htmlPage
247
247
  });
248
248
  this.pageContent = content;