@afeefa/vue-app 0.0.63 → 0.0.66
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/package.json +1 -1
- package/src/components/ABreadcrumbs.vue +75 -18
- package/src/components/ADatePicker.vue +1 -1
- package/src/components/AIcon.vue +3 -6
- package/src/components/AIconButton.vue +1 -2
- package/src/components/AModal.vue +21 -3
- package/src/components/ARichTextArea.vue +95 -85
- package/src/components/ARow.vue +0 -7
- package/src/components/ATableRow.vue +4 -0
- package/src/components/flying-context/FlyingContextEvent.js +5 -0
- package/src/components/form/EditForm.vue +13 -3
- package/src/components/form/EditModal.vue +52 -35
- package/src/components/form/fields/FormFieldRichTextArea.vue +5 -3
- package/src/components/list/ListViewMixin.js +25 -2
- package/src/components/mixins/ClickOutsideMixin.js +5 -1
- package/src/components/search-select/SearchSelectList.vue +0 -1
- package/src/components/vue/Component.js +9 -2
- package/src/events.js +2 -0
- package/src-admin/bootstrap.js +1 -0
- package/src-admin/components/App.vue +58 -59
- package/src-admin/components/FlyingContext.vue +77 -0
- package/src-admin/components/FlyingContextContainer.vue +85 -0
- package/src-admin/components/Sidebar.vue +66 -0
- package/src-admin/components/SidebarItem.vue +59 -0
- package/src-admin/components/StickyFooter.vue +42 -0
- package/src-admin/components/StickyFooterContainer.vue +66 -0
- package/src-admin/components/StickyHeader.vue +73 -0
- package/src-admin/components/app/AppBarButtons.vue +0 -7
- package/src-admin/components/app/AppBarTitle.vue +55 -11
- package/src-admin/components/app/AppBarTitleContainer.vue +2 -3
- package/src-admin/components/controls/SearchSelectFormField.vue +1 -0
- package/src-admin/components/detail/DetailProperty.vue +20 -16
- package/src-admin/components/form/EditFormButtons.vue +25 -6
- package/src-admin/components/form/RemoveButton.vue +17 -8
- package/src-admin/components/index.js +6 -7
- package/src-admin/components/list/ListView.vue +22 -9
- package/src-admin/components/pages/EditPage.vue +17 -8
- package/src-admin/components/routes/DataRouteMixin.js +24 -15
- package/src-admin/config/routing.js +0 -11
- package/src-admin/config/vuetify.js +22 -2
- package/src-admin/directives/index.js +26 -0
- package/src-admin/styles.scss +21 -4
- 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
@@ -0,0 +1,59 @@
|
|
1
|
+
<template>
|
2
|
+
<div class="sidebarItem">
|
3
|
+
<div :class="contextId">
|
4
|
+
<slot />
|
5
|
+
</div>
|
6
|
+
</div>
|
7
|
+
</template>
|
8
|
+
|
9
|
+
<script>
|
10
|
+
import { Component, Vue } from '@a-vue'
|
11
|
+
import { randomCssClass } from '@a-vue/utils/random'
|
12
|
+
|
13
|
+
@Component({
|
14
|
+
props: [
|
15
|
+
{
|
16
|
+
top: true,
|
17
|
+
bottom: false
|
18
|
+
}
|
19
|
+
]
|
20
|
+
})
|
21
|
+
export default class SidebarItem extends Vue {
|
22
|
+
contextId = randomCssClass(10)
|
23
|
+
|
24
|
+
mounted () {
|
25
|
+
const container = this.getSidebarContainer()
|
26
|
+
console.log(container)
|
27
|
+
container.appendChild(this.getContent())
|
28
|
+
}
|
29
|
+
|
30
|
+
destroyed () {
|
31
|
+
const container = this.getSidebarContainer()
|
32
|
+
const el = this.getContent()
|
33
|
+
if (container.contains(el)) {
|
34
|
+
container.removeChild(el)
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
getContent () {
|
39
|
+
return document.querySelector('.' + this.contextId)
|
40
|
+
}
|
41
|
+
|
42
|
+
getSidebarContainer () {
|
43
|
+
console.log('toporbottom', this.$props)
|
44
|
+
return document.querySelector('#sidebar__children > .' + this.position)
|
45
|
+
}
|
46
|
+
|
47
|
+
get position () {
|
48
|
+
if (this.bottom) {
|
49
|
+
return 'bottom'
|
50
|
+
} else {
|
51
|
+
return 'top'
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}
|
55
|
+
</script>
|
56
|
+
|
57
|
+
|
58
|
+
<style lang="scss" scoped>
|
59
|
+
</style>
|
@@ -0,0 +1,42 @@
|
|
1
|
+
<template>
|
2
|
+
<div class="stickyFooter">
|
3
|
+
<div :class="contextId">
|
4
|
+
<slot />
|
5
|
+
</div>
|
6
|
+
</div>
|
7
|
+
</template>
|
8
|
+
|
9
|
+
<script>
|
10
|
+
import { Component, Vue } from '@a-vue'
|
11
|
+
import { randomCssClass } from '@a-vue/utils/random'
|
12
|
+
|
13
|
+
@Component
|
14
|
+
export default class StickyFooter extends Vue {
|
15
|
+
contextId = randomCssClass(10)
|
16
|
+
|
17
|
+
mounted () {
|
18
|
+
const container = this.getFooterContainer()
|
19
|
+
container.appendChild(this.getContent())
|
20
|
+
}
|
21
|
+
|
22
|
+
destroyed () {
|
23
|
+
const container = this.getFooterContainer()
|
24
|
+
const el = this.getContent()
|
25
|
+
if (container.contains(el)) {
|
26
|
+
container.removeChild(el)
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
getContent () {
|
31
|
+
return document.querySelector('.' + this.contextId)
|
32
|
+
}
|
33
|
+
|
34
|
+
getFooterContainer () {
|
35
|
+
return document.getElementById('stickyFooterContainer__children')
|
36
|
+
}
|
37
|
+
}
|
38
|
+
</script>
|
39
|
+
|
40
|
+
|
41
|
+
<style lang="scss" scoped>
|
42
|
+
</style>
|
@@ -0,0 +1,66 @@
|
|
1
|
+
<template>
|
2
|
+
<v-footer
|
3
|
+
id="stickyFooterContainer"
|
4
|
+
fixed
|
5
|
+
app
|
6
|
+
inset
|
7
|
+
:class="{visible}"
|
8
|
+
>
|
9
|
+
<div id="stickyFooterContainer__children" />
|
10
|
+
</v-footer>
|
11
|
+
</template>
|
12
|
+
|
13
|
+
<script>
|
14
|
+
import { Component, Vue } from '@a-vue'
|
15
|
+
|
16
|
+
@Component({
|
17
|
+
props: []
|
18
|
+
})
|
19
|
+
export default class StickyFooterContainer extends Vue {
|
20
|
+
visible = false
|
21
|
+
|
22
|
+
mounted () {
|
23
|
+
this.mutationWatcher = new MutationObserver(this.domChanged)
|
24
|
+
this.mutationWatcher.observe(this.getChildrenContainer(), { childList: true })
|
25
|
+
}
|
26
|
+
|
27
|
+
domChanged () {
|
28
|
+
const container = this.getChildrenContainer()
|
29
|
+
this.visible = !!container.children.length
|
30
|
+
|
31
|
+
this.$nextTick(() => {
|
32
|
+
const mainStyle = document.getElementById('v-main').style
|
33
|
+
if (this.visible) {
|
34
|
+
mainStyle.paddingBottom = this.$el.offsetHeight + 'px'
|
35
|
+
} else {
|
36
|
+
mainStyle.paddingBottom = '0px'
|
37
|
+
}
|
38
|
+
})
|
39
|
+
}
|
40
|
+
|
41
|
+
getChildrenContainer () {
|
42
|
+
return this.$el.querySelector('#stickyFooterContainer__children')
|
43
|
+
}
|
44
|
+
}
|
45
|
+
</script>
|
46
|
+
|
47
|
+
|
48
|
+
<style lang="scss" scoped>
|
49
|
+
#stickyFooterContainer {
|
50
|
+
background: white;
|
51
|
+
padding: 0;
|
52
|
+
|
53
|
+
&:not(.visible) {
|
54
|
+
display: none;
|
55
|
+
}
|
56
|
+
|
57
|
+
&__children {
|
58
|
+
width: 100%;
|
59
|
+
}
|
60
|
+
}
|
61
|
+
|
62
|
+
#stickyFooterContainer__children {
|
63
|
+
background: #F5F5F5;
|
64
|
+
padding: 1rem;
|
65
|
+
}
|
66
|
+
</style>
|
@@ -0,0 +1,73 @@
|
|
1
|
+
<template>
|
2
|
+
<div
|
3
|
+
id="stickyHeader"
|
4
|
+
:class="['d-flex align-center gap-8', {visible}]"
|
5
|
+
>
|
6
|
+
<app-bar-title-container class="appBarTitle flex-grow-1" />
|
7
|
+
<app-bar-buttons class="appBarButtons mr-2" />
|
8
|
+
</div>
|
9
|
+
</template>
|
10
|
+
|
11
|
+
<script>
|
12
|
+
import { Component, Vue } from '@a-vue'
|
13
|
+
import AppBarButtons from './app/AppBarButtons'
|
14
|
+
import AppBarTitleContainer from './app/AppBarTitleContainer'
|
15
|
+
|
16
|
+
@Component({
|
17
|
+
components: {
|
18
|
+
AppBarButtons,
|
19
|
+
AppBarTitleContainer
|
20
|
+
}
|
21
|
+
})
|
22
|
+
export default class StickyHeader extends Vue {
|
23
|
+
visible = false
|
24
|
+
|
25
|
+
mounted () {
|
26
|
+
// watch mutation
|
27
|
+
this.mutationWatcher = new MutationObserver(this.domChanged)
|
28
|
+
this.mutationWatcher.observe(this.$el.querySelector('.appBarTitle'), { childList: true })
|
29
|
+
this.mutationWatcher.observe(this.$el.querySelector('.appBarButtons'), { childList: true })
|
30
|
+
|
31
|
+
// watch intersection
|
32
|
+
const el = document.querySelector('#stickyHeader')
|
33
|
+
const observer = new IntersectionObserver(
|
34
|
+
([e]) => {
|
35
|
+
e.target.classList.toggle('is-pinned', e.intersectionRatio < 1)
|
36
|
+
},
|
37
|
+
{ threshold: [1] }
|
38
|
+
)
|
39
|
+
observer.observe(el)
|
40
|
+
|
41
|
+
this.domChanged()
|
42
|
+
}
|
43
|
+
|
44
|
+
domChanged () {
|
45
|
+
this.visible = this.hasItems()
|
46
|
+
}
|
47
|
+
|
48
|
+
hasItems () {
|
49
|
+
return !!(this.$el.querySelector('.appBarTitle').children.length +
|
50
|
+
this.$el.querySelector('.appBarButtons').children.length)
|
51
|
+
}
|
52
|
+
}
|
53
|
+
</script>
|
54
|
+
|
55
|
+
|
56
|
+
<style lang="scss" scoped>
|
57
|
+
#stickyHeader {
|
58
|
+
position: sticky;
|
59
|
+
top: -1px;
|
60
|
+
margin: -1rem -2rem 2rem;
|
61
|
+
padding: 1rem 2rem;
|
62
|
+
|
63
|
+
&:not(.visible) {
|
64
|
+
display: none !important;
|
65
|
+
}
|
66
|
+
|
67
|
+
&.is-pinned {
|
68
|
+
background: white;
|
69
|
+
z-index: 2;
|
70
|
+
box-shadow: 0 4px 7px -4px #00000033;
|
71
|
+
}
|
72
|
+
}
|
73
|
+
</style>
|
@@ -1,13 +1,36 @@
|
|
1
1
|
<template>
|
2
|
-
<div class="d-flex align-center">
|
3
|
-
<v-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
2
|
+
<div class="d-flex align-center gap-4">
|
3
|
+
<v-btn
|
4
|
+
v-if="back"
|
5
|
+
fab
|
6
|
+
x-small
|
7
|
+
color="#F4F4F4"
|
8
|
+
title="Zurück"
|
9
|
+
class="mr-n2"
|
10
|
+
@click="$router.push(back)"
|
11
|
+
>
|
12
|
+
<v-icon>
|
13
|
+
$arrowLeftIcon
|
14
|
+
</v-icon>
|
15
|
+
</v-btn>
|
16
|
+
|
17
|
+
<v-avatar
|
18
|
+
color="#F4F4F4"
|
19
|
+
size="3rem"
|
20
|
+
>
|
21
|
+
<v-icon
|
22
|
+
:color="icon.color"
|
23
|
+
size="2.2rem"
|
24
|
+
v-text="icon.icon"
|
25
|
+
/>
|
26
|
+
</v-avatar>
|
27
|
+
|
28
|
+
<div class="titleContainer">
|
29
|
+
<h3 v-if="subtitle">
|
30
|
+
{{ subtitle }}
|
31
|
+
</h3>
|
32
|
+
<h2>{{ title }}</h2>
|
33
|
+
</div>
|
11
34
|
</div>
|
12
35
|
</template>
|
13
36
|
|
@@ -15,7 +38,7 @@
|
|
15
38
|
import { Component, Vue } from '@a-vue'
|
16
39
|
|
17
40
|
@Component({
|
18
|
-
props: ['icon', 'title']
|
41
|
+
props: ['back', 'icon', 'title', 'subtitle']
|
19
42
|
})
|
20
43
|
export default class appBarTitle extends Vue {
|
21
44
|
mounted () {
|
@@ -41,8 +64,29 @@ export default class appBarTitle extends Vue {
|
|
41
64
|
|
42
65
|
|
43
66
|
<style lang="scss" scoped>
|
67
|
+
.titleContainer {
|
68
|
+
overflow: hidden;
|
69
|
+
margin-top: -.2rem;
|
70
|
+
}
|
71
|
+
|
72
|
+
h3 {
|
73
|
+
font-size: .9rem;
|
74
|
+
font-weight: normal;
|
75
|
+
margin-bottom: .1rem;
|
76
|
+
line-height: 1rem;
|
77
|
+
color: #999999;
|
78
|
+
|
79
|
+
white-space: nowrap;
|
80
|
+
overflow: hidden;
|
81
|
+
text-overflow: ellipsis;
|
82
|
+
}
|
83
|
+
|
44
84
|
h2 {
|
45
|
-
|
85
|
+
font-size: 1.5rem;
|
46
86
|
line-height: 1.5rem;
|
87
|
+
|
88
|
+
white-space: nowrap;
|
89
|
+
overflow: hidden;
|
90
|
+
text-overflow: ellipsis;
|
47
91
|
}
|
48
92
|
</style>
|
@@ -11,9 +11,8 @@ export default class AppBarTitleContainer extends Vue {
|
|
11
11
|
}
|
12
12
|
</script>
|
13
13
|
|
14
|
-
|
15
14
|
<style lang="scss" scoped>
|
16
|
-
#appBarTitleContainer
|
17
|
-
|
15
|
+
#appBarTitleContainer {
|
16
|
+
min-width: 0; // https://stackoverflow.com/questions/38657688/text-overflow-ellipsis-not-working-in-a-nested-flex-container
|
18
17
|
}
|
19
18
|
</style>
|
@@ -1,17 +1,23 @@
|
|
1
1
|
<template>
|
2
2
|
<div class="detailProperty">
|
3
3
|
<div class="header">
|
4
|
-
<v-
|
4
|
+
<v-avatar
|
5
5
|
v-if="_icon"
|
6
|
-
|
7
|
-
size="
|
6
|
+
color="#EEEEEE"
|
7
|
+
size="2.5rem"
|
8
8
|
>
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
<v-icon
|
10
|
+
:color="_icon.color"
|
11
|
+
size="1.5rem"
|
12
|
+
>
|
13
|
+
{{ _icon.icon }}
|
14
|
+
</v-icon>
|
15
|
+
</v-avatar>
|
16
|
+
|
17
|
+
<label :class="['label', {'label--withIcon': !!_icon}]">{{ label }}</label>
|
12
18
|
</div>
|
13
19
|
|
14
|
-
<div :class="['content', {'content--withIcon': _icon
|
20
|
+
<div :class="['content', {'content--withIcon': !!_icon}]">
|
15
21
|
<a-row
|
16
22
|
vertical
|
17
23
|
gap="6"
|
@@ -52,29 +58,27 @@ export default class DetailProperty extends Vue {
|
|
52
58
|
flex-wrap: nowrap;
|
53
59
|
align-items: center;
|
54
60
|
height: 40px;
|
55
|
-
|
61
|
+
|
62
|
+
.v-avatar {
|
56
63
|
flex: 0 0 40px;
|
57
64
|
margin-right: 15px;
|
58
65
|
}
|
66
|
+
|
59
67
|
.label {
|
60
68
|
display: block;
|
61
69
|
text-transform: uppercase;
|
62
70
|
letter-spacing: 2px;
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
padding-left: 0;
|
67
|
-
}
|
71
|
+
padding-left: 55px;
|
72
|
+
&--withIcon {
|
73
|
+
padding-left: 0;
|
68
74
|
}
|
69
75
|
}
|
70
76
|
}
|
71
77
|
.content {
|
78
|
+
padding-left: 55px;
|
72
79
|
&--withIcon {
|
73
80
|
padding-left: 55px;
|
74
81
|
}
|
75
|
-
@media (max-width: 900px), (orientation : portrait) {
|
76
|
-
padding-left: 55px;
|
77
|
-
}
|
78
82
|
}
|
79
83
|
}
|
80
84
|
</style>
|
@@ -1,17 +1,27 @@
|
|
1
1
|
<template>
|
2
|
-
<a-row
|
2
|
+
<a-row
|
3
|
+
gap="1"
|
4
|
+
v-bind="$attrs"
|
5
|
+
>
|
3
6
|
<v-btn
|
4
|
-
|
5
|
-
|
7
|
+
fab
|
8
|
+
small
|
9
|
+
:disabled="($has.reset && !changed) || !valid"
|
6
10
|
color="green white--text"
|
11
|
+
title="Speichern"
|
7
12
|
@click="$emit('save')"
|
8
13
|
>
|
9
|
-
|
14
|
+
<v-icon>
|
15
|
+
$checkIcon
|
16
|
+
</v-icon>
|
10
17
|
</v-btn>
|
11
18
|
|
12
19
|
<v-icon
|
13
|
-
v-if="changed"
|
20
|
+
v-if="$has.reset && changed"
|
14
21
|
:small="small"
|
22
|
+
:class="{disabled: !changed}"
|
23
|
+
:disabled="!changed"
|
24
|
+
color="#999999"
|
15
25
|
text
|
16
26
|
title="Formular zurücksetzen"
|
17
27
|
@click="$emit('reset')"
|
@@ -29,10 +39,19 @@ import { mdiRotateLeft} from '@mdi/js'
|
|
29
39
|
props: [
|
30
40
|
'changed',
|
31
41
|
'valid',
|
32
|
-
|
42
|
+
{small: false}
|
33
43
|
]
|
34
44
|
})
|
35
45
|
export default class EditFormButtons extends Vue {
|
46
|
+
$hasOptions = ['reset']
|
47
|
+
|
36
48
|
undoIcon = mdiRotateLeft
|
37
49
|
}
|
38
50
|
</script>
|
51
|
+
|
52
|
+
|
53
|
+
<style lang="scss" scoped>
|
54
|
+
.v-icon--disabled {
|
55
|
+
opacity: .3;
|
56
|
+
}
|
57
|
+
</style>
|
@@ -1,13 +1,22 @@
|
|
1
1
|
<template>
|
2
2
|
<div>
|
3
|
-
<
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
3
|
+
<v-hover v-slot="{ hover }">
|
4
|
+
<v-btn
|
5
|
+
:class="'removeButton-' + dialogId"
|
6
|
+
fab
|
7
|
+
small
|
8
|
+
:color="(hover ? 'red' : 'grey lighten-3')"
|
9
|
+
title="Löschen"
|
10
|
+
@click="remove"
|
11
|
+
>
|
12
|
+
<v-icon
|
13
|
+
:color="hover ? 'white' : '#999999'"
|
14
|
+
size="1.4rem"
|
15
|
+
>
|
16
|
+
$trashCanIcon
|
17
|
+
</v-icon>
|
18
|
+
</v-btn>
|
19
|
+
</v-hover>
|
11
20
|
|
12
21
|
<a-dialog
|
13
22
|
:id="dialogId"
|
@@ -7,6 +7,7 @@ import DetailContent from './detail/DetailContent'
|
|
7
7
|
import DetailMeta from './detail/DetailMeta'
|
8
8
|
import DetailProperty from './detail/DetailProperty'
|
9
9
|
import DetailTitle from './detail/DetailTitle'
|
10
|
+
import FlyingContext from './FlyingContext.vue'
|
10
11
|
import EditFormButtons from './form/EditFormButtons'
|
11
12
|
import RemoveButton from './form/RemoveButton'
|
12
13
|
import ListCard from './list/ListCard'
|
@@ -17,11 +18,10 @@ import ListTitle from './list/ListTitle'
|
|
17
18
|
import ListView from './list/ListView'
|
18
19
|
import ModelCount from './model/ModelCount'
|
19
20
|
import ModelIcon from './model/ModelIcon'
|
20
|
-
import CreatePage from './pages/CreatePage'
|
21
|
-
import DetailPage from './pages/DetailPage'
|
22
21
|
import EditPage from './pages/EditPage'
|
23
|
-
import
|
22
|
+
import SidebarItem from './SidebarItem.vue'
|
24
23
|
import Start from './Start.vue'
|
24
|
+
import StickyFooter from './StickyFooter.vue'
|
25
25
|
|
26
26
|
Vue.component('ListCard', ListCard)
|
27
27
|
Vue.component('ListColumnHeader', ListColumnHeader)
|
@@ -29,9 +29,6 @@ Vue.component('ListContent', ListContent)
|
|
29
29
|
Vue.component('ListMeta', ListMeta)
|
30
30
|
Vue.component('ListTitle', ListTitle)
|
31
31
|
Vue.component('ListView', ListView)
|
32
|
-
Vue.component('ListPage', ListPage)
|
33
|
-
|
34
|
-
Vue.component('CreatePage', CreatePage)
|
35
32
|
|
36
33
|
Vue.component('EditPage', EditPage)
|
37
34
|
Vue.component('EditFormButtons', EditFormButtons)
|
@@ -43,7 +40,6 @@ Vue.component('ModelIcon', ModelIcon)
|
|
43
40
|
Vue.component('DetailContent', DetailContent)
|
44
41
|
Vue.component('DetailMeta', DetailMeta)
|
45
42
|
Vue.component('DetailTitle', DetailTitle)
|
46
|
-
Vue.component('DetailPage', DetailPage)
|
47
43
|
Vue.component('DetailProperty', DetailProperty)
|
48
44
|
Vue.component('DetailColumn', DetailColumn)
|
49
45
|
|
@@ -51,3 +47,6 @@ Vue.component('AppBarButton', AppBarButton)
|
|
51
47
|
Vue.component('AppBarTitle', AppBarTitle)
|
52
48
|
|
53
49
|
Vue.component('Start', Start)
|
50
|
+
Vue.component('FlyingContext', FlyingContext)
|
51
|
+
Vue.component('StickyFooter', StickyFooter)
|
52
|
+
Vue.component('SidebarItem', SidebarItem)
|
@@ -8,12 +8,16 @@
|
|
8
8
|
/>
|
9
9
|
</div>
|
10
10
|
|
11
|
+
<slot
|
12
|
+
v-if="$scopedSlots.models"
|
13
|
+
name="before-models"
|
14
|
+
/>
|
15
|
+
|
11
16
|
<template v-if="models_.length">
|
12
17
|
<template v-if="$scopedSlots.models">
|
13
18
|
<slot
|
14
19
|
name="models"
|
15
20
|
:models="models_"
|
16
|
-
:setFilter="setFilter"
|
17
21
|
/>
|
18
22
|
</template>
|
19
23
|
|
@@ -28,7 +32,11 @@
|
|
28
32
|
<a-table-row
|
29
33
|
v-for="model in models_"
|
30
34
|
:key="model.id"
|
31
|
-
|
35
|
+
v-flying-context-trigger="hasFlyingContext"
|
36
|
+
:class="{selectable: hasFlyingContext}"
|
37
|
+
v-bind="getRowAttributes(model)"
|
38
|
+
v-on="getRowListeners(model)"
|
39
|
+
@click="$emit('flyingContext', model)"
|
32
40
|
>
|
33
41
|
<v-icon
|
34
42
|
v-if="$has.icon"
|
@@ -40,7 +48,6 @@
|
|
40
48
|
<slot
|
41
49
|
name="model-table"
|
42
50
|
:model="model"
|
43
|
-
:setFilter="setFilter"
|
44
51
|
/>
|
45
52
|
</a-table-row>
|
46
53
|
</a-table>
|
@@ -50,7 +57,6 @@
|
|
50
57
|
<div
|
51
58
|
v-for="model in models_"
|
52
59
|
:key="model.id"
|
53
|
-
:class="getModelClass(model)"
|
54
60
|
>
|
55
61
|
<slot
|
56
62
|
name="model"
|
@@ -76,7 +82,7 @@ import { ListViewMixin } from '@a-vue/components/list/ListViewMixin'
|
|
76
82
|
import { LoadingEvent } from '@a-vue/events'
|
77
83
|
|
78
84
|
@Component({
|
79
|
-
props: ['
|
85
|
+
props: ['rowAttributes', 'rowListeners']
|
80
86
|
})
|
81
87
|
export default class ListView extends Mixins(ListViewMixin) {
|
82
88
|
$hasOptions = ['icon']
|
@@ -93,12 +99,19 @@ export default class ListView extends Mixins(ListViewMixin) {
|
|
93
99
|
this.$emit('update:isLoading', this.isLoading)
|
94
100
|
}
|
95
101
|
|
96
|
-
|
97
|
-
|
102
|
+
getRowAttributes (model) {
|
103
|
+
if (typeof this.rowAttributes === 'function') {
|
104
|
+
return this.rowAttributes(model)
|
105
|
+
}
|
106
|
+
return this.rowAttributes
|
107
|
+
}
|
108
|
+
|
109
|
+
getRowListeners (model) {
|
110
|
+
return (this.rowListeners && this.rowListeners(model)) || {}
|
98
111
|
}
|
99
112
|
|
100
|
-
|
101
|
-
this.
|
113
|
+
get hasFlyingContext () {
|
114
|
+
return !!this.$listeners.flyingContext
|
102
115
|
}
|
103
116
|
}
|
104
117
|
</script>
|
@@ -4,19 +4,23 @@
|
|
4
4
|
:model="model"
|
5
5
|
:createModelToEdit="createModelToEdit"
|
6
6
|
>
|
7
|
-
<template #
|
7
|
+
<template #form="{modelToEdit, changed, valid}">
|
8
8
|
<slot
|
9
|
-
|
9
|
+
name="form"
|
10
|
+
:modelToEdit="modelToEdit"
|
10
11
|
:changed="changed"
|
11
12
|
:valid="valid"
|
12
13
|
/>
|
13
14
|
|
14
|
-
<
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
<app-bar-button>
|
16
|
+
<edit-form-buttons
|
17
|
+
:changed="changed"
|
18
|
+
:valid="valid"
|
19
|
+
:has="{reset: !!modelToEdit.id}"
|
20
|
+
@save="$emit('save', modelToEdit, ignoreChangesOnRouteChange)"
|
21
|
+
@reset="$refs.form.reset()"
|
22
|
+
/>
|
23
|
+
</app-bar-button>
|
20
24
|
</template>
|
21
25
|
</edit-form>
|
22
26
|
</template>
|
@@ -53,7 +57,12 @@ export default class EditPage extends Vue {
|
|
53
57
|
this.unregisterRouterHook()
|
54
58
|
}
|
55
59
|
|
60
|
+
/**
|
61
|
+
* hook to allow to leave a just created (saved) model
|
62
|
+
*/
|
56
63
|
ignoreChangesOnRouteChange () {
|
64
|
+
// this.$refs.form.forceUnchanged()
|
65
|
+
console.info('TODO switch form to forceUnchanged')
|
57
66
|
this.ignoreChangesOnRouteChange_ = true
|
58
67
|
}
|
59
68
|
}
|