glib-web 4.27.0 → 4.27.3
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/components/_internal_button.vue +10 -6
- package/components/charts/series.js +18 -1
- package/components/fields/_buttonDate.vue +8 -2
- package/components/fields/richText2.vue +107 -7
- package/components/helper.js +5 -1
- package/components/mixins/events.js +2 -1
- package/components/progressCircle.vue +17 -2
- package/nav/dialog.vue +5 -2
- package/package.json +1 -1
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<!-- Use `click.prevent` to prevent bubbling when clicking a dropdown button that is
|
|
3
|
-
located in a list row that has href. -->
|
|
4
2
|
<v-btn :type="type" :disabled="spec.disabled" :style="styles()" :class="$classes()" :href="$href()" :rel="$rel()"
|
|
5
3
|
:variant="variant" :rounded="$classes().includes('rounded') || null" :density="density" :size="size" :color="color"
|
|
6
|
-
:active="$classesInclude('active')" :icon="$classes().includes('icon') ? $vuetify : null" @click
|
|
7
|
-
type == 'submit' ? $dispatchEvent('forms/submit') : $onClick()
|
|
8
|
-
">
|
|
4
|
+
:active="$classesInclude('active')" :icon="$classes().includes('icon') ? $vuetify : null" @click="onClick">
|
|
9
5
|
<!-- <span v-if="spec.icon"><common-icon :spec="spec.icon || {}" /></span> -->
|
|
10
6
|
<common-icon v-if="spec.icon" :spec="spec.icon || {}" />
|
|
11
7
|
<div :class="hideTextOnXs && spec.icon ? 'd-none d-sm-flex' : null">
|
|
@@ -15,7 +11,6 @@
|
|
|
15
11
|
</template>
|
|
16
12
|
|
|
17
13
|
<script>
|
|
18
|
-
import { nextTick } from "vue";
|
|
19
14
|
import { determineColor, determineDensity, determineVariant, determineSize } from '../utils/constant';
|
|
20
15
|
|
|
21
16
|
|
|
@@ -42,6 +37,15 @@ export default {
|
|
|
42
37
|
}
|
|
43
38
|
},
|
|
44
39
|
methods: {
|
|
40
|
+
onClick(e) {
|
|
41
|
+
if (this.type == 'submit') {
|
|
42
|
+
e.preventDefault(); // prevent get submitted twice
|
|
43
|
+
this.$dispatchEvent('forms/submit');
|
|
44
|
+
}
|
|
45
|
+
e.stopPropagation(); // prevent event bubbling
|
|
46
|
+
|
|
47
|
+
this.$onClick();
|
|
48
|
+
},
|
|
45
49
|
// $ready() {
|
|
46
50
|
// this.$type.ifArray(this.spec.styleClasses, val => {
|
|
47
51
|
// this.linkStyling = val.includes("link");
|
|
@@ -122,7 +122,24 @@ function useChart({ dataSeries, spec, multiple = true }) {
|
|
|
122
122
|
let colors = undefined;
|
|
123
123
|
if (spec.colors) colors = spec.colors;
|
|
124
124
|
|
|
125
|
-
|
|
125
|
+
let options = {}
|
|
126
|
+
|
|
127
|
+
if (spec.formatYAxis) {
|
|
128
|
+
options = {
|
|
129
|
+
scales: {
|
|
130
|
+
y: {
|
|
131
|
+
ticks: {
|
|
132
|
+
callback: function (value) {
|
|
133
|
+
return `${spec.prefix || ''}${value.toLocaleString()}${spec.suffix || ''}`;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
plugins: {}
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
|
|
126
143
|
options.plugins = {};
|
|
127
144
|
if (legend) options.plugins.legend = legend;
|
|
128
145
|
if (isDonut) options.cutout = '75%';
|
|
@@ -18,10 +18,11 @@
|
|
|
18
18
|
<v-input :name="fieldName" :rules="$validation()" v-model="model" />
|
|
19
19
|
|
|
20
20
|
<v-dialog v-model="dialog" width="auto">
|
|
21
|
-
<v-date-picker :model-value="new Date(model)" @update:modelValue="handleDatePickerChanged"
|
|
21
|
+
<v-date-picker :model-value="model ? new Date(model) : null" @update:modelValue="handleDatePickerChanged"
|
|
22
22
|
:disabled="inputDisabled" :min="sanitizeValue(spec.min)" :max="sanitizeValue(spec.max)" show-adjacent-months
|
|
23
23
|
location="center" position="fixed">
|
|
24
24
|
<template v-slot:actions>
|
|
25
|
+
<v-btn color="error" @click="remove">Remove</v-btn>
|
|
25
26
|
<v-btn color="primary" @click="dialog = false">Save</v-btn>
|
|
26
27
|
</template>
|
|
27
28
|
</v-date-picker>
|
|
@@ -69,6 +70,11 @@ export default {
|
|
|
69
70
|
model.value = sanitizeValue(val.spec.value);
|
|
70
71
|
});
|
|
71
72
|
|
|
73
|
+
function remove() {
|
|
74
|
+
model.value = '';
|
|
75
|
+
ctx.emit('datePicked', model.value);
|
|
76
|
+
}
|
|
77
|
+
|
|
72
78
|
function handleChanged(e) {
|
|
73
79
|
const { value } = e.srcElement;
|
|
74
80
|
model.value = value;
|
|
@@ -83,7 +89,7 @@ export default {
|
|
|
83
89
|
|
|
84
90
|
const { smAndUp } = useDisplay();
|
|
85
91
|
|
|
86
|
-
return { text, sanitizeValue, dateInput, handleChanged, model, template, dialog, handleDatePickerChanged, smAndUp };
|
|
92
|
+
return { text, sanitizeValue, dateInput, handleChanged, model, template, dialog, handleDatePickerChanged, smAndUp, remove };
|
|
87
93
|
},
|
|
88
94
|
methods: {
|
|
89
95
|
showPicker(e) {
|
|
@@ -153,19 +153,87 @@ export default defineComponent({
|
|
|
153
153
|
]
|
|
154
154
|
};
|
|
155
155
|
if (props.spec.mentionList) {
|
|
156
|
+
const simpleSource = (searchTerm, renderList, mentionChar) => {
|
|
157
|
+
const matches = props.spec.mentionList.toSorted().map((v, index) => ({ id: index + 1, value: v }));
|
|
158
|
+
|
|
159
|
+
if (searchTerm.length === 0) {
|
|
160
|
+
renderList(matches, searchTerm);
|
|
161
|
+
} else {
|
|
162
|
+
renderList(matches.filter((v) => v.value.toLowerCase().includes(searchTerm)), searchTerm);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const advancedSource = (searchTerm, renderList, mentionChar) => {
|
|
167
|
+
|
|
168
|
+
const compareFn = (a, b) => a.value > b.value;
|
|
169
|
+
const options = props.spec.mentionList.toSorted(compareFn);
|
|
170
|
+
const isGrouped = !!props.spec.mentionList[0].group;
|
|
171
|
+
let matches;
|
|
172
|
+
|
|
173
|
+
if (searchTerm.length === 0) {
|
|
174
|
+
matches = options;
|
|
175
|
+
} else {
|
|
176
|
+
matches = options.filter((v) => v.value.toLowerCase().includes(searchTerm));
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (isGrouped) {
|
|
180
|
+
const groupedMatches = Object.groupBy(matches, ({ group }) => group);
|
|
181
|
+
let tmpMatches = [];
|
|
182
|
+
Object.keys(groupedMatches).toSorted().forEach((group) => {
|
|
183
|
+
tmpMatches.push({ id: group, value: group, disabled: true });
|
|
184
|
+
groupedMatches[group].forEach((item) => {
|
|
185
|
+
tmpMatches.push(item);
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
matches = tmpMatches;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
renderList(matches, searchTerm);
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
const source = typeof props.spec.mentionList[0] == 'object' ? advancedSource : simpleSource;
|
|
195
|
+
|
|
156
196
|
Quill.register({ "blots/mention": MentionBlot, "modules/mention": Mention });
|
|
157
197
|
modules.mention = {
|
|
158
198
|
allowedChars: /^[A-Za-z\sÅÄÖåäö]*$/,
|
|
159
199
|
mentionDenotationChars: ["@"],
|
|
160
|
-
|
|
161
|
-
|
|
200
|
+
renderItem: (data) => {
|
|
201
|
+
if (data.disabled) {
|
|
202
|
+
const div = document.createElement("div");
|
|
203
|
+
div.classList.add('glib-quill-group');
|
|
204
|
+
div.innerText = data.value;
|
|
205
|
+
return div;
|
|
206
|
+
}
|
|
207
|
+
const div = document.createElement("div");
|
|
208
|
+
div.classList.add('glib-quill-item');
|
|
209
|
+
|
|
210
|
+
if (data.avatar) {
|
|
211
|
+
const img = document.createElement('img');
|
|
212
|
+
img.src = data.avatar;
|
|
213
|
+
img.classList.add('avatar');
|
|
214
|
+
div.appendChild(img);
|
|
215
|
+
}
|
|
162
216
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
217
|
+
const childDiv = document.createElement('div');
|
|
218
|
+
div.appendChild(childDiv);
|
|
219
|
+
|
|
220
|
+
if (data.text) {
|
|
221
|
+
const title = document.createElement('div');
|
|
222
|
+
title.style.lineHeight = '170%';
|
|
223
|
+
title.innerText = data.text;
|
|
224
|
+
childDiv.appendChild(title);
|
|
167
225
|
}
|
|
168
|
-
|
|
226
|
+
|
|
227
|
+
const subtitle = document.createElement('div');
|
|
228
|
+
subtitle.innerText = data.value;
|
|
229
|
+
childDiv.appendChild(subtitle);
|
|
230
|
+
|
|
231
|
+
return div;
|
|
232
|
+
},
|
|
233
|
+
renderLoading: () => {
|
|
234
|
+
return "Loading...";
|
|
235
|
+
},
|
|
236
|
+
source: source
|
|
169
237
|
};
|
|
170
238
|
}
|
|
171
239
|
onMounted(() => {
|
|
@@ -218,4 +286,36 @@ export default defineComponent({
|
|
|
218
286
|
.ql-container {
|
|
219
287
|
height: fit-content;
|
|
220
288
|
}
|
|
289
|
+
|
|
290
|
+
.glib-quill-group {
|
|
291
|
+
/* padding: 16px 0; */
|
|
292
|
+
color: #A7ADB5;
|
|
293
|
+
font-size: 12px;
|
|
294
|
+
height: 12px;
|
|
295
|
+
line-height: 12px;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.glib-quill-item {
|
|
299
|
+
padding: 8px 0;
|
|
300
|
+
display: flex;
|
|
301
|
+
gap: 12px;
|
|
302
|
+
flex-wrap: nowrap;
|
|
303
|
+
align-items: center;
|
|
304
|
+
|
|
305
|
+
.avatar {
|
|
306
|
+
width: 40px;
|
|
307
|
+
height: 40px;
|
|
308
|
+
border-radius: calc(infinity * 1px);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
div {
|
|
312
|
+
font-size: 14px;
|
|
313
|
+
line-height: 100%;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
.ql-mention-list-container {
|
|
318
|
+
padding-top: 8px !important;
|
|
319
|
+
padding-bottom: 8px !important;
|
|
320
|
+
}
|
|
221
321
|
</style>
|
package/components/helper.js
CHANGED
|
@@ -30,4 +30,8 @@ function closest(component, name) {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
function strandom() {
|
|
34
|
+
return (Math.random() + 1).toString(36).substring(7) + Date.now().toString();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export { realComponent, htmlElement, closest, strandom };
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<v-progress-circular :class="$classes()" :rotate="spec.rotate || 0" :size="spec.size || 100" :width="spec.width || 20"
|
|
3
3
|
:color="spec.color" :model-value="spec.value" :indeterminate="spec.indeterminate">
|
|
4
|
-
|
|
4
|
+
<div>
|
|
5
|
+
<div class="value-style text-center">{{ spec.value }}%</div>
|
|
6
|
+
<span v-if="spec.text" class="text-style">{{ spec.text }}</span>
|
|
7
|
+
</div>
|
|
5
8
|
</v-progress-circular>
|
|
6
9
|
</template>
|
|
7
10
|
|
|
@@ -13,4 +16,16 @@ export default {
|
|
|
13
16
|
};
|
|
14
17
|
</script>
|
|
15
18
|
|
|
16
|
-
<style scoped
|
|
19
|
+
<style scoped>
|
|
20
|
+
.value-style {
|
|
21
|
+
font-size: 16px;
|
|
22
|
+
line-height: 150%;
|
|
23
|
+
font-weight: 700;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.text-style {
|
|
27
|
+
font-size: 16px;
|
|
28
|
+
line-height: 150%;
|
|
29
|
+
font-weight: 400;
|
|
30
|
+
}
|
|
31
|
+
</style>
|
package/nav/dialog.vue
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<v-dialog :class="spec.styleClass" :model-value="model" :width="spec.width || 600" :dark="false"
|
|
3
3
|
:fullscreen="fullscreen" :sm-and-down="false" :persistent="true" @click:outside="clickOutside">
|
|
4
|
-
<v-card :style="hamburgerStyles" class="dialog-hamburger">
|
|
4
|
+
<v-card :style="hamburgerStyles" class="dialog-hamburger" :key="dialogKey">
|
|
5
5
|
|
|
6
6
|
<panels-responsive v-if="header" :spec="header" />
|
|
7
7
|
<div :class="`dialog-title ${title ? '' : 'dialog-absolute'}`">
|
|
@@ -46,6 +46,7 @@ import FormPanel from "../components/panels/form.vue";
|
|
|
46
46
|
import { confirmDirty, dialogs } from "../store";
|
|
47
47
|
import { onMounted, ref } from "vue";
|
|
48
48
|
import { usePasteable } from "../components/composable/pasteable";
|
|
49
|
+
import { strandom } from "../components/helper.js";
|
|
49
50
|
|
|
50
51
|
export default {
|
|
51
52
|
expose: ['model', 'close', 'isFormDirty'],
|
|
@@ -84,7 +85,8 @@ export default {
|
|
|
84
85
|
url: null,
|
|
85
86
|
urlLoaded: false,
|
|
86
87
|
isMobile: false,
|
|
87
|
-
formSpec: null
|
|
88
|
+
formSpec: null,
|
|
89
|
+
dialogKey: 'init',
|
|
88
90
|
};
|
|
89
91
|
},
|
|
90
92
|
computed: {
|
|
@@ -157,6 +159,7 @@ export default {
|
|
|
157
159
|
this.url = newSpec.url;
|
|
158
160
|
this.urlLoaded = false;
|
|
159
161
|
this.show(true);
|
|
162
|
+
this.dialogKey = strandom();
|
|
160
163
|
},
|
|
161
164
|
onResize() {
|
|
162
165
|
this.isMobile = window.innerWidth < 600;
|