glib-web 2.2.1 → 2.3.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.
package/action.js CHANGED
@@ -49,6 +49,7 @@ import ActionsCreditCard from "./actions/auth/creditCard";
49
49
  import ActionsAnalyticsLogEvent from "./actions/analytics/logEvent";
50
50
 
51
51
  import ActionCommandsCopy from "./actions/commands/copy";
52
+ import ActionCommandsCustom from "./actions/commands/custom";
52
53
 
53
54
  import ActionToursStart from "./actions/tours/start";
54
55
 
@@ -102,11 +103,16 @@ const actions = {
102
103
  "auth/creditCard": ActionsCreditCard,
103
104
 
104
105
  "analytics/logEvent": ActionsAnalyticsLogEvent,
106
+
105
107
  "commands/copy": ActionCommandsCopy,
108
+ "commands/custom": ActionCommandsCustom,
109
+
106
110
  "tours/start": ActionToursStart,
107
111
  "components/update": ActionComponentsUpdate
108
112
  };
109
113
 
114
+ const customActions = {};
115
+
110
116
  export default class Action {
111
117
  static execute(spec, component, params = {}) {
112
118
  if (!TypeUtils.isObject(spec)) {
@@ -148,17 +154,21 @@ export default class Action {
148
154
  }
149
155
 
150
156
  static executeGlobal(name, spec, component, params) {
157
+ this._executeInternal(name, spec, component, params, actions);
158
+ }
159
+
160
+ static _executeInternal(name, spec, component, params, registry) {
151
161
  const actionName = name.replace(/-v1$/, "");
152
162
 
153
163
  try {
154
- const action = new actions[actionName]();
164
+ const action = new registry[actionName]();
155
165
  const logDisabled = action.logDisabled && action.logDisabled();
156
166
  if (!logDisabled) {
157
167
  console.log(`Executing "${actionName}"`);
158
168
  }
159
169
  action.execute(spec, component, params);
160
170
  } catch (e) {
161
- console.log(
171
+ console.error(
162
172
  "Failed executing command",
163
173
  actionName,
164
174
  `Error: '${e.message}'`
@@ -178,6 +188,18 @@ export default class Action {
178
188
  GLib.action.execute(response.onResponse, component);
179
189
  window.vueApp.temp.analytics = null;
180
190
  }
191
+
192
+ static registerCustom(actionName, action) {
193
+ if (customActions[actionName]) {
194
+ console.error("Command already registered", actionName);
195
+ } else {
196
+ customActions[actionName] = action;
197
+ }
198
+ }
199
+
200
+ static executeCustom(name, spec, component, params) {
201
+ this._executeInternal(name, spec, component, params, customActions);
202
+ }
181
203
  }
182
204
 
183
205
  window.Action = Action;
@@ -0,0 +1,10 @@
1
+ import Hash from "../../utils/hash";
2
+
3
+ export default class {
4
+ execute(spec, component) {
5
+ const properties = new Hash(spec.properties);
6
+ // `spec` might contain params that were coming from other actions (e.g. `formData`).
7
+ Object.assign(properties, spec);
8
+ GLib.action.executeCustom(spec.name, properties, component);
9
+ }
10
+ }
@@ -5,11 +5,14 @@ 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);
8
+ // const target = component.updatables[spec.targetId];
9
+ // if (!target) console.error("no component found :" + spec.targetId);
10
10
 
11
- Object.assign(target.spec, spec.views[0]);
12
- this.updateComponent(target);
11
+ const target = GLib.component.findById(spec.targetId);
12
+ if (target) {
13
+ Object.assign(target.spec, spec.views[0]);
14
+ this.updateComponent(target);
15
+ }
13
16
  }
14
17
 
15
18
  updateComponent(component) {
package/app.vue CHANGED
@@ -1,7 +1,11 @@
1
1
  <template>
2
2
  <v-app :class="page.styleClasses">
3
- <component :is="containerComponent" :spec="formSpec">
4
- <nav-appbar :page="page" />
3
+ <component
4
+ :is="containerComponent"
5
+ :spec="formSpec"
6
+ :style="'height: 100%;'"
7
+ >
8
+ <nav-appbar ref="appBar" :page="page" />
5
9
 
6
10
  <v-progress-linear
7
11
  v-if="$root.vueApp.indicator"
@@ -11,29 +15,24 @@
11
15
  >
12
16
  </v-progress-linear>
13
17
 
14
- <div class="pages-header">
15
- <layouts-content
16
- :template="page.template"
17
- :spec="header"
18
- :full-height="false"
19
- />
20
- </div>
21
-
22
- <div id="page_body" class="pages-body body-wrapper">
23
- <layouts-content
24
- :template="page.template"
25
- :spec="body"
26
- :full-height="true"
27
- />
28
- </div>
29
-
30
- <div class="pages-footer">
31
- <layouts-content
32
- :template="page.template"
33
- :spec="footer"
34
- :full-height="false"
35
- />
36
- </div>
18
+ <v-main :style="`height: ${mainHeight}px;`">
19
+ <v-container
20
+ :fluid="page.template == 'fullWidth'"
21
+ :class="containerClasses"
22
+ >
23
+ <div class="pages-header">
24
+ <panels-responsive :spec="header" />
25
+ </div>
26
+
27
+ <div id="page_body" class="pages-body body-wrapper">
28
+ <panels-responsive :spec="body" />
29
+ </div>
30
+
31
+ <div class="pages-footer">
32
+ <panels-responsive :spec="footer" />
33
+ </div>
34
+ </v-container>
35
+ </v-main>
37
36
  </component>
38
37
  </v-app>
39
38
  </template>
@@ -41,7 +40,6 @@
41
40
  <script>
42
41
  import NavAppBar from "./nav/appbar";
43
42
  import Utils from "./utils/helper";
44
- import ContentLayout from "./nav/content";
45
43
  import phoenixSocketMixin from "./components/mixins/ws/phoenixSocket.js";
46
44
  import actionCableMixin from "./components/mixins/ws/actionCable.js";
47
45
  import FormPanel from "./components/panels/form";
@@ -49,7 +47,6 @@ import FormPanel from "./components/panels/form";
49
47
  export default {
50
48
  components: {
51
49
  "nav-appbar": NavAppBar,
52
- "layouts-content": ContentLayout,
53
50
  "panels-form": FormPanel
54
51
  },
55
52
  mixins: [phoenixSocketMixin, actionCableMixin],
@@ -58,7 +55,8 @@ export default {
58
55
  },
59
56
  data() {
60
57
  return {
61
- title: "..."
58
+ title: "...",
59
+ mainHeight: 0
62
60
  };
63
61
  },
64
62
  computed: {
@@ -77,6 +75,11 @@ export default {
77
75
  }
78
76
  return "div";
79
77
  },
78
+ containerClasses() {
79
+ const classes = ["hamburger"];
80
+ classes.push(this.page.containerStyleClasses || []);
81
+ return classes;
82
+ },
80
83
  // Use computed to ensure that the spec gets updated when the user navigates to another page.
81
84
  formSpec() {
82
85
  return this.page.fullPageForm;
@@ -96,6 +99,15 @@ export default {
96
99
  Utils.http.promptIfDirtyOnUnload();
97
100
  },
98
101
  methods: {
102
+ $mounted() {
103
+ window.addEventListener(
104
+ "resize",
105
+ event => {
106
+ this.updateMainHeight();
107
+ },
108
+ true
109
+ );
110
+ },
99
111
  $ready() {
100
112
  document.title = this.page.title;
101
113
 
@@ -125,6 +137,15 @@ export default {
125
137
  GLib.action.execute(this.page.onLoad, this);
126
138
  });
127
139
  }
140
+
141
+ // Use nextTick() to allow time for the appBar to complete initialization.
142
+ this.$nextTick(() => {
143
+ this.updateMainHeight();
144
+ });
145
+ },
146
+ updateMainHeight() {
147
+ console.debug("Setting body height");
148
+ this.mainHeight = window.innerHeight - this.$refs.appBar.$el.offsetHeight;
128
149
  }
129
150
  }
130
151
  };
@@ -178,11 +199,12 @@ body,
178
199
 
179
200
  <style scoped>
180
201
  /*** Header/footer support ***/
181
- .application--wrap {
202
+ .hamburger {
182
203
  display: flex;
183
204
  flex-direction: column;
184
205
  justify-content: space-between;
185
206
  height: 100%;
207
+ padding: 0;
186
208
  }
187
209
 
188
210
  .body-wrapper {
@@ -15,6 +15,7 @@
15
15
  :rounded="$classes().includes('rounded')"
16
16
  :depressed="$classes().includes('depressed')"
17
17
  @click="type == 'submit' ? null : $onClick()"
18
+ v-on="eventHandlers"
18
19
  >
19
20
  <span><common-icon :spec="spec.icon || {}"/></span>
20
21
  <div :class="hideTextOnXs && spec.icon ? 'd-none d-sm-flex' : null">
@@ -30,7 +31,8 @@ export default {
30
31
  spec: { type: Object, required: true },
31
32
  type: { type: String, default: "button" },
32
33
  disabled: { type: Boolean, required: true },
33
- hideTextOnXs: { type: Boolean }
34
+ hideTextOnXs: { type: Boolean },
35
+ eventHandlers: { type: Object, default: null }
34
36
  },
35
37
  data: function() {
36
38
  return {
@@ -1,37 +1,29 @@
1
1
  <template>
2
- <v-tooltip
3
- :disabled="!spec.tooltip"
4
- :top="tooltipPositionMatches('top')"
5
- :right="tooltipPositionMatches('right')"
6
- :bottom="tooltipPositionMatches('bottom')"
7
- :left="tooltipPositionMatches('left')"
8
- >
2
+ <common-tooltip :spec="spec">
9
3
  <template v-slot:activator="{ on }">
10
- <span v-on="on">
11
- <common-badge :spec="spec">
12
- <v-chip
13
- v-if="spec.onClick"
14
- :style="genericStyles()"
15
- :class="$classes()"
16
- :href="$href()"
17
- @click="$onClick()"
18
- >
19
- {{ spec.text }}
20
- </v-chip>
21
- <v-chip v-else :style="genericStyles()" :class="$classes()">
22
- {{ spec.text }}
23
- </v-chip>
24
- </common-badge>
25
- </span>
4
+ <common-badge :spec="spec">
5
+ <v-chip
6
+ v-if="spec.onClick"
7
+ :style="genericStyles()"
8
+ :class="$classes()"
9
+ :href="$href()"
10
+ @click="$onClick()"
11
+ v-on="on"
12
+ >
13
+ {{ spec.text }}
14
+ </v-chip>
15
+ <v-chip v-else :style="genericStyles()" :class="$classes()" v-on="on">
16
+ {{ spec.text }}
17
+ </v-chip>
18
+ </common-badge>
26
19
  </template>
27
- <span>{{ tooltip.text }}</span>
28
- </v-tooltip>
20
+ </common-tooltip>
29
21
  </template>
30
22
 
31
23
  <script>
32
- import TooltipMixins from "./mixins/tooltip";
24
+ // import TooltipMixins from "./mixins/tooltip";
33
25
  export default {
34
- mixins: [TooltipMixins],
26
+ // mixins: [TooltipMixins],
35
27
  props: {
36
28
  spec: { type: Object, required: true }
37
29
  },
@@ -50,7 +42,7 @@ export default {
50
42
 
51
43
  <style lang="scss" scoped>
52
44
  // Prevent hover effect if the chip is not clickable.
53
- span.theme--light.v-chip:hover:before {
45
+ .v-chip:not(.v-chip--clickable).theme--light:hover:before {
54
46
  opacity: 0;
55
47
  }
56
48
  </style>
@@ -5,6 +5,7 @@
5
5
  :style="$styles()"
6
6
  :href="$href()"
7
7
  @click="$onClick()"
8
+ v-on="eventHandlers"
8
9
  >
9
10
  <v-row no-gutters class="full-height">
10
11
  <template v-for="(item, index) in spec.childViews">
@@ -31,13 +32,8 @@ import Vue from "vue";
31
32
 
32
33
  export default {
33
34
  props: {
34
- spec: {
35
- type: Object,
36
- required: true,
37
- default: function() {
38
- return {};
39
- }
40
- }
35
+ spec: { type: Object, required: true },
36
+ eventHandlers: { type: Object, default: null }
41
37
  },
42
38
  data() {
43
39
  return {
@@ -46,12 +42,18 @@ export default {
46
42
  },
47
43
  computed: {
48
44
  cssClasses() {
49
- // This panel will be nameless when used in predefined layout (e.g. page.body, list.header, etc.)
50
- this.spec.view = this.spec.view || "panels/responsive";
51
- return this.$classes();
45
+ // Provide a default name so the panel will not be nameless when used in predefined layouts (e.g. page.body, list.header, etc.)
46
+ return this.$classes(
47
+ Object.assign(
48
+ {
49
+ view: "panels/responsive"
50
+ },
51
+ this.spec
52
+ )
53
+ );
52
54
  },
53
55
  componentName() {
54
- return this.$href() ? "a" : "div";
56
+ return this.spec.onClick ? "a" : "div";
55
57
  }
56
58
  },
57
59
  methods: {
@@ -91,7 +93,7 @@ export default {
91
93
  display: flex;
92
94
  flex-direction: column;
93
95
  }
94
- /* Needed to ensure that split's sub panels have the same height */
96
+ // Needed to ensure that split's sub panels have the same height
95
97
  .full-height {
96
98
  height: 100%;
97
99
  }
@@ -0,0 +1,50 @@
1
+ <template>
2
+ <v-tooltip
3
+ :disabled="tooltip.disabled"
4
+ :top="tooltipPositionMatches('top')"
5
+ :right="tooltipPositionMatches('right')"
6
+ :bottom="tooltipPositionMatches('bottom')"
7
+ :left="tooltipPositionMatches('left')"
8
+ >
9
+ <template v-slot:activator="{ on }">
10
+ <!-- Pass the slot props through to the caller using the same slot name (i.e. `activator`) -->
11
+ <slot name="activator" :on="on" />
12
+ </template>
13
+ <span> {{ tooltip.text }} </span>
14
+ </v-tooltip>
15
+ </template>
16
+
17
+ <script>
18
+ // import tooltipMixin from "./mixins/tooltip";
19
+
20
+ export default {
21
+ // mixins: [tooltipMixin],
22
+ props: {
23
+ spec: { type: Object, required: true }
24
+ },
25
+ data() {
26
+ return {
27
+ tooltip: {},
28
+ childSpec: Object.assign({}, this.spec, { id: undefined })
29
+ };
30
+ },
31
+ methods: {
32
+ $ready() {
33
+ this.tooltip = this.spec.tooltip || { disabled: true };
34
+ this.childSpec = Object.assign({}, this.spec, { id: undefined });
35
+ },
36
+ // $initAccessories() {
37
+ // this.tooltip = this.spec.tooltip || { disabled: true };
38
+ // },
39
+ tooltipPositionMatches(position) {
40
+ if (this.spec.tooltip && this.spec.tooltip.position) {
41
+ return position == this.spec.tooltip.position;
42
+ } else {
43
+ return position == "bottom";
44
+ }
45
+ }
46
+ }
47
+ };
48
+ </script>
49
+
50
+ <style lang="scss" scoped></style>
@@ -1,11 +1,5 @@
1
1
  <template>
2
- <v-tooltip
3
- :disabled="tooltip.disabled"
4
- :top="tooltipPositionMatches('top')"
5
- :right="tooltipPositionMatches('right')"
6
- :bottom="tooltipPositionMatches('bottom')"
7
- :left="tooltipPositionMatches('left')"
8
- >
2
+ <common-tooltip :spec="spec">
9
3
  <template v-slot:activator="{ on }">
10
4
  <common-badge :spec="spec">
11
5
  <v-avatar :size="spec.size">
@@ -14,31 +8,18 @@
14
8
  :style="$styles()"
15
9
  :src="spec.url || spec.base64Data"
16
10
  @click="$onClick()"
11
+ v-on="on"
17
12
  />
18
13
  </v-avatar>
19
14
  </common-badge>
20
15
  </template>
21
- <span>{{ tooltip.text }}</span>
22
- </v-tooltip>
16
+ </common-tooltip>
23
17
  </template>
24
18
 
25
19
  <script>
26
- import TooltipMixins from "./mixins/tooltip";
27
-
28
20
  export default {
29
- mixins: [TooltipMixins],
30
21
  props: {
31
22
  spec: { type: Object, required: true }
32
- },
33
- data() {
34
- return {
35
- styles: {}
36
- };
37
- },
38
- methods: {
39
- $ready() {
40
- this.$initAccessories();
41
- }
42
23
  }
43
24
  };
44
25
  </script>
@@ -1,41 +1,15 @@
1
1
  <template>
2
- <div>
3
- <v-tooltip
4
- :disabled="tooltip.disabled"
5
- :top="tooltipPositionMatches('top')"
6
- :right="tooltipPositionMatches('right')"
7
- :bottom="tooltipPositionMatches('bottom')"
8
- :left="tooltipPositionMatches('left')"
9
- >
10
- <template v-slot:activator="{ on }">
11
- <div v-on="on">
12
- <common-button :spec="childSpec" :disabled="$isBusy" />
13
- </div>
14
- </template>
15
- <span> {{ tooltip.text }} </span>
16
- </v-tooltip>
17
- </div>
2
+ <common-tooltip :spec="spec">
3
+ <template v-slot:activator="{ on }">
4
+ <common-button :spec="spec" :disabled="$isBusy" :event-handlers="on" />
5
+ </template>
6
+ </common-tooltip>
18
7
  </template>
19
8
 
20
9
  <script>
21
- import tooltipMixin from "./mixins/tooltip";
22
-
23
10
  export default {
24
- mixins: [tooltipMixin],
25
11
  props: {
26
12
  spec: { type: Object, required: true }
27
- },
28
- data() {
29
- return {
30
- tooltip: {},
31
- childSpec: Object.assign({}, this.spec, { id: undefined })
32
- };
33
- },
34
- methods: {
35
- $ready() {
36
- this.tooltip = this.spec.tooltip || { disabled: true };
37
- this.childSpec = Object.assign({}, this.spec, { id: undefined });
38
- }
39
13
  }
40
14
  };
41
15
  </script>
@@ -10,10 +10,10 @@
10
10
  // https://chartkick.com/vue
11
11
 
12
12
  import annotation from "../mixins/chart/annotation.js";
13
- import tooltip from "../mixins/chart/tooltip.js";
13
+ // import tooltip from "../mixins/chart/tooltip.js";
14
14
 
15
15
  export default {
16
- mixins: [annotation, tooltip],
16
+ mixins: [annotation],
17
17
  props: {
18
18
  spec: { type: Object, required: true }
19
19
  },
@@ -9,10 +9,10 @@
9
9
 
10
10
  <script>
11
11
  import annotation from "../mixins/chart/annotation.js";
12
- import tooltip from "../mixins/chart/tooltip.js";
12
+ // import tooltip from "../mixins/chart/tooltip.js";
13
13
 
14
14
  export default {
15
- mixins: [annotation, tooltip],
15
+ mixins: [annotation],
16
16
  props: {
17
17
  spec: { type: Object, required: true }
18
18
  },
@@ -3,28 +3,9 @@
3
3
  </template>
4
4
 
5
5
  <script>
6
- import TooltipMixins from "./mixins/tooltip";
7
6
  export default {
8
- mixins: [TooltipMixins],
9
7
  props: {
10
8
  spec: { type: Object, required: true }
11
- },
12
- data: function() {
13
- return {
14
- tooltip: {}
15
- };
16
- },
17
- methods: {
18
- $ready() {
19
- this.tooltip = this.spec.tooltip || {};
20
- }
21
9
  }
22
10
  };
23
11
  </script>
24
-
25
- <style lang="scss" scoped>
26
- // Prevent hover effect if the chip is not clickable.
27
- span.theme--light.v-chip:hover:before {
28
- opacity: 0;
29
- }
30
- </style>
@@ -60,12 +60,7 @@ export default {
60
60
  },
61
61
  methods: {
62
62
  $ready() {
63
- this.options = this.normalizedOptions();
64
- this.append = this.spec.append || {};
65
- this.rules = this.$validation();
66
- if (this.defaultValue) {
67
- this.fieldModel = this.defaultValue;
68
- }
63
+ this.updateData();
69
64
  },
70
65
  normalizedOptions() {
71
66
  return this.spec.options.map(i => {
@@ -88,6 +83,17 @@ export default {
88
83
  GLib.action.execute(onChange, this);
89
84
  });
90
85
  });
86
+ },
87
+ updateData() {
88
+ this.options = this.normalizedOptions();
89
+ this.append = this.spec.append || {};
90
+ this.rules = this.$validation();
91
+ if (this.defaultValue) {
92
+ this.fieldModel = this.defaultValue;
93
+ }
94
+ },
95
+ $registryEnabled() {
96
+ return false;
91
97
  }
92
98
  }
93
99
  };
@@ -1,13 +1,17 @@
1
1
  <template>
2
- <div :class="$classes()">
3
- <v-tooltip
2
+ <common-tooltip :spec="spec">
3
+ <template v-slot:activator="{ on }">
4
+ <!-- <common-button :spec="spec" :disabled="$isBusy" :event-handlers="on" /> -->
5
+
6
+ <div :class="$classes()">
7
+ <!-- <v-tooltip
4
8
  :disabled="tooltip.disabled"
5
9
  :top="tooltipPositionMatches('top')"
6
10
  :right="tooltipPositionMatches('right')"
7
11
  :bottom="tooltipPositionMatches('bottom')"
8
12
  :left="tooltipPositionMatches('left')"
9
13
  >
10
- <template v-slot:activator="{ on }">
14
+ <template v-slot:activator="{ on }"> -->
11
15
  <v-radio
12
16
  :label="spec.label"
13
17
  :value="spec.value.presence() || vuetifyEmptyString"
@@ -22,29 +26,31 @@
22
26
  <glib-component :spec="item" />
23
27
  </div>
24
28
  </div>
25
- </template>
29
+ <!-- </template>
26
30
  <span>{{ tooltip.text }}</span>
27
- </v-tooltip>
28
- </div>
31
+ </v-tooltip> -->
32
+ </div>
33
+ </template>
34
+ </common-tooltip>
29
35
  </template>
30
36
 
31
37
  <script>
32
- import TooltipMixins from "../mixins/tooltip";
38
+ // import TooltipMixins from "../mixins/tooltip";
33
39
 
34
40
  export default {
35
- mixins: [TooltipMixins],
41
+ // mixins: [TooltipMixins],
36
42
  props: {
37
43
  spec: { type: Object, required: true }
38
- },
39
- data() {
40
- return {
41
- tooltip: {}
42
- };
43
- },
44
- methods: {
45
- $ready() {
46
- this.tooltip = this.spec.tooltip || { disabled: true };
47
- }
48
44
  }
45
+ // data() {
46
+ // return {
47
+ // tooltip: {}
48
+ // };
49
+ // },
50
+ // methods: {
51
+ // $ready() {
52
+ // this.tooltip = this.spec.tooltip || { disabled: true };
53
+ // }
54
+ // }
49
55
  };
50
56
  </script>