glib-web 3.8.2 → 3.10.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/LICENSE +0 -0
- package/actions/auth/creditCard.js +0 -0
- package/actions/auth/restart.js +0 -0
- package/actions/commands/copy.js +0 -0
- package/actions/dialogs/close.js +0 -0
- package/actions/dialogs/notification.js +0 -0
- package/actions/dialogs/oauth.js +0 -0
- package/actions/dialogs/open.js +0 -0
- package/actions/dialogs/options.js +0 -0
- package/actions/dialogs/reload.js +0 -0
- package/actions/dialogs/show.js +0 -0
- package/actions/forms/submit.js +2 -1
- package/actions/http/delete.js +0 -0
- package/actions/http/patch.js +0 -0
- package/actions/http/post.js +0 -0
- package/actions/http/put.js +0 -0
- package/actions/runMultiple.js +0 -0
- package/actions/sheets/select.js +0 -0
- package/actions/snackbars/alert.js +0 -0
- package/actions/snackbars/select.js +0 -0
- package/actions/timeouts/set.js +0 -0
- package/actions/windows/openWeb.js +0 -0
- package/actions/windows/print.js +0 -0
- package/components/_message.vue +0 -0
- package/components/calendar.vue +0 -0
- package/components/composable/dirtyState.js +5 -6
- package/components/fields/country/countries.js +0 -0
- package/components/fields/country/regions.js +0 -0
- package/components/fields/creditCard.vue +0 -0
- package/components/fields/dynamicGroup.vue +90 -43
- package/components/fields/googlePlace.vue +0 -0
- package/components/fields/phone/countries.js +0 -0
- package/components/fields/phone/sprite.css +0 -0
- package/components/fields/stripeToken.vue +0 -0
- package/components/h1.vue +0 -0
- package/components/h2.vue +0 -0
- package/components/h3.vue +0 -0
- package/components/h5.vue +0 -0
- package/components/h6.vue +0 -0
- package/components/hr.vue +0 -0
- package/components/html.vue +0 -0
- package/components/icon.vue +0 -0
- package/components/mixins/chart/annotation.js +0 -0
- package/components/mixins/chart/tooltip.js +0 -0
- package/components/mixins/dataset.js +0 -0
- package/components/mixins/extension.js +0 -0
- package/components/mixins/longClick.js +0 -0
- package/components/mixins/scrolling.js +0 -0
- package/components/mixins/styles.js +6 -0
- package/components/mixins/table/export.js +0 -0
- package/components/mixins/table/import.js +0 -0
- package/components/mixins/text.js +0 -0
- package/components/multimedia/video.vue +0 -0
- package/components/panels/carousel.vue +0 -0
- package/components/panels/form.vue +4 -4
- package/components/panels/list.vue +6 -2
- package/components/panels/web.vue +0 -0
- package/components/spacer.vue +0 -0
- package/keys.js +0 -0
- package/nav/dialog.vue +4 -3
- package/package.json +1 -1
- package/static/plugins/alignment/alignment.js +0 -0
- package/static/plugins/alignment/alignment.min.js +0 -0
- package/static/plugins/beyondgrammar/beyondgrammar.js +0 -0
- package/static/plugins/beyondgrammar/beyondgrammar.min.js +0 -0
- package/static/plugins/blockcode/blockcode.js +0 -0
- package/static/plugins/blockcode/blockcode.min.js +0 -0
- package/static/plugins/clips/clips.js +0 -0
- package/static/plugins/clips/clips.min.js +0 -0
- package/static/plugins/counter/counter.js +0 -0
- package/static/plugins/counter/counter.min.js +0 -0
- package/static/plugins/definedlinks/definedlinks.js +0 -0
- package/static/plugins/definedlinks/definedlinks.min.js +0 -0
- package/static/plugins/handle/handle.js +0 -0
- package/static/plugins/handle/handle.min.js +0 -0
- package/static/plugins/icons/icons.js +0 -0
- package/static/plugins/icons/icons.min.js +0 -0
- package/static/plugins/imageposition/imageposition.js +0 -0
- package/static/plugins/imageposition/imageposition.min.js +0 -0
- package/static/plugins/inlineformat/inlineformat.js +0 -0
- package/static/plugins/inlineformat/inlineformat.min.js +0 -0
- package/static/plugins/removeformat/removeformat.js +0 -0
- package/static/plugins/removeformat/removeformat.min.js +0 -0
- package/static/plugins/selector/selector.js +0 -0
- package/static/plugins/selector/selector.min.js +0 -0
- package/static/plugins/specialchars/specialchars.js +0 -0
- package/static/plugins/specialchars/specialchars.min.js +0 -0
- package/static/plugins/textdirection/textdirection.js +0 -0
- package/static/plugins/textdirection/textdirection.min.js +0 -0
- package/static/plugins/textexpander/textexpander.js +0 -0
- package/static/plugins/textexpander/textexpander.min.js +0 -0
- package/static/plugins/underline/underline.js +0 -0
- package/static/plugins/underline/underline.min.js +0 -0
- package/static/redactorx.css +0 -0
- package/static/redactorx.min.css +0 -0
- package/static/redactorx.min.js +0 -0
- package/static/redactorx.usm.min.js +0 -0
- package/store.js +2 -0
- package/styles/test.sass +0 -0
- package/styles/test.scss +0 -0
- package/templates/editable.vue +236 -0
- package/templates/thumbnail.vue +21 -10
- package/templates/unsupported.vue +0 -0
- package/utils/dom.js +0 -0
- package/utils/form.js +16 -5
- package/utils/helper.js +0 -0
- package/utils/http.js +6 -5
- package/utils/type.js +0 -0
- package/utils/url.js +4 -0
package/LICENSE
CHANGED
|
File without changes
|
|
File without changes
|
package/actions/auth/restart.js
CHANGED
|
File without changes
|
package/actions/commands/copy.js
CHANGED
|
File without changes
|
package/actions/dialogs/close.js
CHANGED
|
File without changes
|
|
File without changes
|
package/actions/dialogs/oauth.js
CHANGED
|
File without changes
|
package/actions/dialogs/open.js
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/actions/dialogs/show.js
CHANGED
|
File without changes
|
package/actions/forms/submit.js
CHANGED
package/actions/http/delete.js
CHANGED
|
File without changes
|
package/actions/http/patch.js
CHANGED
|
File without changes
|
package/actions/http/post.js
CHANGED
|
File without changes
|
package/actions/http/put.js
CHANGED
|
File without changes
|
package/actions/runMultiple.js
CHANGED
|
File without changes
|
package/actions/sheets/select.js
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/actions/timeouts/set.js
CHANGED
|
File without changes
|
|
File without changes
|
package/actions/windows/print.js
CHANGED
|
File without changes
|
package/components/_message.vue
CHANGED
|
File without changes
|
package/components/calendar.vue
CHANGED
|
File without changes
|
|
@@ -1,27 +1,26 @@
|
|
|
1
1
|
import { watchEffect } from "vue";
|
|
2
|
-
import {
|
|
2
|
+
import { glibevent, ctx } from "../../store";
|
|
3
3
|
|
|
4
4
|
export function useDirtyState() {
|
|
5
|
-
const ctx = dialogStates.slice(-1)[0] || vueApp;
|
|
6
5
|
const prompt = "Changes you made have not been saved. Are you sure?";
|
|
7
6
|
|
|
8
7
|
const isDirty = () => {
|
|
9
|
-
return ctx.isFormDirty && !ctx.isFormSubmitted && !confirm(prompt);
|
|
8
|
+
return ctx().isFormDirty && !ctx().isFormSubmitted && !confirm(prompt);
|
|
10
9
|
};
|
|
11
10
|
|
|
12
11
|
const clearDirtyState = () => {
|
|
13
|
-
ctx.isFormDirty = false;
|
|
12
|
+
ctx().isFormDirty = false;
|
|
14
13
|
};
|
|
15
14
|
|
|
16
15
|
const updateDirtyState = (val, oldVal, spec) => {
|
|
17
16
|
if (!spec.disableDirtyCheck && val != oldVal && val != spec.value) {
|
|
18
|
-
ctx.isFormDirty = true;
|
|
17
|
+
ctx().isFormDirty = true;
|
|
19
18
|
}
|
|
20
19
|
};
|
|
21
20
|
|
|
22
21
|
const watchDirtyState = () => {
|
|
23
22
|
return watchEffect(() => {
|
|
24
|
-
if (ctx.isFormDirty) {
|
|
23
|
+
if (ctx().isFormDirty) {
|
|
25
24
|
window.onbeforeunload = () => !isDirty();
|
|
26
25
|
glibevent.onbeforewindowsopen = () => !isDirty();
|
|
27
26
|
glibevent.onbeforewindowsclose = () => !isDirty();
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<input v-if="isDeleted(groupIndex)" type="hidden" :name="`${spec.name}[${groupIndex}][_destroy]`" value="1" />
|
|
5
5
|
<div :style="{ display: isDeleted(groupIndex) ? 'none' : 'block' }">
|
|
6
6
|
<v-icon class="float-left mr-2" color="error" @click="removeGroup(groupIndex)">remove_circle</v-icon>
|
|
7
|
-
<h4 v-if="spec.titlePrefix">{{ spec.titlePrefix }}
|
|
7
|
+
<h4 v-if="spec.titlePrefix">{{ spec.titlePrefix }}{{ group.actualIndex }}</h4>
|
|
8
8
|
<panels-responsive :spec="group" />
|
|
9
9
|
</div>
|
|
10
10
|
</div>
|
|
@@ -22,46 +22,47 @@ export default {
|
|
|
22
22
|
return {
|
|
23
23
|
groupValues: [],
|
|
24
24
|
template: {},
|
|
25
|
-
templateViews: []
|
|
25
|
+
templateViews: [],
|
|
26
|
+
groupSpecs: []
|
|
26
27
|
};
|
|
27
28
|
},
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
29
|
+
watch: {
|
|
30
|
+
spec: {
|
|
31
|
+
handler(spec) {
|
|
32
|
+
this.template = spec.template;
|
|
33
|
+
this.templateViews = this.template.childViews || [];
|
|
34
|
+
|
|
35
|
+
spec.groupFieldProperties.forEach((group, groupIndex) => {
|
|
36
|
+
group.forEach((properties) => {
|
|
37
|
+
const fullName = this.prefixFieldName(groupIndex, properties.name)
|
|
38
|
+
this.setFieldModel(fullName, properties.value)
|
|
39
|
+
})
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
this.groupValues = spec.groupFieldProperties;
|
|
43
|
+
},
|
|
44
|
+
immediate: true
|
|
45
|
+
},
|
|
46
|
+
groupValues: {
|
|
47
|
+
handler(groupValues) {
|
|
48
|
+
var actualIndex = 0
|
|
49
|
+
this.groupSpecs = groupValues.map((group, groupIndex) => {
|
|
50
|
+
if (!this.isDeleted(groupIndex)) {
|
|
51
|
+
++actualIndex
|
|
40
52
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
53
|
+
|
|
54
|
+
const viewSpecs = this.processTemplate(
|
|
55
|
+
this.mapFieldProperties(group),
|
|
56
|
+
groupIndex
|
|
57
|
+
);
|
|
58
|
+
return Object.assign({}, this.template, { childViews: viewSpecs, actualIndex: actualIndex });
|
|
59
|
+
});
|
|
60
|
+
},
|
|
61
|
+
immediate: true,
|
|
62
|
+
deep: true // Watch insertion and deletion
|
|
44
63
|
}
|
|
45
64
|
},
|
|
46
65
|
methods: {
|
|
47
|
-
$ready() {
|
|
48
|
-
// this.groupValues = this.spec.value;
|
|
49
|
-
this.groupValues = this.spec.groupFieldProperties;
|
|
50
|
-
|
|
51
|
-
this.template = this.spec.template;
|
|
52
|
-
this.templateViews = this.template.childViews || [];
|
|
53
|
-
|
|
54
|
-
this.groupValues.forEach((group, groupIndex) => {
|
|
55
|
-
this.processTemplate(
|
|
56
|
-
this.mapFieldProperties(group),
|
|
57
|
-
groupIndex,
|
|
58
|
-
(viewSpec, fullName, properties) => {
|
|
59
|
-
// this.$data._fieldModels[name] = group[viewSpec.name];
|
|
60
|
-
this.$data._fieldModels[fullName] = properties.value;
|
|
61
|
-
}
|
|
62
|
-
);
|
|
63
|
-
});
|
|
64
|
-
},
|
|
65
66
|
mapFieldProperties(group) {
|
|
66
67
|
const fieldProperties = {};
|
|
67
68
|
group.forEach(field => {
|
|
@@ -69,14 +70,60 @@ export default {
|
|
|
69
70
|
});
|
|
70
71
|
return fieldProperties;
|
|
71
72
|
},
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
73
|
+
// Replace every occurrence of `{{index}}` within any string.
|
|
74
|
+
populateIndexes(object, groupIndex) {
|
|
75
|
+
if (this.$type.isString(object)) {
|
|
76
|
+
return object.replace('{{index}}', groupIndex)
|
|
77
|
+
}
|
|
78
|
+
if (this.$type.isArray(object)) {
|
|
79
|
+
return object.map((o) => this.populateIndexes(o, groupIndex));
|
|
80
|
+
|
|
81
|
+
} else if (this.$type.isObject(object)) {
|
|
82
|
+
const newObject = {}
|
|
83
|
+
for (const key in object) {
|
|
84
|
+
newObject[key] = this.populateIndexes(object[key], groupIndex)
|
|
85
|
+
}
|
|
86
|
+
return newObject
|
|
87
|
+
}
|
|
88
|
+
return object
|
|
89
|
+
},
|
|
90
|
+
processTemplate(properties, groupIndex, processField, processNonField) {
|
|
91
|
+
return this.processViews(
|
|
92
|
+
this.templateViews, properties, groupIndex, processField, processNonField
|
|
93
|
+
)
|
|
94
|
+
},
|
|
95
|
+
prefixFieldName(groupIndex, fieldName) {
|
|
96
|
+
if (fieldName.search(/\[.*\]/) >= 0) {
|
|
97
|
+
return `${this.spec.name}[${groupIndex}]${fieldName}`;
|
|
98
|
+
} else {
|
|
99
|
+
return `${this.spec.name}[${groupIndex}][${fieldName}]`;
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
processField(viewSpec, name, groupIndex) {
|
|
103
|
+
const indexedName = this.populateIndexes(name, groupIndex)
|
|
104
|
+
Object.assign(viewSpec, {
|
|
105
|
+
name: indexedName,
|
|
106
|
+
value: this.getFieldModel(indexedName)
|
|
107
|
+
});
|
|
108
|
+
return viewSpec
|
|
109
|
+
},
|
|
110
|
+
processViews(viewSpecs, properties, groupIndex) {
|
|
111
|
+
return viewSpecs.map(origSpec => {
|
|
112
|
+
const viewSpec = Object.assign({}, origSpec)
|
|
113
|
+
|
|
114
|
+
viewSpec.showIf = this.populateIndexes(viewSpec.showIf, groupIndex)
|
|
115
|
+
viewSpec.loadIf = this.populateIndexes(viewSpec.loadIf, groupIndex)
|
|
116
|
+
|
|
117
|
+
if (Utils.type.isString(viewSpec.name)) { // This is a field
|
|
118
|
+
const fullName = this.prefixFieldName(groupIndex, viewSpec.name)
|
|
119
|
+
return this.processField(viewSpec, fullName, groupIndex);
|
|
78
120
|
}
|
|
79
|
-
|
|
121
|
+
|
|
122
|
+
if (Utils.type.isObject(viewSpec.childViews)) {
|
|
123
|
+
viewSpec.childViews = this.processViews(viewSpec.childViews, properties, groupIndex)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return viewSpec
|
|
80
127
|
});
|
|
81
128
|
},
|
|
82
129
|
addGroup() {
|
|
@@ -87,7 +134,7 @@ export default {
|
|
|
87
134
|
{},
|
|
88
135
|
() => {
|
|
89
136
|
// Don't delete the group in order to maintain consistent indexes between model and view.
|
|
90
|
-
|
|
137
|
+
Object.assign(this.groupValues[index], { _destroy: 1 });
|
|
91
138
|
},
|
|
92
139
|
this
|
|
93
140
|
);
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/components/h1.vue
CHANGED
|
File without changes
|
package/components/h2.vue
CHANGED
|
File without changes
|
package/components/h3.vue
CHANGED
|
File without changes
|
package/components/h5.vue
CHANGED
|
File without changes
|
package/components/h6.vue
CHANGED
|
File without changes
|
package/components/hr.vue
CHANGED
|
File without changes
|
package/components/html.vue
CHANGED
|
File without changes
|
package/components/icon.vue
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -114,6 +114,12 @@ export default {
|
|
|
114
114
|
genericStyles(spec) {
|
|
115
115
|
return this.$styles(spec);
|
|
116
116
|
},
|
|
117
|
+
setFieldModel(name, value) {
|
|
118
|
+
fieldModels[name] = value;
|
|
119
|
+
},
|
|
120
|
+
getFieldModel(name) {
|
|
121
|
+
return fieldModels[name];
|
|
122
|
+
},
|
|
117
123
|
// _checkDirtyState(val, oldVal) {
|
|
118
124
|
// const dirtyCheckEnabled = !this.spec.disableDirtyCheck;
|
|
119
125
|
// // Make sure value has changed and make sure that it is different from the original value.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -86,7 +86,7 @@ export default {
|
|
|
86
86
|
});
|
|
87
87
|
|
|
88
88
|
this.$onEvent("forms/directSubmit", (e) => {
|
|
89
|
-
this.directSubmit(e.data.url);
|
|
89
|
+
this.directSubmit(e.data.url, e.data.method);
|
|
90
90
|
});
|
|
91
91
|
},
|
|
92
92
|
$ready() {
|
|
@@ -141,9 +141,9 @@ export default {
|
|
|
141
141
|
);
|
|
142
142
|
});
|
|
143
143
|
},
|
|
144
|
-
directSubmit(overrideUrl = null) {
|
|
145
|
-
if (overrideUrl) {
|
|
146
|
-
GLib.form.submitData(this.formElement, this, overrideUrl);
|
|
144
|
+
directSubmit(overrideUrl = null, overrideMethod = null) {
|
|
145
|
+
if (overrideUrl || overrideMethod) {
|
|
146
|
+
GLib.form.submitData(this.formElement, this, overrideUrl, overrideMethod);
|
|
147
147
|
} else {
|
|
148
148
|
this.validate(() => {
|
|
149
149
|
GLib.form.submitData(this.formElement, this);
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
:data-dragSectionIndex="sectionIndex" :disabled="!$type.isObject(dragSupport)" @start="onDragStart"
|
|
21
21
|
@end="onDragEnd" item-key="id">
|
|
22
22
|
<template #item="{ element }">
|
|
23
|
-
<component :is="template(element)" :spec="
|
|
23
|
+
<component :is="template(element)" :spec="element" :responsive-cols="spec.responsiveCols"
|
|
24
24
|
:data-dragRowId="element.id" />
|
|
25
25
|
</template>
|
|
26
26
|
</draggable>
|
|
@@ -48,6 +48,7 @@ import { vueApp } from "../../store";
|
|
|
48
48
|
import draggable from "vuedraggable";
|
|
49
49
|
import autoloadMixin from "../mixins/list/autoload.js";
|
|
50
50
|
import ThumbnailTemplate from "../../templates/thumbnail.vue";
|
|
51
|
+
import EditableTemplate from "../../templates/editable.vue";
|
|
51
52
|
import FeaturedTemplate from "../../templates/featured.vue";
|
|
52
53
|
import CommentTemplate from "../../templates/comment.vue";
|
|
53
54
|
|
|
@@ -55,6 +56,7 @@ export default {
|
|
|
55
56
|
components: {
|
|
56
57
|
draggable,
|
|
57
58
|
"template-thumbnail": ThumbnailTemplate,
|
|
59
|
+
"template-editable": EditableTemplate,
|
|
58
60
|
"template-featured": FeaturedTemplate,
|
|
59
61
|
"template-commentOutgoing": CommentTemplate,
|
|
60
62
|
"template-commentIncoming": CommentTemplate,
|
|
@@ -83,7 +85,9 @@ export default {
|
|
|
83
85
|
this.enableInfiniteScrollIfApplicable(spec);
|
|
84
86
|
|
|
85
87
|
for (const section of this.sections) {
|
|
86
|
-
section.rows = section.rows || []
|
|
88
|
+
section.rows = (section.rows || []).map((row) => {
|
|
89
|
+
return this.rowSpec(row)
|
|
90
|
+
})
|
|
87
91
|
}
|
|
88
92
|
},
|
|
89
93
|
immediate: true
|
|
File without changes
|
package/components/spacer.vue
CHANGED
|
File without changes
|
package/keys.js
CHANGED
|
File without changes
|
package/nav/dialog.vue
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<v-dialog :model-value="model" :width="spec.width || 600" :dark="false" :fullscreen="fullscreen" :sm-and-down="false"
|
|
2
|
+
<v-dialog class="dialog-container" :model-value="model" :width="spec.width || 600" :dark="false" :fullscreen="fullscreen" :sm-and-down="false"
|
|
3
3
|
:persistent="true" @click:outside="clickOutside">
|
|
4
4
|
<v-card :style="hamburgerStyles" class="hamburger">
|
|
5
5
|
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
</v-btn>
|
|
16
16
|
</div>
|
|
17
17
|
|
|
18
|
-
<div class="
|
|
18
|
+
<div class="dialog-body relative">
|
|
19
19
|
<component :is="containerComponent" :spec="formSpec">
|
|
20
20
|
<div v-if="message" class="dialog-message">
|
|
21
21
|
<common-message :spec="{ message: message }" />
|
|
@@ -209,7 +209,8 @@ export default {
|
|
|
209
209
|
}
|
|
210
210
|
|
|
211
211
|
.dialog-message {
|
|
212
|
-
padding:
|
|
212
|
+
padding: 0px 20px;
|
|
213
|
+
//padding: 16px 16px 20px 16px;
|
|
213
214
|
/* white-space: pre-wrap; */
|
|
214
215
|
}
|
|
215
216
|
|
package/package.json
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/static/redactorx.css
CHANGED
|
File without changes
|
package/static/redactorx.min.css
CHANGED
|
File without changes
|
package/static/redactorx.min.js
CHANGED
|
File without changes
|
|
File without changes
|
package/store.js
CHANGED
package/styles/test.sass
CHANGED
|
File without changes
|
package/styles/test.scss
CHANGED
|
File without changes
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<component :is="componentName" :href="$href()" class="thumbnail" :class="cssClasses" @[clickCondition]="$onClick()">
|
|
3
|
+
<panels-responsive :spec="spec.header" />
|
|
4
|
+
<div style="display:flex;">
|
|
5
|
+
<!-- <div v-if="spec.leftOuterButtons" style="display:flex; margin-top:10px;">
|
|
6
|
+
<template v-for="(item, index) in spec.leftOuterButtons" :key="index">
|
|
7
|
+
<common-button
|
|
8
|
+
:spec="buttonSpec(item)"
|
|
9
|
+
:disabled="$isBusy"
|
|
10
|
+
/>
|
|
11
|
+
</template>
|
|
12
|
+
</div> -->
|
|
13
|
+
|
|
14
|
+
<v-list-item v-longclick="$onLongPress" class="item-content" :style="columnStyles()">
|
|
15
|
+
<!-- <v-icon v-if="spec.onReorder" class="handle">drag_indicator</v-icon> -->
|
|
16
|
+
|
|
17
|
+
<!-- Specify a key to prevent reuse which causes an issue where the checkbox would use the previous name. -->
|
|
18
|
+
<fields-check v-if="checkSpec" :key="checkSpec.name" :spec="checkSpec" />
|
|
19
|
+
|
|
20
|
+
<template v-slot:prepend>
|
|
21
|
+
<div style="display: flex">
|
|
22
|
+
<div v-if="spec.leftButtons">
|
|
23
|
+
<template v-for="(item, index) in spec.leftButtons" :key="index">
|
|
24
|
+
<glib-button :spec="buttonSpec(item)" :disabled="$isBusy" />
|
|
25
|
+
</template>
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
<common-icon v-if="spec.icon" :spec="spec.icon" />
|
|
29
|
+
</div>
|
|
30
|
+
</template>
|
|
31
|
+
|
|
32
|
+
<!-- <v-list-item-avatar
|
|
33
|
+
v-if="$type.isString(spec.imageUrl)"
|
|
34
|
+
:tile="!spec.avatar"
|
|
35
|
+
style="display:flex;"
|
|
36
|
+
class="left-thumbnail"
|
|
37
|
+
:size="spec.imageSize"
|
|
38
|
+
>
|
|
39
|
+
<img :src="spec.imageUrl" />
|
|
40
|
+
</v-list-item-avatar> -->
|
|
41
|
+
|
|
42
|
+
<!-- <div v-else class="left-icon">
|
|
43
|
+
<v-list-item-avatar v-if="$type.isObject(spec.icon)">
|
|
44
|
+
<common-icon :spec="spec.icon" />
|
|
45
|
+
</v-list-item-avatar>
|
|
46
|
+
</div> -->
|
|
47
|
+
|
|
48
|
+
<div>
|
|
49
|
+
<v-text-field v-if="spec.fieldTitleName" :name="spec.fieldTitleName" :value="spec.title" />
|
|
50
|
+
<v-list-item-title v-else>{{ spec.title }}</v-list-item-title>
|
|
51
|
+
|
|
52
|
+
<v-list-item-subtitle v-if="spec.subtitle">{{
|
|
53
|
+
spec.subtitle
|
|
54
|
+
}}</v-list-item-subtitle>
|
|
55
|
+
<v-list-item-subtitle v-if="spec.subsubtitle">{{
|
|
56
|
+
spec.subsubtitle
|
|
57
|
+
}}</v-list-item-subtitle>
|
|
58
|
+
|
|
59
|
+
<div v-if="hasChips" class="chips">
|
|
60
|
+
<template v-for="(item, index) in chips" :key="index">
|
|
61
|
+
<common-chip :spec="item" />
|
|
62
|
+
</template>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<panels-responsive v-if="spec.body" :spec="spec.body" />
|
|
66
|
+
</div>
|
|
67
|
+
|
|
68
|
+
<template v-slot:append>
|
|
69
|
+
<template v-for="(item, index) in spec.rightButtons" :key="index">
|
|
70
|
+
<glib-button :spec="buttonSpec(item)" :disabled="$isBusy" />
|
|
71
|
+
</template>
|
|
72
|
+
</template>
|
|
73
|
+
|
|
74
|
+
</v-list-item>
|
|
75
|
+
<panels-responsive :spec="spec.right" />
|
|
76
|
+
</div>
|
|
77
|
+
<panels-responsive :spec="spec.footer" />
|
|
78
|
+
</component>
|
|
79
|
+
</template>
|
|
80
|
+
|
|
81
|
+
<script>
|
|
82
|
+
import CheckField from "../components/fields/check.vue";
|
|
83
|
+
|
|
84
|
+
export default {
|
|
85
|
+
components: {
|
|
86
|
+
"fields-check": CheckField
|
|
87
|
+
},
|
|
88
|
+
props: {
|
|
89
|
+
spec: { type: Object, required: true },
|
|
90
|
+
responsiveCols: { type: Number, default: () => 0 }
|
|
91
|
+
},
|
|
92
|
+
data() {
|
|
93
|
+
return {
|
|
94
|
+
// editButtons: []
|
|
95
|
+
};
|
|
96
|
+
},
|
|
97
|
+
computed: {
|
|
98
|
+
componentName() {
|
|
99
|
+
// Use `a` to enable "open in new tab".
|
|
100
|
+
return this.clickCondition ? "a" : "div";
|
|
101
|
+
// return "div"
|
|
102
|
+
},
|
|
103
|
+
cssClasses() {
|
|
104
|
+
return this.$classes(this.spec, "templates/thumbnail");
|
|
105
|
+
},
|
|
106
|
+
clickCondition() {
|
|
107
|
+
if (this.spec.onClick || this.spec.onLongPress) {
|
|
108
|
+
// This will show the clickable indication
|
|
109
|
+
return "click";
|
|
110
|
+
}
|
|
111
|
+
return null;
|
|
112
|
+
},
|
|
113
|
+
hasChips() {
|
|
114
|
+
return this.spec.chips && this.spec.chips.length > 0;
|
|
115
|
+
},
|
|
116
|
+
// Implemented as computed so that it gets reflected when reordering
|
|
117
|
+
chips() {
|
|
118
|
+
return (this.spec.chips || []).map(item => {
|
|
119
|
+
var color = null;
|
|
120
|
+
this.$type.ifArray(item.styleClasses, classes => {
|
|
121
|
+
for (const val of ["success", "info", "warning", "error"]) {
|
|
122
|
+
if (classes.includes(val)) {
|
|
123
|
+
color = val;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
return Object.assign({}, item, { color: color, view: "chip" });
|
|
128
|
+
});
|
|
129
|
+
},
|
|
130
|
+
// Implemented as computed so that it gets reflected when navigating to another list containing check fields.
|
|
131
|
+
checkSpec() {
|
|
132
|
+
if (this.spec.fieldCheckName) {
|
|
133
|
+
return {
|
|
134
|
+
view: "fields/checkGroup",
|
|
135
|
+
name: this.spec.fieldCheckName,
|
|
136
|
+
checkValue: true,
|
|
137
|
+
valueIf: this.spec.fieldCheckValueIf,
|
|
138
|
+
padding: { left: 16 }
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
// cssStyles() {
|
|
144
|
+
// const styles = this.$styles();
|
|
145
|
+
// // switch(this.spec.align) {
|
|
146
|
+
// // case 'middle':
|
|
147
|
+
// // styles['align-items'] = 'center'
|
|
148
|
+
// // break
|
|
149
|
+
// // case 'bottom':
|
|
150
|
+
// // styles['align-items'] = 'flex-end'
|
|
151
|
+
// // break
|
|
152
|
+
// // default:
|
|
153
|
+
// // styles['align-items'] = 'flex-start'
|
|
154
|
+
// // }
|
|
155
|
+
// return styles;
|
|
156
|
+
// },
|
|
157
|
+
},
|
|
158
|
+
methods: {
|
|
159
|
+
$ready() {
|
|
160
|
+
// this.editButtons = this.spec.editButtons || [];
|
|
161
|
+
},
|
|
162
|
+
buttonSpec(item) {
|
|
163
|
+
// Classes should be coming from the backend
|
|
164
|
+
// const styleClasses = ["text", "x-small"]
|
|
165
|
+
// if (!item.text) {
|
|
166
|
+
// styleClasses.push("icon")
|
|
167
|
+
// }
|
|
168
|
+
|
|
169
|
+
return Object.assign({}, item, {
|
|
170
|
+
view: "button"
|
|
171
|
+
});
|
|
172
|
+
},
|
|
173
|
+
columnStyles() {
|
|
174
|
+
if (this.responsiveCols) {
|
|
175
|
+
return `width: ${100 / this.responsiveCols}%; float: left;`;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
</script>
|
|
181
|
+
|
|
182
|
+
<style lang="scss">
|
|
183
|
+
.chips>* {
|
|
184
|
+
margin-right: 10px;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.v-list-item__content {
|
|
188
|
+
width: 100%;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.thumbnail {
|
|
192
|
+
|
|
193
|
+
// Override this when using the `right` property.
|
|
194
|
+
.item-content {
|
|
195
|
+
width: 100%;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
</style>
|
|
199
|
+
|
|
200
|
+
<style lang="scss" scoped>
|
|
201
|
+
a.thumbnail {
|
|
202
|
+
color: inherit;
|
|
203
|
+
text-decoration: inherit;
|
|
204
|
+
display: block;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.item-content {
|
|
208
|
+
display: flex;
|
|
209
|
+
|
|
210
|
+
&.v-list-item--density-default:not(.v-list-item--nav).v-list-item--one-line {
|
|
211
|
+
padding-inline-start: 0;
|
|
212
|
+
padding-inline-end: 0;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
@media (min-width: 600px) {
|
|
217
|
+
.left-thumbnail.v-avatar.v-list-item__avatar {
|
|
218
|
+
margin: 6px 6px 6px 6px;
|
|
219
|
+
width: 60px;
|
|
220
|
+
height: 60px;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.left-icon {
|
|
224
|
+
// margin-left: 16px;
|
|
225
|
+
margin-left: 4px;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// .left-universal {
|
|
229
|
+
// padding-left: 16px;
|
|
230
|
+
// }
|
|
231
|
+
// .handle {
|
|
232
|
+
// // margin-left: 10px;
|
|
233
|
+
// cursor: move;
|
|
234
|
+
// }
|
|
235
|
+
}
|
|
236
|
+
</style>
|
package/templates/thumbnail.vue
CHANGED
|
@@ -14,11 +14,11 @@
|
|
|
14
14
|
<v-list-item v-longclick="$onLongPress" class="item-content" :style="columnStyles()">
|
|
15
15
|
<!-- <v-icon v-if="spec.onReorder" class="handle">drag_indicator</v-icon> -->
|
|
16
16
|
|
|
17
|
-
<!-- Specify a key to prevent reuse which causes an issue where the checkbox would use the previous name. -->
|
|
18
|
-
<fields-check v-if="checkSpec" :key="checkSpec.name" :spec="checkSpec" />
|
|
19
|
-
|
|
20
17
|
<template v-slot:prepend>
|
|
21
18
|
<div style="display: flex">
|
|
19
|
+
<!-- Specify a key to prevent reuse which causes an issue where the checkbox would use the previous name. -->
|
|
20
|
+
<fields-check v-if="checkSpec" :key="checkSpec.name" :spec="checkSpec" />
|
|
21
|
+
|
|
22
22
|
<div v-if="spec.leftButtons">
|
|
23
23
|
<template v-for="(item, index) in spec.leftButtons" :key="index">
|
|
24
24
|
<glib-button :spec="buttonSpec(item)" :disabled="$isBusy" />
|
|
@@ -46,8 +46,7 @@
|
|
|
46
46
|
</div> -->
|
|
47
47
|
|
|
48
48
|
<div>
|
|
49
|
-
<v-
|
|
50
|
-
<v-list-item-title v-else>{{ spec.title }}</v-list-item-title>
|
|
49
|
+
<v-list-item-title>{{ spec.title }}</v-list-item-title>
|
|
51
50
|
|
|
52
51
|
<v-list-item-subtitle v-if="spec.subtitle">{{
|
|
53
52
|
spec.subtitle
|
|
@@ -71,8 +70,6 @@
|
|
|
71
70
|
</template>
|
|
72
71
|
</template>
|
|
73
72
|
|
|
74
|
-
<!-- Deprecated -->
|
|
75
|
-
<!-- <templates-menu :edit-buttons="editButtons" /> -->
|
|
76
73
|
</v-list-item>
|
|
77
74
|
<panels-responsive :spec="spec.right" />
|
|
78
75
|
</div>
|
|
@@ -93,9 +90,24 @@ export default {
|
|
|
93
90
|
},
|
|
94
91
|
data() {
|
|
95
92
|
return {
|
|
96
|
-
//
|
|
93
|
+
// checkSpec: null
|
|
97
94
|
};
|
|
98
95
|
},
|
|
96
|
+
// watch: {
|
|
97
|
+
// spec: {
|
|
98
|
+
// handler(spec) {
|
|
99
|
+
// if (this.spec.fieldCheckName) {
|
|
100
|
+
// this.checkSpec = {
|
|
101
|
+
// view: "fields/checkGroup",
|
|
102
|
+
// name: this.spec.fieldCheckName,
|
|
103
|
+
// checkValue: true,
|
|
104
|
+
// valueIf: this.spec.fieldCheckValueIf
|
|
105
|
+
// };
|
|
106
|
+
// }
|
|
107
|
+
// },
|
|
108
|
+
// immediate: true
|
|
109
|
+
// }
|
|
110
|
+
// },
|
|
99
111
|
computed: {
|
|
100
112
|
componentName() {
|
|
101
113
|
// Use `a` to enable "open in new tab".
|
|
@@ -136,8 +148,7 @@ export default {
|
|
|
136
148
|
view: "fields/checkGroup",
|
|
137
149
|
name: this.spec.fieldCheckName,
|
|
138
150
|
checkValue: true,
|
|
139
|
-
valueIf: this.spec.fieldCheckValueIf
|
|
140
|
-
padding: { left: 16 }
|
|
151
|
+
valueIf: this.spec.fieldCheckValueIf
|
|
141
152
|
};
|
|
142
153
|
}
|
|
143
154
|
return null;
|
|
File without changes
|
package/utils/dom.js
CHANGED
|
File without changes
|
package/utils/form.js
CHANGED
|
@@ -1,22 +1,33 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ctx } from "../store";
|
|
2
2
|
|
|
3
3
|
export default class {
|
|
4
4
|
// Execution flows:
|
|
5
5
|
// Button -> Button.onClick() -> Utils.http.execute() -- doesn't save autofill values
|
|
6
6
|
// Button -> Button.onClick() -> form.submit() -- doesn't execute Form.onSubmit(), so cannot call Utils.http.execute() there
|
|
7
7
|
// Submit -> Form.onSubmit() -> Utils.http.execute() -- save autofill values and auto-submit when ENTER is pressed
|
|
8
|
-
static submitData(form, component, overrideUrl = null) {
|
|
8
|
+
static submitData(form, component, overrideUrl = null, overrideMethod = null) {
|
|
9
9
|
// Analogous to Rails' form_with's `local: true`
|
|
10
10
|
if (form.dataset.local) {
|
|
11
|
+
if (overrideUrl) {
|
|
12
|
+
component.$data.url = overrideUrl
|
|
13
|
+
}
|
|
14
|
+
|
|
11
15
|
// Prevent onUnload dirty prompt.
|
|
12
16
|
// Utils.http.clearDirtyState();
|
|
13
|
-
|
|
14
|
-
|
|
17
|
+
|
|
18
|
+
// Use nextTick to wait for overrideUrl get picked up.
|
|
19
|
+
component.$nextTick(() => {
|
|
20
|
+
ctx().isFormDirty = false;
|
|
21
|
+
form.submit();
|
|
22
|
+
});
|
|
15
23
|
} else {
|
|
16
24
|
const url = overrideUrl ? overrideUrl : form.getAttribute("action");
|
|
17
25
|
const formData = new FormData(form);
|
|
18
|
-
const method = form.getAttribute("method");
|
|
26
|
+
const method = overrideMethod ? overrideMethod : form.getAttribute("method");
|
|
27
|
+
|
|
19
28
|
if (method.toUpperCase() === "GET") {
|
|
29
|
+
// Don't include this token in GET requests.
|
|
30
|
+
formData.delete("authenticity_token")
|
|
20
31
|
const data = {
|
|
21
32
|
url: Utils.url.appendParams(url, formData)
|
|
22
33
|
};
|
package/utils/helper.js
CHANGED
|
File without changes
|
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 { vueApp } from "../store";
|
|
4
|
+
import { ctx, vueApp } from "../store";
|
|
5
5
|
|
|
6
6
|
let loading = false;
|
|
7
7
|
|
|
@@ -137,7 +137,8 @@ export default class {
|
|
|
137
137
|
static reload(properties, component) {
|
|
138
138
|
const currentUrl = window.location.href;
|
|
139
139
|
const data = {
|
|
140
|
-
url: properties.url || currentUrl
|
|
140
|
+
url: properties.url || currentUrl,
|
|
141
|
+
formData: properties.formData
|
|
141
142
|
};
|
|
142
143
|
|
|
143
144
|
Utils.http.execute(data, "GET", component, (page, response) => {
|
|
@@ -257,8 +258,8 @@ export default class {
|
|
|
257
258
|
static forceComponentUpdate(handler) {
|
|
258
259
|
// GLib.component.clearRegistry();
|
|
259
260
|
vueApp.isStale = true;
|
|
260
|
-
|
|
261
|
-
|
|
261
|
+
ctx().isFormSubmitted = false;
|
|
262
|
+
ctx().isFormDirty = false;
|
|
262
263
|
handler();
|
|
263
264
|
|
|
264
265
|
// Queue the execution so the first isStale has time to resets state before handler gets executed
|
|
@@ -272,7 +273,7 @@ export default class {
|
|
|
272
273
|
// }
|
|
273
274
|
|
|
274
275
|
static notifyFormSubmitted() {
|
|
275
|
-
|
|
276
|
+
ctx().isFormSubmitted = true;
|
|
276
277
|
}
|
|
277
278
|
|
|
278
279
|
// `context` can be either window or dialog.
|
package/utils/type.js
CHANGED
|
File without changes
|
package/utils/url.js
CHANGED
|
@@ -100,6 +100,10 @@ export default class {
|
|
|
100
100
|
|
|
101
101
|
// // https://gist.github.com/pirate/9298155edda679510723
|
|
102
102
|
static _extractUrlParams(search) {
|
|
103
|
+
if (search.indexOf("?") <= -1) {
|
|
104
|
+
return {};
|
|
105
|
+
}
|
|
106
|
+
|
|
103
107
|
const hashes = search.slice(search.indexOf("?") + 1).split("&");
|
|
104
108
|
return hashes.reduce((params, hash) => {
|
|
105
109
|
const split = hash.indexOf("=");
|