@afeefa/vue-app 0.0.109 → 0.0.111
Sign up to get free protection for your applications and to get access to all the features.
- package/.afeefa/package/release/version.txt +1 -1
- package/README.md +4 -0
- package/docs/components/amodal.md +19 -0
- package/package.json +1 -1
- package/src/api-resources/ApiAction.js +6 -0
- package/src/api-resources/DeleteAction.js +7 -5
- package/src/api-resources/GetAction.js +7 -5
- package/src/api-resources/SaveAction.js +7 -5
- package/src/components/AAutocomplete.vue +2 -2
- package/src/components/ADatePicker.vue +3 -2
- package/src/components/AGrid.vue +11 -4
- package/src/components/AModal.vue +6 -5
- package/src/components/ASelect.vue +9 -2
- package/src/components/ATextArea.vue +2 -2
- package/src/components/ATextField.vue +131 -41
- package/src/components/form/fields/FormFieldText.vue +2 -68
- package/src/components/index.js +0 -2
- package/src/components/list/filters/ListFilterPage.vue +3 -4
- package/src/components/list/filters/ListFilterSearch.vue +1 -0
- package/src/components/list/filters/ListFilterSelect.vue +1 -0
- package/src/index.js +1 -1
- package/src-admin/bootstrap.js +1 -1
- package/src-admin/components/controls/SearchSelectFormField.vue +2 -2
- package/src/components/list/ListFilterRow.vue +0 -26
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.111
|
package/README.md
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
# AModal
|
2
|
+
|
3
|
+
It's a Modal capsule for vuetifys Modals. Whats the magic about it?
|
4
|
+
|
5
|
+
The Modal is by default relatively positioned near its activator.
|
6
|
+
|
7
|
+
## Properties
|
8
|
+
|
9
|
+
* show
|
10
|
+
* icon
|
11
|
+
* title
|
12
|
+
* beforeClose
|
13
|
+
* anchorPosition
|
14
|
+
* screenCentered
|
15
|
+
|
16
|
+
|
17
|
+
### screenCentered
|
18
|
+
|
19
|
+
if set to true the Modal is positioned in the middle of the Viewport, like in vuetify's default beavior.
|
package/package.json
CHANGED
@@ -10,6 +10,7 @@ export class ApiAction extends ApiResourcesApiAction {
|
|
10
10
|
_dispatchGlobalSaveEvents = false
|
11
11
|
_minDuration = 100
|
12
12
|
_startTime = 0
|
13
|
+
_showError = true
|
13
14
|
|
14
15
|
id (id) {
|
15
16
|
this.param('id', id)
|
@@ -21,6 +22,11 @@ export class ApiAction extends ApiResourcesApiAction {
|
|
21
22
|
return this
|
22
23
|
}
|
23
24
|
|
25
|
+
hideError () {
|
26
|
+
this._showError = false
|
27
|
+
return this
|
28
|
+
}
|
29
|
+
|
24
30
|
dispatchGlobalLoadingEvents (dispatch = true) {
|
25
31
|
this._dispatchGlobalLoadingEvents = dispatch
|
26
32
|
return this
|
@@ -27,10 +27,12 @@ export class DeleteAction extends ApiAction {
|
|
27
27
|
}
|
28
28
|
|
29
29
|
processError (result) {
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
30
|
+
if (this._showError) {
|
31
|
+
eventBus.dispatch(new AlertEvent(AlertEvent.ERROR, {
|
32
|
+
headline: 'Die Daten konnten nicht gelöscht werden.',
|
33
|
+
message: result.message,
|
34
|
+
detail: result.detail
|
35
|
+
}))
|
36
|
+
}
|
35
37
|
}
|
36
38
|
}
|
@@ -9,10 +9,12 @@ export class GetAction extends ApiAction {
|
|
9
9
|
}
|
10
10
|
|
11
11
|
processError (result) {
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
if (this._showError) {
|
13
|
+
eventBus.dispatch(new AlertEvent(AlertEvent.ERROR, {
|
14
|
+
headline: 'Die Daten konntent nicht geladen werden.',
|
15
|
+
message: result.message,
|
16
|
+
detail: result.detail
|
17
|
+
}))
|
18
|
+
}
|
17
19
|
}
|
18
20
|
}
|
@@ -17,10 +17,12 @@ export class SaveAction extends ApiAction {
|
|
17
17
|
}
|
18
18
|
|
19
19
|
processError (result) {
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
if (this._showError) {
|
21
|
+
eventBus.dispatch(new AlertEvent(AlertEvent.ERROR, {
|
22
|
+
headline: 'Die Daten konnten nicht gespeichert werden.',
|
23
|
+
message: result.message,
|
24
|
+
detail: result.detail
|
25
|
+
}))
|
26
|
+
}
|
25
27
|
}
|
26
28
|
}
|
@@ -11,7 +11,7 @@
|
|
11
11
|
no-filter
|
12
12
|
|
13
13
|
:rules="validationRules"
|
14
|
-
v-bind="
|
14
|
+
v-bind="{...$attrs, dense, outlined}"
|
15
15
|
v-on="$listeners"
|
16
16
|
/>
|
17
17
|
</template>
|
@@ -23,7 +23,7 @@ import { Model } from '@afeefa/api-resources-client'
|
|
23
23
|
import { debounce } from '@a-vue/utils/debounce'
|
24
24
|
|
25
25
|
@Component({
|
26
|
-
props: ['items', 'validator', 'defaultValue', 'selectedItemText', 'debounce']
|
26
|
+
props: ['items', 'validator', 'defaultValue', 'selectedItemText', 'debounce', {dense: true, outlined: true}]
|
27
27
|
})
|
28
28
|
export default class AAutocomplete extends Vue {
|
29
29
|
isLoading = false
|
@@ -12,7 +12,7 @@
|
|
12
12
|
:value="formattedDate"
|
13
13
|
:label="label"
|
14
14
|
:style="cwm_widthStyle"
|
15
|
-
v-bind="{...$attrs, ...attrs}"
|
15
|
+
v-bind="{...$attrs, ...attrs, dense, outlined}"
|
16
16
|
:rules="validationRules"
|
17
17
|
:error-messages="errorMessages"
|
18
18
|
:readonly="type === 'month'"
|
@@ -41,7 +41,7 @@ import { formatDate } from '@a-vue/utils/format-date'
|
|
41
41
|
import { ComponentWidthMixin } from './mixins/ComponentWidthMixin'
|
42
42
|
|
43
43
|
@Component({
|
44
|
-
props: ['value', 'validator', 'type']
|
44
|
+
props: ['value', 'validator', 'type', {dense: true, outlined: true}]
|
45
45
|
})
|
46
46
|
export default class ADatePicker extends Mixins(ComponentWidthMixin) {
|
47
47
|
value_ = null
|
@@ -153,6 +153,7 @@ export default class ADatePicker extends Mixins(ComponentWidthMixin) {
|
|
153
153
|
<style lang="scss" scoped>
|
154
154
|
:deep(.v-select__slot) {
|
155
155
|
cursor: pointer;
|
156
|
+
|
156
157
|
input {
|
157
158
|
cursor: pointer;
|
158
159
|
}
|
package/src/components/AGrid.vue
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
<template>
|
2
|
-
<div
|
2
|
+
<div
|
3
|
+
:style="{display: displayStyle}"
|
4
|
+
:class="['a-grid', colsClass, gapClass, evenClass, breakMobileClass]"
|
5
|
+
>
|
3
6
|
<slot />
|
4
7
|
</div>
|
5
8
|
</template>
|
@@ -10,7 +13,7 @@ import { Component, Mixins } from '@a-vue'
|
|
10
13
|
import { ComponentWidthMixin } from './mixins/ComponentWidthMixin'
|
11
14
|
|
12
15
|
@Component({
|
13
|
-
props: ['gap', 'hGap', 'vGap', 'cols', {even: false}, 'breakMobile']
|
16
|
+
props: ['gap', 'hGap', 'vGap', 'cols', {inline: false, even: false}, 'breakMobile']
|
14
17
|
})
|
15
18
|
export default class AGrid extends Mixins(ComponentWidthMixin) {
|
16
19
|
get breakMobileClass () {
|
@@ -19,6 +22,10 @@ export default class AGrid extends Mixins(ComponentWidthMixin) {
|
|
19
22
|
}
|
20
23
|
}
|
21
24
|
|
25
|
+
get displayStyle () {
|
26
|
+
return this.inline ? 'inline-grid' : 'grid'
|
27
|
+
}
|
28
|
+
|
22
29
|
get colsClass () {
|
23
30
|
const cols = this.cols || 2
|
24
31
|
return 'cols-' + cols
|
@@ -53,11 +60,10 @@ export default class AGrid extends Mixins(ComponentWidthMixin) {
|
|
53
60
|
|
54
61
|
<style scoped lang="scss">
|
55
62
|
.a-grid {
|
56
|
-
display: grid;
|
57
|
-
|
58
63
|
@for $i from 1 through 8 {
|
59
64
|
&.cols-#{$i} {
|
60
65
|
grid-template-columns: repeat(#{$i}, auto);
|
66
|
+
|
61
67
|
&.even {
|
62
68
|
grid-template-columns: repeat(#{$i}, 1fr);
|
63
69
|
}
|
@@ -67,6 +73,7 @@ export default class AGrid extends Mixins(ComponentWidthMixin) {
|
|
67
73
|
&.breakMobile {
|
68
74
|
@media (max-width: 900px), (orientation : portrait) {
|
69
75
|
grid-template-columns: 1fr;
|
76
|
+
|
70
77
|
&.even {
|
71
78
|
grid-template-columns: 1fr;
|
72
79
|
}
|
@@ -14,7 +14,7 @@
|
|
14
14
|
<template #activator="{ on }">
|
15
15
|
<div
|
16
16
|
style="width: max-content;"
|
17
|
-
:class="
|
17
|
+
:class="activatorClass"
|
18
18
|
v-on="on"
|
19
19
|
>
|
20
20
|
<slot name="activator" />
|
@@ -56,7 +56,7 @@ import { ComponentWidthMixin } from './mixins/ComponentWidthMixin'
|
|
56
56
|
import { CancelOnEscMixin } from '@a-vue/services/escape/CancelOnEscMixin'
|
57
57
|
|
58
58
|
@Component({
|
59
|
-
props: ['show', 'icon', 'title', 'beforeClose', '
|
59
|
+
props: ['show', 'icon', 'title', 'beforeClose', 'anchorPosition', 'screenCentered']
|
60
60
|
})
|
61
61
|
export default class ADialog extends Mixins(UsesPositionServiceMixin, ComponentWidthMixin, CancelOnEscMixin) {
|
62
62
|
modalId = randomCssClass(10)
|
@@ -121,7 +121,9 @@ export default class ADialog extends Mixins(UsesPositionServiceMixin, ComponentW
|
|
121
121
|
@Watch('modal')
|
122
122
|
modalChanged () {
|
123
123
|
if (this.modal) {
|
124
|
-
this.
|
124
|
+
if (!this.screenCentered) {
|
125
|
+
this.setPosition()
|
126
|
+
}
|
125
127
|
} else {
|
126
128
|
this.removeTransientAnchor()
|
127
129
|
}
|
@@ -204,13 +206,12 @@ export default class ADialog extends Mixins(UsesPositionServiceMixin, ComponentW
|
|
204
206
|
|
205
207
|
:deep(.v-dialog) {
|
206
208
|
position: absolute;
|
207
|
-
top: 0;
|
208
|
-
left: 0;
|
209
209
|
margin: 0;
|
210
210
|
|
211
211
|
transition: none;
|
212
212
|
|
213
213
|
&.v-fade-transition {
|
214
|
+
|
214
215
|
&-enter-active, &-leave, &-leave-to {
|
215
216
|
transition: opacity .3s ease;
|
216
217
|
}
|
@@ -5,7 +5,7 @@
|
|
5
5
|
:items="items_"
|
6
6
|
:valueComparator="compareValues"
|
7
7
|
:style="cwm_widthStyle"
|
8
|
-
v-bind="
|
8
|
+
v-bind="{...$attrs, dense, outlined}"
|
9
9
|
v-on="$listeners"
|
10
10
|
/>
|
11
11
|
</template>
|
@@ -17,7 +17,7 @@ import { Model } from '@afeefa/api-resources-client'
|
|
17
17
|
import { ComponentWidthMixin } from './mixins/ComponentWidthMixin'
|
18
18
|
|
19
19
|
@Component({
|
20
|
-
props: ['validator', 'defaultValue', 'items']
|
20
|
+
props: ['validator', 'defaultValue', 'items', {dense: true, outlined: true}]
|
21
21
|
})
|
22
22
|
export default class ASelect extends Mixins(ComponentWidthMixin) {
|
23
23
|
items_ = []
|
@@ -96,3 +96,10 @@ export default class ASelect extends Mixins(ComponentWidthMixin) {
|
|
96
96
|
}
|
97
97
|
}
|
98
98
|
</script>
|
99
|
+
|
100
|
+
|
101
|
+
<style lang="scss" scoped>
|
102
|
+
.v-text-field :deep(.v-input__icon--clear) { // always show clear icon, https://github.com/vuetifyjs/vuetify/pull/15876
|
103
|
+
opacity: 1;
|
104
|
+
}
|
105
|
+
</style>
|
@@ -3,7 +3,7 @@
|
|
3
3
|
ref="input"
|
4
4
|
:rules="validationRules"
|
5
5
|
:counter="counter"
|
6
|
-
v-bind="
|
6
|
+
v-bind="{...$attrs, dense, outlined}"
|
7
7
|
v-on="$listeners"
|
8
8
|
/>
|
9
9
|
</template>
|
@@ -13,7 +13,7 @@
|
|
13
13
|
import { Component, Vue } from '@a-vue'
|
14
14
|
|
15
15
|
@Component({
|
16
|
-
props: ['validator']
|
16
|
+
props: ['validator', {dense: true, outlined: true}]
|
17
17
|
})
|
18
18
|
export default class ATextArea extends Vue {
|
19
19
|
mounted () {
|
@@ -1,45 +1,142 @@
|
|
1
1
|
<template>
|
2
2
|
<v-text-field
|
3
3
|
ref="input"
|
4
|
-
|
5
|
-
:autocomplete="autocomplete"
|
6
|
-
:rules="validationRules"
|
4
|
+
v-model="internalValue"
|
7
5
|
:counter="counter"
|
8
6
|
:style="cwm_widthStyle"
|
9
|
-
|
10
|
-
v-
|
11
|
-
@
|
7
|
+
:error-messages="errorMessages"
|
8
|
+
v-bind="attrs"
|
9
|
+
@input="inputChanged"
|
10
|
+
@keyup.esc="clear"
|
11
|
+
@click:clear="clear"
|
12
|
+
v-on="listeners"
|
12
13
|
/>
|
13
14
|
</template>
|
14
15
|
|
15
16
|
|
16
17
|
<script>
|
17
|
-
import { Component, Watch, Mixins } from '@a-vue'
|
18
|
+
import { Component, Watch, Mixins, Inject } from '@a-vue'
|
18
19
|
import { debounce } from '@a-vue/utils/debounce'
|
19
20
|
import { ComponentWidthMixin } from './mixins/ComponentWidthMixin'
|
20
21
|
|
21
22
|
@Component({
|
22
|
-
props: ['debounce', 'validator', {
|
23
|
+
props: ['value', 'debounce', 'validator', 'rules', {dense: true, outlined: true, focus: false, number: false}]
|
23
24
|
})
|
24
25
|
export default class ATextField extends Mixins(ComponentWidthMixin) {
|
25
26
|
$hasOptions = ['counter']
|
26
27
|
|
27
|
-
|
28
|
+
@Inject({ from: 'form', default: null }) form
|
29
|
+
|
30
|
+
internalValue = null
|
31
|
+
errorMessages = []
|
32
|
+
debounceInputFunction = null
|
28
33
|
|
29
34
|
created () {
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
}, this.debounce, value => value)
|
34
|
-
}
|
35
|
+
this.form && this.form.register(this)
|
36
|
+
|
37
|
+
this.setInternalValue(this.value)
|
35
38
|
}
|
36
39
|
|
37
40
|
mounted () {
|
38
41
|
this.setFocus()
|
39
42
|
|
40
|
-
|
41
|
-
|
43
|
+
this.$emit('input:internal', this.internalValue)
|
44
|
+
this.validate()
|
45
|
+
}
|
46
|
+
|
47
|
+
setInternalValue (value) {
|
48
|
+
if (typeof value === 'number') {
|
49
|
+
value = value.toString()
|
42
50
|
}
|
51
|
+
this.internalValue = value || ''
|
52
|
+
}
|
53
|
+
|
54
|
+
@Watch('value')
|
55
|
+
valueChanged () {
|
56
|
+
this.setInternalValue(this.value)
|
57
|
+
}
|
58
|
+
|
59
|
+
get listeners () {
|
60
|
+
// remove input from nested listening
|
61
|
+
// let clients listend to only THIS component
|
62
|
+
const listeners = {...this.$listeners}
|
63
|
+
delete listeners.input
|
64
|
+
return listeners
|
65
|
+
}
|
66
|
+
|
67
|
+
get attrs () {
|
68
|
+
// remove 'rules' from being passed to v-text-field
|
69
|
+
const attrs = {...this.$attrs}
|
70
|
+
delete attrs.rules
|
71
|
+
|
72
|
+
attrs.dense = this.dense
|
73
|
+
attrs.outlined = this.outlined
|
74
|
+
return attrs
|
75
|
+
}
|
76
|
+
|
77
|
+
clear () {
|
78
|
+
if (this.$attrs.clearable || this.escClearable) {
|
79
|
+
this.setInternalValue('')
|
80
|
+
this.validate()
|
81
|
+
this.$emit('input', this.emptyValue)
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
inputChanged () {
|
86
|
+
this.$emit('input:internal', this.internalValue)
|
87
|
+
|
88
|
+
const valid = this.validate()
|
89
|
+
if (!valid) {
|
90
|
+
return
|
91
|
+
}
|
92
|
+
|
93
|
+
const value = this.stringToNumber(this.internalValue)
|
94
|
+
|
95
|
+
if (this.debounce) {
|
96
|
+
if (!this.debounceInputFunction) {
|
97
|
+
this.debounceInputFunction = debounce(value => {
|
98
|
+
this.$emit('input', value)
|
99
|
+
}, this.debounce, value => value) // fire immediately if !value (click clearable-x)
|
100
|
+
}
|
101
|
+
this.debounceInputFunction(value)
|
102
|
+
} else {
|
103
|
+
this.$emit('input', value)
|
104
|
+
}
|
105
|
+
}
|
106
|
+
|
107
|
+
stringToNumber (value) {
|
108
|
+
if (this.treatAsNumericValue) {
|
109
|
+
if (!value) {
|
110
|
+
value = null
|
111
|
+
} else {
|
112
|
+
value = this.internalValue.match(/^\d*(.\d+)?$/) ? parseFloat(this.internalValue) : NaN
|
113
|
+
}
|
114
|
+
}
|
115
|
+
return value
|
116
|
+
}
|
117
|
+
|
118
|
+
get type () {
|
119
|
+
return this.$attrs.type || 'text'
|
120
|
+
}
|
121
|
+
|
122
|
+
get treatAsNumericValue () {
|
123
|
+
return this.type === 'number' || this.number
|
124
|
+
}
|
125
|
+
|
126
|
+
validate () {
|
127
|
+
const rules = this.validationRules
|
128
|
+
let errorMessage = null
|
129
|
+
for (const rule of rules) {
|
130
|
+
const value = this.stringToNumber(this.internalValue)
|
131
|
+
const result = rule(value)
|
132
|
+
if (result !== true) {
|
133
|
+
errorMessage = result
|
134
|
+
break
|
135
|
+
}
|
136
|
+
}
|
137
|
+
|
138
|
+
this.errorMessages = [errorMessage].filter(e => e)
|
139
|
+
return !this.errorMessages.length
|
43
140
|
}
|
44
141
|
|
45
142
|
@Watch('focus')
|
@@ -58,49 +155,42 @@ export default class ATextField extends Mixins(ComponentWidthMixin) {
|
|
58
155
|
}
|
59
156
|
}
|
60
157
|
|
61
|
-
get type () {
|
62
|
-
if (this.password && !this.showPassword) {
|
63
|
-
return 'password'
|
64
|
-
}
|
65
|
-
return 'text'
|
66
|
-
}
|
67
|
-
|
68
|
-
get appendIcon () {
|
69
|
-
if (this.password) {
|
70
|
-
return this.showPassword ? '$eyeIcon' : '$eyeOffIcon'
|
71
|
-
}
|
72
|
-
return null
|
73
|
-
}
|
74
|
-
|
75
|
-
get autocomplete () {
|
76
|
-
if (this.password) {
|
77
|
-
return 'new-password'
|
78
|
-
}
|
79
|
-
return null
|
80
|
-
}
|
81
|
-
|
82
158
|
get validationRules () {
|
159
|
+
if (this.$attrs.rules) {
|
160
|
+
return this.$attrs.rules
|
161
|
+
}
|
83
162
|
const label = this.$attrs.label
|
84
163
|
return (this.validator && this.validator.getRules(label)) || []
|
85
164
|
}
|
86
165
|
|
87
166
|
get counter () {
|
88
167
|
if (!this.$has.counter) {
|
89
|
-
return
|
168
|
+
return null
|
90
169
|
}
|
91
170
|
|
92
171
|
if (!this.validator) {
|
93
|
-
return
|
172
|
+
return null
|
94
173
|
}
|
95
174
|
|
96
|
-
return
|
175
|
+
return this.validator.getMaxValueLength()
|
176
|
+
}
|
177
|
+
|
178
|
+
get emptyValue () {
|
179
|
+
if (this.validator) {
|
180
|
+
return this.validator.getEmptyValue()
|
181
|
+
}
|
182
|
+
return null
|
97
183
|
}
|
98
184
|
}
|
99
185
|
</script>
|
100
186
|
|
101
187
|
|
102
188
|
<style lang="scss" scoped>
|
103
|
-
.v-input:not(.v-input--is-focused) :deep(.v-counter) {
|
189
|
+
.v-input:not(.v-input--is-focused) :deep(.v-counter) { // hide counter when not focused
|
104
190
|
display: none;
|
105
191
|
}
|
192
|
+
|
193
|
+
.v-text-field :deep(.v-input__icon--clear) { // always show clear icon, https://github.com/vuetifyjs/vuetify/pull/15876
|
194
|
+
opacity: 1;
|
195
|
+
}
|
106
196
|
</style>
|
@@ -1,12 +1,10 @@
|
|
1
1
|
<template>
|
2
2
|
<a-text-field
|
3
|
-
|
3
|
+
v-model="model[name]"
|
4
4
|
:label="label || name"
|
5
5
|
:validator="validator"
|
6
6
|
v-bind="$attrs"
|
7
7
|
v-on="$listeners"
|
8
|
-
@input="textFieldValueChanged"
|
9
|
-
@blur="onBlur"
|
10
8
|
/>
|
11
9
|
</template>
|
12
10
|
|
@@ -14,71 +12,7 @@
|
|
14
12
|
import { Component, Mixins } from '@a-vue'
|
15
13
|
import { FormFieldMixin } from '../FormFieldMixin'
|
16
14
|
|
17
|
-
@Component
|
18
|
-
props: [{emptyNull: false}]
|
19
|
-
})
|
15
|
+
@Component
|
20
16
|
export default class FormFieldText extends Mixins(FormFieldMixin) {
|
21
|
-
internalValue = ''
|
22
|
-
|
23
|
-
created () {
|
24
|
-
this.setInternalValue(this.model[this.name])
|
25
|
-
this.$watch(() => this.model[this.name], value => {
|
26
|
-
this.setInternalValue(value)
|
27
|
-
})
|
28
|
-
}
|
29
|
-
|
30
|
-
onBlur () {
|
31
|
-
this.setInternalValue(this.model[this.name], true)
|
32
|
-
}
|
33
|
-
|
34
|
-
textFieldValueChanged (value) {
|
35
|
-
this.internalValue = value
|
36
|
-
|
37
|
-
// cast to number
|
38
|
-
if (this.isNumber) {
|
39
|
-
value = Number(value)
|
40
|
-
if (isNaN(value)) {
|
41
|
-
return // do not set anything to the model
|
42
|
-
}
|
43
|
-
}
|
44
|
-
|
45
|
-
// set model value to null if empty
|
46
|
-
if (this.emptyNull) {
|
47
|
-
if (this.isNumber) {
|
48
|
-
if (value === 0) {
|
49
|
-
value = null
|
50
|
-
}
|
51
|
-
} else {
|
52
|
-
if (!value) {
|
53
|
-
value = null
|
54
|
-
}
|
55
|
-
}
|
56
|
-
}
|
57
|
-
|
58
|
-
this.model[this.name] = value
|
59
|
-
this.$emit('input', value)
|
60
|
-
}
|
61
|
-
|
62
|
-
setInternalValue (value, reset = false) {
|
63
|
-
if (this.isNumber) {
|
64
|
-
// reset text field if value is null but keep leading 0 (allows for copy and paste)
|
65
|
-
if (value === null) {
|
66
|
-
if (!reset && this.internalValue === '0') {
|
67
|
-
value = '0'
|
68
|
-
} else {
|
69
|
-
value = ''
|
70
|
-
}
|
71
|
-
}
|
72
|
-
} else { // null string should be ''
|
73
|
-
if (!value) {
|
74
|
-
value = ''
|
75
|
-
}
|
76
|
-
}
|
77
|
-
this.internalValue = value
|
78
|
-
}
|
79
|
-
|
80
|
-
get isNumber () {
|
81
|
-
return this.$attrs.number === ''
|
82
|
-
}
|
83
17
|
}
|
84
18
|
</script>
|
package/src/components/index.js
CHANGED
@@ -15,7 +15,6 @@ import NestedEditForm from './form/NestedEditForm'
|
|
15
15
|
import ListFilterPage from './list/filters/ListFilterPage'
|
16
16
|
import ListFilterSearch from './list/filters/ListFilterSearch'
|
17
17
|
import ListFilterSelect from './list/filters/ListFilterSelect'
|
18
|
-
import ListFilterRow from './list/ListFilterRow'
|
19
18
|
|
20
19
|
Vue.component('EditForm', EditForm)
|
21
20
|
Vue.component('NestedEditForm', NestedEditForm)
|
@@ -31,5 +30,4 @@ Vue.component('FormFieldSelect', FormFieldSelect)
|
|
31
30
|
Vue.component('FormFieldSelect2', FormFieldSelect2)
|
32
31
|
Vue.component('ListFilterPage', ListFilterPage)
|
33
32
|
Vue.component('ListFilterSearch', ListFilterSearch)
|
34
|
-
Vue.component('ListFilterRow', ListFilterRow)
|
35
33
|
Vue.component('ListFilterSelect', ListFilterSelect)
|
@@ -1,7 +1,5 @@
|
|
1
1
|
<template>
|
2
|
-
<a-row
|
3
|
-
gap="8"
|
4
|
-
>
|
2
|
+
<a-row gap="8">
|
5
3
|
<a-pagination
|
6
4
|
v-if="count && numPages > 1"
|
7
5
|
v-model="filter.value"
|
@@ -20,6 +18,7 @@
|
|
20
18
|
:items="pageSizeFilter.options"
|
21
19
|
:defaultValue="pageSizeFilter.defaultValue"
|
22
20
|
:clearable="!pageSizeFilter.hasDefaultValueSet()"
|
21
|
+
hide-details
|
23
22
|
/>
|
24
23
|
</a-row>
|
25
24
|
</template>
|
@@ -54,7 +53,7 @@ export default class ListFilterPage extends Mixins(ListFilterMixin) {
|
|
54
53
|
|
55
54
|
<style lang="scss" scoped>
|
56
55
|
.v-select {
|
57
|
-
max-width:
|
56
|
+
max-width: 150px;
|
58
57
|
}
|
59
58
|
|
60
59
|
.pageNumber {
|
package/src/index.js
CHANGED
package/src-admin/bootstrap.js
CHANGED
@@ -76,7 +76,7 @@
|
|
76
76
|
</template>
|
77
77
|
|
78
78
|
<template #filters>
|
79
|
-
<
|
79
|
+
<a-row gap="4">
|
80
80
|
<list-filter-search
|
81
81
|
:focus="true"
|
82
82
|
maxWidth="100%"
|
@@ -87,7 +87,7 @@
|
|
87
87
|
:has="{page_size: false, page_number: true}"
|
88
88
|
:totalVisible="0"
|
89
89
|
/>
|
90
|
-
</
|
90
|
+
</a-row>
|
91
91
|
</template>
|
92
92
|
|
93
93
|
<template #row="{ model, on }">
|
@@ -1,26 +0,0 @@
|
|
1
|
-
<template>
|
2
|
-
<a-row
|
3
|
-
:gap="gap || 4"
|
4
|
-
class="mb-0"
|
5
|
-
>
|
6
|
-
<slot />
|
7
|
-
</a-row>
|
8
|
-
</template>
|
9
|
-
|
10
|
-
|
11
|
-
<script>
|
12
|
-
import { Component, Vue } from '@a-vue'
|
13
|
-
|
14
|
-
@Component({
|
15
|
-
props: ['gap']
|
16
|
-
})
|
17
|
-
export default class ListFilterRow extends Vue {
|
18
|
-
}
|
19
|
-
</script>
|
20
|
-
|
21
|
-
|
22
|
-
<style scoped lang="scss">
|
23
|
-
:deep(.v-text-field__details) {
|
24
|
-
display: none;
|
25
|
-
}
|
26
|
-
</style>
|