glib-web 3.11.0 → 3.12.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.
package/action.js CHANGED
@@ -57,11 +57,12 @@ import ActionCommandsCustom from "./actions/commands/custom";
57
57
  const ActionToursStart = import("./actions/tours/start");
58
58
  const ActionToursStop = import("./actions/tours/stop");
59
59
 
60
- import ActionComponentsUpdate from "./actions/components/update";
61
-
62
60
  import ActionPopoversOpen from "./actions/popovers/open";
63
61
  import ActionPopoversClose from "./actions/popovers/close";
64
62
 
63
+ import ActionComponentsUpdate from "./actions/components/update";
64
+ import ActionComponentsFind from "./actions/components/find";
65
+
65
66
  import { vueApp } from "./store";
66
67
 
67
68
  const actions = {
@@ -119,11 +120,13 @@ const actions = {
119
120
  "commands/custom": ActionCommandsCustom,
120
121
 
121
122
  "tours/start": ActionToursStart,
122
- "components/update": ActionComponentsUpdate,
123
+ "tours/stop": ActionToursStop,
124
+
123
125
  "popovers/open": ActionPopoversOpen,
124
126
  "popovers/close": ActionPopoversClose,
125
- "tours/stop": ActionToursStop,
126
- "components/update": ActionComponentsUpdate
127
+
128
+ "components/update": ActionComponentsUpdate,
129
+ "components/find": ActionComponentsFind
127
130
  };
128
131
 
129
132
  const customActions = {};
@@ -179,17 +182,22 @@ export default class Action {
179
182
  }
180
183
  }
181
184
 
182
- static handleResponse(response, component, url) {
185
+ static handleResponse(response, component) {
186
+ vueApp.temp.analytics = response.analytics;
187
+ GLib.action.execute(response.onResponse, component);
188
+ vueApp.temp.analytics = null;
189
+
183
190
  // TODO: The execution should be in the following order: onResponse, page render, onLoad
184
191
  if (response.header || response.body || response.footer) {
185
192
  Utils.http.forceComponentUpdate(() => {
186
- vueApp.page = response;
193
+ const dialog = component.$closest("dialog");
194
+ if (dialog) {
195
+ dialog.updateContent(response)
196
+ } else {
197
+ vueApp.page = response;
198
+ }
187
199
  });
188
200
  }
189
-
190
- vueApp.temp.analytics = response.analytics;
191
- GLib.action.execute(response.onResponse, component);
192
- vueApp.temp.analytics = null;
193
201
  }
194
202
 
195
203
  static registerCustom(actionName, action) {
@@ -0,0 +1,6 @@
1
+ export default class {
2
+ execute(spec, component) {
3
+ const target = GLib.component.findById(spec.targetId);
4
+ Action.execute(spec.onFind, target);
5
+ }
6
+ }
@@ -1,5 +1,11 @@
1
+ import { nextTick } from "vue";
2
+
1
3
  export default class {
2
- execute(properties, component) {
3
- Utils.launch.popover.close(properties);
4
- }
4
+ execute(properties, component) {
5
+ Utils.launch.popover.close(properties);
6
+
7
+ nextTick(() => {
8
+ GLib.action.execute(properties.onClose, component);
9
+ })
10
+ }
5
11
  }
@@ -1,27 +1,26 @@
1
1
  import { watchEffect } from "vue";
2
- import { vueApp, glibevent, dialogStates } from "../../store";
2
+ import { glibevent, ctx } from "../../store";
3
3
 
4
4
  export function useDirtyState() {
5
- const ctx = dialogStates.slice(-1)[0] || vueApp;
6
5
  const prompt = "Changes you made have not been saved. Are you sure?";
7
6
 
8
7
  const isDirty = () => {
9
- return ctx.isFormDirty && !ctx.isFormSubmitted && !confirm(prompt);
8
+ return ctx().isFormDirty && !ctx().isFormSubmitted && !confirm(prompt);
10
9
  };
11
10
 
12
11
  const clearDirtyState = () => {
13
- ctx.isFormDirty = false;
12
+ ctx().isFormDirty = false;
14
13
  };
15
14
 
16
15
  const updateDirtyState = (val, oldVal, spec) => {
17
16
  if (!spec.disableDirtyCheck && val != oldVal && val != spec.value) {
18
- ctx.isFormDirty = true;
17
+ ctx().isFormDirty = true;
19
18
  }
20
19
  };
21
20
 
22
21
  const watchDirtyState = () => {
23
22
  return watchEffect(() => {
24
- if (ctx.isFormDirty) {
23
+ if (ctx().isFormDirty) {
25
24
  window.onbeforeunload = () => !isDirty();
26
25
  glibevent.onbeforewindowsopen = () => !isDirty();
27
26
  glibevent.onbeforewindowsclose = () => !isDirty();
@@ -81,10 +81,10 @@ export default {
81
81
  };
82
82
  </script>
83
83
 
84
- <style scoped>
84
+ <style lang="scss" scoped>
85
85
  .otp-input {
86
86
  display: inline-block;
87
- width: 2rem;
87
+ // width: 2rem;
88
88
  text-align: center;
89
89
  margin-right: 8px;
90
90
  margin-bottom: 8px;
@@ -5,7 +5,7 @@
5
5
  <input v-model="uncheckValue" type="hidden" :name="fieldName" />
6
6
  <v-checkbox v-model="fieldModel" :name="fieldName" :readonly="spec.readOnly" :disabled="inputDisabled"
7
7
  :label="fieldModel ? spec.onLabel || spec.label : spec.label" :true-icon="spec.onIcon" :false-icon="spec.offIcon"
8
- :value="spec.checkValue" hide-details @change="changed" color="primary"></v-checkbox>
8
+ :value="spec.value" :true-value="spec.checkValue" hide-details @change="changed" color="primary"></v-checkbox>
9
9
  </div>
10
10
  </template>
11
11
 
@@ -37,12 +37,6 @@ export default {
37
37
  this.$executeOnChange();
38
38
  // }, 500);
39
39
  },
40
- $internalizeValue(val) {
41
- if (val == this.spec.checkValue) {
42
- return val;
43
- }
44
- return this.spec.uncheckValue;
45
- },
46
40
  action_merge(mergedSpec) {
47
41
  Object.assign(this.spec, mergedSpec);
48
42
  this.updateData();
@@ -58,9 +52,9 @@ export default {
58
52
 
59
53
  this.fieldName = this.spec.name || groupName;
60
54
 
61
- this.fieldModel = this.spec.checked
62
- ? this.spec.checkValue
63
- : this.spec.value;
55
+ // this.fieldModel = this.spec.checked
56
+ // ? this.spec.checkValue
57
+ // : this.spec.value;
64
58
 
65
59
  Utils.type.ifArray(this.spec.styleClasses, classes => {
66
60
  if (classes.remove("switch")) {
@@ -20,6 +20,7 @@ export default {
20
20
  },
21
21
  data() {
22
22
  return {
23
+ localFieldModels: {},
23
24
  groupValues: [],
24
25
  template: {},
25
26
  templateViews: [],
@@ -35,9 +36,9 @@ export default {
35
36
 
36
37
  spec.groupFieldProperties.forEach((group, groupIndex) => {
37
38
  group.forEach((properties) => {
38
- const fullName = this.prefixFieldName(groupIndex, properties.name)
39
- this.setFieldModel(fullName, properties.value)
40
- })
39
+ const fullName = this.prefixFieldName(groupIndex, properties.name);
40
+ this.localFieldModels[fullName] = properties.value;
41
+ });
41
42
  });
42
43
 
43
44
  this.groupValues = spec.groupFieldProperties;
@@ -46,10 +47,10 @@ export default {
46
47
  },
47
48
  groupValues: {
48
49
  handler(groupValues) {
49
- var actualIndex = 0
50
+ var actualIndex = 0;
50
51
  this.groupSpecs = groupValues.map((group, groupIndex) => {
51
52
  if (!this.isDeleted(groupIndex)) {
52
- ++actualIndex
53
+ ++actualIndex;
53
54
  }
54
55
 
55
56
  const viewSpecs = this.processTemplate(
@@ -74,24 +75,24 @@ export default {
74
75
  // Replace every occurrence of `{{index}}` within any string.
75
76
  populateIndexes(object, groupIndex) {
76
77
  if (this.$type.isString(object)) {
77
- return object.replace('{{index}}', groupIndex)
78
+ return object.replace('{{index}}', groupIndex);
78
79
  }
79
80
  if (this.$type.isArray(object)) {
80
81
  return object.map((o) => this.populateIndexes(o, groupIndex));
81
82
 
82
83
  } else if (this.$type.isObject(object)) {
83
- const newObject = {}
84
+ const newObject = {};
84
85
  for (const key in object) {
85
- newObject[key] = this.populateIndexes(object[key], groupIndex)
86
+ newObject[key] = this.populateIndexes(object[key], groupIndex);
86
87
  }
87
- return newObject
88
+ return newObject;
88
89
  }
89
- return object
90
+ return object;
90
91
  },
91
92
  processTemplate(properties, groupIndex, processField, processNonField) {
92
93
  return this.processViews(
93
94
  this.templateViews, properties, groupIndex, processField, processNonField
94
- )
95
+ );
95
96
  },
96
97
  prefixFieldName(groupIndex, fieldName) {
97
98
  if (fieldName.search(/\[.*\]/) >= 0) {
@@ -101,33 +102,33 @@ export default {
101
102
  }
102
103
  },
103
104
  processField(viewSpec, name, groupIndex, properties) {
104
- const fullName = this.prefixFieldName(groupIndex, name)
105
- const indexedName = this.populateIndexes(fullName, groupIndex)
105
+ const fullName = this.prefixFieldName(groupIndex, name);
106
+ const indexedName = this.populateIndexes(fullName, groupIndex);
106
107
 
107
108
  // Note that `properties` might contain any properties such as fileTitle/fileUrl which
108
109
  // are needed by file components.
109
110
  Object.assign(viewSpec, properties[name], {
110
111
  name: fullName,
111
- value: this.getFieldModel(indexedName)
112
+ value: this.localFieldModels[indexedName]
112
113
  });
113
- return viewSpec
114
+ return viewSpec;
114
115
  },
115
116
  processViews(viewSpecs, properties, groupIndex) {
116
117
  return viewSpecs.map(origSpec => {
117
- const viewSpec = Object.assign({}, origSpec)
118
+ const viewSpec = Object.assign({}, origSpec);
118
119
 
119
- viewSpec.showIf = this.populateIndexes(viewSpec.showIf, groupIndex)
120
- viewSpec.loadIf = this.populateIndexes(viewSpec.loadIf, groupIndex)
120
+ viewSpec.showIf = this.populateIndexes(viewSpec.showIf, groupIndex);
121
+ viewSpec.loadIf = this.populateIndexes(viewSpec.loadIf, groupIndex);
121
122
 
122
123
  if (Utils.type.isString(viewSpec.name)) { // This is a field
123
124
  return this.processField(viewSpec, viewSpec.name, groupIndex, properties);
124
125
  }
125
126
 
126
127
  if (Utils.type.isObject(viewSpec.childViews)) {
127
- viewSpec.childViews = this.processViews(viewSpec.childViews, properties, groupIndex)
128
+ viewSpec.childViews = this.processViews(viewSpec.childViews, properties, groupIndex);
128
129
  }
129
130
 
130
- return viewSpec
131
+ return viewSpec;
131
132
  });
132
133
  },
133
134
  addGroup() {
@@ -87,8 +87,6 @@ export default {
87
87
  if (Utils.type.isString(this.spec.value)) {
88
88
  this.uploaded = true;
89
89
  this.fileTitle = this.spec.fileTitle;
90
-
91
- // TODO: Rename to fileUrl
92
90
  this.fileImage = this.spec.fileUrl;
93
91
  this.fileValue = this.spec.value;
94
92
  }
@@ -12,7 +12,7 @@
12
12
  use-custom-image-handler :editor-options="editorSettings" @text-change="onRichTextEditorChanged"
13
13
  @image-added="uploadImage" /> -->
14
14
  <QuillEditor v-if="!rawMode" ref="quilEditor" theme="snow" :toolbar="customToolbar" :content="richEditorValue"
15
- contentType="html" :modules="modules" @textChange="onRichTextEditorChanged" class="rich-editor" />
15
+ contentType="html" :modules="modules" @textChange="onRichTextEditorChanged" class="rich-editor" :placeholder="spec.placeholder" />
16
16
  <!-- Hide these fields but don't remove them because these are the values that will get submitted. -->
17
17
  <div :style="{ display: rawMode ? 'block' : 'none' }">
18
18
  <v-textarea class="raw-editor" v-model="rawEditorValue" :style="$styles()" :class="$classes()"
@@ -126,7 +126,7 @@ export default {
126
126
  },
127
127
  _ready() {
128
128
  this._mountedUrl = window.location.href;
129
- this._updatedAt = new Date().getTime();
129
+ // this._updatedAt = new Date().getTime();
130
130
 
131
131
  this.$data._events = [];
132
132
 
@@ -2,12 +2,18 @@ import { vueApp } from "../../store";
2
2
 
3
3
  export default {
4
4
  methods: {
5
+ $componentName() { // Can be overridden
6
+ if (this.spec) {
7
+ return this.spec.view;
8
+ }
9
+ },
5
10
  $closest(name) {
6
11
  var parent = this.$parent;
7
12
  while (parent != null) {
8
13
  if (
9
14
  (Utils.type.isObject(parent.spec) || Utils.type.isObject(parent.formSpec)) &&
10
- GLib.component.vueName(parent) == name
15
+ parent.$componentName() == name
16
+ // GLib.component.vueName(parent) == name
11
17
  ) {
12
18
  return parent;
13
19
  }
@@ -73,7 +73,7 @@ export default {
73
73
  methods: {
74
74
  _initConditional(oldSpec) {
75
75
  // unreg old fieldName
76
- if (oldSpec && fieldModels[oldSpec.name]) {
76
+ if (oldSpec && fieldModels[oldSpec.name] && oldSpec.name != this.spec.name) {
77
77
  delete fieldModels[oldSpec.name];
78
78
  }
79
79
  // unreg watchers if there is
package/nav/appbar.vue CHANGED
@@ -91,7 +91,8 @@ export default {
91
91
  },
92
92
  buttonSpec(item) {
93
93
  const styleClasses = (item.styleClasses || []).concat(
94
- item.text ? ["text"] : ["icon"]
94
+ // item.text ? ["text"] : ["icon"]
95
+ ["text"]
95
96
  );
96
97
  return Object.assign({}, item, {
97
98
  view: "button",
package/nav/dialog.vue CHANGED
@@ -174,13 +174,10 @@ export default {
174
174
  Http.execute({ url: url }, "GET", this, (response) => {
175
175
  Utils.http.forceComponentUpdate(() => {
176
176
  this.urlLoaded = true;
177
- this.title = response.title;
178
177
  this.message = "";
179
178
  this.formSpec = response.fullPageForm;
180
- this.header = response.header;
181
- this.body = response.body;
182
- this.footer = response.footer;
183
179
  this.disableCloseButton = this.spec.disableCloseButton || false;
180
+ this.updateContent(response)
184
181
 
185
182
  Action.execute(response.onLoad, this);
186
183
  });
@@ -196,8 +193,17 @@ export default {
196
193
 
197
194
  this.model = true;
198
195
  },
196
+ updateContent(response) {
197
+ this.title = response.title;
198
+ this.header = response.header;
199
+ this.body = response.body;
200
+ this.footer = response.footer;
201
+ },
199
202
  updateMainHeight() {
200
203
  this.mainHeight = window.innerHeight - 140;
204
+ },
205
+ $componentName() {
206
+ return "dialog";
201
207
  }
202
208
  }
203
209
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "glib-web",
3
- "version": "3.11.0",
3
+ "version": "3.12.0",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/store.js CHANGED
@@ -19,6 +19,8 @@ export const vueApp = reactive({
19
19
 
20
20
  export const dialogStates = reactive([]);
21
21
 
22
+ export const ctx = () => dialogStates.slice(-1)[0] || vueApp;
23
+
22
24
  export const glibevent = reactive({
23
25
  onbeforewindowsopen: null,
24
26
  onbeforewindowsclose: null,
package/utils/form.js CHANGED
@@ -1,4 +1,4 @@
1
- import { vueApp } from "../store";
1
+ import { ctx } from "../store";
2
2
 
3
3
  export default class {
4
4
  // Execution flows:
@@ -17,7 +17,7 @@ export default class {
17
17
 
18
18
  // Use nextTick to wait for overrideUrl get picked up.
19
19
  component.$nextTick(() => {
20
- vueApp.isFormDirty = false;
20
+ ctx().isFormDirty = false;
21
21
  form.submit();
22
22
  });
23
23
  } else {
package/utils/http.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import Type from "./type";
2
2
  import Action from "../action";
3
3
  import { nextTick } from 'vue';
4
- import { vueApp } from "../store";
4
+ import { ctx, vueApp } from "../store";
5
5
 
6
6
  let loading = false;
7
7
 
@@ -80,7 +80,8 @@ export default class {
80
80
  const htmlUrl = Utils.url.htmlUrl(properties["url"]);
81
81
 
82
82
  Utils.http.execute(properties, "GET", component, (data, response) => {
83
- if (htmlUrl !== currentUrl) {
83
+ const dialog = component.$closest("dialog");
84
+ if (htmlUrl !== currentUrl && !Utils.type.isObject(dialog)) {
84
85
  const redirectUrl = Utils.url.htmlUrl(response.url);
85
86
  Utils.history.pushPage(data, redirectUrl);
86
87
  }
@@ -88,7 +89,7 @@ export default class {
88
89
  this.forceComponentUpdate(() => {
89
90
  Utils.history.resetScroll();
90
91
 
91
- vueApp.page = data;
92
+ GLib.action.handleResponse(data, component)
92
93
 
93
94
  Action.execute(properties["onOpen"], component);
94
95
  });
@@ -258,8 +259,8 @@ export default class {
258
259
  static forceComponentUpdate(handler) {
259
260
  // GLib.component.clearRegistry();
260
261
  vueApp.isStale = true;
261
- vueApp.isFormSubmitted = false;
262
- vueApp.isFormDirty = false;
262
+ ctx().isFormSubmitted = false;
263
+ ctx().isFormDirty = false;
263
264
  handler();
264
265
 
265
266
  // Queue the execution so the first isStale has time to resets state before handler gets executed
@@ -273,7 +274,7 @@ export default class {
273
274
  // }
274
275
 
275
276
  static notifyFormSubmitted() {
276
- vueApp.isFormSubmitted = true;
277
+ ctx().isFormSubmitted = true;
277
278
  }
278
279
 
279
280
  // `context` can be either window or dialog.
package/utils/launch.js CHANGED
@@ -149,9 +149,11 @@ class LaunchDialog {
149
149
  dialog.close();
150
150
  });
151
151
 
152
- Utils.type.ifObject(properties["onClose"], it => {
153
- Action.execute(it, component);
154
- });
152
+ Action.execute(properties.onClose, component);
153
+
154
+ // Utils.type.ifObject(properties["onClose"], it => {
155
+ // Action.execute(it, component);
156
+ // });
155
157
  }
156
158
 
157
159
  // This is only meant to be used internally