glib-web 3.15.3 → 3.16.1
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/charts/pie.vue +3 -3
- package/components/component.vue +2 -2
- package/components/fields/_select.vue +11 -4
- package/components/fields/file.vue +10 -32
- package/components/fields/{multipleUpload.vue → multiUpload.vue} +4 -6
- package/components/fields/otpField.vue +29 -12
- package/components/mixins/styles.js +5 -3
- package/components/panels/table.vue +9 -8
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<pie-chart :style="genericStyles()" :class="$classes()" :data="series" :colors="color" :suffix="spec.suffix"
|
|
3
|
-
:prefix="spec.prefix" :min=spec.min :max=spec.max :legend=spec.legend></pie-chart>
|
|
3
|
+
:prefix="spec.prefix" :min="spec.min" :max="spec.max" :legend="spec.legend" :donut="isDonut($classes())"></pie-chart>
|
|
4
4
|
</template>
|
|
5
5
|
|
|
6
6
|
<script setup>
|
|
@@ -9,8 +9,8 @@ const { singleDataSeries } = await import('./series');
|
|
|
9
9
|
|
|
10
10
|
const { spec } = defineProps({ spec: Object });
|
|
11
11
|
const color = spec.colors == null ? '' : spec.colors;
|
|
12
|
-
const series = computed(() => singleDataSeries(spec.dataSeries))
|
|
13
|
-
|
|
12
|
+
const series = computed(() => singleDataSeries(spec.dataSeries));
|
|
13
|
+
const isDonut = (classes) => [classes].flat().includes('donut');
|
|
14
14
|
</script>
|
|
15
15
|
|
|
16
16
|
<style scoped></style>
|
package/components/component.vue
CHANGED
|
@@ -71,7 +71,7 @@ import TextAreaField from "./fields/textarea.vue";
|
|
|
71
71
|
const RichTextField = defineAsyncComponent(() => import("./fields/richText.vue"));
|
|
72
72
|
// import NewRichTextField from "./fields/newRichText.vue";
|
|
73
73
|
const FileField = defineAsyncComponent(() => import("./fields/file.vue"));
|
|
74
|
-
const
|
|
74
|
+
const MultiUploadField = defineAsyncComponent(() => import("./fields/multiUpload.vue"));
|
|
75
75
|
import AutocompleteField from "./fields/autocomplete.vue";
|
|
76
76
|
import SelectField from "./fields/select.vue";
|
|
77
77
|
import TimeZoneField from "./fields/timeZone.vue";
|
|
@@ -164,7 +164,7 @@ export default {
|
|
|
164
164
|
"fields-richText": RichTextField,
|
|
165
165
|
// "fields-newRichText": NewRichTextField,
|
|
166
166
|
"fields-file": FileField,
|
|
167
|
-
"fields-
|
|
167
|
+
"fields-multiUpload": MultiUploadField,
|
|
168
168
|
"fields-autocomplete": AutocompleteField,
|
|
169
169
|
"fields-select": SelectField,
|
|
170
170
|
"fields-timeZone": TimeZoneField,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div :style="$styles()" :class="classes()">
|
|
3
|
-
<v-autocomplete v-model="fieldModel" :label="
|
|
4
|
-
:multiple="spec.multiple" :readonly="spec.readOnly" :clearable="!spec.readOnly"
|
|
3
|
+
<v-autocomplete v-model="fieldModel" :label="label" :items="options || []" :chips="spec.multiple"
|
|
4
|
+
:multiple="spec.multiple" :readonly="spec.readOnly" :clearable="!spec.readOnly"
|
|
5
5
|
:placeholder="spec.placeholder" :rules="rules" persistent-hint :append-icon="append.icon" validate-on="blur"
|
|
6
6
|
item-title='text' :variant="variant" :closable-chips="spec.multiple" :density="density" persistent-placeholder
|
|
7
|
-
@update:modelValue="onChange">
|
|
7
|
+
@update:modelValue="onChange" @focus="focused = true" @blur="focused = false">
|
|
8
8
|
|
|
9
9
|
<template #item="{props, item}">
|
|
10
10
|
<v-list-subheader v-if="item.raw.header">
|
|
@@ -41,7 +41,8 @@ export default {
|
|
|
41
41
|
return {
|
|
42
42
|
options: null,
|
|
43
43
|
append: {},
|
|
44
|
-
rules: []
|
|
44
|
+
rules: [],
|
|
45
|
+
focused: false
|
|
45
46
|
};
|
|
46
47
|
},
|
|
47
48
|
computed: {
|
|
@@ -60,6 +61,12 @@ export default {
|
|
|
60
61
|
},
|
|
61
62
|
density() {
|
|
62
63
|
return determineDensity(this.spec.styleClasses);
|
|
64
|
+
},
|
|
65
|
+
label() {
|
|
66
|
+
if (this.focused) {
|
|
67
|
+
return `${this.spec.label} ${this.spec.hint}`
|
|
68
|
+
}
|
|
69
|
+
return this.spec.label
|
|
63
70
|
}
|
|
64
71
|
},
|
|
65
72
|
methods: {
|
|
@@ -9,28 +9,18 @@
|
|
|
9
9
|
:src="fileImage || placeholder.url" />
|
|
10
10
|
|
|
11
11
|
<v-text-field v-else-if="placeholder.type == 'input'" :value="fileTitle" variant="outlined"
|
|
12
|
-
|
|
12
|
+
:placeholder="placeholder.inputPlaceholder" disabled />
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
<!-- See https://www.freecodecamp.org/news/how-to-use-html-to-open-link-in-new-tab/ -->
|
|
15
15
|
<a href="" @click="showPreview" v-else>{{ fileTitle }}</a>
|
|
16
16
|
|
|
17
|
-
<
|
|
18
|
-
<v-btn @click="triggerUpload">
|
|
19
|
-
<v-icon> {{ spec.uploadIcon || "upload" }} </v-icon>
|
|
20
|
-
{{ spec.uploadText }}
|
|
21
|
-
</v-btn>
|
|
22
|
-
|
|
23
|
-
<v-btn v-if="fileImage" icon @click="removeImage">
|
|
24
|
-
<v-icon>close</v-icon>
|
|
25
|
-
</v-btn>
|
|
26
|
-
</span>
|
|
27
|
-
<div v-else class="action-container">
|
|
17
|
+
<div class="action-container">
|
|
28
18
|
<v-btn @click="triggerUpload" class="upload-btn">
|
|
29
|
-
{{ fileImage ?
|
|
19
|
+
{{ fileImage ? buttonLabels.change : buttonLabels.upload }}
|
|
30
20
|
</v-btn>
|
|
31
21
|
|
|
32
22
|
<v-btn variant="flat" v-if="fileImage" @click="removeImage" class="remove-btn">
|
|
33
|
-
|
|
23
|
+
{{ buttonLabels.delete }}
|
|
34
24
|
</v-btn>
|
|
35
25
|
|
|
36
26
|
|
|
@@ -39,28 +29,13 @@
|
|
|
39
29
|
</div>
|
|
40
30
|
</div>
|
|
41
31
|
<input ref="directUploadFile" style="display: none" type="file" @change="uploadFiles" />
|
|
42
|
-
|
|
43
|
-
<!-- <input type="file" :name="spec.name" ref='directUploadFile' @change='uploadFiles' v-show='!uploaded'/> -->
|
|
44
32
|
<v-progress-linear class="mt-1" v-if="showProgress" v-model="progress.value" />
|
|
45
|
-
<!-- <div v-show='uploaded'>
|
|
46
|
-
<v-layout align-center justify-space-between row>
|
|
47
|
-
<v-chip @click='removeImage' class='mr-2' color='red' text-color="white">X</v-chip>
|
|
48
|
-
<span ref='fileName' class='w-full mr-2'></span>
|
|
49
|
-
<img ref='fileImage' class='place-image-preview' />
|
|
50
|
-
</v-layout>
|
|
51
|
-
</div> -->
|
|
52
33
|
<input type="hidden" :name="spec.name" :value="fileValue" :disabled="inputDisabled" />
|
|
53
34
|
</div>
|
|
54
35
|
</template>
|
|
55
36
|
|
|
56
37
|
<script>
|
|
57
|
-
// import * as ActiveStorage from "@rails/activestorage"
|
|
58
38
|
import Uploader from "../../utils/uploader";
|
|
59
|
-
// import EventController, {
|
|
60
|
-
// DISABLE_SUBMIT_BUTTON
|
|
61
|
-
// } from "../../utils/global-event-controller";
|
|
62
|
-
|
|
63
|
-
// ActiveStorage.start()
|
|
64
39
|
|
|
65
40
|
export default {
|
|
66
41
|
props: {
|
|
@@ -75,6 +50,7 @@ export default {
|
|
|
75
50
|
fileValue: null,
|
|
76
51
|
inputElement: null,
|
|
77
52
|
placeholder: {},
|
|
53
|
+
buttonLabels: { delete: 'Delete', upload: 'Upload', change: 'Change' }
|
|
78
54
|
};
|
|
79
55
|
},
|
|
80
56
|
computed: {
|
|
@@ -91,8 +67,9 @@ export default {
|
|
|
91
67
|
this.fileValue = this.spec.value;
|
|
92
68
|
}
|
|
93
69
|
|
|
94
|
-
this.placeholder = this.spec.placeholderView || {};
|
|
70
|
+
this.placeholder = this.spec.placeholderView || { inputPlaceholder: 'Upload your file' };
|
|
95
71
|
this.inputElement = this.$refs.directUploadFile;
|
|
72
|
+
this.buttonLabels = Object.assign(this.buttonLabels, this.spec.buttonLabels);
|
|
96
73
|
},
|
|
97
74
|
triggerUpload() {
|
|
98
75
|
this.inputElement.click();
|
|
@@ -122,7 +99,7 @@ export default {
|
|
|
122
99
|
const previewWindow = window.open("");
|
|
123
100
|
previewWindow?.document.write(
|
|
124
101
|
`<iframe width='100%' height='100%' src='${this.fileImage}'></iframe>`
|
|
125
|
-
)
|
|
102
|
+
);
|
|
126
103
|
},
|
|
127
104
|
uploadFile(file) {
|
|
128
105
|
const upload = new Uploader(
|
|
@@ -182,6 +159,7 @@ export default {
|
|
|
182
159
|
display: flex;
|
|
183
160
|
align-items: center;
|
|
184
161
|
flex-wrap: wrap;
|
|
162
|
+
gap: 8px;
|
|
185
163
|
|
|
186
164
|
&.uploaded {
|
|
187
165
|
gap: 16px;
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
<div class="cloud" style="pointer-events: none;">
|
|
8
8
|
<v-icon ref="icon" size="48" class="icon">cloud_upload</v-icon>
|
|
9
|
-
<h4 v-if="spec.
|
|
10
|
-
<p v-if="spec.
|
|
9
|
+
<h4 v-if="spec.placeholder" class="title">{{ spec.placeholder }}</h4>
|
|
10
|
+
<p v-if="spec.hint" class="subtitle">{{ spec.hint }}</p>
|
|
11
11
|
</div>
|
|
12
12
|
|
|
13
13
|
<input v-for="(file, index) in Object.values(files)" type="hidden" :name="spec.name" :value="file.signedId"
|
|
@@ -239,8 +239,8 @@ export default defineComponent({
|
|
|
239
239
|
const container = ref(null);
|
|
240
240
|
const icon = ref(null);
|
|
241
241
|
|
|
242
|
-
let files =
|
|
243
|
-
if (spec.files) {
|
|
242
|
+
let files = ref({});
|
|
243
|
+
if (spec.files && spec.files.length > 0) {
|
|
244
244
|
files = ref(spec.files.reduce((prev, curr) => {
|
|
245
245
|
const key = makeKey();
|
|
246
246
|
|
|
@@ -255,8 +255,6 @@ export default defineComponent({
|
|
|
255
255
|
|
|
256
256
|
return prev;
|
|
257
257
|
}, {}));
|
|
258
|
-
} else {
|
|
259
|
-
files = ref([]);
|
|
260
258
|
}
|
|
261
259
|
|
|
262
260
|
const setBusy = (value) => {
|
|
@@ -1,24 +1,41 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
2
|
+
<div :style="$styles()" :class="$classes()">
|
|
3
|
+
<v-otp-input ref="field" v-model="fieldModel" :name="fieldName" :disabled="inputDisabled" :rounded="4"
|
|
4
|
+
:max-width="maxWidth" type="spec.type || 'number'" :length="length" :variant="variant" />
|
|
5
|
+
<label class="hint" v-if="spec.hint">{{ spec.hint }}</label>
|
|
6
|
+
</div>
|
|
3
7
|
</template>
|
|
4
8
|
|
|
5
9
|
<script>
|
|
6
|
-
import
|
|
10
|
+
import inputVariant from "../mixins/inputVariant";
|
|
7
11
|
|
|
8
12
|
export default {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"fields-otp": OtpField,
|
|
12
|
-
},
|
|
13
|
+
expose: ['fieldModel'],
|
|
14
|
+
mixins: [inputVariant],
|
|
13
15
|
props: {
|
|
14
16
|
spec: { type: Object, required: true },
|
|
15
17
|
},
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
18
|
+
computed: {
|
|
19
|
+
length() {
|
|
20
|
+
return this.spec.length || 6;
|
|
21
|
+
},
|
|
22
|
+
maxWidth() {
|
|
23
|
+
const width = 50;
|
|
24
|
+
const pad = 8;
|
|
25
|
+
return this.length * width + this.length * pad;
|
|
26
|
+
}
|
|
20
27
|
},
|
|
28
|
+
methods: {
|
|
29
|
+
$sanitizeValue(val) {
|
|
30
|
+
if (!val) return '';
|
|
31
|
+
|
|
32
|
+
let value = val + '';
|
|
33
|
+
if (this.length > value.length) {
|
|
34
|
+
value = '0'.repeat(this.length - value.length) + value;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return value;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
21
40
|
};
|
|
22
41
|
</script>
|
|
23
|
-
|
|
24
|
-
<style scoped></style>
|
|
@@ -94,7 +94,9 @@ export default {
|
|
|
94
94
|
return;
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
if (this.spec.valueIf) {
|
|
98
|
+
this.fieldModel = this.$sanitizeValue(this.$externalizeValue(value));
|
|
99
|
+
}
|
|
98
100
|
});
|
|
99
101
|
this._watchers.push(watcher1);
|
|
100
102
|
}
|
|
@@ -253,12 +255,12 @@ export default {
|
|
|
253
255
|
|
|
254
256
|
// Avoid user input getting removed when updating certain parts of the page.
|
|
255
257
|
if (valueChanged) {
|
|
256
|
-
this.fieldModel = this
|
|
258
|
+
this.fieldModel = this.$sanitizeValue(this.$externalizeValue(this.spec.value));
|
|
257
259
|
}
|
|
258
260
|
}
|
|
259
261
|
},
|
|
260
262
|
action_resetValue() {
|
|
261
|
-
this.fieldModel = this
|
|
263
|
+
this.fieldModel = this.$sanitizeValue(this.$externalizeValue(this.spec.value));
|
|
262
264
|
},
|
|
263
265
|
$classes(spec, defaultViewName) {
|
|
264
266
|
const properties = Object.assign(
|
|
@@ -49,12 +49,14 @@
|
|
|
49
49
|
<tr :class="row.onClick ? 'clickable' : ''">
|
|
50
50
|
<td v-for="(cell, cellIndex) in row.cellViews" :key="`cell_${cellIndex}`" :colSpan="colSpan(row, cellIndex)"
|
|
51
51
|
:style="colStyles(row, cellIndex)">
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
<
|
|
57
|
-
|
|
52
|
+
<span>
|
|
53
|
+
<!-- Prevent double links -->
|
|
54
|
+
<glib-component v-if="$href(cell)" :spec="cell" />
|
|
55
|
+
<!-- without "|| null" the browser will reload strangely -->
|
|
56
|
+
<a v-else :href="$href(row) || null" @click="$onClick($event, row)">
|
|
57
|
+
<glib-component :spec="cell" />
|
|
58
|
+
</a>
|
|
59
|
+
</span>
|
|
58
60
|
</td>
|
|
59
61
|
</tr>
|
|
60
62
|
</template>
|
|
@@ -175,9 +177,8 @@ tbody {
|
|
|
175
177
|
|
|
176
178
|
td {
|
|
177
179
|
border-top: 1px solid rgba(0, 0, 0, 0.12);
|
|
178
|
-
// border-left: 1px solid rgba(0, 0, 0, 0.12);
|
|
179
180
|
|
|
180
|
-
|
|
181
|
+
span {
|
|
181
182
|
padding: 10px 24px;
|
|
182
183
|
display: block;
|
|
183
184
|
color: inherit;
|