@bildvitta/quasar-ui-asteroid 3.0.0-beta.9 → 3.0.0
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.
- package/dist/api/QasAppBar.json +0 -4
- package/dist/api/QasBtn.json +2 -1
- package/dist/api/QasCard.json +13 -9
- package/dist/api/QasDateTimeInput.json +12 -12
- package/dist/api/QasDialog.json +6 -2
- package/dist/api/QasFilters.json +4 -4
- package/dist/api/QasFormGenerator.json +33 -2
- package/dist/api/QasFormView.json +26 -9
- package/dist/api/QasGridGenerator.json +5 -4
- package/dist/api/QasInput.json +1 -1
- package/dist/api/QasListItems.json +18 -17
- package/dist/api/QasListView.json +21 -7
- package/dist/api/QasNestedFields.json +13 -3
- package/dist/api/QasNumericInput.json +10 -10
- package/dist/api/QasPasswordInput.json +1 -1
- package/dist/api/QasSearchBox.json +80 -1
- package/dist/api/QasSelect.json +79 -6
- package/dist/api/QasSelectList.json +16 -14
- package/dist/api/QasSignaturePad.json +1 -1
- package/dist/api/QasSingleView.json +13 -4
- package/dist/api/QasTabsGenerator.json +5 -2
- package/dist/api/QasUploader.json +5 -0
- package/dist/asteroid.cjs.css +1 -1
- package/dist/asteroid.cjs.js +1463 -663
- package/dist/asteroid.cjs.min.js +2 -2
- package/dist/asteroid.esm.css +1 -1
- package/dist/asteroid.esm.js +1466 -666
- package/dist/asteroid.esm.min.js +2 -2
- package/dist/asteroid.umd.css +1 -1
- package/dist/asteroid.umd.js +1466 -667
- package/dist/asteroid.umd.min.js +2 -2
- package/dist/vetur/asteroid-attributes.json +162 -94
- package/dist/vetur/asteroid-tags.json +54 -37
- package/package.json +1 -1
- package/src/components/actions-menu/QasActionsMenu.vue +2 -8
- package/src/components/app-bar/QasAppBar.vue +16 -12
- package/src/components/app-bar/QasAppBar.yml +0 -4
- package/src/components/avatar/QasAvatar.vue +0 -4
- package/src/components/btn/QasBtn.vue +5 -8
- package/src/components/btn/QasBtn.yml +2 -1
- package/src/components/card/QasCard.vue +18 -9
- package/src/components/card/QasCard.yml +13 -9
- package/src/components/date-time-input/QasDateTimeInput.vue +39 -41
- package/src/components/date-time-input/QasDateTimeInput.yml +11 -12
- package/src/components/delete/QasDelete.vue +15 -1
- package/src/components/dialog/QasDialog.vue +26 -3
- package/src/components/dialog/QasDialog.yml +6 -3
- package/src/components/dialog-router/QasDialogRouter.vue +1 -1
- package/src/components/field/QasField.vue +15 -14
- package/src/components/filters/QasFilters.vue +27 -10
- package/src/components/filters/QasFilters.yml +4 -4
- package/src/components/form-generator/QasFormGenerator.vue +87 -12
- package/src/components/form-generator/QasFormGenerator.yml +16 -2
- package/src/components/form-view/QasFormView.vue +99 -39
- package/src/components/form-view/QasFormView.yml +22 -9
- package/src/components/grid-generator/QasGridGenerator.vue +23 -7
- package/src/components/grid-generator/QasGridGenerator.yml +5 -4
- package/src/components/input/QasInput.vue +37 -21
- package/src/components/input/QasInput.yml +1 -1
- package/src/components/layout/QasLayout.vue +4 -0
- package/src/components/list-items/QasListItems.vue +15 -23
- package/src/components/list-items/QasListItems.yml +14 -15
- package/src/components/list-view/QasListView.vue +45 -24
- package/src/components/list-view/QasListView.yml +19 -7
- package/src/components/map/QasMap.vue +5 -5
- package/src/components/nested-fields/QasNestedFields.vue +29 -21
- package/src/components/nested-fields/QasNestedFields.yml +9 -3
- package/src/components/numeric-input/QasNumericInput.vue +14 -14
- package/src/components/numeric-input/QasNumericInput.yml +10 -10
- package/src/components/page-header/QasPageHeader.vue +14 -11
- package/src/components/password-input/QasPasswordInput.vue +17 -16
- package/src/components/password-input/QasPasswordInput.yml +1 -1
- package/src/components/profile/QasProfile.vue +1 -1
- package/src/components/search-box/QasSearchBox.vue +137 -36
- package/src/components/search-box/QasSearchBox.yml +66 -1
- package/src/components/select/QasSelect.vue +62 -46
- package/src/components/select/QasSelect.yml +63 -6
- package/src/components/select-list/QasSelectList.vue +11 -27
- package/src/components/select-list/QasSelectList.yml +13 -14
- package/src/components/signature-pad/QasSignaturePad.yml +1 -1
- package/src/components/signature-uploader/QasSignatureUploader.vue +7 -5
- package/src/components/single-view/QasSingleView.vue +22 -6
- package/src/components/single-view/QasSingleView.yml +11 -4
- package/src/components/table-generator/QasTableGenerator.vue +11 -1
- package/src/components/tabs-generator/QasTabsGenerator.vue +2 -2
- package/src/components/tabs-generator/QasTabsGenerator.yml +2 -2
- package/src/components/text-truncate/QasTextTruncate.vue +1 -1
- package/src/components/uploader/QasUploader.vue +62 -15
- package/src/components/uploader/QasUploader.yml +5 -0
- package/src/helpers/camelize-fields-name.js +15 -0
- package/src/helpers/filters.js +2 -0
- package/src/helpers/get-normalized-options.js +20 -0
- package/src/helpers/handle-process.js +13 -0
- package/src/helpers/index.js +3 -0
- package/src/mixins/generator.js +10 -2
- package/src/mixins/index.js +2 -0
- package/src/mixins/search-filter.js +227 -0
- package/src/mixins/view.js +32 -12
- package/src/plugins/index.js +4 -2
- package/src/plugins/logger/Logger.js +44 -0
- package/src/plugins/logger/Logger.yml +9 -0
- package/src/vue-plugin.js +6 -3
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
<
|
|
4
|
-
<
|
|
5
|
-
<q-
|
|
6
|
-
<q-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
<q-
|
|
12
|
-
<q-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
</qas-input>
|
|
18
|
-
</div>
|
|
2
|
+
<qas-input ref="input" v-bind="attributes" v-model="currentValue" :unmasked-value="false" @update:model-value="updateModelValue">
|
|
3
|
+
<template #append>
|
|
4
|
+
<q-icon v-if="!useTimeOnly" class="cursor-pointer" name="o_event">
|
|
5
|
+
<q-popup-proxy ref="dateProxy" transition-hide="scale" transition-show="scale">
|
|
6
|
+
<q-date v-model="currentValue" v-bind="dateProps" :mask="maskDate" @update:model-value="updateModelValue" />
|
|
7
|
+
</q-popup-proxy>
|
|
8
|
+
</q-icon>
|
|
9
|
+
|
|
10
|
+
<q-icon v-if="!useDateOnly" class="cursor-pointer q-ml-md" name="o_access_time">
|
|
11
|
+
<q-popup-proxy ref="timeProxy" transition-hide="scale" transition-show="scale">
|
|
12
|
+
<q-time v-model="currentValue" v-bind="timeProps" format24h :mask="maskDate" @update:model-value="updateModelValue" />
|
|
13
|
+
</q-popup-proxy>
|
|
14
|
+
</q-icon>
|
|
15
|
+
</template>
|
|
16
|
+
</qas-input>
|
|
19
17
|
</template>
|
|
20
18
|
|
|
21
19
|
<script>
|
|
@@ -33,33 +31,33 @@ export default {
|
|
|
33
31
|
type: String
|
|
34
32
|
},
|
|
35
33
|
|
|
36
|
-
dateOnly: {
|
|
37
|
-
type: Boolean
|
|
38
|
-
},
|
|
39
|
-
|
|
40
34
|
dateProps: {
|
|
41
35
|
default: () => ({}),
|
|
42
36
|
type: Object
|
|
43
37
|
},
|
|
44
38
|
|
|
45
|
-
gmt: {
|
|
46
|
-
type: Boolean
|
|
47
|
-
},
|
|
48
|
-
|
|
49
39
|
timeMask: {
|
|
50
40
|
default: 'HH:mm',
|
|
51
41
|
type: String
|
|
52
42
|
},
|
|
53
43
|
|
|
54
|
-
timeOnly: {
|
|
55
|
-
type: Boolean
|
|
56
|
-
},
|
|
57
|
-
|
|
58
44
|
timeProps: {
|
|
59
45
|
default: () => ({}),
|
|
60
46
|
type: Object
|
|
61
47
|
},
|
|
62
48
|
|
|
49
|
+
useIso: {
|
|
50
|
+
type: Boolean
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
useTimeOnly: {
|
|
54
|
+
type: Boolean
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
useDateOnly: {
|
|
58
|
+
type: Boolean
|
|
59
|
+
},
|
|
60
|
+
|
|
63
61
|
modelValue: {
|
|
64
62
|
default: '',
|
|
65
63
|
type: String
|
|
@@ -96,16 +94,16 @@ export default {
|
|
|
96
94
|
maskDate () {
|
|
97
95
|
const mask = []
|
|
98
96
|
|
|
99
|
-
if (!this.
|
|
100
|
-
if (!this.
|
|
97
|
+
if (!this.useTimeOnly) { mask.push(this.dateMask) }
|
|
98
|
+
if (!this.useDateOnly) { mask.push(this.timeMask) }
|
|
101
99
|
|
|
102
100
|
return mask.join(' ')
|
|
103
101
|
}
|
|
104
102
|
},
|
|
105
103
|
|
|
106
104
|
watch: {
|
|
107
|
-
|
|
108
|
-
if (!current || this.
|
|
105
|
+
modelValue (current, original) {
|
|
106
|
+
if (!current || this.useTimeOnly) {
|
|
109
107
|
this.currentValue = current
|
|
110
108
|
return
|
|
111
109
|
}
|
|
@@ -131,18 +129,18 @@ export default {
|
|
|
131
129
|
|
|
132
130
|
updateModelValue (value) {
|
|
133
131
|
this.currentValue = value
|
|
134
|
-
const valueLength = value
|
|
132
|
+
const valueLength = value?.replace?.(/_/g, '')?.length
|
|
135
133
|
|
|
136
134
|
if (value === '' || valueLength === this.mask.length) {
|
|
137
|
-
this.lastValue = this.
|
|
135
|
+
this.lastValue = this.useTimeOnly ? value : this.toISOString(value)
|
|
138
136
|
this.$emit('update:modelValue', this.lastValue)
|
|
139
137
|
}
|
|
140
138
|
|
|
141
|
-
if (this.
|
|
139
|
+
if (this.useDateOnly) {
|
|
142
140
|
this.$refs.dateProxy.hide()
|
|
143
141
|
}
|
|
144
142
|
|
|
145
|
-
if (this.
|
|
143
|
+
if (this.useTimeOnly) {
|
|
146
144
|
this.$refs.timeProxy.hide()
|
|
147
145
|
}
|
|
148
146
|
},
|
|
@@ -152,11 +150,11 @@ export default {
|
|
|
152
150
|
return ''
|
|
153
151
|
}
|
|
154
152
|
|
|
155
|
-
if (this.
|
|
153
|
+
if (this.useDateOnly && !this.useIso) {
|
|
156
154
|
return dateFn(date.extractDate(value, this.maskDate), 'yyyy-MM-dd')
|
|
157
155
|
}
|
|
158
156
|
|
|
159
|
-
if (this.
|
|
157
|
+
if (this.useTimeOnly && !this.useIso) {
|
|
160
158
|
return date.extractDate(value, 'HH:MM')
|
|
161
159
|
}
|
|
162
160
|
|
|
@@ -164,14 +162,14 @@ export default {
|
|
|
164
162
|
},
|
|
165
163
|
|
|
166
164
|
toMask (value) {
|
|
167
|
-
if (!value || this.
|
|
165
|
+
if (!value || this.useTimeOnly) {
|
|
168
166
|
return value || ''
|
|
169
167
|
}
|
|
170
168
|
|
|
171
169
|
const newDate = new Date(value).toISOString()
|
|
172
170
|
|
|
173
171
|
return date.formatDate(
|
|
174
|
-
this.
|
|
172
|
+
this.useDateOnly ? newDate.slice(0, 23) : newDate,
|
|
175
173
|
this.maskDate
|
|
176
174
|
)
|
|
177
175
|
}
|
|
@@ -12,19 +12,11 @@ props:
|
|
|
12
12
|
default: DD/MM/YYYY
|
|
13
13
|
type: String
|
|
14
14
|
|
|
15
|
-
date-only:
|
|
16
|
-
desc: Habilita o componente para usar somente data.
|
|
17
|
-
type: Boolean
|
|
18
|
-
|
|
19
15
|
date-props:
|
|
20
16
|
desc: Propriedades do QDate (https://quasar.dev/vue-components/date#introduction).
|
|
21
17
|
default: {}
|
|
22
18
|
type: Object
|
|
23
19
|
|
|
24
|
-
gmt:
|
|
25
|
-
desc: Utilizado para se usar junto da prop "date-only" ou "time-only", caso "gmt" for "true", o model sempre vai ser retornado no padrão ISO 8601, independente ser apenas um campo somente de data ou hora.
|
|
26
|
-
type: Boolean
|
|
27
|
-
|
|
28
20
|
model-value:
|
|
29
21
|
desc: Model do componente, usado para v-model.
|
|
30
22
|
default: ''
|
|
@@ -36,15 +28,22 @@ props:
|
|
|
36
28
|
default: HH:mm
|
|
37
29
|
type: String
|
|
38
30
|
|
|
39
|
-
time-only:
|
|
40
|
-
desc: Habilita o componente para usar somente hora.
|
|
41
|
-
type: Boolean
|
|
42
|
-
|
|
43
31
|
time-props:
|
|
44
32
|
desc: Propriedades do QTime (https://quasar.dev/vue-components/time#introduction).
|
|
45
33
|
default: {}
|
|
46
34
|
type: Object
|
|
47
35
|
|
|
36
|
+
use-time-only:
|
|
37
|
+
desc: Habilita o componente para usar somente hora.
|
|
38
|
+
type: Boolean
|
|
39
|
+
|
|
40
|
+
use-date-only:
|
|
41
|
+
desc: Habilita o componente para usar somente data.
|
|
42
|
+
type: Boolean
|
|
43
|
+
|
|
44
|
+
use-iso:
|
|
45
|
+
desc: Utilizado para se usar junto da prop "date-only" ou "time-only", caso "useIso" for "true", o model sempre vai ser retornado no padrão ISO 8601, independente ser apenas um campo somente de data ou hora.
|
|
46
|
+
type: Boolean
|
|
48
47
|
|
|
49
48
|
events:
|
|
50
49
|
'@update:model-value -> function (value)':
|
|
@@ -106,7 +106,13 @@ export default {
|
|
|
106
106
|
try {
|
|
107
107
|
const { destroyRoutes, history } = useHistory()
|
|
108
108
|
|
|
109
|
-
|
|
109
|
+
const payload = { id: this.id, url: this.url }
|
|
110
|
+
|
|
111
|
+
this.$qas.logger.group(
|
|
112
|
+
`QasDelete - destroy -> Payload do parâmetro do ${this.entity}/destroy`, [payload]
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
await this.$store.dispatch(`${this.entity}/destroy`, payload)
|
|
110
116
|
|
|
111
117
|
NotifySuccess('Item deletado com sucesso!')
|
|
112
118
|
|
|
@@ -120,9 +126,17 @@ export default {
|
|
|
120
126
|
this.createDeleteSuccessEvent()
|
|
121
127
|
|
|
122
128
|
this.$emit('success')
|
|
129
|
+
|
|
130
|
+
this.$qas.logger.info('QasDelete - destroy -> item deletado com sucesso!')
|
|
123
131
|
} catch (error) {
|
|
124
132
|
NotifyError('Ops! Não foi possível deletar o item.')
|
|
125
133
|
this.$emit('error', error)
|
|
134
|
+
|
|
135
|
+
this.$qas.logger.group(
|
|
136
|
+
`QasDelete - destroy -> exceção da action ${this.entity}/destroy`,
|
|
137
|
+
[error],
|
|
138
|
+
{ error: true }
|
|
139
|
+
)
|
|
126
140
|
} finally {
|
|
127
141
|
Loading.hide()
|
|
128
142
|
this.$emit('update:deleting', false)
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<slot name="header">
|
|
6
6
|
<div class="justify-between row">
|
|
7
7
|
<div class="text-bold text-h6">{{ card.title }}</div>
|
|
8
|
-
<qas-btn v-if="
|
|
8
|
+
<qas-btn v-if="useCloseButton" v-close-popup dense flat icon="o_close" rounded />
|
|
9
9
|
</div>
|
|
10
10
|
</slot>
|
|
11
11
|
</q-card-section>
|
|
@@ -100,7 +100,11 @@ export default {
|
|
|
100
100
|
type: Boolean
|
|
101
101
|
},
|
|
102
102
|
|
|
103
|
-
|
|
103
|
+
useCloseButton: {
|
|
104
|
+
type: Boolean
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
useValidationAllAtOnce: {
|
|
104
108
|
type: Boolean
|
|
105
109
|
}
|
|
106
110
|
},
|
|
@@ -148,7 +152,26 @@ export default {
|
|
|
148
152
|
|
|
149
153
|
methods: {
|
|
150
154
|
async submitHandler () {
|
|
151
|
-
|
|
155
|
+
if (!this.useForm) return
|
|
156
|
+
|
|
157
|
+
if (this.useValidationAllAtOnce) {
|
|
158
|
+
let isAllComponentValid = true
|
|
159
|
+
const components = this.$refs.form.getValidationComponents() || []
|
|
160
|
+
|
|
161
|
+
for (const component of components) {
|
|
162
|
+
const isValid = component?.validate?.()
|
|
163
|
+
|
|
164
|
+
if (!isValid) {
|
|
165
|
+
isAllComponentValid = false
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
this.$emit('validate', isAllComponentValid)
|
|
170
|
+
|
|
171
|
+
return
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
this.$emit('validate', await this.$refs.form.validate())
|
|
152
175
|
},
|
|
153
176
|
|
|
154
177
|
// método para funcionar como plugin
|
|
@@ -50,9 +50,9 @@ props:
|
|
|
50
50
|
persistent:
|
|
51
51
|
desc: Define se o dialog vai fechar ou não após clicar fora do dialog.
|
|
52
52
|
default: true
|
|
53
|
-
type:
|
|
53
|
+
type: Boolean
|
|
54
54
|
|
|
55
|
-
use-close-
|
|
55
|
+
use-close-button:
|
|
56
56
|
desc: Define se vai ter ou não Ícone de fechar o dialog.
|
|
57
57
|
type: Boolean
|
|
58
58
|
|
|
@@ -60,8 +60,11 @@ props:
|
|
|
60
60
|
desc: Define se a tag onde fica a descrição no dialog vai ser um "<q-form />" ou "<div />".
|
|
61
61
|
type: Boolean
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
use-validation-at-once:
|
|
64
|
+
desc: Valida todos os campos de uma única vez, ao invés de ser um por vez (que é o padrão).
|
|
65
|
+
type: Boolean
|
|
64
66
|
|
|
67
|
+
slots:
|
|
65
68
|
actions:
|
|
66
69
|
desc: Slot para ações (botões por exemplo).
|
|
67
70
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<q-dialog ref="dialog" persistent @hide="onDialogHide">
|
|
3
3
|
<q-card class="full-width" style="max-width: 80vw;">
|
|
4
4
|
<q-card-section>
|
|
5
|
-
<component :is="component" v-if="component"
|
|
5
|
+
<component :is="component" v-if="component" :route="route" :use-boundary="false" @hide="hide" />
|
|
6
6
|
</q-card-section>
|
|
7
7
|
</q-card>
|
|
8
8
|
</q-dialog>
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
<
|
|
4
|
-
<
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
</component>
|
|
8
|
-
</div>
|
|
2
|
+
<component :is="component.is" v-bind="component" :data-cy="field.name" :model-value="formattedValue" @update:model-value="updateModel">
|
|
3
|
+
<template v-for="(_, name) in $slots" #[name]="context">
|
|
4
|
+
<slot :name="name" v-bind="context || {}" />
|
|
5
|
+
</template>
|
|
6
|
+
</component>
|
|
9
7
|
</template>
|
|
10
8
|
|
|
11
9
|
<script>
|
|
@@ -36,6 +34,8 @@ export default {
|
|
|
36
34
|
QasSignatureUploader
|
|
37
35
|
},
|
|
38
36
|
|
|
37
|
+
inheritAttrs: false,
|
|
38
|
+
|
|
39
39
|
props: {
|
|
40
40
|
error: {
|
|
41
41
|
default: '',
|
|
@@ -75,8 +75,9 @@ export default {
|
|
|
75
75
|
type,
|
|
76
76
|
mask,
|
|
77
77
|
maxFiles,
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
useIso,
|
|
79
|
+
useSearch,
|
|
80
|
+
useLazyLoading
|
|
80
81
|
} = this.formattedField
|
|
81
82
|
|
|
82
83
|
// Default error attributes for Quasar.
|
|
@@ -98,11 +99,11 @@ export default {
|
|
|
98
99
|
minlength,
|
|
99
100
|
suffix,
|
|
100
101
|
prefix,
|
|
101
|
-
|
|
102
|
+
useIso
|
|
102
103
|
}
|
|
103
104
|
|
|
104
105
|
const numericInput = { is: 'qas-numeric-input', ...input }
|
|
105
|
-
const datetimeInput = { is: 'qas-date-time-input',
|
|
106
|
+
const datetimeInput = { is: 'qas-date-time-input', useIso, ...input }
|
|
106
107
|
|
|
107
108
|
// It'll generate a list of acceptable files extensions.
|
|
108
109
|
const accept = extensions && extensions.length ? extensions.map(extension => `.${extension}`).join(',') : ''
|
|
@@ -130,9 +131,9 @@ export default {
|
|
|
130
131
|
money: { ...numericInput, mode: 'money' },
|
|
131
132
|
percent: { ...numericInput, mode: 'percent' },
|
|
132
133
|
|
|
133
|
-
date: { ...datetimeInput,
|
|
134
|
+
date: { ...datetimeInput, useDateOnly: true },
|
|
134
135
|
datetime: { ...datetimeInput },
|
|
135
|
-
time: { ...datetimeInput,
|
|
136
|
+
time: { ...datetimeInput, useTimeOnly: true },
|
|
136
137
|
|
|
137
138
|
boolean: { is: 'q-toggle', label, ...error },
|
|
138
139
|
checkbox: { is: 'qas-checkbox-group', label, options, ...error },
|
|
@@ -143,7 +144,7 @@ export default {
|
|
|
143
144
|
|
|
144
145
|
'signature-uploader': { is: 'qas-signature-uploader', entity, uploadLabel: label, ...error },
|
|
145
146
|
|
|
146
|
-
select: { is: 'qas-select', multiple, options,
|
|
147
|
+
select: { is: 'qas-select', entity, name, multiple, options, useSearch, useLazyLoading, ...input }
|
|
147
148
|
}
|
|
148
149
|
|
|
149
150
|
return { ...(profiles[type] || profiles.default), ...this.$attrs }
|
|
@@ -4,18 +4,18 @@
|
|
|
4
4
|
<div v-if="showSearch" class="col">
|
|
5
5
|
<slot :filter="filter" name="search">
|
|
6
6
|
<q-form v-if="useSearch" @submit.prevent="filter()">
|
|
7
|
-
<
|
|
7
|
+
<qas-input v-model="search" :debounce="debounce" dense hide-bottom-space :outlined="false" :placeholder="searchPlaceholder" type="search">
|
|
8
8
|
<template #append>
|
|
9
|
-
<
|
|
10
|
-
<
|
|
9
|
+
<qas-btn v-if="hasSearch" color="grey-9" flat icon="o_clear" unelevated @click="clearSearch" />
|
|
10
|
+
<qas-btn v-if="!debounce" color="grey-9" flat icon="o_search" type="submit" unelevated @click="filter()" />
|
|
11
11
|
</template>
|
|
12
|
-
</
|
|
12
|
+
</qas-input>
|
|
13
13
|
</q-form>
|
|
14
14
|
</slot>
|
|
15
15
|
</div>
|
|
16
16
|
|
|
17
17
|
<slot v-if="showFilterButton" :filter="filter" name="filter-button">
|
|
18
|
-
<
|
|
18
|
+
<qas-btn v-if="useFilterButton" :color="filterButtonColor" flat icon="o_filter_list" :label="filterButtonLabel">
|
|
19
19
|
<q-menu class="full-width" max-width="240px">
|
|
20
20
|
<div v-if="isFetching" class="q-pa-xl text-center">
|
|
21
21
|
<q-spinner color="grey" size="2em" />
|
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
</div>
|
|
32
32
|
|
|
33
33
|
<div class="text-right">
|
|
34
|
-
<
|
|
35
|
-
<
|
|
34
|
+
<qas-btn class="q-mr-sm" flat label="Limpar" :no-caps="false" size="12px" unelevated @click="clearFilters" />
|
|
35
|
+
<qas-btn color="primary" label="Filtrar" :no-caps="false" size="12px" type="submit" unelevated />
|
|
36
36
|
</div>
|
|
37
37
|
</q-form>
|
|
38
38
|
</q-menu>
|
|
39
|
-
</
|
|
39
|
+
</qas-btn>
|
|
40
40
|
</slot>
|
|
41
41
|
</div>
|
|
42
42
|
|
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
|
|
51
51
|
<script>
|
|
52
52
|
import QasField from '../field/QasField.vue'
|
|
53
|
+
import QasBtn from '../btn/QasBtn.vue'
|
|
53
54
|
|
|
54
55
|
import { camelize, camelizeKeys } from 'humps'
|
|
55
56
|
import { humanize, parseValue } from '../../helpers/filters.js'
|
|
@@ -59,6 +60,7 @@ export default {
|
|
|
59
60
|
name: 'QasFilters',
|
|
60
61
|
|
|
61
62
|
components: {
|
|
63
|
+
QasBtn,
|
|
62
64
|
QasField
|
|
63
65
|
},
|
|
64
66
|
|
|
@@ -100,7 +102,7 @@ export default {
|
|
|
100
102
|
type: String
|
|
101
103
|
},
|
|
102
104
|
|
|
103
|
-
|
|
105
|
+
useForceRefetch: {
|
|
104
106
|
type: Boolean
|
|
105
107
|
}
|
|
106
108
|
},
|
|
@@ -231,7 +233,7 @@ export default {
|
|
|
231
233
|
},
|
|
232
234
|
|
|
233
235
|
async fetchFilters () {
|
|
234
|
-
if (!this.
|
|
236
|
+
if (!this.useForceRefetch && (this.hasFields || !this.useFilterButton)) {
|
|
235
237
|
return null
|
|
236
238
|
}
|
|
237
239
|
|
|
@@ -239,11 +241,26 @@ export default {
|
|
|
239
241
|
this.isFetching = true
|
|
240
242
|
|
|
241
243
|
try {
|
|
244
|
+
this.$qas.logger.group(
|
|
245
|
+
`QasFilters - fetchFilters -> Payload do parâmetro do ${this.entity}/fetchFilters`,
|
|
246
|
+
[{ url: this.url }]
|
|
247
|
+
)
|
|
248
|
+
|
|
242
249
|
const response = await this.$store.dispatch(`${this.entity}/fetchFilters`, { url: this.url })
|
|
243
250
|
this.$emit('fetch-success', response)
|
|
251
|
+
|
|
252
|
+
this.$qas.logger.group(
|
|
253
|
+
`QasFilters - fetchFilters -> resposta da action ${this.entity}/fetchFilters`, [response]
|
|
254
|
+
)
|
|
244
255
|
} catch (error) {
|
|
245
256
|
this.hasFetchError = true
|
|
246
257
|
this.$emit('fetch-error', error)
|
|
258
|
+
|
|
259
|
+
this.$qas.logger.group(
|
|
260
|
+
`QasFilters - fetchFilters -> exceção da action ${this.entity}/fetchFilters`,
|
|
261
|
+
[error],
|
|
262
|
+
{ error: true }
|
|
263
|
+
)
|
|
247
264
|
} finally {
|
|
248
265
|
this.isFetching = false
|
|
249
266
|
}
|
|
@@ -9,10 +9,6 @@ props:
|
|
|
9
9
|
required: true
|
|
10
10
|
type: String
|
|
11
11
|
|
|
12
|
-
force-refetch:
|
|
13
|
-
desc: Força refazer o "fetch" mesmo caso já exista dados na store de filters.
|
|
14
|
-
type: Boolean
|
|
15
|
-
|
|
16
12
|
search-placeholder:
|
|
17
13
|
desc: Placeholder do campo de busca.
|
|
18
14
|
default: Pesquisar...
|
|
@@ -32,6 +28,10 @@ props:
|
|
|
32
28
|
default: true
|
|
33
29
|
type: Boolean
|
|
34
30
|
|
|
31
|
+
use-force-refetch:
|
|
32
|
+
desc: Força refazer o "fetch" mesmo caso já exista dados na store de filters.
|
|
33
|
+
type: Boolean
|
|
34
|
+
|
|
35
35
|
use-search-on-type:
|
|
36
36
|
desc: Habilita ou não o filtro de busca sempre que o usuário digita.
|
|
37
37
|
default: true
|
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div>
|
|
3
|
-
<div :class="
|
|
4
|
-
<
|
|
5
|
-
<
|
|
6
|
-
<qas-field v-bind="fieldsProps[field.name]" :error="errors[key]" :field="field" :model-value="modelValue[field.name]" @update:model-value="updateModelValue(field.name, $event)" />
|
|
7
|
-
</slot>
|
|
8
|
-
</div>
|
|
9
|
-
</div>
|
|
10
|
-
|
|
11
|
-
<div v-for="(field, key) in groupedFields.hidden" :key="key">
|
|
12
|
-
<slot :field="field" :name="`field-${field.name}`">
|
|
13
|
-
<qas-field v-bind="fieldsProps[field.name]" :field="field" :model-value="modelValue[field.name]" @update:model-value="updateModelValue(field.name, $event)" />
|
|
2
|
+
<div :class="fieldsetClasses">
|
|
3
|
+
<div v-for="(fieldsetItem, fieldsetItemKey) in normalizedFields" :key="fieldsetItemKey" class="full-width">
|
|
4
|
+
<slot v-if="fieldsetItem.label" :name="`legend-${fieldsetItemKey}`">
|
|
5
|
+
<qas-label :label="fieldsetItem.label" />
|
|
14
6
|
</slot>
|
|
7
|
+
|
|
8
|
+
<div>
|
|
9
|
+
<div :class="mx_classes">
|
|
10
|
+
<div v-for="(field, key) in fieldsetItem.fields.visible" :key="key" :class="mx_getFieldClass(key)">
|
|
11
|
+
<slot :field="field" :name="`field-${field.name}`">
|
|
12
|
+
<qas-field v-bind="fieldsProps[field.name]" :error="errors[key]" :field="field" :model-value="modelValue[field.name]" @update:model-value="updateModelValue(field.name, $event)" />
|
|
13
|
+
</slot>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<div v-for="(field, key) in fieldsetItem.fields.hidden" :key="key">
|
|
18
|
+
<slot :field="field" :name="`field-${field.name}`">
|
|
19
|
+
<qas-field v-bind="fieldsProps[field.name]" :field="field" :model-value="modelValue[field.name]" @update:model-value="updateModelValue(field.name, $event)" />
|
|
20
|
+
</slot>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
15
23
|
</div>
|
|
16
24
|
</div>
|
|
17
25
|
</template>
|
|
@@ -49,6 +57,19 @@ export default {
|
|
|
49
57
|
default: () => ({}),
|
|
50
58
|
required: true,
|
|
51
59
|
type: Object
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
fieldset: {
|
|
63
|
+
default: () => ({}),
|
|
64
|
+
type: Object
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
fieldsetGutter: {
|
|
68
|
+
default: 'lg',
|
|
69
|
+
type: [String, Boolean],
|
|
70
|
+
validator: value => {
|
|
71
|
+
return typeof value === 'boolean' || ['xs', 'sm', 'md', 'lg', 'xl'].includes(value)
|
|
72
|
+
}
|
|
52
73
|
}
|
|
53
74
|
},
|
|
54
75
|
|
|
@@ -58,6 +79,8 @@ export default {
|
|
|
58
79
|
groupedFields () {
|
|
59
80
|
const fields = { hidden: {}, visible: {} }
|
|
60
81
|
|
|
82
|
+
if (this.hasFieldset) return fields
|
|
83
|
+
|
|
61
84
|
for (const key in this.fields) {
|
|
62
85
|
const field = this.fields[key]
|
|
63
86
|
fields[field.type === 'hidden' ? 'hidden' : 'visible'][key] = field
|
|
@@ -74,6 +97,58 @@ export default {
|
|
|
74
97
|
}
|
|
75
98
|
|
|
76
99
|
return fields
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
normalizedFields () {
|
|
103
|
+
if (!this.hasFieldset) {
|
|
104
|
+
return {
|
|
105
|
+
default: {
|
|
106
|
+
fields: this.groupedFields
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const fields = {}
|
|
112
|
+
|
|
113
|
+
for (const fieldsetKey in this.fieldset) {
|
|
114
|
+
const fieldsetItem = this.fieldset[fieldsetKey]
|
|
115
|
+
|
|
116
|
+
fields[fieldsetKey] = {
|
|
117
|
+
label: fieldsetItem.label,
|
|
118
|
+
fields: { hidden: {}, visible: {} }
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
for (const fieldName of fieldsetItem.fields) {
|
|
122
|
+
const field = this.fields[fieldName]
|
|
123
|
+
|
|
124
|
+
if (!field) continue
|
|
125
|
+
|
|
126
|
+
Object.assign(
|
|
127
|
+
fields[fieldsetKey].fields[
|
|
128
|
+
field.type === 'hidden' ? 'hidden' : 'visible'
|
|
129
|
+
],
|
|
130
|
+
{
|
|
131
|
+
[fieldName]: field
|
|
132
|
+
}
|
|
133
|
+
)
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return fields
|
|
138
|
+
},
|
|
139
|
+
|
|
140
|
+
hasFieldset () {
|
|
141
|
+
return !!Object.keys(this.fieldset).length
|
|
142
|
+
},
|
|
143
|
+
|
|
144
|
+
fieldsetClasses () {
|
|
145
|
+
const classes = ['row']
|
|
146
|
+
|
|
147
|
+
if (this.fieldsetGutter) {
|
|
148
|
+
classes.push(`q-col-gutter-y-${this.fieldsetGutter}`)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return classes
|
|
77
152
|
}
|
|
78
153
|
},
|
|
79
154
|
|
|
@@ -27,11 +27,23 @@ props:
|
|
|
27
27
|
type: Object
|
|
28
28
|
examples: ["{ email: { name: 'email', type: 'email', label: 'E-mail' } }"]
|
|
29
29
|
|
|
30
|
+
fieldset:
|
|
31
|
+
desc: Lista para agrupar elementos por rótulo (label).
|
|
32
|
+
default: {}
|
|
33
|
+
type: Object
|
|
34
|
+
examples: ["{ personalInformation: { label: 'Informações pessoais', fields: [name, email] } }"]
|
|
35
|
+
|
|
36
|
+
fieldset-gutter:
|
|
37
|
+
desc: Espaçamento entre rótulos (label).
|
|
38
|
+
default: lg
|
|
39
|
+
type: [String, Boolean]
|
|
40
|
+
examples: [xs, sm, md, lg, xl, false]
|
|
41
|
+
|
|
30
42
|
gutter:
|
|
31
43
|
desc: Espaçamento entre colunas.
|
|
32
44
|
default: md
|
|
33
|
-
type: String
|
|
34
|
-
examples: [xs, sm, md, lg, xl]
|
|
45
|
+
type: [String, Boolean]
|
|
46
|
+
examples: [xs, sm, md, lg, xl, false]
|
|
35
47
|
|
|
36
48
|
model-value:
|
|
37
49
|
desc: Model do componente, usado para o v-model.
|
|
@@ -54,6 +66,8 @@ slots:
|
|
|
54
66
|
desc: Payload do campo atual.
|
|
55
67
|
default: {}
|
|
56
68
|
type: Object
|
|
69
|
+
'legend-[nome-da-chave]':
|
|
70
|
+
desc: Acessa o slot de um rótulo (label).
|
|
57
71
|
|
|
58
72
|
events:
|
|
59
73
|
'@update:model-value -> function(value)':
|