@mixd-id/web-scaffold 0.2.240706 → 0.2.250801010

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 (220) hide show
  1. package/docs/components/Dashboard.md +56 -0
  2. package/log.txt +7 -0
  3. package/package.json +27 -19
  4. package/src/components/404.vue +61 -0
  5. package/src/components/AccountIcon.vue +19 -0
  6. package/src/components/Ahref.vue +1 -1
  7. package/src/components/Alert.vue +4 -13
  8. package/src/components/ArrayList.vue +49 -0
  9. package/src/components/Article.vue +24 -30
  10. package/src/components/Button.vue +83 -169
  11. package/src/components/Card.vue +257 -0
  12. package/src/components/Carousel.vue +61 -60
  13. package/src/components/Cart.vue +192 -0
  14. package/src/components/CartIcon.vue +89 -0
  15. package/src/components/ChartBar.vue +2 -3
  16. package/src/components/Checkbox.vue +20 -11
  17. package/src/components/Checkout.vue +373 -0
  18. package/src/components/CheckoutDelivery.vue +267 -0
  19. package/src/components/CodeEditor.vue +5 -16
  20. package/src/components/CollapsiblePanel.vue +70 -0
  21. package/src/components/ColorPicker.vue +12 -5
  22. package/src/components/ColorPicker2.vue +41 -19
  23. package/src/components/ColorPicker3.vue +100 -0
  24. package/src/components/Confirm.vue +9 -7
  25. package/src/components/ContextMenu.vue +122 -206
  26. package/src/components/ContextMenuItem.vue +53 -0
  27. package/src/components/Dashboard.vue +243 -0
  28. package/src/components/Dashboard2.vue +118 -0
  29. package/src/components/DashboardComponentSelector.vue +96 -0
  30. package/src/components/DashboardConfigs.vue +202 -0
  31. package/src/components/Datepicker.vue +102 -41
  32. package/src/components/DayTimeRange.vue +3 -2
  33. package/src/components/Dropdown.vue +7 -4
  34. package/src/components/Flex.vue +14 -40
  35. package/src/components/GHeatMaps.vue +2 -2
  36. package/src/components/Grid.vue +6 -6
  37. package/src/components/HTMLEditor.vue +27 -14
  38. package/src/components/Image.vue +62 -108
  39. package/src/components/ImagePreview.vue +14 -4
  40. package/src/components/ImageUploader.vue +114 -0
  41. package/src/components/ImportModal.vue +3 -3
  42. package/src/components/Link.vue +62 -6
  43. package/src/components/List.vue +528 -403
  44. package/src/components/ListContextMenu.vue +88 -0
  45. package/src/components/ListItem.vue +6 -4
  46. package/src/components/ListPage1.vue +14 -15
  47. package/src/components/ListView.vue +5 -6
  48. package/src/components/ListViewSettings.vue +2 -2
  49. package/src/components/LogViewerItem.vue +1 -1
  50. package/src/components/MarkdownEdit.vue +128 -0
  51. package/src/components/MarkdownPreview.vue +102 -0
  52. package/src/components/MenuItem1.vue +36 -0
  53. package/src/components/Modal.vue +95 -43
  54. package/src/components/MultiDropdown.vue +124 -0
  55. package/src/components/MultilineText.vue +1 -4
  56. package/src/components/OTPField.vue +40 -26
  57. package/src/components/ObjectTree.vue +1 -1
  58. package/src/components/PageBuilder.vue +3 -3
  59. package/src/components/Paragraph.vue +1 -2
  60. package/src/components/PresetSelectorFilterItem.vue +107 -95
  61. package/src/components/Radio.vue +1 -1
  62. package/src/components/SearchModal.vue +153 -0
  63. package/src/components/Slider.vue +1 -1
  64. package/src/components/Svg.vue +1 -1
  65. package/src/components/SvgEditor.vue +173 -0
  66. package/src/components/Switch.vue +4 -5
  67. package/src/components/Table.vue +2 -2
  68. package/src/components/TableView.vue +2 -3
  69. package/src/components/TableViewHead.vue +2 -2
  70. package/src/components/Tabs.vue +1 -1
  71. package/src/components/Testimonial.vue +2 -2
  72. package/src/components/Text.vue +7 -22
  73. package/src/components/TextEditor.vue +3 -3
  74. package/src/components/TextWithTag.vue +61 -30
  75. package/src/components/Textarea.vue +16 -22
  76. package/src/components/Textbox.vue +9 -19
  77. package/src/components/Timepicker.vue +25 -15
  78. package/src/components/Toast.vue +5 -3
  79. package/src/components/TreeMenu.vue +122 -0
  80. package/src/components/TreeView.vue +15 -10
  81. package/src/components/TreeView2.vue +38 -0
  82. package/src/components/TreeViewItem.vue +58 -29
  83. package/src/components/TreeViewItem2.vue +55 -0
  84. package/src/components/Uploader.vue +45 -0
  85. package/src/components/Video.vue +119 -0
  86. package/src/components/VirtualGrid.vue +24 -7
  87. package/src/components/VirtualTable.vue +363 -128
  88. package/src/configs/dashboard/data-table.js +9 -0
  89. package/src/configs/web-page-builder.js +118 -0
  90. package/src/directives/intersect.js +26 -0
  91. package/src/hooks/device.js +14 -0
  92. package/src/index.js +62 -107
  93. package/src/mixin/component.js +151 -67
  94. package/src/themes/default/index.js +118 -159
  95. package/src/utils/dashboard.js +22 -962
  96. package/src/utils/helpers.cjs +635 -0
  97. package/src/utils/helpers.js +91 -60
  98. package/src/utils/helpers.mjs +245 -12
  99. package/src/utils/importer.js +22 -3
  100. package/src/utils/list.mjs +1509 -0
  101. package/src/utils/preset-selector.cjs +1455 -0
  102. package/src/utils/preset-selector.js +489 -95
  103. package/src/utils/preset-selector.mjs +59 -20
  104. package/src/utils/queue.js +63 -0
  105. package/src/utils/web.mjs +120 -0
  106. package/src/utils/wss.js +38 -36
  107. package/src/utils/wss.mjs +24 -19
  108. package/src/widgets/AhrefSetting.vue +16 -13
  109. package/src/widgets/ArticleSetting.vue +15 -27
  110. package/src/widgets/BackgroundColorSetting.vue +153 -0
  111. package/src/widgets/BorderColorSetting.vue +57 -0
  112. package/src/widgets/BotEditor/BotEditorActions.vue +3 -2
  113. package/src/widgets/BotEditor/BotEditorSettings.vue +21 -0
  114. package/src/widgets/BotEditor.vue +35 -15
  115. package/src/widgets/ButtonSetting.vue +12 -13
  116. package/src/widgets/CarouselSetting.vue +33 -45
  117. package/src/widgets/CartSetting.vue +46 -0
  118. package/src/widgets/CheckoutSetting.vue +46 -0
  119. package/src/widgets/CollapsiblePanelSetting.vue +46 -0
  120. package/src/widgets/ColumnSelector.vue +29 -5
  121. package/src/widgets/ComponentSetting.vue +1 -1
  122. package/src/widgets/ComponentSetting2.vue +145 -236
  123. package/src/widgets/ComponentSetting3.vue +1 -1
  124. package/src/widgets/ContactForm.vue +3 -3
  125. package/src/widgets/ContactFormSetting.vue +41 -30
  126. package/src/widgets/Dashboard/BarChart.vue +47 -11
  127. package/src/widgets/Dashboard/BarChartSetting.vue +1 -1
  128. package/src/widgets/Dashboard/DataTable.vue +125 -0
  129. package/src/widgets/Dashboard/DataTableSetting.vue +243 -0
  130. package/src/widgets/Dashboard/DatasourceSelector.vue +1 -1
  131. package/src/widgets/Dashboard/Doughnut.vue +49 -7
  132. package/src/widgets/Dashboard/DoughnutSetting.vue +2 -2
  133. package/src/widgets/Dashboard/Metric.vue +78 -19
  134. package/src/widgets/Dashboard/MetricSetting.vue +81 -28
  135. package/src/widgets/Dashboard/Pie.vue +55 -6
  136. package/src/widgets/Dashboard/PieSetting.vue +1 -1
  137. package/src/widgets/Dashboard/PolarArea.vue +49 -7
  138. package/src/widgets/Dashboard/PolarAreaSetting.vue +1 -1
  139. package/src/widgets/Dashboard/SharingModal.vue +4 -5
  140. package/src/widgets/Dashboard/ViewSelector.vue +2 -2
  141. package/src/widgets/Dashboard/VirtualTableSetting.vue +121 -184
  142. package/src/widgets/{Dashboard.vue → Dashboard0.vue} +426 -343
  143. package/src/widgets/EmbeddedVideoSetting.vue +7 -5
  144. package/src/widgets/FAQ.vue +16 -3
  145. package/src/widgets/FAQSetting.vue +53 -47
  146. package/src/widgets/FeatureList.vue +3 -0
  147. package/src/widgets/FeatureListSetting.vue +112 -102
  148. package/src/widgets/FlexSetting.vue +83 -106
  149. package/src/widgets/GridSetting.vue +71 -196
  150. package/src/widgets/Header2.vue +34 -71
  151. package/src/widgets/Header2Setting.vue +95 -179
  152. package/src/widgets/HeaderSetting.vue +16 -18
  153. package/src/widgets/IconListSetting.vue +69 -65
  154. package/src/widgets/ImageSetting.vue +33 -60
  155. package/src/widgets/LinkSetting.vue +60 -37
  156. package/src/widgets/LinkSettingModal.vue +173 -0
  157. package/src/widgets/LogViewer.vue +1 -1
  158. package/src/widgets/MarginSetting.vue +2 -2
  159. package/src/widgets/MenuEditor.vue +1 -1
  160. package/src/widgets/MenuItem1Setting.vue +78 -0
  161. package/src/widgets/ModalSetting.vue +42 -44
  162. package/src/widgets/MultiValueSetting.vue +2 -2
  163. package/src/widgets/MultiValueSetting2.vue +78 -45
  164. package/src/widgets/OGSettingModal.vue +103 -0
  165. package/src/widgets/PaddingSetting.vue +2 -2
  166. package/src/widgets/ParagraphSetting.vue +16 -13
  167. package/src/widgets/PositionSetting.vue +209 -0
  168. package/src/widgets/PresetBar.vue +359 -210
  169. package/src/widgets/PresetBarPivot.vue +31 -19
  170. package/src/widgets/PresetSelector.vue +29 -17
  171. package/src/widgets/SearchModalSetting.vue +70 -0
  172. package/src/widgets/Share.vue +1 -2
  173. package/src/widgets/ShareSetting.vue +67 -60
  174. package/src/widgets/StyleSetting.vue +365 -150
  175. package/src/widgets/TestimonialSetting.vue +97 -88
  176. package/src/widgets/TextBlockSetting.vue +16 -13
  177. package/src/widgets/UserActionBuilder/UserActionConsole.vue +30 -10
  178. package/src/widgets/UserActionBuilder/UserActionOutput.vue +2 -2
  179. package/src/widgets/UserActionBuilder/UserActionOutputReply.vue +64 -87
  180. package/src/widgets/UserActionBuilder/UserActionProps.vue +3 -3
  181. package/src/widgets/UserActionBuilder.vue +4 -16
  182. package/src/widgets/WebComponentSelector.vue +15 -11
  183. package/src/widgets/WebLayoutSelector.vue +41 -270
  184. package/src/widgets/WebPageBuilder.vue +1019 -707
  185. package/src/widgets/WebPageBuilder2.vue +7 -7
  186. package/src/widgets/WebPageBuilder4/ButtonSetting.vue +0 -8
  187. package/src/widgets/WebPageBuilder4/CarouselSetting.vue +63 -7
  188. package/src/widgets/WebPageBuilder4/FlexAlignSetting.vue +3 -3
  189. package/src/widgets/WebPageBuilder4/FlexSetting.vue +1 -10
  190. package/src/widgets/WebPageBuilder4/MultiValueSetting.vue +2 -2
  191. package/src/widgets/WebPageBuilder4/PropertySetting.vue +0 -7
  192. package/src/widgets/WebPageBuilder4/WebPageComponentSelector.vue +1 -7
  193. package/src/widgets/WebPageBuilder4.vue +289 -575
  194. package/src/widgets/WebPageSelector.vue +1 -1
  195. package/src/widgets/YoutubeVideoSetting.vue +16 -13
  196. package/tailwind.config.js +3 -35
  197. package/docs/schema/user-action.json +0 -266
  198. package/src/App.vue +0 -25
  199. package/src/components/SearchButton.vue +0 -57
  200. package/src/entry-client.js +0 -27
  201. package/src/entry-server.js +0 -73
  202. package/src/events/event.js +0 -2
  203. package/src/main.js +0 -29
  204. package/src/mixin/website.js +0 -121
  205. package/src/router.js +0 -57
  206. package/src/widgets/MobileMenu.vue +0 -182
  207. package/src/widgets/WebPageBuilder4/ActionSetting.vue +0 -158
  208. package/src/widgets/WebPageBuilder4/ColorSetting.vue +0 -63
  209. package/src/widgets/WebPageBuilder4/DataSetting.vue +0 -92
  210. package/src/widgets/WebPageBuilder4/FontSizeSetting.vue +0 -76
  211. package/src/widgets/WebPageBuilder4/LinkSetting.vue +0 -68
  212. package/src/widgets/WebPageBuilder4/MobileMenuSetting.vue +0 -106
  213. package/src/widgets/WebPageBuilder4/Setting.vue +0 -73
  214. package/src/widgets/WebPageBuilder4/StyleSetting.vue +0 -77
  215. package/src/widgets/WebPageBuilder4/SvgSetting.vue +0 -207
  216. package/src/widgets/WebPageBuilder4/TextTransformSetting.vue +0 -70
  217. package/src/widgets/WebPageBuilder4/WebPageDataEdit.vue +0 -121
  218. package/test.json +0 -22
  219. /package/src/widgets/{Header1.vue → Header0.vue} +0 -0
  220. /package/src/widgets/{Header1Setting.vue → Header0Setting.vue} +0 -0
@@ -0,0 +1,635 @@
1
+ const ceil = (num, precision = 0) => {
2
+ var p = Math.pow(10, precision)
3
+ var n = (num * p) * (1 + Number.EPSILON)
4
+ return Math.ceil(n) / p
5
+ }
6
+
7
+ const floor = (num, precision = 0) => {
8
+ var p = Math.pow(10, precision)
9
+ var n = (num * p) * (1 + Number.EPSILON)
10
+ return Math.floor(n) / p
11
+ }
12
+
13
+ const ftWildcard = (key) => {
14
+ if(key.indexOf('/') >= 0) return key
15
+
16
+ const term = key.replace(/[\-\+\*\<\>\@\(\)\~]/, ' ', 'gi')
17
+
18
+ const searchTerms = []
19
+ term.split(' ').forEach((txt) => {
20
+ if(txt.length >= 3){
21
+ searchTerms.push(`+${txt}*`)
22
+ }
23
+ })
24
+ return searchTerms.join(' ')
25
+ }
26
+
27
+ const moveFile = function(oldPath, newPath, callback) {
28
+ const fs = require("fs");
29
+
30
+ fs.rename(oldPath, newPath, function (err) {
31
+ if (err) {
32
+ if (err.code === 'EXDEV') {
33
+ copy();
34
+ } else {
35
+ callback(err);
36
+ }
37
+ return;
38
+ }
39
+ callback();
40
+ });
41
+
42
+ function copy() {
43
+ const fs = require("fs");
44
+
45
+ var readStream = fs.createReadStream(oldPath);
46
+ var writeStream = fs.createWriteStream(newPath);
47
+
48
+ readStream.on('error', callback);
49
+ writeStream.on('error', callback);
50
+
51
+ readStream.on('close', function () {
52
+ fs.unlink(oldPath, callback);
53
+ });
54
+
55
+ readStream.pipe(writeStream);
56
+ }
57
+ }
58
+
59
+ const round = (num, precision = 0) => {
60
+ var p = Math.pow(10, precision)
61
+ var n = (num * p) * (1 + Number.EPSILON)
62
+ return Math.round(n) / p
63
+ }
64
+
65
+ const sanitizeMobileNumber = (mobileNumber) => {
66
+ if(typeof mobileNumber !== 'string') return mobileNumber
67
+
68
+ if(mobileNumber.length > 0){
69
+ mobileNumber = mobileNumber.replace(/[\- ]/g, '')
70
+ if(mobileNumber.substring(0, 1) === '0') mobileNumber = '+62' + mobileNumber.substring(1)
71
+ if(mobileNumber.substring(0, 1) !== '+'){
72
+ if(mobileNumber.substring(0, 2) === '62')
73
+ mobileNumber = '+' + mobileNumber
74
+ else
75
+ mobileNumber = '+62' + mobileNumber
76
+ }
77
+ if(mobileNumber.length > 0){
78
+ mobileNumber = mobileNumber[0] + mobileNumber.slice(1).replace(/\D/g, '')
79
+ }
80
+ }
81
+
82
+ return mobileNumber
83
+ }
84
+
85
+ const saveBase64 = async(data, dir = '/storage/files/images') => {
86
+ if(data.indexOf(',') >= 0){
87
+ data = data.substring(data.indexOf(',') + 1)
88
+ }
89
+ const buffer = Buffer.from(data, 'base64');
90
+ return await saveBuffer(buffer, dir)
91
+ }
92
+
93
+ const saveBuffer = async(buffer, dir = '/storage/files/images') => {
94
+
95
+ const fs = require("fs");
96
+ const md5 = require('md5')
97
+
98
+ const { fileTypeFromBuffer } = await import('file-type')
99
+
100
+ const type = await fileTypeFromBuffer(buffer)
101
+
102
+ const storagePath = process.env.ROOT_PATH + dir
103
+ const ext = type && type.ext ? '.' + type.ext : ''
104
+ const filename = md5(buffer) + ext
105
+ const to = storagePath + '/' + filename
106
+
107
+ fs.writeFileSync(to, buffer)
108
+
109
+ return filename
110
+ }
111
+
112
+ const saveFromUrl = async(url, dir = '/storage/files/images') => {
113
+ const axios = require('axios')
114
+
115
+ const res = await axios({
116
+ method: 'GET',
117
+ url,
118
+ responseType: 'arraybuffer',
119
+ })
120
+ const buffer = Buffer.from(res.data)
121
+ return await saveBuffer(buffer, dir)
122
+ }
123
+
124
+ const sleep = ms => new Promise(r => setTimeout(r, ms))
125
+
126
+ const strSlug = (title, separator) => {
127
+ if (typeof separator == 'undefined') separator = '-';
128
+
129
+ // Convert all dashes/underscores into separator
130
+ var flip = separator === '-' ? '_' : '-';
131
+ title = title.replace(flip, separator);
132
+
133
+ // Remove all characters that are not the separator, letters, numbers, or whitespace.
134
+ title = title.toLowerCase()
135
+ .replace(new RegExp('[^a-z0-9' + separator + '\\s]', 'g'), '');
136
+
137
+ // Replace all separator characters and whitespace by a single separator
138
+ title = title.replace(new RegExp('[' + separator + '\\s]+', 'g'), separator);
139
+
140
+ return title.replace(new RegExp('^[' + separator + '\\s]+|[' + separator + '\\s]+$', 'g'),'');
141
+ }
142
+
143
+ const strVars = (text, vars, opt = { emptyUndefined:true }) => {
144
+
145
+ (text.match(/\{.*?(?=\})\}/gi) ?? []).forEach((match) => {
146
+ const key = match.substring(1, match.length - 1)
147
+ const value = vars[key] ?? (opt?.emptyUndefined ? '' : `{${key}}`)
148
+ text = text.replace(match, value)
149
+ })
150
+
151
+ return text
152
+ }
153
+
154
+ const writeStorage = (path, content, append = false) => {
155
+
156
+ const fs = require("fs");
157
+
158
+ if(path.startsWith('/')) path = path.substring(1)
159
+
160
+ if(append){
161
+ fs.appendFileSync(process.env.ROOT_PATH + `/storage/${path}`, content)
162
+ }
163
+ else{
164
+ fs.writeFileSync(process.env.ROOT_PATH + `/storage/${path}`, content)
165
+ }
166
+ }
167
+
168
+ const bufferToStream = (buffer) => {
169
+ const { Duplex } = require('stream')
170
+ let stream = new Duplex()
171
+ stream.push(buffer)
172
+ stream.push(null)
173
+ return stream
174
+ }
175
+
176
+ const sequelizeChunk = async (model, opt, callback, chunkSize = 5000) => {
177
+
178
+ let offset = 0
179
+ let iter = 0
180
+ while(true){
181
+ const items = await model.findAll({
182
+ ...opt,
183
+ offset,
184
+ limit: chunkSize
185
+ })
186
+
187
+ if(items.length > 0){
188
+ await callback(items, iter)
189
+ offset += chunkSize
190
+ iter++
191
+ }
192
+ else{
193
+ break
194
+ }
195
+ }
196
+ }
197
+
198
+ const getPresetSortWhereParams = (order, afterItem) => {
199
+
200
+ const { Op } = require('sequelize')
201
+
202
+ if(order.filter((_) => _[0] === 'id').length <= 0){
203
+ order.push([ 'id', 'desc' ])
204
+ }
205
+
206
+ const opOr = []
207
+ for(let i = 0 ; i < order.length ; i++){
208
+
209
+ const obj = order[i]
210
+
211
+ if(obj.length !== 2) continue
212
+
213
+ const exp = {}
214
+ for(let j = 0 ; j < i ; j++){
215
+ exp[order[j][0]] = afterItem[order[j][0]]
216
+ }
217
+ exp[obj[0]] = obj[1] === 'desc' ? { [Op.lt]:afterItem[obj[0]] } : { [Op.gt]:afterItem[obj[0]] }
218
+
219
+ if(Object.keys(exp).length === 1){
220
+ opOr.push(exp)
221
+ }
222
+ else{
223
+ opOr.push({
224
+ [Op.and]: exp
225
+ })
226
+ }
227
+ }
228
+
229
+ let sortWhere = {}
230
+ if(opOr.length > 0){
231
+ sortWhere = {
232
+ [Op.or]: opOr
233
+ }
234
+ }
235
+ return sortWhere
236
+ }
237
+
238
+ const unflatten = (flatObject) => {
239
+ const nestedObject = {};
240
+
241
+ for (const key in flatObject) {
242
+ if (Object.prototype.hasOwnProperty.call(flatObject, key)) {
243
+ const value = flatObject[key];
244
+ const keys = key.split('.');
245
+
246
+ let currentObj = nestedObject;
247
+ for (let i = 0; i < keys.length; i++) {
248
+ const currentKey = keys[i];
249
+
250
+ if (!currentObj[currentKey]) {
251
+ currentObj[currentKey] = {};
252
+ }
253
+
254
+ if (i === keys.length - 1) {
255
+ currentObj[currentKey] = value;
256
+ } else {
257
+ currentObj = currentObj[currentKey];
258
+ }
259
+ }
260
+ }
261
+ }
262
+
263
+ return nestedObject;
264
+ }
265
+
266
+ const accessNestedObject = function(obj, path) {
267
+ if(!obj || typeof path !== 'string') return undefined
268
+
269
+ const keys = path.split('.');
270
+ let nestedObj = obj;
271
+
272
+ for (let key of keys) {
273
+ if (nestedObj && nestedObj.hasOwnProperty(key)) {
274
+ nestedObj = nestedObj[key];
275
+ } else {
276
+ // Return undefined if any key in the path is missing
277
+ return undefined;
278
+ }
279
+ }
280
+
281
+ return nestedObj;
282
+ }
283
+
284
+ const createObjectFromPath = (obj, path, value) => {
285
+ const keys = path.split('.');
286
+
287
+ let current = obj;
288
+ for (let i = 0; i < keys.length; i++) {
289
+ const key = keys[i];
290
+ const indexMatch = key.match(/^(\d+)$/);
291
+ const isArrayIndex = indexMatch !== null;
292
+
293
+ const nextIsArrayIndex = !!(keys[i + 1] ?? '').match(/^(\d+)$/);
294
+ const isLast = i === keys.length - 1
295
+
296
+ if(isArrayIndex) {
297
+ const index = parseInt(indexMatch[1], 10);
298
+ if (!Array.isArray(current)) {
299
+ current = [];
300
+ }
301
+ if (typeof current[index] === 'undefined') {
302
+ current[index] = isLast ? value : nextIsArrayIndex ? [] : {};
303
+ }
304
+ current = current[index]
305
+ }
306
+ else{
307
+ if(typeof current[key] !== 'object' || current[key] === null) {
308
+ current[key] = isLast ? value : nextIsArrayIndex ? [] : {};
309
+ }
310
+ current = current[key];
311
+ }
312
+ }
313
+
314
+ return obj;
315
+ }
316
+
317
+ const cssDict = {
318
+ 'Global': '*',
319
+ 'Font': 'font-family',
320
+ 'Impact': "'Impact', 'Arial Black', 'Arial Bold', Gadget, sans-serif",
321
+ }
322
+
323
+ const generateStylesheet = (styleObj) => {
324
+
325
+ return `*{ font-family: Impact; }`
326
+
327
+ }
328
+
329
+ const hexToRgb = (hex) => {
330
+ var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
331
+ return result ? {
332
+ r: parseInt(result[1], 16),
333
+ g: parseInt(result[2], 16),
334
+ b: parseInt(result[3], 16)
335
+ } : null;
336
+ }
337
+
338
+ const compClasses = [
339
+ 'aspectRatio',
340
+ 'bdSize', 'bdColor', 'bdRadius', 'bdStyle',
341
+ 'bgColors', 'bgSize', 'bgPosition', 'bgRepeat',
342
+ 'gap',
343
+ 'padding', 'margin',
344
+ 'direction', 'columns', 'display',
345
+ 'width', 'minWidth', 'maxWidth',
346
+ 'height', 'minHeight', 'maxHeight',
347
+ 'fontFamily', 'fontSize', 'fontWeight', 'textColor', 'lineHeight', 'overflow',
348
+ 'boxShadow', 'opacity',
349
+ 'colSpan'
350
+ ]
351
+
352
+ const containerClasses = [
353
+ 'containerVariant', 'containerGridColumn', 'containerGap'
354
+ ]
355
+
356
+ const itemClasses = [
357
+ 'itemMinWidth', 'itemRatio', 'itemVariant'
358
+ ]
359
+
360
+ const createComponentInstance = function(component){
361
+
362
+ if(!component.instance)
363
+ component.instance = {}
364
+
365
+ const compUid = '_' + component.uid.substring(0, 4) + ' '
366
+
367
+ Object.assign(component.instance, {
368
+ type: component.type,
369
+ uid: component.uid,
370
+
371
+ class: compUid + compClasses.map(key => {
372
+ return Array.isArray(component.props[key]) ? component.props[key].join(' ') : ''
373
+ })
374
+ .filter(_ => _)
375
+ .join(' '),
376
+
377
+ containerClass: containerClasses.map(key => {
378
+ return Array.isArray(component.props[key]) ? component.props[key].join(' ') : ''
379
+ })
380
+ .filter(_ => _)
381
+ .join(' '),
382
+
383
+ itemClass: itemClasses.map(key => {
384
+ return Array.isArray(component.props[key]) ? component.props[key].join(' ') : ''
385
+ })
386
+ .filter(_ => _)
387
+ .join(' ')
388
+ })
389
+
390
+ for(let key in component.props){
391
+ if(!compClasses.includes(key) && ![ 'enabled' ].includes(key)){
392
+ component.instance[key] = component.props[key]
393
+ }
394
+ }
395
+
396
+ if(Array.isArray(component.items)){
397
+ component.instance.items = component.items.map((_) => createComponentInstance(_))
398
+ }
399
+
400
+ if(component.props && Array.isArray(component.props.items)){
401
+ component.instance.items = component.props.items
402
+ }
403
+
404
+ return component
405
+ }
406
+
407
+ const deepObjectContainsObject = (outerObject, innerObject) => {
408
+ for (const key in innerObject) {
409
+ if (innerObject.hasOwnProperty(key)) {
410
+ if (typeof innerObject[key] === 'object' && typeof outerObject[key] === 'object') {
411
+ // If both properties are objects, recursively check them
412
+ if (!deepObjectContainsObject(outerObject[key], innerObject[key])) {
413
+ return false; // Nested objects do not match
414
+ }
415
+ } else {
416
+ if (outerObject[key] !== innerObject[key]) {
417
+ return false; // Property in innerObject doesn't exist in outerObject or values don't match
418
+ }
419
+ }
420
+ }
421
+ }
422
+ return true; // All properties and values in innerObject exist in outerObject
423
+ }
424
+
425
+ const removeStyleFromTag = (html) => {
426
+ const regex = /<[^>]+style="[^"]*"[^>]*>/g;
427
+
428
+ return html.replace(regex, (match) => {
429
+ return match.replace(/style="[^"]*"/, '');
430
+ });
431
+ }
432
+
433
+ const datasourceGet = async ({ Models }) => {
434
+
435
+ const models = []
436
+ for(let key in Models){
437
+
438
+ const columns = []
439
+ const attributes = Models[key].getAttributes()
440
+ for(let key in attributes){
441
+
442
+ let type
443
+ const fieldType = attributes[key].type.toString()
444
+
445
+ if(fieldType.startsWith('VARCHAR')){
446
+ type = 'string'
447
+ }
448
+ else if(fieldType.startsWith('INTEGER') || fieldType.startsWith('TINYINT')){
449
+ type = 'number'
450
+ }
451
+ else if(fieldType.startsWith('DATETIME')){
452
+ type = 'date'
453
+ }
454
+
455
+ if(type){
456
+ columns.push({
457
+ name: attributes[key].fieldName,
458
+ type,
459
+ })
460
+ }
461
+ }
462
+
463
+ models.push({
464
+ name: key,
465
+ columns
466
+ })
467
+ }
468
+
469
+ return {
470
+ models
471
+ }
472
+
473
+ }
474
+
475
+ const datasourceLoad = async ({ datasource, Models }) => {
476
+
477
+ const obj = {}
478
+
479
+ if(Array.isArray(datasource)){
480
+ for(let _datasource of datasource){
481
+
482
+ const Model = Models[_datasource.model]
483
+
484
+ const where = {}
485
+ if(Array.isArray(_datasource.filters)){
486
+ for(let filter of _datasource.filters){
487
+
488
+ switch(filter.operator){
489
+
490
+ case '=':
491
+ where[filter.key] = filter.value
492
+ break
493
+
494
+ }
495
+ }
496
+ }
497
+
498
+ const rows = await Model.findAll({
499
+ where,
500
+ limit: 20
501
+ })
502
+
503
+ obj[_datasource.key] = rows.length === 1 ? rows[0].toJSON() :
504
+ (rows.length === 0 ? {} : rows.map(_ => _.toJSON()))
505
+ }
506
+ }
507
+
508
+ return obj
509
+ }
510
+
511
+ const dayTimeRange = (params, value) => {
512
+ const dayjs = require('dayjs')
513
+
514
+ /*params = {
515
+ '*': [ [ '08:00', '12:00' ], [ '13:00', '18:00' ] ],
516
+ 'sat': [ [ '08:00', '12:00' ], [ '13:00', '14:00' ] ],
517
+ }
518
+ value = '2023-02-06 17:59:00'*/
519
+
520
+ if(!value)
521
+ value = dayjs().format('YYYY-MM-DD HH:mm:ss')
522
+
523
+ const curDay = dayjs(value).format('ddd').toLowerCase()
524
+ const curTime = dayjs(value).format('HH:mm')
525
+ const ranges = params[curDay] ?? params['*']
526
+
527
+ return (ranges ?? []).some((range) => {
528
+ return curTime >= range[0] && curTime <= range[1]
529
+ })
530
+ }
531
+
532
+ function capitalize(str) {
533
+ return (str ?? '').toLowerCase().replace(/\b\w/g, function(char) {
534
+ return char.toUpperCase();
535
+ });
536
+ }
537
+
538
+ const removeUnderscoredKey = (obj) => {
539
+ if (Array.isArray(obj)) {
540
+ return obj.map(removeUnderscoredKey);
541
+ }
542
+ else if (obj !== null && typeof obj === 'object') {
543
+ for(let key in obj){
544
+ if(key.startsWith('_')){
545
+ delete obj[key]
546
+ }
547
+ else if(Array.isArray(obj[key]) || (obj[key] !== null && typeof obj[key] === 'object')){
548
+ removeUnderscoredKey(obj[key])
549
+ }
550
+ }
551
+ }
552
+ return obj;
553
+ }
554
+
555
+ const hashMake = async (text) => {
556
+ const bcrypt = require('bcrypt')
557
+
558
+ return bcrypt.hash(text + (process.env.APP_KEY ?? ''), 10)
559
+ }
560
+
561
+ const hashCheck = (text, hash) => {
562
+ const bcrypt = require('bcrypt')
563
+
564
+ return bcrypt.compare(text + (process.env.APP_KEY ?? ''), hash)
565
+ }
566
+
567
+ const transactionWithRetry = async (sequelize, callback, opt = {}) => {
568
+ const { maxRetries = 99, delay = 1000 } = opt
569
+
570
+ let retries = 0
571
+ while(retries < maxRetries){
572
+ try{
573
+ return await sequelize.transaction(callback)
574
+ }
575
+ catch(e){
576
+ if(e.name === 'SequelizeConnectionAcquireTimeoutError' ||
577
+ (e.name === 'SequelizeDatabaseError' && [ 'ER_LOCK_DEADLOCK', '40001' ].includes(e.original.code))){
578
+ retries++
579
+
580
+ if(retries >= maxRetries){
581
+ throw e
582
+ }
583
+
584
+ await new Promise((resolve) => setTimeout(resolve, delay))
585
+ }
586
+
587
+ else{
588
+ throw e
589
+ }
590
+ }
591
+ }
592
+ }
593
+
594
+ const groupBy = (arr, key) => {
595
+ return arr.reduce((acc, item) => {
596
+ (acc[item[key]] = acc[item[key]] || []).push(item);
597
+ return acc;
598
+ }, {});
599
+ }
600
+
601
+ module.exports = {
602
+ capitalize,
603
+ ceil,
604
+ floor,
605
+ ftWildcard,
606
+ moveFile,
607
+ round,
608
+ sanitizeMobileNumber,
609
+ saveBase64,
610
+ saveBuffer,
611
+ saveFromUrl,
612
+ sleep,
613
+ strSlug,
614
+ strVars,
615
+ writeStorage,
616
+ bufferToStream,
617
+ sequelizeChunk,
618
+ getPresetSortWhereParams,
619
+ unflatten,
620
+ accessNestedObject,
621
+ createObjectFromPath,
622
+ generateStylesheet,
623
+ hexToRgb,
624
+ createComponentInstance,
625
+ deepObjectContainsObject,
626
+ removeStyleFromTag,
627
+ datasourceGet,
628
+ datasourceLoad,
629
+ dayTimeRange,
630
+ removeUnderscoredKey,
631
+ hashMake,
632
+ hashCheck,
633
+ transactionWithRetry,
634
+ groupBy
635
+ }