@mixd-id/web-scaffold 0.1.230406302 → 0.1.230406303
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 +26 -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.230406303",
|
|
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,10 @@ class WSS extends EventEmitter2{
|
|
|
97
97
|
this._opt = opt
|
|
98
98
|
this._instance = new WebSocket.Server(opt);
|
|
99
99
|
|
|
100
|
-
this._client = redis.createClient(
|
|
100
|
+
this._client = redis.createClient({
|
|
101
|
+
host: process.env.REDIS_HOST ?? '127.0.0.1',
|
|
102
|
+
port: process.env.REDIS_PORT ?? 6379
|
|
103
|
+
})
|
|
101
104
|
this._client.connect().then()
|
|
102
105
|
|
|
103
106
|
this._instance.on('connection', async (socket, req) => {
|
|
@@ -180,15 +183,21 @@ class WSS extends EventEmitter2{
|
|
|
180
183
|
data = arr.length > 0 ? JSON.parse(JSON.stringify(arr.pop())) : data
|
|
181
184
|
}
|
|
182
185
|
catch(e){
|
|
183
|
-
|
|
186
|
+
|
|
187
|
+
if(e.response){
|
|
188
|
+
'$report' in process ? process.$report(e) : console.error(e.response.status, e.response.data)
|
|
189
|
+
}
|
|
190
|
+
else{
|
|
191
|
+
'$report' in process ? process.$report(e) : console.error(e)
|
|
192
|
+
}
|
|
184
193
|
|
|
185
194
|
status = 500
|
|
186
195
|
data = {
|
|
187
196
|
name: e.name,
|
|
188
197
|
message: e.message,
|
|
189
|
-
errors: e.errors,
|
|
198
|
+
errors: e.response ? e.response.data : e.errors,
|
|
190
199
|
stack: process.env.APP_DEBUG === 'true' ?
|
|
191
|
-
e.stack : undefined
|
|
200
|
+
e.stack : undefined,
|
|
192
201
|
}
|
|
193
202
|
}
|
|
194
203
|
break
|
|
@@ -254,23 +263,22 @@ class WSS extends EventEmitter2{
|
|
|
254
263
|
this._reqFn.push(fn)
|
|
255
264
|
}
|
|
256
265
|
|
|
257
|
-
async broadcast(
|
|
266
|
+
async broadcast(channels, { model, event, items }){
|
|
258
267
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
socket.send(await this.toBinaryData({ data:{ model, event, items } }))
|
|
262
|
-
}
|
|
263
|
-
}*/
|
|
268
|
+
if(!Array.isArray(channels))
|
|
269
|
+
channels = [ channels ]
|
|
264
270
|
|
|
265
|
-
|
|
271
|
+
for(let channel of channels){
|
|
272
|
+
await this._client.publish(channel, JSON.stringify({ model, event, items }))
|
|
266
273
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
+
if(process.verbose){
|
|
275
|
+
process.verbose('wss.broadcast', {
|
|
276
|
+
channel,
|
|
277
|
+
model,
|
|
278
|
+
event,
|
|
279
|
+
items
|
|
280
|
+
})
|
|
281
|
+
}
|
|
274
282
|
}
|
|
275
283
|
}
|
|
276
284
|
|