glib-web 2.5.1 → 2.6.1

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 (62) hide show
  1. package/LICENSE +0 -0
  2. package/action.js +6 -4
  3. package/actions/auth/restart.js +0 -0
  4. package/actions/components/update.js +0 -15
  5. package/actions/dialogs/oauth.js +0 -0
  6. package/actions/dialogs/options.js +0 -0
  7. package/actions/panels/scrollTo.js +4 -2
  8. package/actions/tours/start.js +10 -1
  9. package/actions/tours/stop.js +7 -0
  10. package/app.vue +24 -3
  11. package/components/_button.vue +7 -3
  12. package/components/_message.vue +0 -0
  13. package/components/_responsive.vue +14 -14
  14. package/components/component.vue +43 -12
  15. package/components/datetime.vue +0 -0
  16. package/components/fab.vue +0 -0
  17. package/components/fields/check.vue +1 -11
  18. package/components/fields/country/countries.js +0 -0
  19. package/components/fields/country/field.vue +0 -0
  20. package/components/fields/country/regions.js +0 -0
  21. package/components/fields/datetime.vue +0 -0
  22. package/components/fields/dynamicSelect.vue +0 -0
  23. package/components/fields/file.vue +31 -8
  24. package/components/fields/otpField.vue +58 -17
  25. package/components/fields/radioGroup.vue +1 -5
  26. package/components/fields/richText.vue +29 -43
  27. package/components/fields/text.vue +2 -16
  28. package/components/fields/textarea.vue +7 -1
  29. package/components/fields/timeZone.vue +0 -0
  30. package/components/hr.vue +0 -0
  31. package/components/html.vue +0 -0
  32. package/components/mixins/events.js +37 -19
  33. package/components/mixins/longClick.js +0 -0
  34. package/components/mixins/scrolling.js +0 -0
  35. package/components/mixins/table/export.js +0 -0
  36. package/components/mixins/table/import.js +0 -0
  37. package/components/p.vue +0 -0
  38. package/components/panels/form.vue +13 -12
  39. package/components/panels/horizontal.vue +26 -22
  40. package/components/panels/list.vue +7 -3
  41. package/components/panels/split.vue +1 -1
  42. package/components/panels/vertical.vue +14 -14
  43. package/extensions/string.js +18 -0
  44. package/keys.js +0 -0
  45. package/nav/dialog.vue +78 -15
  46. package/nav/drawerButton.vue +0 -0
  47. package/package.json +1 -1
  48. package/plugins/updatableComponent.js +7 -1
  49. package/settings.json.example +0 -0
  50. package/styles/test.sass +0 -0
  51. package/styles/test.scss +0 -0
  52. package/templates/thumbnail.vue +83 -80
  53. package/templates/unsupported.vue +0 -0
  54. package/utils/component.js +12 -0
  55. package/utils/dom.js +0 -0
  56. package/utils/http.js +5 -2
  57. package/utils/launch.js +8 -0
  58. package/utils/public.js +4 -0
  59. package/utils/queue.js +0 -8
  60. package/utils/settings.js +7 -0
  61. package/utils/storage.js +0 -0
  62. package/utils/url.js +0 -0
package/LICENSE CHANGED
File without changes
package/action.js CHANGED
@@ -53,6 +53,7 @@ import ActionCommandsCustom from "./actions/commands/custom";
53
53
  import ActionCommandsEnqueue from "./actions/commands/enqueue";
54
54
 
55
55
  import ActionToursStart from "./actions/tours/start";
56
+ import ActionToursStop from "./actions/tours/stop";
56
57
 
57
58
  import ActionComponentsUpdate from "./actions/components/update";
58
59
 
@@ -110,6 +111,7 @@ const actions = {
110
111
  "commands/enqueue": ActionCommandsEnqueue,
111
112
 
112
113
  "tours/start": ActionToursStart,
114
+ "tours/stop": ActionToursStop,
113
115
  "components/update": ActionComponentsUpdate
114
116
  };
115
117
 
@@ -170,10 +172,10 @@ export default class Action {
170
172
  }
171
173
  action.execute(spec, component, params);
172
174
  } catch (e) {
173
- console.error(
174
- "Failed executing command",
175
- actionName,
176
- `Error: '${e.message}'`
175
+ GLib.settings.errorHandler(
176
+ new Error(
177
+ `Failed executing command "${actionName}". Error: ${e.message}`
178
+ )
177
179
  );
178
180
  }
179
181
  }
File without changes
@@ -1,5 +1,3 @@
1
- import Vue from "vue";
2
-
3
1
  export default class {
4
2
  execute(spec, component) {
5
3
  if (!spec.views.length > 1) {
@@ -12,17 +10,4 @@ export default class {
12
10
  target.$recursiveUpdate();
13
11
  }
14
12
  }
15
-
16
- // // TODO: Use $recursiveUpdate(). See mixins/events
17
- // updateComponent(component) {
18
- // component.$ready();
19
- // component.$forceUpdate();
20
-
21
- // // Execute on next tick to ensure that the child has received the updated spec.
22
- // Vue.nextTick(() => {
23
- // component.$children.find(child => {
24
- // this.updateComponent(child);
25
- // });
26
- // });
27
- // }
28
13
  }
File without changes
File without changes
@@ -1,7 +1,9 @@
1
1
  // Scroll the main body of the current window
2
2
  export default class {
3
- execute(properties) {
4
- const pageBody = Utils.history._pageBody;
3
+ execute(properties, component) {
4
+ const pageBody =
5
+ Utils.launch.dialog.closestBody(component) || Utils.history._pageBody;
6
+
5
7
  const selector = `#${properties.viewId}`;
6
8
  console.log("Scrolling to", selector);
7
9
  const element = pageBody.querySelector(selector);
@@ -1,9 +1,11 @@
1
1
  import Driver from "driver.js";
2
2
  import "driver.js/dist/driver.min.css";
3
3
 
4
+ let driver = null;
5
+
4
6
  export default class {
5
7
  execute(spec, component) {
6
- let driver = new Driver(spec.options || {});
8
+ driver = new Driver(spec.options || {});
7
9
  let steps = spec.steps;
8
10
  steps
9
11
  .filter(value => value.customBehavior)
@@ -14,4 +16,11 @@ export default class {
14
16
  driver.defineSteps(steps);
15
17
  driver.start(spec.startFrom || 0);
16
18
  }
19
+
20
+ static stopTour() {
21
+ if (driver) {
22
+ driver.reset();
23
+ driver = null;
24
+ }
25
+ }
17
26
  }
@@ -0,0 +1,7 @@
1
+ import tour from "./start.js";
2
+
3
+ export default class {
4
+ execute(spec, component) {
5
+ tour.stopTour();
6
+ }
7
+ }
package/app.vue CHANGED
@@ -125,15 +125,15 @@ export default {
125
125
  console.warn("Analytics not setup. Set `settings.gtagId`.");
126
126
  }
127
127
 
128
+ // Use setTimeout() to wait until page is rendered. Don't use nextTick() because
129
+ // it would execute much earlier (before all components finish initializing).
128
130
  if (Utils.history.isPoppedState(this.page)) {
129
131
  setTimeout(() => {
130
- // Wait until page is rendered
131
132
  GLib.action.execute(this.page.onRefocus, this);
132
133
  GLib.action.execute(this.page.replayGetResponse, this);
133
134
  });
134
135
  } else {
135
136
  setTimeout(() => {
136
- // Wait until page is rendered
137
137
  GLib.action.execute(this.page.onLoad, this);
138
138
  });
139
139
  }
@@ -194,8 +194,29 @@ body,
194
194
  .glib-scrollto--highlighted {
195
195
  background: yellow !important;
196
196
  }
197
- .glib-clickable {
197
+ // Don't override the default button's effect.
198
+ .glib-clickable:not(.v-btn) {
198
199
  cursor: pointer;
200
+
201
+ // // So that we can display a semi-transparent layer on hover (see below)
202
+ position: relative;
203
+
204
+ &:hover:before {
205
+ content: "\A";
206
+ width: 100%;
207
+ height: 100%;
208
+ background: rgba(100, 100, 100, 0.1);
209
+ position: absolute;
210
+ top: 0;
211
+ left: 0;
212
+ }
213
+
214
+ &:active:before {
215
+ background: rgba(100, 100, 100, 0.2);
216
+ }
217
+ }
218
+ .glib-clickable.theme--light.v-list-item:hover:before {
219
+ opacity: 1; // Override Vuetify
199
220
  }
200
221
  /******/
201
222
  </style>
@@ -6,11 +6,11 @@
6
6
  :type="type"
7
7
  :disabled="disabled || $isBusy || spec.disabled"
8
8
  :style="styles()"
9
- :class="$classes()"
9
+ :class="classes()"
10
10
  :href="$href()"
11
11
  :rel="$rel()"
12
12
  :text="linkStyling || $classes().includes('text')"
13
- :small="linkStyling"
13
+ :small="linkStyling || $classes().includes('small')"
14
14
  :icon="$classes().includes('icon')"
15
15
  :outlined="$classes().includes('outlined')"
16
16
  :tile="$classes().includes('tile')"
@@ -50,12 +50,16 @@ export default {
50
50
  });
51
51
  },
52
52
  styles() {
53
- const styles = this.genericStyles();
53
+ const styles = this.$styles();
54
54
  if (this.linkStyling) {
55
55
  styles["color"] = styles["color"] || "#1976d2";
56
56
  }
57
57
  return styles;
58
58
  },
59
+ classes() {
60
+ const classes = this.$classes();
61
+ return classes;
62
+ },
59
63
  $registryEnabled() {
60
64
  return false;
61
65
  }
File without changes
@@ -94,21 +94,21 @@ a.panels-responsive {
94
94
  color: inherit;
95
95
  text-decoration: inherit;
96
96
 
97
- // So that we can display a semi-transparent layer on hover (see below)
98
- position: relative;
97
+ // // So that we can display a semi-transparent layer on hover (see below)
98
+ // position: relative;
99
99
 
100
- &:hover:after {
101
- content: "\A";
102
- width: 100%;
103
- height: 100%;
104
- background: rgba(0, 0, 0, 0.1);
105
- position: absolute;
106
- top: 0;
107
- left: 0;
108
- }
100
+ // &:hover:after {
101
+ // content: "\A";
102
+ // width: 100%;
103
+ // height: 100%;
104
+ // background: rgba(0, 0, 0, 0.1);
105
+ // position: absolute;
106
+ // top: 0;
107
+ // left: 0;
108
+ // }
109
109
 
110
- &:active:after {
111
- background: rgba(0, 0, 0, 0.4);
112
- }
110
+ // &:active:after {
111
+ // background: rgba(0, 0, 0, 0.4);
112
+ // }
113
113
  }
114
114
  </style>
@@ -1,10 +1,31 @@
1
1
  <template>
2
- <fields-text v-if="name == 'fields-text'" :spec="spec" type="text" />
3
- <fields-text v-else-if="name == 'fields-number'" :spec="spec" type="number" />
4
- <fields-text v-else-if="name == 'fields-email'" :spec="spec" type="email" />
5
- <fields-text v-else-if="name == 'fields-url'" :spec="spec" type="url" />
2
+ <fields-text
3
+ v-if="name == 'fields-text'"
4
+ ref="delegate"
5
+ :spec="spec"
6
+ type="text"
7
+ />
8
+ <fields-text
9
+ v-else-if="name == 'fields-number'"
10
+ ref="delegate"
11
+ :spec="spec"
12
+ type="number"
13
+ />
14
+ <fields-text
15
+ v-else-if="name == 'fields-email'"
16
+ ref="delegate"
17
+ :spec="spec"
18
+ type="email"
19
+ />
20
+ <fields-text
21
+ v-else-if="name == 'fields-url'"
22
+ ref="delegate"
23
+ :spec="spec"
24
+ type="url"
25
+ />
6
26
  <fields-text
7
27
  v-else-if="name == 'fields-password'"
28
+ ref="delegate"
8
29
  :spec="spec"
9
30
  type="password"
10
31
  />
@@ -21,12 +42,19 @@
21
42
  <!-- <fields-latLong v-else-if="spec.view == 'fields/latLong-v1'" :spec="spec" /> -->
22
43
  <fields-googlePlace
23
44
  v-else-if="spec.view == 'fields/googlePlace-v1'"
45
+ ref="delegate"
24
46
  :spec="spec"
25
47
  />
26
48
 
27
49
  <!-- <panels-responsive v-else-if="spec.view == 'panels/scroll-v1'" :spec="spec" /> -->
28
50
 
29
- <component :is="name" v-else-if="name" :id="spec.id" :spec="spec" />
51
+ <component
52
+ :is="name"
53
+ v-else-if="name"
54
+ :id="spec.id"
55
+ ref="delegate"
56
+ :spec="spec"
57
+ />
30
58
 
31
59
  <div v-else>Unsupported view: {{ spec.view }}</div>
32
60
  </template>
@@ -216,13 +244,13 @@ export default {
216
244
  name: null
217
245
  };
218
246
  },
219
- beforeUpdate() {
220
- // NOTE: Not sure what this is for
221
- // Make sure vuejs will not attempt to render old data.
222
- // if (this._mountedUrl !== window.location.href) {
223
- // this.name = null;
224
- // }
225
- },
247
+ // beforeUpdate() {
248
+ // // NOTE: Not sure what this is for
249
+ // // Make sure vuejs will not attempt to render old data.
250
+ // // if (this._mountedUrl !== window.location.href) {
251
+ // // this.name = null;
252
+ // // }
253
+ // },
226
254
  methods: {
227
255
  $ready() {
228
256
  const name = Utils.app.componentName(this.spec.view);
@@ -235,6 +263,9 @@ export default {
235
263
  }
236
264
  }
237
265
  },
266
+ $update() {
267
+ this.$refs.delegate.$update();
268
+ },
238
269
  $registryEnabled() {
239
270
  return false;
240
271
  }
File without changes
File without changes
@@ -58,17 +58,7 @@ export default {
58
58
  );
59
59
  }, 100);
60
60
 
61
- // if (this.spec.submitOnChange) {
62
- // setTimeout(() => {
63
- // this.$dispatchEvent("forms/submit");
64
- // }, 200);
65
- // }
66
-
67
- Utils.type.ifObject(this.spec.onChange, onChange => {
68
- this.$nextTick(() => {
69
- GLib.action.execute(onChange, this);
70
- });
71
- });
61
+ this.$executeOnChange();
72
62
  },
73
63
  $internalizeValue(val) {
74
64
  if (val == this.spec.checkValue) {
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -2,14 +2,28 @@
2
2
  <div ref="fileUploadContainer" class="mb-3" :style="$styles()">
3
3
  <label class="v-label v-label--active">{{ spec.label }}</label>
4
4
  <div class="preview-container">
5
- <v-avatar v-if="placeholder.type == 'avatar'" :style="genericStyles(placeholder)" class="mr-4">
5
+ <v-avatar
6
+ v-if="placeholder.type == 'avatar'"
7
+ :style="genericStyles(placeholder)"
8
+ class="mr-4"
9
+ >
6
10
  <img :src="fileImage || placeholder.url" />
7
11
  </v-avatar>
8
- <img v-else-if="placeholder.type == 'image'" class="square-image mr-4" :style="genericStyles(placeholder)"
9
- :src="fileImage || placeholder.url" />
10
-
11
- <v-text-field v-else-if="placeholder.type == 'input'" :value="fileTitle" outlined prominent
12
- placholder="Upload your file" disabled />
12
+ <img
13
+ v-else-if="placeholder.type == 'image'"
14
+ class="square-image mr-4"
15
+ :style="genericStyles(placeholder)"
16
+ :src="fileImage || placeholder.url"
17
+ />
18
+
19
+ <v-text-field
20
+ v-else-if="placeholder.type == 'input'"
21
+ :value="fileTitle"
22
+ outlined
23
+ prominent
24
+ placholder="Upload your file"
25
+ disabled
26
+ />
13
27
 
14
28
  <span v-else class="mr-4">{{ fileTitle }}</span>
15
29
 
@@ -33,7 +47,12 @@
33
47
  </v-btn>
34
48
  </span>
35
49
  </div>
36
- <input ref="directUploadFile" style="display: none;" type="file" @change="uploadFiles" />
50
+ <input
51
+ ref="directUploadFile"
52
+ style="display: none;"
53
+ type="file"
54
+ @change="uploadFiles"
55
+ />
37
56
 
38
57
  <!-- <input type="file" :name="spec.name" ref='directUploadFile' @change='uploadFiles' v-show='!uploaded'/> -->
39
58
  <v-progress-linear v-if="showProgress" v-model="progress.value" />
@@ -73,7 +92,7 @@ export default {
73
92
  };
74
93
  },
75
94
  computed: {
76
- showProgress: function () {
95
+ showProgress: function() {
77
96
  return this.progress.value >= 0;
78
97
  }
79
98
  },
@@ -129,6 +148,10 @@ export default {
129
148
  this.uploaded = true;
130
149
  this.progress.value = -1;
131
150
  this.displayImagePreview(file, blob);
151
+
152
+ // This only works for single uploads. For multi-uploads, we'll need to make sure
153
+ // that all uploads have finished successfully.
154
+ this.$executeOnChange();
132
155
  }
133
156
 
134
157
  input.disabled = false;
@@ -1,18 +1,40 @@
1
1
  <template>
2
2
  <div>
3
- <input
4
- v-for="(digit, index) in digits"
5
- ref="input"
6
- :key="index"
7
- v-model="otp[index]"
8
- maxlength="1"
9
- class="otp-input"
10
- @input="handleInput($event, index)"
11
- @keydown="handleKeydown($event, index)"
12
- @paste="handlePaste($event, index)"
13
- @focus="handleFocus($event, index)"
14
- @blur="handleBlur($event, index)"
15
- />
3
+ <div v-if="spec.type === 'text'">
4
+ <input
5
+ v-for="(digit, index) in digits"
6
+ ref="input"
7
+ :key="index"
8
+ v-model="otp[index]"
9
+ type="text"
10
+ maxlength="1"
11
+ class="otp-input"
12
+ @input="handleInput($event, index)"
13
+ @keydown="handleKeydown($event, index)"
14
+ @paste="handlePaste($event, index)"
15
+ @focus="handleFocus($event, index)"
16
+ @blur="handleBlur($event, index)"
17
+ @click="handleClick($event)"
18
+ />
19
+ </div>
20
+ <div v-else>
21
+ <input
22
+ v-for="(digit, index) in digits"
23
+ ref="input"
24
+ :key="index"
25
+ v-model="otp[index]"
26
+ type="number"
27
+ oninput="javascript: if (this.value.length > this.maxLength) this.value = this.value.slice(0, this.maxLength);"
28
+ maxlength="1"
29
+ class="otp-input"
30
+ @input="handleInput($event, index)"
31
+ @keydown="handleKeydown($event, index)"
32
+ @paste="handlePaste($event, index)"
33
+ @focus="handleFocus($event, index)"
34
+ @blur="handleBlur($event, index)"
35
+ @click="handleClick($event)"
36
+ />
37
+ </div>
16
38
  <input type="hidden" :name="spec.name" :value="otpValue" />
17
39
  </div>
18
40
  </template>
@@ -37,8 +59,8 @@ export default {
37
59
  },
38
60
  methods: {
39
61
  $ready() {
40
- this.digits = this.spec.lengths;
41
- this.otp = Array(this.spec.lengths).fill("");
62
+ this.digits = this.spec.length;
63
+ this.otp = Array(this.spec.length).fill("");
42
64
  },
43
65
  handleInput(event, index) {
44
66
  if (event.target.value.length === 1) {
@@ -48,8 +70,12 @@ export default {
48
70
  handleKeydown(event, index) {
49
71
  if (event.key === "Backspace") {
50
72
  event.preventDefault();
51
- this.focusPrevious(index);
52
- this.$set(this.otp, index, "");
73
+ if (this.otp[index] !== "") {
74
+ this.$set(this.otp, index, "");
75
+ } else {
76
+ this.focusPrevious(index);
77
+ this.$set(this.otp, index - 1, "");
78
+ }
53
79
  }
54
80
  },
55
81
  handlePaste(event, index) {
@@ -81,6 +107,9 @@ export default {
81
107
  if (index > 0) {
82
108
  this.$refs.input[index - 1].focus();
83
109
  }
110
+ },
111
+ handleClick(event) {
112
+ event.target.select();
84
113
  }
85
114
  }
86
115
  };
@@ -95,4 +124,16 @@ export default {
95
124
  font-size: 24px;
96
125
  margin: 8px;
97
126
  }
127
+
128
+ /* Chrome, Safari, Edge, Opera */
129
+ input::-webkit-outer-spin-button,
130
+ input::-webkit-inner-spin-button {
131
+ -webkit-appearance: none;
132
+ margin: 0;
133
+ }
134
+
135
+ /* Firefox */
136
+ input[type="number"] {
137
+ -moz-appearance: textfield;
138
+ }
98
139
  </style>
@@ -34,11 +34,7 @@ export default {
34
34
  },
35
35
  methods: {
36
36
  onChange() {
37
- Utils.type.ifObject(this.spec.onChange, onChange => {
38
- this.$nextTick(() => {
39
- GLib.action.execute(onChange, this);
40
- });
41
- });
37
+ this.$executeOnChange();
42
38
  },
43
39
  updateValue(variable) {
44
40
  if (variable.value) {