@mythpe/quasar-ui-qui 0.0.25-dev → 0.0.26-dev
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/form/MAxios.vue +141 -0
- package/src/components/form/MForm.vue +8 -8
- package/src/components/form/MPassword.vue +73 -0
- package/src/components/form/index.ts +4 -0
- package/src/components/grid/MBlock.vue +0 -1
- package/src/composable/useMyth.ts +252 -244
- package/src/types/api-helpers.d.ts +5 -2
- package/src/types/components.d.ts +107 -25
- package/src/types/index.d.ts +2 -0
- package/src/utils/Helpers.ts +3 -24
- package/src/utils/myth.ts +7 -2
- package/src/utils/vue-plugin.ts +7 -0
package/package.json
CHANGED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
- MyTh Ahmed Faiz Copyright © 2016-2024 All rights reserved.
|
|
3
|
+
- Email: mythpe@gmail.com
|
|
4
|
+
- Mobile: +966590470092
|
|
5
|
+
- Website: https://www.4myth.com
|
|
6
|
+
- Github: https://github.com/mythpe
|
|
7
|
+
-->
|
|
8
|
+
|
|
9
|
+
<script lang="ts" setup>
|
|
10
|
+
|
|
11
|
+
import type { MAxiosProps as Props, MSelectModelEmit } from '../../types'
|
|
12
|
+
import type { QSelectSlots } from 'quasar'
|
|
13
|
+
import { computed, onMounted, ref, toValue, watch } from 'vue'
|
|
14
|
+
import { useSetFieldValue } from 'vee-validate'
|
|
15
|
+
import MSelect from './MSelect.vue'
|
|
16
|
+
import { useMyth } from '../../composable'
|
|
17
|
+
|
|
18
|
+
type P = {
|
|
19
|
+
name: Props['name'];
|
|
20
|
+
label?: Props['label'];
|
|
21
|
+
placeholder?: Props['placeholder'];
|
|
22
|
+
viewMode?: Props['viewMode'];
|
|
23
|
+
viewModeValue?: Props['viewModeValue'];
|
|
24
|
+
service?: Props['service'];
|
|
25
|
+
guest?: Props['guest'];
|
|
26
|
+
requestWith?: Props['requestWith'];
|
|
27
|
+
params?: Props['params'];
|
|
28
|
+
lazy?: Props['lazy'];
|
|
29
|
+
useChoice?: Props['useChoice'];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const props = withDefaults(defineProps<P>(), {
|
|
33
|
+
name: () => '',
|
|
34
|
+
label: undefined,
|
|
35
|
+
placeholder: undefined,
|
|
36
|
+
viewMode: () => !1,
|
|
37
|
+
viewModeValue: undefined,
|
|
38
|
+
service: undefined,
|
|
39
|
+
guest: undefined,
|
|
40
|
+
requestWith: undefined,
|
|
41
|
+
params: () => () => ({}),
|
|
42
|
+
lazy: () => !1,
|
|
43
|
+
useChoice: undefined
|
|
44
|
+
})
|
|
45
|
+
const modelValue = defineModel<Props['modelValue']>({ required: !1, default: undefined })
|
|
46
|
+
type Emits = {
|
|
47
|
+
(e: 'model', value: MSelectModelEmit): void;
|
|
48
|
+
}
|
|
49
|
+
const emit = defineEmits<Emits>()
|
|
50
|
+
const search = defineModel<string>('search', { required: !1, default: '' })
|
|
51
|
+
const setFieldValue = useSetFieldValue(() => props.name)
|
|
52
|
+
const { alertError, api } = useMyth()
|
|
53
|
+
const loading = defineModel<Props['loading']>('loading', { required: !1, default: !1 })
|
|
54
|
+
const items = defineModel<Props['items']>('items', { required: !1, default: [] })
|
|
55
|
+
const isGuest = computed(() => {
|
|
56
|
+
const v = toValue(props.guest)
|
|
57
|
+
return v !== undefined && v !== null && v !== !1
|
|
58
|
+
})
|
|
59
|
+
const prepare = async (fromWatch = !1) => {
|
|
60
|
+
if (!props.service || loading.value) {
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
const method = typeof props.service === 'string'
|
|
64
|
+
? (isGuest.value ? api.value[props.service].staticIndex : api.value[props.service].index)
|
|
65
|
+
: props.service
|
|
66
|
+
if (!method) {
|
|
67
|
+
throw Error(`No service: ${props.service}`)
|
|
68
|
+
}
|
|
69
|
+
const params: any = {
|
|
70
|
+
requestWith: undefined,
|
|
71
|
+
search: search.value,
|
|
72
|
+
itemsPerPage: -1,
|
|
73
|
+
page: 1,
|
|
74
|
+
staticRequest: 1,
|
|
75
|
+
...(toValue(props.params) || {})
|
|
76
|
+
}
|
|
77
|
+
if (props.requestWith) {
|
|
78
|
+
params.requestWith = toValue(props.requestWith)
|
|
79
|
+
}
|
|
80
|
+
loading.value = !0
|
|
81
|
+
items.value = []
|
|
82
|
+
method({ params })
|
|
83
|
+
.then(({ _data }: any) => {
|
|
84
|
+
items.value = _data || []
|
|
85
|
+
})
|
|
86
|
+
.catch((e: any) => {
|
|
87
|
+
alertError(e?.message || 'An error occurred')
|
|
88
|
+
})
|
|
89
|
+
.finally(() => {
|
|
90
|
+
loading.value = !1
|
|
91
|
+
if (fromWatch) {
|
|
92
|
+
if (modelValue.value !== null && modelValue.value !== undefined) {
|
|
93
|
+
setFieldValue(undefined)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
}
|
|
98
|
+
const listeners = {
|
|
99
|
+
'update:search': prepare,
|
|
100
|
+
model: (v: MSelectModelEmit) => emit('model', v)
|
|
101
|
+
}
|
|
102
|
+
onMounted(() => {
|
|
103
|
+
if (!props.lazy) {
|
|
104
|
+
prepare()
|
|
105
|
+
}
|
|
106
|
+
})
|
|
107
|
+
watch(props.params, () => prepare(!0), { deep: !0 })
|
|
108
|
+
const input = ref<InstanceType<typeof MSelect> | null>(null)
|
|
109
|
+
defineExpose<{ input: typeof input }>({ input })
|
|
110
|
+
defineOptions({ name: 'MAxios', inheritAttrs: !1 })
|
|
111
|
+
</script>
|
|
112
|
+
|
|
113
|
+
<template>
|
|
114
|
+
<MSelect
|
|
115
|
+
ref="input"
|
|
116
|
+
v-model="modelValue"
|
|
117
|
+
v-model:loading="loading"
|
|
118
|
+
v-model:search="search"
|
|
119
|
+
:label="label"
|
|
120
|
+
:name="name"
|
|
121
|
+
:options="items"
|
|
122
|
+
:placeholder="placeholder"
|
|
123
|
+
:view-mode="viewMode"
|
|
124
|
+
:view-mode-value="viewModeValue"
|
|
125
|
+
axios-mode
|
|
126
|
+
no-filter
|
|
127
|
+
v-bind="$attrs"
|
|
128
|
+
v-on="listeners"
|
|
129
|
+
>
|
|
130
|
+
<template
|
|
131
|
+
v-for="(_,slot) in $slots as Readonly<QSelectSlots>"
|
|
132
|
+
:key="slot"
|
|
133
|
+
#[slot]="inputSlot"
|
|
134
|
+
>
|
|
135
|
+
<slot
|
|
136
|
+
:name="slot"
|
|
137
|
+
v-bind="inputSlot || {}"
|
|
138
|
+
/>
|
|
139
|
+
</template>
|
|
140
|
+
</MSelect>
|
|
141
|
+
</template>
|
|
@@ -18,11 +18,11 @@ interface P {
|
|
|
18
18
|
opts?: Props['opts'];
|
|
19
19
|
target?: Props['target'];
|
|
20
20
|
emitValues?: Props['emitValues'];
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
state?: Props['state'];
|
|
22
|
+
form?: Props['form'];
|
|
23
|
+
values?: Props['values'];
|
|
24
|
+
errors?: Props['errors'];
|
|
25
|
+
padding?: Props['padding'];
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
const props = withDefaults(defineProps<P>(), {
|
|
@@ -37,7 +37,7 @@ const props = withDefaults(defineProps<P>(), {
|
|
|
37
37
|
padding: undefined
|
|
38
38
|
})
|
|
39
39
|
const formScope = useForm<Record<string, any>>(props.opts)
|
|
40
|
-
const
|
|
40
|
+
const { __, scrollToElementFromErrors } = useMyth()
|
|
41
41
|
const scope = reactive(formScope)
|
|
42
42
|
const { handleSubmit, resetForm, setErrors, setValues } = scope
|
|
43
43
|
type Emits = {
|
|
@@ -48,8 +48,8 @@ const onSuccessSubmission: SubmissionHandler = async (values, ctx) => emit('subm
|
|
|
48
48
|
const onErrorSubmission: InvalidSubmissionHandler = ({ errors }) => {
|
|
49
49
|
const keys: any[] = Object.keys(errors)
|
|
50
50
|
if (keys.length) {
|
|
51
|
-
const message = errors[keys[0]] as string ||
|
|
52
|
-
|
|
51
|
+
const message = errors[keys[0]] as string || __('messages.the_given_data_was_invalid')
|
|
52
|
+
scrollToElementFromErrors({ [keys[0]]: [message] }, undefined, props.target)
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
const defaultSubmit = props.emitValues ? handleSubmit(onSuccessSubmission, onErrorSubmission) : handleSubmit.withControlled(onSuccessSubmission,
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
- MyTh Ahmed Faiz Copyright © 2016-2024 All rights reserved.
|
|
3
|
+
- Email: mythpe@gmail.com
|
|
4
|
+
- Mobile: +966590470092
|
|
5
|
+
- Website: https://www.4myth.com
|
|
6
|
+
- Github: https://github.com/mythpe
|
|
7
|
+
-->
|
|
8
|
+
|
|
9
|
+
<script
|
|
10
|
+
lang="ts"
|
|
11
|
+
setup
|
|
12
|
+
>
|
|
13
|
+
import type { MInputSlots, MPasswordProps as Props } from '../../types'
|
|
14
|
+
import MInput from './MInput.vue'
|
|
15
|
+
import { ref, useTemplateRef } from 'vue'
|
|
16
|
+
|
|
17
|
+
type P = {
|
|
18
|
+
name?: Props['name'];
|
|
19
|
+
icon?: Props['icon'];
|
|
20
|
+
noToggle?: Props['noToggle'];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
withDefaults(defineProps<P>(), {
|
|
24
|
+
name: () => '',
|
|
25
|
+
icon: () => !1,
|
|
26
|
+
noToggle: () => !1
|
|
27
|
+
})
|
|
28
|
+
const modelValue = defineModel<Props['modelValue']>({ required: !1, default: undefined })
|
|
29
|
+
const inputType = ref<'text' | 'password'>('password')
|
|
30
|
+
const togglePassword = () => {
|
|
31
|
+
inputType.value = inputType.value === 'text' ? 'password' : 'text'
|
|
32
|
+
}
|
|
33
|
+
const input = useTemplateRef<InstanceType<typeof MInput>>('input')
|
|
34
|
+
defineExpose<{ input: typeof input }>({ input })
|
|
35
|
+
defineOptions({
|
|
36
|
+
name: 'MPassword',
|
|
37
|
+
inheritAttrs: !1
|
|
38
|
+
})
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<template>
|
|
42
|
+
<MInput
|
|
43
|
+
ref="input"
|
|
44
|
+
v-model="modelValue"
|
|
45
|
+
:name="name"
|
|
46
|
+
v-bind="{...$attrs,type:inputType}"
|
|
47
|
+
>
|
|
48
|
+
<template
|
|
49
|
+
v-if="icon && !Boolean($slots.prepend)"
|
|
50
|
+
#prepend
|
|
51
|
+
>
|
|
52
|
+
<q-icon name="password" />
|
|
53
|
+
</template>
|
|
54
|
+
<template
|
|
55
|
+
v-if="!noToggle && !Boolean($slots.prepend)"
|
|
56
|
+
#append
|
|
57
|
+
>
|
|
58
|
+
<q-btn
|
|
59
|
+
:icon="'ion-ios-eye' + (inputType !== 'password' ? '-off' : '')"
|
|
60
|
+
flat
|
|
61
|
+
round
|
|
62
|
+
@click="togglePassword()"
|
|
63
|
+
/>
|
|
64
|
+
</template>
|
|
65
|
+
<template
|
|
66
|
+
v-for="(_,slot) in $slots as Readonly<MInputSlots>"
|
|
67
|
+
:key="slot"
|
|
68
|
+
#[slot]
|
|
69
|
+
>
|
|
70
|
+
<slot :name="slot" />
|
|
71
|
+
</template>
|
|
72
|
+
</MInput>
|
|
73
|
+
</template>
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* Github: https://github.com/mythpe
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import MAxios from './MAxios.vue'
|
|
9
10
|
import MAvatarViewer from './MAvatarViewer.vue'
|
|
10
11
|
import MBtn from './MBtn.vue'
|
|
11
12
|
import MCheckbox from './MCheckbox.vue'
|
|
@@ -22,12 +23,14 @@ import MInput from './MInput.vue'
|
|
|
22
23
|
import MInputFieldControl from './MInputFieldControl.vue'
|
|
23
24
|
import MInputLabel from './MInputLabel.vue'
|
|
24
25
|
import MMobile from './MMobile.vue'
|
|
26
|
+
import MPassword from './MPassword.vue'
|
|
25
27
|
import MPicker from './MPicker.vue'
|
|
26
28
|
import MRadio from './MRadio.vue'
|
|
27
29
|
import MSelect from './MSelect.vue'
|
|
28
30
|
import MTime from './MTime.vue'
|
|
29
31
|
|
|
30
32
|
export {
|
|
33
|
+
MAxios,
|
|
31
34
|
MAvatarViewer,
|
|
32
35
|
MBtn,
|
|
33
36
|
MCheckbox,
|
|
@@ -44,6 +47,7 @@ export {
|
|
|
44
47
|
MInputFieldControl,
|
|
45
48
|
MInputLabel,
|
|
46
49
|
MMobile,
|
|
50
|
+
MPassword,
|
|
47
51
|
MPicker,
|
|
48
52
|
MRadio,
|
|
49
53
|
MSelect,
|
|
@@ -10,8 +10,9 @@ import lodash from 'lodash'
|
|
|
10
10
|
import { useI18n } from 'vue-i18n'
|
|
11
11
|
import type { RouteLocationNormalizedLoaded } from 'vue-router'
|
|
12
12
|
import { copyToClipboard, Dialog, extend, QDialogOptions, QNotifyCreateOptions, useQuasar } from 'quasar'
|
|
13
|
-
import { Helpers, myth, Str } from '../utils'
|
|
13
|
+
import { Helpers, myth, Str, veeRules } from '../utils'
|
|
14
14
|
import type { MDtColumn, MDtHeadersParameter, ParseHeaderOptions, Vue3MAlertMessage, Vue3MAlertMessageOptions, Vue3MConfirmMessage } from '../types'
|
|
15
|
+
import { computed } from 'vue'
|
|
15
16
|
|
|
16
17
|
export const useMyth = () => {
|
|
17
18
|
const { t, te } = useI18n({ useScope: 'global' })
|
|
@@ -20,275 +21,282 @@ export const useMyth = () => {
|
|
|
20
21
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
21
22
|
// @ts-ignore
|
|
22
23
|
const __ = (key: any, ...rest: unknown[]) => !key ? '' : te(`attributes.${key}`) ? t(`attributes.${key}`, ...rest) : te(key) ? t(key, ...rest) : key
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
const getPageTitle = (route: RouteLocationNormalizedLoaded, number?: number | string): string => {
|
|
25
|
+
number = number || 2
|
|
26
|
+
number = parseInt(number.toString())
|
|
27
|
+
const defaultValue = ''
|
|
28
|
+
// Not is route
|
|
29
|
+
// No page title
|
|
30
|
+
if (!route) {
|
|
31
|
+
return defaultValue
|
|
31
32
|
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function alertMessage (opts: Vue3MAlertMessageOptions): Vue3MAlertMessage {
|
|
35
|
-
return q.notify(helpers.quasarNotifyOptions(opts))
|
|
36
|
-
}
|
|
37
33
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
number = number || 2
|
|
41
|
-
number = parseInt(number.toString())
|
|
42
|
-
const defaultValue = ''
|
|
43
|
-
// Not is route
|
|
44
|
-
// No page title
|
|
45
|
-
if (!route) {
|
|
46
|
-
return defaultValue
|
|
47
|
-
}
|
|
34
|
+
const routePath = route?.path?.toString() || null
|
|
35
|
+
const routeName = route?.name?.toString() || null
|
|
48
36
|
|
|
49
|
-
|
|
50
|
-
|
|
37
|
+
// Not is route
|
|
38
|
+
// No page title
|
|
39
|
+
if (!routePath || !routeName) {
|
|
40
|
+
return defaultValue
|
|
41
|
+
}
|
|
51
42
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
43
|
+
let lastRouteName = routeName.split('.').pop() || ''
|
|
44
|
+
if (lastRouteName === 'index') {
|
|
45
|
+
const s = routeName.split('.')
|
|
46
|
+
lastRouteName = s[s.length - 2] ?? lastRouteName
|
|
47
|
+
}
|
|
48
|
+
const pluralize = Str.pascalCase(lodash.pluralize(lastRouteName))
|
|
49
|
+
const singular = Str.pascalCase(lodash.singularize(lastRouteName))
|
|
50
|
+
const keys = lodash.filter(lodash.uniq([
|
|
51
|
+
`${lastRouteName}Page.title`,
|
|
52
|
+
`${lodash.camelCase(lastRouteName)}Page.title`,
|
|
53
|
+
`choice.${pluralize}`,
|
|
54
|
+
`choice.${singular}`,
|
|
55
|
+
`replace.${lastRouteName}_details`,
|
|
56
|
+
`replace.${lastRouteName}`,
|
|
57
|
+
pluralize,
|
|
58
|
+
lodash.snakeCase(pluralize),
|
|
59
|
+
singular,
|
|
60
|
+
lodash.snakeCase(singular)
|
|
61
|
+
]))
|
|
57
62
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const s = routeName.split('.')
|
|
61
|
-
lastRouteName = s[s.length - 2] ?? lastRouteName
|
|
62
|
-
}
|
|
63
|
-
const pluralize = Str.pascalCase(lodash.pluralize(lastRouteName))
|
|
64
|
-
const singular = Str.pascalCase(lodash.singularize(lastRouteName))
|
|
65
|
-
const keys = lodash.filter(lodash.uniq([
|
|
66
|
-
`${lastRouteName}Page.title`,
|
|
67
|
-
`${lodash.camelCase(lastRouteName)}Page.title`,
|
|
68
|
-
`choice.${pluralize}`,
|
|
69
|
-
`choice.${singular}`,
|
|
70
|
-
`replace.${lastRouteName}_details`,
|
|
71
|
-
`replace.${lastRouteName}`,
|
|
72
|
-
pluralize,
|
|
73
|
-
lodash.snakeCase(pluralize),
|
|
74
|
-
singular,
|
|
75
|
-
lodash.snakeCase(singular)
|
|
76
|
-
]))
|
|
63
|
+
let str: string | null = null
|
|
64
|
+
let k: string | any
|
|
77
65
|
|
|
78
|
-
|
|
79
|
-
|
|
66
|
+
if (te((k = `routes.${routeName}`)) && lodash.isString((str = t(k)))) {
|
|
67
|
+
return str
|
|
68
|
+
}
|
|
80
69
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
70
|
+
if (te((k = `routes.${routePath}`)) && lodash.isString((str = t(k)))) {
|
|
71
|
+
return str
|
|
72
|
+
}
|
|
84
73
|
|
|
85
|
-
|
|
86
|
-
|
|
74
|
+
for (const f in keys) {
|
|
75
|
+
if (!(k = keys[f])) {
|
|
76
|
+
continue
|
|
87
77
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
if (te(_modelChoiceKey)) {
|
|
102
|
-
const l = t(_modelChoiceKey, number as any)
|
|
103
|
-
const rep = lodash.singularize(n[n.length - 1]).toLocaleLowerCase()
|
|
104
|
-
const e = `replace.${rep}`
|
|
105
|
-
str = te(e) ? t(e, { name: l }) : null
|
|
106
|
-
} else {
|
|
107
|
-
const pop: string = k.split('.').pop() || ''
|
|
108
|
-
str = te(k) ? t(k, number as any, { [pop]: number }) : null
|
|
109
|
-
}
|
|
78
|
+
if (te && te(k) && lodash.isString(t(k))) {
|
|
79
|
+
if (lodash.startsWith(k, 'choice.')) {
|
|
80
|
+
const s = k.split('.')
|
|
81
|
+
const n = routeName.split('.')
|
|
82
|
+
if (s.length === 2 && n.length > 1) {
|
|
83
|
+
const model = n[n.length - 2]
|
|
84
|
+
const pluralizeModel = lodash.pluralize(lodash.pascalCase(model))
|
|
85
|
+
const _modelChoiceKey = `choice.${pluralizeModel}`
|
|
86
|
+
if (te(_modelChoiceKey)) {
|
|
87
|
+
const l = t(_modelChoiceKey, number as any)
|
|
88
|
+
const rep = lodash.singularize(n[n.length - 1]).toLocaleLowerCase()
|
|
89
|
+
const e = `replace.${rep}`
|
|
90
|
+
str = te(e) ? t(e, { name: l }) : null
|
|
110
91
|
} else {
|
|
111
92
|
const pop: string = k.split('.').pop() || ''
|
|
112
93
|
str = te(k) ? t(k, number as any, { [pop]: number }) : null
|
|
113
94
|
}
|
|
114
95
|
} else {
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
96
|
+
const pop: string = k.split('.').pop() || ''
|
|
97
|
+
str = te(k) ? t(k, number as any, { [pop]: number }) : null
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
const parents: string[] = routeName.split('.')
|
|
101
|
+
if (parents.length > 1) {
|
|
102
|
+
const e = `choice.${Str.pascalCase(lodash.pluralize(parents[parents.length - 2]))}`
|
|
103
|
+
str = te(e) ? t(k, { name: t(e, '1') }) : null
|
|
104
|
+
} else {
|
|
105
|
+
str = te(k) ? t(k, { name: '' }) : null
|
|
122
106
|
}
|
|
123
|
-
return str || defaultValue
|
|
124
107
|
}
|
|
108
|
+
return str || defaultValue
|
|
125
109
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
110
|
+
}
|
|
111
|
+
return defaultValue
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Custom transformer
|
|
115
|
+
* @param headers
|
|
116
|
+
* @param options
|
|
117
|
+
*/
|
|
118
|
+
const parseHeaders = (headers: MDtHeadersParameter, options: ParseHeaderOptions = {}): MDtColumn[] => {
|
|
119
|
+
const defaultOptions: Partial<ParseHeaderOptions> = {
|
|
120
|
+
controlKey: 'control',
|
|
121
|
+
// controlStyle: 'max-width: 150px',
|
|
122
|
+
align: 'center'
|
|
123
|
+
// sortable: !0
|
|
124
|
+
}
|
|
125
|
+
const opts = extend<ParseHeaderOptions>(!0, defaultOptions, options)
|
|
126
|
+
let control: string | undefined = defaultOptions.controlKey
|
|
127
|
+
let controlStyle: string | undefined = defaultOptions.controlStyle
|
|
128
|
+
if (opts.controlKey) {
|
|
129
|
+
control = opts.controlKey
|
|
130
|
+
delete opts.controlKey
|
|
131
|
+
}
|
|
132
|
+
if (opts.controlStyle) {
|
|
133
|
+
controlStyle = opts.controlStyle
|
|
134
|
+
delete opts.controlStyle
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const result: MDtColumn[] = []
|
|
138
|
+
|
|
139
|
+
headers.forEach((elm: string | MDtColumn | undefined) => {
|
|
140
|
+
if (typeof elm !== 'string' && !elm?.name) return elm
|
|
141
|
+
// Todo: will do this
|
|
142
|
+
let item: MDtColumn = typeof elm === 'string' ? {
|
|
143
|
+
name: elm as string,
|
|
144
|
+
label: elm as string,
|
|
145
|
+
field: elm as string
|
|
146
|
+
} : { ...elm }
|
|
147
|
+
item.name = item.name ?? ''
|
|
148
|
+
item.label = (item.label === undefined || item.label === null) ? item.name : item.label
|
|
149
|
+
item.field = (item.field === undefined || item.field === null) ? item.name : item.field
|
|
150
|
+
item = {
|
|
151
|
+
...item,
|
|
152
|
+
name: Str.strBefore(Str.strBefore(item.name), 'ToString'),
|
|
153
|
+
label: (item.label !== undefined && item.label !== null) ? Str.strBefore(Str.strBefore(item.label), 'ToString') : item.label
|
|
146
154
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
155
|
+
const name = item.name
|
|
156
|
+
let k
|
|
157
|
+
if (te) {
|
|
158
|
+
if (te((k = `attributes.${item.label}`))) {
|
|
159
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
160
|
+
// @ts-ignore
|
|
161
|
+
item.label = t(k)
|
|
162
|
+
} else if (te((k = `attributes.${lodash.snakeCase(item.label)}`))) {
|
|
163
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
164
|
+
// @ts-ignore
|
|
165
|
+
item.label = t(k)
|
|
166
|
+
} else if (te((k = `attributes.${lodash.camelCase(item.label)}`))) {
|
|
167
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
168
|
+
// @ts-ignore
|
|
169
|
+
item.label = t(k)
|
|
170
|
+
} else if (te((k = `attributes.${Str.pascalCase(item.label)}`))) {
|
|
171
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
172
|
+
// @ts-ignore
|
|
173
|
+
item.label = t(k)
|
|
174
|
+
} else if (te((k = `choice.${lodash.pluralize(Str.pascalCase(item.label))}`))) {
|
|
175
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
176
|
+
// @ts-ignore
|
|
177
|
+
item.label = t(k, 2)
|
|
178
|
+
} else if (te((k = item.label))) {
|
|
179
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
180
|
+
// @ts-ignore
|
|
181
|
+
item.label = t(k)
|
|
182
|
+
}
|
|
150
183
|
}
|
|
151
184
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
if (typeof elm !== 'string' && !elm?.name) return elm
|
|
156
|
-
// Todo: will do this
|
|
157
|
-
let item: MDtColumn = typeof elm === 'string' ? {
|
|
158
|
-
name: elm as string,
|
|
159
|
-
label: elm as string,
|
|
160
|
-
field: elm as string
|
|
161
|
-
} : { ...elm }
|
|
162
|
-
item.name = item.name ?? ''
|
|
163
|
-
item.label = (item.label === undefined || item.label === null) ? item.name : item.label
|
|
164
|
-
item.field = (item.field === undefined || item.field === null) ? item.name : item.field
|
|
165
|
-
item = {
|
|
166
|
-
...item,
|
|
167
|
-
name: Str.strBefore(Str.strBefore(item.name), 'ToString'),
|
|
168
|
-
label: (item.label !== undefined && item.label !== null) ? Str.strBefore(Str.strBefore(item.label), 'ToString') : item.label
|
|
185
|
+
if (name === control) {
|
|
186
|
+
if (controlStyle && !item.style) {
|
|
187
|
+
item.style = controlStyle + (item.style ? ` ${item.style}` : '')
|
|
169
188
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
// @ts-ignore
|
|
176
|
-
item.label = t(k)
|
|
177
|
-
} else if (te((k = `attributes.${lodash.snakeCase(item.label)}`))) {
|
|
178
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
179
|
-
// @ts-ignore
|
|
180
|
-
item.label = t(k)
|
|
181
|
-
} else if (te((k = `attributes.${lodash.camelCase(item.label)}`))) {
|
|
182
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
183
|
-
// @ts-ignore
|
|
184
|
-
item.label = t(k)
|
|
185
|
-
} else if (te((k = `attributes.${Str.pascalCase(item.label)}`))) {
|
|
186
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
187
|
-
// @ts-ignore
|
|
188
|
-
item.label = t(k)
|
|
189
|
-
} else if (te((k = `choice.${lodash.pluralize(Str.pascalCase(item.label))}`))) {
|
|
190
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
191
|
-
// @ts-ignore
|
|
192
|
-
item.label = t(k, 2)
|
|
193
|
-
} else if (te((k = item.label))) {
|
|
194
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
195
|
-
// @ts-ignore
|
|
196
|
-
item.label = t(k)
|
|
197
|
-
}
|
|
189
|
+
item.headerClasses = (item.headerClasses ? item.headerClasses : '') + ' m--control-header'
|
|
190
|
+
item.headerClasses = item.headerClasses.trim()
|
|
191
|
+
item.sortable = !1
|
|
192
|
+
if (!item.align) {
|
|
193
|
+
item.align = 'right'
|
|
198
194
|
}
|
|
199
|
-
|
|
200
|
-
if (
|
|
201
|
-
|
|
202
|
-
item.style = controlStyle + (item.style ? ` ${item.style}` : '')
|
|
203
|
-
}
|
|
204
|
-
item.headerClasses = (item.headerClasses ? item.headerClasses : '') + ' m--control-header'
|
|
205
|
-
item.headerClasses = item.headerClasses.trim()
|
|
206
|
-
item.sortable = !1
|
|
207
|
-
if (!item.align) {
|
|
208
|
-
item.align = 'right'
|
|
209
|
-
}
|
|
210
|
-
opts.classes = opts.classes || ''
|
|
211
|
-
if (typeof opts.classes === 'function') {
|
|
212
|
-
opts.classes = opts.classes()
|
|
213
|
-
}
|
|
214
|
-
opts.classes += ' m--control-cell'
|
|
215
|
-
opts.classes = opts.classes.trim()
|
|
195
|
+
opts.classes = opts.classes || ''
|
|
196
|
+
if (typeof opts.classes === 'function') {
|
|
197
|
+
opts.classes = opts.classes()
|
|
216
198
|
}
|
|
199
|
+
opts.classes += ' m--control-cell'
|
|
200
|
+
opts.classes = opts.classes.trim()
|
|
201
|
+
}
|
|
217
202
|
|
|
218
|
-
|
|
203
|
+
item = { ...opts, ...item }
|
|
219
204
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
}
|
|
225
|
-
result.push(item)
|
|
226
|
-
})
|
|
227
|
-
return lodash.uniqBy(result, (e: MDtColumn) => e.name)
|
|
228
|
-
},
|
|
229
|
-
/**
|
|
230
|
-
* Copy text
|
|
231
|
-
* @param text
|
|
232
|
-
*/
|
|
233
|
-
copyText: async (text: string | any) => copyToClipboard(text),
|
|
234
|
-
quasarNotifyOptions,
|
|
235
|
-
alertMessage,
|
|
236
|
-
alertSuccess (message: string) {
|
|
237
|
-
return alertMessage({ type: 'positive', message })
|
|
238
|
-
},
|
|
239
|
-
alertError (message: string) {
|
|
240
|
-
return alertMessage({ type: 'negative', message })
|
|
241
|
-
},
|
|
242
|
-
confirmMessage (message?: string, title?: string, opts?: QDialogOptions): Vue3MConfirmMessage {
|
|
243
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
244
|
-
// @ts-ignore
|
|
245
|
-
title = title || t('messages.are_you_sure') || ''
|
|
246
|
-
message = message || ''
|
|
247
|
-
opts = opts || {}
|
|
248
|
-
const buttonsProps = {
|
|
249
|
-
...(pluginOptions.value.btn || {})
|
|
250
|
-
// ...(options.value.confirmDialogOptions?.buttons || {})
|
|
205
|
+
if (item.sortable === undefined && (options.noSort ?? []).length > 0 && options.noSort?.includes(item.name)) {
|
|
206
|
+
item.sortable = !1
|
|
207
|
+
} else if (item.sortable === undefined) {
|
|
208
|
+
item.sortable = !0
|
|
251
209
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
const cancelProps: any = {}
|
|
256
|
-
// const dialogProps = options.value.confirmDialog || {} as any
|
|
257
|
-
const dialogProps: any = {}
|
|
258
|
-
dialogProps.transitionShow = dialogProps.transitionShow || 'jump-down'
|
|
259
|
-
dialogProps.transitionHide = dialogProps.transitionHide || 'jump-up'
|
|
260
|
-
dialogProps.class = ('m--confirm ') + (dialogProps.class || '')
|
|
261
|
-
return Dialog.create({
|
|
262
|
-
title,
|
|
263
|
-
message,
|
|
264
|
-
focus: 'none',
|
|
265
|
-
cancel: {
|
|
266
|
-
color: cancelProps.color || 'positive',
|
|
267
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
268
|
-
// @ts-ignore
|
|
269
|
-
label: t(cancelProps?.label || 'no'),
|
|
270
|
-
...buttonsProps as any,
|
|
271
|
-
flat: !0,
|
|
272
|
-
unelevated: !0,
|
|
273
|
-
...cancelProps as any
|
|
274
|
-
},
|
|
275
|
-
ok: {
|
|
276
|
-
color: okProps.color || 'negative',
|
|
277
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
278
|
-
// @ts-ignore
|
|
279
|
-
label: t(okProps?.label || 'yes'),
|
|
280
|
-
...buttonsProps as any,
|
|
281
|
-
flat: !0,
|
|
282
|
-
unelevated: !0,
|
|
283
|
-
...okProps as any
|
|
284
|
-
},
|
|
285
|
-
persistent: !0,
|
|
286
|
-
...dialogProps as any,
|
|
287
|
-
...opts as any
|
|
288
|
-
})
|
|
289
|
-
},
|
|
290
|
-
...Helpers
|
|
210
|
+
result.push(item)
|
|
211
|
+
})
|
|
212
|
+
return lodash.uniqBy(result, (e: MDtColumn) => e.name)
|
|
291
213
|
}
|
|
214
|
+
/**
|
|
215
|
+
* Copy text
|
|
216
|
+
* @param text
|
|
217
|
+
*/
|
|
218
|
+
const copyText = async (text: string | any) => copyToClipboard(text)
|
|
292
219
|
|
|
293
|
-
|
|
220
|
+
const quasarNotifyOptions = (opts: QNotifyCreateOptions | string): QNotifyCreateOptions => {
|
|
221
|
+
return {
|
|
222
|
+
badgeColor: 'primary',
|
|
223
|
+
progress: !0,
|
|
224
|
+
...pluginOptions.value.notify as any,
|
|
225
|
+
message: typeof opts === 'string' ? opts : opts.message,
|
|
226
|
+
...(typeof opts !== 'string' ? opts : {})
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
const alertMessage = (opts: Vue3MAlertMessageOptions): Vue3MAlertMessage => {
|
|
230
|
+
return q.notify(quasarNotifyOptions(opts))
|
|
231
|
+
}
|
|
232
|
+
const alertSuccess = (message: string) => {
|
|
233
|
+
return alertMessage({ type: 'positive', message })
|
|
234
|
+
}
|
|
235
|
+
const alertError = (message: string) => {
|
|
236
|
+
return alertMessage({ type: 'negative', message })
|
|
237
|
+
}
|
|
238
|
+
const confirmMessage = (message?: string, title?: string, opts?: QDialogOptions): Vue3MConfirmMessage => {
|
|
239
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
240
|
+
// @ts-ignore
|
|
241
|
+
title = title || t('messages.are_you_sure') || ''
|
|
242
|
+
message = message || ''
|
|
243
|
+
opts = opts || {}
|
|
244
|
+
const buttonsProps = {
|
|
245
|
+
...(pluginOptions.value.btn || {})
|
|
246
|
+
// ...(options.value.confirmDialogOptions?.buttons || {})
|
|
247
|
+
}
|
|
248
|
+
// const okProps = options.value.confirmDialogOptions?.okProps || {}
|
|
249
|
+
const okProps: any = {}
|
|
250
|
+
// const cancelProps = options.value.confirmDialogOptions?.cancelProps || {}
|
|
251
|
+
const cancelProps: any = {}
|
|
252
|
+
// const dialogProps = options.value.confirmDialog || {} as any
|
|
253
|
+
const dialogProps: any = {}
|
|
254
|
+
dialogProps.transitionShow = dialogProps.transitionShow || 'jump-down'
|
|
255
|
+
dialogProps.transitionHide = dialogProps.transitionHide || 'jump-up'
|
|
256
|
+
dialogProps.class = ('m--confirm ') + (dialogProps.class || '')
|
|
257
|
+
return Dialog.create({
|
|
258
|
+
title,
|
|
259
|
+
message,
|
|
260
|
+
focus: 'none',
|
|
261
|
+
cancel: {
|
|
262
|
+
color: cancelProps.color || 'positive',
|
|
263
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
264
|
+
// @ts-ignore
|
|
265
|
+
label: t(cancelProps?.label || 'no'),
|
|
266
|
+
...buttonsProps as any,
|
|
267
|
+
flat: !0,
|
|
268
|
+
unelevated: !0,
|
|
269
|
+
...cancelProps as any
|
|
270
|
+
},
|
|
271
|
+
ok: {
|
|
272
|
+
color: okProps.color || 'negative',
|
|
273
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
274
|
+
// @ts-ignore
|
|
275
|
+
label: t(okProps?.label || 'yes'),
|
|
276
|
+
...buttonsProps as any,
|
|
277
|
+
flat: !0,
|
|
278
|
+
unelevated: !0,
|
|
279
|
+
...okProps as any
|
|
280
|
+
},
|
|
281
|
+
persistent: !0,
|
|
282
|
+
...dialogProps as any,
|
|
283
|
+
...opts as any
|
|
284
|
+
})
|
|
285
|
+
}
|
|
286
|
+
const api = computed(() => myth.api.value)
|
|
287
|
+
return {
|
|
288
|
+
api,
|
|
289
|
+
__,
|
|
290
|
+
getPageTitle,
|
|
291
|
+
parseHeaders,
|
|
292
|
+
copyText,
|
|
293
|
+
quasarNotifyOptions,
|
|
294
|
+
alertMessage,
|
|
295
|
+
alertSuccess,
|
|
296
|
+
alertError,
|
|
297
|
+
confirmMessage,
|
|
298
|
+
...Helpers,
|
|
299
|
+
...Str,
|
|
300
|
+
veeRules
|
|
301
|
+
}
|
|
294
302
|
}
|
|
@@ -81,8 +81,8 @@ export type ParamsType = Record<string, any> | FormData | object
|
|
|
81
81
|
export type ConfigType = AxiosRequestConfig<ApiInterface> & Partial<{
|
|
82
82
|
params: Partial<ApiServiceParams> & Generic
|
|
83
83
|
}>
|
|
84
|
-
export type HelpersStubSchema = {
|
|
85
84
|
|
|
85
|
+
export type HelpersStubSchema = {
|
|
86
86
|
index (config?: ConfigType): Promise<ApiInterface>;
|
|
87
87
|
|
|
88
88
|
staticIndex (config?: ConfigType): Promise<ApiInterface>;
|
|
@@ -108,11 +108,14 @@ export type HelpersStubSchema = {
|
|
|
108
108
|
deleteAttachment (id: UrlType, fileId: string | number, config?: AxiosRequestConfig): Promise<ApiInterface>;
|
|
109
109
|
|
|
110
110
|
updateAttachment (id: UrlType, fileId: string | number, data: Record<string, any>, config?: AxiosRequestConfig): Promise<ApiInterface>;
|
|
111
|
-
|
|
111
|
+
|
|
112
|
+
} | (HelpersStubSchema & Record<string, HelpersStubSchema | ((...args: any) => Promise<ApiInterface>)>)
|
|
113
|
+
|
|
112
114
|
export type StubSchemaContext = HelpersStubSchema
|
|
113
115
|
& Record<string, ((...args: any) => Promise<ApiInterface>)>
|
|
114
116
|
& Record<string, Record<string, ((...args: any) => Promise<ApiInterface>)>>
|
|
115
117
|
& Record<string, Record<string, Record<string, ((...args: any) => Promise<ApiInterface>)>>>
|
|
118
|
+
|
|
116
119
|
export type StubSchema = StubSchemaContext
|
|
117
120
|
& ((...args: any) => Promise<ApiInterface>)
|
|
118
121
|
& string
|
|
@@ -28,10 +28,19 @@ import type {
|
|
|
28
28
|
QTableProps,
|
|
29
29
|
QTimeProps
|
|
30
30
|
} from 'quasar'
|
|
31
|
-
import type {
|
|
31
|
+
import type {
|
|
32
|
+
ComputedRef,
|
|
33
|
+
MaybeRefOrGetter,
|
|
34
|
+
Ref,
|
|
35
|
+
ShallowRef,
|
|
36
|
+
TransitionGroupProps,
|
|
37
|
+
TransitionProps,
|
|
38
|
+
UnwrapNestedRefs,
|
|
39
|
+
VNode,
|
|
40
|
+
WritableComputedRef
|
|
41
|
+
} from 'vue'
|
|
32
42
|
import type { TypedOptions } from 'typed.js'
|
|
33
43
|
import type { FieldContext, FieldOptions, FormContext, FormOptions, FormState } from 'vee-validate'
|
|
34
|
-
|
|
35
44
|
import type { ThemeShadow, ThemeSize } from './theme'
|
|
36
45
|
import type {
|
|
37
46
|
GenericMDtBtn,
|
|
@@ -43,15 +52,16 @@ import type {
|
|
|
43
52
|
MDtServiceNameStringProp
|
|
44
53
|
} from './dt'
|
|
45
54
|
import type { RouteLocationRaw } from 'vue-router'
|
|
55
|
+
import type { AxiosRequestConfig } from 'axios'
|
|
46
56
|
|
|
47
|
-
export
|
|
57
|
+
export interface MTransitionProps extends TransitionGroupProps {
|
|
48
58
|
enterIn?: string;
|
|
49
59
|
enterOut?: string;
|
|
50
60
|
slowIn?: boolean;
|
|
51
61
|
slowOut?: boolean;
|
|
52
62
|
}
|
|
53
63
|
|
|
54
|
-
export
|
|
64
|
+
export interface MTransitionsSlots {
|
|
55
65
|
default: () => VNode[];
|
|
56
66
|
}
|
|
57
67
|
|
|
@@ -146,7 +156,7 @@ export interface MColumnSlots {
|
|
|
146
156
|
default?: () => VNode[];
|
|
147
157
|
}
|
|
148
158
|
|
|
149
|
-
export
|
|
159
|
+
export interface MContainerProps {
|
|
150
160
|
size?: ThemeSize | string | undefined;
|
|
151
161
|
dense?: boolean | undefined;
|
|
152
162
|
fluid?: boolean | undefined;
|
|
@@ -255,7 +265,7 @@ export type InputFormErrorsContext = Record<string, InputErrorsContext> | undefi
|
|
|
255
265
|
|
|
256
266
|
export type MAvatarViewerModelValue = File | null | undefined;
|
|
257
267
|
|
|
258
|
-
export
|
|
268
|
+
export interface MAvatarViewerProps extends QAvatarProps, MColProps {
|
|
259
269
|
/**
|
|
260
270
|
* Comma separated list of unique file type specifiers. Maps to 'accept' attribute of native input type=file element
|
|
261
271
|
*/
|
|
@@ -475,11 +485,31 @@ export interface MInputSlots extends QInputSlots, QFieldSlots, BaseInputsSlots {
|
|
|
475
485
|
//
|
|
476
486
|
}
|
|
477
487
|
|
|
478
|
-
export
|
|
479
|
-
|
|
488
|
+
export interface MPasswordProps extends MInputProps {
|
|
489
|
+
/**
|
|
490
|
+
* icon prepend it to password input.
|
|
491
|
+
*/
|
|
492
|
+
icon?: boolean | undefined;
|
|
493
|
+
/**
|
|
494
|
+
* toggle password append icon.
|
|
495
|
+
*/
|
|
496
|
+
noToggle?: boolean | undefined;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
export interface MEditorProps extends Omit<QEditorProps, 'modelValue' | 'placeholder'>, BaseInputsProps {
|
|
500
|
+
//
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
export interface MEditorSlots extends QEditorSlots, BaseInputsSlots {
|
|
504
|
+
//
|
|
505
|
+
}
|
|
480
506
|
|
|
481
|
-
export
|
|
482
|
-
|
|
507
|
+
export interface MSelectModelEmit {
|
|
508
|
+
value: any | null;
|
|
509
|
+
model: object | null;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
export interface MSelectProps extends Omit<QSelectProps, 'rules' | 'name' | 'modelValue' | 'label' | 'hint' | 'autocomplete'>, BaseInputsProps {
|
|
483
513
|
/**
|
|
484
514
|
* Input search functionality. useInput prop for this feature.
|
|
485
515
|
*/
|
|
@@ -506,12 +536,12 @@ export type MSelectProps = Omit<QSelectProps, 'rules' | 'name' | 'modelValue' |
|
|
|
506
536
|
*/
|
|
507
537
|
// iniData?: boolean;
|
|
508
538
|
}
|
|
509
|
-
export type MSelectSlots = QInputSlots & QFieldSlots & BaseInputsSlots
|
|
510
539
|
|
|
511
|
-
export
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
540
|
+
export interface MSelectSlots extends QInputSlots, QFieldSlots, BaseInputsSlots {
|
|
541
|
+
//
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
export interface MFileProps extends Omit<QFileProps, 'modelValue' | 'rules' | 'name' | 'label' | 'hint'>, Omit<BaseInputsProps, 'autocomplete'> {
|
|
515
545
|
accept?: string | undefined;
|
|
516
546
|
images?: boolean;
|
|
517
547
|
svg?: boolean;
|
|
@@ -520,7 +550,9 @@ export type MFileProps =
|
|
|
520
550
|
excel?: boolean;
|
|
521
551
|
}
|
|
522
552
|
|
|
523
|
-
export
|
|
553
|
+
export interface MFileSlots extends QFileSlots, BaseInputsSlots {
|
|
554
|
+
//
|
|
555
|
+
}
|
|
524
556
|
|
|
525
557
|
export interface BaseCheckboxProps extends Omit<BaseInputsProps, 'topLabel'> {
|
|
526
558
|
/**
|
|
@@ -600,11 +632,19 @@ export interface MTimeSlots extends MPickerSlots {
|
|
|
600
632
|
//
|
|
601
633
|
}
|
|
602
634
|
|
|
603
|
-
export
|
|
604
|
-
|
|
635
|
+
export interface MFieldProps extends Omit<MInputProps, 'viewMode' | 'viewModeValue' | 'fieldOptions'> {
|
|
636
|
+
//
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
export interface MFieldSlots extends MInputSlots {
|
|
640
|
+
//
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
export interface MHiddenInputSlots {
|
|
644
|
+
[key: string]: () => VNode[]
|
|
645
|
+
}
|
|
605
646
|
|
|
606
|
-
export
|
|
607
|
-
export type MHiddenInputProps = Pick<BaseInputFormProps, 'rules' | 'required'> & {
|
|
647
|
+
export interface MHiddenInputProps extends Pick<BaseInputFormProps, 'rules' | 'required'> {
|
|
608
648
|
/**
|
|
609
649
|
* Input name.
|
|
610
650
|
*/
|
|
@@ -615,14 +655,19 @@ export type MHiddenInputProps = Pick<BaseInputFormProps, 'rules' | 'required'> &
|
|
|
615
655
|
modelValue?: any;
|
|
616
656
|
}
|
|
617
657
|
|
|
618
|
-
export
|
|
619
|
-
|
|
658
|
+
export interface MHiddenProps extends MHiddenInputProps, Pick<ViewModeProps, 'viewMode'>, Omit<MColProps, 'name'> {
|
|
659
|
+
//
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
export interface MHiddenSlots {
|
|
620
663
|
/**
|
|
621
664
|
* Field main content
|
|
622
665
|
*/
|
|
623
666
|
default: () => VNode[];
|
|
624
667
|
}
|
|
625
668
|
|
|
669
|
+
export type MFormScope = FormContext<Record<string, any>>;
|
|
670
|
+
|
|
626
671
|
export interface MFormProps {
|
|
627
672
|
/**
|
|
628
673
|
* Form HTML element attributes.
|
|
@@ -664,8 +709,6 @@ export interface MFormProps {
|
|
|
664
709
|
readonly padding?: boolean;
|
|
665
710
|
}
|
|
666
711
|
|
|
667
|
-
export type MFormScope = FormContext<Record<string, any>>;
|
|
668
|
-
|
|
669
712
|
export interface MFormSlots {
|
|
670
713
|
default: (scope: MFormScope) => VNode[];
|
|
671
714
|
}
|
|
@@ -698,7 +741,7 @@ export interface MDtBtnSlots extends MBtnSlots {
|
|
|
698
741
|
loading: () => VNode[];
|
|
699
742
|
}
|
|
700
743
|
|
|
701
|
-
export
|
|
744
|
+
export interface MDatatableProps<I extends GenericFormValues = GenericFormValues> extends Omit<QTableProps, 'rows' | 'rowsPerPageOptions' | 'visibleColumns'> {
|
|
702
745
|
rows?: any[];
|
|
703
746
|
controlKey?: string;
|
|
704
747
|
defaultItem?: Partial<MDtItem<I>>
|
|
@@ -781,10 +824,48 @@ export type MDatatableProps<I extends GenericFormValues = GenericFormValues> = O
|
|
|
781
824
|
|
|
782
825
|
}
|
|
783
826
|
|
|
827
|
+
type ParamsReq = Record<string, any>;
|
|
828
|
+
|
|
829
|
+
export interface MAxiosProps extends Omit<MSelectProps, 'options' | 'axiosMode'> {
|
|
830
|
+
/**
|
|
831
|
+
* Request method. Default is GET.
|
|
832
|
+
*/
|
|
833
|
+
service: ((config?: AxiosRequestConfig) => Promise<any>) | string;
|
|
834
|
+
/**
|
|
835
|
+
* Send request as guest request. If false, send request as authenticated user. Default is true.
|
|
836
|
+
*/
|
|
837
|
+
guest?: boolean | MaybeRefOrGetter<boolean>;
|
|
838
|
+
/**
|
|
839
|
+
* Request params.
|
|
840
|
+
*/
|
|
841
|
+
params?: Ref<ParamsReq> | ShallowRef<ParamsReq> | WritableComputedRef<ParamsReq> | ComputedRef<ParamsReq> | (() => ParamsReq);
|
|
842
|
+
/**
|
|
843
|
+
* Request relations.
|
|
844
|
+
*/
|
|
845
|
+
requestWith?: MaybeRefOrGetter<string> | undefined;
|
|
846
|
+
/**
|
|
847
|
+
* Component items.
|
|
848
|
+
*/
|
|
849
|
+
items?: any[];
|
|
850
|
+
/**
|
|
851
|
+
* The name of the attribute to be used as a label
|
|
852
|
+
*/
|
|
853
|
+
attributeName?: string;
|
|
854
|
+
/**
|
|
855
|
+
* Do fetch asynchronous
|
|
856
|
+
*/
|
|
857
|
+
lazy?: boolean;
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
export interface MAxiosSlots extends MSelectSlots {
|
|
861
|
+
//
|
|
862
|
+
}
|
|
863
|
+
|
|
784
864
|
declare module '@vue/runtime-core' {
|
|
785
865
|
interface GlobalComponents {
|
|
786
866
|
// Form.
|
|
787
867
|
MAvatarViewer: GlobalComponentConstructor<MAvatarViewerProps, MAvatarViewerSlots>;
|
|
868
|
+
MAxios: GlobalComponentConstructor<MAxiosProps, MAxiosSlots>;
|
|
788
869
|
MBtn: GlobalComponentConstructor<MBtnProps, MBtnSlots>;
|
|
789
870
|
MCheckbox: GlobalComponentConstructor<MCheckboxProps, MCheckboxSlots>;
|
|
790
871
|
MColor: GlobalComponentConstructor<MInputProps, MInputSlots>;
|
|
@@ -799,6 +880,7 @@ declare module '@vue/runtime-core' {
|
|
|
799
880
|
MInputFieldControl: GlobalComponentConstructor<MInputFieldControlProps, MInputFieldControlSlots>;
|
|
800
881
|
MInputLabel: GlobalComponentConstructor<MInputLabelProps, MInputLabelSlots>;
|
|
801
882
|
MMobile: GlobalComponentConstructor<MInputProps, MInputSlots>;
|
|
883
|
+
MPassword: GlobalComponentConstructor<MPasswordProps, MInputSlots>;
|
|
802
884
|
MPicker: GlobalComponentConstructor<MPickerProps, MPickerSlots>;
|
|
803
885
|
MRadio: GlobalComponentConstructor<MRadioProps, MRadioSlots>;
|
|
804
886
|
MSelect: GlobalComponentConstructor<MSelectProps, MSelectSlots>;
|
package/src/types/index.d.ts
CHANGED
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
} from './components'
|
|
30
30
|
import { myth } from '../utils'
|
|
31
31
|
import { ThemeBtn, ThemeFluid, ThemeInput, ThemeRounded, ThemeShadow, ThemeSize } from './theme'
|
|
32
|
+
import { HelpersStubSchema } from './api-helpers'
|
|
32
33
|
|
|
33
34
|
/**
|
|
34
35
|
* Default loading q-btn loading slot.
|
|
@@ -142,6 +143,7 @@ export interface InstallOptions {
|
|
|
142
143
|
props?: PropsContext;
|
|
143
144
|
themeInput?: ThemeInput;
|
|
144
145
|
themeBtn?: ThemeBtn;
|
|
146
|
+
api?: HelpersStubSchema;
|
|
145
147
|
}
|
|
146
148
|
|
|
147
149
|
export type MythContext = typeof myth;
|
package/src/utils/Helpers.ts
CHANGED
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
* Github: https://github.com/mythpe
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { AxiosInstance, AxiosRequestConfig } from 'axios'
|
|
9
|
+
import type { AxiosInstance, AxiosRequestConfig } from 'axios'
|
|
10
|
+
import type { ConfigType, DownloadFromResponse, DownloadFromResponseCode, HelpersStubSchema, ParamsType, UrlType } from '../types'
|
|
10
11
|
import lodash from 'lodash'
|
|
11
12
|
import { openURL, scroll } from 'quasar'
|
|
12
|
-
import type { ConfigType, DownloadFromResponse, DownloadFromResponseCode, HelpersStubSchema, ParamsType, UrlType } from '../types'
|
|
13
13
|
|
|
14
14
|
import { nextTick } from 'vue'
|
|
15
15
|
|
|
@@ -58,27 +58,16 @@ export const Helpers = {
|
|
|
58
58
|
async index (config?: ConfigType) {
|
|
59
59
|
const u = makeUrl()
|
|
60
60
|
return axios().get(u, config)
|
|
61
|
-
// return typeof config === 'boolean' ? u : axios().get(u, config)
|
|
62
61
|
},
|
|
63
62
|
async staticIndex (config?: ConfigType) {
|
|
64
63
|
const u = `Static${baseUrl ? `/${baseUrl}` : ''}`
|
|
65
64
|
return axios().get(u, config)
|
|
66
|
-
// config = config || {}
|
|
67
|
-
// config.params = {
|
|
68
|
-
// page: 1,
|
|
69
|
-
// itemsPerPage: -1,
|
|
70
|
-
// ...(config.params ?? {})
|
|
71
|
-
// }
|
|
72
|
-
// return axios().get(u, config)
|
|
73
65
|
},
|
|
74
66
|
async export (data?: ParamsType, config?: AxiosRequestConfig) {
|
|
75
67
|
return axios().post(makeUrl('Export'), data, config)
|
|
76
68
|
},
|
|
77
69
|
async store (data?: ParamsType, config?: AxiosRequestConfig) {
|
|
78
70
|
const u = makeUrl()
|
|
79
|
-
// if (typeof data === 'boolean') {
|
|
80
|
-
// return u
|
|
81
|
-
// }
|
|
82
71
|
const formData = new FormData()
|
|
83
72
|
data && Helpers.appendArray(formData, data)
|
|
84
73
|
return axios().post(u, formData, config)
|
|
@@ -86,22 +75,13 @@ export const Helpers = {
|
|
|
86
75
|
async show (id: UrlType, config?: AxiosRequestConfig) {
|
|
87
76
|
const u = makeUrl(id)
|
|
88
77
|
return axios().get(u, config)
|
|
89
|
-
// return typeof id === 'boolean' ? u : axios().get(u, config)
|
|
90
78
|
},
|
|
91
79
|
async staticShow (id: UrlType, config?: AxiosRequestConfig) {
|
|
92
|
-
// const m = baseUrl ? baseUrl.toString().split('/').pop() : ''
|
|
93
|
-
// const u = 'Static' + (m ? `/${m}` : '') + `/${id}`
|
|
94
80
|
const u = `Static${baseUrl ? `/${baseUrl}` : ''}` + `/${id}`
|
|
95
|
-
// if (typeof id === 'boolean') {
|
|
96
|
-
// return u
|
|
97
|
-
// }
|
|
98
81
|
return axios().get(u, config)
|
|
99
82
|
},
|
|
100
83
|
async update (id: UrlType, data?: ParamsType, config?: AxiosRequestConfig) {
|
|
101
84
|
const u = makeUrl(id)
|
|
102
|
-
// if (typeof id === 'boolean') {
|
|
103
|
-
// return u
|
|
104
|
-
// }
|
|
105
85
|
const formData = new FormData()
|
|
106
86
|
formData.append('_method', 'put')
|
|
107
87
|
data && Helpers.appendArray(formData, data)
|
|
@@ -110,13 +90,12 @@ export const Helpers = {
|
|
|
110
90
|
async destroy (id: UrlType, config?: AxiosRequestConfig) {
|
|
111
91
|
const u = makeUrl(id)
|
|
112
92
|
return axios().delete(u, config)
|
|
113
|
-
// return typeof id === 'boolean' ? u : axios().delete(u, config)
|
|
114
93
|
},
|
|
115
94
|
async destroyAll (ids?: UrlType[], config?: AxiosRequestConfig) {
|
|
116
95
|
const u = makeUrl('DestroyAll')
|
|
117
96
|
return axios().post(u, { ids: (ids || []) }, config)
|
|
118
97
|
},
|
|
119
|
-
getUploadAttachmentsUrl: (id: UrlType) => makeUrl(`${id}/Attachment/Upload`),
|
|
98
|
+
getUploadAttachmentsUrl: (id: UrlType): string => makeUrl(`${id}/Attachment/Upload`),
|
|
120
99
|
async uploadAttachments (id: UrlType, data: Record<string, any>, config?: AxiosRequestConfig) {
|
|
121
100
|
const _url = makeUrl(`${id}/Attachment/Upload`)
|
|
122
101
|
return axios().post(_url, data, config)
|
package/src/utils/myth.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import { ref } from 'vue'
|
|
10
10
|
import { extend } from 'quasar'
|
|
11
|
-
import type { BtnLoading, PropsContext, ThemeBtn, ThemeInput, ThemeRounded, ThemeShadow, ThemeSize } from '../types'
|
|
11
|
+
import type { BtnLoading, HelpersStubSchema, PropsContext, ThemeBtn, ThemeInput, ThemeRounded, ThemeShadow, ThemeSize } from '../types'
|
|
12
12
|
|
|
13
13
|
const props = ref<PropsContext>({})
|
|
14
14
|
const size = ref<ThemeSize>('md')
|
|
@@ -21,6 +21,7 @@ const btnLoading = ref<BtnLoading>({
|
|
|
21
21
|
})
|
|
22
22
|
const themeBtn = ref<ThemeBtn>({})
|
|
23
23
|
const themeInput = ref<ThemeInput>({})
|
|
24
|
+
const api = ref<HelpersStubSchema>({} as HelpersStubSchema)
|
|
24
25
|
export const myth = {
|
|
25
26
|
/**
|
|
26
27
|
* Apply Padding on all sides of components.
|
|
@@ -86,5 +87,9 @@ export const myth = {
|
|
|
86
87
|
/**
|
|
87
88
|
* Theme Shadow.
|
|
88
89
|
*/
|
|
89
|
-
shadow
|
|
90
|
+
shadow,
|
|
91
|
+
api,
|
|
92
|
+
setApi (v: HelpersStubSchema) {
|
|
93
|
+
api.value = v
|
|
94
|
+
}
|
|
90
95
|
}
|
package/src/utils/vue-plugin.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { name, version } from '../../package.json'
|
|
|
11
11
|
import { myth } from './myth'
|
|
12
12
|
import {
|
|
13
13
|
MAvatarViewer,
|
|
14
|
+
MAxios,
|
|
14
15
|
MBlock,
|
|
15
16
|
MBtn,
|
|
16
17
|
MCheckbox,
|
|
@@ -33,6 +34,7 @@ import {
|
|
|
33
34
|
MInputFieldControl,
|
|
34
35
|
MInputLabel,
|
|
35
36
|
MMobile,
|
|
37
|
+
MPassword,
|
|
36
38
|
MPicker,
|
|
37
39
|
MRadio,
|
|
38
40
|
MRow,
|
|
@@ -69,9 +71,13 @@ function install (app: App, options: InstallOptions = {}) {
|
|
|
69
71
|
if (options.themeInput !== undefined) {
|
|
70
72
|
myth.themeInput.value = options.themeInput
|
|
71
73
|
}
|
|
74
|
+
if (options.api !== undefined) {
|
|
75
|
+
myth.setApi(options.api)
|
|
76
|
+
}
|
|
72
77
|
|
|
73
78
|
// Form.
|
|
74
79
|
app.component('MAvatarViewer', MAvatarViewer)
|
|
80
|
+
app.component('MAxios', MAxios)
|
|
75
81
|
app.component('MBtn', MBtn)
|
|
76
82
|
app.component('MCheckbox', MCheckbox)
|
|
77
83
|
app.component('MColor', MColor)
|
|
@@ -87,6 +93,7 @@ function install (app: App, options: InstallOptions = {}) {
|
|
|
87
93
|
app.component('MInputFieldControl', MInputFieldControl)
|
|
88
94
|
app.component('MInputLabel', MInputLabel)
|
|
89
95
|
app.component('MMobile', MMobile)
|
|
96
|
+
app.component('MPassword', MPassword)
|
|
90
97
|
app.component('MPicker', MPicker)
|
|
91
98
|
app.component('MRadio', MRadio)
|
|
92
99
|
app.component('MSelect', MSelect)
|