glib-web 0.6.2 → 0.6.9
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 +7 -4
- package/actions/analytics/logEvent.js +1 -1
- package/actions/auth/creditCard.js +4 -4
- package/actions/auth/saveCsrfToken.js +4 -4
- package/actions/cables/push.js +0 -12
- package/actions/commands/copy.js +12 -0
- package/actions/dialogs/alert.js +2 -2
- package/actions/dialogs/close.js +2 -4
- package/actions/dialogs/notification.js +2 -2
- package/actions/dialogs/open.js +2 -4
- package/actions/dialogs/show.js +3 -2
- package/actions/forms/submit.js +2 -12
- package/actions/http/delete.js +1 -1
- package/actions/http/patch.js +1 -1
- package/actions/http/post.js +1 -1
- package/actions/http/put.js +1 -1
- package/actions/runMultiple.js +2 -2
- package/actions/timeouts/set.js +2 -2
- package/actions/windows/close.js +2 -2
- package/actions/windows/closeAll.js +2 -2
- package/actions/windows/closeWithReload.js +1 -1
- package/actions/windows/open.js +1 -1
- package/actions/windows/reload.js +1 -1
- package/actions/ws/push.js +1 -1
- package/app.vue +5 -3
- package/components/button.vue +9 -2
- package/components/calendar.vue +1 -1
- package/components/component.vue +4 -0
- package/components/fields/googlePlace.vue +80 -52
- package/components/fields/radioGroup.vue +1 -0
- package/components/markdown.vue +7 -0
- package/components/mixins/dataset.js +10 -0
- package/components/mixins/events.js +4 -5
- package/components/mixins/generic.js +6 -0
- package/components/mixins/list/autoload.js +2 -3
- package/components/mixins/table/autoload.js +2 -2
- package/components/mixins/tour.js +75 -0
- package/components/mixins/ws/actionCable.js +1 -1
- package/components/multimedia/video.vue +87 -0
- package/components/panels/form.vue +13 -3
- package/components/panels/list.vue +1 -1
- package/components/switch.vue +2 -2
- package/index.js +3 -0
- package/nav/appbar.vue +1 -1
- package/nav/dialog.vue +2 -2
- package/nav/drawer.vue +38 -8
- package/nav/sheet.vue +1 -2
- package/nav/snackbar.vue +1 -2
- package/package.json +3 -2
- package/utils/form.js +1 -5
- package/utils/http.js +2 -2
- package/utils/launch.js +25 -18
- package/utils/mime_type.js +78 -0
- package/utils/private/ws.js +1 -1
- package/utils/uploader.js +9 -36
|
@@ -69,8 +69,7 @@ export default {
|
|
|
69
69
|
if (!e.metaKey && !e.ctrlKey && e.button === 0) {
|
|
70
70
|
e.preventDefault();
|
|
71
71
|
e.stopPropagation();
|
|
72
|
-
|
|
73
|
-
Action.execute(properties.onClick, null, this);
|
|
72
|
+
Action.execute(properties.onClick, this);
|
|
74
73
|
}
|
|
75
74
|
},
|
|
76
75
|
$rel: function(spec) {
|
|
@@ -88,7 +87,7 @@ export default {
|
|
|
88
87
|
// return this.spec.onLongPress ? this.$onLongPress : null;
|
|
89
88
|
// },
|
|
90
89
|
$onLongPress() {
|
|
91
|
-
GLib.action.execute(this.spec.onLongPress,
|
|
90
|
+
GLib.action.execute(this.spec.onLongPress, this);
|
|
92
91
|
},
|
|
93
92
|
$addViewportChangeListeners: function(handler) {
|
|
94
93
|
window.addEventListener("load", handler);
|
|
@@ -163,12 +162,12 @@ export default {
|
|
|
163
162
|
this.$el.addEventListener(name, handler);
|
|
164
163
|
},
|
|
165
164
|
$onTyping({ duration = 2000 }) {
|
|
166
|
-
GLib.action.execute(this.spec.onTypeStart,
|
|
165
|
+
GLib.action.execute(this.spec.onTypeStart, this);
|
|
167
166
|
clearTimeout(this.timer);
|
|
168
167
|
|
|
169
168
|
this.timer = setTimeout(() => {
|
|
170
169
|
this._typingTimer = null;
|
|
171
|
-
GLib.action.execute(this.spec.onTypeEnd,
|
|
170
|
+
GLib.action.execute(this.spec.onTypeEnd, this);
|
|
172
171
|
}, duration);
|
|
173
172
|
}
|
|
174
173
|
// $onZero() {
|
|
@@ -23,6 +23,12 @@ export default {
|
|
|
23
23
|
});
|
|
24
24
|
return augmentedRules;
|
|
25
25
|
},
|
|
26
|
+
// This can be overridden by the component to ensure that dialogs are shown within the component,
|
|
27
|
+
// which is necessary for operations requiring certain hierarchy, e.g. submitting a form from a
|
|
28
|
+
// child dialog.
|
|
29
|
+
$dialogContainer() {
|
|
30
|
+
return document.body;
|
|
31
|
+
},
|
|
26
32
|
$wsSubscribeEvents(spec) {
|
|
27
33
|
if (!Utils.type.isObject(spec)) {
|
|
28
34
|
return;
|
|
@@ -64,7 +64,6 @@ export default {
|
|
|
64
64
|
(el, visible) => {
|
|
65
65
|
if (visible) {
|
|
66
66
|
this._handleTopScroll(onScrollToTop);
|
|
67
|
-
// GLib.action.execute(onScrollToTop, null, this);
|
|
68
67
|
}
|
|
69
68
|
}
|
|
70
69
|
);
|
|
@@ -72,7 +71,7 @@ export default {
|
|
|
72
71
|
this.$addViewportChangeListeners(this.topScrollHandler);
|
|
73
72
|
},
|
|
74
73
|
_handleTopScroll(onScrollToTop) {
|
|
75
|
-
GLib.action.execute(onScrollToTop,
|
|
74
|
+
GLib.action.execute(onScrollToTop, this);
|
|
76
75
|
},
|
|
77
76
|
_registerBottomScroll(onScrollToBottom) {
|
|
78
77
|
this.bottomScrollHandler = this.$onVisibilityChange(
|
|
@@ -108,7 +107,7 @@ export default {
|
|
|
108
107
|
);
|
|
109
108
|
}
|
|
110
109
|
|
|
111
|
-
GLib.action.execute(onScrollToBottom,
|
|
110
|
+
GLib.action.execute(onScrollToBottom, this);
|
|
112
111
|
},
|
|
113
112
|
autoloadAll(nextPage) {
|
|
114
113
|
const vm = this;
|
|
@@ -56,7 +56,7 @@ export default {
|
|
|
56
56
|
// this.topScrollHandler();
|
|
57
57
|
},
|
|
58
58
|
_handleTopScroll(onScrollToTop) {
|
|
59
|
-
GLib.action.execute(onScrollToTop,
|
|
59
|
+
GLib.action.execute(onScrollToTop, this);
|
|
60
60
|
},
|
|
61
61
|
_registerBottomScroll(onScrollToBottom) {
|
|
62
62
|
this.bottomScrollHandler = this.$onVisibilityChange(
|
|
@@ -95,7 +95,7 @@ export default {
|
|
|
95
95
|
);
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
GLib.action.execute(onScrollToBottom,
|
|
98
|
+
GLib.action.execute(onScrollToBottom, this);
|
|
99
99
|
},
|
|
100
100
|
autoloadAll(nextPage) {
|
|
101
101
|
const vm = this;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import Driver from "driver.js";
|
|
2
|
+
import "driver.js/dist/driver.min.css";
|
|
3
|
+
|
|
4
|
+
class TourHelper {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.keys = [];
|
|
7
|
+
this.storage = window.localStorage;
|
|
8
|
+
|
|
9
|
+
this.driver = new Driver({
|
|
10
|
+
doneBtnText: "Done",
|
|
11
|
+
closeBtnText: "Skip tour",
|
|
12
|
+
nextBtnText: "Next tip",
|
|
13
|
+
prevBtnText: "Prev",
|
|
14
|
+
onHighlighted: element => {
|
|
15
|
+
console.log("onHighlighted", element);
|
|
16
|
+
// TODO
|
|
17
|
+
// this.keys.forEach(value => this.storage.removeItem(value));
|
|
18
|
+
// this.storage.setItem(element.node.dataset.key, 1);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
this.elements = [];
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const helper = new TourHelper();
|
|
27
|
+
|
|
28
|
+
export default {
|
|
29
|
+
methods: {
|
|
30
|
+
registerTour() {
|
|
31
|
+
if (this.spec.tour) {
|
|
32
|
+
helper.elements.push(this);
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
startTour() {
|
|
36
|
+
if (helper.elements && helper.elements.length > 0) {
|
|
37
|
+
helper.elements = Array.from(helper.elements).sort(
|
|
38
|
+
(a, b) => a.index - b.index
|
|
39
|
+
);
|
|
40
|
+
let stepDefinitions = helper.elements.map(element => {
|
|
41
|
+
const tourSpec = element.spec.tour;
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
element: element.$el,
|
|
45
|
+
popover: {
|
|
46
|
+
title: tourSpec.title,
|
|
47
|
+
description: tourSpec.message,
|
|
48
|
+
position: tourSpec.position
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// TODO
|
|
54
|
+
// this.keys = helper.elements.map(value => value.dataset.key);
|
|
55
|
+
|
|
56
|
+
helper.driver.defineSteps(stepDefinitions);
|
|
57
|
+
|
|
58
|
+
helper.driver.start(this.latestTourStep());
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
latestTourStep() {
|
|
62
|
+
let step = 0;
|
|
63
|
+
|
|
64
|
+
// TODO
|
|
65
|
+
// Array.from(this.elements).forEach(element => {
|
|
66
|
+
// if (this.storage.getItem(element.dataset.key)) {
|
|
67
|
+
// step = parseInt(element.dataset.index);
|
|
68
|
+
// }
|
|
69
|
+
// });
|
|
70
|
+
// return step;
|
|
71
|
+
|
|
72
|
+
return step;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :style="styles()" :class="$classes()">
|
|
3
|
+
<iframe
|
|
4
|
+
:width="width"
|
|
5
|
+
:height="height"
|
|
6
|
+
:src="videoUrl"
|
|
7
|
+
allowfullscreen
|
|
8
|
+
></iframe>
|
|
9
|
+
</div>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script>
|
|
13
|
+
const urlRegex = /^(?:(?:https?:)?\/\/)?(?:www\.)?(?:m\.)?(?:youtu(?:be)?\.com\/(?:v\/|embed\/|watch(?:\/|\?v=))|youtu\.be\/)((?:\w|-){11})(?:\S+)?$/;
|
|
14
|
+
|
|
15
|
+
export default {
|
|
16
|
+
props: {
|
|
17
|
+
spec: { type: Object, required: true }
|
|
18
|
+
},
|
|
19
|
+
data() {
|
|
20
|
+
return {
|
|
21
|
+
videoUrl: "",
|
|
22
|
+
width: null,
|
|
23
|
+
height: null,
|
|
24
|
+
paddingBottom: null
|
|
25
|
+
};
|
|
26
|
+
},
|
|
27
|
+
methods: {
|
|
28
|
+
$ready() {
|
|
29
|
+
this.width = this.$length(this.spec.width);
|
|
30
|
+
this.height = this.$length(this.spec.height);
|
|
31
|
+
|
|
32
|
+
if (this.height == null) {
|
|
33
|
+
// Let the container calculates the height
|
|
34
|
+
this.height = "100%";
|
|
35
|
+
|
|
36
|
+
if (this.width == "100%") {
|
|
37
|
+
// 16:9 aspect ratio
|
|
38
|
+
// See https://stackoverflow.com/questions/35814653/automatic-height-when-embedding-a-youtube-video
|
|
39
|
+
this.paddingBottom = "56.25%";
|
|
40
|
+
} else {
|
|
41
|
+
Utils.type.ifNumber(this.spec.width, val => {
|
|
42
|
+
const height = (val * 9) / 16;
|
|
43
|
+
this.paddingBottom = `${height}px`;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const url = this.spec.url;
|
|
49
|
+
if (this.isYoutube(url)) {
|
|
50
|
+
this.videoUrl = this.embededYoutubeUrl(this.extractYoutubeId(url));
|
|
51
|
+
} else {
|
|
52
|
+
this.videoUrl = url;
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
styles() {
|
|
56
|
+
const styles = this.$styles();
|
|
57
|
+
|
|
58
|
+
// See https://stackoverflow.com/questions/35814653/automatic-height-when-embedding-a-youtube-video
|
|
59
|
+
styles["position"] = "relative";
|
|
60
|
+
styles["padding-bottom"] = this.paddingBottom;
|
|
61
|
+
|
|
62
|
+
return styles;
|
|
63
|
+
},
|
|
64
|
+
isYoutube(url) {
|
|
65
|
+
return !!String(url).match(urlRegex);
|
|
66
|
+
},
|
|
67
|
+
extractYoutubeId(url) {
|
|
68
|
+
let match = urlRegex.exec(url);
|
|
69
|
+
return match ? match[1] : false;
|
|
70
|
+
},
|
|
71
|
+
embededYoutubeUrl(youtubeId) {
|
|
72
|
+
return "https://www.youtube.com/embed/:youtubeId".replace(
|
|
73
|
+
":youtubeId",
|
|
74
|
+
youtubeId
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
</script>
|
|
80
|
+
|
|
81
|
+
<style lang="scss" scoped>
|
|
82
|
+
iframe {
|
|
83
|
+
position: absolute;
|
|
84
|
+
top: 0;
|
|
85
|
+
left: 0;
|
|
86
|
+
}
|
|
87
|
+
</style>
|
|
@@ -60,6 +60,10 @@ export default {
|
|
|
60
60
|
this.submit();
|
|
61
61
|
});
|
|
62
62
|
|
|
63
|
+
this.$onEvent("forms/directSubmit", e => {
|
|
64
|
+
this.directSubmit();
|
|
65
|
+
});
|
|
66
|
+
|
|
63
67
|
this.formElement = this.$refs.form.$el;
|
|
64
68
|
this.parentStyles = this.genericStyles({ width: this.spec.width });
|
|
65
69
|
|
|
@@ -104,18 +108,24 @@ export default {
|
|
|
104
108
|
[this.spec.paramNameForFormData || "formData"]: formData
|
|
105
109
|
};
|
|
106
110
|
const data = Object.assign({}, onSubmit, params);
|
|
107
|
-
GLib.action.execute(data,
|
|
111
|
+
GLib.action.execute(data, this);
|
|
108
112
|
},
|
|
109
113
|
() => {
|
|
110
|
-
|
|
114
|
+
this.directSubmit();
|
|
111
115
|
}
|
|
112
116
|
);
|
|
113
117
|
} else {
|
|
114
|
-
Utils.launch.alert("Make sure all fields are valid");
|
|
118
|
+
Utils.launch.dialog.alert("Make sure all fields are valid");
|
|
115
119
|
}
|
|
116
120
|
},
|
|
121
|
+
directSubmit() {
|
|
122
|
+
GLib.form.submitData(this.formElement, this);
|
|
123
|
+
},
|
|
117
124
|
action_clear() {
|
|
118
125
|
this.formElement.reset();
|
|
126
|
+
},
|
|
127
|
+
$dialogContainer() {
|
|
128
|
+
return this.formElement;
|
|
119
129
|
}
|
|
120
130
|
}
|
|
121
131
|
};
|
package/components/switch.vue
CHANGED
|
@@ -26,9 +26,9 @@ export default {
|
|
|
26
26
|
},
|
|
27
27
|
changed() {
|
|
28
28
|
if (this.enabled) {
|
|
29
|
-
GLib.action.execute(this.spec.onEnabled,
|
|
29
|
+
GLib.action.execute(this.spec.onEnabled, this);
|
|
30
30
|
} else {
|
|
31
|
-
GLib.action.execute(this.spec.onDisabled,
|
|
31
|
+
GLib.action.execute(this.spec.onDisabled, this);
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
}
|
package/index.js
CHANGED
|
@@ -78,6 +78,9 @@ Vue.mixin(stylesMixin);
|
|
|
78
78
|
import scrollingMixin from "./components/mixins/scrolling.js";
|
|
79
79
|
Vue.mixin(scrollingMixin);
|
|
80
80
|
|
|
81
|
+
import datasetMixins from "./components/mixins/dataset.js";
|
|
82
|
+
Vue.mixin(datasetMixins);
|
|
83
|
+
|
|
81
84
|
import longClickDirective from "./components/mixins/longClick.js";
|
|
82
85
|
window.longClickInstance = longClickDirective({ delay: 500, interval: 0 });
|
|
83
86
|
Vue.directive("longclick", window.longClickInstance);
|
package/nav/appbar.vue
CHANGED
|
@@ -108,7 +108,7 @@ export default {
|
|
|
108
108
|
},
|
|
109
109
|
viewSource: function() {
|
|
110
110
|
const properties = { message: this.page };
|
|
111
|
-
|
|
111
|
+
Utils.launch.dialog.open(Object.assign({}, properties));
|
|
112
112
|
},
|
|
113
113
|
avatarSpec(spec) {
|
|
114
114
|
return {
|
package/nav/dialog.vue
CHANGED
|
@@ -89,7 +89,7 @@ export default {
|
|
|
89
89
|
this.title = this.spec.title;
|
|
90
90
|
this.message = this.spec.message;
|
|
91
91
|
this.body = this.spec.body;
|
|
92
|
-
Action.execute(spec.onLoad,
|
|
92
|
+
Action.execute(spec.onLoad, this);
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
this.stack.push(this);
|
|
@@ -105,7 +105,7 @@ export default {
|
|
|
105
105
|
click(spec, event) {
|
|
106
106
|
const onClick = spec["onClick"];
|
|
107
107
|
this.model = false;
|
|
108
|
-
Action.execute(onClick,
|
|
108
|
+
Action.execute(onClick, this);
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
};
|
package/nav/drawer.vue
CHANGED
|
@@ -7,26 +7,41 @@
|
|
|
7
7
|
app
|
|
8
8
|
:class="cssClasses"
|
|
9
9
|
:dark="cssClasses.includes('dark')"
|
|
10
|
-
:expand-on-hover="expandOnHover()"
|
|
11
10
|
:permanent="cssClasses.includes('permanent')"
|
|
12
11
|
:style="style"
|
|
12
|
+
:expand-on-hover="expandOnHover()"
|
|
13
|
+
:mini-variant.sync="mini"
|
|
13
14
|
@input="updateState"
|
|
14
15
|
>
|
|
16
|
+
<template v-slot:prepend>
|
|
17
|
+
<v-list-item>
|
|
18
|
+
<v-list-item-icon>
|
|
19
|
+
<v-icon v-if="!mini">mdi-chevron-left</v-icon>
|
|
20
|
+
<v-icon v-if="mini">mdi-chevron-right</v-icon>
|
|
21
|
+
</v-list-item-icon>
|
|
22
|
+
</v-list-item>
|
|
23
|
+
</template>
|
|
24
|
+
|
|
15
25
|
<template v-if="spec.header">
|
|
16
|
-
<!-- <v-toolbar flat> -->
|
|
17
26
|
<panels-responsive :spec="spec.header" />
|
|
18
|
-
<!-- </v-toolbar> -->
|
|
19
|
-
<v-divider></v-divider>
|
|
20
27
|
</template>
|
|
21
28
|
|
|
22
29
|
<v-list dense class="pt-0">
|
|
23
|
-
<div v-for="(item, index) in spec.rows" :key="index">
|
|
30
|
+
<div v-for="(item, index) in spec.rows" :key="index" class="nav-item">
|
|
31
|
+
<div v-if="item.type == 'button'" class="indicator"></div>
|
|
24
32
|
<v-divider v-if="item.type == 'divider'" />
|
|
25
33
|
<nav-drawerLabel v-else-if="item.type == 'label'" :spec="item" />
|
|
26
34
|
<nav-drawerButton v-else :spec="item" />
|
|
27
|
-
<!-- <nav-drawerButton :spec="item" :state="state" v-else /> -->
|
|
28
35
|
</div>
|
|
29
36
|
</v-list>
|
|
37
|
+
|
|
38
|
+
<template v-if="spec.footer" v-slot:append>
|
|
39
|
+
<v-list-item>
|
|
40
|
+
<!-- Display the first line when the drawer is shrunk. Display the second line when the drawer is expanded -->
|
|
41
|
+
<div style="display: none">Show if expand</div>
|
|
42
|
+
<panels-responsive :spec="spec.footer" />
|
|
43
|
+
</v-list-item>
|
|
44
|
+
</template>
|
|
30
45
|
</v-navigation-drawer>
|
|
31
46
|
</template>
|
|
32
47
|
|
|
@@ -50,7 +65,8 @@ export default {
|
|
|
50
65
|
return {
|
|
51
66
|
// Using null as the starting value for its v-model will initialize the drawer as closed on mobile and as open on desktop.
|
|
52
67
|
// See https://vuetifyjs.com/en/components/navigation-drawers
|
|
53
|
-
state: null
|
|
68
|
+
state: null,
|
|
69
|
+
mini: true
|
|
54
70
|
};
|
|
55
71
|
},
|
|
56
72
|
computed: {
|
|
@@ -102,4 +118,18 @@ export default {
|
|
|
102
118
|
};
|
|
103
119
|
</script>
|
|
104
120
|
|
|
105
|
-
<style scoped
|
|
121
|
+
<style scoped>
|
|
122
|
+
.nav-item {
|
|
123
|
+
position: relative;
|
|
124
|
+
}
|
|
125
|
+
.nav-item:hover .indicator {
|
|
126
|
+
display: flex;
|
|
127
|
+
position: absolute;
|
|
128
|
+
width: 3px;
|
|
129
|
+
height: 65%;
|
|
130
|
+
margin: 10px 0;
|
|
131
|
+
justify-content: center;
|
|
132
|
+
align-items: center;
|
|
133
|
+
background-color: white;
|
|
134
|
+
}
|
|
135
|
+
</style>
|
package/nav/sheet.vue
CHANGED
|
@@ -49,8 +49,7 @@ export default {
|
|
|
49
49
|
this.model = false;
|
|
50
50
|
|
|
51
51
|
Utils.type.ifFunction(spec.onClickFunction, f => f());
|
|
52
|
-
GLib.action.execute(spec.onClick,
|
|
53
|
-
// this.$onClick(spec, event.target, this);
|
|
52
|
+
GLib.action.execute(spec.onClick, this);
|
|
54
53
|
}
|
|
55
54
|
}
|
|
56
55
|
};
|
package/nav/snackbar.vue
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "glib-web",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.9",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
"vue2-editor": "^2.9.1",
|
|
29
29
|
"vue2-google-maps": "^0.10.6",
|
|
30
30
|
"vuedraggable": "^2.24.1",
|
|
31
|
-
"vuetify": "2.3.9"
|
|
31
|
+
"vuetify": "2.3.9",
|
|
32
|
+
"driver.js": "^0.9.8"
|
|
32
33
|
},
|
|
33
34
|
"devDependencies": {
|
|
34
35
|
"@types/chart.js": "^2.9.34",
|
package/utils/form.js
CHANGED
|
@@ -2,12 +2,8 @@ export default class {
|
|
|
2
2
|
// Execution flows:
|
|
3
3
|
// Button -> Button.onClick() -> Utils.http.execute() -- doesn't save autofill values
|
|
4
4
|
// Button -> Button.onClick() -> form.submit() -- doesn't execute Form.onSubmit(), so cannot call Utils.http.execute() there
|
|
5
|
-
// Submit -> Form.onSubmit() -> Utils.http.execute() -- save autofill values
|
|
6
|
-
// TOTRY: Button -> Button.onClick() -> form.clickSubmit() -> submit.click() -> Form.onSubmit() -> Utils.http.execute()
|
|
5
|
+
// Submit -> Form.onSubmit() -> Utils.http.execute() -- save autofill values and auto-submit when ENTER is pressed
|
|
7
6
|
static submitData(form, component) {
|
|
8
|
-
// const form = target.closest("form");
|
|
9
|
-
// const form = this.formElement;
|
|
10
|
-
|
|
11
7
|
// Analogous to Rails' form_with's local
|
|
12
8
|
if (form.dataset.local) {
|
|
13
9
|
form.submit();
|
package/utils/http.js
CHANGED
|
@@ -54,7 +54,7 @@ export default class {
|
|
|
54
54
|
this.forceComponentUpdate(() => {
|
|
55
55
|
Utils.history.resetScroll();
|
|
56
56
|
window.vueApp.page = data;
|
|
57
|
-
Action.execute(properties["onOpen"],
|
|
57
|
+
Action.execute(properties["onOpen"], component);
|
|
58
58
|
});
|
|
59
59
|
});
|
|
60
60
|
} else {
|
|
@@ -109,7 +109,7 @@ export default class {
|
|
|
109
109
|
const redirectUrl = Utils.url.htmlUrl(response.url);
|
|
110
110
|
Utils.history.updatePage(redirectUrl);
|
|
111
111
|
|
|
112
|
-
GLib.action.execute(properties["onReload"],
|
|
112
|
+
GLib.action.execute(properties["onReload"], component);
|
|
113
113
|
});
|
|
114
114
|
});
|
|
115
115
|
}
|
package/utils/launch.js
CHANGED
|
@@ -5,7 +5,21 @@ import Snackbar from "../nav/snackbar";
|
|
|
5
5
|
import Vuetify from "vuetify";
|
|
6
6
|
|
|
7
7
|
export default class {
|
|
8
|
-
static dialog(
|
|
8
|
+
static get dialog() {
|
|
9
|
+
return LaunchDialog;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
static get sheet() {
|
|
13
|
+
return LaunchSheet;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
static get snackbar() {
|
|
17
|
+
return LaunchSnackbar;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
class LaunchDialog {
|
|
22
|
+
static open(properties, component) {
|
|
9
23
|
if (!this.stack) {
|
|
10
24
|
this.stack = [];
|
|
11
25
|
}
|
|
@@ -21,19 +35,20 @@ export default class {
|
|
|
21
35
|
propsData: {
|
|
22
36
|
spec: properties,
|
|
23
37
|
stack: this.stack,
|
|
24
|
-
target: target,
|
|
25
38
|
vueApp: window.vueApp
|
|
26
39
|
}
|
|
27
40
|
});
|
|
28
41
|
// instance.stack = this.stack;
|
|
29
42
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
43
|
+
if (component) {
|
|
44
|
+
const placeholder = component
|
|
45
|
+
.$dialogContainer()
|
|
46
|
+
.appendChild(document.createElement("div"));
|
|
47
|
+
instance.$mount(placeholder);
|
|
48
|
+
}
|
|
34
49
|
}
|
|
35
50
|
|
|
36
|
-
static
|
|
51
|
+
static close(properties, component) {
|
|
37
52
|
if (!this.stack) {
|
|
38
53
|
this.stack = [];
|
|
39
54
|
}
|
|
@@ -43,19 +58,11 @@ export default class {
|
|
|
43
58
|
});
|
|
44
59
|
|
|
45
60
|
Utils.type.ifObject(properties["onClose"], it => {
|
|
46
|
-
Action.execute(it,
|
|
61
|
+
Action.execute(it, component);
|
|
47
62
|
});
|
|
48
63
|
}
|
|
49
64
|
|
|
50
|
-
static
|
|
51
|
-
return LaunchSheet;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
static get snackbar() {
|
|
55
|
-
return LaunchSnackbar;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
static alert(message, target) {
|
|
65
|
+
static alert(message) {
|
|
59
66
|
const properties = {
|
|
60
67
|
message: message
|
|
61
68
|
};
|
|
@@ -67,7 +74,7 @@ export default class {
|
|
|
67
74
|
}
|
|
68
75
|
]
|
|
69
76
|
});
|
|
70
|
-
this.dialog(spec
|
|
77
|
+
this.dialog(spec);
|
|
71
78
|
}
|
|
72
79
|
}
|
|
73
80
|
|