glib-web 0.7.1 → 0.8.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/components/component.vue +2 -2
- package/components/mixins/list/autoload.js +51 -31
- package/components/panels/list.vue +9 -3
- package/components/{socialSharing.vue → shareButton.vue} +20 -1
- package/extensions/array.js +4 -0
- package/index.js +1 -1
- package/nav/dialog.vue +1 -1
- package/nav/drawer.vue +85 -3
- package/package.json +1 -1
- package/templates/comment.vue +12 -1
- package/utils/http.js +1 -0
package/components/component.vue
CHANGED
|
@@ -113,7 +113,7 @@ import SelectBanner from "./banners/select";
|
|
|
113
113
|
import LineChart from "./charts/line";
|
|
114
114
|
import ColumnChart from "./charts/column";
|
|
115
115
|
|
|
116
|
-
import
|
|
116
|
+
import ShareButton from "./shareButton";
|
|
117
117
|
|
|
118
118
|
export default {
|
|
119
119
|
components: {
|
|
@@ -145,7 +145,7 @@ export default {
|
|
|
145
145
|
"views-map": Map,
|
|
146
146
|
"views-tabBar": TabBar,
|
|
147
147
|
"views-calendar": Calendar,
|
|
148
|
-
"views-
|
|
148
|
+
"views-shareButton": ShareButton,
|
|
149
149
|
|
|
150
150
|
"fields-hidden": HiddenField,
|
|
151
151
|
"fields-text": TextField,
|
|
@@ -9,13 +9,13 @@ export default {
|
|
|
9
9
|
infiniteScroll: null
|
|
10
10
|
};
|
|
11
11
|
},
|
|
12
|
-
computed: {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
},
|
|
12
|
+
// computed: {
|
|
13
|
+
// bottomAnchorStyles() {
|
|
14
|
+
// return {
|
|
15
|
+
// display: this.infiniteScroll && this.nextPageUrl ? "block" : "none"
|
|
16
|
+
// };
|
|
17
|
+
// }
|
|
18
|
+
// },
|
|
19
19
|
methods: {
|
|
20
20
|
enableInfiniteScrollIfApplicable: function() {
|
|
21
21
|
this.$removeViewportChangeListeners(this.topScrollHandler);
|
|
@@ -24,23 +24,8 @@ export default {
|
|
|
24
24
|
const prevPage = this.spec.prevPage || {};
|
|
25
25
|
const nextPage = this.spec.nextPage || {};
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
// if (infiniteScroll) {
|
|
30
|
-
// const nextPageUrl = nextPage.url;
|
|
31
|
-
// const onScrollToBottom = this.spec.onScrollToBottom;
|
|
32
|
-
// if (nextPageUrl || onScrollToBottom) {
|
|
33
|
-
// this._registerBottomScroll(nextPageUrl, onScrollToBottom);
|
|
34
|
-
// }
|
|
35
|
-
|
|
36
|
-
// const prevPageUrl = prevPage.url;
|
|
37
|
-
// const onScrollToTop = this.spec.onScrollToTop;
|
|
38
|
-
// if (prevPageUrl || onScrollToTop) {
|
|
39
|
-
// this._registerTopScroll(prevPageUrl, onScrollToTop);
|
|
40
|
-
// }
|
|
41
|
-
// }
|
|
42
|
-
|
|
43
|
-
this.infiniteScroll = nextPage.autoload == "asNeeded";
|
|
27
|
+
this.infiniteScroll =
|
|
28
|
+
nextPage.autoload == "asNeeded" || prevPage.autoload == "asNeeded";
|
|
44
29
|
const onScrollToBottom = this.spec.onScrollToBottom;
|
|
45
30
|
const onScrollToTop = this.spec.onScrollToTop;
|
|
46
31
|
|
|
@@ -49,16 +34,18 @@ export default {
|
|
|
49
34
|
this.prevPageUrl = prevPage.url;
|
|
50
35
|
}
|
|
51
36
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
37
|
+
// Avoid executing the scroll actions on page load.
|
|
38
|
+
setTimeout(() => {
|
|
39
|
+
if (this.nextPageUrl || onScrollToBottom) {
|
|
40
|
+
this._registerBottomScroll(onScrollToBottom);
|
|
41
|
+
}
|
|
55
42
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
43
|
+
if (this.prevPageUrl || onScrollToTop) {
|
|
44
|
+
this._registerTopScroll(onScrollToTop);
|
|
45
|
+
}
|
|
46
|
+
}, 1000);
|
|
59
47
|
},
|
|
60
48
|
_registerTopScroll(onScrollToTop) {
|
|
61
|
-
// TODO: Consider adding support for prevPageUrl
|
|
62
49
|
this.topScrollHandler = this.$onVisibilityChange(
|
|
63
50
|
this.$refs.topAnchor,
|
|
64
51
|
(el, visible) => {
|
|
@@ -71,6 +58,39 @@ export default {
|
|
|
71
58
|
this.$addViewportChangeListeners(this.topScrollHandler);
|
|
72
59
|
},
|
|
73
60
|
_handleTopScroll(onScrollToTop) {
|
|
61
|
+
if (this.prevPageUrl) {
|
|
62
|
+
this.request = Utils.http.execute(
|
|
63
|
+
{ url: this.prevPageUrl },
|
|
64
|
+
"GET",
|
|
65
|
+
this,
|
|
66
|
+
response => {
|
|
67
|
+
const prevPage = response.prevPage;
|
|
68
|
+
if (this.$type.isObject(prevPage)) {
|
|
69
|
+
this.prevPageUrl = response.prevPage.url;
|
|
70
|
+
} else {
|
|
71
|
+
this.prevPageUrl = null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
for (const [
|
|
75
|
+
index,
|
|
76
|
+
prependedSection
|
|
77
|
+
] of response.sections.entries()) {
|
|
78
|
+
const section = this.sections[index];
|
|
79
|
+
|
|
80
|
+
Utils.type.ifArray(prependedSection.rows, rows => {
|
|
81
|
+
for (const row of rows) {
|
|
82
|
+
section.rows.unshift(row);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// TODO: scroll back to where the position was before the prepending.
|
|
87
|
+
// https://stackoverflow.com/questions/54765451/preserve-scroll-position-on-dom-update-in-vue-js
|
|
88
|
+
}
|
|
89
|
+
Utils.history.updatePage();
|
|
90
|
+
}
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
74
94
|
GLib.action.execute(onScrollToTop, this);
|
|
75
95
|
},
|
|
76
96
|
_registerBottomScroll(onScrollToBottom) {
|
|
@@ -5,7 +5,11 @@
|
|
|
5
5
|
class="py-0"
|
|
6
6
|
:style="genericStyles()"
|
|
7
7
|
>
|
|
8
|
-
<div ref="topAnchor"
|
|
8
|
+
<div ref="topAnchor">
|
|
9
|
+
<div v-if="prevPageUrl" class="py-3 px-4">
|
|
10
|
+
Loading...
|
|
11
|
+
</div>
|
|
12
|
+
</div>
|
|
9
13
|
|
|
10
14
|
<template v-for="(section, sectionIndex) in sections">
|
|
11
15
|
<div :key="`section${sectionIndex}`">
|
|
@@ -46,8 +50,10 @@
|
|
|
46
50
|
</div>
|
|
47
51
|
</template>
|
|
48
52
|
|
|
49
|
-
<div ref="bottomAnchor"
|
|
50
|
-
|
|
53
|
+
<div ref="bottomAnchor">
|
|
54
|
+
<div v-if="nextPageUrl" class="py-3 px-4">
|
|
55
|
+
Loading...
|
|
56
|
+
</div>
|
|
51
57
|
</div>
|
|
52
58
|
</v-list>
|
|
53
59
|
</template>
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
:url="spec.url"
|
|
6
6
|
:title="spec.title"
|
|
7
7
|
:description="spec.description"
|
|
8
|
-
:quote="spec.
|
|
8
|
+
:quote="spec.facebookQuote"
|
|
9
9
|
:hashtags="spec.hashtags"
|
|
10
10
|
:twitter-user="spec.twitterUser"
|
|
11
11
|
>
|
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
</template>
|
|
17
17
|
|
|
18
18
|
<script>
|
|
19
|
+
import Action from "../action";
|
|
20
|
+
|
|
19
21
|
export default {
|
|
20
22
|
props: {
|
|
21
23
|
spec: { type: Object, required: true }
|
|
@@ -23,6 +25,10 @@ export default {
|
|
|
23
25
|
data() {
|
|
24
26
|
return {
|
|
25
27
|
config: {
|
|
28
|
+
copy: {
|
|
29
|
+
icon: "far fah fa-lg fa-copy",
|
|
30
|
+
color: "#183153"
|
|
31
|
+
},
|
|
26
32
|
email: {
|
|
27
33
|
icon: "far fah fa-lg fa-envelope",
|
|
28
34
|
color: "#333333"
|
|
@@ -85,6 +91,19 @@ export default {
|
|
|
85
91
|
}
|
|
86
92
|
}
|
|
87
93
|
};
|
|
94
|
+
},
|
|
95
|
+
mounted() {
|
|
96
|
+
if (this.spec.onClick) {
|
|
97
|
+
const parentElement = this.$el.parentElement;
|
|
98
|
+
// remove default event listener
|
|
99
|
+
this.$el.replaceWith(this.$el.cloneNode(true));
|
|
100
|
+
// manually attach event listener because @click not working
|
|
101
|
+
parentElement
|
|
102
|
+
.querySelector(`a.${this.$el.classList[0]}`)
|
|
103
|
+
.addEventListener("click", () => {
|
|
104
|
+
Action.execute(this.spec.onClick, this);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
88
107
|
}
|
|
89
108
|
};
|
|
90
109
|
</script>
|
package/extensions/array.js
CHANGED
package/index.js
CHANGED
package/nav/dialog.vue
CHANGED
package/nav/drawer.vue
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
:mini-variant.sync="mini"
|
|
14
14
|
@input="updateState"
|
|
15
15
|
>
|
|
16
|
-
<template v-slot:prepend>
|
|
16
|
+
<template v-if="mini" v-slot:prepend>
|
|
17
17
|
<v-list-item>
|
|
18
18
|
<v-list-item-icon>
|
|
19
19
|
<v-icon v-if="!mini">mdi-chevron-left</v-icon>
|
|
@@ -50,6 +50,75 @@
|
|
|
50
50
|
import NavDrawerButton from "./drawerButton";
|
|
51
51
|
import NavDrawerLabel from "./drawerLabel";
|
|
52
52
|
|
|
53
|
+
const activeClass = (element, action) => {
|
|
54
|
+
let indicator = element.querySelector(".indicator");
|
|
55
|
+
if (indicator) {
|
|
56
|
+
indicator.classList[action]("active");
|
|
57
|
+
}
|
|
58
|
+
let icon = element.querySelector(".v-list-item__action");
|
|
59
|
+
if (icon) {
|
|
60
|
+
icon.classList[action]("active");
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const comparePathname = (hrefPathname, locationPathname) => {
|
|
65
|
+
let value = 0;
|
|
66
|
+
const loc = locationPathname.split("/").filter(v => v);
|
|
67
|
+
const hr = hrefPathname.split("/").filter(v => v);
|
|
68
|
+
|
|
69
|
+
if (loc.length == hr.length) value = value + 1;
|
|
70
|
+
|
|
71
|
+
loc.forEach((route, index) => {
|
|
72
|
+
if (!hr[index]) {
|
|
73
|
+
value = value + 0;
|
|
74
|
+
} else if (hr[index] == route) {
|
|
75
|
+
value = value + 1;
|
|
76
|
+
} else if (hr[index] != route) {
|
|
77
|
+
value = value - 2;
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
return value;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const navigationMap = (element, locationPathname) => {
|
|
85
|
+
return Array.from(element.querySelectorAll(".nav-item")).reduce(
|
|
86
|
+
(prev, curr) => {
|
|
87
|
+
let a = curr.querySelector("a");
|
|
88
|
+
if (a) {
|
|
89
|
+
let obj = {};
|
|
90
|
+
obj[new URL(a.href).pathname] = {
|
|
91
|
+
element: curr,
|
|
92
|
+
matchValue: comparePathname(
|
|
93
|
+
new URL(a.href).pathname,
|
|
94
|
+
locationPathname
|
|
95
|
+
)
|
|
96
|
+
};
|
|
97
|
+
return Object.assign(prev, obj);
|
|
98
|
+
} else {
|
|
99
|
+
return prev;
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
{}
|
|
103
|
+
);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const getActiveNav = navigationMap => {
|
|
107
|
+
let currentRoute = "";
|
|
108
|
+
let maxMatchValue = null;
|
|
109
|
+
|
|
110
|
+
for (let route in navigationMap) {
|
|
111
|
+
if (!maxMatchValue) {
|
|
112
|
+
maxMatchValue = navigationMap[route].matchValue;
|
|
113
|
+
currentRoute = route;
|
|
114
|
+
} else if (maxMatchValue < navigationMap[route].matchValue) {
|
|
115
|
+
maxMatchValue = navigationMap[route].matchValue;
|
|
116
|
+
currentRoute = route;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return navigationMap[currentRoute];
|
|
120
|
+
};
|
|
121
|
+
|
|
53
122
|
export default {
|
|
54
123
|
components: {
|
|
55
124
|
"nav-drawerButton": NavDrawerButton,
|
|
@@ -98,6 +167,9 @@ export default {
|
|
|
98
167
|
},
|
|
99
168
|
methods: {
|
|
100
169
|
$ready() {
|
|
170
|
+
this.mini = !this.cssClasses.includes("maxi");
|
|
171
|
+
this.updateNavigationStyle(window.location);
|
|
172
|
+
|
|
101
173
|
// this.$el.addEventListener('drawers/clickButton', () => { this.updateState(false) }, false)
|
|
102
174
|
this.$el.addEventListener("drawers/clickButton", () => {
|
|
103
175
|
if (!this.permanent) {
|
|
@@ -113,6 +185,15 @@ export default {
|
|
|
113
185
|
this.cssClasses.includes("mini") ||
|
|
114
186
|
(this.cssClasses.includes("mini-lg-and-above") && this.lgAndAbove)
|
|
115
187
|
);
|
|
188
|
+
},
|
|
189
|
+
updateNavigationStyle(urlObject) {
|
|
190
|
+
const navMap = navigationMap(this.$el, urlObject.pathname);
|
|
191
|
+
// remove all active class
|
|
192
|
+
for (let route in navMap) {
|
|
193
|
+
activeClass(navMap[route].element, "remove");
|
|
194
|
+
}
|
|
195
|
+
// add active class to nav
|
|
196
|
+
activeClass(getActiveNav(navMap).element, "add");
|
|
116
197
|
}
|
|
117
198
|
}
|
|
118
199
|
};
|
|
@@ -122,12 +203,13 @@ export default {
|
|
|
122
203
|
.nav-item {
|
|
123
204
|
position: relative;
|
|
124
205
|
}
|
|
125
|
-
.nav-item:hover .indicator
|
|
206
|
+
.nav-item:hover .indicator,
|
|
207
|
+
.nav-item .indicator.active {
|
|
126
208
|
display: flex;
|
|
127
209
|
position: absolute;
|
|
128
210
|
width: 3px;
|
|
129
211
|
height: 65%;
|
|
130
|
-
margin:
|
|
212
|
+
margin: 8px 0;
|
|
131
213
|
justify-content: center;
|
|
132
214
|
align-items: center;
|
|
133
215
|
background-color: white;
|
package/package.json
CHANGED
package/templates/comment.vue
CHANGED
|
@@ -13,9 +13,15 @@
|
|
|
13
13
|
class="font-weight-bold body-2 subtitle"
|
|
14
14
|
>{{ spec.title }}</v-card-title
|
|
15
15
|
>
|
|
16
|
-
|
|
16
|
+
<!-- eslint-disable vue/no-v-html -->
|
|
17
|
+
<div
|
|
18
|
+
v-if="mode !== 'system'"
|
|
19
|
+
class="comment-bubble pa-2"
|
|
20
|
+
v-html="compiledText"
|
|
21
|
+
>
|
|
17
22
|
{{ spec.subtitle }}
|
|
18
23
|
</div>
|
|
24
|
+
<!--eslint-enable-->
|
|
19
25
|
<img
|
|
20
26
|
v-if="spec.image"
|
|
21
27
|
:src="spec.image"
|
|
@@ -51,6 +57,11 @@ export default {
|
|
|
51
57
|
chips: []
|
|
52
58
|
};
|
|
53
59
|
},
|
|
60
|
+
computed: {
|
|
61
|
+
compiledText() {
|
|
62
|
+
return Utils.format.markdown(this.spec.subtitle);
|
|
63
|
+
}
|
|
64
|
+
},
|
|
54
65
|
methods: {
|
|
55
66
|
$ready() {
|
|
56
67
|
const template = this.spec.template;
|