glib-web 3.5.3 → 3.5.4
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/windows/close.js +5 -0
- package/actions/windows/open.js +6 -1
- package/actions/windows/reload.js +5 -1
- package/app.vue +4 -1
- package/components/composable/dirtyState.js +39 -0
- package/components/fab.vue +8 -22
- package/components/fields/_select.vue +11 -1
- package/components/fields/location.vue +3 -3
- package/components/image.vue +15 -10
- package/components/mixins/styles.js +28 -22
- package/nav/dialog.vue +27 -13
- package/package.json +1 -1
- package/plugins/updatableComponent.js +26 -26
- package/store.js +17 -1
- package/utils/component.js +4 -4
- package/utils/form.js +4 -1
- package/utils/http.js +18 -25
package/actions/windows/close.js
CHANGED
|
@@ -3,6 +3,11 @@ import { vueApp } from "../../store";
|
|
|
3
3
|
export default class {
|
|
4
4
|
execute(properties, component) {
|
|
5
5
|
vueApp.richTextValues = {};
|
|
6
|
+
|
|
7
|
+
if (!executeGlobalEvent('onbeforewindowsclose')) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
|
|
6
11
|
Utils.history.back();
|
|
7
12
|
|
|
8
13
|
Utils.type.ifObject(properties["onClose"], it => {
|
package/actions/windows/open.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
import { vueApp } from "../../store";
|
|
1
|
+
import { executeGlobalEvent, vueApp } from "../../store";
|
|
2
2
|
|
|
3
3
|
export default class {
|
|
4
4
|
execute(properties, component) {
|
|
5
5
|
vueApp.richTextValues = {};
|
|
6
|
+
|
|
7
|
+
if (!executeGlobalEvent('onbeforewindowsopen')) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
|
|
6
11
|
Utils.http.load(properties, component);
|
|
7
12
|
}
|
|
8
13
|
}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import { vueApp } from "../../store";
|
|
1
|
+
import { executeGlobalEvent, vueApp } from "../../store";
|
|
2
2
|
|
|
3
3
|
export default class {
|
|
4
4
|
execute(properties, component) {
|
|
5
5
|
vueApp.richTextValues = {};
|
|
6
6
|
|
|
7
|
+
if (!executeGlobalEvent('onbeforewindowsreload')) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
|
|
7
11
|
if (Utils.settings.reactive) {
|
|
8
12
|
Utils.http.reload(properties, component);
|
|
9
13
|
} else {
|
package/app.vue
CHANGED
|
@@ -33,6 +33,9 @@ import Utils from "./utils/helper";
|
|
|
33
33
|
// import actionCableMixin from "./components/mixins/ws/actionCable.js";
|
|
34
34
|
import FormPanel from "./components/panels/form.vue";
|
|
35
35
|
import { vueApp } from "./store";
|
|
36
|
+
import { useDirtyState } from "./components/composable/dirtyState";
|
|
37
|
+
|
|
38
|
+
const { watchDirtyState } = useDirtyState();
|
|
36
39
|
|
|
37
40
|
export default {
|
|
38
41
|
components: {
|
|
@@ -88,7 +91,7 @@ export default {
|
|
|
88
91
|
);
|
|
89
92
|
Utils.history.saveInitialContent(this.page);
|
|
90
93
|
Utils.history.restoreOnBackOrForward();
|
|
91
|
-
|
|
94
|
+
watchDirtyState();
|
|
92
95
|
},
|
|
93
96
|
methods: {
|
|
94
97
|
$mounted() {
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { watchEffect } from "vue";
|
|
2
|
+
import { vueApp, glibevent, dialogStates } from "../../store";
|
|
3
|
+
|
|
4
|
+
export function useDirtyState() {
|
|
5
|
+
const ctx = dialogStates.slice(-1)[0] || vueApp;
|
|
6
|
+
const prompt = "Changes you made have not been saved. Are you sure?";
|
|
7
|
+
|
|
8
|
+
const isDirty = () => {
|
|
9
|
+
return ctx.isFormDirty && !ctx.isFormSubmitted && !confirm(prompt);
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const clearDirtyState = () => {
|
|
13
|
+
ctx.isFormDirty = false;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const updateDirtyState = (val, oldVal, spec) => {
|
|
17
|
+
if (!spec.disableDirtyCheck && val != oldVal && val != spec.value) {
|
|
18
|
+
ctx.isFormDirty = true;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const watchDirtyState = () => {
|
|
23
|
+
return watchEffect(() => {
|
|
24
|
+
if (ctx.isFormDirty) {
|
|
25
|
+
window.onbeforeunload = () => !isDirty();
|
|
26
|
+
glibevent.onbeforewindowsopen = () => !isDirty();
|
|
27
|
+
glibevent.onbeforewindowsclose = () => !isDirty();
|
|
28
|
+
glibevent.onbeforewindowsreload = () => !isDirty();
|
|
29
|
+
} else {
|
|
30
|
+
window.onbeforeunload = null;
|
|
31
|
+
glibevent.onbeforewindowsopen = null;
|
|
32
|
+
glibevent.onbeforewindowsclose = null;
|
|
33
|
+
glibevent.onbeforewindowsreload = null;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
return { clearDirtyState, updateDirtyState, watchDirtyState, isDirty };
|
|
39
|
+
}
|
package/components/fab.vue
CHANGED
|
@@ -1,33 +1,19 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
:disabled="$isBusy"
|
|
6
|
-
:style="genericStyles()"
|
|
7
|
-
:class="$classes()"
|
|
8
|
-
:href="$href()"
|
|
9
|
-
:rel="$rel()"
|
|
10
|
-
fab
|
|
11
|
-
fixed
|
|
12
|
-
bottom
|
|
13
|
-
right
|
|
14
|
-
>
|
|
15
|
-
<!-- Using `white--text` as recommended in https://github.com/vuetifyjs/vuetify/issues/1030 -->
|
|
16
|
-
<common-icon v-if="spec.icon" :spec="spec.icon" class="white--text" />
|
|
17
|
-
</v-btn>
|
|
2
|
+
<div class="fab">
|
|
3
|
+
<common-button :spec="spec"></common-button>
|
|
4
|
+
</div>
|
|
18
5
|
</template>
|
|
19
6
|
|
|
20
7
|
<script>
|
|
21
8
|
export default {
|
|
22
9
|
props: ['spec']
|
|
23
|
-
}
|
|
10
|
+
};
|
|
24
11
|
</script>
|
|
25
12
|
|
|
26
13
|
<style scoped>
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
14
|
+
.fab {
|
|
15
|
+
position: fixed;
|
|
16
|
+
right: 48px;
|
|
17
|
+
bottom: 24px;
|
|
31
18
|
}
|
|
32
|
-
|
|
33
19
|
</style>
|
|
@@ -4,7 +4,17 @@
|
|
|
4
4
|
:multiple="spec.multiple" :disabled="spec.readOnly" :clearable="!spec.readOnly" :hint="spec.hint"
|
|
5
5
|
:placeholder="spec.placeholder" :rules="rules" persistent-hint :append-icon="append.icon" validate-on="blur"
|
|
6
6
|
item-title='text' :variant="variant" :closable-chips="spec.multiple" :density="density" persistent-placeholder
|
|
7
|
-
@update:modelValue="onChange"
|
|
7
|
+
@update:modelValue="onChange">
|
|
8
|
+
|
|
9
|
+
<template #item="data">
|
|
10
|
+
<v-list-subheader v-if="data.props.title.header">
|
|
11
|
+
{{ data.props.title.header }}
|
|
12
|
+
</v-list-subheader>
|
|
13
|
+
<v-divider v-else-if="data.props.title.divider"></v-divider>
|
|
14
|
+
<v-list-item v-else v-bind="data.props" />
|
|
15
|
+
</template>
|
|
16
|
+
|
|
17
|
+
</v-autocomplete>
|
|
8
18
|
|
|
9
19
|
<input v-for="(item, index) in values" :key="index" type="hidden" :name="fieldName" :value="item" />
|
|
10
20
|
</div>
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
<div ref="map" class="map"></div>
|
|
7
7
|
|
|
8
8
|
<div style="padding-top: 8px">
|
|
9
|
-
<fields-text ref="latField" v-if="spec.latitudeField" :spec="spec.latitudeField"></fields-text>
|
|
10
|
-
<fields-text ref="lngField" v-if="spec.longitudeField" :spec="spec.longitudeField"></fields-text>
|
|
11
|
-
<fields-text ref="zoomField" v-if="spec.zoomField" :spec="spec.zoomField"></fields-text>
|
|
9
|
+
<fields-text ref="latField" v-if="spec.latitudeField" :spec="spec.latitudeField" type="text"></fields-text>
|
|
10
|
+
<fields-text ref="lngField" v-if="spec.longitudeField" :spec="spec.longitudeField" type="text"></fields-text>
|
|
11
|
+
<fields-text ref="zoomField" v-if="spec.zoomField" :spec="spec.zoomField" type="number"></fields-text>
|
|
12
12
|
</div>
|
|
13
13
|
|
|
14
14
|
</div>
|
package/components/image.vue
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<v-
|
|
3
|
-
:
|
|
4
|
-
|
|
2
|
+
<common-badge v-if="spec.badge" :spec="spec">
|
|
3
|
+
<img :src="spec.url || spec.base64Data" @click="$onClick()" :style="styles" :height="height" :width="width"
|
|
4
|
+
:class="$classes()" />
|
|
5
|
+
</common-badge>
|
|
6
|
+
<img v-else :src="spec.url || spec.base64Data" @click="$onClick()" :style="styles" :height="height" :width="width"
|
|
7
|
+
:class="$classes()" />
|
|
5
8
|
</template>
|
|
6
9
|
|
|
7
10
|
<script>
|
|
@@ -21,7 +24,7 @@ export default {
|
|
|
21
24
|
$ready() {
|
|
22
25
|
// this.$initAccessories();
|
|
23
26
|
|
|
24
|
-
|
|
27
|
+
let styles = this.genericStyles(Object.assign({}, this.spec));
|
|
25
28
|
this.styles = styles;
|
|
26
29
|
|
|
27
30
|
if (this.spec.url) {
|
|
@@ -58,9 +61,9 @@ export default {
|
|
|
58
61
|
}
|
|
59
62
|
}
|
|
60
63
|
|
|
61
|
-
Object.assign(this.styles, { width, height });
|
|
62
|
-
this.width = width
|
|
63
|
-
this.height = height
|
|
64
|
+
Object.assign(this.styles, { width, height, objectFit: 'contain' });
|
|
65
|
+
this.width = width;
|
|
66
|
+
this.height = height;
|
|
64
67
|
},
|
|
65
68
|
fitCrop(image) {
|
|
66
69
|
let width, height;
|
|
@@ -73,10 +76,12 @@ export default {
|
|
|
73
76
|
height = `${this.spec.height}px`;
|
|
74
77
|
}
|
|
75
78
|
|
|
76
|
-
Object.assign(this.styles, { width, height });
|
|
77
|
-
this.width = width
|
|
78
|
-
this.height = height
|
|
79
|
+
Object.assign(this.styles, { width, height, objectFit: 'cover' });
|
|
80
|
+
this.width = width;
|
|
81
|
+
this.height = height;
|
|
79
82
|
}
|
|
80
83
|
}
|
|
81
84
|
};
|
|
82
85
|
</script>
|
|
86
|
+
|
|
87
|
+
<style scoped></style>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { vueApp } from "../../store";
|
|
2
1
|
import Hash from "../../utils/hash";
|
|
3
2
|
import { fieldModels, watchFieldModels } from "../composable/conditional";
|
|
3
|
+
import { useDirtyState } from "../composable/dirtyState";
|
|
4
|
+
const { updateDirtyState } = useDirtyState();
|
|
4
5
|
|
|
5
6
|
export default {
|
|
6
7
|
data: function () {
|
|
@@ -21,7 +22,7 @@ export default {
|
|
|
21
22
|
|
|
22
23
|
Object.assign(fieldModels, { [this.fieldName]: this.$internalizeValue(val) });
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
updateDirtyState(val, oldVal, this.spec);
|
|
25
26
|
},
|
|
26
27
|
spec: {
|
|
27
28
|
handler(spec, oldSpec) {
|
|
@@ -52,31 +53,36 @@ export default {
|
|
|
52
53
|
});
|
|
53
54
|
}
|
|
54
55
|
},
|
|
56
|
+
unmounted() {
|
|
57
|
+
if (fieldModels[this.fieldName]) {
|
|
58
|
+
delete fieldModels[this.fieldName];
|
|
59
|
+
}
|
|
60
|
+
},
|
|
55
61
|
methods: {
|
|
56
62
|
// TODO: Deprecated
|
|
57
63
|
genericStyles(spec) {
|
|
58
64
|
return this.$styles(spec);
|
|
59
65
|
},
|
|
60
|
-
_checkDirtyState(val, oldVal) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
},
|
|
66
|
+
// _checkDirtyState(val, oldVal) {
|
|
67
|
+
// const dirtyCheckEnabled = !this.spec.disableDirtyCheck;
|
|
68
|
+
// // Make sure value has changed and make sure that it is different from the original value.
|
|
69
|
+
// // Be strict with this so it doesn't execute when the component is just initializing (e.g value changing
|
|
70
|
+
// // from `null` to `this.spec.value`).
|
|
71
|
+
// if (dirtyCheckEnabled && val != oldVal && val != this.spec.value) {
|
|
72
|
+
// const topDialog = Utils.launch.dialog.topDialog();
|
|
73
|
+
// if (topDialog) {
|
|
74
|
+
// if (!topDialog.isFormDirty) {
|
|
75
|
+
// console.debug("Dialog form is now dirty");
|
|
76
|
+
// topDialog.isFormDirty = true;
|
|
77
|
+
// }
|
|
78
|
+
// } else {
|
|
79
|
+
// if (vueApp.isFormDirty) {
|
|
80
|
+
// console.log("Window form is now dirty");
|
|
81
|
+
// vueApp.isFormDirty = true;
|
|
82
|
+
// }
|
|
83
|
+
// }
|
|
84
|
+
// }
|
|
85
|
+
// },
|
|
80
86
|
// NOTE: Styles are dynamic, do not save it in $ready().
|
|
81
87
|
$styles(spec) {
|
|
82
88
|
const properties = spec || this.spec;
|
package/nav/dialog.vue
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<v-dialog :model-value="model" :width="spec.width || 600" :dark="false" :fullscreen="fullscreen" :sm-and-down="false"
|
|
3
|
-
:persistent="
|
|
3
|
+
:persistent="true" @click:outside="clickOutside">
|
|
4
4
|
<v-card :style="hamburgerStyles" class="hamburger">
|
|
5
5
|
|
|
6
6
|
<panels-responsive v-if="header" :spec="header" />
|
|
@@ -43,10 +43,17 @@
|
|
|
43
43
|
import Http from "../utils/http";
|
|
44
44
|
import Action from "../action";
|
|
45
45
|
import FormPanel from "../components/panels/form.vue";
|
|
46
|
-
import {
|
|
47
|
-
|
|
46
|
+
import { useDirtyState } from "../components/composable/dirtyState";
|
|
47
|
+
import { dialogStates } from "../store";
|
|
48
|
+
import { reactive } from "vue";
|
|
48
49
|
|
|
49
50
|
export default {
|
|
51
|
+
setup() {
|
|
52
|
+
const { isDirty } = useDirtyState();
|
|
53
|
+
const context = reactive({ isFormDirty: false });
|
|
54
|
+
|
|
55
|
+
return { isDirty, context };
|
|
56
|
+
},
|
|
50
57
|
components: {
|
|
51
58
|
"panels-form": FormPanel,
|
|
52
59
|
},
|
|
@@ -66,8 +73,6 @@ export default {
|
|
|
66
73
|
url: null,
|
|
67
74
|
urlLoaded: false,
|
|
68
75
|
disableCloseButton: false,
|
|
69
|
-
isFormDirty: false,
|
|
70
|
-
isFormSubmitted: false,
|
|
71
76
|
isMobile: false,
|
|
72
77
|
formSpec: null,
|
|
73
78
|
};
|
|
@@ -98,10 +103,19 @@ export default {
|
|
|
98
103
|
watch: {
|
|
99
104
|
model: function (val, oldVal) {
|
|
100
105
|
if (!val) {
|
|
101
|
-
this.
|
|
106
|
+
if (!this.isDirty()) {
|
|
107
|
+
this.stack.remove(this);
|
|
108
|
+
dialogStates.remove(this.context);
|
|
109
|
+
} else {
|
|
110
|
+
this.model = true;
|
|
111
|
+
}
|
|
102
112
|
}
|
|
103
113
|
},
|
|
104
114
|
},
|
|
115
|
+
mounted() {
|
|
116
|
+
this.stack.push(this);
|
|
117
|
+
dialogStates.push(this.context);
|
|
118
|
+
},
|
|
105
119
|
methods: {
|
|
106
120
|
$mounted() {
|
|
107
121
|
window.addEventListener(
|
|
@@ -115,7 +129,6 @@ export default {
|
|
|
115
129
|
$ready() {
|
|
116
130
|
this.onResize();
|
|
117
131
|
this.show(false);
|
|
118
|
-
this.stack.push(this);
|
|
119
132
|
|
|
120
133
|
this.$nextTick(() => {
|
|
121
134
|
this.updateMainHeight();
|
|
@@ -127,7 +140,10 @@ export default {
|
|
|
127
140
|
// this.stack.remove(this);
|
|
128
141
|
// },
|
|
129
142
|
close() {
|
|
130
|
-
|
|
143
|
+
this.model = false;
|
|
144
|
+
},
|
|
145
|
+
clickOutside() {
|
|
146
|
+
if (this.spec.closeOnBlur) {
|
|
131
147
|
this.model = false;
|
|
132
148
|
}
|
|
133
149
|
},
|
|
@@ -137,11 +153,9 @@ export default {
|
|
|
137
153
|
Action.execute(onClick, this);
|
|
138
154
|
},
|
|
139
155
|
reload(newSpec) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
this.show(true);
|
|
144
|
-
}
|
|
156
|
+
this.spec.url = newSpec.url;
|
|
157
|
+
this.urlLoaded = false;
|
|
158
|
+
this.show(true);
|
|
145
159
|
},
|
|
146
160
|
onResize() {
|
|
147
161
|
this.isMobile = window.innerWidth < 600;
|
package/package.json
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
install: (Vue, options) => {
|
|
3
3
|
Vue.mixin({
|
|
4
|
-
mounted: function () {
|
|
5
|
-
let spec = this.spec;
|
|
6
|
-
if (spec && spec.id && this.$registryEnabled()) {
|
|
7
|
-
const id = spec.id
|
|
8
|
-
const existingComponent = GLib.component.findById(id)
|
|
9
|
-
// A component with the same ID in a different page shouldn't be considered a
|
|
10
|
-
// duplicate. See `utils/components#deregister` for more details.
|
|
11
|
-
if (existingComponent && existingComponent._mountedUrl == this._mountedUrl) {
|
|
12
|
-
console.warn(
|
|
13
|
-
"Duplicate component ID:",
|
|
14
|
-
id,
|
|
15
|
-
"Existing:",
|
|
16
|
-
GLib.component.vueName(existingComponent),
|
|
17
|
-
"New:",
|
|
18
|
-
GLib.component.vueName(this)
|
|
19
|
-
);
|
|
20
|
-
}
|
|
21
|
-
GLib.component.register(id, this);
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
unmounted: function () {
|
|
25
|
-
let spec = this.spec;
|
|
26
|
-
if (spec && spec.id && this.$registryEnabled()) {
|
|
27
|
-
GLib.component.deregister(spec.id, this);
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
4
|
methods: {
|
|
5
|
+
$ready() {
|
|
6
|
+
let spec = this.spec;
|
|
7
|
+
if (spec && spec.id && this.$registryEnabled()) {
|
|
8
|
+
const id = spec.id;
|
|
9
|
+
const existingComponent = GLib.component.findById(id);
|
|
10
|
+
// A component with the same ID in a different page shouldn't be considered a
|
|
11
|
+
// duplicate. See `utils/components#deregister` for more details.
|
|
12
|
+
if (existingComponent) {
|
|
13
|
+
console.warn(
|
|
14
|
+
"Duplicate component ID:",
|
|
15
|
+
id,
|
|
16
|
+
"Existing:",
|
|
17
|
+
GLib.component.vueName(existingComponent),
|
|
18
|
+
"New:",
|
|
19
|
+
GLib.component.vueName(this)
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
GLib.component.register(id, this);
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
$tearDown() {
|
|
26
|
+
let spec = this.spec;
|
|
27
|
+
if (spec && spec.id && this.$registryEnabled()) {
|
|
28
|
+
GLib.component.deregister(spec.id, this);
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
31
|
$registryEnabled() {
|
|
32
32
|
// Common classes such as `_select` need to return false so that it doesn't override its parent (e.g. `select`).
|
|
33
33
|
return true;
|
package/store.js
CHANGED
|
@@ -15,4 +15,20 @@ export const vueApp = reactive({
|
|
|
15
15
|
temp: {},
|
|
16
16
|
richTextValues: {},
|
|
17
17
|
draggedComponent: null
|
|
18
|
-
});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export const dialogStates = reactive([]);
|
|
21
|
+
|
|
22
|
+
export const glibevent = reactive({
|
|
23
|
+
onbeforewindowsopen: null,
|
|
24
|
+
onbeforewindowsclose: null,
|
|
25
|
+
onbeforewindowsreload: null
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export function executeGlobalEvent(name) {
|
|
29
|
+
if (!glibevent[name]) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return glibevent[name]();
|
|
34
|
+
}
|
package/utils/component.js
CHANGED
|
@@ -32,7 +32,7 @@ export default class {
|
|
|
32
32
|
// component will get registered before the old component gets deregistered, in which case we
|
|
33
33
|
// should skip the deregistering or else we'd accidentally deregister the new component.
|
|
34
34
|
if (this._registry[id] == component) {
|
|
35
|
-
console.debug("Deregistering component with ID", id)
|
|
35
|
+
console.debug("Deregistering component with ID", id);
|
|
36
36
|
delete this._registry[id];
|
|
37
37
|
}
|
|
38
38
|
}
|
|
@@ -42,13 +42,13 @@ export default class {
|
|
|
42
42
|
// return component.$options._componentTag;
|
|
43
43
|
if (!component.name && component.spec) {
|
|
44
44
|
if (component.spec.view == 'panels/fullPageForm') {
|
|
45
|
-
component.name = 'panels-form'
|
|
45
|
+
component.name = 'panels-form';
|
|
46
46
|
} else {
|
|
47
|
-
component.name = (component.spec.view || '').replace('/', '-').replace('-v1', '')
|
|
47
|
+
component.name = (component.spec.view || '').replace('/', '-').replace('-v1', '');
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
return component.name
|
|
51
|
+
return component.name;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
static async preserveScroll(promise) {
|
package/utils/form.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { vueApp } from "../store";
|
|
2
|
+
|
|
1
3
|
export default class {
|
|
2
4
|
// Execution flows:
|
|
3
5
|
// Button -> Button.onClick() -> Utils.http.execute() -- doesn't save autofill values
|
|
@@ -7,7 +9,8 @@ export default class {
|
|
|
7
9
|
// Analogous to Rails' form_with's `local: true`
|
|
8
10
|
if (form.dataset.local) {
|
|
9
11
|
// Prevent onUnload dirty prompt.
|
|
10
|
-
Utils.http.clearDirtyState();
|
|
12
|
+
// Utils.http.clearDirtyState();
|
|
13
|
+
vueApp.isFormDirty = false;
|
|
11
14
|
form.submit();
|
|
12
15
|
} else {
|
|
13
16
|
const url = overrideUrl ? overrideUrl : form.getAttribute("action");
|
package/utils/http.js
CHANGED
|
@@ -4,7 +4,6 @@ import { nextTick } from 'vue';
|
|
|
4
4
|
import { vueApp } from "../store";
|
|
5
5
|
|
|
6
6
|
let loading = false;
|
|
7
|
-
const dirtyPrompt = "Changes you made have not been saved. Are you sure?";
|
|
8
7
|
|
|
9
8
|
class HttpRequest {
|
|
10
9
|
constructor() {
|
|
@@ -72,9 +71,9 @@ export default class {
|
|
|
72
71
|
const domainMatched = window.location.hostname == url.hostname;
|
|
73
72
|
|
|
74
73
|
// If this is an external domain, we rely on `onUnload()` instead.
|
|
75
|
-
if (domainMatched && !this.proceedEvenWhenDirty()) {
|
|
76
|
-
|
|
77
|
-
}
|
|
74
|
+
// if (domainMatched && !this.proceedEvenWhenDirty()) {
|
|
75
|
+
// return;
|
|
76
|
+
// }
|
|
78
77
|
|
|
79
78
|
if (Utils.settings.reactive && domainMatched) {
|
|
80
79
|
const currentUrl = window.location.href;
|
|
@@ -268,31 +267,25 @@ export default class {
|
|
|
268
267
|
});
|
|
269
268
|
}
|
|
270
269
|
|
|
271
|
-
static
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
};
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
static clearDirtyState() {
|
|
278
|
-
vueApp.isFormDirty = false;
|
|
279
|
-
}
|
|
270
|
+
// static clearDirtyState() {
|
|
271
|
+
// vueApp.isFormDirty = false;
|
|
272
|
+
// }
|
|
280
273
|
|
|
281
274
|
static notifyFormSubmitted() {
|
|
282
275
|
vueApp.isFormSubmitted = true;
|
|
283
276
|
}
|
|
284
277
|
|
|
285
278
|
// `context` can be either window or dialog.
|
|
286
|
-
static proceedEvenWhenDirty() {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
}
|
|
279
|
+
// static proceedEvenWhenDirty() {
|
|
280
|
+
// const dirtyContext = vueApp;
|
|
281
|
+
// // Don't prompt if this is a result of form submission
|
|
282
|
+
// if (
|
|
283
|
+
// dirtyContext.isFormDirty &&
|
|
284
|
+
// !dirtyContext.isFormSubmitted &&
|
|
285
|
+
// !confirm(dirtyPrompt)
|
|
286
|
+
// ) {
|
|
287
|
+
// return false;
|
|
288
|
+
// }
|
|
289
|
+
// return true;
|
|
290
|
+
// }
|
|
298
291
|
}
|