@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.
- package/docs/components/Dashboard.md +56 -0
- package/log.txt +7 -0
- package/package.json +27 -19
- package/src/components/404.vue +61 -0
- package/src/components/AccountIcon.vue +19 -0
- package/src/components/Ahref.vue +1 -1
- package/src/components/Alert.vue +4 -13
- package/src/components/ArrayList.vue +49 -0
- package/src/components/Article.vue +24 -30
- package/src/components/Button.vue +83 -169
- package/src/components/Card.vue +257 -0
- package/src/components/Carousel.vue +61 -60
- package/src/components/Cart.vue +192 -0
- package/src/components/CartIcon.vue +89 -0
- package/src/components/ChartBar.vue +2 -3
- package/src/components/Checkbox.vue +20 -11
- package/src/components/Checkout.vue +373 -0
- package/src/components/CheckoutDelivery.vue +267 -0
- package/src/components/CodeEditor.vue +5 -16
- package/src/components/CollapsiblePanel.vue +70 -0
- package/src/components/ColorPicker.vue +12 -5
- package/src/components/ColorPicker2.vue +41 -19
- package/src/components/ColorPicker3.vue +100 -0
- package/src/components/Confirm.vue +9 -7
- package/src/components/ContextMenu.vue +122 -206
- package/src/components/ContextMenuItem.vue +53 -0
- package/src/components/Dashboard.vue +243 -0
- package/src/components/Dashboard2.vue +118 -0
- package/src/components/DashboardComponentSelector.vue +96 -0
- package/src/components/DashboardConfigs.vue +202 -0
- package/src/components/Datepicker.vue +102 -41
- package/src/components/DayTimeRange.vue +3 -2
- package/src/components/Dropdown.vue +7 -4
- package/src/components/Flex.vue +14 -40
- package/src/components/GHeatMaps.vue +2 -2
- package/src/components/Grid.vue +6 -6
- package/src/components/HTMLEditor.vue +27 -14
- package/src/components/Image.vue +62 -108
- package/src/components/ImagePreview.vue +14 -4
- package/src/components/ImageUploader.vue +114 -0
- package/src/components/ImportModal.vue +3 -3
- package/src/components/Link.vue +62 -6
- package/src/components/List.vue +528 -403
- package/src/components/ListContextMenu.vue +88 -0
- package/src/components/ListItem.vue +6 -4
- package/src/components/ListPage1.vue +14 -15
- package/src/components/ListView.vue +5 -6
- package/src/components/ListViewSettings.vue +2 -2
- package/src/components/LogViewerItem.vue +1 -1
- package/src/components/MarkdownEdit.vue +128 -0
- package/src/components/MarkdownPreview.vue +102 -0
- package/src/components/MenuItem1.vue +36 -0
- package/src/components/Modal.vue +95 -43
- package/src/components/MultiDropdown.vue +124 -0
- package/src/components/MultilineText.vue +1 -4
- package/src/components/OTPField.vue +40 -26
- package/src/components/ObjectTree.vue +1 -1
- package/src/components/PageBuilder.vue +3 -3
- package/src/components/Paragraph.vue +1 -2
- package/src/components/PresetSelectorFilterItem.vue +107 -95
- package/src/components/Radio.vue +1 -1
- package/src/components/SearchModal.vue +153 -0
- package/src/components/Slider.vue +1 -1
- package/src/components/Svg.vue +1 -1
- package/src/components/SvgEditor.vue +173 -0
- package/src/components/Switch.vue +4 -5
- package/src/components/Table.vue +2 -2
- package/src/components/TableView.vue +2 -3
- package/src/components/TableViewHead.vue +2 -2
- package/src/components/Tabs.vue +1 -1
- package/src/components/Testimonial.vue +2 -2
- package/src/components/Text.vue +7 -22
- package/src/components/TextEditor.vue +3 -3
- package/src/components/TextWithTag.vue +61 -30
- package/src/components/Textarea.vue +16 -22
- package/src/components/Textbox.vue +9 -19
- package/src/components/Timepicker.vue +25 -15
- package/src/components/Toast.vue +5 -3
- package/src/components/TreeMenu.vue +122 -0
- package/src/components/TreeView.vue +15 -10
- package/src/components/TreeView2.vue +38 -0
- package/src/components/TreeViewItem.vue +58 -29
- package/src/components/TreeViewItem2.vue +55 -0
- package/src/components/Uploader.vue +45 -0
- package/src/components/Video.vue +119 -0
- package/src/components/VirtualGrid.vue +24 -7
- package/src/components/VirtualTable.vue +363 -128
- package/src/configs/dashboard/data-table.js +9 -0
- package/src/configs/web-page-builder.js +118 -0
- package/src/directives/intersect.js +26 -0
- package/src/hooks/device.js +14 -0
- package/src/index.js +62 -107
- package/src/mixin/component.js +151 -67
- package/src/themes/default/index.js +118 -159
- package/src/utils/dashboard.js +22 -962
- package/src/utils/helpers.cjs +635 -0
- package/src/utils/helpers.js +91 -60
- package/src/utils/helpers.mjs +245 -12
- package/src/utils/importer.js +22 -3
- package/src/utils/list.mjs +1509 -0
- package/src/utils/preset-selector.cjs +1455 -0
- package/src/utils/preset-selector.js +489 -95
- package/src/utils/preset-selector.mjs +59 -20
- package/src/utils/queue.js +63 -0
- package/src/utils/web.mjs +120 -0
- package/src/utils/wss.js +38 -36
- package/src/utils/wss.mjs +24 -19
- package/src/widgets/AhrefSetting.vue +16 -13
- package/src/widgets/ArticleSetting.vue +15 -27
- package/src/widgets/BackgroundColorSetting.vue +153 -0
- package/src/widgets/BorderColorSetting.vue +57 -0
- package/src/widgets/BotEditor/BotEditorActions.vue +3 -2
- package/src/widgets/BotEditor/BotEditorSettings.vue +21 -0
- package/src/widgets/BotEditor.vue +35 -15
- package/src/widgets/ButtonSetting.vue +12 -13
- package/src/widgets/CarouselSetting.vue +33 -45
- package/src/widgets/CartSetting.vue +46 -0
- package/src/widgets/CheckoutSetting.vue +46 -0
- package/src/widgets/CollapsiblePanelSetting.vue +46 -0
- package/src/widgets/ColumnSelector.vue +29 -5
- package/src/widgets/ComponentSetting.vue +1 -1
- package/src/widgets/ComponentSetting2.vue +145 -236
- package/src/widgets/ComponentSetting3.vue +1 -1
- package/src/widgets/ContactForm.vue +3 -3
- package/src/widgets/ContactFormSetting.vue +41 -30
- package/src/widgets/Dashboard/BarChart.vue +47 -11
- package/src/widgets/Dashboard/BarChartSetting.vue +1 -1
- package/src/widgets/Dashboard/DataTable.vue +125 -0
- package/src/widgets/Dashboard/DataTableSetting.vue +243 -0
- package/src/widgets/Dashboard/DatasourceSelector.vue +1 -1
- package/src/widgets/Dashboard/Doughnut.vue +49 -7
- package/src/widgets/Dashboard/DoughnutSetting.vue +2 -2
- package/src/widgets/Dashboard/Metric.vue +78 -19
- package/src/widgets/Dashboard/MetricSetting.vue +81 -28
- package/src/widgets/Dashboard/Pie.vue +55 -6
- package/src/widgets/Dashboard/PieSetting.vue +1 -1
- package/src/widgets/Dashboard/PolarArea.vue +49 -7
- package/src/widgets/Dashboard/PolarAreaSetting.vue +1 -1
- package/src/widgets/Dashboard/SharingModal.vue +4 -5
- package/src/widgets/Dashboard/ViewSelector.vue +2 -2
- package/src/widgets/Dashboard/VirtualTableSetting.vue +121 -184
- package/src/widgets/{Dashboard.vue → Dashboard0.vue} +426 -343
- package/src/widgets/EmbeddedVideoSetting.vue +7 -5
- package/src/widgets/FAQ.vue +16 -3
- package/src/widgets/FAQSetting.vue +53 -47
- package/src/widgets/FeatureList.vue +3 -0
- package/src/widgets/FeatureListSetting.vue +112 -102
- package/src/widgets/FlexSetting.vue +83 -106
- package/src/widgets/GridSetting.vue +71 -196
- package/src/widgets/Header2.vue +34 -71
- package/src/widgets/Header2Setting.vue +95 -179
- package/src/widgets/HeaderSetting.vue +16 -18
- package/src/widgets/IconListSetting.vue +69 -65
- package/src/widgets/ImageSetting.vue +33 -60
- package/src/widgets/LinkSetting.vue +60 -37
- package/src/widgets/LinkSettingModal.vue +173 -0
- package/src/widgets/LogViewer.vue +1 -1
- package/src/widgets/MarginSetting.vue +2 -2
- package/src/widgets/MenuEditor.vue +1 -1
- package/src/widgets/MenuItem1Setting.vue +78 -0
- package/src/widgets/ModalSetting.vue +42 -44
- package/src/widgets/MultiValueSetting.vue +2 -2
- package/src/widgets/MultiValueSetting2.vue +78 -45
- package/src/widgets/OGSettingModal.vue +103 -0
- package/src/widgets/PaddingSetting.vue +2 -2
- package/src/widgets/ParagraphSetting.vue +16 -13
- package/src/widgets/PositionSetting.vue +209 -0
- package/src/widgets/PresetBar.vue +359 -210
- package/src/widgets/PresetBarPivot.vue +31 -19
- package/src/widgets/PresetSelector.vue +29 -17
- package/src/widgets/SearchModalSetting.vue +70 -0
- package/src/widgets/Share.vue +1 -2
- package/src/widgets/ShareSetting.vue +67 -60
- package/src/widgets/StyleSetting.vue +365 -150
- package/src/widgets/TestimonialSetting.vue +97 -88
- package/src/widgets/TextBlockSetting.vue +16 -13
- package/src/widgets/UserActionBuilder/UserActionConsole.vue +30 -10
- package/src/widgets/UserActionBuilder/UserActionOutput.vue +2 -2
- package/src/widgets/UserActionBuilder/UserActionOutputReply.vue +64 -87
- package/src/widgets/UserActionBuilder/UserActionProps.vue +3 -3
- package/src/widgets/UserActionBuilder.vue +4 -16
- package/src/widgets/WebComponentSelector.vue +15 -11
- package/src/widgets/WebLayoutSelector.vue +41 -270
- package/src/widgets/WebPageBuilder.vue +1019 -707
- package/src/widgets/WebPageBuilder2.vue +7 -7
- package/src/widgets/WebPageBuilder4/ButtonSetting.vue +0 -8
- package/src/widgets/WebPageBuilder4/CarouselSetting.vue +63 -7
- package/src/widgets/WebPageBuilder4/FlexAlignSetting.vue +3 -3
- package/src/widgets/WebPageBuilder4/FlexSetting.vue +1 -10
- package/src/widgets/WebPageBuilder4/MultiValueSetting.vue +2 -2
- package/src/widgets/WebPageBuilder4/PropertySetting.vue +0 -7
- package/src/widgets/WebPageBuilder4/WebPageComponentSelector.vue +1 -7
- package/src/widgets/WebPageBuilder4.vue +289 -575
- package/src/widgets/WebPageSelector.vue +1 -1
- package/src/widgets/YoutubeVideoSetting.vue +16 -13
- package/tailwind.config.js +3 -35
- package/docs/schema/user-action.json +0 -266
- package/src/App.vue +0 -25
- package/src/components/SearchButton.vue +0 -57
- package/src/entry-client.js +0 -27
- package/src/entry-server.js +0 -73
- package/src/events/event.js +0 -2
- package/src/main.js +0 -29
- package/src/mixin/website.js +0 -121
- package/src/router.js +0 -57
- package/src/widgets/MobileMenu.vue +0 -182
- package/src/widgets/WebPageBuilder4/ActionSetting.vue +0 -158
- package/src/widgets/WebPageBuilder4/ColorSetting.vue +0 -63
- package/src/widgets/WebPageBuilder4/DataSetting.vue +0 -92
- package/src/widgets/WebPageBuilder4/FontSizeSetting.vue +0 -76
- package/src/widgets/WebPageBuilder4/LinkSetting.vue +0 -68
- package/src/widgets/WebPageBuilder4/MobileMenuSetting.vue +0 -106
- package/src/widgets/WebPageBuilder4/Setting.vue +0 -73
- package/src/widgets/WebPageBuilder4/StyleSetting.vue +0 -77
- package/src/widgets/WebPageBuilder4/SvgSetting.vue +0 -207
- package/src/widgets/WebPageBuilder4/TextTransformSetting.vue +0 -70
- package/src/widgets/WebPageBuilder4/WebPageDataEdit.vue +0 -121
- package/test.json +0 -22
- /package/src/widgets/{Header1.vue → Header0.vue} +0 -0
- /package/src/widgets/{Header1Setting.vue → Header0Setting.vue} +0 -0
package/src/utils/helpers.js
CHANGED
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
const md5 = require("md5");
|
|
2
|
-
const fs = require("fs");
|
|
3
|
-
const { Op } = require('sequelize')
|
|
4
|
-
const axios = require('axios')
|
|
5
|
-
const dayjs = require('dayjs')
|
|
6
|
-
const { camelCase } = require('lodash')
|
|
7
|
-
|
|
8
|
-
|
|
9
1
|
const ceil = (num, precision = 0) => {
|
|
10
2
|
var p = Math.pow(10, precision)
|
|
11
3
|
var n = (num * p) * (1 + Number.EPSILON)
|
|
@@ -33,6 +25,7 @@ const ftWildcard = (key) => {
|
|
|
33
25
|
}
|
|
34
26
|
|
|
35
27
|
const moveFile = function(oldPath, newPath, callback) {
|
|
28
|
+
const fs = require("fs");
|
|
36
29
|
|
|
37
30
|
fs.rename(oldPath, newPath, function (err) {
|
|
38
31
|
if (err) {
|
|
@@ -47,6 +40,8 @@ const moveFile = function(oldPath, newPath, callback) {
|
|
|
47
40
|
});
|
|
48
41
|
|
|
49
42
|
function copy() {
|
|
43
|
+
const fs = require("fs");
|
|
44
|
+
|
|
50
45
|
var readStream = fs.createReadStream(oldPath);
|
|
51
46
|
var writeStream = fs.createWriteStream(newPath);
|
|
52
47
|
|
|
@@ -97,6 +92,9 @@ const saveBase64 = async(data, dir = '/storage/files/images') => {
|
|
|
97
92
|
|
|
98
93
|
const saveBuffer = async(buffer, dir = '/storage/files/images') => {
|
|
99
94
|
|
|
95
|
+
const fs = require("fs");
|
|
96
|
+
const md5 = require('md5')
|
|
97
|
+
|
|
100
98
|
const { fileTypeFromBuffer } = await import('file-type')
|
|
101
99
|
|
|
102
100
|
const type = await fileTypeFromBuffer(buffer)
|
|
@@ -112,6 +110,7 @@ const saveBuffer = async(buffer, dir = '/storage/files/images') => {
|
|
|
112
110
|
}
|
|
113
111
|
|
|
114
112
|
const saveFromUrl = async(url, dir = '/storage/files/images') => {
|
|
113
|
+
const axios = require('axios')
|
|
115
114
|
|
|
116
115
|
const res = await axios({
|
|
117
116
|
method: 'GET',
|
|
@@ -141,20 +140,21 @@ const strSlug = (title, separator) => {
|
|
|
141
140
|
return title.replace(new RegExp('^[' + separator + '\\s]+|[' + separator + '\\s]+$', 'g'),'');
|
|
142
141
|
}
|
|
143
142
|
|
|
144
|
-
const strVars = (text, vars
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}
|
|
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
|
+
})
|
|
152
150
|
|
|
153
151
|
return text
|
|
154
152
|
}
|
|
155
153
|
|
|
156
154
|
const writeStorage = (path, content, append = false) => {
|
|
157
155
|
|
|
156
|
+
const fs = require("fs");
|
|
157
|
+
|
|
158
158
|
if(path.startsWith('/')) path = path.substring(1)
|
|
159
159
|
|
|
160
160
|
if(append){
|
|
@@ -197,6 +197,8 @@ const sequelizeChunk = async (model, opt, callback, chunkSize = 5000) => {
|
|
|
197
197
|
|
|
198
198
|
const getPresetSortWhereParams = (order, afterItem) => {
|
|
199
199
|
|
|
200
|
+
const { Op } = require('sequelize')
|
|
201
|
+
|
|
200
202
|
if(order.filter((_) => _[0] === 'id').length <= 0){
|
|
201
203
|
order.push([ 'id', 'desc' ])
|
|
202
204
|
}
|
|
@@ -262,7 +264,7 @@ const unflatten = (flatObject) => {
|
|
|
262
264
|
}
|
|
263
265
|
|
|
264
266
|
const accessNestedObject = function(obj, path) {
|
|
265
|
-
if(!obj || typeof path !== 'string') return
|
|
267
|
+
if(!obj || typeof path !== 'string') return undefined
|
|
266
268
|
|
|
267
269
|
const keys = path.split('.');
|
|
268
270
|
let nestedObj = obj;
|
|
@@ -279,43 +281,6 @@ const accessNestedObject = function(obj, path) {
|
|
|
279
281
|
return nestedObj;
|
|
280
282
|
}
|
|
281
283
|
|
|
282
|
-
const accessNestedSequelize = async(obj, path, opt = { defaultValue:'' }) => {
|
|
283
|
-
if(!obj || typeof path !== 'string') return
|
|
284
|
-
|
|
285
|
-
const keys = path.split('.');
|
|
286
|
-
let value = obj;
|
|
287
|
-
|
|
288
|
-
for (let i in keys) {
|
|
289
|
-
const key = keys[i]
|
|
290
|
-
const hasNext = i < keys.length - 1
|
|
291
|
-
|
|
292
|
-
if(hasNext){
|
|
293
|
-
|
|
294
|
-
if(!value[key]){
|
|
295
|
-
try{
|
|
296
|
-
value = await value[camelCase(`get-${key}`)]()
|
|
297
|
-
}
|
|
298
|
-
catch(e){}
|
|
299
|
-
}
|
|
300
|
-
else{
|
|
301
|
-
value = value[key]
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
if(!value){
|
|
305
|
-
return
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
else{
|
|
310
|
-
value = key in value.dataValues ?
|
|
311
|
-
value[key] :
|
|
312
|
-
opt.defaultValue
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
return value;
|
|
317
|
-
}
|
|
318
|
-
|
|
319
284
|
const createObjectFromPath = (obj, path, value) => {
|
|
320
285
|
const keys = path.split('.');
|
|
321
286
|
|
|
@@ -544,6 +509,7 @@ const datasourceLoad = async ({ datasource, Models }) => {
|
|
|
544
509
|
}
|
|
545
510
|
|
|
546
511
|
const dayTimeRange = (params, value) => {
|
|
512
|
+
const dayjs = require('dayjs')
|
|
547
513
|
|
|
548
514
|
/*params = {
|
|
549
515
|
'*': [ [ '08:00', '12:00' ], [ '13:00', '18:00' ] ],
|
|
@@ -564,11 +530,72 @@ const dayTimeRange = (params, value) => {
|
|
|
564
530
|
}
|
|
565
531
|
|
|
566
532
|
function capitalize(str) {
|
|
567
|
-
return (str ?? '')
|
|
568
|
-
.
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
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
|
+
}, {});
|
|
572
599
|
}
|
|
573
600
|
|
|
574
601
|
module.exports = {
|
|
@@ -591,7 +618,6 @@ module.exports = {
|
|
|
591
618
|
getPresetSortWhereParams,
|
|
592
619
|
unflatten,
|
|
593
620
|
accessNestedObject,
|
|
594
|
-
accessNestedSequelize,
|
|
595
621
|
createObjectFromPath,
|
|
596
622
|
generateStylesheet,
|
|
597
623
|
hexToRgb,
|
|
@@ -601,4 +627,9 @@ module.exports = {
|
|
|
601
627
|
datasourceGet,
|
|
602
628
|
datasourceLoad,
|
|
603
629
|
dayTimeRange,
|
|
630
|
+
removeUnderscoredKey,
|
|
631
|
+
hashMake,
|
|
632
|
+
hashCheck,
|
|
633
|
+
transactionWithRetry,
|
|
634
|
+
groupBy
|
|
604
635
|
}
|
package/src/utils/helpers.mjs
CHANGED
|
@@ -80,8 +80,7 @@ const downsizeImage = async (url, targetWidth, imageType, quality, opt = {}) =>
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
const parseBoolean = function(exp){
|
|
83
|
-
return [ 'true', 1
|
|
84
|
-
exp.toLowerCase() : exp)
|
|
83
|
+
return [ 'true', '1' ].includes(`${(exp ?? '')}`.toLowerCase())
|
|
85
84
|
}
|
|
86
85
|
|
|
87
86
|
const strVars = function(text, vars, opt = { emptyUndefined:true }){
|
|
@@ -319,6 +318,17 @@ function unslugAndCapitalize(slug) {
|
|
|
319
318
|
.join(' ');
|
|
320
319
|
}
|
|
321
320
|
|
|
321
|
+
function slugify(text, separator = '-') {
|
|
322
|
+
return text
|
|
323
|
+
.toString() // Ensure the input is a string
|
|
324
|
+
.normalize('NFD') // Normalize to decompose diacritic marks
|
|
325
|
+
.replace(/[\u0300-\u036f]/g, '') // Remove diacritic marks
|
|
326
|
+
.replace(/[^a-zA-Z0-9\s-]/g, '') // Remove special characters
|
|
327
|
+
.trim() // Trim leading/trailing spaces
|
|
328
|
+
.replace(/\s+/g, separator) // Replace spaces with dashes
|
|
329
|
+
.toLowerCase(); // Convert to lowercase
|
|
330
|
+
}
|
|
331
|
+
|
|
322
332
|
const hexToRgb = (hex) => {
|
|
323
333
|
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
324
334
|
return result ? {
|
|
@@ -361,7 +371,7 @@ function applyDatasourceReplacer(value, datasource){
|
|
|
361
371
|
}
|
|
362
372
|
|
|
363
373
|
function capitalize(str) {
|
|
364
|
-
return str.replace(/\b\w/g, function(char) {
|
|
374
|
+
return (str ?? '').toLowerCase().replace(/\b\w/g, function(char) {
|
|
365
375
|
return char.toUpperCase();
|
|
366
376
|
});
|
|
367
377
|
}
|
|
@@ -372,24 +382,237 @@ const round = (num, precision = 0) => {
|
|
|
372
382
|
return Math.round(n) / p
|
|
373
383
|
}
|
|
374
384
|
|
|
375
|
-
|
|
376
|
-
|
|
385
|
+
const invokeAfterIdle = (callback, opt) => {
|
|
386
|
+
|
|
377
387
|
let timeoutId
|
|
388
|
+
const { delay = 500 } = opt ?? {}
|
|
378
389
|
|
|
379
390
|
return function(){
|
|
380
|
-
if(invokeAfterIdleStore.includes(callback))
|
|
381
|
-
return
|
|
382
|
-
|
|
383
|
-
invokeAfterIdleStore.push(callback)
|
|
384
|
-
|
|
385
391
|
window.clearTimeout(timeoutId)
|
|
386
392
|
timeoutId = window.setTimeout(() => {
|
|
387
393
|
callback.apply(this, arguments)
|
|
388
|
-
invokeAfterIdleStore.splice(invokeAfterIdleStore.indexOf(callback), 1)
|
|
389
394
|
}, delay)
|
|
390
395
|
}
|
|
391
396
|
}
|
|
392
397
|
|
|
398
|
+
const queueForLater = (params) => {
|
|
399
|
+
|
|
400
|
+
const instance = {
|
|
401
|
+
delay: 1200,
|
|
402
|
+
...params,
|
|
403
|
+
|
|
404
|
+
items: [],
|
|
405
|
+
timeoutId: null,
|
|
406
|
+
|
|
407
|
+
run: () => {
|
|
408
|
+
const items = instance.items.splice(0, instance.items.length);
|
|
409
|
+
typeof instance.pop === 'function' ? instance.pop(items) : null;
|
|
410
|
+
instance.timeoutId = null
|
|
411
|
+
},
|
|
412
|
+
|
|
413
|
+
queue(item) {
|
|
414
|
+
if(Array.isArray(item))
|
|
415
|
+
instance.items.push(...item)
|
|
416
|
+
else
|
|
417
|
+
instance.items.push(item)
|
|
418
|
+
|
|
419
|
+
if(!instance.timeoutId)
|
|
420
|
+
instance.timeoutId = window.setTimeout(instance.run, instance.delay);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
return instance.queue
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
const queueForLaterWithKey = (params) => {
|
|
428
|
+
|
|
429
|
+
const instance = {
|
|
430
|
+
delay: 1200,
|
|
431
|
+
...params,
|
|
432
|
+
|
|
433
|
+
items: {},
|
|
434
|
+
timeoutId: {},
|
|
435
|
+
|
|
436
|
+
run: (key) => {
|
|
437
|
+
const items = instance.items[key].splice(0, instance.items[key].length);
|
|
438
|
+
//console.log('run', key, items)
|
|
439
|
+
typeof instance.pop === 'function' ? instance.pop(items) : null;
|
|
440
|
+
instance.timeoutId[key] = false
|
|
441
|
+
},
|
|
442
|
+
|
|
443
|
+
queue(key, item) {
|
|
444
|
+
if(!instance.items[key]){
|
|
445
|
+
instance.items[key] = []
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
if(Array.isArray(item))
|
|
449
|
+
instance.items[key].push(...item)
|
|
450
|
+
else
|
|
451
|
+
instance.items[key].push(item)
|
|
452
|
+
|
|
453
|
+
//console.log('queue', key, item, instance.items[key])
|
|
454
|
+
|
|
455
|
+
if(!instance.timeoutId[key])
|
|
456
|
+
instance.timeoutId[key] = window.setTimeout(() => instance.run(key), instance.delay);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
return instance.queue
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
const transactionWithRetry = async (sequelize, callback, opt = {}) => {
|
|
464
|
+
const { maxRetries = 99, delay = 1000, rollback = false } = opt
|
|
465
|
+
|
|
466
|
+
let retries = 0
|
|
467
|
+
while(retries < maxRetries){
|
|
468
|
+
try{
|
|
469
|
+
const transaction = await sequelize.transaction()
|
|
470
|
+
const res = await callback(transaction)
|
|
471
|
+
|
|
472
|
+
if(rollback)
|
|
473
|
+
await transaction.rollback()
|
|
474
|
+
else
|
|
475
|
+
await transaction.commit()
|
|
476
|
+
|
|
477
|
+
return res
|
|
478
|
+
}
|
|
479
|
+
catch(e){
|
|
480
|
+
if(e.name === 'SequelizeConnectionAcquireTimeoutError' ||
|
|
481
|
+
(e.name === 'SequelizeDatabaseError' && [ 'ER_LOCK_DEADLOCK', '40001' ].includes(e.original.code))){
|
|
482
|
+
retries++
|
|
483
|
+
|
|
484
|
+
if(retries >= maxRetries){
|
|
485
|
+
throw e
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
await new Promise((resolve) => setTimeout(resolve, delay))
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
else{
|
|
492
|
+
throw e
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
const groupBy = (arr, key) => {
|
|
499
|
+
return arr.reduce((acc, item) => {
|
|
500
|
+
(acc[item[key]] = acc[item[key]] || []).push(item);
|
|
501
|
+
return acc;
|
|
502
|
+
}, {});
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
const arrayPush = (arr, items, opt = { update:true }) => {
|
|
506
|
+
if(!Array.isArray(arr)) return
|
|
507
|
+
if(!Array.isArray(items)) items = [ items ]
|
|
508
|
+
if(!opt.key){
|
|
509
|
+
opt.key = items[0] && items[0].uid ? 'uid' : 'id'
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
if(!Array.isArray(opt.key)){
|
|
513
|
+
opt.key = [ opt.key ]
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
for(let item of items){
|
|
517
|
+
if(!item) continue
|
|
518
|
+
|
|
519
|
+
const index = arr.findIndex((_) => {
|
|
520
|
+
for(let key of opt.key){
|
|
521
|
+
if(_[key] !== item[key]){
|
|
522
|
+
return false
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
return true
|
|
526
|
+
})
|
|
527
|
+
|
|
528
|
+
if(index >= 0){
|
|
529
|
+
if(opt.update !== false){
|
|
530
|
+
Object.assign(arr[index], item)
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
else{
|
|
534
|
+
arr.push(item)
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
const arrayRemove = (arr, items, opt = {}) => {
|
|
540
|
+
if(!Array.isArray(arr)) return
|
|
541
|
+
if(!Array.isArray(items)) items = [ items ]
|
|
542
|
+
if(!opt.key){
|
|
543
|
+
opt.key = items[0] && items[0].uid ? 'uid' : 'id'
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
items = groupBy(items, opt.key)
|
|
547
|
+
|
|
548
|
+
for(let i = arr.length - 1 ; i >= 0 ; i--){
|
|
549
|
+
if(!arr[i]) continue
|
|
550
|
+
|
|
551
|
+
if(arr[i][opt.key] in items){
|
|
552
|
+
arr.splice(i, 1)
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
const arrayUnshift = (arr, items, opt = { update:true }) => {
|
|
558
|
+
if(!Array.isArray(arr)) return
|
|
559
|
+
if(!Array.isArray(items)) items = [ items ]
|
|
560
|
+
if(!opt.key){
|
|
561
|
+
opt.key = items[0] && items[0].uid ? 'uid' : 'id'
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
if(!Array.isArray(opt.key)){
|
|
565
|
+
opt.key = [ opt.key ]
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
for(let item of items){
|
|
569
|
+
if(!item) continue
|
|
570
|
+
|
|
571
|
+
const index = arr.findIndex((_) => {
|
|
572
|
+
for(let key of opt.key){
|
|
573
|
+
if(_[key] !== item[key]){
|
|
574
|
+
return false
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
return true
|
|
578
|
+
})
|
|
579
|
+
|
|
580
|
+
if(index >= 0){
|
|
581
|
+
if(opt.update !== false){
|
|
582
|
+
Object.assign(arr[index], item)
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
else{
|
|
586
|
+
arr.unshift(item)
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
function addHash(hash, newHash, prefix = '_'){
|
|
592
|
+
const cleaned = hash.split('#')
|
|
593
|
+
.filter(_=>_).map(_ => `#${_}`)
|
|
594
|
+
.filter(_ => !_.startsWith(prefix))
|
|
595
|
+
|
|
596
|
+
cleaned.push(newHash)
|
|
597
|
+
|
|
598
|
+
return cleaned.join('')
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
const downloadUrl = (url, as) => {
|
|
602
|
+
url = url + (url.indexOf('?') >= 0 ? '&' : '?') + 'nocache=' + new Date().getTime()
|
|
603
|
+
|
|
604
|
+
const downloader = document.createElement('a')
|
|
605
|
+
downloader.setAttribute('href', url)
|
|
606
|
+
downloader.target = '_blank'
|
|
607
|
+
if(as) downloader.download = as
|
|
608
|
+
document.body.appendChild(downloader)
|
|
609
|
+
|
|
610
|
+
downloader.click()
|
|
611
|
+
|
|
612
|
+
window.setTimeout(() => {
|
|
613
|
+
document.body.removeChild(downloader)
|
|
614
|
+
}, 100)
|
|
615
|
+
}
|
|
393
616
|
|
|
394
617
|
export {
|
|
395
618
|
capitalize,
|
|
@@ -414,9 +637,19 @@ export {
|
|
|
414
637
|
removeStyleFromTag,
|
|
415
638
|
createFormData,
|
|
416
639
|
unslugAndCapitalize,
|
|
640
|
+
slugify,
|
|
417
641
|
applyDatasourceReplacer,
|
|
418
642
|
strVars,
|
|
419
|
-
invokeAfterIdle
|
|
643
|
+
invokeAfterIdle,
|
|
644
|
+
queueForLater,
|
|
645
|
+
queueForLaterWithKey,
|
|
646
|
+
transactionWithRetry,
|
|
647
|
+
groupBy,
|
|
648
|
+
arrayPush,
|
|
649
|
+
arrayRemove,
|
|
650
|
+
arrayUnshift,
|
|
651
|
+
addHash,
|
|
652
|
+
downloadUrl
|
|
420
653
|
}
|
|
421
654
|
|
|
422
655
|
function observeInit(){
|
package/src/utils/importer.js
CHANGED
|
@@ -5,6 +5,27 @@ const glob = require("glob");
|
|
|
5
5
|
const Exceljs = require("exceljs")
|
|
6
6
|
const { saveBuffer, unflatten } = require('./helpers.js')
|
|
7
7
|
|
|
8
|
+
const getCellText = (cell) => {
|
|
9
|
+
if(!cell) return ''
|
|
10
|
+
|
|
11
|
+
let value = ''
|
|
12
|
+
if(cell.formulaType === 1){
|
|
13
|
+
value = cell.result
|
|
14
|
+
}
|
|
15
|
+
else if(cell.value?.error){
|
|
16
|
+
value = '#ERR'
|
|
17
|
+
}
|
|
18
|
+
else if(cell.value?.hyperlink){
|
|
19
|
+
value = cell.value.hyperlink
|
|
20
|
+
}
|
|
21
|
+
else{
|
|
22
|
+
value = cell.value
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return value
|
|
26
|
+
|
|
27
|
+
}
|
|
28
|
+
|
|
8
29
|
const analyseRequest = async(req) => {
|
|
9
30
|
|
|
10
31
|
const file = req.files[0]
|
|
@@ -161,9 +182,7 @@ const importRequest = async(req) => {
|
|
|
161
182
|
const key = keys[idx]
|
|
162
183
|
if(key.value && columnAddress[key.value]){
|
|
163
184
|
const cell = row.getCell(columnAddress[key.value])
|
|
164
|
-
|
|
165
|
-
if(value && value.error) value = ''
|
|
166
|
-
obj[key.key] = value
|
|
185
|
+
obj[key.key] = getCellText(cell)
|
|
167
186
|
}
|
|
168
187
|
}
|
|
169
188
|
|