@mythpe/quasar-ui-qui 0.1.19 → 0.1.21

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.
@@ -10,44 +10,15 @@
10
10
  lang="ts"
11
11
  setup
12
12
  >
13
- import type {
14
- ApiServiceParams,
15
- FetchRowsArgs,
16
- MDatatableDialogsOptions,
17
- MDatatableFilterForm,
18
- MDatatableMetaServer,
19
- MDatatableOptions,
20
- MDatatablePagination,
21
- MDatatableProps,
22
- MDatatableScope,
23
- MDtExportOptions,
24
- MDtItem,
25
- MDtItemIndex,
26
- MDtMythApiServicesSchema
27
- } from '../../types'
28
- import type { AxiosRequestConfig } from 'axios'
13
+ import type { MDatatableProps } from '../../types'
29
14
  import type { InvalidSubmissionHandler, SubmissionHandler } from 'vee-validate'
30
15
  import { useForm } from 'vee-validate'
31
- import { computed, nextTick, onMounted, reactive, ref, toRef, toValue, useSlots, watch } from 'vue'
16
+ import { onMounted, ref, toValue, watch } from 'vue'
32
17
  import { is as quasarHelpers, QCardSection, QTable, useQuasar } from 'quasar'
33
18
  import lodash from 'lodash'
34
- import { useRoute, useRouter } from 'vue-router'
35
- import { useMyth } from '../../composable'
19
+ import { useDtHelpers, useMyth } from '../../composable'
36
20
  import { useI18n } from 'vue-i18n'
37
21
 
38
- const initPaginationOptions: MDatatablePagination = {
39
- sortBy: undefined,
40
- descending: undefined,
41
- page: 1,
42
- rowsPerPage: 50,
43
- rowsNumber: 0
44
- }
45
- const initMetaServer: MDatatableMetaServer = {
46
- current_page: null,
47
- last_page: null,
48
- total: null
49
- }
50
-
51
22
  type Props = {
52
23
  controlKey?: MDatatableProps['controlKey'];
53
24
  defaultItem?: MDatatableProps['defaultItem'];
@@ -175,115 +146,120 @@ const emit = defineEmits<Emits>()
175
146
  const {
176
147
  __,
177
148
  parseHeaders,
178
- pascalCase,
179
- pluralize,
180
149
  alertError,
181
- confirmMessage,
182
150
  alertSuccess,
183
151
  scrollToElementFromErrors,
184
- downloadFromResponse,
185
152
  props: pluginOptions,
186
153
  theme,
187
- isSmall,
188
- api
154
+ isSmall
189
155
  } = useMyth()
190
156
 
191
- const slots = useSlots()
192
- const router = useRouter()
193
- const route = useRoute()
194
157
  const $q = useQuasar()
195
158
  const { te } = useI18n({ useScope: 'global' })
196
- const defaultItem = computed(() => props.defaultItem)
197
- const getTableTitle = computed(() => {
198
- if (props.title) {
199
- if (te(props.title)) {
200
- return __(props.title)
201
- }
202
- return __('replace.index', { name: __(props.title) })
203
- }
204
- return undefined
205
- })
206
159
  const useFormContext = useForm<any, any>()
207
- // const formScope = reactive(useFormContext)
208
- const { resetForm: resetDialogForm, setValues, handleSubmit } = useFormContext
209
- watch(() => props.defaultItem, (v) => {
210
- resetDialogForm({ values: { ...v || {} } }, { force: !0 })
211
- }, { immediate: !0, deep: !0 })
212
- const resetVeeForm = async (attrs?: Record<string, any>) => {
213
- const init: any = {}
214
- for (const k in props.defaultItem) {
215
- init[k] = attrs && k in attrs ? attrs[k] : props.defaultItem[k]
216
- }
217
- resetDialogForm({ values: init || {} }, { force: !0 })
218
- attrs && setValues(attrs, !1)
219
- }
220
- const serviceName = computed(() => props.serviceName)
221
- const exportToBlob = computed(() => {
222
- if (props.exportUrl === undefined && pluginOptions.value.datatable?.exportUrl === undefined) {
223
- return !0
224
- }
225
- const t = props.exportUrl === undefined ? pluginOptions.value.datatable?.exportUrl : props.exportUrl
226
- if (t !== undefined) {
227
- if (t.toString() === 'true' || t.toString() === '') {
228
- return !1
229
- }
230
- if (t.toString() === 'pdf') {
231
- return 'excel'
232
- }
233
- if (t.toString() === 'excel') {
234
- return 'pdf'
235
- }
236
- }
237
- return !0
238
- })
160
+ const { resetForm: resetDialogForm, handleSubmit } = useFormContext
161
+
162
+ const {
163
+ onRowContextmenu,
164
+ getRowsPerPageOptions,
165
+ getShowSelection,
166
+ defaultTopBtnProps,
167
+ getProp,
168
+ getSlots,
169
+ onClickTopMenu,
170
+ getRows,
171
+ defaultItem,
172
+ getTableTitle,
173
+ showDialogModel,
174
+ formDialogModel,
175
+ dialogItem,
176
+ dialogItemIndex,
177
+ dialogErrors,
178
+ resetDialogs,
179
+ getHeaders,
180
+ visibleHeaders,
181
+ contextmenu,
182
+ selected,
183
+ onUpdateSelectedItems,
184
+ pagination,
185
+ search,
186
+ searchColumnsRef,
187
+ searchPlaceholder,
188
+ loading,
189
+ filterForm,
190
+ tempFilterForm,
191
+ hasAction,
192
+ fullscreen,
193
+ hasAddBtn,
194
+ hasUpdateBtn,
195
+ hasCloneBtn,
196
+ hasShowBtn,
197
+ hasDestroyBtn,
198
+ hasFilterDialog,
199
+ isUpdateMode,
200
+ isSingleSelectedItem,
201
+ hasSelectedItem,
202
+ getShowTitle,
203
+ getFormTitle,
204
+ isGrid,
205
+ getMythApiServicesSchema,
206
+ updateSelectedItems,
207
+ onScroll,
208
+ loadMore,
209
+ refreshNoUpdate,
210
+ refresh,
211
+ getRequestWith,
212
+ getDatatableParams,
213
+ fetchDatatableItems,
214
+ exportData,
215
+ openDialogTimeout,
216
+ openFilterDialog,
217
+ saveFilterDialog,
218
+ closeFilterDialog,
219
+ onRemoveFilter,
220
+ updateFilterOptions,
221
+ openShowDialogNoIndex,
222
+ openShowDialog,
223
+ closeShowDialog,
224
+ openUpdateDialogNoIndex,
225
+ openUpdateDialog,
226
+ openCreateDialog,
227
+ closeFormDialog,
228
+ ignoreKeysProps,
229
+ updateDatatableItem,
230
+ tableOptions,
231
+ removeDtItem,
232
+ onDeleteItem,
233
+ deleteSelectionItem,
234
+ logoutDatatable,
235
+ contextmenuItems,
236
+ datatableItemsScope,
237
+ onCloneItem,
238
+ imageDialog,
239
+ openImageDialog,
240
+ closeImageDialog
241
+ } = useDtHelpers(() => props)
242
+
239
243
  // Prevent user from back
240
244
  /* router.beforeResolve(() => {
241
- if (dialogs.filter) {
245
+ if (filterDialogModel.value) {
242
246
  closeFilterDialog()
243
247
  return !1
244
- } else if (dialogs.show) {
248
+ } else if (showDialogModel.value) {
245
249
  closeShowDialog()
246
250
  return !1
247
- } else if (dialogs.form) {
251
+ } else if (formDialogModel.value) {
248
252
  closeFormDialog()
249
253
  return !1
250
254
  }
251
255
  return !hasAction.value
252
256
  }) */
253
- const getRows = ref<MDtItem[]>([])
254
- watch(() => getRows.value, (v) => emit('update:rows', v), { deep: !0 })
255
- const filterDialogModel = ref(!1)
256
- const showDialogModel = ref(!1)
257
- const formDialogModel = ref(!1)
258
- const isUpdateDialog = ref(!1)
259
- const dialogItem = ref<MDtItem | undefined>(undefined)
260
- const dialogItemIndex = ref<MDtItemIndex | undefined>()
261
- const dialogErrors = ref<any>({})
262
- const dialogs = reactive<MDatatableDialogsOptions>({
263
- filter: filterDialogModel,
264
- show: showDialogModel,
265
- form: formDialogModel,
266
- isUpdate: isUpdateDialog,
267
- item: dialogItem,
268
- index: dialogItemIndex,
269
- errors: dialogErrors
270
- })
271
- const resetDialogs = () => {
272
- console.log('resetDialogs')
273
- dialogs.filter = !1
274
- dialogs.show = !1
275
- dialogs.form = !1
276
- dialogs.isUpdate = !1
277
- dialogs.item = undefined
278
- dialogs.index = undefined
279
- dialogs.errors = {}
280
- }
281
257
 
282
- /** Table */
258
+ watch(defaultItem, (v) => {
259
+ resetDialogForm({ values: { ...v || {} } }, { force: !0 })
260
+ }, { immediate: !0, deep: !0 })
283
261
 
284
- /** --- */
285
- const getHeaders = computed<any[]>(() => parseHeaders(toValue(props.headers), { noSort: props.imageColumns }) || [])
286
- const visibleHeaders = ref<string[]>([])
262
+ watch(() => getRows.value, (v) => emit('update:rows', v), { deep: !0 })
287
263
  watch([
288
264
  () => toValue(props.visibleColumns),
289
265
  () => toValue(props.headers)
@@ -293,19 +269,6 @@ watch([
293
269
  }
294
270
  visibleHeaders.value = v ? parseHeaders(v).map(e => e.name) : []
295
271
  }, { deep: !0, immediate: !0 })
296
- /** --- */
297
-
298
- const selected = ref<MDtItem[]>([])
299
- const onUpdateSelectedItems = () => {
300
- if (contextmenu.value) {
301
- contextmenu.value = !1
302
- }
303
- }
304
-
305
- const meta = ref<MDatatableMetaServer>({ ...initMetaServer })
306
- const pagination = ref<MDatatablePagination>({ ...initPaginationOptions })
307
- const search = ref<string | null>(null)
308
- const searchColumnsRef = ref<string[]>([])
309
272
  watch([
310
273
  () => toValue(props.searchColumns),
311
274
  () => toValue(props.headers)
@@ -317,547 +280,6 @@ watch([
317
280
  .filter(e => e?.field !== props.controlKey)
318
281
  .map(e => e.name)
319
282
  }, { deep: !0, immediate: !0 })
320
- const searchPlaceholder = computed<string>(() => {
321
- if (searchColumnsRef.value.length > 0) {
322
- return __('myth.datatable.searchInputPlaceholder',
323
- {
324
- v: getHeaders.value.filter(e => e?.field !== props.controlKey && searchColumnsRef.value.indexOf(e.name) !== -1)
325
- .map(e => e.label)
326
- .join(', ')
327
- })
328
- }
329
- return 'myth.datatable.searchInput'
330
- })
331
- const loading = ref<boolean>(!1)
332
- const filterForm = ref<MDatatableFilterForm>({})
333
- const tempFilterForm = ref<MDatatableFilterForm>({})
334
- const hasAction = ref<boolean>(!1)
335
- const fullscreen = ref(!1)
336
- const tableOptions = reactive<MDatatableOptions>({
337
- search,
338
- loading,
339
- pagination,
340
- meta,
341
- filter: filterForm,
342
- tempFilter: tempFilterForm,
343
- selected,
344
- hasAction,
345
- fullscreen,
346
- getHeaders,
347
- visibleHeaders
348
- })
349
- /** Table */
350
-
351
- /** --- */
352
- /* const addListBtnComputed = computed(() => {
353
- if (props.addListBtn !== undefined) {
354
- return props.addListBtn
355
- }
356
- if (pluginOptions.value.datatable?.addListBtn !== undefined) {
357
- return pluginOptions.value.datatable?.addListBtn
358
- }
359
- return !1
360
- }) */
361
- const hasAddBtn = computed<boolean>(() => {
362
- if (props.hideAddBtn) {
363
- return !1
364
- }
365
- return !!slots.form || !!props.storeRoute
366
- })
367
- const hasUpdateBtn = computed<boolean>(() => {
368
- if (props.hideUpdateBtn) {
369
- return !1
370
- }
371
- return !!slots.form || !!props.updateRoute || props.updateQueryParams
372
- })
373
- const hasCloneBtn = computed<boolean>(() => Boolean(props.cloneBtn))
374
- const hasShowBtn = computed<boolean>(() => {
375
- if (props.hideShowBtn) {
376
- return !1
377
- }
378
- return !!slots.show || !!props.showRoute || props.showQueryParams
379
- })
380
- const hasDestroyBtn = computed<boolean>(() => !props.hideDestroyBtn)
381
- const hasFilterDialog = computed<boolean>(() => !!slots.filter)
382
- /* const hasMenu = computed<boolean>(() => {
383
- const pdf = props.pdf && getRows.value.length > 0
384
- const excel = props.excel && getRows.value.length > 0
385
- if (pdf || excel) {
386
- return !0
387
- }
388
- return hasAddBtn.value && !!addListBtnComputed.value
389
- }) */
390
-
391
- const isUpdateMode = ref<boolean>(!1)
392
- const formMode = computed<'update' | 'store'>(() => isUpdateMode.value ? 'update' : 'store')
393
- const isSingleSelectedItem = computed<boolean>(() => selected.value.length === 1)
394
- const firstSelectedItem = computed(() => selected.value[0] as MDtItem)
395
- const hasSelectedItem = computed<boolean>(() => selected.value.length > 0)
396
-
397
- /* Titles */
398
- const getShowTitle = computed(() => {
399
- if (serviceName.value && typeof serviceName.value !== 'function') {
400
- const c = pascalCase(pluralize(serviceName.value.split('/').pop()))
401
- return __('replace.show_details', { name: __(`choice.${c}`, 1) })
402
- }
403
- return __('show_details')
404
- })
405
- const getFormTitle = computed(() => {
406
- const name = serviceName.value && typeof serviceName.value !== 'function' ? __(`choice.${pascalCase(pluralize(
407
- serviceName.value.split(
408
- '/').pop()))}`, 1) : ''
409
- return __(`replace.${formMode.value}`, { name })
410
- })
411
- const isGrid = computed(() => {
412
- if (props.grid !== undefined) {
413
- return props.grid
414
- }
415
- return $q.screen.lt.md
416
- })
417
- /* Titles */
418
-
419
- /** Methods */
420
- const getMythApiServicesSchema = (): MDtMythApiServicesSchema => {
421
- if (typeof serviceName.value === 'function') {
422
- return serviceName.value() as MDtMythApiServicesSchema
423
- }
424
- const c = api.value.services[serviceName.value]
425
- if (!c) {
426
- throw Error(`No Service: ${serviceName.value}`)
427
- }
428
- return c
429
- }
430
- const updateSelectedItems = (items: MDtItem[]) => {
431
- selected.value = items as any
432
- }
433
- const onScroll = ({ index, to }: any) => {
434
- if (index && to && index === to) {
435
- loadMore()
436
- }
437
- }
438
- const loadMore = () => {
439
- nextTick(() => {
440
- fetchDatatableItems({
441
- pagination: {
442
- ...pagination.value,
443
- page: (pagination.value.page ?? 0) + 1
444
- },
445
- filter: search.value
446
- })
447
- })
448
- }
449
- const refreshNoUpdate = (done?: () => void) => {
450
- if (contextmenu.value) {
451
- contextmenu.value = !1
452
- }
453
- meta.value = { ...initMetaServer }
454
- pagination.value.page = 1
455
- pagination.value.rowsNumber = 0
456
- getRows.value = []
457
- nextTick(() => {
458
- fetchDatatableItems({
459
- pagination: pagination.value,
460
- filter: search.value
461
- })
462
- if (done) {
463
- done()
464
- }
465
- })
466
- }
467
- const refresh = (done?: () => void) => refreshNoUpdate(done)
468
- const getRequestWith = (type: 'withIndex' | 'withShow' | 'withUpdate' | 'withStore'): string | null => {
469
- let v: any = []
470
- const params: { [k: string]: string } & string | (() => string | object) = props[type] as any
471
- if (params) {
472
- if (typeof params === 'string') {
473
- v = params.split(',')
474
- }
475
-
476
- if (lodash.isArray(params)) {
477
- v = [...params]
478
- } else if (lodash.isObject(params) && typeof params !== 'function') {
479
- let e
480
- for (const k in params) {
481
- e = params[k]
482
- v.push(`${k}=${e}`)
483
- }
484
- } else if (lodash.isFunction(params)) {
485
- const f = params()
486
- v = typeof f === 'string' ? f.split(',') : f
487
- }
488
- }
489
- return v.join(',') ?? null
490
- }
491
- const getDatatableParams = ({
492
- pagination,
493
- filter
494
- }: FetchRowsArgs = {}, merge: Partial<ApiServiceParams> = {}): ApiServiceParams => {
495
- const headerItems = getHeaders.value.map((e: any) => e.name).join(',')
496
- // console.log(headerItems)
497
- let params: ApiServiceParams = {
498
- headerItems,
499
- indexType: 'index',
500
- fdt: 'i',
501
- itemsPerPage: pagination?.rowsPerPage === 0 ? -1 : (pagination?.rowsPerPage !== undefined ? pagination?.rowsPerPage : 0),
502
- page: pagination?.page !== undefined ? pagination.page : 0,
503
- sortBy: pagination?.sortBy !== undefined ? pagination.sortBy : undefined,
504
- sortDesc: !pagination?.sortBy ? undefined : (pagination?.descending === !0 ? 1 : (pagination?.descending === !1 ? 0 : undefined))
505
- }
506
- if (filter) {
507
- params.search = filter
508
- }
509
- if (Object.keys(filterForm.value).length > 0) {
510
- const TempFilter = { ...filterForm.value } as any
511
- for (const fKey in TempFilter) {
512
- if (lodash.isArray(TempFilter[fKey])) {
513
- TempFilter[fKey] = TempFilter[fKey].map((elm: any) => {
514
- if (elm.id) {
515
- return elm.id
516
- } else if (elm.value) {
517
- return elm.value
518
- }
519
- return elm
520
- })
521
- } else if (lodash.isPlainObject(TempFilter[fKey])) {
522
- if (TempFilter[fKey].id) {
523
- TempFilter[fKey] = TempFilter[fKey].id
524
- } else if (TempFilter[fKey].value) {
525
- TempFilter[fKey] = TempFilter[fKey].value
526
- }
527
- }
528
- }
529
- // console.log(JSON.stringify(filterForm.value))
530
- // params.filter = filterForm.value
531
- // console.log(TempFilter)
532
- params.filter = TempFilter
533
- }
534
- if (searchColumnsRef.value.length > 0) {
535
- params.searchColumns = searchColumnsRef.value.join(',')
536
- }
537
- if (props.requestParams) {
538
- if (typeof props.requestParams === 'function') {
539
- params = props.requestParams(params) as ApiServiceParams
540
- } else {
541
- params = {
542
- ...params,
543
- ...props.requestParams
544
- }
545
- }
546
- }
547
- return { ...params, ...merge }
548
- }
549
- const fetchDatatableItems = (opts: FetchRowsArgs = {}) => {
550
- if (props.endReach && meta.value.last_page && pagination.value.page >= meta.value.last_page) {
551
- return
552
- }
553
- if (loading.value || !serviceName.value) return
554
- loading.value = !0
555
- selected.value = []
556
- nextTick(() => {
557
- const params = getDatatableParams(opts)
558
- const requestWith = getRequestWith('withIndex')
559
- if (requestWith) {
560
- params.requestWith = requestWith
561
- }
562
- // console.log({ params })
563
- getMythApiServicesSchema().index({ params })
564
- .then((result: any) => {
565
- const { _data, _meta } = result
566
- pagination.value = {
567
- page: parseInt((_meta?.current_page || 1).toString()) || 1,
568
- rowsPerPage: parseInt(_meta?.per_page) || 0,
569
- rowsNumber: parseInt((_meta?.total || 0).toString()) || 0,
570
- sortBy: opts?.pagination?.sortBy || undefined,
571
- descending: opts?.pagination?.descending || undefined
572
- }
573
- _meta && (meta.value = _meta)
574
- if (props.endReach) {
575
- getRows.value = [...getRows.value, ...(_data || [])]
576
- } else {
577
- getRows.value = _data || []
578
- }
579
- })
580
- .catch((e) => {
581
- // console.log(e)
582
- if (e?.response?.status === 401) {
583
- logoutDatatable()
584
- return e
585
- }
586
- if (e?._message) {
587
- alertError(e._message)
588
- } else if (e?.message) {
589
- alertError(e.message)
590
- }
591
- })
592
- .finally(() => {
593
- loading.value = !1
594
- })
595
- })
596
- }
597
- const exportData = (type: MDtExportOptions) => {
598
- if (loading.value) {
599
- return
600
- }
601
- const ex = async () => {
602
- loading.value = !0
603
- const toBLob = exportToBlob.value === !0 || exportToBlob.value === type
604
- const headerItems = getHeaders.value.filter(e => e?.field !== props.controlKey && visibleHeaders.value.indexOf(e.name) !== -1)
605
- const data = getDatatableParams({
606
- pagination: pagination.value,
607
- filter: search.value
608
- }, {
609
- indexType: type,
610
- fdt: 'e',
611
- toUrl: toBLob === !0 ? !1 : exportToBlob.value !== type,
612
- headerItems
613
- })
614
- if (selected.value.length > 0) {
615
- data.ids = selected.value.map((e: any) => e.id)
616
- }
617
- // console.log(3)
618
- const config: AxiosRequestConfig = {}
619
- if (toBLob) {
620
- config.responseType = 'blob'
621
- }
622
- getMythApiServicesSchema().export(data, config)
623
- .then(async (response) => {
624
- const { _message } = response || {}
625
- _message && (alertSuccess(_message))
626
- try {
627
- await downloadFromResponse(response)
628
- } catch (e: any) {
629
- if (response.status === 200 && response.headers['content-type'] === 'application/json') {
630
- return response
631
- }
632
- if (e?.code) {
633
- alertError(__(`messages.${e.code}`))
634
- } else if (e?.message) {
635
- alertError(e.message)
636
- }
637
- console.log(e)
638
- }
639
- return response
640
- })
641
- .catch((e) => {
642
- alertError(e?._message || e?.message || 'Error')
643
- })
644
- .finally(() => {
645
- loading.value = !1
646
- })
647
- }
648
- if (!selected.value.length) {
649
- confirmMessage(__('messages.export_all')).onOk(() => ex())
650
- } else {
651
- ex()
652
- }
653
- }
654
- /** Methods */
655
-
656
- const openDialogTimeout = 100
657
- /**
658
- * Filter Dialog
659
- */
660
- const openFilterDialog = () => {
661
- resetDialogForm({ values: {}, errors: {} }, { force: !0 })
662
- nextTick(() => {
663
- tempFilterForm.value = { ...filterForm.value }
664
- dialogs.filter = !0
665
- })
666
- }
667
- const saveFilterDialog = () => {
668
- dialogs.filter = !1
669
- nextTick(() => (filterForm.value = { ...tempFilterForm.value }))
670
- }
671
- const closeFilterDialog = () => {
672
- dialogs.filter = !1
673
- tempFilterForm.value = { ...filterForm.value }
674
- }
675
- const onRemoveFilter = (key: string | number) => {
676
- const filter = filterForm.value
677
- delete filter[key]
678
- filterForm.value = { ...filter }
679
- if (route.query[key]) {
680
- const query = { ...route.query }
681
- delete query[key]
682
- router.push({ query })
683
- }
684
- }
685
- const updateFilterOptions = (data: Record<string, any>) => {
686
- filterForm.value = {
687
- ...filterForm.value,
688
- ...data
689
- }
690
- }
691
- /**
692
- * Filter Dialog
693
- */
694
-
695
- /**
696
- * Show Dialog
697
- */
698
- const openShowDialogNoIndex = async (i: MDtItem) => {
699
- const item = toRef(i)
700
- const index = getRows.value.findIndex(e => e.id === item.value.id)
701
- return openShowDialog(item.value, index)
702
- }
703
- const openShowDialog = async (i: MDtItem, index: MDtItemIndex) => {
704
- const fdt = 's'
705
- const item = toRef(i)
706
- if (props.showQueryParams) {
707
- router.push({ query: { ...route.query, id: item.value.id, fdt } })
708
- return
709
- }
710
- if (props.showRoute) {
711
- if (typeof props.showRoute === 'string') {
712
- router.push({ name: props.showRoute, params: { id: item.value.id }, query: route.query })
713
- } else {
714
- router.push(props.showRoute)
715
- }
716
- return
717
- }
718
- if (loading.value) {
719
- return
720
- }
721
- loading.value = !0
722
- const params: any = { fdt }
723
- if (getRequestWith('withShow')) {
724
- params.requestWith = getRequestWith('withShow')
725
- }
726
-
727
- getMythApiServicesSchema().show(item.value.id, { params })
728
- .then(({ _data }) => {
729
- dialogs.item = _data
730
- dialogs.index = index
731
- getRows.value[index as any] = _data as any
732
- nextTick(() => setTimeout(() => (selected.value = [getRows.value[index] as any]), openDialogTimeout))
733
- setTimeout(() => (dialogs.show = !0), openDialogTimeout)
734
- })
735
- .catch((e: any) => {
736
- const message = e?._message || e?.message
737
- message && alertError(message)
738
- })
739
- .finally(() => (loading.value = !1))
740
- }
741
- const closeShowDialog = () => {
742
- dialogs.show = !1
743
- dialogs.item = undefined
744
- dialogs.index = undefined
745
- }
746
- /**
747
- * Show Dialog
748
- */
749
-
750
- /**
751
- * Form Dialog
752
- */
753
- const updateRouteProp = computed(() => props.updateRoute)
754
- const openUpdateDialogNoIndex = (i: MDtItem) => {
755
- const item = toRef(i)
756
- const index = getRows.value.findIndex(e => e.id === item.value.id)
757
- return openUpdateDialog(item.value, index)
758
- }
759
- const openUpdateDialog = (i: MDtItem, index: MDtItemIndex) => {
760
- const fdt = 'u'
761
- const item = { ...toValue(i) }
762
- if (props.updateQueryParams) {
763
- router.push({ query: { ...route.query, id: item.id, fdt } })
764
- return
765
- }
766
- if (updateRouteProp.value) {
767
- if (typeof updateRouteProp.value === 'string') {
768
- router.push({ name: updateRouteProp.value, params: { id: item.id }, query: route.query })
769
- } else {
770
- router.push(updateRouteProp.value)
771
- }
772
- return
773
- }
774
- if (loading.value) {
775
- return
776
- }
777
- loading.value = !0
778
- isUpdateMode.value = !0
779
- const params: any = { fdt }
780
- if (getRequestWith('withUpdate')) {
781
- params.requestWith = getRequestWith('withUpdate')
782
- }
783
- getMythApiServicesSchema().show(item.id, { params })
784
- .then(({ _data }) => {
785
- dialogs.item = _data
786
- dialogs.index = index
787
- if (_data) {
788
- getRows.value[index] = { ..._data } as any
789
- nextTick(() => setTimeout(() => (selected.value = [getRows.value[index] as any]), openDialogTimeout))
790
- }
791
- setTimeout(() => {
792
- resetVeeForm(_data)
793
- nextTick(() => {
794
- dialogs.form = !0
795
- })
796
- }, openDialogTimeout)
797
- })
798
- .catch((e: any) => {
799
- const message = e?._message || e?.message
800
- message && alertError(message)
801
- })
802
- .finally(() => (loading.value = !1))
803
- }
804
- const openCreateDialog = (dtItem?: MDtItem) => {
805
- const fdt = 'c'
806
- if (props.storeQueryParams) {
807
- router.push({ query: { ...route.query, id: undefined, fdt } })
808
- return
809
- }
810
- if (props.storeRoute) {
811
- if (typeof props.storeRoute === 'string') {
812
- router.push({ name: props.storeRoute, query: route.query })
813
- } else {
814
- router.push(props.storeRoute)
815
- }
816
- return
817
- }
818
- isUpdateMode.value = !1
819
- dialogs.item = { ...defaultItem.value, ...dtItem } as MDtItem
820
- dialogs.index = undefined
821
- setTimeout(() => {
822
- resetVeeForm(dtItem)
823
- dialogs.form = !0
824
- }, openDialogTimeout)
825
- }
826
- const closeFormDialog = () => {
827
- dialogs.form = !1
828
- isUpdateMode.value = !1
829
- dialogs.item = undefined
830
- dialogs.index = undefined
831
- setTimeout(() => resetVeeForm(), openDialogTimeout)
832
- }
833
- /**
834
- * Form Dialog
835
- */
836
-
837
- const updateDatatableItem = (i: MDtItem, index?: MDtItemIndex) => {
838
- const item = { ...toValue(i) }
839
- if (item) {
840
- if (index !== undefined) {
841
- getRows.value[index] = item
842
- } else {
843
- const findIndex = getRows.value.findIndex(e => parseInt(e.id?.toString?.() ?? '') === parseInt(item?.id?.toString?.() ?? ''))
844
- if (findIndex >= 0) {
845
- getRows.value[findIndex] = item
846
- }
847
- }
848
- selected.value.length === 1 && updateSelectedItems([item])
849
- }
850
- }
851
- const removeDtItem = (i: MDtItem | number) => {
852
- const item = toRef<MDtItem | number>(i)
853
- const id: string | number = typeof item.value !== 'object' ? item.value : item.value.id as string
854
- if (typeof item.value !== 'object') {
855
- getRows.value = getRows.value.filter((e, i) => i !== id)
856
- } else {
857
- getRows.value = getRows.value.filter((e) => parseInt(e.id?.toString() ?? '') !== parseInt(id.toString()))
858
- }
859
- }
860
- const ignoreKeysProps = computed(() => props.ignoreKeys)
861
283
 
862
284
  const formDialogCartSection = ref<InstanceType<typeof QCardSection> | null>(null)
863
285
  const onSuccess: SubmissionHandler = async (form) => {
@@ -899,7 +321,7 @@ const onSuccess: SubmissionHandler = async (form) => {
899
321
  requestWith: getRequestWith(isUpdateMode.value ? 'withUpdate' : 'withStore') || undefined
900
322
  }
901
323
  }
902
- const method = async () => isUpdateMode.value ? await apiServices.update(dialogs.item?.id || '',
324
+ const method = async () => isUpdateMode.value ? await apiServices.update(dialogItem.value?.id || '',
903
325
  form,
904
326
  _conf) : await apiServices.store(form, _conf)
905
327
  try {
@@ -908,7 +330,7 @@ const onSuccess: SubmissionHandler = async (form) => {
908
330
  if (_success) {
909
331
  if (isUpdateMode.value) {
910
332
  if (_data) {
911
- updateDatatableItem(_data, dialogs.index)
333
+ updateDatatableItem(_data, dialogItemIndex.value)
912
334
  }
913
335
  } else {
914
336
  setTimeout(() => refresh(), openDialogTimeout)
@@ -918,7 +340,7 @@ const onSuccess: SubmissionHandler = async (form) => {
918
340
  }
919
341
  } catch (e: any) {
920
342
  const { _message, _errors } = e || {}
921
- dialogs.errors = _errors || {}
343
+ dialogErrors.value = _errors || {}
922
344
  scrollToElementFromErrors(_errors, undefined, '.m--datatable__dialog-form-container')
923
345
  _message && alertError(_message)
924
346
  if (_errors) {
@@ -937,195 +359,7 @@ const onInvalidSubmit: InvalidSubmissionHandler = ({ errors }) => {
937
359
  }
938
360
  const defaultSubmitItem = handleSubmit.withControlled(onSuccess, onInvalidSubmit)
939
361
 
940
- const hideAutoMessage = computed(() => props.hideAutoMessage)
941
- const onDeleteItem = (i: MDtItem, index: number) => {
942
- const item = toRef(i)
943
- if (loading.value || !item.value?.id) {
944
- return
945
- }
946
- hasAction.value = !0
947
- confirmMessage(__('messages.confirm_delete')).onOk(async () => {
948
- loading.value = !0
949
- try {
950
- const { _message, _success } = await getMythApiServicesSchema().destroy(item.value.id)
951
- if (!hideAutoMessage.value && _success && _message) {
952
- _message && alertSuccess(_message)
953
- }
954
- if (_success) {
955
- if (pagination.value.rowsNumber !== undefined) {
956
- --pagination.value.rowsNumber
957
- selected.value = []
958
- }
959
- removeDtItem(index)
960
- }
961
- } catch (e: any) {
962
- e?._message && alertError(e._message)
963
- } finally {
964
- loading.value = !1
965
- }
966
- }).onDismiss(() => {
967
- hasAction.value = !1
968
- })
969
- }
970
- const deleteSelectionItem = () => {
971
- if (!selected.value.length) return
972
- if (loading.value || !selected.value.length) {
973
- return
974
- }
975
- if (selected.value.length === 1) {
976
- const dtItem = selected.value[0] as MDtItem
977
- const index = getRows.value.findIndex((e: any) => parseInt(e.id) === parseInt(dtItem?.id?.toString() || ''))
978
- return onDeleteItem(dtItem, index)
979
- }
980
- if (!props.multiDestroy) {
981
- return
982
- }
983
- hasAction.value = !0
984
- confirmMessage(__('messages.confirm_delete')).onOk(async () => {
985
- loading.value = !0
986
- try {
987
- const {
988
- _message,
989
- _success
990
- } = await getMythApiServicesSchema().destroyAll(selected.value.map((e: MDtItem) => e.id))
991
- if (!hideAutoMessage.value && _success && _message) {
992
- _message && alertSuccess(_message)
993
- }
994
- if (_success) {
995
- refresh()
996
- }
997
- } catch (e: any) {
998
- e?._message && alertError(e._message)
999
- } finally {
1000
- loading.value = !1
1001
- nextTick()
1002
- selected.value = []
1003
- }
1004
- }).onDismiss(() => {
1005
- hasAction.value = !1
1006
- })
1007
- }
1008
- const logoutDatatable = () => {
1009
- //
1010
- }
1011
- /**
1012
- * ---
1013
- */
1014
-
1015
- /**
1016
- * Dom
1017
- */
1018
- const contextmenu = ref(!1)
1019
- const onRowContextmenu = (e: MouseEvent | Event, row: MDtItem, index: number | undefined) => {
1020
- e.preventDefault?.()
1021
- row = toValue(row)
1022
- if (index === dialogs.index) {
1023
- selected.value = []
1024
- dialogs.item = undefined
1025
- dialogs.index = undefined
1026
- if (contextmenu.value) {
1027
- contextmenu.value = !1
1028
- }
1029
- return
1030
- }
1031
- selected.value = [row]
1032
- dialogs.item = row
1033
- dialogs.index = index
1034
- if (isGrid.value) {
1035
- contextmenu.value = !0
1036
- }
1037
- }
1038
- const contextmenuItems = computed<any>(() => ([
1039
- {
1040
- name: 'show',
1041
- label: pluginOptions.value?.dt?.contextmenu?.btnStyle?.showLabel ? 'labels.show' : undefined,
1042
- click: (item: MDtItem, index: MDtItemIndex) => {
1043
- openShowDialog(item, index)
1044
- },
1045
- showIf: hasShowBtn.value,
1046
- order: 100
1047
- },
1048
- {
1049
- name: 'clone',
1050
- label: pluginOptions.value?.dt?.contextmenu?.btnStyle?.showLabel ? 'labels.clone' : undefined,
1051
- click: onCloneItem,
1052
- showIf: hasCloneBtn.value,
1053
- order: 200
1054
- },
1055
- {
1056
- name: 'update',
1057
- label: pluginOptions.value?.dt?.contextmenu?.btnStyle?.showLabel ? 'labels.update' : undefined,
1058
- click: (item: MDtItem, index: MDtItemIndex) => {
1059
- openUpdateDialog(item, index)
1060
- },
1061
- showIf: hasUpdateBtn.value,
1062
- order: 300
1063
- },
1064
- {
1065
- name: 'destroy',
1066
- label: pluginOptions.value?.dt?.contextmenu?.btnStyle?.showLabel ? 'labels.destroy' : undefined,
1067
- click: (item: MDtItem, index: MDtItemIndex) => {
1068
- selected.value = [item]
1069
- onDeleteItem(item, index)
1070
- },
1071
- showIf: hasDestroyBtn.value,
1072
- attr: {
1073
- color: 'negative'
1074
- },
1075
- order: 400
1076
- },
1077
- ...(props.contextItems || [])
1078
- ].sort((a, b) => (a.order ?? 0) - (b.order ?? 0))))
1079
- const onCloneItem = (item: MDtItem) => {
1080
- item = toValue(item)
1081
- confirmMessage()
1082
- .onOk(() => {
1083
- $q.loading.show()
1084
- getMythApiServicesSchema().clone(item.id)
1085
- .then(({ _message }) => {
1086
- _message && alertSuccess(_message)
1087
- refreshNoUpdate()
1088
- })
1089
- .catch(({ _message }) => {
1090
- _message && alertError(_message)
1091
- })
1092
- .finally(() => {
1093
- $q.loading.hide()
1094
- })
1095
- })
1096
- }
1097
- const endReach = computed<boolean>(() => Boolean(props.endReach))
1098
- const rowsPerPageOptions = computed(() => props.rowsPerPageOptions)
1099
- const getRowsPerPageOptions = computed<any[]>(() => endReach.value ? [0] : (rowsPerPageOptions.value || [0]))
1100
-
1101
- /**
1102
- * Image Dialog Start.
1103
- */
1104
- const imageDialog = reactive<MDatatableScope['imageDialog']>({
1105
- value: !1,
1106
- src: undefined,
1107
- asAttachment: undefined
1108
- })
1109
- const openImageDialog = (src: string, opts?: { asAttachment?: boolean }) => {
1110
- imageDialog.src = src
1111
- imageDialog.asAttachment = opts?.asAttachment
1112
- nextTick(() => {
1113
- imageDialog.value = !0
1114
- })
1115
- }
1116
- const closeImageDialog = () => {
1117
- imageDialog.value = !1
1118
- nextTick(() => {
1119
- imageDialog.src = undefined
1120
- imageDialog.asAttachment = undefined
1121
- })
1122
- }
1123
- /**
1124
- * Image Dialog End.
1125
- */
1126
-
1127
362
  onMounted(() => refresh())
1128
-
1129
363
  watch(loading, v => {
1130
364
  if (pluginOptions.value?.dt?.useQuasarLoading) {
1131
365
  if (v) {
@@ -1139,42 +373,15 @@ watch(loading, v => {
1139
373
  watch([filterForm, () => $q.lang.nativeName], () => refreshNoUpdate(), { deep: !0 })
1140
374
  watch(formDialogModel, (v) => {
1141
375
  if (!v) {
1142
- dialogs.errors = {}
376
+ dialogErrors.value = {}
1143
377
  }
1144
378
  })
1145
379
 
1146
- const datatableItemsScope = reactive({
1147
- openShowDialog,
1148
- openShowDialogNoIndex,
1149
- closeShowDialog,
1150
- openUpdateDialog,
1151
- openUpdateDialogNoIndex,
1152
- openCreateDialog,
1153
- closeFormDialog,
1154
- onDeleteItem,
1155
- refresh,
1156
- refreshNoUpdate,
1157
- tableOptions,
1158
- isSingleSelectedItem,
1159
- firstSelectedItem,
1160
- updateDatatableItem,
1161
- updateSelectedItems,
1162
- imageDialog,
1163
- openImageDialog,
1164
- closeImageDialog
1165
- })
1166
-
1167
- const getShowSelection = computed<boolean | undefined>(() => {
1168
- if (props.hideSelection) {
1169
- return !1
1170
- }
1171
- return props.showSelection
1172
- })
1173
- const defaultTopBtnProps: any = {
1174
- dense: !0,
1175
- flat: !0
1176
- }
1177
380
  const table = ref<InstanceType<typeof QTable>>()
381
+ defineOptions({
382
+ name: 'MDatatable',
383
+ inheritAttrs: !1
384
+ })
1178
385
  defineExpose({
1179
386
  resetDialogs,
1180
387
  tableOptions,
@@ -1208,37 +415,6 @@ defineExpose({
1208
415
  openImageDialog,
1209
416
  closeImageDialog
1210
417
  })
1211
-
1212
- const getProp = computed(() => (k: keyof Props) => {
1213
- if (props[k] !== undefined) {
1214
- return props[k]
1215
- }
1216
- if (pluginOptions.value.datatable?.[k] !== undefined) {
1217
- return pluginOptions.value.datatable?.[k]
1218
- }
1219
- return props[k]
1220
- })
1221
- const componentSlots = useSlots()
1222
- const skipSlots = ['default', 'top', 'title']
1223
- const getSlots = computed(() => {
1224
- const keys = Object.keys(componentSlots || {})
1225
- return keys.filter(e => !skipSlots.includes(e))
1226
- })
1227
-
1228
- const onClickTopMenu = (item: any) => {
1229
- if (item.multiClick && selected.value.length > 1) {
1230
- item.multiClick(selected.value)
1231
- return
1232
- }
1233
-
1234
- if (item.click) {
1235
- item.click(selected.value[0], 0)
1236
- }
1237
- }
1238
- defineOptions({
1239
- name: 'MDatatable',
1240
- inheritAttrs: !1
1241
- })
1242
418
  </script>
1243
419
 
1244
420
  <template>
@@ -1261,7 +437,7 @@ defineOptions({
1261
437
  v-bind="pluginOptions.dt?.contextmenu?.menu"
1262
438
  >
1263
439
  <q-list
1264
- v-if="dialogs.item"
440
+ v-if="dialogItem"
1265
441
  :separator="!isSmall"
1266
442
  style="min-width: 280px;"
1267
443
  v-bind="pluginOptions.dt?.contextmenu?.list"
@@ -1271,13 +447,13 @@ defineOptions({
1271
447
  :key="i"
1272
448
  >
1273
449
  <MDtBtn
1274
- v-if="typeof contextmenuItem.showIf === 'function' ? contextmenuItem.showIf(dialogs.item,dialogs.index) : contextmenuItem.showIf"
450
+ v-if="typeof contextmenuItem.showIf === 'function' ? contextmenuItem.showIf(dialogItem,dialogItemIndex) : contextmenuItem.showIf"
1275
451
  :[contextmenuItem.name]="!0"
1276
452
  :dense="dense === undefined ? (theme.buttons.dense !== undefined ? theme.buttons.dense : pluginOptions.datatable?.dense) : dense"
1277
453
  :label="contextmenuItem.contextLabel !== undefined ? (contextmenuItem.contextLabel === null ? undefined : __(contextmenuItem.contextLabel)) : __(contextmenuItem.label || contextmenuItem.name) "
1278
454
  list-item
1279
455
  v-bind="contextmenuItem.attr"
1280
- @click="contextmenuItem.click ? contextmenuItem.click(dialogs.item,dialogs.index) : undefined"
456
+ @click="contextmenuItem.click ? contextmenuItem.click(dialogItem,dialogItemIndex) : undefined"
1281
457
  />
1282
458
  </template>
1283
459
  </q-list>
@@ -1308,13 +484,13 @@ defineOptions({
1308
484
  v-bind="{
1309
485
  virtualScroll: !0,
1310
486
  wrapCells:!0,
1311
- ...pluginOptions.datatable,
1312
- ...$attrs,
487
+ ...pluginOptions.datatable as any,
488
+ ...$attrs as any,
1313
489
  title: getTableTitle,
1314
490
  bordered: bordered === undefined ? pluginOptions.datatable?.bordered : bordered,
1315
491
  dense: dense === undefined ? ( theme.inputs.dense !== undefined ? theme.inputs.dense : pluginOptions.datatable?.dense) : dense,
1316
492
  flat: flat === undefined ? pluginOptions.datatable?.flat : flat,
1317
- }"
493
+ } as any"
1318
494
  @request="fetchDatatableItems"
1319
495
  @update:selected="onUpdateSelectedItems"
1320
496
  @virtual-scroll="endReach ? onScroll : undefined"
@@ -1508,7 +684,7 @@ defineOptions({
1508
684
  name="top-search"
1509
685
  />
1510
686
  <MInput
1511
- v-if="!hideSearch && !dialogs.form"
687
+ v-if="!hideSearch && !formDialogModel"
1512
688
  v-model="search"
1513
689
  :debounce="searchDebounce"
1514
690
  :dense="dense === undefined ? (pluginOptions.datatable?.dense !== undefined ? pluginOptions.datatable?.dense : !0) : dense"
@@ -1618,7 +794,9 @@ defineOptions({
1618
794
  v-bind="{...defaultTopBtnProps,...pluginOptions.dt?.buttons?.filter}"
1619
795
  @click="exportData('pdf')"
1620
796
  >
1621
- <q-tooltip>{{ __('myth.titles.exportPdf') }}</q-tooltip>
797
+ <q-tooltip class="m--dt-btn-tooltip">
798
+ {{ __('myth.titles.exportPdf') }}
799
+ </q-tooltip>
1622
800
  </MDtBtn>
1623
801
 
1624
802
  <!-- Export Excel-->
@@ -1629,7 +807,9 @@ defineOptions({
1629
807
  v-bind="{...defaultTopBtnProps,...pluginOptions.dt?.buttons?.filter}"
1630
808
  @click="exportData('excel')"
1631
809
  >
1632
- <q-tooltip>{{ __('myth.titles.exportExcel') }}</q-tooltip>
810
+ <q-tooltip class="m--dt-btn-tooltip">
811
+ {{ __('myth.titles.exportExcel') }}
812
+ </q-tooltip>
1633
813
  </MDtBtn>
1634
814
 
1635
815
  <!-- Filter dialog -->
@@ -1989,7 +1169,7 @@ defineOptions({
1989
1169
 
1990
1170
  <!-- Show Dialog -->
1991
1171
  <MDialog
1992
- v-model="dialogs.show"
1172
+ v-model="showDialogModel"
1993
1173
  v-bind="pluginOptions.dt?.showDialogProps"
1994
1174
  >
1995
1175
  <q-card class="m--dialog-card">
@@ -2041,7 +1221,7 @@ defineOptions({
2041
1221
 
2042
1222
  <!-- Form Dialog -->
2043
1223
  <MDialog
2044
- v-model="dialogs.form"
1224
+ v-model="formDialogModel"
2045
1225
  v-bind="pluginOptions.dt?.formDialogProps"
2046
1226
  >
2047
1227
  <div class="m--form__container full-height no-wrap">
@@ -2067,7 +1247,7 @@ defineOptions({
2067
1247
  name="form-title"
2068
1248
  >
2069
1249
  <q-toolbar-title>
2070
- <template v-if="loading && !dialogs.item">
1250
+ <template v-if="loading && !dialogItem">
2071
1251
  <q-skeleton width="200px" />
2072
1252
  </template>
2073
1253
  <template v-else>
@@ -2101,7 +1281,7 @@ defineOptions({
2101
1281
  class="scroll m--datatable__dialog-form-container"
2102
1282
  >
2103
1283
  <MContainer
2104
- v-if="loading && !dialogs.item"
1284
+ v-if="loading && !dialogItem"
2105
1285
  :fluid="!1"
2106
1286
  >
2107
1287
  <MRow