glib-web 0.6.3 → 0.6.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 +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/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/nav/appbar.vue +1 -1
- package/nav/dialog.vue +2 -2
- 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/private/ws.js +1 -1
- package/utils/uploader.js +4 -22
package/action.js
CHANGED
|
@@ -45,6 +45,8 @@ import ActionsCreditCard from "./actions/auth/creditCard";
|
|
|
45
45
|
|
|
46
46
|
import ActionsAnalyticsLogEvent from "./actions/analytics/logEvent";
|
|
47
47
|
|
|
48
|
+
import ActionCommandsCopy from "./actions/commands/copy";
|
|
49
|
+
|
|
48
50
|
const actions = {
|
|
49
51
|
runMultiple: ActionsRunMultiple,
|
|
50
52
|
|
|
@@ -89,11 +91,12 @@ const actions = {
|
|
|
89
91
|
"auth/restart": ActionsAuthRestart,
|
|
90
92
|
"auth/creditCard": ActionsCreditCard,
|
|
91
93
|
|
|
92
|
-
"analytics/logEvent": ActionsAnalyticsLogEvent
|
|
94
|
+
"analytics/logEvent": ActionsAnalyticsLogEvent,
|
|
95
|
+
"commands/copy": ActionCommandsCopy
|
|
93
96
|
};
|
|
94
97
|
|
|
95
98
|
export default class Action {
|
|
96
|
-
static execute(spec,
|
|
99
|
+
static execute(spec, component, params = {}) {
|
|
97
100
|
if (!TypeUtils.isObject(spec)) {
|
|
98
101
|
return;
|
|
99
102
|
}
|
|
@@ -141,7 +144,7 @@ export default class Action {
|
|
|
141
144
|
if (!logDisabled) {
|
|
142
145
|
console.log(`Executing "${actionName}"`);
|
|
143
146
|
}
|
|
144
|
-
action.execute(spec,
|
|
147
|
+
action.execute(spec, component, params);
|
|
145
148
|
} catch (e) {
|
|
146
149
|
console.log(
|
|
147
150
|
"Failed executing command",
|
|
@@ -159,7 +162,7 @@ export default class Action {
|
|
|
159
162
|
}
|
|
160
163
|
|
|
161
164
|
window.vueApp.temp.analytics = response.analytics;
|
|
162
|
-
GLib.action.execute(response.onResponse,
|
|
165
|
+
GLib.action.execute(response.onResponse, component);
|
|
163
166
|
window.vueApp.temp.analytics = null;
|
|
164
167
|
}
|
|
165
168
|
}
|
|
@@ -9,9 +9,9 @@ export default class {
|
|
|
9
9
|
Utils.http.stopIndicator(component);
|
|
10
10
|
|
|
11
11
|
if (result.error) {
|
|
12
|
-
GLib.action.execute(properties.onFailure,
|
|
12
|
+
GLib.action.execute(properties.onFailure, component);
|
|
13
13
|
} else {
|
|
14
|
-
GLib.action.execute(properties.onSuccess,
|
|
14
|
+
GLib.action.execute(properties.onSuccess, component);
|
|
15
15
|
}
|
|
16
16
|
});
|
|
17
17
|
} else {
|
|
@@ -19,9 +19,9 @@ export default class {
|
|
|
19
19
|
Utils.http.stopIndicator(component);
|
|
20
20
|
|
|
21
21
|
if (result.error) {
|
|
22
|
-
GLib.action.execute(properties.onFailure,
|
|
22
|
+
GLib.action.execute(properties.onFailure, component);
|
|
23
23
|
} else {
|
|
24
|
-
GLib.action.execute(properties.onSuccess,
|
|
24
|
+
GLib.action.execute(properties.onSuccess, component);
|
|
25
25
|
}
|
|
26
26
|
});
|
|
27
27
|
}
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
// import Keys from '../../keys'
|
|
3
3
|
|
|
4
4
|
export default class {
|
|
5
|
-
execute(properties,
|
|
5
|
+
execute(properties, component) {
|
|
6
6
|
// console.log(properties['token'])
|
|
7
7
|
// Storage.setLocal(Keys.Db.csrfToken, properties['token'])
|
|
8
|
-
|
|
9
|
-
Utils.dom.setCsrf(properties[
|
|
10
|
-
Action.execute(properties[
|
|
8
|
+
|
|
9
|
+
Utils.dom.setCsrf(properties["token"]);
|
|
10
|
+
Action.execute(properties["onSave"], component);
|
|
11
11
|
}
|
|
12
12
|
}
|
package/actions/cables/push.js
CHANGED
|
@@ -1,17 +1,5 @@
|
|
|
1
1
|
export default class {
|
|
2
2
|
execute(properties) {
|
|
3
|
-
// const spec = Object.assign({}, properties, {
|
|
4
|
-
// buttons: [
|
|
5
|
-
// {
|
|
6
|
-
// text: "OK",
|
|
7
|
-
// onClick: properties.onClose
|
|
8
|
-
// }
|
|
9
|
-
// ]
|
|
10
|
-
// });
|
|
11
|
-
// Launch.dialog(spec);
|
|
12
|
-
|
|
13
|
-
// const ws = window.vueApp.actionCable;
|
|
14
|
-
|
|
15
3
|
Utils.type.ifString(properties.channel, channelName => {
|
|
16
4
|
const ws = window.vueApp.actionCable;
|
|
17
5
|
const channel = ws.channels[channelName];
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export default class {
|
|
2
|
+
execute(properties) {
|
|
3
|
+
let spec = Object.assign({}, properties, {
|
|
4
|
+
message: "Copied",
|
|
5
|
+
styleClasses: ["success"]
|
|
6
|
+
});
|
|
7
|
+
navigator.clipboard.writeText(properties.text).then(
|
|
8
|
+
() => Utils.launch.snackbar.open(spec),
|
|
9
|
+
reason => console.error("Could not copy text: " + reason)
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
}
|
package/actions/dialogs/alert.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Launch from "../../utils/launch";
|
|
2
2
|
|
|
3
3
|
export default class {
|
|
4
|
-
execute(properties) {
|
|
4
|
+
execute(properties, component) {
|
|
5
5
|
const spec = Object.assign({}, properties, {
|
|
6
6
|
buttons: [
|
|
7
7
|
{
|
|
@@ -10,6 +10,6 @@ export default class {
|
|
|
10
10
|
}
|
|
11
11
|
]
|
|
12
12
|
});
|
|
13
|
-
|
|
13
|
+
Utils.launch.dialog.open(spec, component);
|
|
14
14
|
}
|
|
15
15
|
}
|
package/actions/dialogs/close.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import Push from "push.js";
|
|
2
2
|
|
|
3
3
|
export default class {
|
|
4
|
-
execute(properties,
|
|
4
|
+
execute(properties, component) {
|
|
5
5
|
Push.create(properties.title, {
|
|
6
6
|
body: properties.message,
|
|
7
7
|
onClick() {
|
|
8
8
|
const onClick = properties.onClick;
|
|
9
|
-
GLib.action.execute(onClick,
|
|
9
|
+
GLib.action.execute(onClick, component);
|
|
10
10
|
this.close();
|
|
11
11
|
}
|
|
12
12
|
});
|
package/actions/dialogs/open.js
CHANGED
package/actions/dialogs/show.js
CHANGED
package/actions/forms/submit.js
CHANGED
|
@@ -1,15 +1,5 @@
|
|
|
1
1
|
export default class {
|
|
2
|
-
execute(properties,
|
|
3
|
-
|
|
4
|
-
if (form != null) {
|
|
5
|
-
form.submit();
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
// const vm = this;
|
|
9
|
-
// // Allows time for things to get finalized. For example, select.vue needs time to insert values
|
|
10
|
-
// // into hidden fields before they get submitted.
|
|
11
|
-
// setTimeout(() => {
|
|
12
|
-
// vm.submit(target, component);
|
|
13
|
-
// }, 10);
|
|
2
|
+
execute(properties, component) {
|
|
3
|
+
component.$dispatchEvent("forms/directSubmit");
|
|
14
4
|
}
|
|
15
5
|
}
|
package/actions/http/delete.js
CHANGED
package/actions/http/patch.js
CHANGED
package/actions/http/post.js
CHANGED
package/actions/http/put.js
CHANGED
package/actions/runMultiple.js
CHANGED
|
@@ -3,9 +3,9 @@ export default class {
|
|
|
3
3
|
return true;
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
execute(properties,
|
|
6
|
+
execute(properties, component) {
|
|
7
7
|
for (const action of properties.childActions) {
|
|
8
|
-
GLib.action.execute(action,
|
|
8
|
+
GLib.action.execute(action, component);
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
}
|
package/actions/timeouts/set.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export default class {
|
|
2
|
-
execute(properties,
|
|
2
|
+
execute(properties, component) {
|
|
3
3
|
component.$data._isBusy = true;
|
|
4
4
|
|
|
5
5
|
if (properties.repeat) {
|
|
@@ -15,6 +15,6 @@ export default class {
|
|
|
15
15
|
|
|
16
16
|
onTimeout(properties, component) {
|
|
17
17
|
component.$data._isBusy = false;
|
|
18
|
-
GLib.action.execute(properties.onTimeout,
|
|
18
|
+
GLib.action.execute(properties.onTimeout, component);
|
|
19
19
|
}
|
|
20
20
|
}
|
package/actions/windows/close.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
export default class {
|
|
2
|
-
execute(properties,
|
|
2
|
+
execute(properties, component) {
|
|
3
3
|
Utils.history.back();
|
|
4
4
|
|
|
5
5
|
Utils.type.ifObject(properties["onClose"], it => {
|
|
6
6
|
// Allow time for history.back() to complete, which is important for actions that need
|
|
7
7
|
// to use window.location.href such as windows/reload
|
|
8
8
|
setTimeout(function() {
|
|
9
|
-
GLib.action.execute(it,
|
|
9
|
+
GLib.action.execute(it, component);
|
|
10
10
|
}, 100);
|
|
11
11
|
});
|
|
12
12
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Type from "../../utils/type";
|
|
2
2
|
|
|
3
3
|
export default class {
|
|
4
|
-
execute(properties,
|
|
4
|
+
execute(properties, component) {
|
|
5
5
|
// TODO
|
|
6
6
|
// window.history.deleteAll()
|
|
7
7
|
|
|
@@ -9,7 +9,7 @@ export default class {
|
|
|
9
9
|
// Allow time for history.back() to complete, which is important for actions that need
|
|
10
10
|
// to use window.location.href such as windows/reload
|
|
11
11
|
setTimeout(function() {
|
|
12
|
-
GLib.action.execute(it,
|
|
12
|
+
GLib.action.execute(it, component);
|
|
13
13
|
}, 100);
|
|
14
14
|
});
|
|
15
15
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Hash from "../../utils/hash";
|
|
2
2
|
|
|
3
3
|
export default class {
|
|
4
|
-
execute(properties,
|
|
4
|
+
execute(properties, component) {
|
|
5
5
|
const fallbackUrl = new Hash(properties).remove("fallbackUrl");
|
|
6
6
|
const data = Object.assign({}, properties);
|
|
7
7
|
if (!Utils.history.back()) {
|
package/actions/windows/open.js
CHANGED
package/actions/ws/push.js
CHANGED
package/app.vue
CHANGED
|
@@ -42,13 +42,14 @@ import Utils from "./utils/helper";
|
|
|
42
42
|
import ContentLayout from "./nav/content";
|
|
43
43
|
import phoenixSocketMixin from "./components/mixins/ws/phoenixSocket.js";
|
|
44
44
|
import actionCableMixin from "./components/mixins/ws/actionCable.js";
|
|
45
|
+
import tourMixin from "./components/mixins/tour";
|
|
45
46
|
|
|
46
47
|
export default {
|
|
47
48
|
components: {
|
|
48
49
|
"nav-appbar": NavAppBar,
|
|
49
50
|
"layouts-content": ContentLayout
|
|
50
51
|
},
|
|
51
|
-
mixins: [phoenixSocketMixin, actionCableMixin],
|
|
52
|
+
mixins: [phoenixSocketMixin, actionCableMixin, tourMixin],
|
|
52
53
|
props: {
|
|
53
54
|
page: { type: Object, required: true }
|
|
54
55
|
},
|
|
@@ -103,12 +104,13 @@ export default {
|
|
|
103
104
|
if (Utils.history.isPoppedState(this.page)) {
|
|
104
105
|
setTimeout(() => {
|
|
105
106
|
// Wait until page is rendered
|
|
106
|
-
GLib.action.execute(this.page.onRefocus,
|
|
107
|
+
GLib.action.execute(this.page.onRefocus, this);
|
|
107
108
|
});
|
|
108
109
|
} else {
|
|
109
110
|
setTimeout(() => {
|
|
110
111
|
// Wait until page is rendered
|
|
111
|
-
GLib.action.execute(this.page.onLoad,
|
|
112
|
+
GLib.action.execute(this.page.onLoad, this);
|
|
113
|
+
this.startTour();
|
|
112
114
|
});
|
|
113
115
|
}
|
|
114
116
|
}
|
package/components/button.vue
CHANGED
|
@@ -21,11 +21,18 @@
|
|
|
21
21
|
</template>
|
|
22
22
|
|
|
23
23
|
<script>
|
|
24
|
-
import
|
|
24
|
+
import tooltipMixin from "./mixins/tooltip";
|
|
25
|
+
import tourMixin from "./mixins/tour";
|
|
26
|
+
|
|
25
27
|
export default {
|
|
26
|
-
mixins: [
|
|
28
|
+
mixins: [tooltipMixin, tourMixin],
|
|
27
29
|
props: {
|
|
28
30
|
spec: { type: Object, required: true }
|
|
31
|
+
},
|
|
32
|
+
methods: {
|
|
33
|
+
$ready() {
|
|
34
|
+
this.registerTour();
|
|
35
|
+
}
|
|
29
36
|
}
|
|
30
37
|
};
|
|
31
38
|
</script>
|
package/components/calendar.vue
CHANGED
package/components/component.vue
CHANGED
|
@@ -105,6 +105,8 @@ import ResponsivePanel from "./panels/responsive";
|
|
|
105
105
|
import UlPanel from "./panels/ul";
|
|
106
106
|
import WebPanel from "./panels/web";
|
|
107
107
|
|
|
108
|
+
import MultimediaVideo from "./multimedia/video";
|
|
109
|
+
|
|
108
110
|
import AlertBanner from "./banners/alert";
|
|
109
111
|
import SelectBanner from "./banners/select";
|
|
110
112
|
|
|
@@ -185,6 +187,8 @@ export default {
|
|
|
185
187
|
"panels-ul": UlPanel,
|
|
186
188
|
"panels-web": WebPanel,
|
|
187
189
|
|
|
190
|
+
"multimedia-video": MultimediaVideo,
|
|
191
|
+
|
|
188
192
|
"banners-alert": AlertBanner,
|
|
189
193
|
"banners-select": SelectBanner,
|
|
190
194
|
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
|
|
2
1
|
<!-- TODO: This probably can be merged with latLong-v1 or map-v1, i.e. add infoWindow support to latLong or map -->
|
|
3
2
|
|
|
4
3
|
<template>
|
|
5
|
-
<v-container fluid class=
|
|
4
|
+
<v-container fluid class="pa-0">
|
|
6
5
|
<div class="v-input v-text-field theme--light">
|
|
7
6
|
<div class="v-input__control">
|
|
8
7
|
<div class="v-input__slot">
|
|
9
8
|
<div class="v-text-field__slot">
|
|
10
|
-
<label
|
|
9
|
+
<label
|
|
10
|
+
class="v-label theme--light v-label--active"
|
|
11
|
+
style="left: 0px; right: auto; position: absolute;"
|
|
12
|
+
>Address</label
|
|
13
|
+
>
|
|
11
14
|
<!-- <gmap-place-input :default-place="placeName" :placeholder="Address" @place_changed="setPlace" /> -->
|
|
12
15
|
<gmap-autocomplete
|
|
13
16
|
:name="spec.name"
|
|
@@ -20,22 +23,39 @@
|
|
|
20
23
|
</div>
|
|
21
24
|
|
|
22
25
|
<gmap-map
|
|
26
|
+
ref="map"
|
|
23
27
|
:center="{ lat: 25.105497, lng: 121.597366 }"
|
|
24
28
|
:zoom="13"
|
|
25
29
|
map-type-id="roadmap"
|
|
26
30
|
style="width: 100%; height: 300px"
|
|
27
|
-
@click=
|
|
28
|
-
ref='map'
|
|
31
|
+
@click="onMapClick"
|
|
29
32
|
>
|
|
30
|
-
<gmap-info-window
|
|
31
|
-
|
|
33
|
+
<gmap-info-window
|
|
34
|
+
:options="infoOptions"
|
|
35
|
+
:position="markerPos"
|
|
36
|
+
:opened="infoWinOpen"
|
|
37
|
+
@closeclick="closeInfoWindow"
|
|
38
|
+
>
|
|
39
|
+
<div v-if="place !== null">
|
|
32
40
|
<strong>{{ place.name }}</strong>
|
|
33
41
|
<div>Place ID: {{ place.place_id }}</div>
|
|
34
42
|
<div>Address: {{ place.formatted_address }}</div>
|
|
35
|
-
<div>
|
|
43
|
+
<div>
|
|
44
|
+
Longitude: {{ place.geometry.location.lng() }}, Latitude:
|
|
45
|
+
{{ place.geometry.location.lat() }}
|
|
46
|
+
</div>
|
|
36
47
|
</div>
|
|
37
|
-
<div
|
|
38
|
-
|
|
48
|
+
<div
|
|
49
|
+
v-if="
|
|
50
|
+
spec.hasOwnProperty('infoWindow') &&
|
|
51
|
+
spec.infoWindow['actionButtons'].length > 0
|
|
52
|
+
"
|
|
53
|
+
>
|
|
54
|
+
<v-btn
|
|
55
|
+
v-for="(buttonSpec, i) in spec.infoWindow.actionButtons"
|
|
56
|
+
:key="i"
|
|
57
|
+
@click="onActionButtonClick($event, buttonSpec)"
|
|
58
|
+
>
|
|
39
59
|
{{ buttonSpec.text }}
|
|
40
60
|
</v-btn>
|
|
41
61
|
</div>
|
|
@@ -47,7 +67,7 @@
|
|
|
47
67
|
@click="openInfoWindow"
|
|
48
68
|
/>
|
|
49
69
|
<template v-slot:visible>
|
|
50
|
-
<div id="loading-container" class="d-none"
|
|
70
|
+
<div id="loading-container" ref="loading" class="d-none">
|
|
51
71
|
<v-progress-circular indeterminate color="primary" />
|
|
52
72
|
</div>
|
|
53
73
|
</template>
|
|
@@ -56,10 +76,10 @@
|
|
|
56
76
|
</template>
|
|
57
77
|
|
|
58
78
|
<script>
|
|
59
|
-
import Action from "../../action"
|
|
79
|
+
import Action from "../../action";
|
|
60
80
|
|
|
61
81
|
export default {
|
|
62
|
-
props: [
|
|
82
|
+
props: ["spec"],
|
|
63
83
|
data() {
|
|
64
84
|
return {
|
|
65
85
|
infoOptions: {
|
|
@@ -71,77 +91,85 @@ export default {
|
|
|
71
91
|
markerPos: { lat: 0, lng: 0 },
|
|
72
92
|
infoWinOpen: false,
|
|
73
93
|
place: null
|
|
74
|
-
}
|
|
94
|
+
};
|
|
75
95
|
},
|
|
76
96
|
computed: {
|
|
77
97
|
placeName() {
|
|
78
|
-
return
|
|
98
|
+
return this.place == null ? "" : this.place.name;
|
|
79
99
|
}
|
|
80
100
|
},
|
|
81
101
|
methods: {
|
|
82
102
|
closeInfoWindow() {
|
|
83
|
-
this.infoWinOpen = false
|
|
103
|
+
this.infoWinOpen = false;
|
|
84
104
|
},
|
|
85
105
|
openInfoWindow() {
|
|
86
|
-
this.infoWinOpen = true
|
|
106
|
+
this.infoWinOpen = true;
|
|
87
107
|
},
|
|
88
108
|
toggleLoadingIndicator() {
|
|
89
|
-
this.$refs.loading.classList.toggle(
|
|
90
|
-
this.$refs.loading.classList.toggle(
|
|
109
|
+
this.$refs.loading.classList.toggle("d-none");
|
|
110
|
+
this.$refs.loading.classList.toggle("d-flex");
|
|
91
111
|
},
|
|
92
112
|
onActionButtonClick(event, properties) {
|
|
93
|
-
properties.onClick[
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
113
|
+
properties.onClick["formData"] = {
|
|
114
|
+
"place[google_place_id]": this.place.place_id,
|
|
115
|
+
"place[name]": this.place.name,
|
|
116
|
+
"place[address]": this.place.formatted_address,
|
|
117
|
+
"place[longitude]": this.place.geometry.location.lng(),
|
|
118
|
+
"place[latitude]": this.place.geometry.location.lat()
|
|
119
|
+
};
|
|
100
120
|
|
|
101
|
-
Action.execute(properties.onClick,
|
|
121
|
+
Action.execute(properties.onClick, this);
|
|
102
122
|
},
|
|
103
123
|
onMapClick(e) {
|
|
104
|
-
this.closeInfoWindow()
|
|
124
|
+
this.closeInfoWindow();
|
|
105
125
|
|
|
106
126
|
if (e.placeId === undefined) {
|
|
107
|
-
return
|
|
127
|
+
return;
|
|
108
128
|
}
|
|
109
129
|
|
|
110
|
-
e.stop()
|
|
111
|
-
this.toggleLoadingIndicator()
|
|
130
|
+
e.stop();
|
|
131
|
+
this.toggleLoadingIndicator();
|
|
112
132
|
|
|
113
133
|
const request = {
|
|
114
134
|
placeId: e.placeId,
|
|
115
|
-
fields: [
|
|
116
|
-
}
|
|
117
|
-
var service = new google.maps.places.PlacesService(
|
|
135
|
+
fields: ["place_id", "geometry", "name", "formatted_address"]
|
|
136
|
+
};
|
|
137
|
+
var service = new google.maps.places.PlacesService(
|
|
138
|
+
this.$refs.map.$mapObject
|
|
139
|
+
);
|
|
118
140
|
service.getDetails(request, place => {
|
|
119
|
-
this.toggleLoadingIndicator()
|
|
120
|
-
this.markerPos = place.geometry.location
|
|
121
|
-
this.place = place
|
|
122
|
-
this.openInfoWindow()
|
|
123
|
-
})
|
|
141
|
+
this.toggleLoadingIndicator();
|
|
142
|
+
this.markerPos = place.geometry.location;
|
|
143
|
+
this.place = place;
|
|
144
|
+
this.openInfoWindow();
|
|
145
|
+
});
|
|
124
146
|
},
|
|
125
147
|
setLocationField(name, value) {
|
|
126
|
-
let field = document.querySelector(`input[name="${name}"]`)
|
|
127
|
-
field.closest(
|
|
128
|
-
field.closest(
|
|
129
|
-
field.previousSibling.classList.add(
|
|
130
|
-
field.value = value
|
|
148
|
+
let field = document.querySelector(`input[name="${name}"]`);
|
|
149
|
+
field.closest("div.v-input").classList.add("v-input--is-label-active");
|
|
150
|
+
field.closest("div.v-input").classList.add("v-input--is-dirty");
|
|
151
|
+
field.previousSibling.classList.add("v-label--active");
|
|
152
|
+
field.value = value;
|
|
131
153
|
},
|
|
132
154
|
setPlace(place) {
|
|
133
|
-
const { location } = place.geometry
|
|
134
|
-
this.place = place
|
|
135
|
-
this.markerPos = location
|
|
136
|
-
this.$refs.map.$mapObject.setCenter(location)
|
|
155
|
+
const { location } = place.geometry;
|
|
156
|
+
this.place = place;
|
|
157
|
+
this.markerPos = location;
|
|
158
|
+
this.$refs.map.$mapObject.setCenter(location);
|
|
137
159
|
|
|
138
|
-
if (this.spec.hasOwnProperty(
|
|
139
|
-
this.setLocationField(
|
|
140
|
-
|
|
160
|
+
if (this.spec.hasOwnProperty("locationFields")) {
|
|
161
|
+
this.setLocationField(
|
|
162
|
+
this.spec.locationFields.latitudeName,
|
|
163
|
+
location.lat()
|
|
164
|
+
);
|
|
165
|
+
this.setLocationField(
|
|
166
|
+
this.spec.locationFields.longitudeName,
|
|
167
|
+
location.lng()
|
|
168
|
+
);
|
|
141
169
|
}
|
|
142
170
|
}
|
|
143
171
|
}
|
|
144
|
-
}
|
|
172
|
+
};
|
|
145
173
|
</script>
|
|
146
174
|
|
|
147
175
|
<style scoped>
|
|
@@ -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/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/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.4",
|
|
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
|
|
package/utils/private/ws.js
CHANGED
package/utils/uploader.js
CHANGED
|
@@ -63,28 +63,6 @@ export default class Uploader {
|
|
|
63
63
|
|
|
64
64
|
validateFile(spec) {
|
|
65
65
|
return this.validateFileAccordingToRules(spec.accepts);
|
|
66
|
-
|
|
67
|
-
// if (Type.isString(spec.accepts)) {
|
|
68
|
-
// if (spec.accepts) {
|
|
69
|
-
// const acceptsRegex = new RegExp(spec.accepts);
|
|
70
|
-
|
|
71
|
-
// if (!acceptsRegex.test(this.file.type)) {
|
|
72
|
-
// alert("Invalid file type.");
|
|
73
|
-
// return false;
|
|
74
|
-
// }
|
|
75
|
-
// }
|
|
76
|
-
|
|
77
|
-
// if (spec.file_size_limit) {
|
|
78
|
-
// if (this.file.size > spec.file_size_limit * MB_SIZE) {
|
|
79
|
-
// alert(spec.file_size_limit_alert_text);
|
|
80
|
-
// return false;
|
|
81
|
-
// }
|
|
82
|
-
// }
|
|
83
|
-
// } else {
|
|
84
|
-
// return this.validateFileAccordingToRules(spec.accepts);
|
|
85
|
-
// }
|
|
86
|
-
|
|
87
|
-
// return true;
|
|
88
66
|
}
|
|
89
67
|
|
|
90
68
|
validateFileAccordingToRules(spec) {
|
|
@@ -98,6 +76,10 @@ export default class Uploader {
|
|
|
98
76
|
case "pdf":
|
|
99
77
|
mimeType = "application/pdf";
|
|
100
78
|
break;
|
|
79
|
+
case "zip":
|
|
80
|
+
// See https://stackoverflow.com/questions/856013/mime-type-for-zip-file-in-google-chrome
|
|
81
|
+
mimeType = "application/(zip|x-zip-compressed|octet-stream)";
|
|
82
|
+
break;
|
|
101
83
|
default:
|
|
102
84
|
return;
|
|
103
85
|
}
|