@mixd-id/web-scaffold 0.1.230406001
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/LICENSE +21 -0
- package/README.md +3 -0
- package/package.json +71 -0
- package/public/images/mixd-logo2.png +0 -0
- package/src/App.vue +17 -0
- package/src/components/Ahref.vue +34 -0
- package/src/components/Alert.vue +160 -0
- package/src/components/Button.vue +253 -0
- package/src/components/ButtonGroup.vue +101 -0
- package/src/components/Carousel.vue +293 -0
- package/src/components/ChatTyping.vue +69 -0
- package/src/components/Checkbox.vue +152 -0
- package/src/components/ContextMenu.vue +261 -0
- package/src/components/CopyToClipboard.vue +59 -0
- package/src/components/Countdown.vue +213 -0
- package/src/components/Datepicker.vue +312 -0
- package/src/components/Dropdown.vue +198 -0
- package/src/components/DynamicTemplate.vue +44 -0
- package/src/components/ErrorText.vue +36 -0
- package/src/components/Feed.vue +118 -0
- package/src/components/Gmaps.vue +227 -0
- package/src/components/Grid.vue +29 -0
- package/src/components/GridColumn.vue +31 -0
- package/src/components/HTMLEditor.vue +396 -0
- package/src/components/Image.vue +207 -0
- package/src/components/Image360.vue +140 -0
- package/src/components/ImageFullScreen.vue +101 -0
- package/src/components/ImagePreview.vue +71 -0
- package/src/components/ImportModal.vue +247 -0
- package/src/components/ListItem.vue +147 -0
- package/src/components/ListPage1.vue +1331 -0
- package/src/components/ListPage1Filter.vue +170 -0
- package/src/components/Modal.vue +253 -0
- package/src/components/OTPField.vue +126 -0
- package/src/components/Radio.vue +134 -0
- package/src/components/SearchButton.vue +57 -0
- package/src/components/Slider.vue +285 -0
- package/src/components/SplitPane.vue +129 -0
- package/src/components/Switch.vue +89 -0
- package/src/components/TabView.vue +106 -0
- package/src/components/TableView.vue +201 -0
- package/src/components/TableViewHead.vue +159 -0
- package/src/components/Tabs.vue +74 -0
- package/src/components/TextEditor.vue +85 -0
- package/src/components/Textarea.vue +184 -0
- package/src/components/Textbox.vue +200 -0
- package/src/components/Timepicker.vue +108 -0
- package/src/components/Toast.vue +93 -0
- package/src/components/VirtualScroll.vue +215 -0
- package/src/components/VirtualTable.vue +497 -0
- package/src/entry-client.js +27 -0
- package/src/entry-server.js +73 -0
- package/src/index.css +3 -0
- package/src/index.js +255 -0
- package/src/main.js +38 -0
- package/src/router.js +57 -0
- package/src/themes/default/index.js +200 -0
- package/src/utils/helpers.js +185 -0
- package/src/utils/helpers.mjs +197 -0
- package/src/utils/importer.js +156 -0
- package/src/utils/listpage1.js +1371 -0
- package/src/utils/selection.js +64 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
const md5 = require("md5");
|
|
2
|
+
const fs = require("fs");
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
const ceil = (num, precision = 0) => {
|
|
6
|
+
var p = Math.pow(10, precision)
|
|
7
|
+
var n = (num * p) * (1 + Number.EPSILON)
|
|
8
|
+
return Math.ceil(n) / p
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const floor = (num, precision = 0) => {
|
|
12
|
+
var p = Math.pow(10, precision)
|
|
13
|
+
var n = (num * p) * (1 + Number.EPSILON)
|
|
14
|
+
return Math.floor(n) / p
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const ftWildcard = (key) => {
|
|
18
|
+
const term = key.replace(/[\-\+\<\>\@\(\)\~]/, ' ', 'gi')
|
|
19
|
+
|
|
20
|
+
const searchTerms = []
|
|
21
|
+
term.split(' ').forEach((txt) => {
|
|
22
|
+
if(txt.length >= 3){
|
|
23
|
+
searchTerms.push(`+${txt}*`)
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
return searchTerms.join(' ')
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const moveFile = function(oldPath, newPath, callback) {
|
|
30
|
+
|
|
31
|
+
fs.rename(oldPath, newPath, function (err) {
|
|
32
|
+
if (err) {
|
|
33
|
+
if (err.code === 'EXDEV') {
|
|
34
|
+
copy();
|
|
35
|
+
} else {
|
|
36
|
+
callback(err);
|
|
37
|
+
}
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
callback();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
function copy() {
|
|
44
|
+
var readStream = fs.createReadStream(oldPath);
|
|
45
|
+
var writeStream = fs.createWriteStream(newPath);
|
|
46
|
+
|
|
47
|
+
readStream.on('error', callback);
|
|
48
|
+
writeStream.on('error', callback);
|
|
49
|
+
|
|
50
|
+
readStream.on('close', function () {
|
|
51
|
+
fs.unlink(oldPath, callback);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
readStream.pipe(writeStream);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const round = (num, precision = 0) => {
|
|
59
|
+
var p = Math.pow(10, precision)
|
|
60
|
+
var n = (num * p) * (1 + Number.EPSILON)
|
|
61
|
+
return Math.round(n) / p
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const sanitizeMobileNumber = (mobileNumber) => {
|
|
65
|
+
if(typeof mobileNumber !== 'string') return mobileNumber
|
|
66
|
+
|
|
67
|
+
if(mobileNumber.length > 0){
|
|
68
|
+
mobileNumber = mobileNumber.replace(/[\- ]/g, '')
|
|
69
|
+
if(mobileNumber.substring(0, 1) === '0') mobileNumber = '+62' + mobileNumber.substring(1)
|
|
70
|
+
if(mobileNumber.substring(0, 1) !== '+'){
|
|
71
|
+
if(mobileNumber.substring(0, 2) === '62')
|
|
72
|
+
mobileNumber = '+' + mobileNumber
|
|
73
|
+
else
|
|
74
|
+
mobileNumber = '+62' + mobileNumber
|
|
75
|
+
}
|
|
76
|
+
if(mobileNumber.length > 0){
|
|
77
|
+
mobileNumber = mobileNumber[0] + mobileNumber.slice(1).replace(/\D/g, '')
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return mobileNumber
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const saveBase64 = async(data, dir = '/storage/files/images') => {
|
|
85
|
+
if(data.indexOf(',') >= 0){
|
|
86
|
+
data = data.substring(data.indexOf(',') + 1)
|
|
87
|
+
}
|
|
88
|
+
const buffer = Buffer.from(data, 'base64');
|
|
89
|
+
return await saveBuffer(buffer, dir)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const saveBuffer = async(buffer, dir = '/storage/files/images') => {
|
|
93
|
+
|
|
94
|
+
const { fileTypeFromBuffer } = await import('file-type')
|
|
95
|
+
|
|
96
|
+
const type = await fileTypeFromBuffer(buffer)
|
|
97
|
+
|
|
98
|
+
const storagePath = process.env.ROOT_PATH + (dir)
|
|
99
|
+
const ext = type && type.ext ? '.' + type.ext : ''
|
|
100
|
+
const filename = md5(buffer) + ext
|
|
101
|
+
const to = storagePath + '/' + filename
|
|
102
|
+
|
|
103
|
+
fs.writeFileSync(to, buffer)
|
|
104
|
+
|
|
105
|
+
return filename
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const saveFromUrl = async(url, dir = '/storage/files/images') => {
|
|
109
|
+
|
|
110
|
+
const res = await axios({
|
|
111
|
+
method: 'GET',
|
|
112
|
+
url,
|
|
113
|
+
responseType: 'arraybuffer',
|
|
114
|
+
})
|
|
115
|
+
const buffer = Buffer.from(res.data)
|
|
116
|
+
return await saveBuffer(buffer, dir)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const sleep = ms => new Promise(r => setTimeout(r, ms))
|
|
120
|
+
|
|
121
|
+
const strSlug = (title, separator) => {
|
|
122
|
+
if (typeof separator == 'undefined') separator = '-';
|
|
123
|
+
|
|
124
|
+
// Convert all dashes/underscores into separator
|
|
125
|
+
var flip = separator === '-' ? '_' : '-';
|
|
126
|
+
title = title.replace(flip, separator);
|
|
127
|
+
|
|
128
|
+
// Remove all characters that are not the separator, letters, numbers, or whitespace.
|
|
129
|
+
title = title.toLowerCase()
|
|
130
|
+
.replace(new RegExp('[^a-z0-9' + separator + '\\s]', 'g'), '');
|
|
131
|
+
|
|
132
|
+
// Replace all separator characters and whitespace by a single separator
|
|
133
|
+
title = title.replace(new RegExp('[' + separator + '\\s]+', 'g'), separator);
|
|
134
|
+
|
|
135
|
+
return title.replace(new RegExp('^[' + separator + '\\s]+|[' + separator + '\\s]+$', 'g'),'');
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const strVars = (text, vars) => {
|
|
139
|
+
|
|
140
|
+
(text.match(/\{.*?(?=\})\}/gi) ?? []).forEach((match) => {
|
|
141
|
+
const key = match.substring(1, match.length - 1)
|
|
142
|
+
const value = vars[key] ?? ''
|
|
143
|
+
text = text.replace(match, value)
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
return text
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const writeStorage = (path, content, append = false) => {
|
|
150
|
+
|
|
151
|
+
if(path.startsWith('/')) path = path.substring(1)
|
|
152
|
+
|
|
153
|
+
if(append){
|
|
154
|
+
fs.appendFileSync(process.env.ROOT_PATH + `/storage/${path}`, content)
|
|
155
|
+
}
|
|
156
|
+
else{
|
|
157
|
+
fs.writeFileSync(process.env.ROOT_PATH + `/storage/${path}`, content)
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const bufferToStream = (buffer) => {
|
|
162
|
+
const { Duplex } = require('stream')
|
|
163
|
+
let stream = new Duplex()
|
|
164
|
+
stream.push(buffer)
|
|
165
|
+
stream.push(null)
|
|
166
|
+
return stream
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
module.exports = {
|
|
171
|
+
ceil,
|
|
172
|
+
floor,
|
|
173
|
+
ftWildcard,
|
|
174
|
+
moveFile,
|
|
175
|
+
round,
|
|
176
|
+
sanitizeMobileNumber,
|
|
177
|
+
saveBase64,
|
|
178
|
+
saveBuffer,
|
|
179
|
+
saveFromUrl,
|
|
180
|
+
sleep,
|
|
181
|
+
strSlug,
|
|
182
|
+
strVars,
|
|
183
|
+
writeStorage,
|
|
184
|
+
bufferToStream
|
|
185
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
|
|
2
|
+
const csvToArray = (str, delimiter = null) => {
|
|
3
|
+
|
|
4
|
+
if(!delimiter){
|
|
5
|
+
delimiter = str.indexOf(';') >= 0 ? ';' : ','
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
str = str.trim()
|
|
9
|
+
|
|
10
|
+
const headers = str.slice(0, str.indexOf("\n")).split(delimiter);
|
|
11
|
+
|
|
12
|
+
const rows = str.slice(str.indexOf("\n") + 1).split("\n");
|
|
13
|
+
|
|
14
|
+
const arr = rows.map(function (row) {
|
|
15
|
+
const values = row.split(delimiter);
|
|
16
|
+
let el = {}
|
|
17
|
+
if(values.length === headers.length){
|
|
18
|
+
el = headers.reduce(function (object, header, index) {
|
|
19
|
+
object[header] = values[index];
|
|
20
|
+
return object;
|
|
21
|
+
}, {});
|
|
22
|
+
}
|
|
23
|
+
return el;
|
|
24
|
+
})
|
|
25
|
+
.filter((_) => Object.keys(_).length > 0);
|
|
26
|
+
|
|
27
|
+
return arr;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const downsizeImage = async (url, targetWidth, imageType, quality, opt = {}) => {
|
|
31
|
+
|
|
32
|
+
let defaultImageType = 'image/jpeg'
|
|
33
|
+
|
|
34
|
+
if(url instanceof File){
|
|
35
|
+
|
|
36
|
+
defaultImageType = url.type
|
|
37
|
+
|
|
38
|
+
await (new Promise((resolve, reject) => {
|
|
39
|
+
var reader = new FileReader();
|
|
40
|
+
reader.addEventListener('load', () => {
|
|
41
|
+
url = reader.result
|
|
42
|
+
resolve()
|
|
43
|
+
}, false)
|
|
44
|
+
reader.addEventListener('error', (e) => {
|
|
45
|
+
reject(e)
|
|
46
|
+
})
|
|
47
|
+
reader.readAsDataURL(url);
|
|
48
|
+
}))
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return new Promise((resolve, reject) => {
|
|
52
|
+
|
|
53
|
+
const image = new Image()
|
|
54
|
+
image.addEventListener('load', () => {
|
|
55
|
+
|
|
56
|
+
const canvasWidth = image.width > targetWidth ? targetWidth : image.width
|
|
57
|
+
const canvasHeight = Math.round((image.height / image.width) * canvasWidth)
|
|
58
|
+
|
|
59
|
+
const canvas = document.createElement('canvas');
|
|
60
|
+
canvas.width = canvasWidth;
|
|
61
|
+
canvas.height = canvasHeight;
|
|
62
|
+
|
|
63
|
+
if(opt.constraint){
|
|
64
|
+
if(canvasWidth / canvasHeight !== opt.constraint)
|
|
65
|
+
reject(new Error('Image constraint error'))
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const ctx = canvas.getContext("2d");
|
|
69
|
+
ctx.drawImage(image, 0, 0, canvasWidth, canvasHeight);
|
|
70
|
+
|
|
71
|
+
canvas.toBlob((blob) => {
|
|
72
|
+
resolve(blob)
|
|
73
|
+
}, imageType ?? defaultImageType, quality ?? .8)
|
|
74
|
+
})
|
|
75
|
+
image.addEventListener('error', (e) => {
|
|
76
|
+
reject(e)
|
|
77
|
+
})
|
|
78
|
+
image.src = url
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const parseBoolean = function(exp){
|
|
83
|
+
return [ 'true', 1, true ].includes(typeof exp === 'string' ?
|
|
84
|
+
exp.toLowerCase() : exp)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const strVars = function(text, vars){
|
|
88
|
+
|
|
89
|
+
(text.match(/\{.*?(?=\})\}/gi) ?? []).forEach((match) => {
|
|
90
|
+
const key = match.substring(1, match.length - 1)
|
|
91
|
+
const value = vars[key] ?? ''
|
|
92
|
+
text = text.replace(match, value)
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
return text
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
let _QS
|
|
99
|
+
const urlQuery = function(){
|
|
100
|
+
|
|
101
|
+
if(!_QS){
|
|
102
|
+
_QS = new Proxy(new URLSearchParams(window.location.search), {
|
|
103
|
+
get: (searchParams, prop) => searchParams.get(prop),
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return _QS
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const getQueryString = function(key){
|
|
111
|
+
urlQuery()
|
|
112
|
+
|
|
113
|
+
if(typeof key === 'string'){
|
|
114
|
+
return _QS[key]
|
|
115
|
+
}
|
|
116
|
+
else if(Array.isArray(key)){
|
|
117
|
+
return key.map((k) => {
|
|
118
|
+
return _QS[k]
|
|
119
|
+
})
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
let __uid = new Date().getTime()
|
|
124
|
+
const uid = function(prefix){
|
|
125
|
+
return (prefix ?? '') + __uid++;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export {
|
|
129
|
+
downsizeImage,
|
|
130
|
+
uid,
|
|
131
|
+
observeInit,
|
|
132
|
+
csvToArray,
|
|
133
|
+
parseBoolean,
|
|
134
|
+
urlQuery,
|
|
135
|
+
getQueryString
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function observeInit(){
|
|
139
|
+
|
|
140
|
+
const intersectionObserver = new IntersectionObserver(
|
|
141
|
+
onIntersection,
|
|
142
|
+
{
|
|
143
|
+
rootMargin: '50px 50px 50px 50px',
|
|
144
|
+
threshold: 0.01,
|
|
145
|
+
}
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
function onIntersection(entries, observer) {
|
|
149
|
+
|
|
150
|
+
entries.forEach((entry) => {
|
|
151
|
+
if (entry.intersectionRatio === 0) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const item = entry.target
|
|
156
|
+
const key = item.__observeKey
|
|
157
|
+
const { type, callback } = observeCols[key]
|
|
158
|
+
|
|
159
|
+
if(typeof callback === 'function')
|
|
160
|
+
callback.apply(item)
|
|
161
|
+
|
|
162
|
+
if(type === 'once'){
|
|
163
|
+
observer.unobserve(item)
|
|
164
|
+
delete observeCols[key]
|
|
165
|
+
}
|
|
166
|
+
})
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const observeCols = {}
|
|
170
|
+
|
|
171
|
+
const once = function(el, callback)
|
|
172
|
+
{
|
|
173
|
+
if(typeof el.__observeKey !== 'undefined') return
|
|
174
|
+
|
|
175
|
+
intersectionObserver.observe(el)
|
|
176
|
+
|
|
177
|
+
const key = 'observe-' + uid()
|
|
178
|
+
observeCols[key] = { type:'once', callback }
|
|
179
|
+
el.__observeKey = key
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const always = function(el, callback)
|
|
183
|
+
{
|
|
184
|
+
if(typeof el.__observeKey !== 'undefined') return
|
|
185
|
+
|
|
186
|
+
intersectionObserver.observe(el)
|
|
187
|
+
|
|
188
|
+
const key = 'observe-' + uid()
|
|
189
|
+
observeCols[key] = { type:'one', callback }
|
|
190
|
+
el.__observeKey = key
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return {
|
|
194
|
+
once,
|
|
195
|
+
always
|
|
196
|
+
}
|
|
197
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
const md5 = require("md5");
|
|
2
|
+
const fs = require("fs");
|
|
3
|
+
const AdmZip = require("adm-zip");
|
|
4
|
+
const glob = require("glob");
|
|
5
|
+
const Exceljs = require("exceljs")
|
|
6
|
+
const { saveBuffer } = require('./helpers.js')
|
|
7
|
+
|
|
8
|
+
const analyseRequest = async(req) => {
|
|
9
|
+
|
|
10
|
+
const file = req.files[0]
|
|
11
|
+
const ext = file.originalname.split('.').slice(-1).pop()
|
|
12
|
+
|
|
13
|
+
let folderName = md5('motor-import-analyse' + new Date().getTime())
|
|
14
|
+
let xlsxFileType, xlsxFile
|
|
15
|
+
|
|
16
|
+
fs.mkdirSync(process.env.ROOT_PATH + '/storage/files/temp/' + folderName)
|
|
17
|
+
|
|
18
|
+
if(ext === 'zip'){
|
|
19
|
+
|
|
20
|
+
const zip = new AdmZip(file.buffer)
|
|
21
|
+
zip.extractAllTo(process.env.ROOT_PATH + '/storage/files/temp/' + folderName, true)
|
|
22
|
+
|
|
23
|
+
const res = glob.sync(process.env.ROOT_PATH + '/storage/files/temp/' + folderName + '/**/*(*.xlsx|*.csv)')
|
|
24
|
+
|
|
25
|
+
if(res.length < 1)
|
|
26
|
+
throw new Error('Invalid file')
|
|
27
|
+
else if(res.length > 1)
|
|
28
|
+
throw new Error('Invalid file')
|
|
29
|
+
else{
|
|
30
|
+
xlsxFile = res[0]
|
|
31
|
+
xlsxFileType = xlsxFile.split('.').slice(-1).pop()
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
else{
|
|
36
|
+
xlsxFileType = ext
|
|
37
|
+
const filename = await saveBuffer(file.buffer, '/storage/files/temp/' + folderName)
|
|
38
|
+
xlsxFile = process.env.ROOT_PATH + '/storage/files/temp/' + folderName + '/' + filename
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
const workbook = new Exceljs.Workbook();
|
|
43
|
+
switch(xlsxFileType){
|
|
44
|
+
|
|
45
|
+
case 'xlsx':
|
|
46
|
+
await workbook.xlsx.readFile(xlsxFile)
|
|
47
|
+
break
|
|
48
|
+
|
|
49
|
+
case 'csv':
|
|
50
|
+
await workbook.csv.readFile(xlsxFile, {
|
|
51
|
+
parserOptions: {
|
|
52
|
+
delimiter: ';'
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
break
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if(workbook.worksheets.length > 1)
|
|
59
|
+
throw new Error('Number of sheet allowed within file is 1')
|
|
60
|
+
else if(workbook.worksheets.length < 1)
|
|
61
|
+
throw new Error('Unable to read worksheet')
|
|
62
|
+
|
|
63
|
+
const worksheet = workbook.worksheets[0]
|
|
64
|
+
|
|
65
|
+
const columns = []
|
|
66
|
+
const header = worksheet.getRow(1)
|
|
67
|
+
if(!header)
|
|
68
|
+
throw new Error('Invalid file')
|
|
69
|
+
header.eachCell((cell) => {
|
|
70
|
+
columns.push(cell.value)
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
columns,
|
|
75
|
+
folderName,
|
|
76
|
+
xlsxFileType,
|
|
77
|
+
xlsxFile
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const importRequest = async(req) => {
|
|
82
|
+
|
|
83
|
+
const { columns, folderName, xlsxFileType, xlsxFile, keys } = req.body
|
|
84
|
+
|
|
85
|
+
keys.forEach((key) => {
|
|
86
|
+
if (key.required && !key.value)
|
|
87
|
+
throw new Error({name: ['Kolom ' + key.text + ' harus diisi']})
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
const rows = []
|
|
91
|
+
const cols = {}
|
|
92
|
+
const workbook = new Exceljs.Workbook();
|
|
93
|
+
switch(xlsxFileType){
|
|
94
|
+
|
|
95
|
+
case 'xlsx':
|
|
96
|
+
await workbook.xlsx.readFile(xlsxFile)
|
|
97
|
+
break
|
|
98
|
+
|
|
99
|
+
case 'csv':
|
|
100
|
+
await workbook.csv.readFile(xlsxFile, {
|
|
101
|
+
parserOptions: {
|
|
102
|
+
delimiter: ';'
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
break
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const worksheet = workbook.worksheets[0]
|
|
109
|
+
worksheet.eachRow((row, index) => {
|
|
110
|
+
if(index === 1){
|
|
111
|
+
row.eachCell((cell, index) => {
|
|
112
|
+
|
|
113
|
+
let mapped = false
|
|
114
|
+
keys.forEach((key) => {
|
|
115
|
+
if(key.value === cell.value){
|
|
116
|
+
cols[key.key] = index
|
|
117
|
+
mapped = true
|
|
118
|
+
}
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
if(!mapped){
|
|
122
|
+
cols[cell.value] = index
|
|
123
|
+
}
|
|
124
|
+
})
|
|
125
|
+
}
|
|
126
|
+
else{
|
|
127
|
+
const obj = {}
|
|
128
|
+
|
|
129
|
+
for(let key in cols){
|
|
130
|
+
const cell = row.getCell(cols[key])
|
|
131
|
+
obj[key] = cell.formulaType === 1 ? cell.result : cell.value
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
rows.push(obj)
|
|
135
|
+
}
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
//console.log(JSON.stringify(rows, null, 2))
|
|
139
|
+
|
|
140
|
+
const images = glob.sync(process.env.ROOT_PATH + '/storage/files/temp/' + folderName +
|
|
141
|
+
'/**/*(*.jpg|*.jpeg|*.png|*.webp)')
|
|
142
|
+
|
|
143
|
+
return {
|
|
144
|
+
...req.body,
|
|
145
|
+
rows,
|
|
146
|
+
images,
|
|
147
|
+
columns,
|
|
148
|
+
keys
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
module.exports = {
|
|
154
|
+
analyseRequest,
|
|
155
|
+
importRequest
|
|
156
|
+
}
|