@bildvitta/quasar-ui-asteroid 3.11.0 → 3.12.0-beta.1
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/package.json +1 -1
- package/src/components/app-user/QasAppUser.vue +1 -1
- package/src/components/filters/QasFilters.vue +8 -15
- package/src/components/search-box/QasSearchBox.vue +1 -1
- package/src/components/select-list-dialog/QasSelectListDialog.vue +379 -0
- package/src/components/select-list-dialog/QasSelectListDialog.yml +103 -0
- package/src/components/text-truncate/QasTextTruncate.vue +105 -20
- package/src/components/text-truncate/QasTextTruncate.yml +24 -0
- package/src/components/timeline/QasTimeline.vue +140 -0
- package/src/components/timeline/QasTimeline.yml +36 -0
- package/src/composables/index.js +3 -1
- package/src/composables/use-context.js +15 -0
- package/src/composables/use-query-cache.js +53 -0
- package/src/vue-plugin.js +9 -3
package/package.json
CHANGED
|
@@ -224,9 +224,14 @@ export default {
|
|
|
224
224
|
}
|
|
225
225
|
},
|
|
226
226
|
|
|
227
|
-
created () {
|
|
228
|
-
this.fetchFilters()
|
|
229
|
-
|
|
227
|
+
async created () {
|
|
228
|
+
await this.fetchFilters()
|
|
229
|
+
|
|
230
|
+
if (this.useUpdateRoute) {
|
|
231
|
+
this.updateValues()
|
|
232
|
+
this.updateCurrentFilters()
|
|
233
|
+
}
|
|
234
|
+
|
|
230
235
|
this.handleSearchModelOnCreate()
|
|
231
236
|
},
|
|
232
237
|
|
|
@@ -371,18 +376,6 @@ export default {
|
|
|
371
376
|
return isMultiple ? [value] : value
|
|
372
377
|
},
|
|
373
378
|
|
|
374
|
-
watchOnceFields () {
|
|
375
|
-
if (!this.useUpdateRoute) return
|
|
376
|
-
|
|
377
|
-
const watchOnce = this.$watch('fields', values => {
|
|
378
|
-
if (Object.keys(values || {}).length) {
|
|
379
|
-
this.updateValues()
|
|
380
|
-
this.updateCurrentFilters()
|
|
381
|
-
watchOnce()
|
|
382
|
-
}
|
|
383
|
-
})
|
|
384
|
-
},
|
|
385
|
-
|
|
386
379
|
handleSearchModelOnCreate () {
|
|
387
380
|
if (this.useUpdateRoute && !this.useFilterButton) {
|
|
388
381
|
this.setSearch()
|
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="app-select-list-dialog full-width">
|
|
3
|
+
<header class="flex items-center justify-between no-wrap">
|
|
4
|
+
<qas-label v-bind="labelProps" />
|
|
5
|
+
|
|
6
|
+
<qas-btn
|
|
7
|
+
v-bind="defaultAddButtonProps"
|
|
8
|
+
@click="toggleDialog"
|
|
9
|
+
/>
|
|
10
|
+
</header>
|
|
11
|
+
|
|
12
|
+
<div
|
|
13
|
+
v-if="props.description"
|
|
14
|
+
class="q-mt-md text-body1 text-grey-8"
|
|
15
|
+
>
|
|
16
|
+
{{ props.description }}
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<qas-box
|
|
20
|
+
v-if="hasBox"
|
|
21
|
+
class="q-mt-md relative-position"
|
|
22
|
+
>
|
|
23
|
+
<span class="text-grey-9 text-subtitle1">
|
|
24
|
+
{{ props.listLabel }}
|
|
25
|
+
</span>
|
|
26
|
+
|
|
27
|
+
<q-virtual-scroll #default="{ item, index }" class="app-select-list-dialog__list q-mt-md" :items="selectedOptions" separator>
|
|
28
|
+
<q-item class="q-px-none text-body1 text-grey-8">
|
|
29
|
+
<q-item-section>
|
|
30
|
+
{{ item.label }}
|
|
31
|
+
</q-item-section>
|
|
32
|
+
|
|
33
|
+
<q-item-section avatar>
|
|
34
|
+
<qas-btn v-bind="getRemoveButtonProps({ index, option: item })" />
|
|
35
|
+
</q-item-section>
|
|
36
|
+
</q-item>
|
|
37
|
+
</q-virtual-scroll>
|
|
38
|
+
|
|
39
|
+
<q-inner-loading :showing="props.loading">
|
|
40
|
+
<q-spinner
|
|
41
|
+
color="grey"
|
|
42
|
+
size="2em"
|
|
43
|
+
/>
|
|
44
|
+
</q-inner-loading>
|
|
45
|
+
</qas-box>
|
|
46
|
+
|
|
47
|
+
<span
|
|
48
|
+
v-if="hasError"
|
|
49
|
+
class="app-select-list-dialog__error"
|
|
50
|
+
>
|
|
51
|
+
{{ errorMessage }}
|
|
52
|
+
</span>
|
|
53
|
+
|
|
54
|
+
<qas-dialog
|
|
55
|
+
v-bind="defaultDialogProps"
|
|
56
|
+
v-model="showDialog"
|
|
57
|
+
>
|
|
58
|
+
<template v-for="(_, name) in $slots" #[name]="context">
|
|
59
|
+
<slot :name="`dialog-${name}`" v-bind="context || {}" />
|
|
60
|
+
</template>
|
|
61
|
+
|
|
62
|
+
<template #description>
|
|
63
|
+
<slot name="dialog-description">
|
|
64
|
+
<div v-if="dialogDescription" class="q-mb-xl text-center">
|
|
65
|
+
{{ dialogDescription }}
|
|
66
|
+
</div>
|
|
67
|
+
|
|
68
|
+
<qas-select-list
|
|
69
|
+
v-model="listModel"
|
|
70
|
+
v-bind="defaultSelectListProps"
|
|
71
|
+
/>
|
|
72
|
+
</slot>
|
|
73
|
+
</template>
|
|
74
|
+
</qas-dialog>
|
|
75
|
+
</div>
|
|
76
|
+
</template>
|
|
77
|
+
|
|
78
|
+
<script setup>
|
|
79
|
+
import { computed, ref, watch } from 'vue'
|
|
80
|
+
|
|
81
|
+
defineOptions({ name: 'QasSelectListDialog' })
|
|
82
|
+
|
|
83
|
+
const props = defineProps({
|
|
84
|
+
addButtonProps: {
|
|
85
|
+
type: Object,
|
|
86
|
+
default: () => ({})
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
description: {
|
|
90
|
+
type: String,
|
|
91
|
+
default: ''
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
disable: {
|
|
95
|
+
type: Boolean
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
error: {
|
|
99
|
+
type: [String, Array],
|
|
100
|
+
default: ''
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
dialogProps: {
|
|
104
|
+
type: Object,
|
|
105
|
+
default: () => ({})
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
options: {
|
|
109
|
+
type: Array,
|
|
110
|
+
default: () => []
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
label: {
|
|
114
|
+
type: String,
|
|
115
|
+
default: ''
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
listLabel: {
|
|
119
|
+
type: String,
|
|
120
|
+
default: ''
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
loading: {
|
|
124
|
+
type: Boolean
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
modelValue: {
|
|
128
|
+
type: Array,
|
|
129
|
+
default: () => []
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
selectListProps: {
|
|
133
|
+
type: Object,
|
|
134
|
+
default: () => ({})
|
|
135
|
+
}
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
const emit = defineEmits(['add', 'remove', 'update:modelValue'])
|
|
139
|
+
|
|
140
|
+
const hasError = computed(() => Array.isArray(props.error) ? !!props.error.length : !!props.error)
|
|
141
|
+
const errorMessage = computed(() => Array.isArray(props.error) ? props.error.join(' ') : props.error)
|
|
142
|
+
|
|
143
|
+
const {
|
|
144
|
+
listModel,
|
|
145
|
+
showDialog,
|
|
146
|
+
|
|
147
|
+
defaultDialogProps,
|
|
148
|
+
defaultSelectListProps,
|
|
149
|
+
dialogDescription,
|
|
150
|
+
|
|
151
|
+
toggleDialog
|
|
152
|
+
} = useSelectDialog()
|
|
153
|
+
|
|
154
|
+
const {
|
|
155
|
+
selectedOptions,
|
|
156
|
+
|
|
157
|
+
hasBox,
|
|
158
|
+
|
|
159
|
+
add,
|
|
160
|
+
removeAll,
|
|
161
|
+
remove,
|
|
162
|
+
getRemoveButtonProps
|
|
163
|
+
} = useList()
|
|
164
|
+
|
|
165
|
+
defineExpose({ add, removeAll, remove })
|
|
166
|
+
|
|
167
|
+
const model = ref([...props.modelValue])
|
|
168
|
+
|
|
169
|
+
const defaultAddButtonProps = computed(() => {
|
|
170
|
+
return {
|
|
171
|
+
icon: 'sym_r_add',
|
|
172
|
+
useLabelOnSmallScreen: false,
|
|
173
|
+
...props.addButtonProps,
|
|
174
|
+
disable: props.disable,
|
|
175
|
+
loading: props.loading
|
|
176
|
+
}
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
const labelProps = computed(() => {
|
|
180
|
+
return {
|
|
181
|
+
label: props.label,
|
|
182
|
+
margin: 'none',
|
|
183
|
+
color: hasError.value ? 'negative' : 'grey-9'
|
|
184
|
+
}
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
const hasLazyLoading = computed(() => !!props.selectListProps?.searchBoxProps?.useLazyLoading)
|
|
188
|
+
|
|
189
|
+
watch(() => props.modelValue, newValue => {
|
|
190
|
+
model.value = [...newValue]
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
function updateModel () {
|
|
194
|
+
emit('update:modelValue', model.value)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// ------------------------- composable functions ------------------------------
|
|
198
|
+
function useList () {
|
|
199
|
+
const filteredOptions = ref(props.options)
|
|
200
|
+
|
|
201
|
+
const selectedOptions = computed(() => {
|
|
202
|
+
const options = []
|
|
203
|
+
|
|
204
|
+
model.value.forEach(value => {
|
|
205
|
+
const option = filteredOptions.value.find(option => option.value === value)
|
|
206
|
+
|
|
207
|
+
if (option) return options.push(option)
|
|
208
|
+
|
|
209
|
+
options.push({ label: value })
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
return options
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
watch(() => props.options, options => {
|
|
216
|
+
filteredOptions.value = [...options]
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
const hasBox = computed(() => hasFilteredOptions.value || props.loading)
|
|
220
|
+
const hasFilteredOptions = computed(() => model.value.length)
|
|
221
|
+
|
|
222
|
+
/*
|
|
223
|
+
* caso não passe o value, o valor sera automaticamente o value da option
|
|
224
|
+
*/
|
|
225
|
+
function add ({ options = [], value }) {
|
|
226
|
+
const normalizedItems = Array.isArray(options) ? options : [options]
|
|
227
|
+
|
|
228
|
+
/*
|
|
229
|
+
* Validação necessária pois se não estiver com lazyloading e adicionar mais opções, as options vai vir duplicadas
|
|
230
|
+
* com as opções que já foram adicionadas
|
|
231
|
+
*/
|
|
232
|
+
if (hasLazyLoading.value) {
|
|
233
|
+
filteredOptions.value.push(...normalizedItems)
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const newModel = value || normalizedItems.map(item => item.value)
|
|
237
|
+
|
|
238
|
+
model.value.push(...newModel)
|
|
239
|
+
|
|
240
|
+
emit('add', newModel)
|
|
241
|
+
|
|
242
|
+
updateModel()
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function removeAll () {
|
|
246
|
+
model.value = []
|
|
247
|
+
filteredOptions.value = []
|
|
248
|
+
|
|
249
|
+
updateModel()
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function remove (value) {
|
|
253
|
+
const index = model.value.findIndex(item => item === value)
|
|
254
|
+
const optionIndex = filteredOptions.value.findIndex(option => option.value === value)
|
|
255
|
+
|
|
256
|
+
if (~index) model.value.splice(index, 1)
|
|
257
|
+
if (~optionIndex) filteredOptions.value.splice(optionIndex, 1)
|
|
258
|
+
|
|
259
|
+
emit('remove', value)
|
|
260
|
+
updateModel()
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function getRemoveButtonProps ({ option }) {
|
|
264
|
+
return {
|
|
265
|
+
color: 'grey-9',
|
|
266
|
+
icon: 'sym_r_delete',
|
|
267
|
+
variant: 'tertiary',
|
|
268
|
+
disable: props.disable || !!option.disable,
|
|
269
|
+
onClick: () => remove(option.value)
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return {
|
|
274
|
+
filteredOptions,
|
|
275
|
+
selectedOptions,
|
|
276
|
+
|
|
277
|
+
hasBox,
|
|
278
|
+
hasFilteredOptions,
|
|
279
|
+
|
|
280
|
+
add,
|
|
281
|
+
removeAll,
|
|
282
|
+
remove,
|
|
283
|
+
getRemoveButtonProps
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function useSelectDialog () {
|
|
288
|
+
const showDialog = ref(false)
|
|
289
|
+
const listModel = ref([])
|
|
290
|
+
|
|
291
|
+
const defaultDialogProps = computed(() => {
|
|
292
|
+
return {
|
|
293
|
+
useFullMaxWidth: true,
|
|
294
|
+
|
|
295
|
+
...props.dialogProps,
|
|
296
|
+
|
|
297
|
+
onBeforeShow: event => {
|
|
298
|
+
resetListModel()
|
|
299
|
+
|
|
300
|
+
props.dialogProps.onBeforeShow && props.dialogProps.onBeforeShow(event)
|
|
301
|
+
},
|
|
302
|
+
|
|
303
|
+
ok: {
|
|
304
|
+
label: 'Adicionar',
|
|
305
|
+
|
|
306
|
+
disable: !listModel.value.length,
|
|
307
|
+
|
|
308
|
+
...props.dialogProps.ok,
|
|
309
|
+
|
|
310
|
+
onClick: () => {
|
|
311
|
+
props.dialogProps.ok?.onClick?.()
|
|
312
|
+
onAdd()
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
})
|
|
317
|
+
|
|
318
|
+
const defaultSelectListProps = computed(() => {
|
|
319
|
+
return {
|
|
320
|
+
emitValue: false,
|
|
321
|
+
|
|
322
|
+
...props.selectListProps,
|
|
323
|
+
|
|
324
|
+
searchBoxProps: {
|
|
325
|
+
list: props.options,
|
|
326
|
+
height: '160px',
|
|
327
|
+
optionsToExclude: model.value,
|
|
328
|
+
|
|
329
|
+
...props.selectListProps.searchBoxProps
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
})
|
|
333
|
+
|
|
334
|
+
const dialogDescription = computed(() => props.dialogProps.card?.description)
|
|
335
|
+
|
|
336
|
+
function toggleDialog () {
|
|
337
|
+
showDialog.value = !showDialog.value
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function resetListModel () {
|
|
341
|
+
listModel.value = []
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
function onAdd () {
|
|
345
|
+
if (listModel.value.length) add({ options: listModel.value })
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
return {
|
|
349
|
+
listModel,
|
|
350
|
+
showDialog,
|
|
351
|
+
|
|
352
|
+
defaultDialogProps,
|
|
353
|
+
defaultSelectListProps,
|
|
354
|
+
dialogDescription,
|
|
355
|
+
|
|
356
|
+
toggleDialog
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
</script>
|
|
360
|
+
|
|
361
|
+
<style lang="scss">
|
|
362
|
+
.app-select-list-dialog {
|
|
363
|
+
.q-item {
|
|
364
|
+
@include set-typography($body1)
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// simulando q-field--error
|
|
368
|
+
&__error {
|
|
369
|
+
padding-top: var(--qas-spacing-sm);
|
|
370
|
+
color: var(--q-negative) !important;
|
|
371
|
+
font-size: 12px;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
&__list {
|
|
375
|
+
max-height: 250px;
|
|
376
|
+
overflow-y: auto;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
</style>
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
type: component
|
|
2
|
+
|
|
3
|
+
meta:
|
|
4
|
+
desc: Componente de seleção de itens dentro do QasDialog.
|
|
5
|
+
|
|
6
|
+
props:
|
|
7
|
+
add-button-props:
|
|
8
|
+
desc: Props repassadas para o botão de adicionar (QasBtn)
|
|
9
|
+
default: {}
|
|
10
|
+
type: Object
|
|
11
|
+
|
|
12
|
+
description:
|
|
13
|
+
desc: Descrição acima da lista de itens selecionados.
|
|
14
|
+
default: ''
|
|
15
|
+
type: String
|
|
16
|
+
|
|
17
|
+
disable:
|
|
18
|
+
desc: Desabilita o componente (remoção e adição).
|
|
19
|
+
default: false
|
|
20
|
+
type: Boolean
|
|
21
|
+
|
|
22
|
+
dialog-props:
|
|
23
|
+
desc: Propriedades repassadas para o dialog (QasDialog).
|
|
24
|
+
default: {}
|
|
25
|
+
type: Object
|
|
26
|
+
|
|
27
|
+
error:
|
|
28
|
+
desc: Mensagem de erro.
|
|
29
|
+
default: ''
|
|
30
|
+
type: String
|
|
31
|
+
|
|
32
|
+
options:
|
|
33
|
+
desc: Opções de itens disponíveis para seleção.
|
|
34
|
+
default: []
|
|
35
|
+
type: Array
|
|
36
|
+
|
|
37
|
+
label:
|
|
38
|
+
desc: Label do componente.
|
|
39
|
+
default: ''
|
|
40
|
+
type: String
|
|
41
|
+
|
|
42
|
+
list-label:
|
|
43
|
+
desc: Label da acima dos itens selecionados.
|
|
44
|
+
default: ''
|
|
45
|
+
type: String
|
|
46
|
+
|
|
47
|
+
loading:
|
|
48
|
+
desc: Estado de carregamento do componente.
|
|
49
|
+
default: false
|
|
50
|
+
type: Boolean
|
|
51
|
+
|
|
52
|
+
model-value:
|
|
53
|
+
desc: Model do componente.
|
|
54
|
+
default: []
|
|
55
|
+
type: Array
|
|
56
|
+
model: true
|
|
57
|
+
|
|
58
|
+
select-list-props:
|
|
59
|
+
desc: Propriedades repassadas para o componente QasSelectList.
|
|
60
|
+
default: []
|
|
61
|
+
type: Array
|
|
62
|
+
|
|
63
|
+
slots:
|
|
64
|
+
dialog-actions:
|
|
65
|
+
desc: Slot para substituir ações do dialog.
|
|
66
|
+
|
|
67
|
+
dialog-description:
|
|
68
|
+
desc: Slot para substituir a descrição do dialog.
|
|
69
|
+
|
|
70
|
+
dialog-header:
|
|
71
|
+
desc: Slot para substituir cabeçalho do dialog.
|
|
72
|
+
|
|
73
|
+
events:
|
|
74
|
+
'add -> function(list)':
|
|
75
|
+
desc: Dispara toda vez que é adicionado novos itens.
|
|
76
|
+
params:
|
|
77
|
+
list:
|
|
78
|
+
desc: Lista de itens adicionados.
|
|
79
|
+
type: Array
|
|
80
|
+
|
|
81
|
+
'remove -> function(value)':
|
|
82
|
+
desc: Dispara toda vez que é removido um item.
|
|
83
|
+
params:
|
|
84
|
+
value:
|
|
85
|
+
desc: Valor do item (uuid/id/slug).
|
|
86
|
+
type: String
|
|
87
|
+
|
|
88
|
+
'update:model-value -> function(list)':
|
|
89
|
+
desc: Dispara toda vez que o model é atualizado.
|
|
90
|
+
params:
|
|
91
|
+
list:
|
|
92
|
+
desc: Lista de itens selecionados.
|
|
93
|
+
type: Array
|
|
94
|
+
|
|
95
|
+
methods:
|
|
96
|
+
'add ({ options = [], value }) => undefined':
|
|
97
|
+
desc: Adiciona itens a lista de selecionados, é preciso adicionar quais opções são referentes ao model.
|
|
98
|
+
|
|
99
|
+
'remove (value) => undefined':
|
|
100
|
+
desc: remove um item da lista de selecionados passando o valor referente a ele na lista.
|
|
101
|
+
|
|
102
|
+
'removeAll () => undefined':
|
|
103
|
+
desc: remove todos os itens da lista de selecionados.
|
|
@@ -1,16 +1,26 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div ref="parent" class="
|
|
3
|
-
<div class="
|
|
4
|
-
<div ref="truncate"
|
|
5
|
-
<slot>{{
|
|
2
|
+
<div ref="parent" :class="classes">
|
|
3
|
+
<div class="no-wrap row text-no-wrap">
|
|
4
|
+
<div ref="truncate" class="ellipsis">
|
|
5
|
+
<slot>{{ displayText }}</slot>
|
|
6
6
|
</div>
|
|
7
7
|
|
|
8
|
-
<
|
|
9
|
-
{{ seeMoreLabel }}
|
|
10
|
-
</div>
|
|
8
|
+
<qas-btn v-if="hasButton" class="q-ml-sm" :label="buttonLabel" @click.stop.prevent="toggle" />
|
|
11
9
|
</div>
|
|
12
10
|
|
|
13
|
-
<qas-dialog v-model="show" v-bind="defaultProps" aria-label="Diálogo de texto completo" role="dialog"
|
|
11
|
+
<qas-dialog v-model="show" v-bind="defaultProps" aria-label="Diálogo de texto completo" role="dialog">
|
|
12
|
+
<template v-if="isCounterMode" #description>
|
|
13
|
+
<div class="q-col-gutter-y-md row">
|
|
14
|
+
<div
|
|
15
|
+
v-for="(item, index) in normalizedList"
|
|
16
|
+
:key="index"
|
|
17
|
+
class="col-12"
|
|
18
|
+
>
|
|
19
|
+
{{ item }}
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
</template>
|
|
23
|
+
</qas-dialog>
|
|
14
24
|
</div>
|
|
15
25
|
</template>
|
|
16
26
|
|
|
@@ -23,8 +33,6 @@ import {
|
|
|
23
33
|
watch
|
|
24
34
|
} from 'vue'
|
|
25
35
|
|
|
26
|
-
import useScreen from '../../composables/use-screen'
|
|
27
|
-
|
|
28
36
|
import QasDialog from '../dialog/QasDialog.vue'
|
|
29
37
|
|
|
30
38
|
// define component name
|
|
@@ -32,6 +40,11 @@ defineOptions({ name: 'QasTextTruncate' })
|
|
|
32
40
|
|
|
33
41
|
// props
|
|
34
42
|
const props = defineProps({
|
|
43
|
+
color: {
|
|
44
|
+
type: String,
|
|
45
|
+
default: 'grey-8'
|
|
46
|
+
},
|
|
47
|
+
|
|
35
48
|
dialogProps: {
|
|
36
49
|
type: Object,
|
|
37
50
|
default: () => ({ persistent: false })
|
|
@@ -47,6 +60,11 @@ const props = defineProps({
|
|
|
47
60
|
default: 0
|
|
48
61
|
},
|
|
49
62
|
|
|
63
|
+
maxVisibleItem: {
|
|
64
|
+
type: Number,
|
|
65
|
+
default: 1
|
|
66
|
+
},
|
|
67
|
+
|
|
50
68
|
seeMoreLabel: {
|
|
51
69
|
type: String,
|
|
52
70
|
default: 'Ver mais'
|
|
@@ -55,6 +73,20 @@ const props = defineProps({
|
|
|
55
73
|
text: {
|
|
56
74
|
type: String,
|
|
57
75
|
default: ''
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
typography: {
|
|
79
|
+
type: String,
|
|
80
|
+
default: 'body1'
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
list: {
|
|
84
|
+
type: Array,
|
|
85
|
+
default: () => []
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
useObjectList: {
|
|
89
|
+
type: Boolean
|
|
58
90
|
}
|
|
59
91
|
})
|
|
60
92
|
|
|
@@ -66,8 +98,6 @@ const parent = ref(null)
|
|
|
66
98
|
const {
|
|
67
99
|
textContent,
|
|
68
100
|
isTruncated,
|
|
69
|
-
truncateTextClass,
|
|
70
|
-
|
|
71
101
|
truncateText
|
|
72
102
|
} = useTruncate({ parent, props })
|
|
73
103
|
|
|
@@ -77,8 +107,18 @@ const {
|
|
|
77
107
|
toggle
|
|
78
108
|
} = useDialog({ props, textContent })
|
|
79
109
|
|
|
110
|
+
const {
|
|
111
|
+
buttonLabel,
|
|
112
|
+
displayText,
|
|
113
|
+
hasButton,
|
|
114
|
+
isCounterMode,
|
|
115
|
+
normalizedList
|
|
116
|
+
} = useTemplate()
|
|
117
|
+
|
|
80
118
|
useMutationObserver({ truncate, callbackFn: truncateText })
|
|
81
119
|
|
|
120
|
+
const classes = computed(() => [`text-${props.color}`, `text-${props.typography}`])
|
|
121
|
+
|
|
82
122
|
// composable functions
|
|
83
123
|
function useDialog ({ props, textContent }) {
|
|
84
124
|
// reactive vars
|
|
@@ -136,9 +176,6 @@ function useMutationObserver ({ truncate, callbackFn = () => {} }) {
|
|
|
136
176
|
}
|
|
137
177
|
|
|
138
178
|
function useTruncate ({ parent, props }) {
|
|
139
|
-
// global
|
|
140
|
-
const screen = useScreen()
|
|
141
|
-
|
|
142
179
|
// reactive vars
|
|
143
180
|
const maxPossibleWidth = ref('')
|
|
144
181
|
const textContent = ref('')
|
|
@@ -153,10 +190,6 @@ function useTruncate ({ parent, props }) {
|
|
|
153
190
|
// computed
|
|
154
191
|
const isTruncated = computed(() => textWidth.value > maxPossibleWidth.value)
|
|
155
192
|
|
|
156
|
-
const truncateTextClass = computed(() => {
|
|
157
|
-
return (isTruncated.value || screen.isSmall) && 'ellipsis q-pr-sm'
|
|
158
|
-
})
|
|
159
|
-
|
|
160
193
|
// methods
|
|
161
194
|
function truncateText () {
|
|
162
195
|
parent.value.style.maxWidth = '100%'
|
|
@@ -174,9 +207,61 @@ function useTruncate ({ parent, props }) {
|
|
|
174
207
|
textWidth,
|
|
175
208
|
|
|
176
209
|
isTruncated,
|
|
177
|
-
truncateTextClass,
|
|
178
210
|
|
|
179
211
|
truncateText
|
|
180
212
|
}
|
|
181
213
|
}
|
|
214
|
+
|
|
215
|
+
function useTemplate () {
|
|
216
|
+
const {
|
|
217
|
+
counterLabel,
|
|
218
|
+
normalizedList,
|
|
219
|
+
normalizedCounterText
|
|
220
|
+
} = useCounter()
|
|
221
|
+
|
|
222
|
+
const isCounterMode = computed(() => !!props.list.length)
|
|
223
|
+
|
|
224
|
+
const hasButton = computed(() => {
|
|
225
|
+
return isCounterMode.value ? normalizedList.value.length > props.maxVisibleItem : isTruncated.value
|
|
226
|
+
})
|
|
227
|
+
|
|
228
|
+
const displayText = computed(() => {
|
|
229
|
+
return isCounterMode.value ? normalizedCounterText.value : props.text
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
const buttonLabel = computed(() => {
|
|
233
|
+
return isCounterMode.value ? counterLabel.value : props.seeMoreLabel
|
|
234
|
+
})
|
|
235
|
+
|
|
236
|
+
return {
|
|
237
|
+
buttonLabel,
|
|
238
|
+
displayText,
|
|
239
|
+
hasButton,
|
|
240
|
+
isCounterMode,
|
|
241
|
+
normalizedList
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function useCounter () {
|
|
246
|
+
const normalizedList = computed(() => {
|
|
247
|
+
return props.useObjectList ? props.list.map(({ label }) => label) : props.list
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
const counterText = computed(() => {
|
|
251
|
+
return props.maxVisibleItem > 1
|
|
252
|
+
? normalizedList.value.slice(0, props.maxVisibleItem).join(', ')
|
|
253
|
+
: normalizedList.value[0]
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
const normalizedCounterText = computed(() => counterText.value || '-')
|
|
257
|
+
|
|
258
|
+
const counter = computed(() => (normalizedList.value.length || 1) - props.maxVisibleItem)
|
|
259
|
+
const counterLabel = computed(() => `+${counter.value}`)
|
|
260
|
+
|
|
261
|
+
return {
|
|
262
|
+
normalizedList,
|
|
263
|
+
normalizedCounterText,
|
|
264
|
+
counterLabel
|
|
265
|
+
}
|
|
266
|
+
}
|
|
182
267
|
</script>
|
|
@@ -4,6 +4,11 @@ meta:
|
|
|
4
4
|
desc: Trunca um texto baseado no tamanho do elemento pai e adiciona um rotulo "ver mais" que quando clicado mostra um dialog com o texto original completo (sem ser truncado).
|
|
5
5
|
|
|
6
6
|
props:
|
|
7
|
+
color:
|
|
8
|
+
desc: Cor do texto.
|
|
9
|
+
type: String
|
|
10
|
+
default: grey-8
|
|
11
|
+
|
|
7
12
|
dialog-props:
|
|
8
13
|
desc: Repassa todas props e eventos para o componente `QasDialog`.
|
|
9
14
|
type: Object
|
|
@@ -18,6 +23,11 @@ props:
|
|
|
18
23
|
type: Number
|
|
19
24
|
default: 0
|
|
20
25
|
|
|
26
|
+
max-visible-item:
|
|
27
|
+
desc: Quantidade de itens a serem exibidos fora do dialog (uso junto a prop list).
|
|
28
|
+
type: Number
|
|
29
|
+
default: 0
|
|
30
|
+
|
|
21
31
|
see-more-label:
|
|
22
32
|
desc: Texto que vai aparecer para ser clicado quando o texto original for truncado.
|
|
23
33
|
type: String
|
|
@@ -27,6 +37,20 @@ props:
|
|
|
27
37
|
desc: Texto a ser truncado.
|
|
28
38
|
type: String
|
|
29
39
|
|
|
40
|
+
typography:
|
|
41
|
+
desc: Tipografia.
|
|
42
|
+
default: body1
|
|
43
|
+
type: String
|
|
44
|
+
|
|
45
|
+
list:
|
|
46
|
+
desc: Lista de itens a serem exibidos (uso junto a prop list).
|
|
47
|
+
default: []
|
|
48
|
+
type: Array
|
|
49
|
+
|
|
50
|
+
use-object-list:
|
|
51
|
+
desc: Utiliza a propriedade "list" como array de objeto contendo label (uso junto a prop list).
|
|
52
|
+
type: Boolean
|
|
53
|
+
|
|
30
54
|
slots:
|
|
31
55
|
default:
|
|
32
56
|
desc: slot padrão que é utilizado para acessar o texto original (tanto o que é truncado quando o de dentro do dialog)
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<q-timeline
|
|
3
|
+
class="qas-timeline"
|
|
4
|
+
color="grey-6"
|
|
5
|
+
layout="comfortable"
|
|
6
|
+
>
|
|
7
|
+
<template
|
|
8
|
+
v-for="(item, index) in list"
|
|
9
|
+
:key="`timeline-${index}-${uid()}`"
|
|
10
|
+
>
|
|
11
|
+
<q-timeline-entry
|
|
12
|
+
side="left"
|
|
13
|
+
:subtitle="getFormattedValue(item, Masks.Date)"
|
|
14
|
+
>
|
|
15
|
+
<slot :item="item">
|
|
16
|
+
<div class="column justify-center q-gutter-sm q-py-md qas-timeline__content">
|
|
17
|
+
<slot :item="item" name="hour">
|
|
18
|
+
<div class="text-body2 text-grey-8">
|
|
19
|
+
Adicionado às {{ getFormattedValue(item, Masks.Hour) }}
|
|
20
|
+
</div>
|
|
21
|
+
</slot>
|
|
22
|
+
|
|
23
|
+
<slot :item="item" name="description">
|
|
24
|
+
<div class="text-body1 text-grey-9">
|
|
25
|
+
{{ item[descriptionKey] }}
|
|
26
|
+
</div>
|
|
27
|
+
</slot>
|
|
28
|
+
</div>
|
|
29
|
+
</slot>
|
|
30
|
+
</q-timeline-entry>
|
|
31
|
+
</template>
|
|
32
|
+
</q-timeline>
|
|
33
|
+
</template>
|
|
34
|
+
|
|
35
|
+
<script setup>
|
|
36
|
+
import { date as dateFn } from '../../helpers/filters'
|
|
37
|
+
import { uid } from 'quasar'
|
|
38
|
+
|
|
39
|
+
defineOptions({ name: 'QasTimeline' })
|
|
40
|
+
|
|
41
|
+
const Masks = {
|
|
42
|
+
Hour: 'HH:mm',
|
|
43
|
+
Date: 'dd MMM yyyy'
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const props = defineProps({
|
|
47
|
+
list: {
|
|
48
|
+
type: Array,
|
|
49
|
+
default: () => []
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
dateKey: {
|
|
53
|
+
type: String,
|
|
54
|
+
default: 'date'
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
hourKey: {
|
|
58
|
+
type: String,
|
|
59
|
+
default: 'date'
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
descriptionKey: {
|
|
63
|
+
type: String,
|
|
64
|
+
default: 'description'
|
|
65
|
+
}
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
function isInvalidDate (date) {
|
|
69
|
+
const day = new Date(date).getDay()
|
|
70
|
+
|
|
71
|
+
return isNaN(day)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function getFormattedValue (item, mask) {
|
|
75
|
+
const itemKey = mask === Masks.Hour ? props.hourKey : props.dateKey
|
|
76
|
+
|
|
77
|
+
const date = item[itemKey]
|
|
78
|
+
|
|
79
|
+
return isInvalidDate(date) ? date : dateFn(date, mask)
|
|
80
|
+
}
|
|
81
|
+
</script>
|
|
82
|
+
|
|
83
|
+
<style lang="scss">
|
|
84
|
+
.qas-timeline {
|
|
85
|
+
margin: 0;
|
|
86
|
+
|
|
87
|
+
&__content {
|
|
88
|
+
min-height: 100px;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.q-timeline__subtitle {
|
|
92
|
+
color: $dark;
|
|
93
|
+
opacity: initial;
|
|
94
|
+
padding-right: 0;
|
|
95
|
+
position: relative;
|
|
96
|
+
text-align: center;
|
|
97
|
+
vertical-align: middle;
|
|
98
|
+
width: 80px;
|
|
99
|
+
|
|
100
|
+
&::before {
|
|
101
|
+
background-color: currentColor;
|
|
102
|
+
bottom: 0;
|
|
103
|
+
content: "";
|
|
104
|
+
display: block;
|
|
105
|
+
opacity: 0.4;
|
|
106
|
+
position: absolute;
|
|
107
|
+
right: -30px;
|
|
108
|
+
top: 0px;
|
|
109
|
+
transition: opacity var(--qas-generic-transition) ease;
|
|
110
|
+
width: 3px;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.q-timeline__entry {
|
|
115
|
+
&:hover,
|
|
116
|
+
.active {
|
|
117
|
+
.q-timeline__subtitle {
|
|
118
|
+
&::before {
|
|
119
|
+
background-color: $primary;
|
|
120
|
+
opacity: 1;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.q-timeline__content {
|
|
127
|
+
padding-bottom: 0;
|
|
128
|
+
vertical-align: middle;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.q-timeline__title {
|
|
132
|
+
margin-bottom: 0;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.q-timeline__dot::before,
|
|
136
|
+
.q-timeline__dot::after {
|
|
137
|
+
display: none;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
</style>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
type: component
|
|
2
|
+
|
|
3
|
+
meta:
|
|
4
|
+
desc: Componente para timeline que implementa o "QTimeline".
|
|
5
|
+
|
|
6
|
+
props:
|
|
7
|
+
list:
|
|
8
|
+
desc: Lista de itens com datas e descrições que serão exibidios na timeline.
|
|
9
|
+
default: []
|
|
10
|
+
type: Array
|
|
11
|
+
examples: ["[{ date: '2023-01-11T14:58:40.000000Z', description: 'Descrição' }"]
|
|
12
|
+
|
|
13
|
+
dateKey:
|
|
14
|
+
desc: Chave do campo que será exibido à esquerda da timeline.
|
|
15
|
+
default: date
|
|
16
|
+
type: String
|
|
17
|
+
|
|
18
|
+
hourKey:
|
|
19
|
+
desc: Chave do campo que será exibido acima da descrição.
|
|
20
|
+
default: date
|
|
21
|
+
type: String
|
|
22
|
+
|
|
23
|
+
descriptionKey:
|
|
24
|
+
desc: Chave do campo que será exibido na descrição.
|
|
25
|
+
default: description
|
|
26
|
+
type: String
|
|
27
|
+
|
|
28
|
+
slots:
|
|
29
|
+
default:
|
|
30
|
+
desc: slot para substituir o conteúdo todo da timeline.
|
|
31
|
+
|
|
32
|
+
hour:
|
|
33
|
+
desc: slot para substituir o conteúdo acima da descrição.
|
|
34
|
+
|
|
35
|
+
description:
|
|
36
|
+
desc: slot para substituir o conteúdo da descrição.
|
package/src/composables/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
export { default as
|
|
1
|
+
export { default as useContext } from './use-context.js'
|
|
2
2
|
export { default as useForm } from './use-form.js'
|
|
3
|
+
export { default as useHistory } from './use-history.js'
|
|
4
|
+
export { default as useQueryCache } from './use-query-cache.js'
|
|
3
5
|
export { default as useScreen } from './use-screen.js'
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { computed } from 'vue'
|
|
2
|
+
import { useRoute } from 'vue-router'
|
|
3
|
+
|
|
4
|
+
export default function () {
|
|
5
|
+
const route = useRoute()
|
|
6
|
+
|
|
7
|
+
const context = computed(() => {
|
|
8
|
+
const { limit, ordering, page, search, ...filters } = route.query
|
|
9
|
+
return { filters, limit, ordering, page: page ? parseInt(page) : 1, search }
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
return {
|
|
13
|
+
context
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { SessionStorage } from 'quasar'
|
|
2
|
+
import { filterObject } from '../helpers'
|
|
3
|
+
|
|
4
|
+
const cachedFilters = SessionStorage.getItem('cachedFilters') || {}
|
|
5
|
+
|
|
6
|
+
function updateSessionStorage () {
|
|
7
|
+
SessionStorage.set('cachedFilters', cachedFilters)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default function () {
|
|
11
|
+
function addOne (key, { label, value }) {
|
|
12
|
+
cachedFilters[key][label] = value
|
|
13
|
+
updateSessionStorage()
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function addMany (key, filters) {
|
|
17
|
+
cachedFilters[key] = filters
|
|
18
|
+
updateSessionStorage()
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function findOne (key, filter) {
|
|
22
|
+
return cachedFilters[key][filter]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function findAll (key) {
|
|
26
|
+
return cachedFilters[key]
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function clearOne (key, filter) {
|
|
30
|
+
delete cachedFilters[key][filter]
|
|
31
|
+
updateSessionStorage()
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function clearAll (key, { exclude = [] } = {}) {
|
|
35
|
+
if (exclude.length) {
|
|
36
|
+
cachedFilters[key] = filterObject(cachedFilters[key], exclude)
|
|
37
|
+
} else {
|
|
38
|
+
delete cachedFilters[key]
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
updateSessionStorage()
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
addOne,
|
|
46
|
+
addMany,
|
|
47
|
+
findOne,
|
|
48
|
+
findAll,
|
|
49
|
+
clearOne,
|
|
50
|
+
clearAll,
|
|
51
|
+
cachedFilters
|
|
52
|
+
}
|
|
53
|
+
}
|
package/src/vue-plugin.js
CHANGED
|
@@ -21,7 +21,6 @@ import QasDialog from './components/dialog/QasDialog.vue'
|
|
|
21
21
|
import QasDialogRouter from './components/dialog-router/QasDialogRouter.vue'
|
|
22
22
|
import QasEmptyResultText from './components/empty-result-text/QasEmptyResultText.vue'
|
|
23
23
|
import QasField from './components/field/QasField.vue'
|
|
24
|
-
import QasSearchInput from './components/search-input/QasSearchInput.vue'
|
|
25
24
|
import QasFilters from './components/filters/QasFilters.vue'
|
|
26
25
|
import QasFormGenerator from './components/form-generator/QasFormGenerator.vue'
|
|
27
26
|
import QasFormView from './components/form-view/QasFormView.vue'
|
|
@@ -44,8 +43,10 @@ import QasPasswordStrengthChecker from './components/password-strength-checker/Q
|
|
|
44
43
|
import QasProfile from './components/profile/QasProfile.vue'
|
|
45
44
|
import QasResizer from './components/resizer/QasResizer.vue'
|
|
46
45
|
import QasSearchBox from './components/search-box/QasSearchBox.vue'
|
|
46
|
+
import QasSearchInput from './components/search-input/QasSearchInput.vue'
|
|
47
47
|
import QasSelect from './components/select/QasSelect.vue'
|
|
48
48
|
import QasSelectList from './components/select-list/QasSelectList.vue'
|
|
49
|
+
import QasSelectListDialog from './components/select-list-dialog/QasSelectListDialog.vue'
|
|
49
50
|
import QasSignaturePad from './components/signature-pad/QasSignaturePad.vue'
|
|
50
51
|
import QasSignatureUploader from './components/signature-uploader/QasSignatureUploader.vue'
|
|
51
52
|
import QasSingleView from './components/single-view/QasSingleView.vue'
|
|
@@ -54,6 +55,7 @@ import QasStatus from './components/status/QasStatus.vue'
|
|
|
54
55
|
import QasTableGenerator from './components/table-generator/QasTableGenerator.vue'
|
|
55
56
|
import QasTabsGenerator from './components/tabs-generator/QasTabsGenerator.vue'
|
|
56
57
|
import QasTextTruncate from './components/text-truncate/QasTextTruncate.vue'
|
|
58
|
+
import QasTimeline from './components/timeline/QasTimeline.vue'
|
|
57
59
|
import QasTransfer from './components/transfer/QasTransfer.vue'
|
|
58
60
|
import QasTreeGenerator from './components/tree-generator/QasTreeGenerator.vue'
|
|
59
61
|
import QasUploader from './components/uploader/QasUploader.vue'
|
|
@@ -102,7 +104,6 @@ async function install (app) {
|
|
|
102
104
|
app.component('QasDialogRouter', QasDialogRouter)
|
|
103
105
|
app.component('QasEmptyResultText', QasEmptyResultText)
|
|
104
106
|
app.component('QasField', QasField)
|
|
105
|
-
app.component('QasSearchInput', QasSearchInput)
|
|
106
107
|
app.component('QasFilters', QasFilters)
|
|
107
108
|
app.component('QasFormGenerator', QasFormGenerator)
|
|
108
109
|
app.component('QasFormView', QasFormView)
|
|
@@ -125,8 +126,10 @@ async function install (app) {
|
|
|
125
126
|
app.component('QasProfile', QasProfile)
|
|
126
127
|
app.component('QasResizer', QasResizer)
|
|
127
128
|
app.component('QasSearchBox', QasSearchBox)
|
|
129
|
+
app.component('QasSearchInput', QasSearchInput)
|
|
128
130
|
app.component('QasSelect', QasSelect)
|
|
129
131
|
app.component('QasSelectList', QasSelectList)
|
|
132
|
+
app.component('QasSelectListDialog', QasSelectListDialog)
|
|
130
133
|
app.component('QasSignaturePad', QasSignaturePad)
|
|
131
134
|
app.component('QasSignatureUploader', QasSignatureUploader)
|
|
132
135
|
app.component('QasSingleView', QasSingleView)
|
|
@@ -135,6 +138,7 @@ async function install (app) {
|
|
|
135
138
|
app.component('QasTableGenerator', QasTableGenerator)
|
|
136
139
|
app.component('QasTabsGenerator', QasTabsGenerator)
|
|
137
140
|
app.component('QasTextTruncate', QasTextTruncate)
|
|
141
|
+
app.component('QasTimeline', QasTimeline)
|
|
138
142
|
app.component('QasTransfer', QasTransfer)
|
|
139
143
|
app.component('QasTreeGenerator', QasTreeGenerator)
|
|
140
144
|
app.component('QasUploader', QasUploader)
|
|
@@ -181,7 +185,6 @@ export {
|
|
|
181
185
|
QasDialogRouter,
|
|
182
186
|
QasEmptyResultText,
|
|
183
187
|
QasField,
|
|
184
|
-
QasSearchInput,
|
|
185
188
|
QasFilters,
|
|
186
189
|
QasFormGenerator,
|
|
187
190
|
QasFormView,
|
|
@@ -204,8 +207,10 @@ export {
|
|
|
204
207
|
QasProfile,
|
|
205
208
|
QasResizer,
|
|
206
209
|
QasSearchBox,
|
|
210
|
+
QasSearchInput,
|
|
207
211
|
QasSelect,
|
|
208
212
|
QasSelectList,
|
|
213
|
+
QasSelectListDialog,
|
|
209
214
|
QasSignaturePad,
|
|
210
215
|
QasSignatureUploader,
|
|
211
216
|
QasSingleView,
|
|
@@ -214,6 +219,7 @@ export {
|
|
|
214
219
|
QasTableGenerator,
|
|
215
220
|
QasTabsGenerator,
|
|
216
221
|
QasTextTruncate,
|
|
222
|
+
QasTimeline,
|
|
217
223
|
QasTransfer,
|
|
218
224
|
QasTreeGenerator,
|
|
219
225
|
QasUploader,
|