glib-web 2.6.7 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/action.js +39 -17
- package/actions/analytics/logEvent.js +2 -2
- package/actions/auth/saveCsrfToken.js +6 -0
- package/actions/cables/push.js +4 -4
- package/actions/commands/enqueue.js +17 -0
- package/actions/fields/reset.js +2 -2
- package/actions/http/get.js +15 -27
- package/actions/panels/scrollTo.js +1 -1
- package/actions/panels/scrollToBottom.js +1 -1
- package/actions/popovers/close.js +5 -0
- package/actions/popovers/open.js +9 -0
- package/actions/windows/closeWithReload.js +1 -1
- package/actions/windows/refreshState.js +3 -1
- package/actions/ws/push.js +5 -3
- package/app.vue +59 -27
- package/components/_badge.vue +1 -6
- package/components/_button.vue +30 -30
- package/components/_chip.vue +27 -29
- package/components/_dropdownMenu.vue +10 -23
- package/components/_icon.vue +5 -5
- package/components/_responsive.vue +7 -21
- package/components/avatar.vue +11 -15
- package/components/banners/alert.vue +2 -7
- package/components/banners/select.vue +18 -30
- package/components/button.vue +4 -5
- package/components/component.vue +112 -133
- package/components/datetime.vue +2 -0
- package/components/fields/_patternText.vue +8 -19
- package/components/fields/_select.vue +9 -27
- package/components/fields/autocomplete.vue +8 -21
- package/components/fields/check.vue +5 -12
- package/components/fields/checkGroup.vue +3 -13
- package/components/fields/country/field.vue +9 -27
- package/components/fields/date.vue +5 -5
- package/components/fields/datetime.vue +6 -11
- package/components/fields/dynamicSelect.vue +8 -29
- package/components/fields/file.vue +10 -29
- package/components/fields/newRichText.vue +67 -54
- package/components/fields/otpField.vue +11 -31
- package/components/fields/phone/field.vue +60 -78
- package/components/fields/radio.vue +8 -44
- package/components/fields/radioGroup.vue +17 -19
- package/components/fields/rating.vue +9 -16
- package/components/fields/richText.vue +27 -45
- package/components/fields/select.vue +10 -7
- package/components/fields/stripe/stripeFields.vue +9 -2
- package/components/fields/stripe/stripeIndividualFields.vue +9 -7
- package/components/fields/stripeExternalAccount.vue +10 -24
- package/components/fields/text.vue +26 -50
- package/components/fields/textarea.vue +14 -27
- package/components/fields/timeZone.vue +9 -6
- package/components/fields/timer.vue +5 -11
- package/components/image.vue +12 -23
- package/components/label.vue +10 -18
- package/components/markdown.vue +45 -23
- package/components/mixins/events.js +24 -25
- package/components/mixins/generic.js +7 -4
- package/components/mixins/inputVariant.js +16 -0
- package/components/mixins/list/autoload.js +7 -5
- package/components/mixins/styles.js +16 -16
- package/components/mixins/table/autoload.js +6 -4
- package/components/mixins/ws/actionCable.js +6 -5
- package/components/mixins/ws/phoenixSocket.js +11 -9
- package/components/p.vue +10 -0
- package/components/panels/column.vue +8 -19
- package/components/panels/custom.vue +9 -13
- package/components/panels/flow.vue +19 -13
- package/components/panels/form.vue +26 -34
- package/components/panels/grid.vue +15 -9
- package/components/panels/horizontal.vue +58 -54
- package/components/panels/list.vue +37 -72
- package/components/panels/responsive.vue +2 -33
- package/components/panels/scroll.vue +3 -0
- package/components/panels/split.vue +2 -2
- package/components/panels/table.vue +32 -63
- package/components/panels/timeline.vue +20 -30
- package/components/panels/vertical.vue +8 -13
- package/components/popover.vue +39 -0
- package/components/progressCircle.vue +2 -8
- package/components/progressbar.vue +4 -14
- package/components/shareButton.vue +24 -30
- package/components/tabBar.vue +29 -28
- package/index.js +60 -94
- package/nav/appbar.vue +8 -6
- package/nav/dialog.vue +30 -49
- package/nav/drawer.vue +39 -51
- package/nav/drawerButton.vue +5 -7
- package/nav/drawerLabel.vue +2 -3
- package/nav/sheet.vue +21 -22
- package/nav/snackbar.vue +19 -30
- package/package.json +13 -16
- package/plugins/driverCustomBehavior.js +1 -1
- package/plugins/updatableComponent.js +2 -2
- package/plugins/vuetify.js +26 -0
- package/store.js +16 -0
- package/templates/comment.vue +42 -19
- package/templates/featured.vue +8 -9
- package/templates/thumbnail-old.vue +188 -0
- package/templates/thumbnail.vue +3 -208
- package/tsconfig.json +1 -1
- package/utils/component.js +18 -18
- package/utils/constant.js +4 -0
- package/utils/eventBus.js +9 -2
- package/utils/history.js +12 -8
- package/utils/http.js +29 -71
- package/utils/launch.js +89 -52
- package/utils/private/ws.js +5 -3
- package/utils/public.js +6 -0
- package/utils/queue.js +102 -0
- package/utils/settings.js +3 -9
package/utils/history.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { nextTick } from "vue";
|
|
2
|
+
import eventBus from "./eventBus";
|
|
3
|
+
import { vueApp } from "../store";
|
|
2
4
|
|
|
3
5
|
export default class {
|
|
4
6
|
static saveInitialContent(content) {
|
|
@@ -20,7 +22,7 @@ export default class {
|
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
static _data(content) {
|
|
23
|
-
return { content: content, navigationCount: this.navigationCount };
|
|
25
|
+
return { content: JSON.parse(JSON.stringify(content)), navigationCount: this.navigationCount };
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
static pushPage(content, url) {
|
|
@@ -47,17 +49,19 @@ export default class {
|
|
|
47
49
|
// return false;
|
|
48
50
|
// }
|
|
49
51
|
|
|
50
|
-
|
|
52
|
+
vueApp.isFormDirty = false
|
|
51
53
|
|
|
52
54
|
// Save scroll position of the current page when navigating through back/forward button
|
|
53
55
|
this.bodyScrollTops[this.navigationCount] = this._pageBody.scrollTop;
|
|
54
56
|
|
|
55
57
|
const data = event.state;
|
|
56
58
|
data.content.__poppedState = true;
|
|
57
|
-
|
|
59
|
+
//
|
|
60
|
+
|
|
61
|
+
vueApp.page = data.content
|
|
58
62
|
vm.navigationCount = data.navigationCount;
|
|
59
63
|
|
|
60
|
-
|
|
64
|
+
nextTick(() => {
|
|
61
65
|
const scrollTop = this.bodyScrollTops[this.navigationCount];
|
|
62
66
|
this._pageBody.scrollTop = scrollTop;
|
|
63
67
|
});
|
|
@@ -68,8 +72,8 @@ export default class {
|
|
|
68
72
|
return page.__poppedState == true;
|
|
69
73
|
}
|
|
70
74
|
|
|
71
|
-
static updatePage(url = window.location.href) {
|
|
72
|
-
window.history.replaceState(this._data(
|
|
75
|
+
static updatePage(page, url = window.location.href) {
|
|
76
|
+
window.history.replaceState(this._data(page), "", url);
|
|
73
77
|
}
|
|
74
78
|
|
|
75
79
|
static back() {
|
|
@@ -77,7 +81,7 @@ export default class {
|
|
|
77
81
|
window.history.back();
|
|
78
82
|
return true;
|
|
79
83
|
} else {
|
|
80
|
-
console.
|
|
84
|
+
console.log("Reached beginning of navigation stack");
|
|
81
85
|
return false;
|
|
82
86
|
}
|
|
83
87
|
}
|
package/utils/http.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import Type from "./type";
|
|
2
2
|
import Action from "../action";
|
|
3
|
-
import
|
|
3
|
+
import eventBus from "./eventBus";
|
|
4
|
+
import { nextTick } from 'vue'
|
|
5
|
+
import { vueApp } from "../store";
|
|
4
6
|
|
|
5
7
|
let loading = false;
|
|
6
8
|
const dirtyPrompt = "Changes you made have not been saved. Are you sure?";
|
|
@@ -31,8 +33,7 @@ export default class {
|
|
|
31
33
|
const formData = new FormData();
|
|
32
34
|
var params = data || {};
|
|
33
35
|
for (const key in params) {
|
|
34
|
-
|
|
35
|
-
this._populateFormData(formData, key, params[key]);
|
|
36
|
+
formData.append(key, params[key]);
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
if (needCsrfToken && !Type.isString(params["authenticity_token"])) {
|
|
@@ -41,33 +42,8 @@ export default class {
|
|
|
41
42
|
return formData;
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
static _populateFormData(formData, key, value) {
|
|
45
|
-
if (GLib.type.isArray(value)) {
|
|
46
|
-
for (const item of value) {
|
|
47
|
-
this._populateFormData(formData, `${key}[]`, item);
|
|
48
|
-
}
|
|
49
|
-
} else if (GLib.type.isObject(value)) {
|
|
50
|
-
for (const innerKey in value) {
|
|
51
|
-
this._populateFormData(
|
|
52
|
-
formData,
|
|
53
|
-
`${key}[${innerKey}]`,
|
|
54
|
-
value[innerKey]
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
} else {
|
|
58
|
-
formData.append(key, value);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
45
|
static load(properties, component) {
|
|
63
|
-
const
|
|
64
|
-
let url;
|
|
65
|
-
try {
|
|
66
|
-
url = new URL(urlString);
|
|
67
|
-
} catch (e) {
|
|
68
|
-
console.warn("Invalid URL", urlString);
|
|
69
|
-
throw e;
|
|
70
|
-
}
|
|
46
|
+
const url = new URL(properties["url"]);
|
|
71
47
|
const domainMatched = window.location.hostname == url.hostname;
|
|
72
48
|
|
|
73
49
|
// If this is an external domain, we rely on `onUnload()` instead.
|
|
@@ -87,7 +63,9 @@ export default class {
|
|
|
87
63
|
|
|
88
64
|
this.forceComponentUpdate(() => {
|
|
89
65
|
Utils.history.resetScroll();
|
|
90
|
-
|
|
66
|
+
|
|
67
|
+
vueApp.page = data
|
|
68
|
+
|
|
91
69
|
Action.execute(properties["onOpen"], component);
|
|
92
70
|
});
|
|
93
71
|
});
|
|
@@ -99,7 +77,7 @@ export default class {
|
|
|
99
77
|
|
|
100
78
|
static analyticsHeaders(component) {
|
|
101
79
|
const pageAnalytics =
|
|
102
|
-
|
|
80
|
+
vueApp.temp.analytics || vueApp.page || {};
|
|
103
81
|
const featureAnalytics = pageAnalytics.feature;
|
|
104
82
|
|
|
105
83
|
const headers = {};
|
|
@@ -140,16 +118,16 @@ export default class {
|
|
|
140
118
|
|
|
141
119
|
Utils.http.execute(data, "GET", component, (page, response) => {
|
|
142
120
|
Utils.http.forceComponentUpdate(() => {
|
|
143
|
-
|
|
121
|
+
vueApp.page = page
|
|
144
122
|
const redirectUrl = Utils.url.htmlUrl(response.url);
|
|
145
|
-
Utils.history.updatePage(redirectUrl);
|
|
123
|
+
Utils.history.updatePage(page, redirectUrl);
|
|
146
124
|
|
|
147
125
|
GLib.action.execute(properties["onReload"], component);
|
|
148
126
|
});
|
|
149
127
|
});
|
|
150
128
|
}
|
|
151
129
|
|
|
152
|
-
static execute(properties, methodName, component, jsonHandler
|
|
130
|
+
static execute(properties, methodName, component, jsonHandler) {
|
|
153
131
|
this.startIndicator(component);
|
|
154
132
|
|
|
155
133
|
// `fetch()` only supports uppercase
|
|
@@ -160,23 +138,18 @@ export default class {
|
|
|
160
138
|
url = Utils.url.appendParams(url, body);
|
|
161
139
|
body = null;
|
|
162
140
|
}
|
|
163
|
-
console.
|
|
141
|
+
console.log(`${method} ${url}`);
|
|
164
142
|
|
|
165
143
|
const request = new HttpRequest();
|
|
166
144
|
let response = null;
|
|
167
145
|
const vm = this;
|
|
168
146
|
|
|
169
147
|
const analyticsHeaders = this.analyticsHeaders(component);
|
|
170
|
-
const headers = Object.assign(
|
|
171
|
-
{ Accept: "text/html" },
|
|
172
|
-
analyticsHeaders,
|
|
173
|
-
GLib.settings.headerAugmenter(url, method)
|
|
174
|
-
);
|
|
175
148
|
|
|
176
149
|
fetch(url, {
|
|
177
150
|
method: method,
|
|
178
151
|
body: body,
|
|
179
|
-
headers:
|
|
152
|
+
headers: Object.assign({ Accept: "text/html" }, analyticsHeaders),
|
|
180
153
|
// Make sure to pass cookies for same origin URLs.
|
|
181
154
|
// Needed for some browsers, e.g. Edge and Android's native.
|
|
182
155
|
credentials: "same-origin",
|
|
@@ -185,12 +158,12 @@ export default class {
|
|
|
185
158
|
.then(res => {
|
|
186
159
|
vm.stopIndicator(component);
|
|
187
160
|
|
|
188
|
-
response = res;
|
|
189
161
|
if (res.status >= 500) {
|
|
190
162
|
throw "Server error";
|
|
191
163
|
} else if (res.status >= 400) {
|
|
192
164
|
throw "Not accessible";
|
|
193
165
|
} else {
|
|
166
|
+
response = res;
|
|
194
167
|
return res.json();
|
|
195
168
|
}
|
|
196
169
|
})
|
|
@@ -200,17 +173,9 @@ export default class {
|
|
|
200
173
|
})
|
|
201
174
|
.catch(error => {
|
|
202
175
|
vm.stopIndicator(component);
|
|
203
|
-
|
|
204
176
|
if (!request.canceled) {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
console.error("Error:", message);
|
|
208
|
-
|
|
209
|
-
if (errorHandler) {
|
|
210
|
-
errorHandler(error, response);
|
|
211
|
-
} else {
|
|
212
|
-
Utils.launch.snackbar.error(message, component);
|
|
213
|
-
}
|
|
177
|
+
console.error("Error:", error);
|
|
178
|
+
Utils.launch.snackbar.error(error, component);
|
|
214
179
|
} else {
|
|
215
180
|
console.info("Canceled");
|
|
216
181
|
}
|
|
@@ -234,54 +199,47 @@ export default class {
|
|
|
234
199
|
setTimeout(() => {
|
|
235
200
|
if (loading) {
|
|
236
201
|
loading = false;
|
|
237
|
-
|
|
202
|
+
vueApp.indicator = true
|
|
238
203
|
}
|
|
239
204
|
}, 200);
|
|
240
205
|
}
|
|
241
206
|
|
|
242
207
|
static _hideIndicator() {
|
|
243
208
|
loading = false;
|
|
244
|
-
|
|
209
|
+
vueApp.indicator = false
|
|
245
210
|
}
|
|
246
211
|
|
|
247
212
|
// See generic.js
|
|
248
213
|
static forceComponentUpdate(handler) {
|
|
249
214
|
// GLib.component.clearRegistry();
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
215
|
+
vueApp.isStale = true
|
|
216
|
+
vueApp.isFormSubmitted = false
|
|
217
|
+
vueApp.isFormDirty = false
|
|
218
|
+
handler();
|
|
254
219
|
|
|
255
220
|
// Queue the execution so the first isStale has time to resets state before handler gets executed
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
dirtyContext.isFormDirty = false;
|
|
259
|
-
handler();
|
|
260
|
-
window.vueApp.isStale = false;
|
|
221
|
+
nextTick(() => {
|
|
222
|
+
vueApp.isStale = false
|
|
261
223
|
});
|
|
262
224
|
}
|
|
263
225
|
|
|
264
226
|
static promptIfDirtyOnUnload() {
|
|
265
227
|
window.onbeforeunload = () => {
|
|
266
|
-
|
|
228
|
+
vueApp.isFormDirty ? dirtyPrompt : null;
|
|
267
229
|
};
|
|
268
230
|
}
|
|
269
231
|
|
|
270
|
-
static dirtyContext() {
|
|
271
|
-
return Utils.launch.dialog.topDialog() || window.vueApp;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
232
|
static clearDirtyState() {
|
|
275
|
-
|
|
233
|
+
vueApp.isFormDirty = false
|
|
276
234
|
}
|
|
277
235
|
|
|
278
236
|
static notifyFormSubmitted() {
|
|
279
|
-
|
|
237
|
+
vueApp.isFormSubmitted = true
|
|
280
238
|
}
|
|
281
239
|
|
|
282
240
|
// `context` can be either window or dialog.
|
|
283
241
|
static proceedEvenWhenDirty() {
|
|
284
|
-
const dirtyContext =
|
|
242
|
+
const dirtyContext = vueApp
|
|
285
243
|
// Don't prompt if this is a result of form submission
|
|
286
244
|
if (
|
|
287
245
|
dirtyContext.isFormDirty &&
|
package/utils/launch.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import Vue from "
|
|
2
|
-
import Dialog from "../nav/dialog";
|
|
3
|
-
import Sheet from "../nav/sheet";
|
|
4
|
-
import Snackbar from "../nav/snackbar";
|
|
5
|
-
import
|
|
1
|
+
import { Vue } from "../index";
|
|
2
|
+
import Dialog from "../nav/dialog.vue";
|
|
3
|
+
import Sheet from "../nav/sheet.vue";
|
|
4
|
+
import Snackbar from "../nav/snackbar.vue";
|
|
5
|
+
import Popover from "../components/popover.vue";
|
|
6
|
+
import { computePosition, shift, offset } from '@floating-ui/dom'
|
|
7
|
+
import bus from "./eventBus";
|
|
8
|
+
|
|
9
|
+
import { createApp, h } from "vue";
|
|
6
10
|
|
|
7
11
|
export default class {
|
|
8
12
|
static get dialog() {
|
|
@@ -16,11 +20,53 @@ export default class {
|
|
|
16
20
|
static get snackbar() {
|
|
17
21
|
return LaunchSnackbar;
|
|
18
22
|
}
|
|
23
|
+
|
|
24
|
+
static get popover() {
|
|
25
|
+
return LaunchPopover;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
class LaunchPopover {
|
|
30
|
+
static open(properties, component) {
|
|
31
|
+
const instance = createApp(
|
|
32
|
+
{
|
|
33
|
+
render: function () {
|
|
34
|
+
return h(Popover, { spec: properties })
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
)
|
|
38
|
+
Object.assign(instance._context, Vue._context)
|
|
39
|
+
|
|
40
|
+
if (component) {
|
|
41
|
+
const placeholder = document.createElement('div')
|
|
42
|
+
component.$el.parentElement.appendChild(placeholder)
|
|
43
|
+
instance.mount(placeholder);
|
|
44
|
+
|
|
45
|
+
const reference = component.$el instanceof HTMLElement ? component.$el : component.$el.nextElementSibling
|
|
46
|
+
|
|
47
|
+
const floating = placeholder
|
|
48
|
+
const placement = properties.location || 'right'
|
|
49
|
+
const offsetSize = properties.offset || 8
|
|
50
|
+
computePosition(reference, floating, { placement: placement, middleware: [shift(), offset(offsetSize)] })
|
|
51
|
+
.then(({ x, y }) => {
|
|
52
|
+
Object.assign(placeholder.style, { top: `${y}px`, left: `${x}px`, position: 'absolute', zIndex: 1000, display: 'block' })
|
|
53
|
+
})
|
|
54
|
+
} else {
|
|
55
|
+
console.error("A popover has to be displayed in a component");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return instance;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static close(properties) {
|
|
62
|
+
bus.$emit(`popover/close-${properties.key}`, properties)
|
|
63
|
+
}
|
|
19
64
|
}
|
|
20
65
|
|
|
21
66
|
class LaunchDialog {
|
|
22
67
|
static closestBody(component) {
|
|
23
|
-
const
|
|
68
|
+
const element = component.$el instanceof HTMLElement ? component.$el : component.$el.nextElementSibling
|
|
69
|
+
const dialog = element.closest(".v-dialog");
|
|
24
70
|
if (dialog) {
|
|
25
71
|
return dialog.querySelector(".dialogs-body");
|
|
26
72
|
}
|
|
@@ -44,30 +90,26 @@ class LaunchDialog {
|
|
|
44
90
|
this.stack = [];
|
|
45
91
|
}
|
|
46
92
|
|
|
93
|
+
|
|
47
94
|
// https://css-tricks.com/creating-vue-js-component-instances-programmatically/
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
95
|
+
const props = {
|
|
96
|
+
spec: properties,
|
|
97
|
+
stack: this.stack
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const instance = createApp(
|
|
101
|
+
{
|
|
102
|
+
render: function () {
|
|
103
|
+
return h(Dialog, props)
|
|
53
104
|
}
|
|
54
|
-
}),
|
|
55
|
-
propsData: {
|
|
56
|
-
spec: properties,
|
|
57
|
-
stack: this.stack,
|
|
58
|
-
vueApp: window.vueApp
|
|
59
105
|
}
|
|
60
|
-
|
|
106
|
+
)
|
|
107
|
+
Object.assign(instance._context, Vue._context)
|
|
61
108
|
|
|
62
109
|
if (component) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const placeholder = component.$el.appendChild(
|
|
68
|
-
document.createElement("div")
|
|
69
|
-
);
|
|
70
|
-
instance.$mount(placeholder);
|
|
110
|
+
const placeholder = document.createElement('div')
|
|
111
|
+
document.body.appendChild(placeholder)
|
|
112
|
+
instance.mount(placeholder);
|
|
71
113
|
} else {
|
|
72
114
|
console.error("A dialog has to be displayed in a component");
|
|
73
115
|
}
|
|
@@ -116,21 +158,19 @@ class LaunchDialog {
|
|
|
116
158
|
|
|
117
159
|
class LaunchSheet {
|
|
118
160
|
static open(properties, component) {
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
themes: Utils.settings.themes
|
|
161
|
+
const instance = createApp(
|
|
162
|
+
{
|
|
163
|
+
render: function () {
|
|
164
|
+
return h(Sheet, { spec: properties })
|
|
124
165
|
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
|
|
166
|
+
}
|
|
167
|
+
)
|
|
168
|
+
Object.assign(instance._context, Vue._context)
|
|
128
169
|
|
|
129
170
|
if (component) {
|
|
130
|
-
const placeholder =
|
|
131
|
-
|
|
132
|
-
);
|
|
133
|
-
instance.$mount(placeholder);
|
|
171
|
+
const placeholder = document.createElement('div')
|
|
172
|
+
document.body.appendChild(placeholder)
|
|
173
|
+
instance.mount(placeholder);
|
|
134
174
|
} else {
|
|
135
175
|
console.error("A sheet has to be displayed in a component");
|
|
136
176
|
}
|
|
@@ -158,25 +198,22 @@ class LaunchSheet {
|
|
|
158
198
|
|
|
159
199
|
class LaunchSnackbar {
|
|
160
200
|
static open(properties, component) {
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
201
|
+
const instance = createApp(
|
|
202
|
+
{
|
|
203
|
+
render: function () {
|
|
204
|
+
return h(Snackbar, { spec: properties })
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
)
|
|
208
|
+
Object.assign(instance._context, Vue._context)
|
|
166
209
|
|
|
167
210
|
if (component) {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
// );
|
|
172
|
-
|
|
173
|
-
const placeholder = document.body.appendChild(
|
|
174
|
-
document.createElement("div")
|
|
175
|
-
);
|
|
176
|
-
instance.$mount(placeholder);
|
|
211
|
+
const placeholder = document.createElement('div')
|
|
212
|
+
document.body.appendChild(placeholder)
|
|
213
|
+
instance.mount(placeholder);
|
|
177
214
|
instance.show = true;
|
|
178
215
|
} else {
|
|
179
|
-
console.error("A
|
|
216
|
+
console.error("A Snackbar has to be displayed in a component");
|
|
180
217
|
}
|
|
181
218
|
|
|
182
219
|
return instance;
|
package/utils/private/ws.js
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
|
+
import { vueApp } from "../../store";
|
|
2
|
+
|
|
1
3
|
export default class {
|
|
2
4
|
static handleResponse(payload, component) {
|
|
3
5
|
if (!Utils.type.isObject(payload)) {
|
|
4
6
|
return;
|
|
5
7
|
}
|
|
6
8
|
|
|
7
|
-
const ws =
|
|
9
|
+
const ws = vueApp.webSocket;
|
|
8
10
|
Utils.type.ifObject(payload.wsHeader, header => {
|
|
9
11
|
Object.assign(ws.header, header);
|
|
10
|
-
console.
|
|
12
|
+
console.log("New header: ", ws.header);
|
|
11
13
|
});
|
|
12
14
|
|
|
13
15
|
const actionName = payload.action;
|
|
14
16
|
if (actionName.startsWith("component/")) {
|
|
15
17
|
const methodName = actionName.replace(/^component\//, "");
|
|
16
|
-
console.
|
|
18
|
+
console.log(`Executing component action: ${methodName}`);
|
|
17
19
|
component[`action_${methodName}`](payload);
|
|
18
20
|
} else {
|
|
19
21
|
GLib.action.execute(payload, component);
|
package/utils/public.js
CHANGED
|
@@ -5,8 +5,11 @@ import Type from "./type";
|
|
|
5
5
|
import Form from "./form";
|
|
6
6
|
import Component from "./component";
|
|
7
7
|
import Hash from "./hash";
|
|
8
|
+
import Queue from "./queue";
|
|
8
9
|
import Settings from "./settings";
|
|
9
10
|
|
|
11
|
+
const _queue = new Queue();
|
|
12
|
+
|
|
10
13
|
export default class {
|
|
11
14
|
static get action() {
|
|
12
15
|
return Action;
|
|
@@ -32,4 +35,7 @@ export default class {
|
|
|
32
35
|
static get settings() {
|
|
33
36
|
return Settings;
|
|
34
37
|
}
|
|
38
|
+
static get queue() {
|
|
39
|
+
return _queue;
|
|
40
|
+
}
|
|
35
41
|
}
|
package/utils/queue.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// From https://stackoverflow.com/questions/47157428/how-to-implement-a-pseudo-blocking-async-queue-in-js-ts
|
|
2
|
+
|
|
3
|
+
// const jobQueue = [];
|
|
4
|
+
export default class {
|
|
5
|
+
constructor() {
|
|
6
|
+
// invariant: at least one of the arrays is empty
|
|
7
|
+
this.resolvers = [];
|
|
8
|
+
this.promises = [];
|
|
9
|
+
}
|
|
10
|
+
_add() {
|
|
11
|
+
this.promises.push(
|
|
12
|
+
new Promise(resolve => {
|
|
13
|
+
this.resolvers.push(resolve);
|
|
14
|
+
})
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
enqueue(t) {
|
|
18
|
+
// if (this.resolvers.length) this.resolvers.shift()(t);
|
|
19
|
+
// else this.promises.push(Promise.resolve(t));
|
|
20
|
+
if (!this.resolvers.length) this._add();
|
|
21
|
+
this.resolvers.shift()(t);
|
|
22
|
+
}
|
|
23
|
+
dequeue() {
|
|
24
|
+
if (!this.promises.length) this._add();
|
|
25
|
+
return this.promises.shift();
|
|
26
|
+
}
|
|
27
|
+
// now some utilities:
|
|
28
|
+
isEmpty() {
|
|
29
|
+
// there are no values available
|
|
30
|
+
return !this.promises.length; // this.length <= 0
|
|
31
|
+
}
|
|
32
|
+
isBlocked() {
|
|
33
|
+
// it's waiting for values
|
|
34
|
+
return !!this.resolvers.length; // this.length < 0
|
|
35
|
+
}
|
|
36
|
+
get length() {
|
|
37
|
+
return this.promises.length - this.resolvers.length;
|
|
38
|
+
}
|
|
39
|
+
sleep(ms) {
|
|
40
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
41
|
+
}
|
|
42
|
+
async start() {
|
|
43
|
+
// TODO: This is experimental
|
|
44
|
+
const delayBetweenJobs = 2000;
|
|
45
|
+
|
|
46
|
+
for await (const job of this) {
|
|
47
|
+
console.log("Executing job...");
|
|
48
|
+
job();
|
|
49
|
+
if (delayBetweenJobs) {
|
|
50
|
+
console.log("Waiting for next job1...");
|
|
51
|
+
await this.sleep(delayBetweenJobs);
|
|
52
|
+
console.log("Waiting for next job2...");
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
[Symbol.asyncIterator]() {
|
|
57
|
+
// Todo: Use AsyncIterator.from()
|
|
58
|
+
return {
|
|
59
|
+
next: () => this.dequeue().then(value => ({ done: false, value })),
|
|
60
|
+
[Symbol.asyncIterator]() {
|
|
61
|
+
return this;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// export default class {
|
|
68
|
+
// constructor() {
|
|
69
|
+
// this.jobQueue = [];
|
|
70
|
+
// this.timerHandle = null;
|
|
71
|
+
// }
|
|
72
|
+
// // static get csrfElement() {
|
|
73
|
+
// // return document.querySelector(`meta[name="csrf-token"]`);
|
|
74
|
+
// // }
|
|
75
|
+
|
|
76
|
+
// // static getCsrf() {
|
|
77
|
+
// // return this.csrfElement.getAttribute("content");
|
|
78
|
+
// // }
|
|
79
|
+
|
|
80
|
+
// // static setCsrf(value) {
|
|
81
|
+
// // return this.csrfElement.setAttribute("content", value);
|
|
82
|
+
// // }
|
|
83
|
+
|
|
84
|
+
// start(interval) {
|
|
85
|
+
// this.timerHandle = setInterval(() => {
|
|
86
|
+
// console.log("DEQUQE1");
|
|
87
|
+
// const oldestJob = this.jobQueue.shift();
|
|
88
|
+
// if (oldestJob) {
|
|
89
|
+
// console.log("DEQUQE2");
|
|
90
|
+
// oldestJob();
|
|
91
|
+
// }
|
|
92
|
+
// }, interval);
|
|
93
|
+
// }
|
|
94
|
+
|
|
95
|
+
// stop() {
|
|
96
|
+
// clearInterval(this.timerHandle);
|
|
97
|
+
// }
|
|
98
|
+
|
|
99
|
+
// enqueue(job) {
|
|
100
|
+
// this.jobQueue.push(job);
|
|
101
|
+
// }
|
|
102
|
+
// }
|
package/utils/settings.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import config from '../package.json';
|
|
2
|
+
|
|
1
3
|
class MutableSettings {
|
|
2
4
|
constructor() {
|
|
3
5
|
this.reactive = true;
|
|
@@ -6,10 +8,6 @@ class MutableSettings {
|
|
|
6
8
|
this.errorHandler = err => {
|
|
7
9
|
console.error(err.message);
|
|
8
10
|
};
|
|
9
|
-
this.headerAugmenter = (_url, _method) => {
|
|
10
|
-
// Set a custom augmenter to add custom HTTP headers.
|
|
11
|
-
return {};
|
|
12
|
-
};
|
|
13
11
|
}
|
|
14
12
|
}
|
|
15
13
|
const settings = new MutableSettings();
|
|
@@ -28,16 +26,12 @@ export default class ImmutableSettings {
|
|
|
28
26
|
return settings.errorHandler;
|
|
29
27
|
}
|
|
30
28
|
|
|
31
|
-
static get headerAugmenter() {
|
|
32
|
-
return settings.headerAugmenter;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
29
|
static get env() {
|
|
36
30
|
return process.env.NODE_ENV;
|
|
37
31
|
}
|
|
38
32
|
|
|
39
33
|
static get appVersion() {
|
|
40
|
-
return
|
|
34
|
+
return config.version;
|
|
41
35
|
}
|
|
42
36
|
|
|
43
37
|
// static get build() {
|