@afeefa/vue-app 0.0.61 → 0.0.64
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/.afeefa/package/release/version.txt +1 -1
- package/README.md +3 -1
- package/package.json +1 -1
- package/src/api-resources/ApiAction.js +87 -0
- package/src/api-resources/ApiActions2.js +13 -0
- package/src/api-resources/DeleteAction.js +21 -0
- package/src/api-resources/GetAction.js +18 -0
- package/src/api-resources/ListAction.js +27 -0
- package/src/api-resources/SaveAction.js +15 -0
- package/src/components/AModal.vue +21 -3
- package/src/components/ASearchSelect.vue +2 -2
- package/src/components/ATableRow.vue +4 -0
- package/src/components/flying-context/FlyingContextEvent.js +5 -0
- package/src/components/form/EditForm.vue +30 -8
- package/src/components/form/EditModal.vue +50 -35
- package/src/components/form/FormFieldMixin.js +1 -1
- package/src/components/form/NestedEditForm.vue +4 -0
- package/src/components/list/ListViewMixin.js +2 -2
- package/src/events.js +1 -0
- package/src-admin/bootstrap.js +1 -0
- package/src-admin/components/App.vue +5 -1
- package/src-admin/components/FlyingContext.vue +77 -0
- package/src-admin/components/FlyingContextContainer.vue +85 -0
- package/src-admin/components/app/AppBarButton.vue +10 -2
- package/src-admin/components/controls/SearchSelectFormField.vue +1 -1
- package/src-admin/components/form/EditFormButtons.vue +40 -0
- package/src-admin/components/form/RemoveButton.vue +71 -0
- package/src-admin/components/index.js +7 -8
- package/src-admin/components/list/ListView.vue +19 -5
- package/src-admin/components/pages/EditPage.vue +48 -134
- package/src-admin/components/routes/DataRouteMixin.js +84 -0
- package/src-admin/config/routing.js +0 -11
- package/src-admin/directives/index.js +26 -0
- package/src-admin/models/Model.js +3 -3
- package/src-admin/components/pages/CreatePage.vue +0 -114
- package/src-admin/components/pages/DetailPage.vue +0 -143
- package/src-admin/components/pages/EditPageMixin.js +0 -96
- package/src-admin/components/pages/ListPage.vue +0 -55
- package/src-admin/components/routes/CreateRoute.vue +0 -15
- package/src-admin/components/routes/DetailRoute.vue +0 -85
- package/src-admin/components/routes/EditRoute.vue +0 -78
- package/src-admin/components/routes/ListRoute.vue +0 -110
@@ -1,114 +0,0 @@
|
|
1
|
-
<template>
|
2
|
-
<div class="createPage">
|
3
|
-
<app-bar-title
|
4
|
-
:icon="_icon"
|
5
|
-
:title="_title"
|
6
|
-
/>
|
7
|
-
|
8
|
-
<app-bar-button>
|
9
|
-
<v-btn
|
10
|
-
:to="_listLink"
|
11
|
-
small
|
12
|
-
>
|
13
|
-
Liste
|
14
|
-
</v-btn>
|
15
|
-
</app-bar-button>
|
16
|
-
|
17
|
-
<edit-form
|
18
|
-
:model="modelToEdit"
|
19
|
-
:valid.sync="valid"
|
20
|
-
:changed.sync="changed"
|
21
|
-
>
|
22
|
-
<template #fields>
|
23
|
-
<slot
|
24
|
-
name="fields"
|
25
|
-
:model="modelToEdit"
|
26
|
-
/>
|
27
|
-
</template>
|
28
|
-
</edit-form>
|
29
|
-
|
30
|
-
<a-row class="mt-6">
|
31
|
-
<v-btn
|
32
|
-
:disabled="!changed || !valid"
|
33
|
-
color="green white--text"
|
34
|
-
@click="save"
|
35
|
-
>
|
36
|
-
Anlegen
|
37
|
-
</v-btn>
|
38
|
-
|
39
|
-
<v-btn
|
40
|
-
v-if="changed"
|
41
|
-
text
|
42
|
-
@click="reset"
|
43
|
-
>
|
44
|
-
Zurücksetzen
|
45
|
-
</v-btn>
|
46
|
-
</a-row>
|
47
|
-
</div>
|
48
|
-
</template>
|
49
|
-
|
50
|
-
<script>
|
51
|
-
import { Component, Mixins } from '@a-vue'
|
52
|
-
import { EditPageMixin } from './EditPageMixin'
|
53
|
-
|
54
|
-
@Component({
|
55
|
-
props: ['icon', 'title', 'createModel', 'listLink']
|
56
|
-
})
|
57
|
-
export default class CreatePage extends Mixins(EditPageMixin) {
|
58
|
-
created () {
|
59
|
-
if (!this.$parent.constructor.getCreateRouteConfig) {
|
60
|
-
console.warn('<create-page> owner must provide a static createRouteConfig method.')
|
61
|
-
}
|
62
|
-
|
63
|
-
this.reset()
|
64
|
-
}
|
65
|
-
|
66
|
-
get editConfig () {
|
67
|
-
return this.$parent.constructor.getCreateRouteConfig(this.$route)
|
68
|
-
}
|
69
|
-
|
70
|
-
get modelUpateAction () {
|
71
|
-
return this.editConfig.createAction || this.ModelClass.getAction('save')
|
72
|
-
}
|
73
|
-
|
74
|
-
get _icon () {
|
75
|
-
return this.icon || this.modelToEdit.getIcon()
|
76
|
-
}
|
77
|
-
|
78
|
-
get _title () {
|
79
|
-
const title = this.modelToEdit.getTitle()
|
80
|
-
if (title) {
|
81
|
-
return title
|
82
|
-
}
|
83
|
-
|
84
|
-
if (this.title) {
|
85
|
-
return this.title
|
86
|
-
}
|
87
|
-
|
88
|
-
return this.$t('Admin.Types', this.ModelClass.type, null, 'TITLE_NEW', 'de')
|
89
|
-
}
|
90
|
-
|
91
|
-
get _listLink () {
|
92
|
-
if (this.listLink) {
|
93
|
-
if (typeof this.listLink === 'function') {
|
94
|
-
return this.listLink()
|
95
|
-
} else {
|
96
|
-
return this.listLink
|
97
|
-
}
|
98
|
-
}
|
99
|
-
return this.modelToEdit.getLink('list')
|
100
|
-
}
|
101
|
-
|
102
|
-
createModelToEdit () {
|
103
|
-
if (this.createModel) {
|
104
|
-
return this.createModel(this.fields)
|
105
|
-
}
|
106
|
-
return this.ModelClass.createForNew(this.fields)
|
107
|
-
}
|
108
|
-
|
109
|
-
saved (model) {
|
110
|
-
this.ignoreChanged = true
|
111
|
-
this.$router.push(model.getLink('edit'))
|
112
|
-
}
|
113
|
-
}
|
114
|
-
</script>
|
@@ -1,143 +0,0 @@
|
|
1
|
-
<template>
|
2
|
-
<div class="detailPage ml-4 mt-12">
|
3
|
-
<app-bar-title
|
4
|
-
:icon="_icon"
|
5
|
-
:title="_title"
|
6
|
-
/>
|
7
|
-
|
8
|
-
<app-bar-button v-if="$has.remove">
|
9
|
-
<v-btn
|
10
|
-
small
|
11
|
-
color="red white--text"
|
12
|
-
class="removeButton"
|
13
|
-
@click="remove"
|
14
|
-
>
|
15
|
-
Löschen
|
16
|
-
</v-btn>
|
17
|
-
</app-bar-button>
|
18
|
-
|
19
|
-
<app-bar-button v-if="$has.edit">
|
20
|
-
<a-icon-button
|
21
|
-
:to="model.getLink('edit')"
|
22
|
-
icon="$pencilIcon"
|
23
|
-
text="Bearbeiten"
|
24
|
-
color="green white--text"
|
25
|
-
/>
|
26
|
-
</app-bar-button>
|
27
|
-
|
28
|
-
<slot
|
29
|
-
name="model"
|
30
|
-
:model="model"
|
31
|
-
/>
|
32
|
-
|
33
|
-
<a-dialog
|
34
|
-
id="detailPageRemoveDialog"
|
35
|
-
:anchor="[document, '.removeButton']"
|
36
|
-
:active="protectRemove ? removeKey === removeConfirmed : true"
|
37
|
-
>
|
38
|
-
<template v-if="protectRemove">
|
39
|
-
<div>Bitte folgenden Key eingeben: <strong class="removeKey">{{ removeKey }}</strong></div>
|
40
|
-
|
41
|
-
<a-text-field
|
42
|
-
v-model="removeConfirmed"
|
43
|
-
label="Key"
|
44
|
-
:focus="true"
|
45
|
-
width="100"
|
46
|
-
/>
|
47
|
-
</template>
|
48
|
-
</a-dialog>
|
49
|
-
</div>
|
50
|
-
</template>
|
51
|
-
|
52
|
-
|
53
|
-
<script>
|
54
|
-
import { Component, Vue, Watch } from '@a-vue'
|
55
|
-
import { RemoveAction } from '@a-vue/api-resources/ApiActions'
|
56
|
-
|
57
|
-
@Component({
|
58
|
-
props: ['model', 'title', 'icon', 'protectRemove', 'listLink']
|
59
|
-
})
|
60
|
-
export default class DetailPage extends Vue {
|
61
|
-
$hasOptions = ['edit', 'remove', 'list']
|
62
|
-
|
63
|
-
removeKey = null
|
64
|
-
removeConfirmed = null
|
65
|
-
|
66
|
-
created () {
|
67
|
-
if (!this.$parent.constructor.getDetailRouteConfig) {
|
68
|
-
console.warn('<detail-page> owner must provide a static getDetailRouteConfig method.')
|
69
|
-
}
|
70
|
-
this.$emit('model', this.model)
|
71
|
-
}
|
72
|
-
|
73
|
-
@Watch('model')
|
74
|
-
modelChanged () {
|
75
|
-
this.$emit('model', this.model)
|
76
|
-
}
|
77
|
-
|
78
|
-
get _title () {
|
79
|
-
return this.title || this.model.getTitle()
|
80
|
-
}
|
81
|
-
|
82
|
-
get detailConfig () {
|
83
|
-
return this.$parent.constructor.getDetailRouteConfig(this.$route)
|
84
|
-
}
|
85
|
-
|
86
|
-
get document () {
|
87
|
-
return document
|
88
|
-
}
|
89
|
-
|
90
|
-
get ModelClass () {
|
91
|
-
return this.detailConfig.ModelClass
|
92
|
-
}
|
93
|
-
|
94
|
-
get _listLink () {
|
95
|
-
if (this.listLink) {
|
96
|
-
if (typeof this.listLink === 'function') {
|
97
|
-
return this.listLink()
|
98
|
-
} else {
|
99
|
-
return this.listLink
|
100
|
-
}
|
101
|
-
}
|
102
|
-
return this.model.getLink('list')
|
103
|
-
}
|
104
|
-
|
105
|
-
get _icon () {
|
106
|
-
if (this.icon) {
|
107
|
-
return this.icon
|
108
|
-
}
|
109
|
-
return this.model.getIcon()
|
110
|
-
}
|
111
|
-
|
112
|
-
get _deleteAction () {
|
113
|
-
return this.detailConfig.removeAction || this.ModelClass.getAction('save')
|
114
|
-
}
|
115
|
-
|
116
|
-
async remove () {
|
117
|
-
this.removeKey = [...Array(6)].map(() => Math.floor(Math.random() * 16).toString(16)).join('')
|
118
|
-
|
119
|
-
const result = await new RemoveAction()
|
120
|
-
.setAction(this._deleteAction)
|
121
|
-
.setId(this.model.id)
|
122
|
-
.setDialog({
|
123
|
-
id: 'detailPageRemoveDialog',
|
124
|
-
title: this.model.getTitle() + ' löschen?',
|
125
|
-
message: 'Soll ' + this.model.getTitle() + ' gelöscht werden?',
|
126
|
-
yesButton: 'Löschen',
|
127
|
-
yesColor: 'red white--text'
|
128
|
-
})
|
129
|
-
.delete()
|
130
|
-
|
131
|
-
if (result) {
|
132
|
-
this.$router.push(this.model.getLink('list'))
|
133
|
-
}
|
134
|
-
}
|
135
|
-
}
|
136
|
-
</script>
|
137
|
-
|
138
|
-
|
139
|
-
<style lang="scss" scoped>
|
140
|
-
.removeKey {
|
141
|
-
user-select: none;
|
142
|
-
}
|
143
|
-
</style>
|
@@ -1,96 +0,0 @@
|
|
1
|
-
import { Component, Vue } from '@a-vue'
|
2
|
-
import { SaveAction } from '@a-vue/api-resources/ApiActions'
|
3
|
-
import { DialogEvent } from '@a-vue/events'
|
4
|
-
|
5
|
-
@Component({
|
6
|
-
props: ['saveAction']
|
7
|
-
})
|
8
|
-
export class EditPageMixin extends Vue {
|
9
|
-
valid = false
|
10
|
-
changed = false
|
11
|
-
modelToEdit = null
|
12
|
-
ignoreChanged = false
|
13
|
-
|
14
|
-
unregisterRouterHook = null
|
15
|
-
|
16
|
-
created () {
|
17
|
-
this.unregisterRouterHook = this.$router.beforeEach(async (to, from, next) => {
|
18
|
-
if (!this.ignoreChanged && this.changed) {
|
19
|
-
const result = await this.$events.dispatch(new DialogEvent(DialogEvent.SHOW, {
|
20
|
-
title: 'Änderungen verwerfen?',
|
21
|
-
message: 'Im Formular sind nicht gespeicherte Änderungen. Sollen diese verworfen werden?',
|
22
|
-
yesButton: 'Verwerfen'
|
23
|
-
}))
|
24
|
-
if (result === DialogEvent.RESULT_YES) {
|
25
|
-
next()
|
26
|
-
}
|
27
|
-
return
|
28
|
-
}
|
29
|
-
next()
|
30
|
-
})
|
31
|
-
}
|
32
|
-
|
33
|
-
destroyed () {
|
34
|
-
this.unregisterRouterHook()
|
35
|
-
}
|
36
|
-
|
37
|
-
createModelToEdit () {
|
38
|
-
return null
|
39
|
-
}
|
40
|
-
|
41
|
-
get editConfig () {
|
42
|
-
return null
|
43
|
-
}
|
44
|
-
|
45
|
-
get ModelClass () {
|
46
|
-
return this.editConfig.ModelClass
|
47
|
-
}
|
48
|
-
|
49
|
-
get _saveAction () {
|
50
|
-
if (this.saveAction) {
|
51
|
-
return this.saveAction
|
52
|
-
}
|
53
|
-
return this.modelUpateAction
|
54
|
-
}
|
55
|
-
|
56
|
-
get modelUpateAction () {
|
57
|
-
return null
|
58
|
-
}
|
59
|
-
|
60
|
-
get fields () {
|
61
|
-
return this.editConfig.fields
|
62
|
-
}
|
63
|
-
|
64
|
-
get saveParams () {
|
65
|
-
return {}
|
66
|
-
}
|
67
|
-
|
68
|
-
async save () {
|
69
|
-
const model = await new SaveAction()
|
70
|
-
.setAction(this._saveAction)
|
71
|
-
.setFields(this.fields)
|
72
|
-
.setId(this.modelToEdit.id)
|
73
|
-
.setData(this.modelToEdit.serialize(this.fields))
|
74
|
-
.setAfterSaveHook(this.afterSave)
|
75
|
-
.save()
|
76
|
-
|
77
|
-
this.saved(model)
|
78
|
-
}
|
79
|
-
|
80
|
-
reset () {
|
81
|
-
const modelToEdit = this.createModelToEdit()
|
82
|
-
if (this.editConfig.createModelToEdit) {
|
83
|
-
this.editConfig.createModelToEdit(modelToEdit)
|
84
|
-
}
|
85
|
-
this.modelToEdit = modelToEdit // this assignment makes modelToEdit recursively reactive
|
86
|
-
this.$emit('model', this.modelToEdit)
|
87
|
-
}
|
88
|
-
|
89
|
-
afterSave (_model) {
|
90
|
-
// e.g. reload model
|
91
|
-
}
|
92
|
-
|
93
|
-
saved (_model) {
|
94
|
-
// e.g. redirect after save
|
95
|
-
}
|
96
|
-
}
|
@@ -1,55 +0,0 @@
|
|
1
|
-
<template>
|
2
|
-
<div class="listPage">
|
3
|
-
<app-bar-title
|
4
|
-
:icon="_icon"
|
5
|
-
:title="_title"
|
6
|
-
/>
|
7
|
-
|
8
|
-
<app-bar-button v-if="$has.add">
|
9
|
-
<a-icon-button
|
10
|
-
v-if="$has.add"
|
11
|
-
:to="_newLink"
|
12
|
-
icon="$plusIcon"
|
13
|
-
:text="_newTitle"
|
14
|
-
color="green white--text"
|
15
|
-
/>
|
16
|
-
</app-bar-button>
|
17
|
-
|
18
|
-
<slot />
|
19
|
-
</div>
|
20
|
-
</template>
|
21
|
-
|
22
|
-
<script>
|
23
|
-
import { Component, Vue } from '@a-vue'
|
24
|
-
|
25
|
-
@Component({
|
26
|
-
props: ['icon', 'title', 'newTitle', 'newLink', 'Model']
|
27
|
-
})
|
28
|
-
export default class ListPage extends Vue {
|
29
|
-
$hasOptions = ['add']
|
30
|
-
|
31
|
-
get _icon () {
|
32
|
-
return this.icon || this.Model.icon
|
33
|
-
}
|
34
|
-
|
35
|
-
get _title () {
|
36
|
-
if (this.title) {
|
37
|
-
return this.title
|
38
|
-
}
|
39
|
-
|
40
|
-
return this.$t('Admin.Types', this.Model.type, null, 'TITLE_PLURAL', 'de')
|
41
|
-
}
|
42
|
-
|
43
|
-
get _newTitle () {
|
44
|
-
if (this.newTitle) {
|
45
|
-
return this.newTitle
|
46
|
-
}
|
47
|
-
|
48
|
-
return this.$t('Admin.Types', this.Model.type, null, 'TITLE_SINGULAR', 'de')
|
49
|
-
}
|
50
|
-
|
51
|
-
get _newLink () {
|
52
|
-
return this.newLink || this.Model.getLink('new')
|
53
|
-
}
|
54
|
-
}
|
55
|
-
</script>
|
@@ -1,15 +0,0 @@
|
|
1
|
-
<template>
|
2
|
-
<component :is="Component" />
|
3
|
-
</template>
|
4
|
-
|
5
|
-
|
6
|
-
<script>
|
7
|
-
import { Component, Vue } from '@a-vue'
|
8
|
-
|
9
|
-
@Component
|
10
|
-
export default class CreateRoute extends Vue {
|
11
|
-
get Component () {
|
12
|
-
return this.$routeDefinition.config.new
|
13
|
-
}
|
14
|
-
}
|
15
|
-
</script>
|
@@ -1,85 +0,0 @@
|
|
1
|
-
<template>
|
2
|
-
<component
|
3
|
-
:is="Component"
|
4
|
-
v-if="model"
|
5
|
-
:model="model"
|
6
|
-
/>
|
7
|
-
</template>
|
8
|
-
|
9
|
-
<script>
|
10
|
-
import { Component, Vue, Watch } from '@a-vue'
|
11
|
-
import { GetAction } from '@a-vue/api-resources/ApiActions'
|
12
|
-
|
13
|
-
Component.registerHooks([
|
14
|
-
'beforeRouteEnter',
|
15
|
-
'beforeRouteUpdate'
|
16
|
-
])
|
17
|
-
|
18
|
-
function load (route) {
|
19
|
-
const routeDefinition = route.meta.routeDefinition
|
20
|
-
const Component = routeDefinition.config.detail
|
21
|
-
|
22
|
-
if (!Component.getDetailRouteConfig) {
|
23
|
-
console.warn('A detail route component must implement a static getDetailRouteConfig property.')
|
24
|
-
}
|
25
|
-
|
26
|
-
const detailConfig = Component.getDetailRouteConfig(route)
|
27
|
-
const action = detailConfig.action || detailConfig.ModelClass.getAction('get')
|
28
|
-
|
29
|
-
return new GetAction()
|
30
|
-
.setAction(action)
|
31
|
-
.setFields(detailConfig.fields)
|
32
|
-
.setId(detailConfig.id || route.params[routeDefinition.idKey])
|
33
|
-
.load()
|
34
|
-
}
|
35
|
-
|
36
|
-
let routerHookCalled = false
|
37
|
-
|
38
|
-
@Component
|
39
|
-
export default class DetailRoute extends Vue {
|
40
|
-
model = null
|
41
|
-
|
42
|
-
/**
|
43
|
-
* triggered, when the route name changes
|
44
|
-
* not triggered, when only route params change
|
45
|
-
*/
|
46
|
-
async beforeRouteEnter (to, from, next) {
|
47
|
-
routerHookCalled = true
|
48
|
-
const result = await load(to)
|
49
|
-
next(vm => {
|
50
|
-
if (result !== false) {
|
51
|
-
vm.model = result
|
52
|
-
}
|
53
|
-
routerHookCalled = false
|
54
|
-
})
|
55
|
-
}
|
56
|
-
|
57
|
-
/**
|
58
|
-
* triggered both, if route name or route params change
|
59
|
-
*/
|
60
|
-
@Watch('$route.params')
|
61
|
-
async routeParamsChanged () {
|
62
|
-
if (routerHookCalled) {
|
63
|
-
// set model to null in order to not recreate detail route's
|
64
|
-
// child components with the stale model which is still active
|
65
|
-
// in between resolving the route with next() + creating the
|
66
|
-
// route detail component and resetting vm.model later in the callback
|
67
|
-
this.model = null
|
68
|
-
return
|
69
|
-
}
|
70
|
-
this.model = await load(this.$route)
|
71
|
-
}
|
72
|
-
|
73
|
-
// probably not needed
|
74
|
-
// @Watch('$route.name')
|
75
|
-
// async routeNameChanged () {
|
76
|
-
// if (routerHookCalled) {
|
77
|
-
// // this.model = null
|
78
|
-
// }
|
79
|
-
// }
|
80
|
-
|
81
|
-
get Component () {
|
82
|
-
return this.$routeDefinition.config.detail
|
83
|
-
}
|
84
|
-
}
|
85
|
-
</script>
|
@@ -1,78 +0,0 @@
|
|
1
|
-
<template>
|
2
|
-
<component
|
3
|
-
:is="Component"
|
4
|
-
v-if="model"
|
5
|
-
:model="model"
|
6
|
-
/>
|
7
|
-
</template>
|
8
|
-
|
9
|
-
|
10
|
-
<script>
|
11
|
-
import { Component, Vue, Watch } from '@a-vue'
|
12
|
-
import { GetAction } from '@a-vue/api-resources/ApiActions'
|
13
|
-
|
14
|
-
Component.registerHooks([
|
15
|
-
'beforeRouteEnter',
|
16
|
-
'beforeRouteUpdate'
|
17
|
-
])
|
18
|
-
|
19
|
-
function load (route) {
|
20
|
-
const routeDefinition = route.meta.routeDefinition
|
21
|
-
const Component = routeDefinition.config.edit
|
22
|
-
|
23
|
-
if (!Component.getEditRouteConfig) {
|
24
|
-
console.warn('An edit route component must implement a static getEditRouteConfig property.')
|
25
|
-
}
|
26
|
-
|
27
|
-
const editConfig = Component.getEditRouteConfig(route)
|
28
|
-
const action = editConfig.getAction || editConfig.ModelClass.getAction('get')
|
29
|
-
|
30
|
-
return new GetAction()
|
31
|
-
.setAction(action)
|
32
|
-
.setFields(editConfig.fields)
|
33
|
-
.setId(editConfig.id || route.params[routeDefinition.idKey])
|
34
|
-
.load()
|
35
|
-
}
|
36
|
-
|
37
|
-
let routerHookCalled = false
|
38
|
-
|
39
|
-
@Component
|
40
|
-
export default class EditRoute extends Vue {
|
41
|
-
model = null
|
42
|
-
|
43
|
-
/**
|
44
|
-
* triggered, when the route name changes
|
45
|
-
* not triggered, when only route params change
|
46
|
-
*/
|
47
|
-
async beforeRouteEnter (to, from, next) {
|
48
|
-
routerHookCalled = true
|
49
|
-
const result = await load(to)
|
50
|
-
next(vm => {
|
51
|
-
if (result !== false) {
|
52
|
-
vm.model = result
|
53
|
-
}
|
54
|
-
routerHookCalled = false
|
55
|
-
})
|
56
|
-
}
|
57
|
-
|
58
|
-
/**
|
59
|
-
* triggered both, if route name or route params change
|
60
|
-
*/
|
61
|
-
@Watch('$route.params')
|
62
|
-
async routeParamsChanged () {
|
63
|
-
if (routerHookCalled) {
|
64
|
-
// set model to null in order to not recreate detail route's
|
65
|
-
// child components with the stale model which is still active
|
66
|
-
// in between resolving the route with next() + creating the
|
67
|
-
// route edit component and resetting vm.model later in the callback
|
68
|
-
this.model = null
|
69
|
-
return
|
70
|
-
}
|
71
|
-
this.model = await load(this.$route)
|
72
|
-
}
|
73
|
-
|
74
|
-
get Component () {
|
75
|
-
return this.$routeDefinition.config.edit
|
76
|
-
}
|
77
|
-
}
|
78
|
-
</script>
|
@@ -1,110 +0,0 @@
|
|
1
|
-
<template>
|
2
|
-
<component
|
3
|
-
:is="Component"
|
4
|
-
v-if="isLoaded"
|
5
|
-
:models="models"
|
6
|
-
:meta="meta"
|
7
|
-
/>
|
8
|
-
</template>
|
9
|
-
|
10
|
-
<script>
|
11
|
-
import { Component, Vue, Watch } from '@a-vue'
|
12
|
-
import { ListAction } from '@a-vue/api-resources/ApiActions'
|
13
|
-
import { NextRouteFilterSource } from '@a-vue/components/list/NextRouteFilterSource'
|
14
|
-
import { ListViewModel } from '@afeefa/api-resources-client'
|
15
|
-
|
16
|
-
Component.registerHooks([
|
17
|
-
'beforeRouteEnter',
|
18
|
-
'beforeRouteUpdate'
|
19
|
-
])
|
20
|
-
|
21
|
-
/**
|
22
|
-
* keep track 'this' in beforeRouteEnter
|
23
|
-
* in order to avoid rendering list pages with a stale set
|
24
|
-
* of models because next(vm => ...) will first create the
|
25
|
-
* list page with the existing set of models and update the
|
26
|
-
* models afterwards.
|
27
|
-
*/
|
28
|
-
let lastVm = null
|
29
|
-
|
30
|
-
function load (route) {
|
31
|
-
const routeDefinition = route.meta.routeDefinition
|
32
|
-
const Component = routeDefinition.config.list
|
33
|
-
|
34
|
-
if (!Component.getListRouteConfig) {
|
35
|
-
console.warn('A list route component must implement a static getListRouteConfig property.')
|
36
|
-
}
|
37
|
-
|
38
|
-
const request = new ListViewModel(Component.getListRouteConfig(route))
|
39
|
-
// read from next route query string, but do not push
|
40
|
-
// list component will be init with used_filters
|
41
|
-
.filterSource(new NextRouteFilterSource(route), false)
|
42
|
-
// read from history, but do not push
|
43
|
-
// list component will be init with used_filters
|
44
|
-
.historyKey(route.path, false)
|
45
|
-
.initFilters({
|
46
|
-
source: true,
|
47
|
-
history: true
|
48
|
-
})
|
49
|
-
.getApiRequest()
|
50
|
-
|
51
|
-
return new ListAction()
|
52
|
-
.setRequest(request)
|
53
|
-
.load()
|
54
|
-
}
|
55
|
-
|
56
|
-
let routerHookCalled = false
|
57
|
-
|
58
|
-
@Component
|
59
|
-
export default class ListRoute extends Vue {
|
60
|
-
models = null
|
61
|
-
meta = null
|
62
|
-
isLoaded = false
|
63
|
-
|
64
|
-
async beforeRouteEnter (to, from, next) {
|
65
|
-
routerHookCalled = true
|
66
|
-
const result = await load(to)
|
67
|
-
|
68
|
-
if (lastVm) {
|
69
|
-
lastVm.isLoaded = false
|
70
|
-
}
|
71
|
-
|
72
|
-
next(vm => {
|
73
|
-
if (result !== false) {
|
74
|
-
const {models, meta} = result
|
75
|
-
vm.models = models
|
76
|
-
vm.meta = meta
|
77
|
-
vm.isLoaded = true
|
78
|
-
}
|
79
|
-
|
80
|
-
lastVm = vm
|
81
|
-
routerHookCalled = false
|
82
|
-
})
|
83
|
-
}
|
84
|
-
|
85
|
-
/**
|
86
|
-
* triggered both, if route name or route params change
|
87
|
-
*/
|
88
|
-
@Watch('$route.params')
|
89
|
-
async routeParamsChanged () {
|
90
|
-
if (routerHookCalled) {
|
91
|
-
return
|
92
|
-
}
|
93
|
-
|
94
|
-
if (!this.isLoaded) {
|
95
|
-
const result = await load(this.$route)
|
96
|
-
|
97
|
-
if (result !== false) {
|
98
|
-
const {models, meta} = result
|
99
|
-
this.models = models
|
100
|
-
this.meta = meta
|
101
|
-
this.isLoaded = true
|
102
|
-
}
|
103
|
-
}
|
104
|
-
}
|
105
|
-
|
106
|
-
get Component () {
|
107
|
-
return this.$routeDefinition.config.list
|
108
|
-
}
|
109
|
-
}
|
110
|
-
</script>
|