glib-web 2.4.1 → 2.5.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 (53) hide show
  1. package/LICENSE +0 -0
  2. package/action.js +2 -0
  3. package/actions/auth/restart.js +0 -0
  4. package/actions/commands/enqueue.js +17 -0
  5. package/actions/components/update.js +12 -13
  6. package/actions/dialogs/oauth.js +0 -0
  7. package/actions/dialogs/options.js +0 -0
  8. package/app.vue +3 -0
  9. package/components/_message.vue +0 -0
  10. package/components/component.vue +2 -0
  11. package/components/datetime.vue +0 -0
  12. package/components/fab.vue +0 -0
  13. package/components/fields/country/countries.js +0 -0
  14. package/components/fields/country/field.vue +0 -0
  15. package/components/fields/country/regions.js +0 -0
  16. package/components/fields/datetime.vue +0 -0
  17. package/components/fields/dynamicSelect.vue +0 -0
  18. package/components/fields/file.vue +12 -18
  19. package/components/fields/otpField.vue +98 -0
  20. package/components/fields/text.vue +14 -5
  21. package/components/fields/timeZone.vue +0 -0
  22. package/components/hr.vue +0 -0
  23. package/components/html.vue +0 -0
  24. package/components/map.vue +115 -29
  25. package/components/mixins/events.js +11 -0
  26. package/components/mixins/longClick.js +0 -0
  27. package/components/mixins/scrolling.js +0 -0
  28. package/components/mixins/styles.js +8 -4
  29. package/components/mixins/table/export.js +0 -0
  30. package/components/mixins/table/import.js +0 -0
  31. package/components/p.vue +0 -0
  32. package/components/panels/custom.vue +3 -0
  33. package/components/panels/horizontal.vue +134 -7
  34. package/components/panels/list.vue +34 -18
  35. package/components/panels/responsive.vue +10 -6
  36. package/components/panels/vertical.vue +1 -1
  37. package/keys.js +0 -0
  38. package/nav/drawerButton.vue +0 -0
  39. package/package.json +2 -2
  40. package/plugins/updatableComponent.js +0 -6
  41. package/settings.json.example +0 -0
  42. package/styles/test.sass +0 -0
  43. package/styles/test.scss +0 -0
  44. package/templates/thumbnail.vue +34 -11
  45. package/templates/unsupported.vue +0 -0
  46. package/utils/dom.js +0 -0
  47. package/utils/mime_type.js +2 -0
  48. package/utils/public.js +6 -0
  49. package/utils/queue.js +112 -0
  50. package/utils/settings.js +0 -0
  51. package/utils/storage.js +0 -0
  52. package/utils/uploader.js +3 -0
  53. package/utils/url.js +0 -0
package/LICENSE CHANGED
File without changes
package/action.js CHANGED
@@ -50,6 +50,7 @@ import ActionsAnalyticsLogEvent from "./actions/analytics/logEvent";
50
50
 
51
51
  import ActionCommandsCopy from "./actions/commands/copy";
52
52
  import ActionCommandsCustom from "./actions/commands/custom";
53
+ import ActionCommandsEnqueue from "./actions/commands/enqueue";
53
54
 
54
55
  import ActionToursStart from "./actions/tours/start";
55
56
 
@@ -106,6 +107,7 @@ const actions = {
106
107
 
107
108
  "commands/copy": ActionCommandsCopy,
108
109
  "commands/custom": ActionCommandsCustom,
110
+ "commands/enqueue": ActionCommandsEnqueue,
109
111
 
110
112
  "tours/start": ActionToursStart,
111
113
  "components/update": ActionComponentsUpdate
File without changes
@@ -0,0 +1,17 @@
1
+ // import Hash from "../../utils/hash";
2
+
3
+ export default class {
4
+ // async executeJob(spec, component) {
5
+ // console.log("Waiting for next job1...");
6
+ // GLib.action.execute(spec.onExecute, component);
7
+ // await this.sleep(2000);
8
+ // console.log("Waiting for next job2...");
9
+ // }
10
+ execute(spec, component) {
11
+ GLib.queue.enqueue(() => {
12
+ GLib.action.execute(spec.onExecute, component);
13
+ // console.log("Waiting for next job0...");
14
+ // this.executeJob(spec, component);
15
+ });
16
+ }
17
+ }
@@ -5,25 +5,24 @@ export default class {
5
5
  if (!spec.views.length > 1) {
6
6
  console.warn("Make sure views only have 1 child!");
7
7
  }
8
- // const target = component.updatables[spec.targetId];
9
- // if (!target) console.error("no component found :" + spec.targetId);
10
8
 
11
9
  const target = GLib.component.findById(spec.targetId);
12
10
  if (target) {
13
11
  Object.assign(target.spec, spec.views[0]);
14
- this.updateComponent(target);
12
+ target.$recursiveUpdate();
15
13
  }
16
14
  }
17
15
 
18
- updateComponent(component) {
19
- component.$ready();
20
- component.$forceUpdate();
16
+ // // TODO: Use $recursiveUpdate(). See mixins/events
17
+ // updateComponent(component) {
18
+ // component.$ready();
19
+ // component.$forceUpdate();
21
20
 
22
- // Execute on next tick to ensure that the child has received the updated spec.
23
- Vue.nextTick(() => {
24
- component.$children.find(child => {
25
- this.updateComponent(child);
26
- });
27
- });
28
- }
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
+ // }
29
28
  }
File without changes
File without changes
package/app.vue CHANGED
@@ -194,6 +194,9 @@ body,
194
194
  .glib-scrollto--highlighted {
195
195
  background: yellow !important;
196
196
  }
197
+ .glib-clickable {
198
+ cursor: pointer;
199
+ }
197
200
  /******/
198
201
  </style>
199
202
 
File without changes
@@ -90,6 +90,7 @@ import CreditCardField from "./fields/creditCard";
90
90
  import RatingField from "./fields/rating";
91
91
  import PhoneField from "./fields/phone/field";
92
92
  import TimerField from "./fields/timer";
93
+ import OtpField from "./fields/otpField";
93
94
 
94
95
  import ScrollPanel from "./panels/scroll";
95
96
  import VerticalPanel from "./panels/vertical";
@@ -179,6 +180,7 @@ export default {
179
180
  "fields-rating": RatingField,
180
181
  "fields-phone": PhoneField,
181
182
  "fields-timer": TimerField,
183
+ "fields-otp": OtpField,
182
184
 
183
185
  "panels-scroll": ScrollPanel,
184
186
  "panels-vertical": VerticalPanel,
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -2,19 +2,15 @@
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
6
- v-if="placeholder.type == 'avatar'"
7
- :style="genericStyles(placeholder)"
8
- class="mr-4"
9
- >
5
+ <v-avatar v-if="placeholder.type == 'avatar'" :style="genericStyles(placeholder)" class="mr-4">
10
6
  <img :src="fileImage || placeholder.url" />
11
7
  </v-avatar>
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
- />
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 />
13
+
18
14
  <span v-else class="mr-4">{{ fileTitle }}</span>
19
15
 
20
16
  <span v-if="spec.uploadText">
@@ -37,12 +33,7 @@
37
33
  </v-btn>
38
34
  </span>
39
35
  </div>
40
- <input
41
- ref="directUploadFile"
42
- style="display: none;"
43
- type="file"
44
- @change="uploadFiles"
45
- />
36
+ <input ref="directUploadFile" style="display: none;" type="file" @change="uploadFiles" />
46
37
 
47
38
  <!-- <input type="file" :name="spec.name" ref='directUploadFile' @change='uploadFiles' v-show='!uploaded'/> -->
48
39
  <v-progress-linear v-if="showProgress" v-model="progress.value" />
@@ -82,7 +73,7 @@ export default {
82
73
  };
83
74
  },
84
75
  computed: {
85
- showProgress: function() {
76
+ showProgress: function () {
86
77
  return this.progress.value >= 0;
87
78
  }
88
79
  },
@@ -165,6 +156,9 @@ export default {
165
156
 
166
157
  <style lang="scss" scoped>
167
158
  .preview-container {
159
+ display: flex;
160
+ align-items: center;
161
+
168
162
  .action-container {
169
163
  padding-left: 10px;
170
164
  }
@@ -0,0 +1,98 @@
1
+ <template>
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
+ />
16
+ <input type="hidden" :name="spec.name" :value="otpValue" />
17
+ </div>
18
+ </template>
19
+
20
+ <script>
21
+ export default {
22
+ props: {
23
+ spec: { type: Object, required: true }
24
+ },
25
+ data() {
26
+ return {
27
+ digits: 0,
28
+ otp: []
29
+ };
30
+ },
31
+
32
+ computed: {
33
+ otpValue() {
34
+ // concatenate the digits into a single string
35
+ return this.otp.join("");
36
+ }
37
+ },
38
+ methods: {
39
+ $ready() {
40
+ this.digits = this.spec.lengths;
41
+ this.otp = Array(this.spec.lengths).fill("");
42
+ },
43
+ handleInput(event, index) {
44
+ if (event.target.value.length === 1) {
45
+ this.focusNext(index);
46
+ }
47
+ },
48
+ handleKeydown(event, index) {
49
+ if (event.key === "Backspace") {
50
+ event.preventDefault();
51
+ this.focusPrevious(index);
52
+ this.$set(this.otp, index, "");
53
+ }
54
+ },
55
+ handlePaste(event, index) {
56
+ event.preventDefault();
57
+ const pasted = event.clipboardData
58
+ .getData("text")
59
+ .slice(0, this.digits - index);
60
+ for (let i = 0; i < pasted.length; i++) {
61
+ this.$set(this.otp, index + i, pasted[i]);
62
+ }
63
+ this.focusNext(index + pasted.length - 1);
64
+ },
65
+ handleFocus(event, index) {
66
+ if (index > 0 && this.otp[index - 1] === "") {
67
+ this.focusPrevious(index);
68
+ }
69
+ },
70
+ handleBlur(event, index) {
71
+ if (this.otp.filter(digit => digit === "").length === 0) {
72
+ this.$emit("complete", this.otp.join(""));
73
+ }
74
+ },
75
+ focusNext(index) {
76
+ if (index < this.digits - 1) {
77
+ this.$refs.input[index + 1].focus();
78
+ }
79
+ },
80
+ focusPrevious(index) {
81
+ if (index > 0) {
82
+ this.$refs.input[index - 1].focus();
83
+ }
84
+ }
85
+ }
86
+ };
87
+ </script>
88
+ <style scoped>
89
+ .otp-input {
90
+ border: 1px solid #47495f;
91
+ text-align: center;
92
+ width: 50px;
93
+ height: 50px;
94
+ border-radius: 4px;
95
+ font-size: 24px;
96
+ margin: 8px;
97
+ }
98
+ </style>
@@ -12,7 +12,7 @@
12
12
  :type="variant.type"
13
13
  :rules="rules"
14
14
  :prepend-inner-icon="leftIconName"
15
- :append-icon="variant.appendIcon"
15
+ :append-icon="rightIconName || variant.appendIcon"
16
16
  :prefix="spec.leftText"
17
17
  :suffix="spec.rightText"
18
18
  :min="spec.min"
@@ -22,7 +22,7 @@
22
22
  :dense="$classes().includes('dense')"
23
23
  :autofocus="spec.autoFocus || false"
24
24
  validate-on-blur
25
- @click:append="onRightIconClick"
25
+ v-on="onRightIconClick ? { 'click:append': onRightIconClick } : null"
26
26
  @input="onChange"
27
27
  />
28
28
  <input
@@ -46,6 +46,7 @@ export default {
46
46
  return {
47
47
  variant: {},
48
48
  rules: [],
49
+ onRightIconClick: null,
49
50
  fields: {
50
51
  email: {
51
52
  type: "email",
@@ -104,12 +105,23 @@ export default {
104
105
  const icon = this.spec.leftIcon || {};
105
106
  const materialIcon = icon.material || {};
106
107
  return materialIcon.name;
108
+ },
109
+ rightIconName() {
110
+ const icon = this.spec.rightIcon || {};
111
+ const materialIcon = icon.material || {};
112
+ return materialIcon.name;
107
113
  }
108
114
  },
109
115
  methods: {
110
116
  $ready() {
111
117
  this.variant = this.fields[this.type] || {};
112
118
  this.rules = this.$validation(this.variant.rules);
119
+
120
+ if (this.variant.onRightIconClick) {
121
+ this.onRightIconClick = () => {
122
+ this.variant.onRightIconClick(this);
123
+ };
124
+ }
113
125
  },
114
126
  togglePasswordVisibility() {
115
127
  const passwordField = this.fields["password"];
@@ -121,9 +133,6 @@ export default {
121
133
  passwordField.appendIcon = "visibility";
122
134
  }
123
135
  },
124
- onRightIconClick() {
125
- this.variant.onRightIconClick(this);
126
- },
127
136
  classes() {
128
137
  return this.$classes().concat("g-text-field--hintless");
129
138
  },
File without changes
package/components/hr.vue CHANGED
File without changes
File without changes
@@ -1,5 +1,4 @@
1
1
  <template>
2
- <!-- <div ref="map" :style="genericStyles()"></div> -->
3
2
  <gmap-map
4
3
  ref="map"
5
4
  :center="center"
@@ -43,19 +42,48 @@
43
42
  </gmap-marker>
44
43
  </gmap-cluster>
45
44
  <template v-else>
46
- <gmap-custom-marker
47
- v-for="(marker, index) in markers"
48
- :key="index"
49
- :marker="{ lat: marker.latitude, lng: marker.longitude }"
50
- @click.native="onMarkerClick(marker, index)"
51
- >
52
- <img v-if="marker.imageUrl" :src="marker.imageUrl" class="marker" />
53
- <common-icon
54
- v-else
55
- class="marker"
56
- :spec="{ material: { name: 'place', size: 40 }, color: '#c92b2a' }"
57
- />
58
- </gmap-custom-marker>
45
+ <template v-if="spec.direction">
46
+ <gmap-custom-marker
47
+ v-for="(marker, index) in markers"
48
+ :key="index"
49
+ :marker="{ lat: marker.latitude, lng: marker.longitude }"
50
+ @click.native="onMarkerClick(marker, index)"
51
+ >
52
+ <div class="marker-wrapper">
53
+ <img v-if="marker.imageUrl" :src="marker.imageUrl" class="marker" />
54
+ <common-icon
55
+ v-else
56
+ class="marker"
57
+ :spec="{
58
+ material: { name: 'circle', size: 40 },
59
+ color: marker.markerColor
60
+ }"
61
+ />
62
+ <p class="marker-number">{{ marker.markerNumber }}</p>
63
+ </div>
64
+ </gmap-custom-marker>
65
+ </template>
66
+ <template v-else>
67
+ <gmap-custom-marker
68
+ v-for="(marker, index) in markers"
69
+ :key="index"
70
+ :marker="{ lat: marker.latitude, lng: marker.longitude }"
71
+ @click.native="onMarkerClick(marker, index)"
72
+ >
73
+ <div class="marker-wrapper">
74
+ <img v-if="marker.imageUrl" :src="marker.imageUrl" class="marker" />
75
+ <common-icon
76
+ v-else
77
+ class="marker"
78
+ :spec="{
79
+ material: { name: 'place', size: 40 },
80
+ color: '#c92b2a'
81
+ }"
82
+ />
83
+ <p class="marker-number">{{ marker.markerNumber }}</p>
84
+ </div>
85
+ </gmap-custom-marker>
86
+ </template>
59
87
  </template>
60
88
  </gmap-map>
61
89
  </template>
@@ -85,9 +113,35 @@ export default {
85
113
  selectedMarker: null,
86
114
  center: { lat: 0, lng: 0 },
87
115
  zoom: 11,
88
- markers: []
116
+ markers: [],
117
+ locations: this.spec.locations
89
118
  };
90
119
  },
120
+ // mounted: function() {
121
+ // // switch (this.spec.provider) {
122
+ // // case 'baidu':
123
+ // // this.renderBaiduMap()
124
+ // // break
125
+ // // default:
126
+ // // this.renderGoogleMap()
127
+ // // }
128
+ // const { latitude, longitude, zoom } = this.spec
129
+ // this.updateMapCenter(latitude, longitude)
130
+ // this.zoom = zoom
131
+
132
+ // this.fetchMarkers()
133
+ // }
134
+ mounted: function() {
135
+ // use $nextTick instead setTimeout
136
+ // https://stackoverflow.com/questions/57847474/react-and-vue-google-map-api-remove-rendered-direction-before-setting-a-new-one
137
+ this.$nextTick(function() {
138
+ this.$gmapApiPromiseLazy().then(() => {
139
+ if (this.spec.direction === true) {
140
+ this.drawLineBetweenPoint();
141
+ }
142
+ });
143
+ });
144
+ },
91
145
  methods: {
92
146
  // See https://stackoverflow.com/questions/37597324/markercluster-one-marker-for-a-group for calculator example
93
147
  _calculator(markers, numStyles) {
@@ -195,26 +249,58 @@ export default {
195
249
  const { center } = this.$refs.map.$mapObject;
196
250
  this.updateMapCenter(center.lat(), center.lng());
197
251
  this.fetchMarkers();
252
+ },
253
+ drawLineBetweenPoint() {
254
+ let directionService = new window.google.maps.DirectionsService();
255
+ let directionDisplay = new window.google.maps.DirectionsRenderer();
256
+
257
+ for (let l = 0; l < this.locations.length; l++) {
258
+ for (let i = 0; i < this.locations[l].length; i++) {
259
+ let travel = {
260
+ origin: this.locations[l][i],
261
+ destination: this.locations[l][i + 1],
262
+ travelMode: "DRIVING"
263
+ };
264
+
265
+ directionService.route(travel, (response, status) => {
266
+ if (status === "OK") {
267
+ let map = this.$refs.map;
268
+ directionDisplay = new window.google.maps.DirectionsRenderer({
269
+ suppressMarkers: true,
270
+ polylineOptions: {
271
+ strokeColor: "#2ab3a6",
272
+ stropeOpacity: 0.8,
273
+ strokeWeight: 5
274
+ }
275
+ });
276
+ directionDisplay.setMap(map.$mapObject);
277
+ directionDisplay.setDirections(response);
278
+ }
279
+ });
280
+ }
281
+ }
198
282
  }
199
283
  }
200
- // mounted: function() {
201
- // // switch (this.spec.provider) {
202
- // // case 'baidu':
203
- // // this.renderBaiduMap()
204
- // // break
205
- // // default:
206
- // // this.renderGoogleMap()
207
- // // }
208
- // const { latitude, longitude, zoom } = this.spec
209
- // this.updateMapCenter(latitude, longitude)
210
- // this.zoom = zoom
211
-
212
- // this.fetchMarkers()
213
- // }
214
284
  };
215
285
  </script>
216
286
 
217
287
  <style lang="scss" scoped>
288
+ .marker-wrapper {
289
+ position: relative;
290
+ width: 40px;
291
+ height: 40px;
292
+ }
293
+
294
+ .marker-number {
295
+ font-weight: 800;
296
+ font-size: 16px;
297
+ position: absolute;
298
+ top: 6px;
299
+ width: 40px;
300
+ text-align: center;
301
+ color: white;
302
+ }
303
+
218
304
  .marker {
219
305
  width: 40px;
220
306
  height: 40px;
@@ -152,6 +152,17 @@ export default {
152
152
  $updated() {
153
153
  // To be overridden
154
154
  },
155
+ $recursiveUpdate() {
156
+ this.$ready();
157
+ this.$forceUpdate();
158
+
159
+ // Execute on next tick to ensure that the child has received the updated spec.
160
+ this.$nextTick(() => {
161
+ this.$children.find(child => {
162
+ child.$recursiveUpdate();
163
+ });
164
+ });
165
+ },
155
166
  $dispatchEvent(name, data) {
156
167
  const event = new Event(name, { bubbles: true });
157
168
 
File without changes
File without changes
@@ -125,10 +125,10 @@ export default {
125
125
  val => (styles["height"] = val)
126
126
  );
127
127
 
128
- Utils.type.ifObject(
129
- properties.onClick,
130
- () => (styles["cursor"] = "pointer")
131
- );
128
+ // Utils.type.ifObject(
129
+ // properties.onClick,
130
+ // () => (styles["cursor"] = "pointer")
131
+ // );
132
132
 
133
133
  // This is the main reason styles have to be used in a dynamic way.
134
134
  this._updateDisplay(styles, properties);
@@ -213,6 +213,10 @@ export default {
213
213
  const componentName = Utils.app.componentName(properties.view);
214
214
  const classes = (properties.styleClasses || []).concat(componentName);
215
215
 
216
+ Utils.type.ifObject(properties.onClick, () =>
217
+ classes.push("glib-clickable")
218
+ );
219
+
216
220
  Utils.type.ifArray(properties.styleClasses, val => {
217
221
  if (val.includes("card")) {
218
222
  classes.push("v-card");
File without changes
File without changes
package/components/p.vue CHANGED
File without changes
@@ -57,6 +57,9 @@ export default {
57
57
  $ready() {
58
58
  const onClick = this.spec.onClick ? { onClick: this.spec.onClick } : {};
59
59
  this.customData = Object.assign(onClick, this.spec.data);
60
+ },
61
+ $registryEnabled() {
62
+ return false;
60
63
  }
61
64
  }
62
65
  };