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.
Files changed (204) hide show
  1. package/.eslintrc.js +37 -0
  2. package/LICENSE +201 -0
  3. package/README.md +33 -0
  4. package/action.js +167 -0
  5. package/actions/analytics/logEvent.js +26 -0
  6. package/actions/auth/creditCard.js +29 -0
  7. package/actions/auth/restart.js +5 -0
  8. package/actions/auth/saveCsrfToken.js +12 -0
  9. package/actions/cables/push.js +38 -0
  10. package/actions/dialogs/alert.js +15 -0
  11. package/actions/dialogs/close.js +7 -0
  12. package/actions/dialogs/notification.js +14 -0
  13. package/actions/dialogs/oauth.js +6 -0
  14. package/actions/dialogs/open.js +7 -0
  15. package/actions/dialogs/options.js +5 -0
  16. package/actions/dialogs/show.js +5 -0
  17. package/actions/forms/submit.js +15 -0
  18. package/actions/http/delete.js +7 -0
  19. package/actions/http/patch.js +7 -0
  20. package/actions/http/post.js +7 -0
  21. package/actions/http/put.js +7 -0
  22. package/actions/panels/scrollTo.js +18 -0
  23. package/actions/panels/scrollToBottom.js +11 -0
  24. package/actions/runMultiple.js +11 -0
  25. package/actions/sheets/select.js +5 -0
  26. package/actions/snackbars/alert.js +15 -0
  27. package/actions/snackbars/select.js +5 -0
  28. package/actions/timeouts/set.js +20 -0
  29. package/actions/windows/close.js +13 -0
  30. package/actions/windows/closeAll.js +16 -0
  31. package/actions/windows/closeWithReload.js +18 -0
  32. package/actions/windows/open.js +5 -0
  33. package/actions/windows/openWeb.js +5 -0
  34. package/actions/windows/refreshState.js +5 -0
  35. package/actions/windows/reload.js +24 -0
  36. package/actions/ws/push.js +35 -0
  37. package/app.vue +180 -0
  38. package/components/_button.vue +101 -0
  39. package/components/_dropdownMenu.vue +76 -0
  40. package/components/_icon.vue +50 -0
  41. package/components/_message.vue +25 -0
  42. package/components/avatar.vue +16 -0
  43. package/components/banners/alert.vue +49 -0
  44. package/components/banners/select.vue +82 -0
  45. package/components/button.vue +13 -0
  46. package/components/calendar.vue +105 -0
  47. package/components/charts/column.vue +26 -0
  48. package/components/charts/line.vue +61 -0
  49. package/components/chip.vue +24 -0
  50. package/components/component.vue +222 -0
  51. package/components/datetime.vue +54 -0
  52. package/components/fab.vue +33 -0
  53. package/components/fields/_patternText.vue +61 -0
  54. package/components/fields/_select.vue +86 -0
  55. package/components/fields/autocomplete.vue +73 -0
  56. package/components/fields/check.vue +104 -0
  57. package/components/fields/checkGroup.vue +51 -0
  58. package/components/fields/country/countries.js +251 -0
  59. package/components/fields/country/field.vue +81 -0
  60. package/components/fields/country/regions.js +12 -0
  61. package/components/fields/creditCard.vue +105 -0
  62. package/components/fields/date.vue +24 -0
  63. package/components/fields/datetime.vue +49 -0
  64. package/components/fields/dynamicGroup.vue +106 -0
  65. package/components/fields/dynamicSelect.vue +173 -0
  66. package/components/fields/file.vue +166 -0
  67. package/components/fields/googlePlace.vue +158 -0
  68. package/components/fields/hidden.vue +18 -0
  69. package/components/fields/location.vue +223 -0
  70. package/components/fields/newRichText.vue +191 -0
  71. package/components/fields/phone/countries.js +315 -0
  72. package/components/fields/phone/field.vue +348 -0
  73. package/components/fields/phone/sprite.css +1071 -0
  74. package/components/fields/radio.vue +64 -0
  75. package/components/fields/radioGroup.vue +93 -0
  76. package/components/fields/rating.vue +26 -0
  77. package/components/fields/richText.vue +172 -0
  78. package/components/fields/select.vue +17 -0
  79. package/components/fields/stripe/stripeFields.vue +93 -0
  80. package/components/fields/stripe/stripeIndividualFields.vue +207 -0
  81. package/components/fields/stripeExternalAccount.vue +135 -0
  82. package/components/fields/stripeToken.vue +59 -0
  83. package/components/fields/submit.vue +23 -0
  84. package/components/fields/text.vue +144 -0
  85. package/components/fields/textarea.vue +59 -0
  86. package/components/fields/timeZone.vue +22 -0
  87. package/components/fields/timer.vue +83 -0
  88. package/components/h1.vue +28 -0
  89. package/components/h2.vue +20 -0
  90. package/components/h3.vue +22 -0
  91. package/components/h4.vue +20 -0
  92. package/components/h5.vue +20 -0
  93. package/components/h6.vue +20 -0
  94. package/components/hr.vue +13 -0
  95. package/components/html.vue +13 -0
  96. package/components/icon.vue +25 -0
  97. package/components/image.vue +87 -0
  98. package/components/label.vue +62 -0
  99. package/components/map.vue +206 -0
  100. package/components/markdown.vue +52 -0
  101. package/components/mixins/events.js +178 -0
  102. package/components/mixins/generic.js +58 -0
  103. package/components/mixins/list/autoload.js +144 -0
  104. package/components/mixins/longClick.js +56 -0
  105. package/components/mixins/scrolling.js +35 -0
  106. package/components/mixins/styles.js +221 -0
  107. package/components/mixins/table/autoload.js +131 -0
  108. package/components/mixins/table/export.js +52 -0
  109. package/components/mixins/table/import.js +106 -0
  110. package/components/mixins/text.js +20 -0
  111. package/components/mixins/ws/actionCable.js +48 -0
  112. package/components/mixins/ws/phoenixSocket.js +117 -0
  113. package/components/p.vue +36 -0
  114. package/components/panels/carousel.vue +55 -0
  115. package/components/panels/column.vue +117 -0
  116. package/components/panels/custom.vue +52 -0
  117. package/components/panels/flow.vue +81 -0
  118. package/components/panels/form.vue +126 -0
  119. package/components/panels/horizontal.vue +73 -0
  120. package/components/panels/list.vue +241 -0
  121. package/components/panels/responsive.vue +88 -0
  122. package/components/panels/scroll.vue +68 -0
  123. package/components/panels/split.vue +52 -0
  124. package/components/panels/table.vue +234 -0
  125. package/components/panels/ul.vue +34 -0
  126. package/components/panels/vertical.vue +71 -0
  127. package/components/panels/web.vue +11 -0
  128. package/components/spacer.vue +11 -0
  129. package/components/switch.vue +42 -0
  130. package/components/tabBar.vue +44 -0
  131. package/extensions/array.js +20 -0
  132. package/extensions/string.js +21 -0
  133. package/index.js +195 -0
  134. package/keys.js +12 -0
  135. package/nav/appbar.vue +117 -0
  136. package/nav/content.vue +40 -0
  137. package/nav/dialog.vue +127 -0
  138. package/nav/drawer.vue +88 -0
  139. package/nav/drawerButton.vue +28 -0
  140. package/nav/drawerLabel.vue +21 -0
  141. package/nav/sheet.vue +57 -0
  142. package/nav/snackbar.vue +72 -0
  143. package/package.json +42 -0
  144. package/settings.json.example +21 -0
  145. package/static/plugins/alignment/alignment.js +76 -0
  146. package/static/plugins/alignment/alignment.min.js +1 -0
  147. package/static/plugins/beyondgrammar/beyondgrammar.js +46 -0
  148. package/static/plugins/beyondgrammar/beyondgrammar.min.js +1 -0
  149. package/static/plugins/blockcode/blockcode.js +110 -0
  150. package/static/plugins/blockcode/blockcode.min.js +1 -0
  151. package/static/plugins/clips/clips.js +44 -0
  152. package/static/plugins/clips/clips.min.js +1 -0
  153. package/static/plugins/counter/counter.js +60 -0
  154. package/static/plugins/counter/counter.min.js +1 -0
  155. package/static/plugins/definedlinks/definedlinks.js +64 -0
  156. package/static/plugins/definedlinks/definedlinks.min.js +1 -0
  157. package/static/plugins/handle/handle.js +173 -0
  158. package/static/plugins/handle/handle.min.js +1 -0
  159. package/static/plugins/icons/icons.js +72 -0
  160. package/static/plugins/icons/icons.min.js +1 -0
  161. package/static/plugins/imageposition/imageposition.js +85 -0
  162. package/static/plugins/imageposition/imageposition.min.js +1 -0
  163. package/static/plugins/inlineformat/inlineformat.js +85 -0
  164. package/static/plugins/inlineformat/inlineformat.min.js +1 -0
  165. package/static/plugins/removeformat/removeformat.js +28 -0
  166. package/static/plugins/removeformat/removeformat.min.js +1 -0
  167. package/static/plugins/selector/selector.js +96 -0
  168. package/static/plugins/selector/selector.min.js +1 -0
  169. package/static/plugins/specialchars/specialchars.js +63 -0
  170. package/static/plugins/specialchars/specialchars.min.js +1 -0
  171. package/static/plugins/textdirection/textdirection.js +55 -0
  172. package/static/plugins/textdirection/textdirection.min.js +1 -0
  173. package/static/plugins/textexpander/textexpander.js +46 -0
  174. package/static/plugins/textexpander/textexpander.min.js +1 -0
  175. package/static/plugins/underline/underline.js +27 -0
  176. package/static/plugins/underline/underline.min.js +1 -0
  177. package/static/redactorx.css +1344 -0
  178. package/static/redactorx.js +14254 -0
  179. package/static/redactorx.min.css +1 -0
  180. package/static/redactorx.min.js +1 -0
  181. package/static/redactorx.usm.min.js +2 -0
  182. package/styles/test.sass +3 -0
  183. package/styles/test.scss +5 -0
  184. package/templates/_menu.vue +38 -0
  185. package/templates/comment.vue +202 -0
  186. package/templates/featured.vue +32 -0
  187. package/templates/thumbnail.vue +138 -0
  188. package/templates/unsupported.vue +12 -0
  189. package/utils/app.js +14 -0
  190. package/utils/dom.js +13 -0
  191. package/utils/form.js +34 -0
  192. package/utils/format.js +14 -0
  193. package/utils/hash.js +29 -0
  194. package/utils/helper.js +44 -0
  195. package/utils/history.js +70 -0
  196. package/utils/http.js +209 -0
  197. package/utils/launch.js +135 -0
  198. package/utils/private/ws.js +22 -0
  199. package/utils/public.js +23 -0
  200. package/utils/settings.js +48 -0
  201. package/utils/storage.js +9 -0
  202. package/utils/type.js +69 -0
  203. package/utils/uploader.js +121 -0
  204. package/utils/url.js +132 -0
@@ -0,0 +1,144 @@
1
+ export default {
2
+ data: function() {
3
+ return {
4
+ topScrollHandler: null,
5
+ bottomScrollHandler: null,
6
+ nextPageUrl: null,
7
+ prevPageUrl: null,
8
+ request: null,
9
+ infiniteScroll: null
10
+ };
11
+ },
12
+ computed: {
13
+ bottomAnchorStyles() {
14
+ return {
15
+ display: this.infiniteScroll && this.nextPageUrl ? "block" : "none"
16
+ };
17
+ }
18
+ },
19
+ methods: {
20
+ enableInfiniteScrollIfApplicable: function() {
21
+ this.$removeViewportChangeListeners(this.topScrollHandler);
22
+ this.$removeViewportChangeListeners(this.bottomScrollHandler);
23
+
24
+ const prevPage = this.spec.prevPage || {};
25
+ const nextPage = this.spec.nextPage || {};
26
+
27
+ // const infiniteScroll = nextPage.autoload == "asNeeded";
28
+ // // const infiniteScroll = nextPage.autoLoad;
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";
44
+ const onScrollToBottom = this.spec.onScrollToBottom;
45
+ const onScrollToTop = this.spec.onScrollToTop;
46
+
47
+ if (this.infiniteScroll) {
48
+ this.nextPageUrl = nextPage.url;
49
+ this.prevPageUrl = prevPage.url;
50
+ }
51
+
52
+ if (this.nextPageUrl || onScrollToBottom) {
53
+ this._registerBottomScroll(onScrollToBottom);
54
+ }
55
+
56
+ if (this.prevPageUrl || onScrollToTop) {
57
+ this._registerTopScroll(onScrollToTop);
58
+ }
59
+ },
60
+ _registerTopScroll(onScrollToTop) {
61
+ // TODO: Consider adding support for prevPageUrl
62
+ this.topScrollHandler = this.$onVisibilityChange(
63
+ this.$refs.topAnchor,
64
+ (el, visible) => {
65
+ if (visible) {
66
+ this._handleTopScroll(onScrollToTop);
67
+ // GLib.action.execute(onScrollToTop, null, this);
68
+ }
69
+ }
70
+ );
71
+
72
+ this.$addViewportChangeListeners(this.topScrollHandler);
73
+ },
74
+ _handleTopScroll(onScrollToTop) {
75
+ GLib.action.execute(onScrollToTop, null, this);
76
+ },
77
+ _registerBottomScroll(onScrollToBottom) {
78
+ this.bottomScrollHandler = this.$onVisibilityChange(
79
+ this.$refs.bottomAnchor,
80
+ (el, visible) => {
81
+ if (visible) {
82
+ this._handleBottomScroll(onScrollToBottom);
83
+ }
84
+ }
85
+ );
86
+
87
+ this.$addViewportChangeListeners(this.bottomScrollHandler);
88
+ },
89
+ _handleBottomScroll(onScrollToBottom) {
90
+ if (this.nextPageUrl) {
91
+ this.request = Utils.http.execute(
92
+ { url: this.nextPageUrl },
93
+ "GET",
94
+ this,
95
+ response => {
96
+ const nextPage = response.nextPage;
97
+ if (this.$type.isObject(nextPage)) {
98
+ this.nextPageUrl = response.nextPage.url;
99
+ } else {
100
+ this.nextPageUrl = null;
101
+ }
102
+
103
+ for (const section of response.sections) {
104
+ this.sections.push(section);
105
+ }
106
+ Utils.history.updatePage();
107
+ }
108
+ );
109
+ }
110
+
111
+ GLib.action.execute(onScrollToBottom, null, this);
112
+ },
113
+ autoloadAll(nextPage) {
114
+ const vm = this;
115
+
116
+ if (!this.$type.isObject(nextPage)) {
117
+ return;
118
+ }
119
+ if (nextPage.autoload !== "all") {
120
+ return;
121
+ }
122
+
123
+ let nextPageUrl = nextPage.url;
124
+
125
+ this.request = Utils.http.execute(
126
+ { url: nextPageUrl },
127
+ "GET",
128
+ vm,
129
+ function(response) {
130
+ for (const section of response.sections) {
131
+ vm.sections.push(section);
132
+ }
133
+ vm.autoloadAll(response.nextPage);
134
+ }
135
+ );
136
+ },
137
+ cancelAutoloadRequest() {
138
+ // Avoid old data coming in when this component gets reused.
139
+ if (this.request) {
140
+ this.request.cancel();
141
+ }
142
+ }
143
+ }
144
+ };
@@ -0,0 +1,56 @@
1
+ // From https://github.com/ittus/vue-long-click
2
+ export default ({ delay = 400, interval = 50 }) => ({
3
+ bind: function(el, binding, vNode) {
4
+ if (typeof binding.value !== "function") {
5
+ const compName = vNode.context.name;
6
+ let warn = `[longclick:] provided expression '${binding.expression}' is not a function, but has to be`;
7
+ if (compName) {
8
+ warn += `Found in component '${compName}' `;
9
+ }
10
+ console.warn(warn) // eslint-disable-line
11
+ return;
12
+ }
13
+
14
+ let pressTimer = null;
15
+ let pressInterval = null;
16
+
17
+ const start = e => {
18
+ if (e.type === "mousedown" && e.button !== 0) {
19
+ return;
20
+ }
21
+
22
+ if (pressTimer === null) {
23
+ pressTimer = setTimeout(() => {
24
+ if (interval && interval > 0) {
25
+ pressInterval = setInterval(() => {
26
+ handler();
27
+ }, interval);
28
+ }
29
+ handler();
30
+ pressTimer = null;
31
+ }, delay);
32
+ }
33
+ };
34
+
35
+ // Cancel Timeout
36
+ const cancel = () => {
37
+ if (pressTimer !== null) {
38
+ clearTimeout(pressTimer);
39
+ pressTimer = null;
40
+ }
41
+ if (pressInterval) {
42
+ clearInterval(pressInterval);
43
+ pressInterval = null;
44
+ }
45
+ };
46
+ // Run Function
47
+ const handler = e => {
48
+ binding.value(e);
49
+ };
50
+
51
+ ["mousedown", "touchstart"].forEach(e => el.addEventListener(e, start));
52
+ ["click", "mouseup", "touchend", "touchcancel"].forEach(e => {
53
+ el.addEventListener(e, cancel);
54
+ });
55
+ }
56
+ });
@@ -0,0 +1,35 @@
1
+ export default {
2
+ methods: {
3
+ _isElementInViewport(el) {
4
+ var rect = el.getBoundingClientRect();
5
+
6
+ return (
7
+ rect.top >= 0 &&
8
+ rect.left >= 0 &&
9
+ rect.bottom <=
10
+ (window.innerHeight ||
11
+ document.documentElement.clientHeight) /*or $(window).height() */ &&
12
+ rect.right <=
13
+ (window.innerWidth ||
14
+ document.documentElement.clientWidth) /*or $(window).width() */
15
+ );
16
+ },
17
+ // From https://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport/7557433#7557433
18
+ $onVisibilityChange(el, callback) {
19
+ const isElementInViewport = this._isElementInViewport;
20
+ var old_visible;
21
+ const handler = function() {
22
+ var visible = isElementInViewport(el);
23
+ if (visible != old_visible) {
24
+ old_visible = visible;
25
+ callback(el, visible);
26
+ }
27
+ };
28
+
29
+ // Make sure it executes right away (e.g. during onReady())
30
+ handler();
31
+
32
+ return handler;
33
+ }
34
+ }
35
+ };
@@ -0,0 +1,221 @@
1
+ import Hash from "../../utils/hash";
2
+ import Vue from "vue";
3
+
4
+ var jsonLogic = require("json-logic-js");
5
+
6
+ // jsonLogic.add_operation("add_ms", function(a, b) {
7
+ // if (Utils.type.isString(a)) {
8
+ // const newValue = new Date(new Date(a).getTime() + b * 1000);
9
+ // return newValue.toISOString();
10
+ // }
11
+ // return null;
12
+ // });
13
+ export default {
14
+ data: function() {
15
+ return {
16
+ _fieldModels: {},
17
+ fieldName: null,
18
+ fieldModel: null,
19
+
20
+ // Some components do not support null or empty string value, so we need to use an intermediary value.
21
+ // See https://github.com/vuetifyjs/vuetify/issues/8876
22
+ vuetifyEmptyString: "<EMPTY_STRING>"
23
+ };
24
+ },
25
+ computed: {
26
+ display() {
27
+ const conditions = this.spec.showIf;
28
+ if (conditions) {
29
+ return jsonLogic.apply(conditions, this.$data._fieldModels)
30
+ ? this.$displayValue()
31
+ : "none";
32
+ } else {
33
+ return this.$displayValue();
34
+ }
35
+ }
36
+ },
37
+ watch: {
38
+ fieldModel: function(val, oldVal) {
39
+ if (val === this.vuetifyEmptyString) {
40
+ val = "";
41
+ }
42
+ // Make the field property observable for dynamic showing/hiding
43
+ Vue.set(
44
+ this.$data._fieldModels,
45
+ this.fieldName,
46
+ this.$internalizeValue(val)
47
+ );
48
+
49
+ // this.$saveValue(val);
50
+ // Vue.set(this.$data._fieldModels, this.fieldName, val);
51
+ }
52
+ },
53
+ methods: {
54
+ // TODO: Deprecated
55
+ genericStyles(spec) {
56
+ return this.$styles(spec);
57
+ },
58
+ // NOTE: Styles are dynamic, do not save it in $ready().
59
+ $styles(spec) {
60
+ const properties = spec || this.spec;
61
+ const styles = {
62
+ // color: properties.color,
63
+ // "background-color": properties.backgroundColor,
64
+ // "text-align": properties.textAlign
65
+ };
66
+
67
+ Utils.type.ifString(properties.color, val => (styles["color"] = val));
68
+
69
+ Utils.type.ifString(
70
+ properties.backgroundColor,
71
+ val => (styles["background-color"] = val)
72
+ );
73
+
74
+ Utils.type.ifString(
75
+ properties.textAlign,
76
+ val => (styles["text-align"] = val)
77
+ );
78
+
79
+ // const padding = properties.padding;
80
+ // if (Utils.type.isObject(padding)) {
81
+ // Utils.type.ifNumber(
82
+ // padding.top,
83
+ // top => (styles["padding-top"] = `${top}px`)
84
+ // );
85
+ // Utils.type.ifNumber(
86
+ // padding.bottom,
87
+ // bottom => (styles["padding-bottom"] = `${bottom}px`)
88
+ // );
89
+ // Utils.type.ifNumber(
90
+ // padding.left,
91
+ // left => (styles["padding-left"] = `${left}px`)
92
+ // );
93
+ // Utils.type.ifNumber(
94
+ // padding.right,
95
+ // right => (styles["padding-right"] = `${right}px`)
96
+ // );
97
+ // }
98
+
99
+ Utils.type.ifObject(properties.padding, padding => {
100
+ Utils.type.ifNumber(
101
+ padding.top,
102
+ top => (styles["padding-top"] = `${top}px`)
103
+ );
104
+ Utils.type.ifNumber(
105
+ padding.bottom,
106
+ bottom => (styles["padding-bottom"] = `${bottom}px`)
107
+ );
108
+ Utils.type.ifNumber(
109
+ padding.left,
110
+ left => (styles["padding-left"] = `${left}px`)
111
+ );
112
+ Utils.type.ifNumber(
113
+ padding.right,
114
+ right => (styles["padding-right"] = `${right}px`)
115
+ );
116
+ });
117
+
118
+ Utils.type.ifString(
119
+ this.$length(properties.width),
120
+ val => (styles["width"] = val)
121
+ );
122
+ Utils.type.ifString(
123
+ this.$length(properties.height),
124
+ val => (styles["height"] = val)
125
+ );
126
+
127
+ Utils.type.ifObject(
128
+ properties.onClick,
129
+ () => (styles["cursor"] = "pointer")
130
+ );
131
+
132
+ // This is the main reason styles have to be used in a dynamic way.
133
+ this._updateDisplay(styles, properties);
134
+
135
+ return new Hash(styles);
136
+ },
137
+ $length: function(length) {
138
+ if (Utils.type.isString(length) || Utils.type.isNumber(length)) {
139
+ switch (length) {
140
+ case "wrapContent":
141
+ return null;
142
+ case "matchParent":
143
+ return "100%";
144
+ default:
145
+ return `${length}px`;
146
+ }
147
+ }
148
+ return null;
149
+ },
150
+ $builtinColor(styleClasses) {
151
+ let color = null;
152
+ Utils.type.ifArray(styleClasses, classes => {
153
+ for (const val of ["success", "info", "warning", "error"]) {
154
+ if (classes.remove(val)) {
155
+ color = val;
156
+ }
157
+ }
158
+ });
159
+ return color;
160
+ },
161
+ _updateDisplay(styles, properties) {
162
+ Utils.type.ifObject(
163
+ properties.showIf,
164
+ () => (styles["display"] = this.display)
165
+ );
166
+ Utils.type.ifObject(properties.valueIf, logic => {
167
+ const newValue = jsonLogic.apply(logic, this.$data._fieldModels);
168
+ this.fieldModel = this._sanitizeValue(this.$externalizeValue(newValue));
169
+ });
170
+ },
171
+ $displayValue() {
172
+ return "block"; // To be overridden
173
+ },
174
+ _sanitizeValue(val) {
175
+ return Utils.type.isNotNull(val) ? this.$sanitizeValue(val) : null;
176
+ },
177
+ $sanitizeValue(val) {
178
+ return val; // To be overridden
179
+ },
180
+ $internalizeValue(val) {
181
+ return val;
182
+ },
183
+ $externalizeValue(val) {
184
+ return val;
185
+ },
186
+ _linkFieldModels() {
187
+ const hasCondition = this.spec && this.spec.showIf;
188
+ const name = Utils.app.vueName(this);
189
+ const isField = name && name.startsWith("fields-");
190
+ if (hasCondition || isField) {
191
+ const form = this.$closest("panels-form");
192
+ if (form != null) {
193
+ this.$data._fieldModels = form.$data._fieldModels;
194
+ }
195
+
196
+ // Has to be executed before $ready(). This executes regardless of whether a form is found because fields
197
+ // may be used without a form.
198
+ this.fieldName = this.spec.name;
199
+ this.fieldModel = this._sanitizeValue(this.spec.value);
200
+ }
201
+ },
202
+ $classes(spec) {
203
+ const properties = spec || this.spec;
204
+ const componentName = Utils.app.componentName(properties.view);
205
+ const classes = (properties.styleClasses || []).concat(componentName);
206
+
207
+ Utils.type.ifArray(properties.styleClasses, val => {
208
+ if (val.includes("card")) {
209
+ classes.push("v-card");
210
+ classes.push("v-sheet");
211
+ classes.push("theme--light");
212
+
213
+ if (val.includes("outlined")) {
214
+ classes.push("v-sheet--outlined");
215
+ }
216
+ }
217
+ });
218
+ return classes;
219
+ }
220
+ }
221
+ };
@@ -0,0 +1,131 @@
1
+ export default {
2
+ data: function() {
3
+ return {
4
+ topScrollHandler: null,
5
+ bottomScrollHandler: null,
6
+ nextPageUrl: null,
7
+ prevPageUrl: null,
8
+ request: null,
9
+ infiniteScroll: null
10
+ };
11
+ },
12
+ computed: {
13
+ bottomAnchorStyles() {
14
+ return {
15
+ display: this.infiniteScroll && this.nextPageUrl ? "block" : "none"
16
+ };
17
+ }
18
+ },
19
+ methods: {
20
+ enableInfiniteScrollIfApplicable: function() {
21
+ this.$removeViewportChangeListeners(this.topScrollHandler);
22
+ this.$removeViewportChangeListeners(this.bottomScrollHandler);
23
+
24
+ const prevPage = this.spec.prevPage || {};
25
+ const nextPage = this.spec.nextPage || {};
26
+
27
+ this.infiniteScroll = nextPage.autoload == "asNeeded";
28
+ const onScrollToBottom = this.spec.onScrollToBottom;
29
+ const onScrollToTop = this.spec.onScrollToTop;
30
+
31
+ if (this.infiniteScroll) {
32
+ this.nextPageUrl = nextPage.url;
33
+ this.prevPageUrl = prevPage.url;
34
+ }
35
+
36
+ if (this.nextPageUrl || onScrollToBottom) {
37
+ this._registerBottomScroll(onScrollToBottom);
38
+ }
39
+
40
+ if (this.prevPageUrl || onScrollToTop) {
41
+ this._registerTopScroll(onScrollToTop);
42
+ }
43
+ },
44
+ _registerTopScroll(onScrollToTop) {
45
+ // TODO: Consider adding support for prevPageUrl
46
+ this.topScrollHandler = this.$onVisibilityChange(
47
+ this.$refs.topAnchor,
48
+ (el, visible) => {
49
+ if (visible) {
50
+ this._handleTopScroll(onScrollToTop);
51
+ }
52
+ }
53
+ );
54
+
55
+ this.$addViewportChangeListeners(this.topScrollHandler);
56
+ // this.topScrollHandler();
57
+ },
58
+ _handleTopScroll(onScrollToTop) {
59
+ GLib.action.execute(onScrollToTop, null, this);
60
+ },
61
+ _registerBottomScroll(onScrollToBottom) {
62
+ this.bottomScrollHandler = this.$onVisibilityChange(
63
+ this.$refs.bottomAnchor,
64
+ (el, visible) => {
65
+ if (visible) {
66
+ this._handleBottomScroll(onScrollToBottom);
67
+ }
68
+ }
69
+ );
70
+
71
+ this.$addViewportChangeListeners(this.bottomScrollHandler);
72
+ // NOTE: Right now there is an issue where after popping to previus page, the page auto-loads from the beginning
73
+ // again, so we get duplicate rows.
74
+ // this.bottomScrollHandler();
75
+ },
76
+ _handleBottomScroll(onScrollToBottom) {
77
+ if (this.nextPageUrl) {
78
+ this.request = Utils.http.execute(
79
+ { url: this.nextPageUrl },
80
+ "GET",
81
+ this,
82
+ response => {
83
+ const nextPage = response.nextPage;
84
+ if (this.$type.isObject(nextPage)) {
85
+ this.nextPageUrl = response.nextPage.url;
86
+ } else {
87
+ this.nextPageUrl = null;
88
+ }
89
+
90
+ for (const section of response.sections) {
91
+ this.sections.push(section);
92
+ }
93
+ Utils.history.updatePage();
94
+ }
95
+ );
96
+ }
97
+
98
+ GLib.action.execute(onScrollToBottom, null, this);
99
+ },
100
+ autoloadAll(nextPage) {
101
+ const vm = this;
102
+
103
+ if (!this.$type.isObject(nextPage)) {
104
+ return;
105
+ }
106
+ if (nextPage.autoload !== "all") {
107
+ return;
108
+ }
109
+
110
+ let nextPageUrl = nextPage.url;
111
+
112
+ this.request = Utils.http.execute(
113
+ { url: nextPageUrl },
114
+ "GET",
115
+ vm,
116
+ function(response) {
117
+ for (const section of response.sections) {
118
+ vm.sections.push(section);
119
+ }
120
+ vm.autoloadAll(response.nextPage);
121
+ }
122
+ );
123
+ },
124
+ cancelAutoloadRequest() {
125
+ // Avoid old data coming in when this component gets reused.
126
+ if (this.request) {
127
+ this.request.cancel();
128
+ }
129
+ }
130
+ }
131
+ };
@@ -0,0 +1,52 @@
1
+ export default {
2
+ data: function () {
3
+ return {
4
+ exportable: false,
5
+ exportLabel: 'CSV',
6
+ exportFile: 'output',
7
+ }
8
+ },
9
+ methods: {
10
+ initCsvExport() {
11
+ let exportName = 'output'
12
+ const vm = this
13
+ Utils.type.ifObject(this.spec.export, obj => {
14
+ vm.exportable = true
15
+
16
+ Utils.type.ifString(obj.label, val => {
17
+ vm.exportLabel = val
18
+ })
19
+ Utils.type.ifString(obj.fileName, val => {
20
+ exportName = val
21
+ })
22
+ })
23
+
24
+ this.exportFile = `${exportName}.csv`
25
+ },
26
+ exportCsv(section) {
27
+ return 'data:text/csv;charset=' + document.characterSet + ',' + encodeURI(this._compileCsvRows(section));
28
+ },
29
+ _compileCsvRows(section) {
30
+ const lines = []
31
+ lines.push(this._compileCsvRow(section.header))
32
+ for (const row of section.rows) {
33
+ lines.push(this._compileCsvRow(row))
34
+ }
35
+ return lines.join("\n")
36
+ },
37
+ _compileCsvRow(row) {
38
+ return row.cellViews.map(view => this._escapeForCsv(view.text)).join(",")
39
+ },
40
+ _escapeForCsv(text) {
41
+ if (Utils.type.isString(text)) {
42
+ if (text === "") {
43
+ return '""'
44
+ } else if (text.contains('"') || text.contains("\n") || text.contains("\r") || text.contains(",")) {
45
+ return '"' + text.replace(/"/g, '""') + '"'
46
+ }
47
+ return text
48
+ }
49
+ return '""'
50
+ },
51
+ }
52
+ }