@afeefa/vue-app 0.0.63 → 0.0.66

Sign up to get free protection for your applications and to get access to all the features.
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
  }