@afeefa/vue-app 0.0.48 → 0.0.52

Sign up to get free protection for your applications and to get access to all the features.
@@ -1 +1 @@
1
- 0.0.48
1
+ 0.0.52
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@afeefa/vue-app",
3
- "version": "0.0.48",
3
+ "version": "0.0.52",
4
4
  "description": "",
5
5
  "author": "Afeefa Kollektiv <kollektiv@afeefa.de>",
6
6
  "license": "MIT",
@@ -197,6 +197,7 @@ export class RemoveAction {
197
197
  .params({
198
198
  id: this.id
199
199
  })
200
+ .data(null)
200
201
  .send()
201
202
 
202
203
  if (this.afterRemoveHook) {
@@ -6,7 +6,7 @@
6
6
  >
7
7
  <slot name="activator">
8
8
  <a-icon class="contextButton">
9
- $dotsHorizontalIcon
9
+ {{ triggerIcon || '$dotsHorizontalIcon' }}
10
10
  </a-icon>
11
11
  </slot>
12
12
  </div>
@@ -31,7 +31,7 @@ import { Positions, PositionConfig } from '../services/PositionService'
31
31
  import { randomCssClass } from '../utils/random'
32
32
 
33
33
  @Component({
34
- props: ['contentHeight', 'repositionWatchKey']
34
+ props: ['contentHeight', 'repositionWatchKey', 'triggerIcon']
35
35
  })
36
36
  export default class AContextMenu extends Mixins(UsesPositionServiceMixin) {
37
37
  CONTEXT_MENU = true
@@ -10,7 +10,9 @@
10
10
  <script>
11
11
  import { Component, Vue } from 'vue-property-decorator'
12
12
 
13
- @Component
13
+ @Component({
14
+ props: ['to']
15
+ })
14
16
  export default class AContextMenuItem extends Vue {
15
17
  get contextMenu () {
16
18
  let parent = this.$parent
@@ -25,7 +27,12 @@ export default class AContextMenuItem extends Vue {
25
27
 
26
28
  click () {
27
29
  this.contextMenu.close()
28
- this.$emit('click')
30
+ if (this.to) {
31
+ this.$router.push(this.to)
32
+ .catch(() => null) // prevent duplicated navigation
33
+ } else {
34
+ this.$emit('click')
35
+ }
29
36
  }
30
37
  }
31
38
  </script>
@@ -46,8 +46,8 @@
46
46
  v-if="isOpen"
47
47
  v-bind="listConfig"
48
48
  :q="q"
49
- :noEvents="true"
50
- :noHistory="true"
49
+ :events="false"
50
+ :history="false"
51
51
  :filterSource="filterSource"
52
52
  :loadOnlyIfKeyword="_loadOnlyIfKeyword"
53
53
  :count.sync="count"
@@ -1,6 +1,6 @@
1
- import { BaseFilterSource } from '@afeefa/api-resources-client'
1
+ import { ListViewFilterSource } from '@afeefa/api-resources-client'
2
2
 
3
- export class RouteFilterSource extends BaseFilterSource {
3
+ export class CurrentRouteFilterSource extends ListViewFilterSource {
4
4
  router = null
5
5
 
6
6
  constructor (router) {
@@ -2,9 +2,6 @@ export class FilterSourceType {
2
2
  // filters are synchronized with url's query string
3
3
  static QUERY_STRING = 'query_string'
4
4
 
5
- // filters are initialized from given route params (no synchronisation allowed)
6
- static ROUTE_PARAMS = 'route_params'
7
-
8
5
  // filters are synchronized with plain history object
9
6
  static OBJECT = 'object'
10
7
  }
@@ -1,26 +1,31 @@
1
1
  import { ListAction } from '@a-vue/api-resources/ApiActions'
2
+ import { propsWithDefaults } from '@a-vue/utils/props-helper'
2
3
  import { ListViewModel } from '@afeefa/api-resources-client'
3
4
  import { Component, Vue, Watch } from 'vue-property-decorator'
4
5
 
6
+ import { CurrentRouteFilterSource } from './CurrentRouteFilterSource'
5
7
  import { FilterSourceType } from './FilterSourceType'
6
- import { RouteFilterSource } from './RouteFilterSource'
7
8
 
8
9
  @Component({
9
- props: [
10
- 'models', 'meta', // if already loaded
10
+ ...propsWithDefaults([
11
+ 'models', 'meta', // given, if already loaded
11
12
  'listViewConfig',
12
- 'noEvents', 'noHistory',
13
- 'filterHistoryKey', 'filterSource',
14
- 'loadOnlyIfKeyword'
15
- ]
13
+ 'filterHistoryKey',
14
+ 'loadOnlyIfKeyword',
15
+ {
16
+ filterSource: FilterSourceType.QUERY_STRING,
17
+ events: true,
18
+ history: true
19
+ }
20
+ ])
16
21
  })
17
22
  export class ListViewMixin extends Vue {
18
23
  LIST_VIEW = true
19
24
 
25
+ listViewModel = null
20
26
  models_ = []
21
27
  meta_ = {}
22
28
  isLoading = false
23
- listViewModel = null
24
29
 
25
30
  created () {
26
31
  this.init()
@@ -36,10 +41,12 @@ export class ListViewMixin extends Vue {
36
41
  this.listViewModel.off('change', this.filtersChanged)
37
42
  }
38
43
 
39
- const historyKey = this.noHistory
40
- ? undefined
41
- : [this.$route.path, this.filterHistoryKey].filter(i => i).join('.')
42
- const filterSource = this.filterSource === FilterSourceType.OBJECT ? undefined : new RouteFilterSource(this.$router)
44
+ const historyKey = this.history
45
+ ? [this.$route.path, this.filterHistoryKey].filter(i => i).join('.')
46
+ : undefined
47
+ const filterSource = this.filterSource === FilterSourceType.QUERY_STRING
48
+ ? new CurrentRouteFilterSource(this.$router)
49
+ : undefined
43
50
 
44
51
  if (this.models) {
45
52
  this.models_ = this.models
@@ -47,12 +54,12 @@ export class ListViewMixin extends Vue {
47
54
  }
48
55
 
49
56
  this.listViewModel = new ListViewModel(this.listViewConfig)
50
- .filterSource(filterSource, true)
51
- .historyKey(historyKey, true)
57
+ .filterSource(filterSource, !!filterSource)
58
+ .historyKey(historyKey, this.history)
52
59
  .usedFilters(this.meta_.used_filters || null, this.meta_.count_search || 0)
53
60
  .initFilters({
54
- source: true,
55
- history: true,
61
+ source: !!filterSource,
62
+ history: !!historyKey,
56
63
  used: !!this.models
57
64
  })
58
65
  .on('change', this.filtersChanged) // listen to change
@@ -68,7 +75,7 @@ export class ListViewMixin extends Vue {
68
75
 
69
76
  @Watch('$route.query')
70
77
  routeQueryChanged () {
71
- if (this.filterSource !== FilterSourceType.QUERY_STRING) {
78
+ if (this.filterSource === FilterSourceType.QUERY_STRING) {
72
79
  this.listViewModel.filterSourceChanged()
73
80
  }
74
81
  }
@@ -117,7 +124,7 @@ export class ListViewMixin extends Vue {
117
124
 
118
125
  const {models, meta} = await new ListAction()
119
126
  .setRequest(request)
120
- .noEvents(this.noEvents === true)
127
+ .noEvents(!this.events)
121
128
  .load()
122
129
 
123
130
  if (!models) { // error happened
@@ -0,0 +1,15 @@
1
+ import { ListViewFilterSource } from '@afeefa/api-resources-client'
2
+
3
+ export class NextRouteFilterSource extends ListViewFilterSource {
4
+ route = null
5
+
6
+ constructor (route) {
7
+ super()
8
+
9
+ this.route = route
10
+ }
11
+
12
+ getQuery () {
13
+ return this.route.query
14
+ }
15
+ }
@@ -22,7 +22,7 @@ export default class ListFilterSelect extends Mixins(ListFilterMixin) {
22
22
  items = null
23
23
 
24
24
  created () {
25
- if (this.filter.hasRequest()) {
25
+ if (this.filter.hasOptionsRequest()) {
26
26
  this.items = this.loadRequestOptions()
27
27
  } else if (this.filter.hasOptions()) {
28
28
  this.items = this.getOptions()
@@ -54,7 +54,7 @@ export default class ListFilterSelect extends Mixins(ListFilterMixin) {
54
54
 
55
55
  async loadRequestOptions () {
56
56
  const {models} = await new ListAction()
57
- .setRequest(this.filter.request)
57
+ .setRequest(this.filter.createOptionsRequest())
58
58
  .noEvents()
59
59
  .load()
60
60
 
@@ -0,0 +1,21 @@
1
+ export function propsWithDefaults (props) {
2
+ const normalizedProps = {}
3
+
4
+ for (const prop of props) {
5
+ if (typeof prop === 'object') {
6
+ Object.keys(prop).forEach(subProp => {
7
+ if (typeof prop[subProp] === 'object') {
8
+ normalizedProps[subProp] = prop[subProp]
9
+ } else {
10
+ normalizedProps[subProp] = { default: prop[subProp] }
11
+ }
12
+ })
13
+ } else {
14
+ normalizedProps[prop] = null
15
+ }
16
+ }
17
+
18
+ return {
19
+ props: normalizedProps
20
+ }
21
+ }
@@ -13,7 +13,7 @@
13
13
  >
14
14
  <router-link
15
15
  :to="{name: rootRouteName}"
16
- class="logoContainer d-flex flex-column pa-6"
16
+ class="logoContainer d-flex flex-column align-center pa-6"
17
17
  >
18
18
  <img
19
19
  v-if="logoUrl"
@@ -59,32 +59,14 @@
59
59
  </div>
60
60
  </div>
61
61
 
62
- <v-menu top>
63
- <template #activator="{ on, attrs }">
64
- <v-icon
65
- class="contextButton"
66
- v-bind="attrs"
67
- v-on="on"
68
- >
69
- $dotsVerticalIcon
70
- </v-icon>
71
- </template>
72
-
73
- <v-list
74
- class="pa-0"
62
+ <a-context-menu triggerIcon="$dotsVerticalIcon">
63
+ <a-context-menu-item
64
+ :to="{name: 'settings', params: {accountId: account.id}}"
75
65
  >
76
- <v-list-item :to="{name: 'accounts.edit', params: {accountId: account.id}}">
77
- <v-list-item-icon class="ma-0 mr-2 align-self-center">
78
- <v-icon class="ml-n1 mr-1">
79
- $pencilIcon
80
- </v-icon>
81
- </v-list-item-icon>
82
- <v-list-item-title>
83
- Einstellungen
84
- </v-list-item-title>
85
- </v-list-item>
86
- </v-list>
87
- </v-menu>
66
+ <v-icon>$pencilIcon</v-icon>
67
+ Einstellungen
68
+ </a-context-menu-item>
69
+ </a-context-menu>
88
70
  </div>
89
71
  </v-container>
90
72
  </v-container>
@@ -73,7 +73,7 @@ export default class ListView extends Mixins(ListViewMixin) {
73
73
 
74
74
  @Watch('isLoading')
75
75
  isLoadingChanged () {
76
- if (this.noEvents === undefined || !this.noEvents) {
76
+ if (this.events) {
77
77
  if (this.isLoading) {
78
78
  this.$events.dispatch(new LoadingEvent(LoadingEvent.START_LOADING))
79
79
  } else {
@@ -56,8 +56,8 @@ import { apiResources } from '@afeefa/api-resources-client'
56
56
  })
57
57
  export default class CreatePage extends Mixins(EditPageMixin) {
58
58
  created () {
59
- if (!this.$parent.constructor.getCreateConfig) {
60
- console.warn('<create-page> owner must provide a static getCreateConfig method.')
59
+ if (!this.$parent.constructor.createRouteConfig) {
60
+ console.warn('<create-page> owner must provide a static createRouteConfig method.')
61
61
  }
62
62
 
63
63
  this.reset()
@@ -65,11 +65,11 @@ export default class CreatePage extends Mixins(EditPageMixin) {
65
65
  }
66
66
 
67
67
  get editConfig () {
68
- return this.$parent.constructor.getCreateConfig(this.$route)
68
+ return this.$parent.constructor.createRouteConfig
69
69
  }
70
70
 
71
71
  get modelUpateAction () {
72
- return this.ModelClass.getAction('create')
72
+ return this.editConfig.createAction || this.ModelClass.getAction('save')
73
73
  }
74
74
 
75
75
  get _icon () {
@@ -55,7 +55,7 @@ import { Component, Vue, Watch } from 'vue-property-decorator'
55
55
  import { RemoveAction } from '@a-vue/api-resources/ApiActions'
56
56
 
57
57
  @Component({
58
- props: ['model', 'title', 'icon', 'removeAction', 'protectRemove', 'listLink']
58
+ props: ['model', 'title', 'icon', 'protectRemove', 'listLink']
59
59
  })
60
60
  export default class DetailPage extends Vue {
61
61
  $hasOptions = ['edit', 'remove', 'list']
@@ -64,7 +64,7 @@ export default class DetailPage extends Vue {
64
64
  removeConfirmed = null
65
65
 
66
66
  created () {
67
- if (!this.$parent.constructor.getDetailConfig) {
67
+ if (!this.$parent.constructor.detailRouteConfig) {
68
68
  console.warn('<detail-page> owner must provide a static getDetailConfig method.')
69
69
  }
70
70
  this.$emit('model', this.model)
@@ -80,7 +80,7 @@ export default class DetailPage extends Vue {
80
80
  }
81
81
 
82
82
  get detailConfig () {
83
- return this.$parent.constructor.getDetailConfig(this.$route)
83
+ return this.$parent.constructor.detailRouteConfig
84
84
  }
85
85
 
86
86
  get document () {
@@ -110,10 +110,7 @@ export default class DetailPage extends Vue {
110
110
  }
111
111
 
112
112
  get _deleteAction () {
113
- if (this.removeAction) {
114
- return this.removeAction
115
- }
116
- return this.ModelClass.getAction('delete')
113
+ return this.detailConfig.removeAction || this.ModelClass.getAction('save')
117
114
  }
118
115
 
119
116
  async remove () {
@@ -78,8 +78,8 @@ export default class EditPage extends Mixins(EditPageMixin) {
78
78
  model_ = null
79
79
 
80
80
  created () {
81
- if (!this.$parent.constructor.getEditConfig) {
82
- console.warn('<edit-page> owner must provide a static getEditConfig method.')
81
+ if (!this.$parent.constructor.editRouteConfig) {
82
+ console.warn('<edit-page> owner must provide a static editRouteConfig method.')
83
83
  }
84
84
 
85
85
  this.model_ = this.model
@@ -95,11 +95,11 @@ export default class EditPage extends Mixins(EditPageMixin) {
95
95
  }
96
96
 
97
97
  get editConfig () {
98
- return this.$parent.constructor.getEditConfig(this.$route)
98
+ return this.$parent.constructor.editRouteConfig
99
99
  }
100
100
 
101
101
  get modelUpateAction () {
102
- return this.ModelClass.getAction('update')
102
+ return this.editConfig.updateAction || this.ModelClass.getAction('save')
103
103
  }
104
104
 
105
105
  get _getAction () {
@@ -18,13 +18,18 @@ Component.registerHooks([
18
18
  function load (route) {
19
19
  const routeDefinition = route.meta.routeDefinition
20
20
  const Component = routeDefinition.config.detail
21
- const detailConfig = Component.getDetailConfig(route)
21
+
22
+ if (!Component.detailRouteConfig) {
23
+ console.warn('A detail route component must implement a static detailRouteConfig property.')
24
+ }
25
+
26
+ const detailConfig = Component.detailRouteConfig
22
27
  const action = detailConfig.action || detailConfig.ModelClass.getAction('get')
23
28
 
24
29
  return new GetAction()
25
30
  .setAction(action)
26
31
  .setFields(detailConfig.fields)
27
- .setId(route.params[routeDefinition.idKey])
32
+ .setId(detailConfig.id || route.params[routeDefinition.idKey])
28
33
  .load()
29
34
  }
30
35
 
@@ -19,13 +19,18 @@ Component.registerHooks([
19
19
  function load (route) {
20
20
  const routeDefinition = route.meta.routeDefinition
21
21
  const Component = routeDefinition.config.edit
22
- const editConfig = Component.getEditConfig(route)
22
+
23
+ if (!Component.editRouteConfig) {
24
+ console.warn('An edit route component must implement a static editRouteConfig property.')
25
+ }
26
+
27
+ const editConfig = Component.editRouteConfig
23
28
  const action = editConfig.getAction || editConfig.ModelClass.getAction('get')
24
29
 
25
30
  return new GetAction()
26
31
  .setAction(action)
27
32
  .setFields(editConfig.fields)
28
- .setId(route.params[routeDefinition.idKey])
33
+ .setId(editConfig.id || route.params[routeDefinition.idKey])
29
34
  .load()
30
35
  }
31
36
 
@@ -10,7 +10,7 @@
10
10
  <script>
11
11
  import { Component, Vue, Watch } from 'vue-property-decorator'
12
12
  import { ListAction } from '@a-vue/api-resources/ApiActions'
13
- import { RouteQueryFilterSource } from '@a-vue/components/list/RouteQueryFilterSource'
13
+ import { NextRouteFilterSource } from '@a-vue/components/list/NextRouteFilterSource'
14
14
  import { ListViewModel } from '@afeefa/api-resources-client'
15
15
 
16
16
  Component.registerHooks([
@@ -36,7 +36,11 @@ function load (route) {
36
36
  }
37
37
 
38
38
  const request = new ListViewModel(Component.listViewConfig)
39
- .filterSource(new RouteQueryFilterSource(route), false)
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
40
44
  .historyKey(route.path, false)
41
45
  .initFilters({
42
46
  source: true,
@@ -1,18 +0,0 @@
1
- import { BaseFilterSource } from '@afeefa/api-resources-client'
2
-
3
- export class RouteQueryFilterSource extends BaseFilterSource {
4
- route = null
5
-
6
- constructor (route) {
7
- super()
8
-
9
- this.route = route
10
- }
11
-
12
- getQuery () {
13
- return this.route.query
14
- }
15
-
16
- push (_query) {
17
- }
18
- }