@afeefa/vue-app 0.0.220 → 0.0.221

Sign up to get free protection for your applications and to get access to all the features.
@@ -1 +1 @@
1
- 0.0.220
1
+ 0.0.221
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@afeefa/vue-app",
3
- "version": "0.0.220",
3
+ "version": "0.0.221",
4
4
  "description": "",
5
5
  "author": "Afeefa Kollektiv <kollektiv@afeefa.de>",
6
6
  "license": "MIT",
@@ -17,6 +17,7 @@ import RemoveDialog from './form/RemoveDialog'
17
17
  import HSeparator from './HSeparator'
18
18
  import ListCard from './list/ListCard'
19
19
  import ListColumnHeader from './list/ListColumnHeader'
20
+ import ListColumnSelector from './list/ListColumnSelector'
20
21
  import ListContent from './list/ListContent'
21
22
  import ListMeta from './list/ListMeta'
22
23
  import ListTitle from './list/ListTitle'
@@ -35,6 +36,7 @@ Vue.component('ListContent', ListContent)
35
36
  Vue.component('ListMeta', ListMeta)
36
37
  Vue.component('ListTitle', ListTitle)
37
38
  Vue.component('ListView', ListView)
39
+ Vue.component('ListColumnSelector', ListColumnSelector)
38
40
 
39
41
  Vue.component('EditPage', EditPage)
40
42
  Vue.component('EditFormButtons', EditFormButtons)
@@ -0,0 +1,58 @@
1
+ <template>
2
+ <div>
3
+ <a-context-menu>
4
+ <template #activator>
5
+ <div class="contextButton">
6
+ {{ selectedColumns.length }}/{{ Object.keys(columns).length }}
7
+ </div>
8
+ </template>
9
+
10
+ <a-checkbox-group
11
+ v-model="selectedColumns"
12
+ :options="options"
13
+ vertical
14
+ v-on="$listeners"
15
+ @input="columnSelected"
16
+ />
17
+ </a-context-menu>
18
+ </div>
19
+ </template>
20
+
21
+ <script>
22
+ import { Component, Vue } from '@a-vue'
23
+
24
+ @Component({
25
+ props: ['columns']
26
+ })
27
+ export default class ListColumnSelector extends Vue {
28
+ selectedColumns = []
29
+
30
+ created () {
31
+ this.selectedColumns = Object.keys(this.columns)
32
+ .filter(k => this.columns[k].visible)
33
+ }
34
+
35
+ get options () {
36
+ return Object.keys(this.columns).map(k => {
37
+ return {
38
+ itemText: this.columns[k].title,
39
+ itemValue: k
40
+ }
41
+ })
42
+ }
43
+
44
+ columnSelected () {
45
+ for (const key in this.columns) {
46
+ this.columns[key].visible = this.selectedColumns.includes(key)
47
+ }
48
+ }
49
+ }
50
+ </script>
51
+
52
+
53
+ <style lang="scss" scoped>
54
+ .contextButton {
55
+ font-size: .7rem;
56
+ cursor: pointer;
57
+ }
58
+ </style>
@@ -1,5 +1,8 @@
1
1
  <template>
2
- <div class="listView">
2
+ <div
3
+ class="listView"
4
+ @mousedown="startShifting"
5
+ >
3
6
  <div
4
7
  v-if="$has.filters"
5
8
  class="filters"
@@ -29,7 +32,9 @@
29
32
  <div class="a-table-wrapper">
30
33
  <a-table>
31
34
  <a-table-header>
32
- <div v-if="$has.icon" />
35
+ <div v-if="$has.icon">
36
+ <slot name="header-icon" />
37
+ </div>
33
38
 
34
39
  <slot name="header-table" />
35
40
  </a-table-header>
@@ -99,7 +104,7 @@
99
104
 
100
105
  <div
101
106
  v-if="$has.filters"
102
- class="filters"
107
+ class="filters filters-below"
103
108
  >
104
109
  <slot
105
110
  name="filters-below"
@@ -122,6 +127,11 @@ import { LoadingEvent } from '@a-vue/events'
122
127
  export default class ListView extends Mixins(ListViewMixin) {
123
128
  $hasOptions = ['icon', 'filters']
124
129
 
130
+ xStart = null
131
+ scrollLeftStart = null
132
+ yStart = null
133
+ scrollTopStart = null
134
+
125
135
  @Watch('isLoading')
126
136
  isLoadingChanged () {
127
137
  if (this.events) {
@@ -191,6 +201,81 @@ export default class ListView extends Mixins(ListViewMixin) {
191
201
  }
192
202
  this.$emit('flyingContext', model)
193
203
  }
204
+
205
+ startShifting (event) {
206
+ if (this.scrollContainerX || this.scrollContainerY) {
207
+ window.addEventListener('mouseup', this.stopShifting)
208
+ window.addEventListener('mousemove', this.shift)
209
+
210
+ this.$el.style.userSelect = 'none'
211
+
212
+ if (this.scrollContainerX) {
213
+ this.xStart = event.clientX
214
+ this.scrollLeftStart = this.scrollContainerX.scrollLeft
215
+ }
216
+
217
+ if (this.scrollContainerY) {
218
+ this.yStart = event.clientY
219
+ this.scrollTopStart = this.scrollContainerY.scrollTop
220
+ }
221
+ }
222
+ }
223
+
224
+ stopShifting (event) {
225
+ window.removeEventListener('mouseup', this.stopShifting)
226
+ window.removeEventListener('mousemove', this.shift)
227
+
228
+ this.$el.style.userSelect = 'auto'
229
+ }
230
+
231
+ shift (event) {
232
+ if (this.scrollContainerX || this.scrollContainerY) {
233
+ if (this.scrollContainerX) {
234
+ const diffX = this.xStart - event.clientX
235
+ this.scrollContainerX.scrollLeft = this.scrollLeftStart + diffX
236
+ }
237
+
238
+ if (this.scrollContainerY) {
239
+ const diffY = this.yStart - event.clientY
240
+ this.scrollContainerY.scrollTop = this.scrollTopStart + diffY
241
+ }
242
+ }
243
+ }
244
+
245
+ @Watch('$route.name')
246
+ routeChanged () {
247
+ if (this.scrollContainerX) {
248
+ this.scrollContainerX.scrollLeft = 0
249
+ }
250
+
251
+ if (this.scrollContainerY) {
252
+ this.scrollContainerY.scrollTop = 0
253
+ }
254
+ }
255
+
256
+ get scrollContainerX () {
257
+ return this.getScrollParent(this.$el.querySelector('.a-table-wrapper'), 'h')
258
+ }
259
+
260
+ get scrollContainerY () {
261
+ return this.getScrollParent(this.$el.querySelector('.a-table-wrapper'), 'v')
262
+ }
263
+
264
+ getScrollParent (node, direction) {
265
+ if (node == null) {
266
+ return null
267
+ }
268
+
269
+ if (direction === 'h' && (node.scrollWidth > node.clientWidth)) {
270
+ return node
271
+ }
272
+
273
+ if (direction === 'v' && (node.scrollHeight > node.clientHeight)) {
274
+ return node
275
+ }
276
+
277
+ return this.getScrollParent(node.parentNode, direction)
278
+ }
194
279
  }
195
280
  </script>
196
281
 
@@ -199,15 +284,26 @@ export default class ListView extends Mixins(ListViewMixin) {
199
284
  .listView {
200
285
  max-width: 100%;
201
286
  padding-top: .2rem; // unless, floating input labels might be cut
287
+ }
288
+
289
+ .a-table-wrapper {
290
+ max-width: 100%;
202
291
  overflow-x: auto;
203
292
  overflow-y: hidden;
293
+ padding-bottom: 1rem;
294
+ cursor: grab;
204
295
  }
205
296
 
206
- .filters {
297
+ .filters:not(:empty) {
207
298
  margin-left: 4px;
208
299
  margin-bottom: 2rem;
209
300
  }
210
301
 
302
+ filters-below:not(:empty) {
303
+ margin-left: 4px;
304
+ margin-top: 2rem;
305
+ }
306
+
211
307
  :deep(.a-table-row > :last-child) {
212
308
  width: 100%;
213
309
  }