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