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.
@@ -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.prevent="
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
- const options = {};
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
- source: function (searchTerm, renderList, mentionChar) {
161
- const values = props.spec.mentionList.map((v, index) => ({ id: index + 1, value: v }));
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
- if (searchTerm.length === 0) {
164
- renderList(values, searchTerm);
165
- } else {
166
- renderList(values.filter((v) => v.value.toLowerCase().includes(searchTerm)), searchTerm);
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>
@@ -30,4 +30,8 @@ function closest(component, name) {
30
30
  }
31
31
  }
32
32
 
33
- export { realComponent, htmlElement, closest };
33
+ function strandom() {
34
+ return (Math.random() + 1).toString(36).substring(7) + Date.now().toString();
35
+ }
36
+
37
+ export { realComponent, htmlElement, closest, strandom };
@@ -88,7 +88,8 @@ export default {
88
88
  return `#${onClick.viewId}`;
89
89
  }
90
90
  }
91
- return '';
91
+
92
+ return null;
92
93
  },
93
94
  $onClick: function (explicitEvent, spec) {
94
95
  const properties = spec || this.spec;
@@ -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
- <span v-if="spec.text" class="grey--text text--lighten-1 text-h5">{{ spec.text }}</span>
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></style>
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "glib-web",
3
- "version": "4.27.0",
3
+ "version": "4.27.3",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {