glib-web 4.34.4 → 4.35.0
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/README.md +1 -0
- package/actions/snackbars/alert.js +3 -4
- package/actions/windows/openWeb.js +2 -1
- package/components/_avatar.vue +19 -3
- package/components/_internal_button.vue +2 -0
- package/components/composable/upload_nothing.js +21 -0
- package/components/fields/file.vue +9 -2
- package/components/fields/multiUpload.vue +10 -4
- package/components/panels/form.vue +1 -1
- package/components/panels/table.vue +15 -0
- package/nav/appBar.vue +2 -1
- package/nav/snackbar.vue +9 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,16 +2,15 @@ export default class {
|
|
|
2
2
|
execute(spec, component) {
|
|
3
3
|
// Set default timeout as recommended by Vuetify
|
|
4
4
|
// See https://vuetifyjs.com/en/api/v-snackbar/#props
|
|
5
|
-
const timeout = spec.timeout || 4000
|
|
6
|
-
const persistent = timeout < 0
|
|
5
|
+
const timeout = spec.timeout || 4000;
|
|
6
|
+
const persistent = timeout < 0;
|
|
7
7
|
|
|
8
8
|
const properties = Object.assign({}, spec, {
|
|
9
9
|
timeout: timeout,
|
|
10
10
|
closeDelay: timeout,
|
|
11
11
|
buttons: persistent ? [
|
|
12
12
|
{
|
|
13
|
-
text: "CLOSE"
|
|
14
|
-
onClick: spec.onClose
|
|
13
|
+
text: "CLOSE"
|
|
15
14
|
}
|
|
16
15
|
] : []
|
|
17
16
|
});
|
package/components/_avatar.vue
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<common-badge :spec="spec">
|
|
3
|
-
<v-avatar :size="spec.size" :color="spec.backgroundColor || 'surface-variant'" :class="
|
|
4
|
-
<p v-if="spec.initials" :style="{ color: spec.initials.color || 'white' }">{{ spec.initials.text }}</p>
|
|
3
|
+
<v-avatar :size="spec.size" :color="spec.backgroundColor || 'surface-variant'" :class="cssClasses">
|
|
4
|
+
<p class="initials" v-if="spec.initials" :style="{ color: spec.initials.color || 'white' }">{{ spec.initials.text }}</p>
|
|
5
5
|
<!-- Use `img` instead of `v-img` otherwise the rounded border will not work. -->
|
|
6
6
|
<!-- <img :style="$styles()" :src="spec.url || spec.base64Data" @click="$onClick()" /> -->
|
|
7
7
|
<v-img :style="$styles()" :class="$classes()" :src="spec.url || spec.base64Data" @click="$onClick()"
|
|
@@ -14,6 +14,22 @@
|
|
|
14
14
|
export default {
|
|
15
15
|
props: {
|
|
16
16
|
spec: { type: Object, required: true }
|
|
17
|
-
}
|
|
17
|
+
},
|
|
18
|
+
computed: {
|
|
19
|
+
cssClasses() {
|
|
20
|
+
// Icons are nameless when used in other components, e.g. buttons
|
|
21
|
+
this.spec.view = this.spec.view || "avatar";
|
|
22
|
+
|
|
23
|
+
return this.$classes();
|
|
24
|
+
},
|
|
25
|
+
},
|
|
18
26
|
};
|
|
19
27
|
</script>
|
|
28
|
+
|
|
29
|
+
<style lang="scss">
|
|
30
|
+
.views {
|
|
31
|
+
.initials {
|
|
32
|
+
// To be overridden
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
</style>
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
:active="$classesInclude('active')" :icon="$classes().includes('icon') ? $vuetify : null" @click="onClick">
|
|
5
5
|
<!-- <span v-if="spec.icon"><common-icon :spec="spec.icon || {}" /></span> -->
|
|
6
6
|
<common-icon v-if="spec.icon" :spec="spec.icon || {}" />
|
|
7
|
+
<common-avatar v-if="spec.avatar" :spec="spec.avatar || {}" />
|
|
8
|
+
|
|
7
9
|
<div :class="hideTextOnXs && spec.icon ? 'd-none d-sm-flex' : null">
|
|
8
10
|
{{ spec.text }}
|
|
9
11
|
</div>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useFileUtils, validateFile } from "./file";
|
|
2
|
+
|
|
3
|
+
const { makeKey, Item } = useFileUtils();
|
|
4
|
+
|
|
5
|
+
function uploadFiles({ droppedFiles, files, spec }) {
|
|
6
|
+
const { accepts } = spec;
|
|
7
|
+
let key = '';
|
|
8
|
+
files.value = {};
|
|
9
|
+
for (let index = 0; index < droppedFiles.length; index++) {
|
|
10
|
+
if (!validateFile(accepts, droppedFiles[index])) {
|
|
11
|
+
continue;
|
|
12
|
+
}
|
|
13
|
+
key = makeKey();
|
|
14
|
+
files.value[key] = new Item({ el: droppedFiles[index], status: 'pending' });
|
|
15
|
+
// validate per file, skip if invalid
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function submitOnAllUploaded(obj) { }
|
|
19
|
+
function setBusyWhenUploading(obj) { }
|
|
20
|
+
|
|
21
|
+
export { uploadFiles, submitOnAllUploaded, setBusyWhenUploading };
|
|
@@ -26,9 +26,10 @@
|
|
|
26
26
|
<glib-component v-if="spec.infoSpec" :spec="spec.infoSpec"></glib-component>
|
|
27
27
|
</div>
|
|
28
28
|
</div>
|
|
29
|
-
<input ref="directUploadFile" style="display: none" type="file"
|
|
29
|
+
<input ref="directUploadFile" :name="spec.directUploadUrl ? '' : fieldName" style="display: none" type="file"
|
|
30
|
+
@change="uploadFiles" />
|
|
31
|
+
<input v-if="spec.directUploadUrl" type="hidden" :name="fieldName" :value="fileValue" :disabled="inputDisabled" />
|
|
30
32
|
<v-progress-linear class="mt-1" v-if="showProgress" v-model="progress.value" />
|
|
31
|
-
<input type="hidden" :name="fieldName" :value="fileValue" :disabled="inputDisabled" />
|
|
32
33
|
</div>
|
|
33
34
|
</template>
|
|
34
35
|
|
|
@@ -88,6 +89,8 @@ export default {
|
|
|
88
89
|
this.fileValue = null;
|
|
89
90
|
},
|
|
90
91
|
displayImagePreview(file, blob) {
|
|
92
|
+
if (!file.type.startsWith('image')) return;
|
|
93
|
+
|
|
91
94
|
let reader = new FileReader();
|
|
92
95
|
reader.onload = (e) => {
|
|
93
96
|
this.fileTitle = file.name;
|
|
@@ -151,6 +154,10 @@ export default {
|
|
|
151
154
|
}
|
|
152
155
|
},
|
|
153
156
|
uploadFiles(e) {
|
|
157
|
+
if (!this.spec.directUploadUrl) {
|
|
158
|
+
this.displayImagePreview(e.target.files[0], {});
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
154
161
|
Array.from(e.target.files).forEach((file) => this.uploadFile(file));
|
|
155
162
|
},
|
|
156
163
|
// toggleDisplayProgressIndicator() {
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
<div :style="$styles()" :class="$classes()" v-if="loadIf">
|
|
3
3
|
<div ref="container" @click="handleClick" @drop="handleDrop" @dragover="handleDragOver" @dragleave="handleDragLeave"
|
|
4
4
|
class="gdrop-file border-[2px]">
|
|
5
|
-
<input ref="fileSelect" type="file" multiple
|
|
5
|
+
<input :name="props.spec.directUploadUrl ? '' : fieldName" ref="fileSelect" type="file" multiple
|
|
6
|
+
style="display: none">
|
|
6
7
|
|
|
7
8
|
<div class="cloud" style="pointer-events: none;">
|
|
8
9
|
<v-icon ref="icon" size="48" class="icon">cloud_upload</v-icon>
|
|
@@ -10,8 +11,11 @@
|
|
|
10
11
|
<p v-if="props.spec.hint" class="subtitle">{{ props.spec.hint }}</p>
|
|
11
12
|
</div>
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
|
|
15
|
+
<template v-if="props.spec.directUploadUrl">
|
|
16
|
+
<input v-for="(file, index) in files" type="hidden" :name="fieldName" :value="file.signedId"
|
|
17
|
+
:disabled="inputDisabled" :key="`hidden-${index}`">
|
|
18
|
+
</template>
|
|
15
19
|
</div>
|
|
16
20
|
|
|
17
21
|
<div class="guploaded-file" v-if="showUploadedFile">
|
|
@@ -58,6 +62,7 @@ import { ref, computed, defineComponent, watch, getCurrentInstance } from 'vue';
|
|
|
58
62
|
import { VIcon } from 'vuetify/components';
|
|
59
63
|
import * as dropUploader from "../composable/upload";
|
|
60
64
|
import * as delegateUploader from "../composable/upload_delegator";
|
|
65
|
+
import * as nothingUploader from "../composable/upload_nothing";
|
|
61
66
|
import { triggerOnChange, useGlibInput } from "../composable/form";
|
|
62
67
|
import { nextTick } from "vue";
|
|
63
68
|
import { useFilesState, useFileUtils } from "../composable/file";
|
|
@@ -70,7 +75,8 @@ export default defineComponent({
|
|
|
70
75
|
props: { spec: { type: Object } },
|
|
71
76
|
components: { VIcon },
|
|
72
77
|
setup(props) {
|
|
73
|
-
const
|
|
78
|
+
const defaultUploader = props.spec.directUploadUrl ? dropUploader : nothingUploader;
|
|
79
|
+
const uploader = props.spec.strategy == 'delegate' ? delegateUploader : defaultUploader;
|
|
74
80
|
|
|
75
81
|
const fileSelect = ref(null);
|
|
76
82
|
const container = ref(null);
|
|
@@ -141,7 +141,7 @@ export default {
|
|
|
141
141
|
this.formCtx = { form: this.$refs.form };
|
|
142
142
|
if (onChange) this.$executeOnChange();
|
|
143
143
|
};
|
|
144
|
-
this.formElement.onchange = eventFiltering.debounce(onChangeHandler,
|
|
144
|
+
this.formElement.onchange = eventFiltering.debounce(onChangeHandler, 500);
|
|
145
145
|
|
|
146
146
|
this.formElement.oninput = (event) => this.glibForm.updateDirtyState(event);
|
|
147
147
|
}
|
|
@@ -70,6 +70,21 @@
|
|
|
70
70
|
</td>
|
|
71
71
|
</tr>
|
|
72
72
|
</tbody>
|
|
73
|
+
|
|
74
|
+
<tfoot>
|
|
75
|
+
<tr v-if="section.footer" :style="$styles(section.footer)">
|
|
76
|
+
<template v-if="section.footer.dataCells">
|
|
77
|
+
<th v-for="(cell, index) in section.footer.dataCells" :key="index"
|
|
78
|
+
:colSpan="colSpan(section.footer, index)">
|
|
79
|
+
{{ cell }}
|
|
80
|
+
</th>
|
|
81
|
+
</template>
|
|
82
|
+
<th v-for="(cell, index) in section.footer.cellViews" v-else :key="index"
|
|
83
|
+
:colSpan="colSpan(section.footer, index)">
|
|
84
|
+
<glib-component :spec="cell" />
|
|
85
|
+
</th>
|
|
86
|
+
</tr>
|
|
87
|
+
</tfoot>
|
|
73
88
|
</template>
|
|
74
89
|
</table>
|
|
75
90
|
|
package/nav/appBar.vue
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
<v-toolbar-items :class="navBar.collapseButtonsOnMobile ? 'hidden-sm-and-down' : null">
|
|
20
20
|
<template v-for="(btn, index) in navBar.rightButtons">
|
|
21
21
|
<common-dropdownMenu v-if="btn.childButtons" :key="index" :spec="btn" />
|
|
22
|
+
<v-divider vertical thickness="1" v-else-if="btn.type == 'divider'" :key="`divider_${index}`"></v-divider>
|
|
22
23
|
<common-button v-else :key="`right_${index}`" :spec="buttonSpec(btn)" />
|
|
23
24
|
</template>
|
|
24
25
|
</v-toolbar-items>
|
|
@@ -124,7 +125,7 @@ export default {
|
|
|
124
125
|
});
|
|
125
126
|
},
|
|
126
127
|
triggerDrawer() {
|
|
127
|
-
eventBus.$emit("drawers/toggle");
|
|
128
|
+
eventBus.$emit("glib-drawers/toggle");
|
|
128
129
|
},
|
|
129
130
|
// viewSourceEnabled: function () {
|
|
130
131
|
// // return process.env.NODE_ENV === "development";
|
package/nav/snackbar.vue
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<v-snackbar :vertical="vertical" v-model="show" :location="location" :color="gcolor"
|
|
3
|
-
:
|
|
4
|
-
:variant="variant">
|
|
2
|
+
<v-snackbar :vertical="vertical" v-model="show" :location="location" :color="gcolor" :timeout="spec.timeout"
|
|
3
|
+
:close-delay="spec.closeDelay" :variant="variant">
|
|
5
4
|
<common-message :spec="spec" />
|
|
6
5
|
|
|
7
6
|
<template v-slot:actions v-if="spec.buttons">
|
|
@@ -15,6 +14,7 @@
|
|
|
15
14
|
</template>
|
|
16
15
|
|
|
17
16
|
<script>
|
|
17
|
+
import Action from "../action";
|
|
18
18
|
import { determineColor, determineVariant } from '../utils/constant';
|
|
19
19
|
|
|
20
20
|
export default {
|
|
@@ -36,15 +36,19 @@ export default {
|
|
|
36
36
|
return this.spec.location || 'top';
|
|
37
37
|
}
|
|
38
38
|
},
|
|
39
|
+
watch: {
|
|
40
|
+
show: function (value) {
|
|
41
|
+
if (value) return;
|
|
42
|
+
Action.execute(this.spec.onClose, this);
|
|
43
|
+
}
|
|
44
|
+
},
|
|
39
45
|
methods: {
|
|
40
46
|
$ready() {
|
|
41
47
|
this.variant = determineVariant(this.spec.styleClasses, 'elevated');
|
|
42
48
|
this.vertical = [this.spec.styleClasses].flat().includes('vertical');
|
|
43
49
|
},
|
|
44
50
|
click: function (spec) {
|
|
45
|
-
const onClick = spec["onClick"];
|
|
46
51
|
this.show = false;
|
|
47
|
-
GLib.action.execute(onClick, this);
|
|
48
52
|
}
|
|
49
53
|
}
|
|
50
54
|
};
|