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.
- package/actions/forms/submit.js +3 -1
- package/components/fields/dynamicGroup.vue +3 -13
- package/components/fields/richText.vue +17 -1
- package/components/map.vue +24 -7
- package/components/panels/form.vue +9 -5
- package/components/panels/timeline.vue +37 -54
- package/nav/appbar.vue +16 -44
- package/nav/drawer.vue +5 -6
- package/package.json +3 -2
- package/utils/eventBus.js +2 -0
- package/utils/form.js +2 -2
package/actions/forms/submit.js
CHANGED
|
@@ -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
|
-
|
|
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="
|
|
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;
|
package/components/map.vue
CHANGED
|
@@ -39,26 +39,35 @@
|
|
|
39
39
|
:clickable="true"
|
|
40
40
|
:title="String(marker.clusterSize || 1)"
|
|
41
41
|
@click="onMarkerClick(marker, index)"
|
|
42
|
-
|
|
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
|
-
:
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
|
|
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="
|
|
3
|
+
<v-timeline v-if="events" dense align-top>
|
|
4
4
|
<v-timeline-item
|
|
5
|
-
v-for="(item,
|
|
6
|
-
: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
|
-
|
|
11
|
+
class="my-6"
|
|
12
12
|
:hide-dot="item.hide_dot"
|
|
13
13
|
>
|
|
14
14
|
<template v-slot:icon>
|
|
15
|
-
<div
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
<div v-
|
|
20
|
-
|
|
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
|
-
|
|
53
|
-
|
|
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
|
-
|
|
61
|
-
|
|
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
|
-
|
|
75
|
-
return
|
|
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
|
-
|
|
13
|
-
|
|
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
|
-
|
|
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
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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.
|
|
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
|
+
}
|
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") {
|