@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.
Files changed (51) hide show
  1. package/.afeefa/package/release/version.txt +1 -1
  2. package/package.json +1 -1
  3. package/src/components/ABreadcrumbs.vue +75 -18
  4. package/src/components/ADatePicker.vue +1 -1
  5. package/src/components/AIcon.vue +3 -6
  6. package/src/components/AIconButton.vue +1 -2
  7. package/src/components/AModal.vue +21 -3
  8. package/src/components/ARichTextArea.vue +95 -85
  9. package/src/components/ARow.vue +0 -7
  10. package/src/components/ATableRow.vue +4 -0
  11. package/src/components/flying-context/FlyingContextEvent.js +5 -0
  12. package/src/components/form/EditForm.vue +13 -3
  13. package/src/components/form/EditModal.vue +52 -35
  14. package/src/components/form/fields/FormFieldRichTextArea.vue +5 -3
  15. package/src/components/list/ListViewMixin.js +25 -2
  16. package/src/components/mixins/ClickOutsideMixin.js +5 -1
  17. package/src/components/search-select/SearchSelectList.vue +0 -1
  18. package/src/components/vue/Component.js +9 -2
  19. package/src/events.js +2 -0
  20. package/src-admin/bootstrap.js +1 -0
  21. package/src-admin/components/App.vue +58 -59
  22. package/src-admin/components/FlyingContext.vue +77 -0
  23. package/src-admin/components/FlyingContextContainer.vue +85 -0
  24. package/src-admin/components/Sidebar.vue +66 -0
  25. package/src-admin/components/SidebarItem.vue +59 -0
  26. package/src-admin/components/StickyFooter.vue +42 -0
  27. package/src-admin/components/StickyFooterContainer.vue +66 -0
  28. package/src-admin/components/StickyHeader.vue +73 -0
  29. package/src-admin/components/app/AppBarButtons.vue +0 -7
  30. package/src-admin/components/app/AppBarTitle.vue +55 -11
  31. package/src-admin/components/app/AppBarTitleContainer.vue +2 -3
  32. package/src-admin/components/controls/SearchSelectFormField.vue +1 -0
  33. package/src-admin/components/detail/DetailProperty.vue +20 -16
  34. package/src-admin/components/form/EditFormButtons.vue +25 -6
  35. package/src-admin/components/form/RemoveButton.vue +17 -8
  36. package/src-admin/components/index.js +6 -7
  37. package/src-admin/components/list/ListView.vue +22 -9
  38. package/src-admin/components/pages/EditPage.vue +17 -8
  39. package/src-admin/components/routes/DataRouteMixin.js +24 -15
  40. package/src-admin/config/routing.js +0 -11
  41. package/src-admin/config/vuetify.js +22 -2
  42. package/src-admin/directives/index.js +26 -0
  43. package/src-admin/styles.scss +21 -4
  44. package/src-admin/components/pages/CreatePage.vue +0 -114
  45. package/src-admin/components/pages/DetailPage.vue +0 -143
  46. package/src-admin/components/pages/EditPageMixin.js +0 -96
  47. package/src-admin/components/pages/ListPage.vue +0 -55
  48. package/src-admin/components/routes/CreateRoute.vue +0 -15
  49. package/src-admin/components/routes/DetailRoute.vue +0 -85
  50. package/src-admin/components/routes/EditRoute.vue +0 -78
  51. 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>
@@ -12,10 +12,3 @@ import { Component, Vue } from '@a-vue'
12
12
  export default class AppBarButtons extends Vue {
13
13
  }
14
14
  </script>
15
-
16
-
17
- <style lang="scss" scoped>
18
- #appBarButtons:empty {
19
- display: none !important;
20
- }
21
- </style>
@@ -1,13 +1,36 @@
1
1
  <template>
2
- <div class="d-flex align-center">
3
- <v-icon
4
- class="mr-2"
5
- :color="icon.color"
6
- size="1.8rem"
7
- v-text="icon.icon"
8
- />
9
-
10
- <h2>{{ title }}</h2>
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
- // white-space: nowrap;
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:empty {
17
- display: none;
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>
@@ -68,6 +68,7 @@
68
68
  >
69
69
  <template #activator>
70
70
  <a-icon-button
71
+ small
71
72
  icon="$plusIcon"
72
73
  :text="selectableConfig.addButtonTitle || 'Hinzufügen'"
73
74
  class="mt-4"
@@ -1,17 +1,23 @@
1
1
  <template>
2
2
  <div class="detailProperty">
3
3
  <div class="header">
4
- <v-icon
4
+ <v-avatar
5
5
  v-if="_icon"
6
- :color="_icon.color"
7
- size="2rem"
6
+ color="#EEEEEE"
7
+ size="2.5rem"
8
8
  >
9
- {{ _icon.icon }}
10
- </v-icon>
11
- <label :class="['label', {'label--withIcon': _icon != null}]">{{ label }}</label>
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 != null}]">
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
- .v-icon {
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
- @media (max-width: 900px), (orientation : portrait) {
64
- padding-left: 55px;
65
- &--withIcon {
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 gap="2">
2
+ <a-row
3
+ gap="1"
4
+ v-bind="$attrs"
5
+ >
3
6
  <v-btn
4
- :small="small"
5
- :disabled="!changed || !valid"
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
- Speichern
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
- 'small'
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
- <a-icon-button
4
- small
5
- color="red white--text"
6
- :class="'removeButton-' + dialogId"
7
- icon="$trashCanIcon"
8
- text="Löschen"
9
- @click="remove"
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 ListPage from './pages/ListPage'
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
- :class="getModelClass(model)"
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: ['modelClass']
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
- getModelClass (model) {
97
- return this.modelClass && this.modelClass(model)
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
- setFilter (name, value) {
101
- this.filters[name].value = value
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 #default="{model, changed, valid}">
7
+ <template #form="{modelToEdit, changed, valid}">
8
8
  <slot
9
- :model="model"
9
+ name="form"
10
+ :modelToEdit="modelToEdit"
10
11
  :changed="changed"
11
12
  :valid="valid"
12
13
  />
13
14
 
14
- <edit-form-buttons
15
- :changed="changed"
16
- :valid="valid"
17
- @save="$emit('save', model, ignoreChangesOnRouteChange)"
18
- @reset="$refs.form.reset()"
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
  }