glib-web 3.24.2 → 3.24.4
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/action.js +2 -2
- package/actions/components/set.js +8 -2
- package/actions/fields/blur.js +2 -2
- package/actions/fields/focus.js +2 -2
- package/app.vue +6 -40
- package/components/component.vue +1 -1
- package/components/composable/dropable.js +23 -2
- package/components/composable/pasteable.js +49 -0
- package/components/fields/_select.vue +20 -20
- package/components/fields/check.vue +5 -8
- package/components/fields/checkGroup.vue +2 -1
- package/components/fields/otpField.vue +0 -1
- package/components/fields/select.vue +1 -4
- package/components/fields/text.vue +0 -1
- package/components/label.vue +0 -15
- package/components/mixins/events.js +6 -6
- package/components/mixins/generic.js +1 -1
- package/components/mixins/styles.js +6 -3
- package/components/p.vue +1 -16
- package/components/panels/column.vue +17 -16
- package/components/treeView.vue +1 -0
- package/nav/dialog.vue +9 -2
- package/package.json +1 -1
- package/plugins/updatableComponent.js +3 -2
- package/utils/http.js +2 -2
- package/utils/uploader.js +3 -2
package/action.js
CHANGED
|
@@ -71,7 +71,7 @@ import ActionComponentsSet from "./actions/components/set";
|
|
|
71
71
|
|
|
72
72
|
import ActionListsAppend from "./actions/lists/append";
|
|
73
73
|
|
|
74
|
-
import { vueApp } from "./store";
|
|
74
|
+
import { dialogs, vueApp } from "./store";
|
|
75
75
|
|
|
76
76
|
const actions = {
|
|
77
77
|
runMultiple: ActionsRunMultiple,
|
|
@@ -206,7 +206,7 @@ export default class Action {
|
|
|
206
206
|
|
|
207
207
|
if (response.header || response.body || response.footer) {
|
|
208
208
|
Utils.http.forceComponentUpdate(() => {
|
|
209
|
-
const dialog =
|
|
209
|
+
const dialog = dialogs.last();
|
|
210
210
|
const updateDialog = windowMode ? false : Utils.type.isObject(dialog);
|
|
211
211
|
if (updateDialog) {
|
|
212
212
|
dialog.updateContent(response);
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
const setFileModel = (component, value) => {
|
|
2
|
+
component.fieldModel = component.$sanitizeValue(component.$externalizeValue(value));
|
|
3
|
+
};
|
|
4
|
+
|
|
5
|
+
|
|
1
6
|
export default class {
|
|
2
7
|
execute(spec, component) {
|
|
3
8
|
let targetComponent = component;
|
|
@@ -7,8 +12,9 @@ export default class {
|
|
|
7
12
|
}
|
|
8
13
|
|
|
9
14
|
Utils.type.ifObject(spec.data, (data) => {
|
|
10
|
-
targetComponent.action_merge(data)
|
|
11
|
-
|
|
15
|
+
targetComponent.action_merge(data);
|
|
16
|
+
if (data.value) setFileModel(targetComponent, data.value);
|
|
17
|
+
});
|
|
12
18
|
|
|
13
19
|
GLib.action.execute(spec.onSet, targetComponent);
|
|
14
20
|
}
|
package/actions/fields/blur.js
CHANGED
package/actions/fields/focus.js
CHANGED
package/app.vue
CHANGED
|
@@ -35,14 +35,16 @@ import FormPanel from "./components/panels/form.vue";
|
|
|
35
35
|
import { vueApp } from "./store";
|
|
36
36
|
import { useDirtyState } from "./components/composable/dirtyState";
|
|
37
37
|
import { useSocket } from "./components/composable/socket";
|
|
38
|
-
import {
|
|
39
|
-
import {
|
|
38
|
+
import { usePasteable } from "./components/composable/pasteable";
|
|
39
|
+
import { computed } from "vue";
|
|
40
40
|
|
|
41
41
|
const { watchDirtyState } = useDirtyState();
|
|
42
|
-
const { signedIds } = useDropableUtils();
|
|
43
42
|
|
|
44
43
|
export default {
|
|
45
|
-
setup() {
|
|
44
|
+
setup(props) {
|
|
45
|
+
const filePaster = computed(() => props.page.filePaster);
|
|
46
|
+
usePasteable(filePaster);
|
|
47
|
+
|
|
46
48
|
return { vueApp };
|
|
47
49
|
},
|
|
48
50
|
components: {
|
|
@@ -95,7 +97,6 @@ export default {
|
|
|
95
97
|
handler(val, oldVal) {
|
|
96
98
|
if (!val) return;
|
|
97
99
|
this.handleActionCable(val);
|
|
98
|
-
this.handlePasteFile(val);
|
|
99
100
|
},
|
|
100
101
|
immediate: true
|
|
101
102
|
}
|
|
@@ -123,41 +124,6 @@ export default {
|
|
|
123
124
|
this.actionCableConsumer = null;
|
|
124
125
|
}
|
|
125
126
|
},
|
|
126
|
-
handlePasteFile(val) {
|
|
127
|
-
// paste event
|
|
128
|
-
if (val.pasteFile) {
|
|
129
|
-
document.addEventListener('paste', this.onPaste);
|
|
130
|
-
} else {
|
|
131
|
-
document.removeEventListener('paste', this.onPaste);
|
|
132
|
-
}
|
|
133
|
-
},
|
|
134
|
-
async onPaste(event) {
|
|
135
|
-
const { directUploadUrl, accepts, url, inputName } = this.page.pasteFile;
|
|
136
|
-
const pastedFiles = event.clipboardData.files;
|
|
137
|
-
if (pastedFiles.length <= 0) return;
|
|
138
|
-
|
|
139
|
-
const files = ref({});
|
|
140
|
-
setBusyWhenUploading({ files });
|
|
141
|
-
const { uploaded } = useFilesState(files);
|
|
142
|
-
watch(uploaded, (val) => {
|
|
143
|
-
if (val) {
|
|
144
|
-
GLib.action.execute({
|
|
145
|
-
action: 'http/post',
|
|
146
|
-
url,
|
|
147
|
-
formData: inputName ? { [inputName]: { signed_ids: signedIds(files) } } : { signed_ids: signedIds(files) }
|
|
148
|
-
}, this);
|
|
149
|
-
files.value = {};
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
uploadFiles({
|
|
153
|
-
droppedFiles: pastedFiles,
|
|
154
|
-
files,
|
|
155
|
-
accepts,
|
|
156
|
-
directUploadUrl,
|
|
157
|
-
responseMessages: {}
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
},
|
|
161
127
|
$mounted() {
|
|
162
128
|
window.addEventListener(
|
|
163
129
|
"resize",
|
package/components/component.vue
CHANGED
|
@@ -2,6 +2,7 @@ import { computed, watch, onMounted, nextTick } from 'vue';
|
|
|
2
2
|
import { triggerOnChange } from "./form";
|
|
3
3
|
import Uploader from "../../utils/uploader";
|
|
4
4
|
import { vueApp } from "../../store";
|
|
5
|
+
import Action from "../../action";
|
|
5
6
|
|
|
6
7
|
function useDropableUtils() {
|
|
7
8
|
const makeKey = () => Math.random().toString(36).slice(2, 7);
|
|
@@ -77,11 +78,31 @@ function setBusyWhenUploading({ files }) {
|
|
|
77
78
|
});
|
|
78
79
|
}
|
|
79
80
|
|
|
81
|
+
const showError = (options) => {
|
|
82
|
+
const { body, button } = options;
|
|
83
|
+
Action.execute(
|
|
84
|
+
{
|
|
85
|
+
action: 'snackbars/select',
|
|
86
|
+
message: body,
|
|
87
|
+
styleClasses: ['error', 'vertical'],
|
|
88
|
+
buttons: [{ text: button }]
|
|
89
|
+
},
|
|
90
|
+
{}
|
|
91
|
+
);
|
|
92
|
+
};
|
|
80
93
|
function uploadFiles({ droppedFiles, files, directUploadUrl, accepts = {}, responseMessages = {}, container }) {
|
|
81
|
-
const maxFileLength = accepts
|
|
94
|
+
const { maxFileLength } = accepts;
|
|
95
|
+
// const droppedFilesSizeInByte = Array.from(droppedFiles).reduce((prev, curr) => prev + curr.size, 0);
|
|
96
|
+
|
|
97
|
+
// if (droppedFilesSizeInByte > maxFileSize * 1000) {
|
|
98
|
+
// showError(accepts.maxFileSizeErrorText);
|
|
99
|
+
|
|
100
|
+
// return;
|
|
101
|
+
// }
|
|
82
102
|
|
|
83
103
|
if (droppedFiles.length > maxFileLength) {
|
|
84
|
-
|
|
104
|
+
showError(accepts.maxFileLengthErrorText);
|
|
105
|
+
|
|
85
106
|
return;
|
|
86
107
|
}
|
|
87
108
|
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { onMounted, ref, watch } from "vue";
|
|
2
|
+
import { uploadFiles, useFilesState, setBusyWhenUploading, useDropableUtils } from "./dropable";
|
|
3
|
+
|
|
4
|
+
const { signedIds } = useDropableUtils();
|
|
5
|
+
|
|
6
|
+
const onPaste = async (event, filePaster) => {
|
|
7
|
+
const { directUploadUrl, accepts, url, inputName } = filePaster;
|
|
8
|
+
const pastedFiles = event.clipboardData.files;
|
|
9
|
+
if (pastedFiles.length <= 0) return;
|
|
10
|
+
|
|
11
|
+
const files = ref({});
|
|
12
|
+
setBusyWhenUploading({ files });
|
|
13
|
+
const { uploaded } = useFilesState(files);
|
|
14
|
+
watch(uploaded, (val) => {
|
|
15
|
+
if (val) {
|
|
16
|
+
GLib.action.execute({
|
|
17
|
+
action: 'http/post',
|
|
18
|
+
url,
|
|
19
|
+
formData: inputName ? { [inputName]: { signed_ids: signedIds(files) } } : { signed_ids: signedIds(files) }
|
|
20
|
+
}, {});
|
|
21
|
+
files.value = {};
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
uploadFiles({
|
|
25
|
+
droppedFiles: pastedFiles,
|
|
26
|
+
files,
|
|
27
|
+
accepts,
|
|
28
|
+
directUploadUrl,
|
|
29
|
+
responseMessages: {}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
let handler = () => { };
|
|
35
|
+
|
|
36
|
+
function usePasteable(filePaster) {
|
|
37
|
+
handler = (event) => onPaste(event, filePaster.value);
|
|
38
|
+
onMounted(() => {
|
|
39
|
+
watch(filePaster, (val, oldVal) => {
|
|
40
|
+
if (val) {
|
|
41
|
+
document.addEventListener('paste', handler);
|
|
42
|
+
} else {
|
|
43
|
+
document.removeEventListener('paste', handler);
|
|
44
|
+
}
|
|
45
|
+
}, { immediate: true });
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export { usePasteable };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div ref="container" :style="$styles()" :class="classes()">
|
|
3
|
-
<v-autocomplete :color="gcolor" v-model="fieldModel" :label="label" :items="
|
|
4
|
-
:
|
|
5
|
-
:rules="rules" persistent-hint :append-icon="append.icon" validate-on="blur"
|
|
6
|
-
:closable-chips="spec.multiple" :density="density" persistent-placeholder
|
|
7
|
-
@focus="focused = true" @blur="focused = false">
|
|
3
|
+
<v-autocomplete :color="gcolor" v-model="fieldModel" :label="label" :items="normalizedOptions"
|
|
4
|
+
:chips="spec.multiple" :multiple="spec.multiple" :readonly="spec.readOnly" :clearable="!spec.readOnly"
|
|
5
|
+
:placeholder="spec.placeholder" :rules="rules" persistent-hint :append-icon="append.icon" validate-on="blur"
|
|
6
|
+
item-title='text' :variant="variant" :closable-chips="spec.multiple" :density="density" persistent-placeholder
|
|
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">
|
|
@@ -54,6 +54,20 @@ export default {
|
|
|
54
54
|
};
|
|
55
55
|
},
|
|
56
56
|
computed: {
|
|
57
|
+
normalizedOptions() {
|
|
58
|
+
return this.spec.options.map(i => {
|
|
59
|
+
switch (i.type) {
|
|
60
|
+
case "label":
|
|
61
|
+
return { header: i.text };
|
|
62
|
+
case "divider":
|
|
63
|
+
return { divider: true };
|
|
64
|
+
default:
|
|
65
|
+
return Object.assign({}, i, {
|
|
66
|
+
props: { subtitle: i.subtitle }
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
},
|
|
57
71
|
values() {
|
|
58
72
|
// Depends on whether the field is single or multiple
|
|
59
73
|
if (this.$type.isArray(this.fieldModel)) {
|
|
@@ -88,25 +102,11 @@ export default {
|
|
|
88
102
|
$ready() {
|
|
89
103
|
this.updateData(false);
|
|
90
104
|
},
|
|
91
|
-
normalizedOptions() {
|
|
92
|
-
return this.spec.options.map(i => {
|
|
93
|
-
switch (i.type) {
|
|
94
|
-
case "label":
|
|
95
|
-
return { header: i.text };
|
|
96
|
-
case "divider":
|
|
97
|
-
return { divider: true };
|
|
98
|
-
default:
|
|
99
|
-
return Object.assign({}, i, {
|
|
100
|
-
props: { subtitle: i.subtitle }
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
},
|
|
105
105
|
classes() {
|
|
106
106
|
return this.$classes().concat("g-text-field--hintless");
|
|
107
107
|
},
|
|
108
108
|
updateData(reinitValue) {
|
|
109
|
-
this.options = this.normalizedOptions();
|
|
109
|
+
// this.options = this.normalizedOptions();
|
|
110
110
|
this.append = this.spec.append || {};
|
|
111
111
|
this.rules = this.$validation();
|
|
112
112
|
|
|
@@ -22,6 +22,11 @@ export default {
|
|
|
22
22
|
uncheckValue: this.spec.uncheckValue
|
|
23
23
|
};
|
|
24
24
|
},
|
|
25
|
+
computed: {
|
|
26
|
+
fieldName() {
|
|
27
|
+
return this.spec.name || this.spec.parentName;
|
|
28
|
+
}
|
|
29
|
+
},
|
|
25
30
|
methods: {
|
|
26
31
|
$ready() {
|
|
27
32
|
this.updateData();
|
|
@@ -45,14 +50,6 @@ export default {
|
|
|
45
50
|
updateData() {
|
|
46
51
|
this.groupElement = this.$el.closest("[data-component=checkGroup]");
|
|
47
52
|
|
|
48
|
-
let groupName = null;
|
|
49
|
-
this.$type.ifObject(
|
|
50
|
-
this.groupElement,
|
|
51
|
-
val => (groupName = val.getAttribute("name"))
|
|
52
|
-
);
|
|
53
|
-
|
|
54
|
-
this.fieldName = this.spec.name || groupName;
|
|
55
|
-
|
|
56
53
|
// this.fieldModel = this.spec.checked
|
|
57
54
|
// ? this.spec.checkValue
|
|
58
55
|
// : this.spec.value;
|
|
@@ -70,12 +70,13 @@ export default {
|
|
|
70
70
|
childSpec(item) {
|
|
71
71
|
if (this.spec.readOnly) {
|
|
72
72
|
return Object.assign(item, {
|
|
73
|
+
parentName: this.spec.name,
|
|
73
74
|
readOnly: this.spec.readOnly,
|
|
74
75
|
onChange: this.spec.onChange,
|
|
75
76
|
});
|
|
76
77
|
}
|
|
77
78
|
|
|
78
|
-
return Object.assign(item, { onChange: this.spec.onChange });
|
|
79
|
+
return Object.assign(item, { onChange: this.spec.onChange, parentName: this.spec.name });
|
|
79
80
|
},
|
|
80
81
|
},
|
|
81
82
|
};
|
package/components/label.vue
CHANGED
|
@@ -13,22 +13,7 @@ export default {
|
|
|
13
13
|
props: {
|
|
14
14
|
spec: { type: Object, required: true }
|
|
15
15
|
},
|
|
16
|
-
data: function () {
|
|
17
|
-
return {
|
|
18
|
-
// text: " "
|
|
19
|
-
};
|
|
20
|
-
},
|
|
21
16
|
methods: {
|
|
22
|
-
$ready() {
|
|
23
|
-
// this.$wsInitActionCable(this.spec.actionCable);
|
|
24
|
-
|
|
25
|
-
// this.text = this.spec.text;
|
|
26
|
-
},
|
|
27
|
-
// action_set(spec) {
|
|
28
|
-
// if (spec.user_id !== spec.filterKey) {
|
|
29
|
-
// this.text = spec.text;
|
|
30
|
-
// }
|
|
31
|
-
// },
|
|
32
17
|
action_merge(mergedSpec) {
|
|
33
18
|
Object.assign(this.spec, mergedSpec);
|
|
34
19
|
this.$ready();
|
|
@@ -30,12 +30,12 @@ export default {
|
|
|
30
30
|
},
|
|
31
31
|
created() {
|
|
32
32
|
// watch components/update
|
|
33
|
-
if (this.spec) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
33
|
+
// if (this.spec) {
|
|
34
|
+
// this.$watch(
|
|
35
|
+
// () => Object.keys(this.spec).map((specKey) => this.spec[specKey]),
|
|
36
|
+
// () => this._ready()
|
|
37
|
+
// );
|
|
38
|
+
// }
|
|
39
39
|
|
|
40
40
|
this.$created();
|
|
41
41
|
},
|
|
@@ -11,7 +11,7 @@ const isNeedToBeFixed = (val, component) => {
|
|
|
11
11
|
export default {
|
|
12
12
|
data: function () {
|
|
13
13
|
return {
|
|
14
|
-
fieldName: null,
|
|
14
|
+
// fieldName: null,
|
|
15
15
|
fieldModel: null,
|
|
16
16
|
_show: true,
|
|
17
17
|
_watchers: [],
|
|
@@ -35,6 +35,9 @@ export default {
|
|
|
35
35
|
panelContext: { default: {} }
|
|
36
36
|
},
|
|
37
37
|
computed: {
|
|
38
|
+
fieldName() {
|
|
39
|
+
if (this.spec && this.spec.name) return this.spec.name;
|
|
40
|
+
},
|
|
38
41
|
inputDisabled() {
|
|
39
42
|
let disabled = false;
|
|
40
43
|
if (Object.keys(this.panelContext).length > 0) { // handle nested
|
|
@@ -82,7 +85,7 @@ export default {
|
|
|
82
85
|
},
|
|
83
86
|
methods: {
|
|
84
87
|
viewKey(item, index) {
|
|
85
|
-
if (!item) return '';
|
|
88
|
+
if (!item || !item.view) return '';
|
|
86
89
|
// random string to trigger render
|
|
87
90
|
const forceUpdate = (Math.random() + 1).toString(36).substring(7);
|
|
88
91
|
if (item.view.startsWith('charts/')) return forceUpdate;
|
|
@@ -266,7 +269,7 @@ export default {
|
|
|
266
269
|
if (hasCondition || isField) {
|
|
267
270
|
// Has to be executed before $ready(). This executes regardless of whether a form is found because fields
|
|
268
271
|
// may be used without a form.
|
|
269
|
-
this.fieldName = this.spec.name;
|
|
272
|
+
// this.fieldName = this.spec.name;
|
|
270
273
|
|
|
271
274
|
// Avoid user input getting removed when updating certain parts of the page.
|
|
272
275
|
if (valueChanged) {
|
package/components/p.vue
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
3
|
-
<p :style="genericStyles()" :class="$classes()">{{ text }}</p>
|
|
2
|
+
<p :style="$styles()" :class="$classes()">{{ spec.text }}</p>
|
|
4
3
|
</template>
|
|
5
4
|
|
|
6
5
|
<script>
|
|
@@ -9,21 +8,7 @@
|
|
|
9
8
|
export default {
|
|
10
9
|
props: {
|
|
11
10
|
spec: { type: Object, required: true }
|
|
12
|
-
},
|
|
13
|
-
computed: {
|
|
14
|
-
text() {
|
|
15
|
-
return this.spec.text;
|
|
16
|
-
}
|
|
17
11
|
}
|
|
18
|
-
// computed: {
|
|
19
|
-
// compiledText() {
|
|
20
|
-
// if (this.spec.format == "markdown") {
|
|
21
|
-
// return marked(this.spec.text, { sanitize: true });
|
|
22
|
-
// } else {
|
|
23
|
-
// return this.spec.text;
|
|
24
|
-
// }
|
|
25
|
-
// }
|
|
26
|
-
// }
|
|
27
12
|
};
|
|
28
13
|
</script>
|
|
29
14
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<v-col :xxl="xxl.cols" :xl="xl.cols" :lg="lg.cols" :md="md.cols" :sm="sm.cols" :style="cssStyles
|
|
2
|
+
<v-col :xxl="xxl.cols" :xl="xl.cols" :lg="lg.cols" :md="md.cols" :sm="sm.cols" :style="cssStyles" :class="$classes()"
|
|
3
3
|
:cols="xs.cols || 12" :order-xl="xl.order" :order-lg="lg.order" :order-md="md.order" :order-sm="sm.order"
|
|
4
4
|
:order="xs.order">
|
|
5
5
|
<common-responsive :spec="innerSpec()" :full-height="fullHeight" />
|
|
@@ -26,21 +26,7 @@ export default {
|
|
|
26
26
|
computed: {
|
|
27
27
|
fullHeight() {
|
|
28
28
|
// Provide a default name so the panel will not be nameless when used in predefined layouts (e.g. page.body, list.header, etc.)
|
|
29
|
-
return this.spec.height == 'matchParent'
|
|
30
|
-
},
|
|
31
|
-
},
|
|
32
|
-
methods: {
|
|
33
|
-
$ready() {
|
|
34
|
-
this.xxl = this.spec.xxl || this.xxl;
|
|
35
|
-
this.xl = this.spec.xl || this.xl;
|
|
36
|
-
this.lg = this.spec.lg || this.lg;
|
|
37
|
-
this.md = this.spec.md || this.md;
|
|
38
|
-
this.sm = this.spec.sm || this.sm;
|
|
39
|
-
this.xs = this.spec.xs || this.xs;
|
|
40
|
-
},
|
|
41
|
-
innerSpec() {
|
|
42
|
-
// Remove properties that are handled by the container (i.e. v-col).
|
|
43
|
-
return new Hash(this.spec).without("padding").without("styleClasses");
|
|
29
|
+
return this.spec.height == 'matchParent';
|
|
44
30
|
},
|
|
45
31
|
cssStyles() {
|
|
46
32
|
const styles = Object.assign({}, this.$styles());
|
|
@@ -111,7 +97,22 @@ export default {
|
|
|
111
97
|
// Don't interfere with v-col's height (which is full height by default anyway) in order not to break the full height behaviour.
|
|
112
98
|
// Let this be handled by the child (responsive) panel instead.
|
|
113
99
|
return new Hash(styles).without("height");
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
methods: {
|
|
103
|
+
$ready() {
|
|
104
|
+
this.xxl = this.spec.xxl || this.xxl;
|
|
105
|
+
this.xl = this.spec.xl || this.xl;
|
|
106
|
+
this.lg = this.spec.lg || this.lg;
|
|
107
|
+
this.md = this.spec.md || this.md;
|
|
108
|
+
this.sm = this.spec.sm || this.sm;
|
|
109
|
+
this.xs = this.spec.xs || this.xs;
|
|
114
110
|
},
|
|
111
|
+
innerSpec() {
|
|
112
|
+
// Remove properties that are handled by the container (i.e. v-col).
|
|
113
|
+
return new Hash(this.spec).without("padding").without("styleClasses");
|
|
114
|
+
},
|
|
115
|
+
|
|
115
116
|
applyStyles(styles, spec) {
|
|
116
117
|
Object.assign(styles, this.$styles(spec));
|
|
117
118
|
Utils.type.ifBoolean(spec.hide, () => {
|
package/components/treeView.vue
CHANGED
package/nav/dialog.vue
CHANGED
|
@@ -45,12 +45,17 @@ import Action from "../action";
|
|
|
45
45
|
import FormPanel from "../components/panels/form.vue";
|
|
46
46
|
import { useDirtyState } from "../components/composable/dirtyState";
|
|
47
47
|
import { dialogs } from "../store";
|
|
48
|
+
import { ref } from "vue";
|
|
49
|
+
import { usePasteable } from "../components/composable/pasteable";
|
|
48
50
|
|
|
49
51
|
export default {
|
|
50
52
|
expose: ['isFormDirty', 'model'],
|
|
51
|
-
setup() {
|
|
53
|
+
setup(props) {
|
|
54
|
+
const filePaster = ref(undefined);
|
|
55
|
+
usePasteable(filePaster);
|
|
56
|
+
|
|
52
57
|
const { isDirty } = useDirtyState();
|
|
53
|
-
return { isDirty };
|
|
58
|
+
return { isDirty, filePaster };
|
|
54
59
|
},
|
|
55
60
|
components: {
|
|
56
61
|
"panels-form": FormPanel,
|
|
@@ -129,6 +134,7 @@ export default {
|
|
|
129
134
|
// },
|
|
130
135
|
close() {
|
|
131
136
|
if (!this.isDirty()) {
|
|
137
|
+
this.filePaster = null;
|
|
132
138
|
dialogs.remove(this);
|
|
133
139
|
this.model = false;
|
|
134
140
|
}
|
|
@@ -167,6 +173,7 @@ export default {
|
|
|
167
173
|
"GET",
|
|
168
174
|
this,
|
|
169
175
|
(response) => {
|
|
176
|
+
this.filePaster = response.filePaster;
|
|
170
177
|
Utils.http.forceComponentUpdate(() => {
|
|
171
178
|
this.urlLoaded = true;
|
|
172
179
|
this.message = "";
|
package/package.json
CHANGED
|
@@ -19,7 +19,8 @@ export default {
|
|
|
19
19
|
GLib.component.vueName(this)
|
|
20
20
|
);
|
|
21
21
|
}
|
|
22
|
-
|
|
22
|
+
const newComponent = this.$refs.delegate || this;
|
|
23
|
+
GLib.component.register(id, newComponent);
|
|
23
24
|
}
|
|
24
25
|
},
|
|
25
26
|
$tearDown() {
|
|
@@ -30,7 +31,7 @@ export default {
|
|
|
30
31
|
},
|
|
31
32
|
$registryEnabled() {
|
|
32
33
|
// Common classes such as `_select` need to return false so that it doesn't override its parent (e.g. `select`).
|
|
33
|
-
return
|
|
34
|
+
return false;
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
37
|
});
|
package/utils/http.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Type from "./type";
|
|
2
2
|
import Action from "../action";
|
|
3
3
|
import { nextTick } from 'vue';
|
|
4
|
-
import { ctx, vueApp } from "../store";
|
|
4
|
+
import { ctx, dialogs, vueApp } from "../store";
|
|
5
5
|
|
|
6
6
|
let loading = false;
|
|
7
7
|
|
|
@@ -80,7 +80,7 @@ export default class {
|
|
|
80
80
|
const htmlUrl = Utils.url.htmlUrl(properties["url"]);
|
|
81
81
|
|
|
82
82
|
Utils.http.execute(properties, "GET", component, (data, response) => {
|
|
83
|
-
const pushHistory = windowMode ? true : !Utils.type.isObject(
|
|
83
|
+
const pushHistory = windowMode ? true : !Utils.type.isObject(dialogs.last());
|
|
84
84
|
if (htmlUrl !== currentUrl && pushHistory) {
|
|
85
85
|
const redirectUrl = Utils.url.htmlUrl(response.url);
|
|
86
86
|
Utils.history.pushPage(data, redirectUrl);
|
package/utils/uploader.js
CHANGED
|
@@ -65,7 +65,7 @@ export default class Uploader {
|
|
|
65
65
|
[spec.fileType].flat().forEach(key => {
|
|
66
66
|
const acceptsRegex = new RegExp(mimeType[key]);
|
|
67
67
|
if (!mimeType[key]) {
|
|
68
|
-
console.error(`Mime type not found: ${key}`)
|
|
68
|
+
console.error(`Mime type not found: ${key}`);
|
|
69
69
|
}
|
|
70
70
|
if (acceptsRegex.test(this.file.type)) {
|
|
71
71
|
validFileType = true;
|
|
@@ -79,7 +79,8 @@ export default class Uploader {
|
|
|
79
79
|
|
|
80
80
|
if (spec.maxFileSize) {
|
|
81
81
|
if (this.file.size > spec.maxFileSize * MB_SIZE) {
|
|
82
|
-
|
|
82
|
+
// support for old version, maxFileSizeErrorText is type of Object not String
|
|
83
|
+
if (typeof spec.maxFileSizeErrorText == 'string') alert(spec.maxFileSizeErrorText || "File too big");
|
|
83
84
|
return false;
|
|
84
85
|
}
|
|
85
86
|
}
|