glib-web 0.5.77
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/.eslintrc.js +37 -0
- package/LICENSE +201 -0
- package/README.md +33 -0
- package/action.js +167 -0
- package/actions/analytics/logEvent.js +26 -0
- package/actions/auth/creditCard.js +29 -0
- package/actions/auth/restart.js +5 -0
- package/actions/auth/saveCsrfToken.js +12 -0
- package/actions/cables/push.js +38 -0
- package/actions/dialogs/alert.js +15 -0
- package/actions/dialogs/close.js +7 -0
- package/actions/dialogs/notification.js +14 -0
- package/actions/dialogs/oauth.js +6 -0
- package/actions/dialogs/open.js +7 -0
- package/actions/dialogs/options.js +5 -0
- package/actions/dialogs/show.js +5 -0
- package/actions/forms/submit.js +15 -0
- package/actions/http/delete.js +7 -0
- package/actions/http/patch.js +7 -0
- package/actions/http/post.js +7 -0
- package/actions/http/put.js +7 -0
- package/actions/panels/scrollTo.js +18 -0
- package/actions/panels/scrollToBottom.js +11 -0
- package/actions/runMultiple.js +11 -0
- package/actions/sheets/select.js +5 -0
- package/actions/snackbars/alert.js +15 -0
- package/actions/snackbars/select.js +5 -0
- package/actions/timeouts/set.js +20 -0
- package/actions/windows/close.js +13 -0
- package/actions/windows/closeAll.js +16 -0
- package/actions/windows/closeWithReload.js +18 -0
- package/actions/windows/open.js +5 -0
- package/actions/windows/openWeb.js +5 -0
- package/actions/windows/refreshState.js +5 -0
- package/actions/windows/reload.js +24 -0
- package/actions/ws/push.js +35 -0
- package/app.vue +180 -0
- package/components/_button.vue +101 -0
- package/components/_dropdownMenu.vue +76 -0
- package/components/_icon.vue +50 -0
- package/components/_message.vue +25 -0
- package/components/avatar.vue +16 -0
- package/components/banners/alert.vue +49 -0
- package/components/banners/select.vue +82 -0
- package/components/button.vue +13 -0
- package/components/calendar.vue +105 -0
- package/components/charts/column.vue +26 -0
- package/components/charts/line.vue +61 -0
- package/components/chip.vue +24 -0
- package/components/component.vue +222 -0
- package/components/datetime.vue +54 -0
- package/components/fab.vue +33 -0
- package/components/fields/_patternText.vue +61 -0
- package/components/fields/_select.vue +86 -0
- package/components/fields/autocomplete.vue +73 -0
- package/components/fields/check.vue +104 -0
- package/components/fields/checkGroup.vue +51 -0
- package/components/fields/country/countries.js +251 -0
- package/components/fields/country/field.vue +81 -0
- package/components/fields/country/regions.js +12 -0
- package/components/fields/creditCard.vue +105 -0
- package/components/fields/date.vue +24 -0
- package/components/fields/datetime.vue +49 -0
- package/components/fields/dynamicGroup.vue +106 -0
- package/components/fields/dynamicSelect.vue +173 -0
- package/components/fields/file.vue +166 -0
- package/components/fields/googlePlace.vue +158 -0
- package/components/fields/hidden.vue +18 -0
- package/components/fields/location.vue +223 -0
- package/components/fields/newRichText.vue +191 -0
- package/components/fields/phone/countries.js +315 -0
- package/components/fields/phone/field.vue +348 -0
- package/components/fields/phone/sprite.css +1071 -0
- package/components/fields/radio.vue +64 -0
- package/components/fields/radioGroup.vue +93 -0
- package/components/fields/rating.vue +26 -0
- package/components/fields/richText.vue +172 -0
- package/components/fields/select.vue +17 -0
- package/components/fields/stripe/stripeFields.vue +93 -0
- package/components/fields/stripe/stripeIndividualFields.vue +207 -0
- package/components/fields/stripeExternalAccount.vue +135 -0
- package/components/fields/stripeToken.vue +59 -0
- package/components/fields/submit.vue +23 -0
- package/components/fields/text.vue +144 -0
- package/components/fields/textarea.vue +59 -0
- package/components/fields/timeZone.vue +22 -0
- package/components/fields/timer.vue +83 -0
- package/components/h1.vue +28 -0
- package/components/h2.vue +20 -0
- package/components/h3.vue +22 -0
- package/components/h4.vue +20 -0
- package/components/h5.vue +20 -0
- package/components/h6.vue +20 -0
- package/components/hr.vue +13 -0
- package/components/html.vue +13 -0
- package/components/icon.vue +25 -0
- package/components/image.vue +87 -0
- package/components/label.vue +62 -0
- package/components/map.vue +206 -0
- package/components/markdown.vue +52 -0
- package/components/mixins/events.js +178 -0
- package/components/mixins/generic.js +58 -0
- package/components/mixins/list/autoload.js +144 -0
- package/components/mixins/longClick.js +56 -0
- package/components/mixins/scrolling.js +35 -0
- package/components/mixins/styles.js +221 -0
- package/components/mixins/table/autoload.js +131 -0
- package/components/mixins/table/export.js +52 -0
- package/components/mixins/table/import.js +106 -0
- package/components/mixins/text.js +20 -0
- package/components/mixins/ws/actionCable.js +48 -0
- package/components/mixins/ws/phoenixSocket.js +117 -0
- package/components/p.vue +36 -0
- package/components/panels/carousel.vue +55 -0
- package/components/panels/column.vue +117 -0
- package/components/panels/custom.vue +52 -0
- package/components/panels/flow.vue +81 -0
- package/components/panels/form.vue +126 -0
- package/components/panels/horizontal.vue +73 -0
- package/components/panels/list.vue +241 -0
- package/components/panels/responsive.vue +88 -0
- package/components/panels/scroll.vue +68 -0
- package/components/panels/split.vue +52 -0
- package/components/panels/table.vue +234 -0
- package/components/panels/ul.vue +34 -0
- package/components/panels/vertical.vue +71 -0
- package/components/panels/web.vue +11 -0
- package/components/spacer.vue +11 -0
- package/components/switch.vue +42 -0
- package/components/tabBar.vue +44 -0
- package/extensions/array.js +20 -0
- package/extensions/string.js +21 -0
- package/index.js +195 -0
- package/keys.js +12 -0
- package/nav/appbar.vue +117 -0
- package/nav/content.vue +40 -0
- package/nav/dialog.vue +127 -0
- package/nav/drawer.vue +88 -0
- package/nav/drawerButton.vue +28 -0
- package/nav/drawerLabel.vue +21 -0
- package/nav/sheet.vue +57 -0
- package/nav/snackbar.vue +72 -0
- package/package.json +42 -0
- package/settings.json.example +21 -0
- package/static/plugins/alignment/alignment.js +76 -0
- package/static/plugins/alignment/alignment.min.js +1 -0
- package/static/plugins/beyondgrammar/beyondgrammar.js +46 -0
- package/static/plugins/beyondgrammar/beyondgrammar.min.js +1 -0
- package/static/plugins/blockcode/blockcode.js +110 -0
- package/static/plugins/blockcode/blockcode.min.js +1 -0
- package/static/plugins/clips/clips.js +44 -0
- package/static/plugins/clips/clips.min.js +1 -0
- package/static/plugins/counter/counter.js +60 -0
- package/static/plugins/counter/counter.min.js +1 -0
- package/static/plugins/definedlinks/definedlinks.js +64 -0
- package/static/plugins/definedlinks/definedlinks.min.js +1 -0
- package/static/plugins/handle/handle.js +173 -0
- package/static/plugins/handle/handle.min.js +1 -0
- package/static/plugins/icons/icons.js +72 -0
- package/static/plugins/icons/icons.min.js +1 -0
- package/static/plugins/imageposition/imageposition.js +85 -0
- package/static/plugins/imageposition/imageposition.min.js +1 -0
- package/static/plugins/inlineformat/inlineformat.js +85 -0
- package/static/plugins/inlineformat/inlineformat.min.js +1 -0
- package/static/plugins/removeformat/removeformat.js +28 -0
- package/static/plugins/removeformat/removeformat.min.js +1 -0
- package/static/plugins/selector/selector.js +96 -0
- package/static/plugins/selector/selector.min.js +1 -0
- package/static/plugins/specialchars/specialchars.js +63 -0
- package/static/plugins/specialchars/specialchars.min.js +1 -0
- package/static/plugins/textdirection/textdirection.js +55 -0
- package/static/plugins/textdirection/textdirection.min.js +1 -0
- package/static/plugins/textexpander/textexpander.js +46 -0
- package/static/plugins/textexpander/textexpander.min.js +1 -0
- package/static/plugins/underline/underline.js +27 -0
- package/static/plugins/underline/underline.min.js +1 -0
- package/static/redactorx.css +1344 -0
- package/static/redactorx.js +14254 -0
- package/static/redactorx.min.css +1 -0
- package/static/redactorx.min.js +1 -0
- package/static/redactorx.usm.min.js +2 -0
- package/styles/test.sass +3 -0
- package/styles/test.scss +5 -0
- package/templates/_menu.vue +38 -0
- package/templates/comment.vue +202 -0
- package/templates/featured.vue +32 -0
- package/templates/thumbnail.vue +138 -0
- package/templates/unsupported.vue +12 -0
- package/utils/app.js +14 -0
- package/utils/dom.js +13 -0
- package/utils/form.js +34 -0
- package/utils/format.js +14 -0
- package/utils/hash.js +29 -0
- package/utils/helper.js +44 -0
- package/utils/history.js +70 -0
- package/utils/http.js +209 -0
- package/utils/launch.js +135 -0
- package/utils/private/ws.js +22 -0
- package/utils/public.js +23 -0
- package/utils/settings.js +48 -0
- package/utils/storage.js +9 -0
- package/utils/type.js +69 -0
- package/utils/uploader.js +121 -0
- package/utils/url.js +132 -0
package/utils/http.js
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import Type from "./type";
|
|
2
|
+
import Action from "../action";
|
|
3
|
+
|
|
4
|
+
let loading = false;
|
|
5
|
+
|
|
6
|
+
class HttpRequest {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.controller = new AbortController();
|
|
9
|
+
this.canceled = false;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
cancel() {
|
|
13
|
+
this.canceled = true;
|
|
14
|
+
this.controller.abort();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default class {
|
|
19
|
+
static _extractFormData(properties, needCsrfToken) {
|
|
20
|
+
// if (properties["formDataEncoded"]) {
|
|
21
|
+
// return properties["formData"];
|
|
22
|
+
// }
|
|
23
|
+
|
|
24
|
+
const data = properties.formData;
|
|
25
|
+
if (data instanceof FormData) {
|
|
26
|
+
return data;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const formData = new FormData();
|
|
30
|
+
var params = data || {};
|
|
31
|
+
for (const key in params) {
|
|
32
|
+
formData.append(key, params[key]);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (needCsrfToken && !Type.isString(params["authenticity_token"])) {
|
|
36
|
+
formData.append("authenticity_token", Utils.dom.getCsrf());
|
|
37
|
+
}
|
|
38
|
+
return formData;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static load(properties, target, component) {
|
|
42
|
+
const url = new URL(properties["url"]);
|
|
43
|
+
const domainMatched = window.location.hostname == url.hostname;
|
|
44
|
+
if (Utils.settings.reactive && domainMatched) {
|
|
45
|
+
const currentUrl = window.location.href;
|
|
46
|
+
const htmlUrl = Utils.url.htmlUrl(properties["url"]);
|
|
47
|
+
|
|
48
|
+
Utils.http.execute(properties, "GET", component, (data, response) => {
|
|
49
|
+
if (htmlUrl !== currentUrl) {
|
|
50
|
+
const redirectUrl = Utils.url.htmlUrl(response.url);
|
|
51
|
+
Utils.history.pushPage(data, redirectUrl);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
this.forceComponentUpdate(() => {
|
|
55
|
+
Utils.history.resetScroll();
|
|
56
|
+
window.vueApp.page = data;
|
|
57
|
+
Action.execute(properties["onOpen"], target, component);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
} else {
|
|
61
|
+
window.location = Utils.url.htmlUrl(properties["url"]);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
static analyticsHeaders(component) {
|
|
66
|
+
const pageAnalytics =
|
|
67
|
+
window.vueApp.temp.analytics || window.vueApp.page.analytics || {};
|
|
68
|
+
const featureAnalytics = pageAnalytics.feature;
|
|
69
|
+
|
|
70
|
+
const headers = {};
|
|
71
|
+
if (featureAnalytics) {
|
|
72
|
+
const componentAnalytics = component.spec.analytics || {};
|
|
73
|
+
if (componentAnalytics.disabled) {
|
|
74
|
+
return headers;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
Utils.type.ifString(
|
|
78
|
+
componentAnalytics.group || featureAnalytics.group,
|
|
79
|
+
value => (headers["GApp-Analytics-Referer-Group"] = value)
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
Utils.type.ifString(
|
|
83
|
+
componentAnalytics.action || featureAnalytics.action,
|
|
84
|
+
value => (headers["GApp-Analytics-Referer-Action"] = value)
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
Utils.type.ifString(
|
|
88
|
+
componentAnalytics.segment || featureAnalytics.segment,
|
|
89
|
+
value => (headers["GApp-Analytics-Referer-Segment"] = value)
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
Utils.type.ifString(
|
|
93
|
+
componentAnalytics.placement,
|
|
94
|
+
value => (headers["GApp-Analytics-Referer-Placement"] = value)
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
return headers;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
static reload(properties, component) {
|
|
101
|
+
const currentUrl = window.location.href;
|
|
102
|
+
const data = {
|
|
103
|
+
url: properties.url || currentUrl
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
Utils.http.execute(data, "GET", component, (page, response) => {
|
|
107
|
+
Utils.http.forceComponentUpdate(() => {
|
|
108
|
+
window.vueApp.page = page;
|
|
109
|
+
const redirectUrl = Utils.url.htmlUrl(response.url);
|
|
110
|
+
Utils.history.updatePage(redirectUrl);
|
|
111
|
+
|
|
112
|
+
GLib.action.execute(properties["onReload"], null, component);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
static execute(properties, methodName, component, jsonHandler) {
|
|
118
|
+
this.startIndicator(component);
|
|
119
|
+
|
|
120
|
+
// `fetch()` only supports uppercase
|
|
121
|
+
const method = methodName.toUpperCase();
|
|
122
|
+
let url = Utils.url.jsonUrl(properties["url"]);
|
|
123
|
+
let body = this._extractFormData(properties, method !== "GET");
|
|
124
|
+
if (method === "GET") {
|
|
125
|
+
url = Utils.url.appendParams(url, body);
|
|
126
|
+
body = null;
|
|
127
|
+
}
|
|
128
|
+
console.log(`${method} ${url}`);
|
|
129
|
+
|
|
130
|
+
const request = new HttpRequest();
|
|
131
|
+
let response = null;
|
|
132
|
+
const vm = this;
|
|
133
|
+
|
|
134
|
+
const analyticsHeaders = this.analyticsHeaders(component);
|
|
135
|
+
|
|
136
|
+
fetch(url, {
|
|
137
|
+
method: method,
|
|
138
|
+
body: body,
|
|
139
|
+
headers: Object.assign({ Accept: "text/html" }, analyticsHeaders),
|
|
140
|
+
// Make sure to pass cookies for same origin URLs.
|
|
141
|
+
// Needed for some browsers, e.g. Edge and Android's native.
|
|
142
|
+
credentials: "same-origin",
|
|
143
|
+
signal: request.controller.signal
|
|
144
|
+
})
|
|
145
|
+
.then(res => {
|
|
146
|
+
vm.stopIndicator(component);
|
|
147
|
+
|
|
148
|
+
if (res.status >= 500) {
|
|
149
|
+
throw "Server error";
|
|
150
|
+
} else if (res.status >= 400) {
|
|
151
|
+
throw "Not accessible";
|
|
152
|
+
} else {
|
|
153
|
+
response = res;
|
|
154
|
+
return res.json();
|
|
155
|
+
}
|
|
156
|
+
})
|
|
157
|
+
.then(data => {
|
|
158
|
+
console.debug("Success", data);
|
|
159
|
+
jsonHandler(data, response);
|
|
160
|
+
})
|
|
161
|
+
.catch(error => {
|
|
162
|
+
vm.stopIndicator(component);
|
|
163
|
+
if (!request.canceled) {
|
|
164
|
+
console.error("Error:", error);
|
|
165
|
+
Utils.launch.snackbar.error(error);
|
|
166
|
+
} else {
|
|
167
|
+
console.info("Canceled");
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
return request;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
static startIndicator(component) {
|
|
175
|
+
this._showIndicator();
|
|
176
|
+
component.$data._isBusy = true;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
static stopIndicator(component) {
|
|
180
|
+
this._hideIndicator();
|
|
181
|
+
component.$data._isBusy = false;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
static _showIndicator() {
|
|
185
|
+
loading = true;
|
|
186
|
+
setTimeout(() => {
|
|
187
|
+
if (loading) {
|
|
188
|
+
loading = false;
|
|
189
|
+
window.vueApp.indicator = true;
|
|
190
|
+
}
|
|
191
|
+
}, 200);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
static _hideIndicator() {
|
|
195
|
+
loading = false;
|
|
196
|
+
window.vueApp.indicator = false;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// See generic.js
|
|
200
|
+
static forceComponentUpdate(handler) {
|
|
201
|
+
window.vueApp.isStale = true;
|
|
202
|
+
|
|
203
|
+
// Queue the execution so the first isStale has time to resets state before handler gets executed
|
|
204
|
+
setTimeout(() => {
|
|
205
|
+
handler();
|
|
206
|
+
window.vueApp.isStale = false;
|
|
207
|
+
}, 0);
|
|
208
|
+
}
|
|
209
|
+
}
|
package/utils/launch.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import Vue from "vue";
|
|
2
|
+
import Dialog from "../nav/dialog";
|
|
3
|
+
import Sheet from "../nav/sheet";
|
|
4
|
+
import Snackbar from "../nav/snackbar";
|
|
5
|
+
import Vuetify from "vuetify";
|
|
6
|
+
|
|
7
|
+
export default class {
|
|
8
|
+
static dialog(properties, target) {
|
|
9
|
+
if (!this.stack) {
|
|
10
|
+
this.stack = [];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// https://css-tricks.com/creating-vue-js-component-instances-programmatically/
|
|
14
|
+
const DialogClass = Vue.extend(Dialog);
|
|
15
|
+
const instance = new DialogClass({
|
|
16
|
+
vuetify: new Vuetify({
|
|
17
|
+
theme: {
|
|
18
|
+
themes: Utils.settings.themes
|
|
19
|
+
}
|
|
20
|
+
}),
|
|
21
|
+
propsData: {
|
|
22
|
+
spec: properties,
|
|
23
|
+
stack: this.stack,
|
|
24
|
+
target: target,
|
|
25
|
+
vueApp: window.vueApp
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
// instance.stack = this.stack;
|
|
29
|
+
|
|
30
|
+
const placeholder = document.body.appendChild(
|
|
31
|
+
document.createElement("div")
|
|
32
|
+
);
|
|
33
|
+
instance.$mount(placeholder);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
static closeDialog(properties, target, component) {
|
|
37
|
+
if (!this.stack) {
|
|
38
|
+
this.stack = [];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
Utils.type.ifObject(this.stack.last(), dialog => {
|
|
42
|
+
dialog.close();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
Utils.type.ifObject(properties["onClose"], it => {
|
|
46
|
+
Action.execute(it, target, component);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
static get sheet() {
|
|
51
|
+
return LaunchSheet;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
static get snackbar() {
|
|
55
|
+
return LaunchSnackbar;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
static alert(message, target) {
|
|
59
|
+
const properties = {
|
|
60
|
+
message: message
|
|
61
|
+
};
|
|
62
|
+
const spec = Object.assign({}, properties, {
|
|
63
|
+
buttons: [
|
|
64
|
+
{
|
|
65
|
+
text: "OK",
|
|
66
|
+
onClick: properties.onClose
|
|
67
|
+
}
|
|
68
|
+
]
|
|
69
|
+
});
|
|
70
|
+
this.dialog(spec, target);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
class LaunchSheet {
|
|
75
|
+
static open(properties) {
|
|
76
|
+
const SheetClass = Vue.extend(Sheet);
|
|
77
|
+
const instance = new SheetClass({
|
|
78
|
+
vuetify: new Vuetify({
|
|
79
|
+
theme: {
|
|
80
|
+
themes: Utils.settings.themes
|
|
81
|
+
}
|
|
82
|
+
}),
|
|
83
|
+
propsData: { spec: properties }
|
|
84
|
+
});
|
|
85
|
+
const placeholder = document.body.appendChild(
|
|
86
|
+
document.createElement("div")
|
|
87
|
+
);
|
|
88
|
+
instance.$mount(placeholder);
|
|
89
|
+
// instance.show = true
|
|
90
|
+
return instance;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
static confirm(properties, onConfirm) {
|
|
94
|
+
const spec = Object.assign({}, properties, {
|
|
95
|
+
buttons: [
|
|
96
|
+
{
|
|
97
|
+
text: "Confirm",
|
|
98
|
+
onClickFunction: onConfirm
|
|
99
|
+
}
|
|
100
|
+
]
|
|
101
|
+
});
|
|
102
|
+
this.open(spec);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
static alert(message, buttons) {
|
|
106
|
+
const spec = { message: message, buttons: buttons };
|
|
107
|
+
this.open(spec);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
class LaunchSnackbar {
|
|
112
|
+
static open(properties) {
|
|
113
|
+
const SnackbarClass = Vue.extend(Snackbar);
|
|
114
|
+
const instance = new SnackbarClass({
|
|
115
|
+
vuetify: window.vueApp.vuetify,
|
|
116
|
+
propsData: { spec: properties, vueApp: window.vueApp }
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
const placeholder = document.body.appendChild(
|
|
120
|
+
document.createElement("div")
|
|
121
|
+
);
|
|
122
|
+
instance.$mount(placeholder);
|
|
123
|
+
instance.show = true;
|
|
124
|
+
return instance;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
static error(message) {
|
|
128
|
+
this.open({ message: message, styleClasses: ["error"] });
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
static indicator(message) {
|
|
132
|
+
const instance = this.open({ message: message, timeout: -1 });
|
|
133
|
+
instance.indicator = true;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export default class {
|
|
2
|
+
static handleResponse(payload, component) {
|
|
3
|
+
if (!Utils.type.isObject(payload)) {
|
|
4
|
+
return;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const ws = window.vueApp.webSocket;
|
|
8
|
+
Utils.type.ifObject(payload.wsHeader, header => {
|
|
9
|
+
Object.assign(ws.header, header);
|
|
10
|
+
console.log("New header: ", ws.header);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const actionName = payload.action;
|
|
14
|
+
if (actionName.startsWith("component/")) {
|
|
15
|
+
const methodName = actionName.replace(/^component\//, "");
|
|
16
|
+
console.log(`Executing component action: ${methodName}`);
|
|
17
|
+
component[`action_${methodName}`](payload);
|
|
18
|
+
} else {
|
|
19
|
+
GLib.action.execute(payload, null, component);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
package/utils/public.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import Action from "../action";
|
|
2
|
+
import Url from "./url";
|
|
3
|
+
import Http from "./http";
|
|
4
|
+
import Type from "./type";
|
|
5
|
+
import Form from "./form";
|
|
6
|
+
|
|
7
|
+
export default class {
|
|
8
|
+
static get action() {
|
|
9
|
+
return Action;
|
|
10
|
+
}
|
|
11
|
+
static get url() {
|
|
12
|
+
return Url;
|
|
13
|
+
}
|
|
14
|
+
static get http() {
|
|
15
|
+
return Http;
|
|
16
|
+
}
|
|
17
|
+
static get type() {
|
|
18
|
+
return Type;
|
|
19
|
+
}
|
|
20
|
+
static get form() {
|
|
21
|
+
return Form;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
class MutableSettings {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.reactive = true;
|
|
4
|
+
this.themes = {};
|
|
5
|
+
this.gtagId = null;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
const settings = new MutableSettings();
|
|
9
|
+
export { settings };
|
|
10
|
+
|
|
11
|
+
export default class ImmutableSettings {
|
|
12
|
+
static get reactive() {
|
|
13
|
+
return settings.reactive;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
static get themes() {
|
|
17
|
+
return settings.themes;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static get env() {
|
|
21
|
+
return process.env.NODE_ENV;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static get appVersion() {
|
|
25
|
+
return require("../package.json").version;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// static get build() {
|
|
29
|
+
// switch (this.env) {
|
|
30
|
+
// case 'development':
|
|
31
|
+
// return new DevBuild()
|
|
32
|
+
// default:
|
|
33
|
+
// return new ProdBuild()
|
|
34
|
+
// }
|
|
35
|
+
// }
|
|
36
|
+
|
|
37
|
+
static get assetCdn() {
|
|
38
|
+
return `${this.build.assetDomain}/${this.appVersion}`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static get apiHost() {
|
|
42
|
+
return this.build.apiDomain;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
static get isDev() {
|
|
46
|
+
return this.env == "development";
|
|
47
|
+
}
|
|
48
|
+
}
|
package/utils/storage.js
ADDED
package/utils/type.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export default class {
|
|
2
|
+
static isObject(obj) {
|
|
3
|
+
return typeof obj === "object" && obj !== null;
|
|
4
|
+
}
|
|
5
|
+
static isString(obj) {
|
|
6
|
+
return typeof obj === "string";
|
|
7
|
+
}
|
|
8
|
+
static isNumber(obj) {
|
|
9
|
+
return typeof obj === "number" && !isNaN(obj);
|
|
10
|
+
}
|
|
11
|
+
static isBoolean(obj) {
|
|
12
|
+
return typeof obj === "boolean";
|
|
13
|
+
}
|
|
14
|
+
static isArray(obj) {
|
|
15
|
+
return this.isObject(obj) && Array.isArray(obj);
|
|
16
|
+
}
|
|
17
|
+
static isFunction(obj) {
|
|
18
|
+
return typeof obj === "function";
|
|
19
|
+
}
|
|
20
|
+
static isNotNull(obj) {
|
|
21
|
+
return typeof obj !== "undefined" && obj !== null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static ifObject(obj, ifCommand, elseCommand) {
|
|
25
|
+
if (this.isObject(obj)) {
|
|
26
|
+
ifCommand(obj);
|
|
27
|
+
} else if (elseCommand) {
|
|
28
|
+
elseCommand();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
static ifString(obj, command) {
|
|
32
|
+
if (this.isString(obj)) {
|
|
33
|
+
command(obj);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
static ifNumber(obj, command) {
|
|
37
|
+
if (this.isNumber(obj)) {
|
|
38
|
+
command(obj);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
static ifBoolean(obj, command) {
|
|
42
|
+
if (this.isBoolean(obj)) {
|
|
43
|
+
command(obj);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
static ifArray(obj, command) {
|
|
47
|
+
if (this.isArray(obj)) {
|
|
48
|
+
command(obj);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
static ifFunction(obj, command) {
|
|
52
|
+
if (this.isFunction(obj)) {
|
|
53
|
+
command(obj);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
static ifNotNull(obj, command) {
|
|
57
|
+
if (this.isNotNull(obj)) {
|
|
58
|
+
command(obj);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
static floatValue(obj) {
|
|
63
|
+
return this.float(obj) || 0;
|
|
64
|
+
}
|
|
65
|
+
static float(obj) {
|
|
66
|
+
const val = parseFloat(obj);
|
|
67
|
+
return isNaN(val) ? null : val;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { DirectUpload } from "@rails/activestorage";
|
|
2
|
+
import Type from "../utils/type";
|
|
3
|
+
|
|
4
|
+
const MB_SIZE = 1000;
|
|
5
|
+
|
|
6
|
+
export default class Uploader {
|
|
7
|
+
// constructor(input, file, url) {
|
|
8
|
+
// this.input = input
|
|
9
|
+
// this.file = file
|
|
10
|
+
// this.url = url
|
|
11
|
+
// this.upload = new DirectUpload(this.file, this.url, this)
|
|
12
|
+
// }
|
|
13
|
+
|
|
14
|
+
constructor(file, url, progress) {
|
|
15
|
+
this.file = file;
|
|
16
|
+
this.url = url;
|
|
17
|
+
this.progress = progress;
|
|
18
|
+
this.upload = new DirectUpload(this.file, this.url, this);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
start(callback) {
|
|
22
|
+
this.progress.value = 0;
|
|
23
|
+
// this.dispatch("start")
|
|
24
|
+
this.upload.create((error, blob) => callback(error, blob));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// dispatchEvent(element, type, eventInit = {}) {
|
|
28
|
+
// const { disabled } = element
|
|
29
|
+
// const { bubbles, cancelable, detail } = eventInit
|
|
30
|
+
// const event = document.createEvent("Event")
|
|
31
|
+
|
|
32
|
+
// event.initEvent(type, bubbles || true, cancelable || true)
|
|
33
|
+
// event.detail = detail || {}
|
|
34
|
+
|
|
35
|
+
// try {
|
|
36
|
+
// element.disabled = false
|
|
37
|
+
// element.dispatchEvent(event)
|
|
38
|
+
// } finally {
|
|
39
|
+
// element.disabled = disabled
|
|
40
|
+
// }
|
|
41
|
+
|
|
42
|
+
// return event
|
|
43
|
+
// }
|
|
44
|
+
|
|
45
|
+
// dispatch(name, detail = {}) {
|
|
46
|
+
// detail.file = this.file
|
|
47
|
+
// return this.dispatchEvent(this.input, `direct-upload:${name}`, { detail })
|
|
48
|
+
// }
|
|
49
|
+
|
|
50
|
+
// Called by DirectUpload
|
|
51
|
+
directUploadWillStoreFileWithXHR(request) {
|
|
52
|
+
request.upload.addEventListener("progress", event =>
|
|
53
|
+
this.directUploadDidProgress(event)
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
directUploadDidProgress(event) {
|
|
58
|
+
// const progress = event.loaded / event.total * 100
|
|
59
|
+
// if (progress)
|
|
60
|
+
// this.dispatch("progress", { progress })
|
|
61
|
+
this.progress.value = (event.loaded / event.total) * 100;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
validateFile(spec) {
|
|
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
|
+
}
|
|
89
|
+
|
|
90
|
+
validateFileAccordingToRules(spec) {
|
|
91
|
+
if (Type.isObject(spec)) {
|
|
92
|
+
let mimeType;
|
|
93
|
+
switch (spec.fileType) {
|
|
94
|
+
case "image/*": // Legacy
|
|
95
|
+
case "image":
|
|
96
|
+
mimeType = "image/*";
|
|
97
|
+
break;
|
|
98
|
+
case "pdf":
|
|
99
|
+
mimeType = "application/pdf";
|
|
100
|
+
break;
|
|
101
|
+
default:
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const acceptsRegex = new RegExp(mimeType);
|
|
106
|
+
if (!acceptsRegex.test(this.file.type)) {
|
|
107
|
+
alert(spec.fileTypeErrorText || "Invalid file type");
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (spec.maxFileSize) {
|
|
112
|
+
if (this.file.size > spec.maxFileSize * MB_SIZE) {
|
|
113
|
+
alert(spec.maxFileSizeErrorText || "File too big");
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
}
|