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/components/markdown.vue
CHANGED
|
@@ -2,35 +2,59 @@
|
|
|
2
2
|
<div :style="genericStyles()" :class="$classes()">
|
|
3
3
|
<!-- eslint-disable-next-line vue/no-v-html -->
|
|
4
4
|
<span v-html="compiledText"></span>
|
|
5
|
-
<div
|
|
6
|
-
v-
|
|
7
|
-
|
|
8
|
-
>
|
|
9
|
-
<youtube :video-id="youtubeId" fit-parent></youtube>
|
|
5
|
+
<div class="flex w-100 justify-start" v-if="videoUrls">
|
|
6
|
+
<MultimediaVideo class="mr-2" v-for="videoUrl in videoUrls"
|
|
7
|
+
:spec="{ width: 360, height: 180, url: videoUrl, view: 'multimedia-video' }" />
|
|
10
8
|
</div>
|
|
11
9
|
</div>
|
|
12
10
|
</template>
|
|
13
11
|
|
|
14
12
|
<script>
|
|
13
|
+
import MultimediaVideo from '../components/multimedia/video.vue'
|
|
14
|
+
|
|
15
|
+
const extractUrl = (str, lower = false) => {
|
|
16
|
+
const regexp = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()'@:%_\+.~#?!&//=]*)/gi;
|
|
17
|
+
|
|
18
|
+
if (typeof str !== "string") {
|
|
19
|
+
throw new TypeError(
|
|
20
|
+
`The str argument should be a string, got ${typeof str}`
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (str) {
|
|
25
|
+
let urls = str.match(regexp);
|
|
26
|
+
if (urls) {
|
|
27
|
+
return lower ? urls.map((item) => item.toLowerCase()) : urls;
|
|
28
|
+
} else {
|
|
29
|
+
undefined;
|
|
30
|
+
}
|
|
31
|
+
} else {
|
|
32
|
+
undefined;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
15
36
|
export default {
|
|
37
|
+
components: {
|
|
38
|
+
MultimediaVideo
|
|
39
|
+
},
|
|
16
40
|
props: {
|
|
17
41
|
spec: { type: Object, required: true }
|
|
18
42
|
},
|
|
19
43
|
data() {
|
|
20
44
|
return {
|
|
21
|
-
|
|
45
|
+
videoUrls: ''
|
|
22
46
|
};
|
|
23
47
|
},
|
|
24
48
|
computed: {
|
|
25
49
|
compiledText() {
|
|
26
|
-
return Utils.format.markdown(this.spec.text);
|
|
50
|
+
return Utils.format.markdown(this.spec.text || '');
|
|
27
51
|
}
|
|
28
52
|
},
|
|
29
53
|
methods: {
|
|
30
54
|
$ready() {
|
|
31
55
|
if (this.spec.previewVideo) {
|
|
32
|
-
this.
|
|
33
|
-
console.
|
|
56
|
+
this.videoUrls = extractUrl(this.spec.text);
|
|
57
|
+
console.log("Detected url", this.videoUrls);
|
|
34
58
|
}
|
|
35
59
|
// Set all links to be openWeb or open in a new tab by default
|
|
36
60
|
if (!this.spec.openWeb) {
|
|
@@ -40,63 +64,61 @@ export default {
|
|
|
40
64
|
}
|
|
41
65
|
}
|
|
42
66
|
},
|
|
43
|
-
// From https://gist.github.com/takien/4077195
|
|
44
|
-
extractYoutubeId(url) {
|
|
45
|
-
var ID = "";
|
|
46
|
-
url = url
|
|
47
|
-
.replace(/(>|<)/gi, "")
|
|
48
|
-
.split(/(vi\/|v=|\/v\/|youtu\.be\/|\/embed\/)/);
|
|
49
|
-
if (url[2] !== undefined) {
|
|
50
|
-
ID = url[2].split(/[^0-9a-z_\-]/i);
|
|
51
|
-
ID = ID[0];
|
|
52
|
-
}
|
|
53
|
-
return ID;
|
|
54
|
-
}
|
|
55
67
|
}
|
|
56
68
|
};
|
|
57
69
|
</script>
|
|
58
70
|
|
|
59
71
|
<style lang="scss">
|
|
60
72
|
.views-markdown {
|
|
61
|
-
|
|
73
|
+
&>span> :last-child {
|
|
62
74
|
margin-bottom: 0;
|
|
63
75
|
}
|
|
76
|
+
|
|
64
77
|
pre {
|
|
65
78
|
background-color: #f0f0f0;
|
|
66
79
|
padding: 8px 10px;
|
|
67
80
|
|
|
68
|
-
|
|
81
|
+
&>code {
|
|
69
82
|
background-color: transparent;
|
|
70
83
|
padding: 0;
|
|
71
84
|
}
|
|
72
85
|
}
|
|
73
86
|
}
|
|
87
|
+
|
|
74
88
|
.line-clamp {
|
|
75
89
|
display: -webkit-box;
|
|
76
90
|
-webkit-box-orient: vertical;
|
|
77
91
|
overflow: hidden;
|
|
78
92
|
}
|
|
93
|
+
|
|
79
94
|
.line-clamp-1 {
|
|
80
95
|
-webkit-line-clamp: 1;
|
|
81
96
|
}
|
|
97
|
+
|
|
82
98
|
.line-clamp-2 {
|
|
83
99
|
-webkit-line-clamp: 2;
|
|
84
100
|
}
|
|
101
|
+
|
|
85
102
|
.line-clamp-3 {
|
|
86
103
|
-webkit-line-clamp: 3;
|
|
87
104
|
}
|
|
105
|
+
|
|
88
106
|
.line-clamp-4 {
|
|
89
107
|
-webkit-line-clamp: 4;
|
|
90
108
|
}
|
|
109
|
+
|
|
91
110
|
.line-clamp-5 {
|
|
92
111
|
-webkit-line-clamp: 5;
|
|
93
112
|
}
|
|
113
|
+
|
|
94
114
|
.line-clamp-6 {
|
|
95
115
|
-webkit-line-clamp: 6;
|
|
96
116
|
}
|
|
117
|
+
|
|
97
118
|
.line-clamp-7 {
|
|
98
119
|
-webkit-line-clamp: 7;
|
|
99
120
|
}
|
|
121
|
+
|
|
100
122
|
.line-clamp-8 {
|
|
101
123
|
-webkit-line-clamp: 8;
|
|
102
124
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import Action from "../../action";
|
|
2
2
|
import UrlUtils from "../../utils/url";
|
|
3
3
|
import TypeUtils from "../../utils/type";
|
|
4
|
+
import { vueApp } from "../../store";
|
|
4
5
|
|
|
5
6
|
export default {
|
|
6
7
|
data() {
|
|
@@ -10,7 +11,8 @@ export default {
|
|
|
10
11
|
// Submit button needs to be disabled when redirecting after form submission
|
|
11
12
|
_isBusy: false,
|
|
12
13
|
_events: [],
|
|
13
|
-
_typingTimer: null
|
|
14
|
+
_typingTimer: null,
|
|
15
|
+
_mountedUrl: null,
|
|
14
16
|
};
|
|
15
17
|
},
|
|
16
18
|
computed: {
|
|
@@ -33,11 +35,17 @@ export default {
|
|
|
33
35
|
this._ready();
|
|
34
36
|
this.$mounted();
|
|
35
37
|
},
|
|
36
|
-
|
|
38
|
+
beforeUpdate() {
|
|
39
|
+
if (vueApp.isStale) {
|
|
40
|
+
this._mountedUrl = null
|
|
41
|
+
}
|
|
42
|
+
|
|
37
43
|
if (!this._renderingTheSamePage()) {
|
|
38
44
|
this.$tearDown();
|
|
39
45
|
this._ready();
|
|
40
46
|
}
|
|
47
|
+
},
|
|
48
|
+
updated() {
|
|
41
49
|
// this._executeIfReady(true);
|
|
42
50
|
this.$updated();
|
|
43
51
|
},
|
|
@@ -51,18 +59,9 @@ export default {
|
|
|
51
59
|
// this._ready();
|
|
52
60
|
// }
|
|
53
61
|
// },
|
|
54
|
-
|
|
62
|
+
onDeactivated() {
|
|
55
63
|
this.$tearDown();
|
|
56
64
|
},
|
|
57
|
-
watch: {
|
|
58
|
-
// See Utils.http
|
|
59
|
-
"$root.vueApp.isStale": function(val, oldVal) {
|
|
60
|
-
if (val === true) {
|
|
61
|
-
// Make sure $ready() will be called in the next update
|
|
62
|
-
this._mountedUrl = null;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
},
|
|
66
65
|
methods: {
|
|
67
66
|
$href(spec) {
|
|
68
67
|
const properties = spec || this.spec;
|
|
@@ -77,7 +76,7 @@ export default {
|
|
|
77
76
|
}
|
|
78
77
|
return null;
|
|
79
78
|
},
|
|
80
|
-
$onClick: function(explicitEvent, spec) {
|
|
79
|
+
$onClick: function (explicitEvent, spec) {
|
|
81
80
|
const properties = spec || this.spec;
|
|
82
81
|
const e = explicitEvent || event;
|
|
83
82
|
|
|
@@ -92,7 +91,7 @@ export default {
|
|
|
92
91
|
Action.execute(properties.onClick, this);
|
|
93
92
|
}
|
|
94
93
|
},
|
|
95
|
-
$rel: function(spec) {
|
|
94
|
+
$rel: function (spec) {
|
|
96
95
|
const properties = spec || this.spec;
|
|
97
96
|
const onClick = properties.onClick;
|
|
98
97
|
if (TypeUtils.isObject(onClick)) {
|
|
@@ -109,12 +108,12 @@ export default {
|
|
|
109
108
|
$onLongPress() {
|
|
110
109
|
GLib.action.execute(this.spec.onLongPress, this);
|
|
111
110
|
},
|
|
112
|
-
$addViewportChangeListeners: function(handler) {
|
|
111
|
+
$addViewportChangeListeners: function (handler) {
|
|
113
112
|
window.addEventListener("load", handler);
|
|
114
113
|
window.addEventListener("resize", handler);
|
|
115
114
|
this._pageBody.addEventListener("scroll", handler);
|
|
116
115
|
},
|
|
117
|
-
$removeViewportChangeListeners: function(handler) {
|
|
116
|
+
$removeViewportChangeListeners: function (handler) {
|
|
118
117
|
window.removeEventListener("load", handler);
|
|
119
118
|
window.removeEventListener("resize", handler);
|
|
120
119
|
this._pageBody.removeEventListener("scroll", handler);
|
|
@@ -170,13 +169,13 @@ export default {
|
|
|
170
169
|
this.$update();
|
|
171
170
|
this.$forceUpdate();
|
|
172
171
|
|
|
173
|
-
// Execute on next tick to ensure that the
|
|
174
|
-
//
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
});
|
|
172
|
+
// Execute on next tick to ensure that the child has received the updated spec.
|
|
173
|
+
// $children is removed in vue 3
|
|
174
|
+
// this.$nextTick(() => {
|
|
175
|
+
// this.$children.find(child => {
|
|
176
|
+
// child.$recursiveUpdate();
|
|
177
|
+
// });
|
|
178
|
+
// });
|
|
180
179
|
},
|
|
181
180
|
// _recursiveUpdate() {
|
|
182
181
|
// this.$update();
|
|
@@ -222,8 +221,8 @@ export default {
|
|
|
222
221
|
};
|
|
223
222
|
const params = this.spec.paramNameForFormData
|
|
224
223
|
? {
|
|
225
|
-
|
|
226
|
-
|
|
224
|
+
[this.spec.paramNameForFormData]: formData
|
|
225
|
+
}
|
|
227
226
|
: formData;
|
|
228
227
|
const data = Object.assign({}, onChange, params);
|
|
229
228
|
GLib.action.execute(data, this);
|
|
@@ -1,14 +1,17 @@
|
|
|
1
|
+
import { vueApp } from "../../store";
|
|
2
|
+
|
|
1
3
|
export default {
|
|
2
4
|
methods: {
|
|
3
5
|
$closest(name) {
|
|
4
6
|
var parent = this.$parent;
|
|
5
7
|
while (parent != null) {
|
|
6
8
|
if (
|
|
7
|
-
Utils.type.isObject(parent.spec) &&
|
|
9
|
+
(Utils.type.isObject(parent.spec) || Utils.type.isObject(parent.formSpec)) &&
|
|
8
10
|
GLib.component.vueName(parent) == name
|
|
9
11
|
) {
|
|
10
12
|
return parent;
|
|
11
13
|
}
|
|
14
|
+
|
|
12
15
|
parent = parent.$parent;
|
|
13
16
|
}
|
|
14
17
|
},
|
|
@@ -50,11 +53,11 @@ export default {
|
|
|
50
53
|
return;
|
|
51
54
|
}
|
|
52
55
|
|
|
53
|
-
const ws =
|
|
56
|
+
const ws = vueApp.webSocket;
|
|
54
57
|
const channel = ws.channels[topicName];
|
|
55
58
|
|
|
56
59
|
if (!channel) {
|
|
57
|
-
console.
|
|
60
|
+
console.log(`Topic not ready: '${topicName}'`);
|
|
58
61
|
setTimeout(() => {
|
|
59
62
|
// Wait until $wsInitPhoenixSocket() has executed.
|
|
60
63
|
this.$wsSubscribeEvents(spec);
|
|
@@ -63,7 +66,7 @@ export default {
|
|
|
63
66
|
}
|
|
64
67
|
|
|
65
68
|
for (const eventName of events) {
|
|
66
|
-
console.
|
|
69
|
+
console.log(`Registering event '${eventName}'`);
|
|
67
70
|
channel.on(eventName, payload => {
|
|
68
71
|
console.debug(`Received '${eventName}' event`, payload);
|
|
69
72
|
Utils.ws.handleResponse(payload.onResponse, this);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const variants = ['outlined', 'plain', 'underlined', 'filled', 'solo', 'solo-inverted', 'solo-filled']
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
data: function () {
|
|
5
|
+
return {
|
|
6
|
+
variant: 'outlined'
|
|
7
|
+
}
|
|
8
|
+
},
|
|
9
|
+
methods: {
|
|
10
|
+
$ready() {
|
|
11
|
+
variants.forEach((value) => {
|
|
12
|
+
if (this.$classes().includes(value)) this.variant = value
|
|
13
|
+
})
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { vueApp } from "../../../store";
|
|
2
|
+
|
|
1
3
|
export default {
|
|
2
|
-
data: function() {
|
|
4
|
+
data: function () {
|
|
3
5
|
return {
|
|
4
6
|
topScrollHandler: null,
|
|
5
7
|
bottomScrollHandler: null,
|
|
@@ -17,7 +19,7 @@ export default {
|
|
|
17
19
|
// }
|
|
18
20
|
// },
|
|
19
21
|
methods: {
|
|
20
|
-
enableInfiniteScrollIfApplicable: function() {
|
|
22
|
+
enableInfiniteScrollIfApplicable: function () {
|
|
21
23
|
this.$removeViewportChangeListeners(this.topScrollHandler);
|
|
22
24
|
this.$removeViewportChangeListeners(this.bottomScrollHandler);
|
|
23
25
|
|
|
@@ -95,7 +97,7 @@ export default {
|
|
|
95
97
|
|
|
96
98
|
this._updateScrollAfterPrepending(previousFirstRowIndex);
|
|
97
99
|
}
|
|
98
|
-
Utils.history.updatePage();
|
|
100
|
+
Utils.history.updatePage(vueApp.page);
|
|
99
101
|
}
|
|
100
102
|
);
|
|
101
103
|
}
|
|
@@ -153,7 +155,7 @@ export default {
|
|
|
153
155
|
for (const section of response.sections) {
|
|
154
156
|
this.sections.push(section);
|
|
155
157
|
}
|
|
156
|
-
Utils.history.updatePage();
|
|
158
|
+
Utils.history.updatePage(vueApp.page);
|
|
157
159
|
}
|
|
158
160
|
);
|
|
159
161
|
}
|
|
@@ -176,7 +178,7 @@ export default {
|
|
|
176
178
|
{ url: nextPageUrl },
|
|
177
179
|
"GET",
|
|
178
180
|
vm,
|
|
179
|
-
function(response) {
|
|
181
|
+
function (response) {
|
|
180
182
|
for (const section of response.sections) {
|
|
181
183
|
vm.sections.push(section);
|
|
182
184
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
+
import { vueApp } from "../../store";
|
|
1
2
|
import Hash from "../../utils/hash";
|
|
2
|
-
import Vue from "vue";
|
|
3
|
-
import launch from "../../utils/launch";
|
|
4
3
|
|
|
5
|
-
|
|
4
|
+
import jsonLogic from 'json-logic-js';
|
|
6
5
|
|
|
7
6
|
// jsonLogic.add_operation("add_ms", function(a, b) {
|
|
8
7
|
// if (Utils.type.isString(a)) {
|
|
@@ -12,7 +11,7 @@ var jsonLogic = require("json-logic-js");
|
|
|
12
11
|
// return null;
|
|
13
12
|
// });
|
|
14
13
|
export default {
|
|
15
|
-
data: function() {
|
|
14
|
+
data: function () {
|
|
16
15
|
return {
|
|
17
16
|
_fieldModels: {},
|
|
18
17
|
fieldName: null,
|
|
@@ -36,17 +35,13 @@ export default {
|
|
|
36
35
|
}
|
|
37
36
|
},
|
|
38
37
|
watch: {
|
|
39
|
-
fieldModel: function(val, oldVal) {
|
|
38
|
+
fieldModel: function (val, oldVal) {
|
|
40
39
|
if (val === this.vuetifyEmptyString) {
|
|
41
40
|
val = "";
|
|
42
41
|
}
|
|
43
42
|
|
|
44
43
|
// Make the field property observable for dynamic showing/hiding
|
|
45
|
-
|
|
46
|
-
this.$data._fieldModels,
|
|
47
|
-
this.fieldName,
|
|
48
|
-
this.$internalizeValue(val)
|
|
49
|
-
);
|
|
44
|
+
Object.assign(this.$data._fieldModels, { [this.fieldName]: this.$internalizeValue(val) })
|
|
50
45
|
|
|
51
46
|
this._checkDirtyState(val, oldVal);
|
|
52
47
|
}
|
|
@@ -65,13 +60,13 @@ export default {
|
|
|
65
60
|
const topDialog = Utils.launch.dialog.topDialog();
|
|
66
61
|
if (topDialog) {
|
|
67
62
|
if (!topDialog.isFormDirty) {
|
|
68
|
-
console.
|
|
63
|
+
console.log("Dialog form is now dirty");
|
|
69
64
|
topDialog.isFormDirty = true;
|
|
70
65
|
}
|
|
71
66
|
} else {
|
|
72
|
-
if (
|
|
73
|
-
console.
|
|
74
|
-
|
|
67
|
+
if (vueApp.isFormDirty) {
|
|
68
|
+
console.log("Window form is now dirty");
|
|
69
|
+
vueApp.isFormDirty = true;
|
|
75
70
|
}
|
|
76
71
|
}
|
|
77
72
|
}
|
|
@@ -135,7 +130,7 @@ export default {
|
|
|
135
130
|
|
|
136
131
|
return new Hash(styles);
|
|
137
132
|
},
|
|
138
|
-
$length: function(length) {
|
|
133
|
+
$length: function (length) {
|
|
139
134
|
if (Utils.type.isString(length) || Utils.type.isNumber(length)) {
|
|
140
135
|
switch (length) {
|
|
141
136
|
case "wrapContent":
|
|
@@ -162,7 +157,9 @@ export default {
|
|
|
162
157
|
_updateDisplay(styles, properties) {
|
|
163
158
|
Utils.type.ifObject(
|
|
164
159
|
properties.showIf,
|
|
165
|
-
() =>
|
|
160
|
+
() => {
|
|
161
|
+
styles["display"] = this.display
|
|
162
|
+
}
|
|
166
163
|
);
|
|
167
164
|
Utils.type.ifObject(properties.valueIf, logic => {
|
|
168
165
|
const newValue = jsonLogic.apply(logic, this.$data._fieldModels);
|
|
@@ -192,6 +189,7 @@ export default {
|
|
|
192
189
|
_linkFieldModels() {
|
|
193
190
|
const hasCondition = this.spec && this.spec.showIf;
|
|
194
191
|
const name = GLib.component.vueName(this);
|
|
192
|
+
|
|
195
193
|
const isField = name && name.startsWith("fields-");
|
|
196
194
|
if (hasCondition || isField) {
|
|
197
195
|
const form = this.$closest("panels-form");
|
|
@@ -220,6 +218,7 @@ export default {
|
|
|
220
218
|
classes.push("glib-clickable")
|
|
221
219
|
);
|
|
222
220
|
|
|
221
|
+
// This could appear not as before after migration to vuetify 3
|
|
223
222
|
Utils.type.ifArray(properties.styleClasses, val => {
|
|
224
223
|
if (val.includes("card")) {
|
|
225
224
|
classes.push("v-card");
|
|
@@ -231,6 +230,7 @@ export default {
|
|
|
231
230
|
}
|
|
232
231
|
}
|
|
233
232
|
});
|
|
233
|
+
|
|
234
234
|
return classes;
|
|
235
235
|
}
|
|
236
236
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { vueApp } from "../../../store";
|
|
2
|
+
|
|
1
3
|
export default {
|
|
2
|
-
data: function() {
|
|
4
|
+
data: function () {
|
|
3
5
|
return {
|
|
4
6
|
topScrollHandler: null,
|
|
5
7
|
bottomScrollHandler: null,
|
|
@@ -17,7 +19,7 @@ export default {
|
|
|
17
19
|
}
|
|
18
20
|
},
|
|
19
21
|
methods: {
|
|
20
|
-
enableInfiniteScrollIfApplicable: function() {
|
|
22
|
+
enableInfiniteScrollIfApplicable: function () {
|
|
21
23
|
this.$removeViewportChangeListeners(this.topScrollHandler);
|
|
22
24
|
this.$removeViewportChangeListeners(this.bottomScrollHandler);
|
|
23
25
|
|
|
@@ -90,7 +92,7 @@ export default {
|
|
|
90
92
|
for (const section of response.sections) {
|
|
91
93
|
this.sections.push(section);
|
|
92
94
|
}
|
|
93
|
-
Utils.history.updatePage();
|
|
95
|
+
Utils.history.updatePage(vueApp.page);
|
|
94
96
|
}
|
|
95
97
|
);
|
|
96
98
|
}
|
|
@@ -113,7 +115,7 @@ export default {
|
|
|
113
115
|
{ url: nextPageUrl },
|
|
114
116
|
"GET",
|
|
115
117
|
vm,
|
|
116
|
-
function(response) {
|
|
118
|
+
function (response) {
|
|
117
119
|
for (const section of response.sections) {
|
|
118
120
|
vm.sections.push(section);
|
|
119
121
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { createConsumer } from "@rails/actioncable";
|
|
2
|
+
import { vueApp } from "../../../store";
|
|
2
3
|
|
|
3
4
|
const consumer = createConsumer();
|
|
4
5
|
|
|
5
6
|
export default {
|
|
6
|
-
data: function() {
|
|
7
|
+
data: function () {
|
|
7
8
|
return {
|
|
8
9
|
_wsSocket: null
|
|
9
10
|
};
|
|
@@ -19,16 +20,16 @@ export default {
|
|
|
19
20
|
channel: channelName
|
|
20
21
|
});
|
|
21
22
|
|
|
22
|
-
console.
|
|
23
|
+
console.log("Connecting to channel", subscription);
|
|
23
24
|
|
|
24
25
|
consumer.subscriptions.create(subscription, {
|
|
25
26
|
connected() {
|
|
26
|
-
const ws =
|
|
27
|
+
const ws = vueApp.actionCable;
|
|
27
28
|
ws.channels[channelName] = this;
|
|
28
|
-
console.
|
|
29
|
+
console.log("Connected to channel", channelName);
|
|
29
30
|
},
|
|
30
31
|
|
|
31
|
-
disconnected() {},
|
|
32
|
+
disconnected() { },
|
|
32
33
|
|
|
33
34
|
received(data) {
|
|
34
35
|
const action = data.action;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Socket } from "phoenix";
|
|
2
2
|
import Hash from "../../../utils/hash";
|
|
3
|
+
import { vueApp } from "../../../store";
|
|
3
4
|
|
|
4
5
|
export default {
|
|
5
|
-
data: function() {
|
|
6
|
+
data: function () {
|
|
6
7
|
return {
|
|
7
8
|
_wsSocket: null
|
|
8
9
|
};
|
|
@@ -12,6 +13,7 @@ export default {
|
|
|
12
13
|
Utils.type.ifObject(
|
|
13
14
|
spec,
|
|
14
15
|
ws => {
|
|
16
|
+
console.log("Connecting socket...");
|
|
15
17
|
Utils.launch.snackbar.indicator("Connecting...");
|
|
16
18
|
Utils.http.startIndicator(this);
|
|
17
19
|
|
|
@@ -53,19 +55,19 @@ export default {
|
|
|
53
55
|
|
|
54
56
|
this._wsSocket = socket;
|
|
55
57
|
socket.onOpen(() => {
|
|
56
|
-
console.
|
|
58
|
+
console.log("Connected socket");
|
|
57
59
|
this._wsJoinChannel(socket, spec);
|
|
58
60
|
Utils.http.stopIndicator(this);
|
|
59
61
|
});
|
|
60
62
|
socket.onError(() => {
|
|
61
63
|
// Start the indicator again because this can trigger even after successfully connected.
|
|
62
64
|
Utils.http.startIndicator(this);
|
|
63
|
-
console.
|
|
65
|
+
console.log("Unable to connect socket");
|
|
64
66
|
});
|
|
65
67
|
socket.connect();
|
|
66
68
|
},
|
|
67
69
|
_wsJoinChannel(socket, spec) {
|
|
68
|
-
const ws =
|
|
70
|
+
const ws = vueApp.webSocket;
|
|
69
71
|
Utils.type.ifObject(spec.header, header => {
|
|
70
72
|
ws.header = header;
|
|
71
73
|
});
|
|
@@ -79,7 +81,7 @@ export default {
|
|
|
79
81
|
const channel = socket.channel(topicName, {});
|
|
80
82
|
|
|
81
83
|
for (const eventName of events) {
|
|
82
|
-
console.
|
|
84
|
+
console.log(`Registering event '${eventName}'`);
|
|
83
85
|
channel.on(eventName, payload => {
|
|
84
86
|
console.debug(`Received '${eventName}' event`, payload);
|
|
85
87
|
Utils.ws.handleResponse(payload.onResponse, this);
|
|
@@ -89,11 +91,11 @@ export default {
|
|
|
89
91
|
channel
|
|
90
92
|
.join()
|
|
91
93
|
.receive("ok", resp => {
|
|
92
|
-
console.
|
|
94
|
+
console.log(`Channel joined '${topicName}'`, resp);
|
|
93
95
|
ws.channels[topicName] = channel;
|
|
94
96
|
})
|
|
95
97
|
.receive("error", resp => {
|
|
96
|
-
console.
|
|
98
|
+
console.log(`Unable to join channel '${topicName}'`, resp);
|
|
97
99
|
Utils.launch.snackbar.error(
|
|
98
100
|
"Unable to connect. Please try again.",
|
|
99
101
|
this
|
|
@@ -102,13 +104,13 @@ export default {
|
|
|
102
104
|
},
|
|
103
105
|
_wsDisconnectSocket() {
|
|
104
106
|
if (this._wsSocket) {
|
|
105
|
-
console.
|
|
107
|
+
console.log("Disconnecting socket");
|
|
106
108
|
// Sometimes this doesn't prevent errorneous socket from trying to reconnect. In this case,
|
|
107
109
|
// the socket will keep attempting to connect.
|
|
108
110
|
this._wsSocket.disconnect();
|
|
109
111
|
this._wsSocket = null;
|
|
110
112
|
|
|
111
|
-
const ws =
|
|
113
|
+
const ws = vueApp.webSocket;
|
|
112
114
|
ws.channels = {};
|
|
113
115
|
ws.header = {};
|
|
114
116
|
|
package/components/p.vue
CHANGED
|
@@ -30,7 +30,17 @@ p {
|
|
|
30
30
|
display: inline-block;
|
|
31
31
|
margin-bottom: 0;
|
|
32
32
|
}
|
|
33
|
+
|
|
33
34
|
p.muted {
|
|
34
35
|
opacity: 0.7;
|
|
35
36
|
}
|
|
37
|
+
|
|
38
|
+
.tooltip {
|
|
39
|
+
padding: 4px 8px;
|
|
40
|
+
color: white;
|
|
41
|
+
font-weight: 500;
|
|
42
|
+
background-color: #111827;
|
|
43
|
+
border-radius: .5rem;
|
|
44
|
+
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
|
45
|
+
}
|
|
36
46
|
</style>
|
|
@@ -1,18 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<v-col
|
|
3
|
-
:xl="xl.
|
|
4
|
-
:
|
|
5
|
-
:md="md.cols"
|
|
6
|
-
:sm="sm.cols"
|
|
7
|
-
:style="cssStyles()"
|
|
8
|
-
:class="$classes()"
|
|
9
|
-
:cols="xs.cols || 12"
|
|
10
|
-
:order-xl="xl.order"
|
|
11
|
-
:order-lg="lg.order"
|
|
12
|
-
:order-md="md.order"
|
|
13
|
-
:order-sm="sm.order"
|
|
14
|
-
:order="xs.order"
|
|
15
|
-
>
|
|
2
|
+
<v-col :xl="xl.cols" :lg="lg.cols" :md="md.cols" :sm="sm.cols" :style="cssStyles()" :class="$classes()"
|
|
3
|
+
:cols="xs.cols || 12" :order-xl="xl.order" :order-lg="lg.order" :order-md="md.order" :order-sm="sm.order"
|
|
4
|
+
:order="xs.order">
|
|
16
5
|
<panels-responsive :spec="innerSpec()" />
|
|
17
6
|
</v-col>
|
|
18
7
|
</template>
|
|
@@ -22,7 +11,7 @@ import Hash from "../../utils/hash";
|
|
|
22
11
|
|
|
23
12
|
export default {
|
|
24
13
|
props: {
|
|
25
|
-
spec: { type: Object, required: true }
|
|
14
|
+
spec: { type: Object, required: true },
|
|
26
15
|
},
|
|
27
16
|
data() {
|
|
28
17
|
return {
|
|
@@ -30,7 +19,7 @@ export default {
|
|
|
30
19
|
lg: {},
|
|
31
20
|
md: {},
|
|
32
21
|
sm: {},
|
|
33
|
-
xs: {}
|
|
22
|
+
xs: {},
|
|
34
23
|
};
|
|
35
24
|
},
|
|
36
25
|
methods: {
|
|
@@ -47,7 +36,7 @@ export default {
|
|
|
47
36
|
},
|
|
48
37
|
cssStyles() {
|
|
49
38
|
const styles = Object.assign({}, this.$styles());
|
|
50
|
-
switch (this.$vuetify.
|
|
39
|
+
switch (this.$vuetify.display.name) {
|
|
51
40
|
case "xl":
|
|
52
41
|
this.applyStyles(styles, this.xs);
|
|
53
42
|
this.applyStyles(styles, this.sm);
|
|
@@ -101,8 +90,8 @@ export default {
|
|
|
101
90
|
Utils.type.ifBoolean(spec.hide, () => {
|
|
102
91
|
styles["display"] = "none";
|
|
103
92
|
});
|
|
104
|
-
}
|
|
105
|
-
}
|
|
93
|
+
},
|
|
94
|
+
},
|
|
106
95
|
};
|
|
107
96
|
</script>
|
|
108
97
|
|