glib-web 3.0.0-beta1 → 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 (85) hide show
  1. package/action.js +22 -11
  2. package/actions/cables/push.js +3 -1
  3. package/actions/components/update.js +0 -15
  4. package/actions/fields/focus.js +6 -0
  5. package/actions/fields/reset.js +12 -0
  6. package/actions/forms/submit.js +1 -1
  7. package/actions/http/get.js +1 -1
  8. package/actions/panels/scrollTo.js +4 -2
  9. package/actions/popovers/close.js +5 -0
  10. package/actions/popovers/open.js +9 -0
  11. package/actions/tours/start.js +10 -1
  12. package/actions/tours/stop.js +7 -0
  13. package/actions/windows/refreshState.js +3 -1
  14. package/actions/ws/push.js +3 -1
  15. package/app.vue +72 -15
  16. package/components/_badge.vue +1 -6
  17. package/components/_button.vue +22 -11
  18. package/components/_chip.vue +27 -17
  19. package/components/_responsive.vue +15 -15
  20. package/components/button.vue +4 -5
  21. package/components/component.vue +24 -9
  22. package/components/fields/_patternText.vue +8 -5
  23. package/components/fields/_select.vue +8 -5
  24. package/components/fields/autocomplete.vue +4 -1
  25. package/components/fields/check.vue +9 -32
  26. package/components/fields/checkGroup.vue +17 -24
  27. package/components/fields/datetime.vue +1 -6
  28. package/components/fields/file.vue +28 -28
  29. package/components/fields/otpField.vue +36 -7
  30. package/components/fields/phone/field.vue +1 -1
  31. package/components/fields/radio.vue +2 -31
  32. package/components/fields/radioGroup.vue +23 -27
  33. package/components/fields/richText.vue +33 -37
  34. package/components/fields/stripe/stripeFields.vue +9 -2
  35. package/components/fields/stripe/stripeIndividualFields.vue +9 -7
  36. package/components/fields/text.vue +25 -34
  37. package/components/fields/textarea.vue +11 -4
  38. package/components/image.vue +9 -13
  39. package/components/label.vue +6 -10
  40. package/components/markdown.vue +33 -18
  41. package/components/mixins/events.js +58 -32
  42. package/components/mixins/generic.js +5 -2
  43. package/components/mixins/inputVariant.js +16 -0
  44. package/components/mixins/list/autoload.js +7 -5
  45. package/components/mixins/styles.js +12 -8
  46. package/components/mixins/table/autoload.js +6 -4
  47. package/components/mixins/ws/actionCable.js +4 -3
  48. package/components/mixins/ws/phoenixSocket.js +4 -3
  49. package/components/p.vue +10 -0
  50. package/components/panels/column.vue +4 -15
  51. package/components/panels/custom.vue +8 -4
  52. package/components/panels/form.vue +24 -20
  53. package/components/panels/horizontal.vue +29 -25
  54. package/components/panels/list.vue +15 -33
  55. package/components/panels/responsive.vue +0 -6
  56. package/components/panels/split.vue +1 -1
  57. package/components/panels/table.vue +2 -2
  58. package/components/panels/vertical.vue +14 -14
  59. package/components/popover.vue +39 -0
  60. package/components/progressCircle.vue +2 -8
  61. package/components/progressbar.vue +4 -14
  62. package/components/shareButton.vue +24 -30
  63. package/components/tabBar.vue +10 -17
  64. package/extensions/string.js +22 -0
  65. package/index.js +24 -54
  66. package/nav/appbar.vue +4 -2
  67. package/nav/dialog.vue +68 -15
  68. package/nav/sheet.vue +7 -2
  69. package/nav/snackbar.vue +8 -9
  70. package/package.json +6 -8
  71. package/plugins/updatableComponent.js +7 -1
  72. package/plugins/vuetify.js +1 -2
  73. package/store.js +16 -0
  74. package/templates/thumbnail.vue +8 -4
  75. package/utils/component.js +42 -10
  76. package/utils/constant.js +4 -0
  77. package/utils/history.js +5 -4
  78. package/utils/http.js +20 -25
  79. package/utils/launch.js +56 -3
  80. package/utils/mime_type.js +2 -0
  81. package/utils/private/ws.js +3 -1
  82. package/utils/public.js +4 -0
  83. package/utils/queue.js +0 -8
  84. package/utils/settings.js +7 -0
  85. package/utils/uploader.js +3 -0
package/action.js CHANGED
@@ -2,7 +2,9 @@ import TypeUtils from "./utils/type";
2
2
 
3
3
  import ActionsRunMultiple from "./actions/runMultiple";
4
4
 
5
- import ActionsFormsSubmitV1 from "./actions/forms/submit";
5
+ import ActionsFormsSubmit from "./actions/forms/submit";
6
+ import ActionsFieldsReset from "./actions/fields/reset";
7
+ import ActionsFieldsFocus from "./actions/fields/focus";
6
8
 
7
9
  import ActionsHttpGetV1 from "./actions/http/get";
8
10
  import ActionsHttpPostV1 from "./actions/http/post";
@@ -53,15 +55,21 @@ import ActionCommandsCustom from "./actions/commands/custom";
53
55
  import ActionCommandsEnqueue from "./actions/commands/enqueue";
54
56
 
55
57
  import ActionToursStart from "./actions/tours/start";
58
+ import ActionToursStop from "./actions/tours/stop";
56
59
 
57
60
  import ActionComponentsUpdate from "./actions/components/update";
58
61
 
59
- import eventBus from "./utils/eventBus";
62
+ import ActionPopoversOpen from "./actions/popovers/open"
63
+ import ActionPopoversClose from "./actions/popovers/close"
64
+
65
+ import { vueApp } from "./store";
60
66
 
61
67
  const actions = {
62
68
  runMultiple: ActionsRunMultiple,
63
69
 
64
- "forms/submit": ActionsFormsSubmitV1,
70
+ "forms/submit": ActionsFormsSubmit,
71
+ "fields/reset": ActionsFieldsReset,
72
+ "fields/focus": ActionsFieldsFocus,
65
73
 
66
74
  "http/get": ActionsHttpGetV1,
67
75
  "http/post": ActionsHttpPostV1,
@@ -112,6 +120,10 @@ const actions = {
112
120
  "commands/enqueue": ActionCommandsEnqueue,
113
121
 
114
122
  "tours/start": ActionToursStart,
123
+ "components/update": ActionComponentsUpdate,
124
+ "popovers/open": ActionPopoversOpen,
125
+ "popovers/close": ActionPopoversClose,
126
+ "tours/stop": ActionToursStop,
115
127
  "components/update": ActionComponentsUpdate
116
128
  };
117
129
 
@@ -172,10 +184,10 @@ export default class Action {
172
184
  }
173
185
  action.execute(spec, component, params);
174
186
  } catch (e) {
175
- console.error(
176
- "Failed executing command",
177
- actionName,
178
- `Error: '${e.message}'`
187
+ GLib.settings.errorHandler(
188
+ new Error(
189
+ `Failed executing command "${actionName}". Error: ${e.message}`
190
+ )
179
191
  );
180
192
  }
181
193
  }
@@ -184,14 +196,13 @@ export default class Action {
184
196
  // TODO: The execution should be in the following order: onResponse, page render, onLoad
185
197
  if (response.header || response.body || response.footer) {
186
198
  Utils.http.forceComponentUpdate(() => {
187
- // window.vueApp.page = response;
188
- eventBus.$emit('app/updatePage', response)
199
+ vueApp.page = response
189
200
  });
190
201
  }
191
202
 
192
- window.vueApp.temp.analytics = response.analytics;
203
+ vueApp.temp.analytics = response.analytics;
193
204
  GLib.action.execute(response.onResponse, component);
194
- window.vueApp.temp.analytics = null;
205
+ vueApp.temp.analytics = null;
195
206
  }
196
207
 
197
208
  static registerCustom(actionName, action) {
@@ -1,7 +1,9 @@
1
+ import { vueApp } from "../../store";
2
+
1
3
  export default class {
2
4
  execute(properties, component) {
3
5
  Utils.type.ifString(properties.channel, channelName => {
4
- const ws = window.vueApp.actionCable;
6
+ const ws = vueApp.actionCable;
5
7
  const channel = ws.channels[channelName];
6
8
 
7
9
  console.log("Pushing to", channel);
@@ -1,5 +1,3 @@
1
- import { Vue } from "../../index";
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
  }
@@ -0,0 +1,6 @@
1
+ export default class {
2
+ execute(properties, component) {
3
+ const target = GLib.component.findById(properties.targetId);
4
+ target.action_focus();
5
+ }
6
+ }
@@ -0,0 +1,12 @@
1
+ import { nextTick } from "vue";
2
+
3
+ export default class {
4
+ execute(properties, component) {
5
+ const target = GLib.component.findById(properties.targetId);
6
+ target.action_resetValue();
7
+
8
+ nextTick(() => {
9
+ GLib.action.execute(properties["onReset"], component);
10
+ });
11
+ }
12
+ }
@@ -2,6 +2,6 @@ export default class {
2
2
  execute(properties, component) {
3
3
  component.$dispatchEvent("forms/directSubmit", {
4
4
  url: properties.overrideUrl
5
- });
5
+ })
6
6
  }
7
7
  }
@@ -8,7 +8,7 @@ export default class {
8
8
  const cleanUrl = Utils.url.htmlUrl(historyUrl);
9
9
  if (cleanUrl !== currentUrl) {
10
10
  console.log("URL", cleanUrl, response.url, response);
11
- const data = Object.assign({}, window.vueApp.page, {
11
+ const data = Object.assign({}, page, {
12
12
  replayGetResponse: page.onResponse
13
13
  });
14
14
 
@@ -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);
@@ -0,0 +1,5 @@
1
+ export default class {
2
+ execute(properties, component) {
3
+ Utils.launch.popover.close(properties);
4
+ }
5
+ }
@@ -0,0 +1,9 @@
1
+ import { nextTick } from "vue";
2
+ import bus from "../../utils/eventBus";
3
+
4
+ export default class {
5
+ execute(properties, component) {
6
+ Utils.launch.popover.open(properties, component);
7
+
8
+ }
9
+ }
@@ -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
+ }
@@ -1,5 +1,7 @@
1
+ import { vueApp } from '../../store'
2
+
1
3
  export default class {
2
4
  execute(properties) {
3
- window.vueApp.stateUpdatedAt = Date.now();
5
+ vueApp.stateUpdatedAt = Date.now
4
6
  }
5
7
  }
@@ -1,7 +1,9 @@
1
+ import { vueApp } from "../../store";
2
+
1
3
  export default class {
2
4
  execute(properties, component, params) {
3
5
  Utils.type.ifString(properties.topic, topicName => {
4
- const ws = window.vueApp.webSocket;
6
+ const ws = vueApp.webSocket;
5
7
  const channel = ws.channels[topicName];
6
8
 
7
9
  Utils.type.ifString(properties.event, eventName => {
package/app.vue CHANGED
@@ -3,7 +3,7 @@
3
3
  <component :is="containerComponent" :spec="formSpec" :style="'height: 100%;'">
4
4
  <nav-appbar ref="appBar" :page="page" />
5
5
 
6
- <v-progress-linear v-if="$root.vueApp.indicator" :indeterminate="true" height="5"
6
+ <v-progress-linear color="primary" v-if="vueApp.indicator" :indeterminate="true" height="5"
7
7
  style="position: fixed; z-index: 4;">
8
8
  </v-progress-linear>
9
9
 
@@ -32,6 +32,7 @@ import Utils from "./utils/helper";
32
32
  import phoenixSocketMixin from "./components/mixins/ws/phoenixSocket.js";
33
33
  import actionCableMixin from "./components/mixins/ws/actionCable.js";
34
34
  import FormPanel from "./components/panels/form.vue";
35
+ import { vueApp } from "./store";
35
36
 
36
37
  export default {
37
38
  components: {
@@ -46,6 +47,7 @@ export default {
46
47
  return {
47
48
  title: "...",
48
49
  mainHeight: 0,
50
+ vueApp
49
51
  };
50
52
  },
51
53
  computed: {
@@ -60,6 +62,7 @@ export default {
60
62
  },
61
63
  containerComponent() {
62
64
  if (this.formSpec) {
65
+ this.name = 'panels-form'
63
66
  return "panels-form";
64
67
  }
65
68
  return "div";
@@ -75,7 +78,7 @@ export default {
75
78
  },
76
79
  },
77
80
  watch: {
78
- "$root.indicator": function (val, oldVal) {
81
+ "vueApp.indicator": function (val, oldVal) {
79
82
  document.title = val ? "..." : this.page.title;
80
83
  }
81
84
  },
@@ -103,26 +106,27 @@ export default {
103
106
  this.$wsInitPhoenixSocket(this.page.phoenixSocket);
104
107
  this.$wsInitActionCable(this.page.actionCable);
105
108
 
106
- if (this.$gtag) {
107
- if (!Utils.settings.isDev) {
108
- console.log(`Tracking analytics: ${window.location}`);
109
- this.$gtag.pageview({
110
- page_location: window.location,
111
- });
112
- }
113
- } else {
114
- console.warn("Analytics not setup. Set `settings.gtagId`.");
115
- }
109
+ // TODO: Remove gtag dependency
110
+ // if (this.$gtag) {
111
+ // if (!Utils.settings.isDev) {
112
+ // console.log(`Tracking analytics: ${window.location}`);
113
+ // this.$gtag.pageview({
114
+ // page_location: window.location
115
+ // });
116
+ // }
117
+ // } else {
118
+ // console.warn("Analytics not setup. Set `settings.gtagId`.");
119
+ // }
116
120
 
121
+ // Use setTimeout() to wait until page is rendered. Don't use nextTick() because
122
+ // it would execute much earlier (before all components finish initializing).
117
123
  if (Utils.history.isPoppedState(this.page)) {
118
124
  setTimeout(() => {
119
- // Wait until page is rendered
120
125
  GLib.action.execute(this.page.onRefocus, this);
121
126
  GLib.action.execute(this.page.replayGetResponse, this);
122
127
  });
123
128
  } else {
124
129
  setTimeout(() => {
125
- // Wait until page is rendered
126
130
  GLib.action.execute(this.page.onLoad, this);
127
131
  });
128
132
  }
@@ -188,8 +192,61 @@ body,
188
192
  background: yellow !important;
189
193
  }
190
194
 
191
- .glib-clickable {
195
+ // Don't override the default button's effect.
196
+ .glib-clickable:not(.v-btn) {
192
197
  cursor: pointer;
198
+
199
+ // // So that we can display a semi-transparent layer on hover (see below)
200
+ position: relative;
201
+
202
+ &:hover:before {
203
+ content: "\A";
204
+ width: 100%;
205
+ height: 100%;
206
+ background: rgba(100, 100, 100, 0.1);
207
+ position: absolute;
208
+ top: 0;
209
+ left: 0;
210
+ }
211
+
212
+ &:active:before {
213
+ background: rgba(100, 100, 100, 0.2);
214
+ }
215
+ }
216
+
217
+ .glib-clickable.theme--light.v-list-item:hover:before {
218
+ opacity: 1; // Override Vuetify
219
+ }
220
+
221
+ .popover-menu {
222
+ padding: 8px 0;
223
+ background-color: white;
224
+ border-radius: 8px;
225
+ box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
226
+ height: fit-content;
227
+ }
228
+
229
+ .popover-menu-item {
230
+ font-size: 14px;
231
+ padding: 8px 16px;
232
+ width: 100%;
233
+ }
234
+
235
+ .popover-menu-item:hover {
236
+ background-color: #f3f4f6;
237
+ }
238
+
239
+ .v-input__details {
240
+ min-height: 0;
241
+ margin-bottom: 0;
242
+
243
+ .v-messages {
244
+ min-height: 0;
245
+ }
246
+ }
247
+
248
+ .v-label {
249
+ opacity: 1;
193
250
  }
194
251
 
195
252
  /******/
@@ -1,10 +1,5 @@
1
1
  <template>
2
- <v-badge
3
- :color="badge.backgroundColor || 'red'"
4
- overlap
5
- :value="badgeExists()"
6
- :style="styles()"
7
- >
2
+ <v-badge :color="badge.backgroundColor || 'red'" overlap :model-value="badgeExists()" :style="styles()">
8
3
  <template v-slot:badge>{{ badge.text }}</template>
9
4
  <slot />
10
5
  </v-badge>
@@ -1,33 +1,32 @@
1
1
  <template>
2
- <!-- <common-badge :spec="spec"> -->
3
2
  <!-- Use `click.prevent` to prevent bubbling when clicking a dropdown button that is
4
3
  located in a list row that has href. -->
5
- <v-btn :type="type" :disabled="disabled || $isBusy || spec.disabled" :style="styles()" :class="$classes()"
6
- :href="$href()" :rel="$rel()" :small="linkStyling || null" :icon="$classes().includes('icon')"
7
- :outlined="$classes().includes('outlined') || null" :tile="$classes().includes('tile') || null"
8
- :rounded="$classes().includes('rounded')" :depressed="$classes().includes('depressed') || null" @click.prevent="
4
+ <v-btn :type="type" :disabled="disabled || $isBusy || spec.disabled" :style="styles()" :class="classes()"
5
+ :href="$href()" :rel="$rel()" :variant="variant" :rounded="$classes().includes('rounded') || null" @click.prevent="
9
6
  type == 'submit' ? $dispatchEvent('forms/submit') : $onClick()
10
- ">
11
- <span><common-icon :spec="spec.icon || {}" /></span>
7
+ ">
8
+ <span v-if="spec.icon"><common-icon :spec="spec.icon || {}" /></span>
12
9
  <div :class="hideTextOnXs && spec.icon ? 'd-none d-sm-flex' : null">
13
10
  {{ spec.text }}
14
11
  </div>
15
12
  </v-btn>
16
- <!-- </common-badge> -->
17
13
  </template>
18
14
 
19
15
  <script>
16
+ import { variants } from '../utils/constant'
17
+
20
18
  export default {
21
19
  props: {
22
20
  spec: { type: Object, required: true },
23
21
  type: { type: String, default: "button" },
24
- disabled: { type: Boolean, required: true },
22
+ disabled: { type: Boolean },
25
23
  hideTextOnXs: { type: Boolean },
26
24
  eventHandlers: { type: Object, default: null }
27
25
  },
28
26
  data: function () {
29
27
  return {
30
- linkStyling: false
28
+ linkStyling: false,
29
+ variant: 'elevated'
31
30
  };
32
31
  },
33
32
  methods: {
@@ -35,14 +34,25 @@ export default {
35
34
  this.$type.ifArray(this.spec.styleClasses, val => {
36
35
  this.linkStyling = val.includes("link");
37
36
  });
37
+
38
+ const vm = this
39
+ variants.forEach((value) => {
40
+ if (vm.$classes().includes(value)) {
41
+ vm.variant = value
42
+ }
43
+ })
38
44
  },
39
45
  styles() {
40
- const styles = this.genericStyles();
46
+ const styles = this.$styles();
41
47
  if (this.linkStyling) {
42
48
  styles["color"] = styles["color"] || "#1976d2";
43
49
  }
44
50
  return styles;
45
51
  },
52
+ classes() {
53
+ const classes = this.$classes();
54
+ return classes;
55
+ },
46
56
  $registryEnabled() {
47
57
  return false;
48
58
  }
@@ -79,6 +89,7 @@ button {
79
89
  font-size: 16px;
80
90
  line-height: 1;
81
91
  min-width: auto;
92
+ box-shadow: none !important;
82
93
  }
83
94
  }
84
95
 
@@ -1,22 +1,27 @@
1
1
  <template>
2
- <!-- <common-tooltip :spec="spec"> -->
3
- <!-- <template v-slot:activator="{ on }"> -->
4
- <!-- <common-badge :spec="spec"> -->
5
- <div>
6
- <v-chip v-if="spec.onClick" :style="genericStyles()" :class="$classes()" :href="$href()" @click="$onClick()">
7
- {{ spec.text }}
8
- </v-chip>
9
- <v-chip v-else :style="genericStyles()" :class="$classes()">
10
- {{ spec.text }}
11
- </v-chip>
12
- </div>
13
- <!-- </common-badge> -->
14
- <!-- </template> -->
15
- <!-- </common-tooltip> -->
2
+ <common-badge :spec="spec">
3
+ <div>
4
+ <v-chip v-if="spec.onClick" :style="genericStyles()" :color="color" :class="$classes()" :href="$href()"
5
+ @click="$onClick()" :variant="variant">
6
+ {{ spec.text }}
7
+ </v-chip>
8
+ <v-chip v-else :style="genericStyles()" :color="color" :class="$classes()" :variant="variant">
9
+ {{ spec.text }}
10
+ </v-chip>
11
+ </div>
12
+ </common-badge>
16
13
  </template>
17
14
 
18
15
  <script>
16
+ import { colors, variants } from '../utils/constant'
17
+
19
18
  export default {
19
+ data: function () {
20
+ return {
21
+ color: '',
22
+ variant: 'tonal'
23
+ }
24
+ },
20
25
  props: {
21
26
  spec: { type: Object, required: true }
22
27
  },
@@ -26,9 +31,14 @@ export default {
26
31
  // };
27
32
  // },
28
33
  methods: {
29
- // $ready() {
30
- // this.tooltip = this.spec.tooltip || {};
31
- // },
34
+ $ready() {
35
+ colors.forEach((value) => {
36
+ if (this.$classes().includes(value)) this.color = value;
37
+ })
38
+ variants.forEach((value) => {
39
+ if (this.$classes().includes(value)) this.variant = value;
40
+ })
41
+ },
32
42
  $registryEnabled() {
33
43
  return false;
34
44
  }
@@ -45,7 +45,7 @@ export default {
45
45
  default:
46
46
  align = "flex-start";
47
47
  }
48
- Object.assign(this.innerStyles, { 'align-items': align })
48
+ Object.assign(this.innerStyles, { 'align-items': align, height: 'auto' })
49
49
  },
50
50
  isColumn(item) {
51
51
  return item.view == "panels/column-v1";
@@ -80,21 +80,21 @@ a.panels-responsive {
80
80
  color: inherit;
81
81
  text-decoration: inherit;
82
82
 
83
- // So that we can display a semi-transparent layer on hover (see below)
84
- position: relative;
83
+ // // So that we can display a semi-transparent layer on hover (see below)
84
+ // position: relative;
85
85
 
86
- &:hover:after {
87
- content: "\A";
88
- width: 100%;
89
- height: 100%;
90
- background: rgba(0, 0, 0, 0.1);
91
- position: absolute;
92
- top: 0;
93
- left: 0;
94
- }
86
+ // &:hover:after {
87
+ // content: "\A";
88
+ // width: 100%;
89
+ // height: 100%;
90
+ // background: rgba(0, 0, 0, 0.1);
91
+ // position: absolute;
92
+ // top: 0;
93
+ // left: 0;
94
+ // }
95
95
 
96
- &:active:after {
97
- background: rgba(0, 0, 0, 0.4);
98
- }
96
+ // &:active:after {
97
+ // background: rgba(0, 0, 0, 0.4);
98
+ // }
99
99
  }
100
100
  </style>
@@ -1,9 +1,8 @@
1
1
  <template>
2
- <!-- <common-tooltip ref="tooltip" :spec="spec"> -->
3
- <!-- <template v-slot:activator="{ on }"> -->
4
- <common-button :spec="spec" :disabled="$isBusy" />
5
- <!-- </template> -->
6
- <!-- </common-tooltip> -->
2
+ <common-badge v-if="spec.badge" :spec="spec">
3
+ <common-button :spec="spec" :disabled="$isBusy" />
4
+ </common-badge>
5
+ <common-button v-else :spec="spec" :disable="$isBusy" />
7
6
  </template>
8
7
 
9
8
  <script>
@@ -19,8 +19,8 @@
19
19
 
20
20
  <!-- <panels-responsive v-else-if="spec.view == 'panels/scroll-v1'" :spec="spec" /> -->
21
21
 
22
- <component :is="name" v-else-if="name" :id="spec.id" :spec="spec" />
23
-
22
+ <component v-else-if="name" :is="name" :id="spec.id" ref="delegate" :spec="spec"
23
+ @[menter]="handlePopover(spec.onMouseEnter)" @[mleave]="handlePopover(spec.onMouseLeave)" />
24
24
  <div v-else>Unsupported view: {{ spec.view }}</div>
25
25
  </template>
26
26
 
@@ -112,6 +112,7 @@ import ColumnChart from "./charts/column.vue";
112
112
  import PieChart from "./charts/pie.vue";
113
113
 
114
114
  import ShareButton from "./shareButton.vue";
115
+ import Action from "../action";
115
116
 
116
117
  import { getCurrentInstance } from 'vue';
117
118
 
@@ -208,16 +209,24 @@ export default {
208
209
  },
209
210
  data() {
210
211
  return {
211
- name: null,
212
+ name: null
212
213
  };
213
214
  },
214
- beforeUpdate() {
215
- // NOTE: Not sure what this is for
216
- // Make sure vuejs will not attempt to render old data.
217
- // if (this._mountedUrl !== window.location.href) {
218
- // this.name = null;
219
- // }
215
+ computed: {
216
+ menter() {
217
+ return this.spec.onMouseEnter ? 'mouseenter' : null
218
+ },
219
+ mleave() {
220
+ return this.spec.onMouseLeave ? 'mouseleave' : null
221
+ }
220
222
  },
223
+ // beforeUpdate() {
224
+ // // NOTE: Not sure what this is for
225
+ // // Make sure vuejs will not attempt to render old data.
226
+ // // if (this._mountedUrl !== window.location.href) {
227
+ // // this.name = null;
228
+ // // }
229
+ // },
221
230
  methods: {
222
231
  $ready() {
223
232
  const name = Utils.app.componentName(this.spec.view);
@@ -230,9 +239,15 @@ export default {
230
239
  }
231
240
  }
232
241
  },
242
+ $update() {
243
+ this.$refs.delegate.$update();
244
+ },
233
245
  $registryEnabled() {
234
246
  return false;
235
247
  },
248
+ handlePopover(spec) {
249
+ GLib.action.execute(spec, this)
250
+ }
236
251
  },
237
252
  };
238
253
  </script>