@mixd-id/web-scaffold 0.1.230406302 → 0.1.230406304
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/package.json +1 -3
- package/src/components/Alert.vue +9 -3
- package/src/components/Button.vue +4 -1
- package/src/components/ImagePreview.vue +1 -1
- package/src/components/List.vue +2 -2
- package/src/index.js +84 -31
- package/src/themes/default/index.js +4 -2
- package/src/utils/wss.js +27 -18
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mixd-id/web-scaffold",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.230406304",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "vite serve",
|
|
7
7
|
"build": "vite build",
|
|
@@ -39,7 +39,6 @@
|
|
|
39
39
|
"@tailwindcss/line-clamp": "^0.4.0",
|
|
40
40
|
"@vueuse/core": "^9.0.2",
|
|
41
41
|
"adm-zip": "^0.5.10",
|
|
42
|
-
"axios": "^1.3.4",
|
|
43
42
|
"chart.js": "^4.2.1",
|
|
44
43
|
"compression": "^1.7.4",
|
|
45
44
|
"cookie-parser": "^1.4.6",
|
|
@@ -57,7 +56,6 @@
|
|
|
57
56
|
"pinia": "^2.0.14",
|
|
58
57
|
"prismjs": "^1.28.0",
|
|
59
58
|
"redis": "^4.6.13",
|
|
60
|
-
"sequelize": "^6.37.3",
|
|
61
59
|
"serve-static": "^1.15.0",
|
|
62
60
|
"tailwindcss": "^3.2.4",
|
|
63
61
|
"vue": "^3.2.25",
|
package/src/components/Alert.vue
CHANGED
|
@@ -130,8 +130,14 @@ export default{
|
|
|
130
130
|
|
|
131
131
|
message(){
|
|
132
132
|
if(this.err.errors){
|
|
133
|
-
return typeof this.err.errors === 'object' &&
|
|
134
|
-
Object.
|
|
133
|
+
return typeof this.err.errors === 'object' &&
|
|
134
|
+
Object.keys(this.err.errors).length > 0 ?
|
|
135
|
+
Object.values(this.err.errors).map(_ => {
|
|
136
|
+
if(Array.isArray(_))
|
|
137
|
+
return _
|
|
138
|
+
return JSON.stringify(_)
|
|
139
|
+
})
|
|
140
|
+
.join("\n"):
|
|
135
141
|
this.err.errors
|
|
136
142
|
}
|
|
137
143
|
else if(this.err.reason){
|
|
@@ -216,7 +222,7 @@ export default{
|
|
|
216
222
|
}
|
|
217
223
|
|
|
218
224
|
.details{
|
|
219
|
-
@apply flex-1 flex flex-col gap-4 overflow-
|
|
225
|
+
@apply flex-1 flex flex-col gap-4 overflow-auto min-h-[1.6rem] self-stretch;
|
|
220
226
|
}
|
|
221
227
|
.details::-webkit-scrollbar {
|
|
222
228
|
display: none;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<button :class="compClass" :disabled="isDisabled" @click="onClick" :style="computedStyle"
|
|
2
|
+
<button :class="compClass" :disabled="isDisabled" @click="onClick" :style="computedStyle"
|
|
3
|
+
v-tooltip="disabledText">
|
|
3
4
|
<slot>{{ text }}</slot>
|
|
4
5
|
<div v-if="isLoading" :class="$style.loadingPane">
|
|
5
6
|
<svg :class="$style.spinner" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
|
@@ -38,6 +39,8 @@ export default{
|
|
|
38
39
|
|
|
39
40
|
width: Array,
|
|
40
41
|
|
|
42
|
+
disabledText: String
|
|
43
|
+
|
|
41
44
|
},
|
|
42
45
|
|
|
43
46
|
computed:{
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<Modal :state="isOpen" width="400" height="400" :class="$style.previewModal">
|
|
3
3
|
<div class="flex-1 flex flex-col">
|
|
4
4
|
<div class="flex flex-row justify-end items-center p-3">
|
|
5
|
-
<a v-if="download" :href="imageUrl" download>
|
|
5
|
+
<a v-if="download" :href="imageUrl" target="_blank" download>
|
|
6
6
|
<svg xmlns="http://www.w3.org/2000/svg" width="42" height="42" viewBox="0 0 24 24" class="fill-text"><path class="primary" d="M15 15v-3a3 3 0 0 0-6 0v3H6a4 4 0 0 1-.99-7.88 5.5 5.5 0 0 1 10.86-.82A4.49 4.49 0 0 1 22 10.5a4.5 4.5 0 0 1-4.5 4.5H15z"/><path class="secondary" d="M11 18.59V12a1 1 0 0 1 2 0v6.59l1.3-1.3a1 1 0 0 1 1.4 1.42l-3 3a1 1 0 0 1-1.4 0l-3-3a1 1 0 0 1 1.4-1.42l1.3 1.3z"/></svg>
|
|
7
7
|
</a>
|
|
8
8
|
<button class="ml-3" @click="close">
|
package/src/components/List.vue
CHANGED
|
@@ -379,7 +379,7 @@ export default{
|
|
|
379
379
|
},
|
|
380
380
|
|
|
381
381
|
loadPreset(){
|
|
382
|
-
if(!(
|
|
382
|
+
if(!Object.keys(this.$route.query).map(_ => _.toLowerCase()).includes('reset')){
|
|
383
383
|
if(this.presetKey){
|
|
384
384
|
return this.socket.send('user.preset', { key:this.presetKey })
|
|
385
385
|
.then(config => {
|
|
@@ -394,7 +394,7 @@ export default{
|
|
|
394
394
|
|
|
395
395
|
const query = {}
|
|
396
396
|
for(let key in this.$route.query){
|
|
397
|
-
if(key !== 'reset')
|
|
397
|
+
if(key.toLowerCase() !== 'reset')
|
|
398
398
|
query[key] = this.$route.query[key]
|
|
399
399
|
}
|
|
400
400
|
this.$router.replace({
|
package/src/index.js
CHANGED
|
@@ -330,42 +330,60 @@ export default{
|
|
|
330
330
|
const tooltips = {}
|
|
331
331
|
|
|
332
332
|
app.directive('tooltip', (el, binding) => {
|
|
333
|
-
el.addEventListener('mouseover', () => {
|
|
334
333
|
|
|
335
|
-
|
|
336
|
-
const tooltip = document.createElement('div')
|
|
337
|
-
tooltip.classList.add('tooltip')
|
|
338
|
-
tooltip.innerHTML = binding.value
|
|
339
|
-
document.body.appendChild(tooltip)
|
|
334
|
+
if(!el.getAttribute('data-tooltip')) {
|
|
340
335
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
336
|
+
const uid = uniqid()
|
|
337
|
+
el.setAttribute('data-tooltip', uid)
|
|
338
|
+
|
|
339
|
+
const tooltip = document.createElement('div')
|
|
340
|
+
tooltip.classList.add('tooltip')
|
|
341
|
+
document.body.appendChild(tooltip)
|
|
342
|
+
tooltips[uid] = {
|
|
343
|
+
el: tooltip,
|
|
344
|
+
text: binding.value
|
|
344
345
|
}
|
|
345
346
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
347
|
+
el.addEventListener('mouseover', () => {
|
|
348
|
+
const { text } = tooltips[uid]
|
|
349
|
+
if(!text) return
|
|
350
|
+
|
|
351
|
+
tooltip.innerHTML = text
|
|
352
|
+
|
|
353
|
+
window.setTimeout(() => {
|
|
354
|
+
if(el.getAttribute('data-tooltip-open')){
|
|
355
|
+
const rect = el.getBoundingClientRect()
|
|
356
|
+
if(rect && rect.width > 0){
|
|
357
|
+
|
|
358
|
+
if(rect.y + rect.height + tooltip.clientHeight > window.innerHeight){
|
|
359
|
+
delete tooltip.style.top
|
|
360
|
+
tooltip.style.bottom = ((window.innerHeight - rect.y) + 10) + 'px'
|
|
361
|
+
tooltip.style.transformOrigin = 'left bottom'
|
|
362
|
+
tooltip.style.left = rect.x + 'px'
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
else{
|
|
366
|
+
delete tooltip.style.bottom
|
|
367
|
+
tooltip.style.top = (rect.y + rect.height + 10) + 'px'
|
|
368
|
+
tooltip.style.transformOrigin = 'left top'
|
|
369
|
+
tooltip.style.left = rect.x + 'px'
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
tooltip.classList.add('active')
|
|
373
|
+
}
|
|
355
374
|
}
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
el.removeAttribute('data-tooltip-open')
|
|
363
|
-
const uid = el.getAttribute('data-tooltip')
|
|
364
|
-
const tooltip = tooltips[uid]
|
|
365
|
-
if(tooltip){
|
|
375
|
+
}, 1000)
|
|
376
|
+
el.setAttribute('data-tooltip-open', true)
|
|
377
|
+
})
|
|
378
|
+
|
|
379
|
+
el.addEventListener('mouseout', () => {
|
|
380
|
+
el.removeAttribute('data-tooltip-open')
|
|
366
381
|
tooltip.classList.remove('active')
|
|
367
|
-
}
|
|
368
|
-
}
|
|
382
|
+
})
|
|
383
|
+
}
|
|
384
|
+
else{
|
|
385
|
+
tooltips[el.getAttribute('data-tooltip')].text = binding.value
|
|
386
|
+
}
|
|
369
387
|
})
|
|
370
388
|
|
|
371
389
|
const privateVars = {}
|
|
@@ -416,6 +434,41 @@ export default{
|
|
|
416
434
|
}
|
|
417
435
|
return privateVars.isDebugMode
|
|
418
436
|
}
|
|
437
|
+
app.config.globalProperties.$validate = (obj, rules) => {
|
|
438
|
+
|
|
439
|
+
const errors = {}
|
|
440
|
+
|
|
441
|
+
for(let key in rules){
|
|
442
|
+
|
|
443
|
+
let value
|
|
444
|
+
if(typeof rules[key] === 'string'){
|
|
445
|
+
value = rules[key].split('|')
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
const keyErrors = []
|
|
449
|
+
for(let _value of value){
|
|
450
|
+
|
|
451
|
+
switch(_value){
|
|
452
|
+
|
|
453
|
+
case 'required':
|
|
454
|
+
if(!(key in obj)){
|
|
455
|
+
keyErrors.push(`${key} is required`)
|
|
456
|
+
}
|
|
457
|
+
break
|
|
458
|
+
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
if(keyErrors.length > 0){
|
|
464
|
+
errors[key] = keyErrors
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
return Object.keys(errors).length > 0 ?
|
|
469
|
+
errors :
|
|
470
|
+
undefined
|
|
471
|
+
}
|
|
419
472
|
|
|
420
473
|
if(typeof window !== 'undefined') {
|
|
421
474
|
|
|
@@ -632,6 +685,6 @@ export default{
|
|
|
632
685
|
app.component('TypographySetting', defineAsyncComponent(() => import("./widgets/TypographySetting.vue")))
|
|
633
686
|
app.component('FiltersSetting', defineAsyncComponent(() => import("./widgets/FiltersSetting.vue")))
|
|
634
687
|
app.component('MenuEditor', defineAsyncComponent(() => import("./widgets/MenuEditor.vue")))
|
|
635
|
-
}
|
|
688
|
+
}
|
|
636
689
|
|
|
637
690
|
}
|
|
@@ -170,11 +170,13 @@ const plugin = Plugin(function({ addBase, addUtilities, config, theme }) {
|
|
|
170
170
|
position: "fixed",
|
|
171
171
|
'z-index': 1000,
|
|
172
172
|
transform: 'scale(0)',
|
|
173
|
-
padding: '
|
|
173
|
+
padding: '1rem',
|
|
174
174
|
background: 'rgb(var(--text-50))',
|
|
175
175
|
'border-radius': '5px',
|
|
176
176
|
transition: 'transform .2s ease-in-out',
|
|
177
|
-
'
|
|
177
|
+
'white-space': 'pre-line',
|
|
178
|
+
'text-align': 'left',
|
|
179
|
+
'line-height': '1.8rem',
|
|
178
180
|
},
|
|
179
181
|
|
|
180
182
|
'.tooltip.active': {
|
package/src/utils/wss.js
CHANGED
|
@@ -97,7 +97,11 @@ class WSS extends EventEmitter2{
|
|
|
97
97
|
this._opt = opt
|
|
98
98
|
this._instance = new WebSocket.Server(opt);
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
console.log('WSS', process.env.REDIS_HOST, process.env.REDIS_PORT)
|
|
101
|
+
this._client = redis.createClient({
|
|
102
|
+
host: process.env.REDIS_HOST ?? '127.0.0.1',
|
|
103
|
+
port: process.env.REDIS_PORT ?? 6379
|
|
104
|
+
})
|
|
101
105
|
this._client.connect().then()
|
|
102
106
|
|
|
103
107
|
this._instance.on('connection', async (socket, req) => {
|
|
@@ -180,15 +184,21 @@ class WSS extends EventEmitter2{
|
|
|
180
184
|
data = arr.length > 0 ? JSON.parse(JSON.stringify(arr.pop())) : data
|
|
181
185
|
}
|
|
182
186
|
catch(e){
|
|
183
|
-
|
|
187
|
+
|
|
188
|
+
if(e.response){
|
|
189
|
+
'$report' in process ? process.$report(e) : console.error(e.response.status, e.response.data)
|
|
190
|
+
}
|
|
191
|
+
else{
|
|
192
|
+
'$report' in process ? process.$report(e) : console.error(e)
|
|
193
|
+
}
|
|
184
194
|
|
|
185
195
|
status = 500
|
|
186
196
|
data = {
|
|
187
197
|
name: e.name,
|
|
188
198
|
message: e.message,
|
|
189
|
-
errors: e.errors,
|
|
199
|
+
errors: e.response ? e.response.data : e.errors,
|
|
190
200
|
stack: process.env.APP_DEBUG === 'true' ?
|
|
191
|
-
e.stack : undefined
|
|
201
|
+
e.stack : undefined,
|
|
192
202
|
}
|
|
193
203
|
}
|
|
194
204
|
break
|
|
@@ -254,23 +264,22 @@ class WSS extends EventEmitter2{
|
|
|
254
264
|
this._reqFn.push(fn)
|
|
255
265
|
}
|
|
256
266
|
|
|
257
|
-
async broadcast(
|
|
267
|
+
async broadcast(channels, { model, event, items }){
|
|
258
268
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
socket.send(await this.toBinaryData({ data:{ model, event, items } }))
|
|
262
|
-
}
|
|
263
|
-
}*/
|
|
269
|
+
if(!Array.isArray(channels))
|
|
270
|
+
channels = [ channels ]
|
|
264
271
|
|
|
265
|
-
|
|
272
|
+
for(let channel of channels){
|
|
273
|
+
await this._client.publish(channel, JSON.stringify({ model, event, items }))
|
|
266
274
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
275
|
+
if(process.verbose){
|
|
276
|
+
process.verbose('wss.broadcast', {
|
|
277
|
+
channel,
|
|
278
|
+
model,
|
|
279
|
+
event,
|
|
280
|
+
items
|
|
281
|
+
})
|
|
282
|
+
}
|
|
274
283
|
}
|
|
275
284
|
}
|
|
276
285
|
|