glib-web 4.4.0 → 4.5.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/action.js +5 -3
- package/actions/components/find.js +6 -0
- package/actions/components/replace.js +5 -4
- package/actions/components/replaceChildren.js +7 -3
- package/actions/components/set.js +4 -4
- package/actions/fields/focus.js +4 -3
- package/actions/fields/getDynamicGroupEntryValues.js +3 -3
- package/actions/fields/reset.js +7 -1
- package/actions/files/upload.js +32 -0
- package/actions/http/modifyFormData.js +7 -0
- package/actions/http/patch.js +5 -1
- package/actions/http/post.js +5 -1
- package/actions/http/put.js +5 -1
- package/actions/logics/set.js +30 -12
- package/actions/runMultiple.js +8 -3
- package/components/component.vue +2 -0
- package/components/composable/dirtyState.js +7 -5
- package/components/composable/file.js +1 -1
- package/components/composable/tree.js +66 -0
- package/components/composable/upload.js +1 -1
- package/components/fields/check/_featured.vue +96 -0
- package/components/fields/check/_thumbnail.vue +38 -0
- package/components/fields/check.vue +15 -1
- package/components/fields/file.vue +1 -1
- package/components/fields/multiUpload.vue +1 -1
- package/components/fields/radio/_featured.vue +117 -0
- package/components/fields/radio/_thumbnail.vue +32 -0
- package/components/fields/radio.vue +11 -10
- package/components/mixins/events.js +1 -1
- package/components/mixins/generic.js +1 -1
- package/components/mixins/styles.js +13 -4
- package/components/panels/association.vue +1 -1
- package/components/panels/column.vue +3 -3
- package/components/panels/custom.vue +1 -1
- package/components/panels/flow.vue +1 -1
- package/components/panels/form.vue +3 -1
- package/components/panels/grid.vue +2 -8
- package/components/panels/horizontal.vue +2 -1
- package/components/panels/list.vue +3 -3
- package/components/panels/responsive.vue +1 -1
- package/components/panels/scroll.vue +1 -1
- package/components/panels/split.vue +1 -1
- package/components/panels/table.vue +2 -2
- package/components/panels/timeline.vue +1 -1
- package/components/panels/tree/TreeNode.js +24 -0
- package/components/panels/tree/standard.vue +78 -0
- package/components/panels/tree.vue +41 -0
- package/components/panels/ul.vue +1 -1
- package/components/panels/vertical.vue +2 -1
- package/cypress/e2e/glib-web/formDynamic.cy.ts +6 -9
- package/cypress/e2e/glib-web/multiupload.cy.ts +8 -8
- package/nav/dialog.vue +1 -4
- package/package.json +1 -1
- package/plugins/updatableComponent.js +1 -6
- package/utils/component.js +3 -3
- package/actions/components/update.js +0 -12
package/action.js
CHANGED
|
@@ -66,7 +66,6 @@ import ActionsFieldsFocus from "./actions/fields/focus";
|
|
|
66
66
|
import ActionsFieldsBlur from "./actions/fields/blur";
|
|
67
67
|
import ActionsFieldsGetDynamicGroupEntryValues from "./actions/fields/getDynamicGroupEntryValues";
|
|
68
68
|
|
|
69
|
-
import ActionComponentsUpdate from "./actions/components/update";
|
|
70
69
|
import ActionComponentsFind from "./actions/components/find";
|
|
71
70
|
import ActionComponentsFindClosest from "./actions/components/findClosest";
|
|
72
71
|
import ActionComponentsReplace from "./actions/components/replace";
|
|
@@ -84,6 +83,8 @@ import ActionBottomBannersClose from "./actions/bottom_banners/close";
|
|
|
84
83
|
import ActionGlobalStatesWatch from "./actions/global_states/watch";
|
|
85
84
|
import ActionGlobalStatesSet from "./actions/global_states/set";
|
|
86
85
|
|
|
86
|
+
import ActionFilesUpload from "./actions/files/upload";
|
|
87
|
+
|
|
87
88
|
import { dialogs, jsonView, vueApp } from "./store";
|
|
88
89
|
|
|
89
90
|
const actions = {
|
|
@@ -152,7 +153,6 @@ const actions = {
|
|
|
152
153
|
"fields/blur": ActionsFieldsBlur,
|
|
153
154
|
"fields/getDynamicGroupEntryValues": ActionsFieldsGetDynamicGroupEntryValues,
|
|
154
155
|
|
|
155
|
-
"components/update": ActionComponentsUpdate,
|
|
156
156
|
"components/find": ActionComponentsFind,
|
|
157
157
|
"components/findClosest": ActionComponentsFindClosest,
|
|
158
158
|
"components/replace": ActionComponentsReplace,
|
|
@@ -168,7 +168,9 @@ const actions = {
|
|
|
168
168
|
"bottomBanners/close": ActionBottomBannersClose,
|
|
169
169
|
|
|
170
170
|
"globalStates/watch": ActionGlobalStatesWatch,
|
|
171
|
-
"globalStates/set": ActionGlobalStatesSet
|
|
171
|
+
"globalStates/set": ActionGlobalStatesSet,
|
|
172
|
+
|
|
173
|
+
"files/upload": ActionFilesUpload,
|
|
172
174
|
};
|
|
173
175
|
|
|
174
176
|
const customActions = {};
|
|
@@ -3,6 +3,12 @@ import Action from "../../action";
|
|
|
3
3
|
export default class {
|
|
4
4
|
execute(spec, component) {
|
|
5
5
|
const target = GLib.component.findById(spec.targetId);
|
|
6
|
+
|
|
7
|
+
if (!target) {
|
|
8
|
+
console.warn("Component ID not found", spec.targetId);
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
|
|
6
12
|
Action.execute(spec.onFind, target);
|
|
7
13
|
}
|
|
8
14
|
}
|
|
@@ -3,10 +3,11 @@ import Action from "../../action";
|
|
|
3
3
|
// Experimental. Can this be merged with `components_set` ?
|
|
4
4
|
export default class {
|
|
5
5
|
execute(spec, component) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
if (
|
|
9
|
-
|
|
6
|
+
let target = GLib.component.findById(spec.targetId);
|
|
7
|
+
|
|
8
|
+
if (!target) {
|
|
9
|
+
console.warn("Component ID not found", spec.targetId);
|
|
10
|
+
return;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
target.action_merge(spec.newView);
|
|
@@ -4,11 +4,15 @@ import Action from "../../action";
|
|
|
4
4
|
// Experimental
|
|
5
5
|
export default class {
|
|
6
6
|
execute(spec, component) {
|
|
7
|
-
const target = GLib.component.findById(spec.targetId)
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
const target = GLib.component.findById(spec.targetId);
|
|
8
|
+
|
|
9
|
+
if (!target) {
|
|
10
|
+
console.warn("Component ID not found", spec.targetId);
|
|
11
|
+
return;
|
|
10
12
|
}
|
|
11
13
|
|
|
14
|
+
Object.assign(target.spec.childViews, spec.childViews);
|
|
15
|
+
|
|
12
16
|
nextTick(() => {
|
|
13
17
|
Action.execute(spec.onReplace, target);
|
|
14
18
|
});
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
|
|
2
2
|
export default class {
|
|
3
3
|
execute(spec, component) {
|
|
4
|
-
let targetComponent = component;
|
|
4
|
+
let targetComponent = GLib.component.findById(spec.targetId);
|
|
5
5
|
|
|
6
|
-
if (
|
|
7
|
-
|
|
6
|
+
if (!targetComponent) {
|
|
7
|
+
console.warn("Component ID not found", spec.targetId);
|
|
8
|
+
return;
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
Utils.type.ifObject(spec.data, (data) => {
|
|
11
12
|
targetComponent.action_merge(data);
|
|
12
|
-
|
|
13
13
|
});
|
|
14
14
|
|
|
15
15
|
GLib.action.execute(spec.onSet, targetComponent);
|
package/actions/fields/focus.js
CHANGED
|
@@ -3,10 +3,11 @@ import Action from "../../action";
|
|
|
3
3
|
|
|
4
4
|
export default class {
|
|
5
5
|
execute(spec, component) {
|
|
6
|
-
let targetComponent = component;
|
|
6
|
+
let targetComponent = GLib.component.findById(spec.targetId);
|
|
7
7
|
|
|
8
|
-
if (
|
|
9
|
-
|
|
8
|
+
if (!targetComponent) {
|
|
9
|
+
console.warn("Component ID not found", spec.targetId);
|
|
10
|
+
return;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
targetComponent.action_focus();
|
|
@@ -3,13 +3,13 @@ export default class {
|
|
|
3
3
|
const dynamicGroupEntry = component.$closest("fields/internalDynamicGroupEntry");
|
|
4
4
|
if (dynamicGroupEntry) {
|
|
5
5
|
const values = dynamicGroupEntry.$values(spec.paramNameForFieldName || 'entry');
|
|
6
|
-
this.executeOnGet(spec, values)
|
|
6
|
+
this.executeOnGet(spec, values, component)
|
|
7
7
|
} else {
|
|
8
8
|
console.error('Action invoked outside of dynamicGroup')
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
executeOnGet(spec, formData) {
|
|
12
|
+
executeOnGet(spec, formData, component) {
|
|
13
13
|
Utils.type.ifObject(spec.onGet, onGet => {
|
|
14
14
|
const params = {
|
|
15
15
|
// Make sure to pass along the formData from the spec.
|
|
@@ -17,7 +17,7 @@ export default class {
|
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
const data = Object.assign({}, onGet, params);
|
|
20
|
-
GLib.action.execute(data,
|
|
20
|
+
GLib.action.execute(data, component);
|
|
21
21
|
});
|
|
22
22
|
}
|
|
23
23
|
}
|
package/actions/fields/reset.js
CHANGED
|
@@ -2,7 +2,13 @@ import { nextTick } from "vue";
|
|
|
2
2
|
|
|
3
3
|
export default class {
|
|
4
4
|
execute(properties, component) {
|
|
5
|
-
const target = GLib.component.findById(properties.targetId)
|
|
5
|
+
const target = GLib.component.findById(properties.targetId);
|
|
6
|
+
|
|
7
|
+
if (!target) {
|
|
8
|
+
console.warn("Component ID not found", properties.targetId);
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
|
|
6
12
|
target.action_resetValue();
|
|
7
13
|
|
|
8
14
|
nextTick(() => {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ref, watch } from "vue";
|
|
2
|
+
import { uploadFiles, setBusyWhenUploading } from "../../components/composable/upload";
|
|
3
|
+
import { useFilesState } from "../../components/composable/file";
|
|
4
|
+
import Action from "../../action";
|
|
5
|
+
|
|
6
|
+
export default class {
|
|
7
|
+
execute(spec, component, params) {
|
|
8
|
+
const files = ref({});
|
|
9
|
+
const droppedFiles = params.files;
|
|
10
|
+
const container = ref(component.$el);
|
|
11
|
+
const context = params.data;
|
|
12
|
+
|
|
13
|
+
// if drop item is not file
|
|
14
|
+
if (droppedFiles.length <= 0) {
|
|
15
|
+
Action.execute(spec.onFinished, {}, { glib: { context } });
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
setBusyWhenUploading({ files });
|
|
20
|
+
// if drop item is file
|
|
21
|
+
uploadFiles({ droppedFiles, files, spec, container });
|
|
22
|
+
|
|
23
|
+
const { uploaded } = useFilesState(files);
|
|
24
|
+
if (spec.onFinished) {
|
|
25
|
+
watch(uploaded, (val) => {
|
|
26
|
+
const signedIds = Object.values(files.value).map((f) => f.signedId);
|
|
27
|
+
const obj = Object.assign({}, { glib: { signedIds, context } });
|
|
28
|
+
if (val) Action.execute(spec.onFinished, {}, obj);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
package/actions/http/patch.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import modifyFormData from "./modifyFormData";
|
|
2
|
+
|
|
1
3
|
export default class {
|
|
2
|
-
execute(properties, controller) {
|
|
4
|
+
execute(properties, controller, params) {
|
|
5
|
+
modifyFormData(properties, params);
|
|
6
|
+
|
|
3
7
|
GLib.http.execute(properties, "PATCH", controller, response =>
|
|
4
8
|
GLib.action.handleResponse(response, controller)
|
|
5
9
|
);
|
package/actions/http/post.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import modifyFormData from "./modifyFormData";
|
|
2
|
+
|
|
1
3
|
export default class {
|
|
2
|
-
execute(properties, controller) {
|
|
4
|
+
execute(properties, controller, params) {
|
|
5
|
+
modifyFormData(properties, params);
|
|
6
|
+
|
|
3
7
|
GLib.http.execute(properties, "POST", controller, response =>
|
|
4
8
|
GLib.action.handleResponse(response, controller)
|
|
5
9
|
);
|
package/actions/http/put.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import modifyFormData from "./modifyFormData";
|
|
2
|
+
|
|
1
3
|
export default class {
|
|
2
|
-
execute(properties, controller) {
|
|
4
|
+
execute(properties, controller, params) {
|
|
5
|
+
modifyFormData(properties, params);
|
|
6
|
+
|
|
3
7
|
GLib.http.execute(properties, "PUT", controller, response =>
|
|
4
8
|
GLib.action.handleResponse(response, controller)
|
|
5
9
|
);
|
package/actions/logics/set.js
CHANGED
|
@@ -23,21 +23,39 @@ jsonLogic.add_operation("??", nullishCoalescing);
|
|
|
23
23
|
|
|
24
24
|
export default class {
|
|
25
25
|
execute(spec, component) {
|
|
26
|
-
let targetComponent
|
|
26
|
+
let targetComponent;
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
targetComponent =
|
|
28
|
+
const dynamicGroupEntry = component.$closest("fields/internalDynamicGroupEntry");
|
|
29
|
+
const targetIds = spec.targetId ? [spec.targetId] : spec.targetIds;
|
|
30
|
+
if (targetIds.length > 0) {
|
|
31
|
+
targetComponent = targetIds.map((id) => {
|
|
32
|
+
if (dynamicGroupEntry) {
|
|
33
|
+
id = dynamicGroupEntry.$populateIndexes(id);
|
|
34
|
+
}
|
|
35
|
+
return GLib.component.findById(id);
|
|
36
|
+
});
|
|
32
37
|
}
|
|
33
|
-
|
|
34
|
-
|
|
38
|
+
|
|
39
|
+
if (!targetComponent) {
|
|
40
|
+
console.warn("Component ID not found", spec.targetId);
|
|
41
|
+
return;
|
|
35
42
|
}
|
|
36
43
|
|
|
44
|
+
if (spec.debug) {
|
|
45
|
+
const targetComponents = Array.isArray(targetComponent) ? targetComponent : [targetComponent];
|
|
46
|
+
console.log("Evaluating...", targetComponents.map((comp) => comp.viewId));
|
|
47
|
+
}
|
|
37
48
|
let data = {};
|
|
38
49
|
Utils.type.ifObject(spec.conditionalData, (properties) => {
|
|
39
50
|
for (const key in properties) {
|
|
40
|
-
|
|
51
|
+
let condition = properties[key];
|
|
52
|
+
if (dynamicGroupEntry) {
|
|
53
|
+
condition = dynamicGroupEntry.$populateIndexes(condition);
|
|
54
|
+
}
|
|
55
|
+
data[key] = jsonLogic.apply(condition, Object.assign({}, fieldModels, spec.variables));
|
|
56
|
+
if (spec.debug) {
|
|
57
|
+
console.log("Result", condition, key, data[key]);
|
|
58
|
+
}
|
|
41
59
|
}
|
|
42
60
|
});
|
|
43
61
|
Utils.type.ifObject(spec.data, (additionalData) => {
|
|
@@ -47,16 +65,16 @@ export default class {
|
|
|
47
65
|
if (Object.keys(data).length > 0) {
|
|
48
66
|
// Array.isArray(targetComponent) ? targetComponent.forEach((comp) => comp.action_merge(data)) : targetComponent.action_merge(data);
|
|
49
67
|
|
|
50
|
-
const targetComponents = Array.isArray(targetComponent) ? targetComponent : [targetComponent]
|
|
68
|
+
const targetComponents = Array.isArray(targetComponent) ? targetComponent : [targetComponent];
|
|
51
69
|
targetComponents.forEach((comp) => {
|
|
52
|
-
comp.action_merge(data)
|
|
70
|
+
comp.action_merge(data);
|
|
53
71
|
|
|
54
72
|
if (spec.cacheData) {
|
|
55
73
|
Utils.type.ifString(comp.viewId, (viewId) => {
|
|
56
74
|
GLib.component.registerData(viewId, data);
|
|
57
|
-
})
|
|
75
|
+
});
|
|
58
76
|
}
|
|
59
|
-
})
|
|
77
|
+
});
|
|
60
78
|
}
|
|
61
79
|
|
|
62
80
|
GLib.action.execute(spec.onSet, targetComponent);
|
package/actions/runMultiple.js
CHANGED
|
@@ -3,9 +3,14 @@ export default class {
|
|
|
3
3
|
return true;
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
execute(
|
|
7
|
-
for (const
|
|
8
|
-
|
|
6
|
+
execute(spec, component) {
|
|
7
|
+
for (const actionSpec of spec.childActions) {
|
|
8
|
+
const params = {
|
|
9
|
+
// Make sure to pass along the formData from the spec.
|
|
10
|
+
formData: spec.formData
|
|
11
|
+
}
|
|
12
|
+
const properties = Object.assign({}, actionSpec, params);
|
|
13
|
+
GLib.action.execute(properties, component);
|
|
9
14
|
}
|
|
10
15
|
}
|
|
11
16
|
}
|
package/components/component.vue
CHANGED
|
@@ -111,6 +111,7 @@ import WebPanel from "./panels/web.vue";
|
|
|
111
111
|
import GridPanel from "./panels/grid.vue";
|
|
112
112
|
import TimelinePanel from "./panels/timeline.vue";
|
|
113
113
|
import AssociationPanel from "./panels/association.vue";
|
|
114
|
+
import TreePanel from "./panels/tree.vue";
|
|
114
115
|
|
|
115
116
|
import MultimediaVideo from "./multimedia/video.vue";
|
|
116
117
|
|
|
@@ -205,6 +206,7 @@ export default {
|
|
|
205
206
|
"panels-grid": GridPanel,
|
|
206
207
|
"panels-timeline": TimelinePanel,
|
|
207
208
|
"panels-association": AssociationPanel,
|
|
209
|
+
"panels-tree": TreePanel,
|
|
208
210
|
|
|
209
211
|
"multimedia-video": MultimediaVideo,
|
|
210
212
|
|
|
@@ -11,13 +11,15 @@ export function useDirtyState() {
|
|
|
11
11
|
return ctx().isFormDirty && !ctx().isFormSubmitted && !confirm(prompt);
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
-
const clearDirtyState = () => {
|
|
15
|
-
ctx
|
|
14
|
+
const clearDirtyState = (context) => {
|
|
15
|
+
const ctx = context || ctx;
|
|
16
|
+
ctx.isFormDirty = false;
|
|
16
17
|
};
|
|
17
18
|
|
|
18
|
-
const setDirty = () => ctx().isFormDirty = true;
|
|
19
|
+
const setDirty = (context) => (context || ctx()).isFormDirty = true;
|
|
19
20
|
|
|
20
|
-
const updateDirtyState = () => {
|
|
21
|
+
const updateDirtyState = (context) => {
|
|
22
|
+
const ctx = context || ctx;
|
|
21
23
|
const clean = Object.keys(dirtySpecs).reduce((prev, curr) => {
|
|
22
24
|
if (dirtySpecs[curr].disable) return prev;
|
|
23
25
|
const initValue = dirtySpecs[curr].initValue || '';
|
|
@@ -25,7 +27,7 @@ export function useDirtyState() {
|
|
|
25
27
|
return prev && (currValue.toString() == initValue.toString() || !currValue.toString());
|
|
26
28
|
}, true);
|
|
27
29
|
|
|
28
|
-
clean ? clearDirtyState() : setDirty();
|
|
30
|
+
clean ? clearDirtyState(ctx) : setDirty(ctx);
|
|
29
31
|
};
|
|
30
32
|
|
|
31
33
|
return { clearDirtyState, setDirty, isDirty, updateDirtyState };
|
|
@@ -58,7 +58,7 @@ function useFileUtils() {
|
|
|
58
58
|
function useFilesState(files) {
|
|
59
59
|
const uploading = computed(() => {
|
|
60
60
|
if (Object.values(files.value).filter((v) => v.status != null).length > 0) {
|
|
61
|
-
Object.values(files.value).reduce((prev, curr) => {
|
|
61
|
+
return Object.values(files.value).reduce((prev, curr) => {
|
|
62
62
|
if (curr.status == null) return prev;
|
|
63
63
|
return prev || curr.status == 'pending';
|
|
64
64
|
}, false);
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { inject, ref, watch } from "vue";
|
|
2
|
+
import Action from "../../action";
|
|
3
|
+
|
|
4
|
+
function useGlibTreeNode(props) {
|
|
5
|
+
const node = ref(props.node);
|
|
6
|
+
const dropBox = inject('dropBox');
|
|
7
|
+
const selected = inject('selected');
|
|
8
|
+
const currTreeNode = inject('currTreeNode');
|
|
9
|
+
|
|
10
|
+
watch(selected, (val) => {
|
|
11
|
+
selectIfIdMatch(val);
|
|
12
|
+
}, { immediate: true });
|
|
13
|
+
|
|
14
|
+
function selectIfIdMatch(value) {
|
|
15
|
+
node.value.selected = false;
|
|
16
|
+
if (!value) return;
|
|
17
|
+
if (node.value.id == value) {
|
|
18
|
+
node.value.expand = true;
|
|
19
|
+
node.value.selected = true;
|
|
20
|
+
let curr = node.value.parent;
|
|
21
|
+
while (curr != null) {
|
|
22
|
+
curr.expand = true;
|
|
23
|
+
curr = curr.parent;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function handleClick(node) {
|
|
29
|
+
Action.execute(node.onClick, {});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function handleDragOver(e, node) {
|
|
33
|
+
node.selected = true;
|
|
34
|
+
node.expand = true;
|
|
35
|
+
currTreeNode.value = node;
|
|
36
|
+
e.preventDefault();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function handleDragLeave(e, node) {
|
|
40
|
+
node.selected = false;
|
|
41
|
+
currTreeNode.value = null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function handleDrop(e, node) {
|
|
45
|
+
node.selected = false;
|
|
46
|
+
currTreeNode.value = null;
|
|
47
|
+
e.preventDefault();
|
|
48
|
+
|
|
49
|
+
dropBox.value = {};
|
|
50
|
+
|
|
51
|
+
const data = {};
|
|
52
|
+
const files = e.dataTransfer.files;
|
|
53
|
+
|
|
54
|
+
if (files.length <= 0) {
|
|
55
|
+
const dragData = JSON.parse(e.dataTransfer.getData('text'));
|
|
56
|
+
Object.assign(data, dragData, node.dropData);
|
|
57
|
+
} else {
|
|
58
|
+
Object.assign(data, node.dropData);
|
|
59
|
+
}
|
|
60
|
+
dropBox.value = { data, files };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return { node, handleClick, handleDragOver, handleDragLeave, handleDrop };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export { useGlibTreeNode };
|
|
@@ -2,7 +2,6 @@ import { watch } from 'vue';
|
|
|
2
2
|
import { triggerOnChange } from "./form";
|
|
3
3
|
import Uploader from "../../utils/glibDirectUpload";
|
|
4
4
|
import { vueApp } from "../../store";
|
|
5
|
-
import { showError } from "./alert";
|
|
6
5
|
import { useFilesState, useFileUtils } from "./file";
|
|
7
6
|
|
|
8
7
|
function submitOnAllUploaded({ url, formData, files }) {
|
|
@@ -70,6 +69,7 @@ function uploadOneFile({ files, key, spec, container, onAfterUploaded }) {
|
|
|
70
69
|
|
|
71
70
|
// validate per file, skip if invalid
|
|
72
71
|
if (!uploader.validateFile({ accepts: accepts })) {
|
|
72
|
+
console.log(accepts)
|
|
73
73
|
delete files.value[key];
|
|
74
74
|
return;
|
|
75
75
|
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="checked ? 'thumbnail-checked' : 'thumbnail-check'" @click="handleClick">
|
|
3
|
+
<v-checkbox :color="gcolor" v-model="fieldModel" :name="fieldName" :readonly="spec.readOnly"
|
|
4
|
+
:disabled="inputDisabled" :true-icon="spec.onIcon" :false-icon="spec.offIcon" :value="spec.value"
|
|
5
|
+
:true-value="spec.checkValue" :false-value="uncheckValue" hide-details @change="$emit('change')"
|
|
6
|
+
:rules="$validation()" :multiple="false">
|
|
7
|
+
<div class="thumbnail-content-wrapper">
|
|
8
|
+
<div class="thumbnail-check-img">
|
|
9
|
+
<img :src="spec.image.url" alt="" :width="spec.image.width" :height="spec.image.height" />
|
|
10
|
+
</div>
|
|
11
|
+
<div :class="checked ? 'thumbnail-check-label-checked' : 'thumbnail-check-label'">
|
|
12
|
+
{{ fieldModel ? spec.onLabel || spec.label : spec.label }}
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
</v-checkbox>
|
|
16
|
+
</div>
|
|
17
|
+
</template>
|
|
18
|
+
|
|
19
|
+
<script>
|
|
20
|
+
export default {
|
|
21
|
+
emits: ['oncheck'],
|
|
22
|
+
props: {
|
|
23
|
+
spec: { type: Object, required: true },
|
|
24
|
+
checkValue: { type: String }
|
|
25
|
+
},
|
|
26
|
+
data() {
|
|
27
|
+
return {
|
|
28
|
+
checked: this.spec.value ? true : false
|
|
29
|
+
};
|
|
30
|
+
},
|
|
31
|
+
methods: {
|
|
32
|
+
handleClick() {
|
|
33
|
+
this.checked = !this.checked
|
|
34
|
+
},
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<style scoped>
|
|
40
|
+
.thumbnail-check-img img {
|
|
41
|
+
margin: auto;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.thumbnail-check-label {
|
|
45
|
+
font-size: 22px;
|
|
46
|
+
color: black;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.thumbnail-check-label-checked {
|
|
50
|
+
font-size: 22px;
|
|
51
|
+
font-weight: 700;
|
|
52
|
+
color: #0A2A9E;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.thumbnail-check ::v-deep .v-selection-control__wrapper {
|
|
56
|
+
width: 240px;
|
|
57
|
+
height: 254px;
|
|
58
|
+
position: relative;
|
|
59
|
+
border: 1px solid #E6E6E6;
|
|
60
|
+
border-radius: 24px;
|
|
61
|
+
|
|
62
|
+
.v-selection-control__input {
|
|
63
|
+
border-radius: 0%;
|
|
64
|
+
position: absolute;
|
|
65
|
+
width: 240px;
|
|
66
|
+
height: 254px;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.v-selection-control__input i {
|
|
70
|
+
display: none;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.thumbnail-checked ::v-deep .v-selection-control__wrapper {
|
|
75
|
+
width: 240px;
|
|
76
|
+
height: 254px;
|
|
77
|
+
position: relative;
|
|
78
|
+
border: 2px solid #0A2A9E;
|
|
79
|
+
border-radius: 24px;
|
|
80
|
+
|
|
81
|
+
.v-selection-control__input {
|
|
82
|
+
border-radius: 0%;
|
|
83
|
+
position: absolute;
|
|
84
|
+
width: 240px;
|
|
85
|
+
height: 254px;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.v-selection-control__input i {
|
|
89
|
+
display: none;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.thumbnail-check ::v-deep .v-selection-control__input::before {
|
|
94
|
+
background-color: transparent
|
|
95
|
+
}
|
|
96
|
+
</style>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="checkbox-container">
|
|
3
|
+
<v-checkbox :color="gcolor" v-model="fieldModel" :name="fieldName" :readonly="spec.readOnly"
|
|
4
|
+
:disabled="inputDisabled" :true-icon="spec.onIcon" :false-icon="spec.offIcon" :value="spec.value"
|
|
5
|
+
:true-value="spec.checkValue" :false-value="uncheckValue" hide-details @change="$emit('change')"
|
|
6
|
+
:rules="$validation()" :multiple="false"></v-checkbox>
|
|
7
|
+
<div class="checkbox-icon">
|
|
8
|
+
<img :src="spec.image.url" :width="spec.image.width" :height="spec.image.height" alt="img" />
|
|
9
|
+
</div>
|
|
10
|
+
<p>{{ fieldModel ? spec.onLabel || spec.label : spec.label }} </p>
|
|
11
|
+
</div>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script>
|
|
15
|
+
export default {
|
|
16
|
+
props: {
|
|
17
|
+
spec: { type: Object, required: true },
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<style scoped>
|
|
23
|
+
.checkbox-container {
|
|
24
|
+
padding-left: 20px;
|
|
25
|
+
display: flex;
|
|
26
|
+
align-items: center;
|
|
27
|
+
gap: 8px;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.checkbox-container ::v-deep .v-selection-control__wrapper {
|
|
31
|
+
width: 0;
|
|
32
|
+
height: 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.checkbox-icon {
|
|
36
|
+
margin-left: 10px;
|
|
37
|
+
}
|
|
38
|
+
</style>
|
|
@@ -6,12 +6,26 @@
|
|
|
6
6
|
<v-checkbox :color="gcolor" v-model="fieldModel" :name="fieldName" :readonly="spec.readOnly"
|
|
7
7
|
:disabled="inputDisabled" :label="fieldModel ? spec.onLabel || spec.label : spec.label" :true-icon="spec.onIcon"
|
|
8
8
|
:false-icon="spec.offIcon" :value="spec.value" :true-value="spec.checkValue" :false-value="uncheckValue"
|
|
9
|
-
hide-details @change="onChange()" :rules="$validation()" :multiple="false"
|
|
9
|
+
hide-details @change="onChange()" :rules="$validation()" :multiple="false" v-if="!spec.image">
|
|
10
|
+
</v-checkbox>
|
|
11
|
+
<thumbnail-check v-if="spec.image && spec.image.template == 'thumbnail'" :spec=this.spec
|
|
12
|
+
@change="onChange"></thumbnail-check>
|
|
13
|
+
|
|
14
|
+
<featured-check v-if="spec.image && spec.image.template == 'featured'" :spec=this.spec
|
|
15
|
+
@change="onChange"></featured-check>
|
|
16
|
+
|
|
17
|
+
|
|
10
18
|
</div>
|
|
11
19
|
</template>
|
|
12
20
|
|
|
13
21
|
<script>
|
|
22
|
+
import ThumbnailCheck from "../fields/check/_thumbnail.vue";
|
|
23
|
+
import FeaturedCheck from "../fields/check/_featured.vue";
|
|
14
24
|
export default {
|
|
25
|
+
components: {
|
|
26
|
+
"thumbnail-check": ThumbnailCheck,
|
|
27
|
+
"featured-check": FeaturedCheck,
|
|
28
|
+
},
|
|
15
29
|
emits: ['oncheck'],
|
|
16
30
|
props: {
|
|
17
31
|
spec: { type: Object, required: true }
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
</div>
|
|
29
29
|
<input ref="directUploadFile" style="display: none" type="file" @change="uploadFiles" />
|
|
30
30
|
<v-progress-linear class="mt-1" v-if="showProgress" v-model="progress.value" />
|
|
31
|
-
<input type="hidden" :name="
|
|
31
|
+
<input type="hidden" :name="fieldName" :value="fileValue" :disabled="inputDisabled" />
|
|
32
32
|
</div>
|
|
33
33
|
</template>
|
|
34
34
|
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<p v-if="props.spec.hint" class="subtitle">{{ props.spec.hint }}</p>
|
|
11
11
|
</div>
|
|
12
12
|
|
|
13
|
-
<input v-for="(file, index) in files" type="hidden" :name="
|
|
13
|
+
<input v-for="(file, index) in files" type="hidden" :name="fieldName" :value="file.signedId"
|
|
14
14
|
:disabled="inputDisabled" :key="`hidden-${index}`">
|
|
15
15
|
</div>
|
|
16
16
|
|