glib-web 1.0.1 → 2.1.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.
@@ -1,5 +1,7 @@
1
1
  export default class {
2
2
  execute(properties, component) {
3
- component.$dispatchEvent("forms/directSubmit");
3
+ component.$dispatchEvent("forms/directSubmit", {
4
+ url: properties.overrideUrl
5
+ });
4
6
  }
5
7
  }
@@ -1,20 +1,10 @@
1
1
  <template>
2
2
  <div :style="genericStyles()" :class="$classes()">
3
3
  <div v-for="(group, groupIndex) in groupSpecs" :key="`group${groupIndex}`">
4
- <input
5
- v-if="isDeleted(groupIndex)"
6
- type="hidden"
7
- :name="`${spec.name}[${groupIndex}][_destroy]`"
8
- value="1"
9
- />
4
+ <input v-if="isDeleted(groupIndex)" type="hidden" :name="`${spec.name}[${groupIndex}][_destroy]`" value="1" />
10
5
  <div :style="{ display: isDeleted(groupIndex) ? 'none' : 'block' }">
11
- <v-icon
12
- class="float-left mr-2"
13
- color="error"
14
- @click="removeGroup(groupIndex)"
15
- >remove_circle</v-icon
16
- >
17
- <h4>{{ spec.titlePrefix }} {{ groupIndex + 1 }}</h4>
6
+ <v-icon class="float-left mr-2" color="error" @click="removeGroup(groupIndex)">remove_circle</v-icon>
7
+ <h4 v-if="spec.titlePrefix">{{ spec.titlePrefix }} {{ groupIndex + 1 }}</h4>
18
8
  <panels-responsive :spec="group" />
19
9
  </div>
20
10
  </div>
@@ -5,7 +5,7 @@
5
5
  v-model="rawValue"
6
6
  :editor-toolbar="customToolbar"
7
7
  use-custom-image-handler
8
- @text-change="separateOutImages"
8
+ @text-change="onChange"
9
9
  @image-added="uploadImage"
10
10
  />
11
11
  <input type="hidden" :name="spec.name" :value="produceValue" />
@@ -127,6 +127,22 @@ export default {
127
127
  });
128
128
  }
129
129
  },
130
+ onChange() {
131
+ this.separateOutImages();
132
+
133
+ Utils.type.ifObject(this.spec.onChange, onChange => {
134
+ this.$nextTick(() => {
135
+ const params = {
136
+ [this.spec.paramNameForFormData || "formData"]: {
137
+ [this.fieldName]: this.fieldModel
138
+ }
139
+ };
140
+
141
+ const data = Object.assign({}, onChange, params);
142
+ GLib.action.execute(data, this);
143
+ });
144
+ });
145
+ },
130
146
  separateOutImages: function() {
131
147
  const vm = this;
132
148
  var index = 0;
@@ -39,26 +39,35 @@
39
39
  :clickable="true"
40
40
  :title="String(marker.clusterSize || 1)"
41
41
  @click="onMarkerClick(marker, index)"
42
- ></gmap-marker>
42
+ >
43
+ </gmap-marker>
43
44
  </gmap-cluster>
44
45
  <template v-else>
45
- <gmap-marker
46
+ <gmap-custom-marker
46
47
  v-for="(marker, index) in markers"
47
48
  :key="index"
48
- :position="{ lat: marker.latitude, lng: marker.longitude }"
49
- :clickable="true"
50
- @click="onMarkerClick(marker, index)"
51
- ></gmap-marker>
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>
52
59
  </template>
53
60
  </gmap-map>
54
61
  </template>
55
62
 
56
63
  <script>
57
64
  import GmapCluster from "vue2-google-maps/dist/components/cluster";
65
+ import GmapCustomMarker from "vue2-gmap-custom-marker";
58
66
 
59
67
  export default {
60
68
  components: {
61
- "gmap-cluster": GmapCluster
69
+ "gmap-cluster": GmapCluster,
70
+ "gmap-custom-marker": GmapCustomMarker
62
71
  },
63
72
  props: {
64
73
  spec: { type: Object, required: true }
@@ -204,3 +213,11 @@ export default {
204
213
  // }
205
214
  };
206
215
  </script>
216
+
217
+ <style lang="scss" scoped>
218
+ .marker {
219
+ width: 40px;
220
+ height: 40px;
221
+ cursor: pointer;
222
+ }
223
+ </style>
@@ -64,7 +64,7 @@ export default {
64
64
  });
65
65
 
66
66
  this.$onEvent("forms/directSubmit", e => {
67
- this.directSubmit();
67
+ this.directSubmit(e.data.url);
68
68
  });
69
69
  },
70
70
  $ready() {
@@ -117,10 +117,14 @@ export default {
117
117
  );
118
118
  });
119
119
  },
120
- directSubmit() {
121
- this.validate(() => {
122
- GLib.form.submitData(this.formElement, this);
123
- });
120
+ directSubmit(overrideUrl = null) {
121
+ if (overrideUrl) {
122
+ GLib.form.submitData(this.formElement, this, overrideUrl);
123
+ } else {
124
+ this.validate(() => {
125
+ GLib.form.submitData(this.formElement, this);
126
+ });
127
+ }
124
128
  },
125
129
  validate(onPassed) {
126
130
  if (this.$refs.form.validate()) {
@@ -1,42 +1,32 @@
1
1
  <template>
2
2
  <v-container :class="$classes()">
3
- <v-timeline v-if="items" dense align-top>
3
+ <v-timeline v-if="events" dense align-top>
4
4
  <v-timeline-item
5
- v-for="(item, item_key) in items"
6
- :key="item_key"
5
+ v-for="(item, index) in events"
6
+ :key="index"
7
7
  color="white"
8
8
  fill-dot
9
9
  :small="$classes().includes('small')"
10
10
  :large="$classes().includes('large')"
11
- :class="timelineItemClasses(item)"
11
+ class="my-6"
12
12
  :hide-dot="item.hide_dot"
13
13
  >
14
14
  <template v-slot:icon>
15
- <div
16
- :class="$classes().includes('outlined') ? 'outlined-dots' : ''"
17
- :style="`border-color: ${dotColor(item)};`"
18
- >
19
- <div v-if="item.left_label" class="number-circle">
20
- {{ item.left_label }}
15
+ <div :class="$classes().includes('outlined') ? 'outlined-dots' : ''">
16
+ <div v-if="item.label" class="number-circle">
17
+ {{ item.label }}
18
+ </div>
19
+ <div v-else class="icon">
20
+ <common-icon
21
+ :spec="{
22
+ material: { name: item.icon, size: iconSize() },
23
+ color: item.color
24
+ }"
25
+ />
21
26
  </div>
22
- <!-- TODO: Use common-icon -->
23
- <v-icon v-else size="24" :color="dotColor(item)">
24
- {{ dotIcon(item) }}
25
- </v-icon>
26
27
  </div>
27
28
  </template>
28
-
29
- <div :class="item.subtitle ? 'mt-5' : 'mt-2'" class="content">
30
- <div
31
- :class="item.active ? 'font-weight-bold' : 'font-weight-regular'"
32
- >
33
- {{ item.label }}
34
- </div>
35
- <div class="font-weight-regular">
36
- {{ item.subtitle }}
37
- </div>
38
- <panels-responsive v-if="item.active" :spec="spec" />
39
- </div>
29
+ <panels-responsive :spec="{ childViews: [childViews[index]] }" />
40
30
  </v-timeline-item>
41
31
  </v-timeline>
42
32
  </v-container>
@@ -49,32 +39,17 @@ export default {
49
39
  },
50
40
  data() {
51
41
  return {
52
- items: this.spec.items,
53
- uncompletedIcon: this.spec.uncompletedIcon || "check_circle",
54
- completedIcon: this.spec.completedIcon || "radio_button_unchecked",
55
- completedColor: this.spec.completedColor || "blue",
56
- uncompletedColor: this.spec.uncompletedColor || "grey"
42
+ events: null,
43
+ childViews: null
57
44
  };
58
45
  },
59
46
  methods: {
60
- timelineItemClasses(item) {
61
- let classes = !item.completed && !item.active ? "uncompleted" : "";
62
-
63
- if (!this.$classes().includes("small")) {
64
- classes += " my-6";
65
- }
66
-
67
- return classes;
68
- },
69
- dotColor(item) {
70
- return !item.completed && !item.active
71
- ? this.uncompletedColor
72
- : this.completedColor;
47
+ $ready() {
48
+ this.events = this.spec.events;
49
+ this.childViews = this.spec.childViews;
73
50
  },
74
- dotIcon(item) {
75
- return item.active || item.completed
76
- ? item.uncompletedIcon || this.uncompletedIcon
77
- : item.completedIcon || this.completedIcon
51
+ iconSize() {
52
+ return this.$classes().includes("small") ? 16 : 24;
78
53
  }
79
54
  }
80
55
  };
@@ -84,18 +59,12 @@ export default {
84
59
  .v-timeline {
85
60
  padding-top: 0px;
86
61
  }
87
-
88
62
  .v-timeline-item {
89
63
  padding-bottom: 0px !important;
90
64
  }
91
65
  .container {
92
66
  padding-top: 0px;
93
67
  }
94
- .small {
95
- > .number-circle {
96
- font-size: 14px;
97
- }
98
- }
99
68
  .outlined-dots {
100
69
  border-radius: 50%;
101
70
  width: 100%;
@@ -111,4 +80,18 @@ export default {
111
80
  box-shadow: none;
112
81
  }
113
82
  }
83
+ .icon {
84
+ display: inline-flex;
85
+ vertical-align: middle;
86
+ }
87
+
88
+ // Size variations
89
+ .number-circle {
90
+ font-size: 16px;
91
+ }
92
+ .small {
93
+ .number-circle {
94
+ font-size: 14px;
95
+ }
96
+ }
114
97
  </style>
package/nav/appbar.vue CHANGED
@@ -1,22 +1,11 @@
1
1
  <template>
2
2
  <div>
3
- <nav-drawer
4
- v-if="page.leftDrawer"
5
- :trigger="drawerTrigger"
6
- :permanent="isPermanent"
7
- :spec="page.leftDrawer"
8
- />
3
+ <nav-drawer v-if="page.leftDrawer" :trigger="drawerTrigger" :permanent="isPermanent" :spec="page.leftDrawer" />
9
4
 
10
- <v-toolbar :style="style" :height="navBar.height" :class="cssClasses()">
11
- <v-app-bar-nav-icon
12
- v-if="page.leftDrawer && !isPermanent"
13
- style="color: inherit;"
14
- @click="drawerTrigger = new Date()"
15
- ></v-app-bar-nav-icon>
16
- <v-progress-circular
17
- v-if="$root.vueApp.indicator"
18
- indeterminate
19
- ></v-progress-circular>
5
+ <v-toolbar v-if="navBar.height" :style="style" :height="navBar.height" :class="cssClasses()">
6
+ <v-app-bar-nav-icon v-if="page.leftDrawer && !isPermanent" style="color: inherit;"
7
+ @click="drawerTrigger = new Date()"></v-app-bar-nav-icon>
8
+ <v-progress-circular v-if="$root.vueApp.indicator" indeterminate></v-progress-circular>
20
9
  <div v-else>
21
10
  <panels-responsive v-if="navBar.logo" :spec="navBar.logo" />
22
11
  <v-toolbar-title v-else-if="navBar.showTitle">{{
@@ -28,35 +17,16 @@
28
17
  <!-- See https://codesandbox.io/embed/14ry9r3lll -->
29
18
  <v-toolbar-items class="hidden-sm-and-down">
30
19
  <template v-for="(btn, index) in navBar.rightButtons">
31
- <common-dropdownMenu
32
- v-if="btn.childButtons"
33
- :key="index"
34
- :spec="btn"
35
- :disabled="$isBusy"
36
- />
37
- <common-button
38
- v-else
39
- :key="`right_${index}`"
40
- :spec="buttonSpec(btn)"
41
- :disabled="$isBusy"
42
- />
20
+ <common-dropdownMenu v-if="btn.childButtons" :key="index" :spec="btn" :disabled="$isBusy" />
21
+ <common-button v-else :key="`right_${index}`" :spec="buttonSpec(btn)" :disabled="$isBusy" />
43
22
  </template>
44
23
  </v-toolbar-items>
45
24
 
46
- <common-dropdownMenu
47
- v-if="showMobileMenu"
48
- class="hidden-md-and-up"
49
- :spec="mobileMenu"
50
- />
25
+ <common-dropdownMenu v-if="showMobileMenu" class="hidden-md-and-up" :spec="mobileMenu" />
51
26
 
52
27
  <views-avatar v-if="navBar.imageUrl" :spec="avatarSpec(navBar)" />
53
28
 
54
- <v-btn
55
- v-if="viewSourceEnabled()"
56
- icon
57
- style="color: inherit;"
58
- @click="viewSource"
59
- >
29
+ <v-btn v-if="viewSourceEnabled()" icon style="color: inherit;" @click="viewSource">
60
30
  <v-icon>zoom_in</v-icon>
61
31
  </v-btn>
62
32
  </v-toolbar>
@@ -75,7 +45,7 @@ export default {
75
45
  props: {
76
46
  page: { type: Object, required: true }
77
47
  },
78
- data: function() {
48
+ data: function () {
79
49
  return {
80
50
  drawerTrigger: null,
81
51
  navBar: {},
@@ -84,11 +54,11 @@ export default {
84
54
  };
85
55
  },
86
56
  computed: {
87
- style: function() {
57
+ style: function () {
88
58
  return Object.assign(this.genericStyles(this.navBar), this.leftPadding);
89
59
  },
90
60
  // We could've used the `app` attribute on `v-toolbar` if it didn't conflict with our header-footer css.
91
- leftPadding: function() {
61
+ leftPadding: function () {
92
62
  switch (this.$vuetify.breakpoint.name) {
93
63
  case "lg":
94
64
  case "xl":
@@ -124,11 +94,11 @@ export default {
124
94
  styleClasses: styleClasses
125
95
  });
126
96
  },
127
- viewSourceEnabled: function() {
97
+ viewSourceEnabled: function () {
128
98
  // return process.env.NODE_ENV === "development";
129
99
  return false;
130
100
  },
131
- viewSource: function() {
101
+ viewSource: function () {
132
102
  const properties = { message: this.page };
133
103
  Utils.launch.dialog.open(Object.assign({}, properties));
134
104
  },
@@ -157,11 +127,13 @@ export default {
157
127
  &.icon {
158
128
  color: inherit;
159
129
  }
130
+
160
131
  &.text {
161
132
  color: inherit;
162
133
  }
163
134
  }
164
135
  }
136
+
165
137
  .pages-navBar {
166
138
  box-shadow: none !important;
167
139
  }
package/nav/drawer.vue CHANGED
@@ -51,6 +51,7 @@
51
51
  // import UrlUtils from "../utils/url";
52
52
  import NavDrawerButton from "./drawerButton";
53
53
  import NavDrawerLabel from "./drawerLabel";
54
+ import bus from "../utils/eventBus";
54
55
 
55
56
  export default {
56
57
  components: {
@@ -102,12 +103,10 @@ export default {
102
103
  methods: {
103
104
  $ready() {
104
105
  this.shrunk = this.mini = this.cssClasses.includes("mini");
105
-
106
- // this.$el.addEventListener('drawers/clickButton', () => { this.updateState(false) }, false)
107
- this.$el.addEventListener("drawers/clickButton", () => {
108
- if (!this.permanent) {
109
- this.updateState(false);
110
- }
106
+ },
107
+ $mounted() {
108
+ bus.$on("drawers/toggle", () => {
109
+ this.updateState(!this.state);
111
110
  });
112
111
  },
113
112
  updateState(state) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "glib-web",
3
- "version": "1.0.1",
3
+ "version": "2.1.1",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -30,6 +30,7 @@
30
30
  "vue-youtube": "^1.4.0",
31
31
  "vue2-editor": "^2.9.1",
32
32
  "vue2-google-maps": "^0.10.6",
33
+ "vue2-gmap-custom-marker": "^6.1.1",
33
34
  "vuedraggable": "^2.24.1",
34
35
  "vuetify": "2.3.9"
35
36
  },
@@ -44,4 +45,4 @@
44
45
  "eslint-plugin-vuetify": "^1.0.0-beta.3",
45
46
  "prettier": "^1.18.2"
46
47
  }
47
- }
48
+ }
@@ -0,0 +1,2 @@
1
+ import Vue from "vue";
2
+ export default new Vue();
package/utils/form.js CHANGED
@@ -3,14 +3,14 @@ export default class {
3
3
  // Button -> Button.onClick() -> Utils.http.execute() -- doesn't save autofill values
4
4
  // Button -> Button.onClick() -> form.submit() -- doesn't execute Form.onSubmit(), so cannot call Utils.http.execute() there
5
5
  // Submit -> Form.onSubmit() -> Utils.http.execute() -- save autofill values and auto-submit when ENTER is pressed
6
- static submitData(form, component) {
6
+ static submitData(form, component, overrideUrl = null) {
7
7
  // Analogous to Rails' form_with's `local: true`
8
8
  if (form.dataset.local) {
9
9
  // Prevent onUnload dirty prompt.
10
10
  Utils.http.clearDirtyState();
11
11
  form.submit();
12
12
  } else {
13
- const url = form.getAttribute("action");
13
+ const url = overrideUrl ? overrideUrl : form.getAttribute("action");
14
14
  const formData = new FormData(form);
15
15
  const method = form.getAttribute("method");
16
16
  if (method.toUpperCase() === "GET") {