@d-mok/quasar-app-extension-quasar-axe 3.1.45 → 3.1.47
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/templates/src/utils/dialog/advanced.ts +60 -58
- package/src/templates/src/utils/dialog/basic.ts +1 -1
- package/src/templates/src/utils/dialog/custom/dialogCheckboxText.vue +97 -0
- package/src/templates/src/utils/dialog/custom/dialogForm.vue +56 -14
- package/src/templates/src/utils/dialog/custom/dialogRadioText.vue +77 -0
- package/src/templates/src/utils/dialog/custom_base.ts +16 -0
- package/src/templates/src/utils/dialog/form.ts +75 -0
- package/src/templates/src/utils/dialog/index.ts +2 -1
- package/src/templates/src/utils/puppets/builder/index.ts +13 -4
package/package.json
CHANGED
|
@@ -1,33 +1,28 @@
|
|
|
1
|
-
import { Dialog, QDialogOptions } from 'quasar'
|
|
2
1
|
import dialogTextarea from './custom/dialogTextarea.vue'
|
|
3
2
|
import dialogTable from './custom/dialogTable.vue'
|
|
4
|
-
import dialogForm from './custom/dialogForm.vue'
|
|
5
3
|
import dialogBtn from './custom/dialogBtn.vue'
|
|
6
4
|
import dialogFile from './custom/dialogFile.vue'
|
|
5
|
+
import dialogRadioText from './custom/dialogRadioText.vue'
|
|
6
|
+
import dialogCheckboxText from './custom/dialogCheckboxText.vue'
|
|
7
7
|
import { throwError } from './basic'
|
|
8
|
+
import type { Component } from 'vue'
|
|
9
|
+
import { base } from './custom_base'
|
|
8
10
|
|
|
9
11
|
type Predicate<T> = (_: T) => boolean
|
|
10
12
|
type Mapper<T, S> = (_: T) => S
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
...props,
|
|
19
|
-
},
|
|
20
|
-
})
|
|
21
|
-
.onOk((data: any) => resolve(data))
|
|
22
|
-
.onCancel(() => reject('dialog cancelled by user.'))
|
|
23
|
-
)
|
|
24
|
-
}
|
|
14
|
+
type VueComponent = Component & (new (...args: any) => any)
|
|
15
|
+
type PropType<C extends VueComponent> = Omit<
|
|
16
|
+
InstanceType<C>['$props'],
|
|
17
|
+
'onOk' | 'onHide' | `onVnode${string}` | `ref_${string}`
|
|
18
|
+
>
|
|
19
|
+
type OkType<C extends VueComponent> = Parameters<InstanceType<C>['$emit']>[1]
|
|
25
20
|
|
|
26
|
-
export async function custom(
|
|
27
|
-
component:
|
|
28
|
-
props
|
|
29
|
-
) {
|
|
30
|
-
return await base(component, props)
|
|
21
|
+
export async function custom<C extends VueComponent>(
|
|
22
|
+
component: C,
|
|
23
|
+
props?: PropType<C>
|
|
24
|
+
): Promise<OkType<C>> {
|
|
25
|
+
return await base(component, props ?? {})
|
|
31
26
|
}
|
|
32
27
|
|
|
33
28
|
/**
|
|
@@ -75,7 +70,7 @@ export async function askFn(
|
|
|
75
70
|
funcs: Record<string, () => any>
|
|
76
71
|
): Promise<string> {
|
|
77
72
|
let key = await askBtn(title, message, Object.keys(funcs))
|
|
78
|
-
await funcs[key]()
|
|
73
|
+
await funcs[key]?.()
|
|
79
74
|
return key
|
|
80
75
|
}
|
|
81
76
|
|
|
@@ -148,43 +143,6 @@ export async function askArray(
|
|
|
148
143
|
return result.pluck('value').unmatch([''])
|
|
149
144
|
}
|
|
150
145
|
|
|
151
|
-
type FormPrefill = Record<
|
|
152
|
-
string,
|
|
153
|
-
| string
|
|
154
|
-
| number
|
|
155
|
-
| boolean
|
|
156
|
-
| { type: 'select'; value: string; options: string[] }
|
|
157
|
-
| { type: 'autocomplete'; value: string; options: string[] }
|
|
158
|
-
>
|
|
159
|
-
|
|
160
|
-
type FormFlat<T extends FormPrefill> = {
|
|
161
|
-
[P in keyof T]: T[P] extends object ? T[P]['value'] : T[P]
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Ask for an objects.
|
|
166
|
-
*/
|
|
167
|
-
export async function askForm<T extends FormPrefill>(
|
|
168
|
-
title: string,
|
|
169
|
-
message: string,
|
|
170
|
-
prefill: T,
|
|
171
|
-
validators: [(_: FormFlat<T>) => boolean, string][] = [[$ => true, '']]
|
|
172
|
-
): Promise<FormFlat<T>> {
|
|
173
|
-
const standardPrefill = Object.mapValues(prefill, $ => {
|
|
174
|
-
if (typeof $ === 'string') return { type: 'string', value: $ }
|
|
175
|
-
if (typeof $ === 'number') return { type: 'number', value: $ }
|
|
176
|
-
if (typeof $ === 'boolean') return { type: 'boolean', value: $ }
|
|
177
|
-
return $
|
|
178
|
-
})
|
|
179
|
-
|
|
180
|
-
return await base(dialogForm, {
|
|
181
|
-
title,
|
|
182
|
-
message,
|
|
183
|
-
prefill: standardPrefill,
|
|
184
|
-
validators,
|
|
185
|
-
})
|
|
186
|
-
}
|
|
187
|
-
|
|
188
146
|
/**
|
|
189
147
|
* Show a dialog with text area display.
|
|
190
148
|
*/
|
|
@@ -269,3 +227,47 @@ export async function askFiles(
|
|
|
269
227
|
cancel: true,
|
|
270
228
|
})
|
|
271
229
|
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Ask to select one text by a radio button.
|
|
233
|
+
*/
|
|
234
|
+
export async function askRadioText(
|
|
235
|
+
title: string,
|
|
236
|
+
message: string = '',
|
|
237
|
+
items: string[],
|
|
238
|
+
prefill: string = items[0]!,
|
|
239
|
+
newLabel: string = '',
|
|
240
|
+
isValid: Predicate<string> = $ => true
|
|
241
|
+
): Promise<string> {
|
|
242
|
+
return await base(dialogRadioText, {
|
|
243
|
+
title,
|
|
244
|
+
message,
|
|
245
|
+
items,
|
|
246
|
+
prefill,
|
|
247
|
+
newLabel,
|
|
248
|
+
isValid,
|
|
249
|
+
cancel: true,
|
|
250
|
+
})
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Ask to select multiple text by checkboxs.
|
|
255
|
+
*/
|
|
256
|
+
export async function askCheckboxText(
|
|
257
|
+
title: string,
|
|
258
|
+
message: string = '',
|
|
259
|
+
items: string[],
|
|
260
|
+
prefill: string[] = [],
|
|
261
|
+
newLabel: string = '',
|
|
262
|
+
isValid: Predicate<string[]> = $ => true
|
|
263
|
+
): Promise<string[]> {
|
|
264
|
+
return await base(dialogCheckboxText, {
|
|
265
|
+
title,
|
|
266
|
+
message,
|
|
267
|
+
items,
|
|
268
|
+
prefill,
|
|
269
|
+
newLabel,
|
|
270
|
+
isValid,
|
|
271
|
+
cancel: true,
|
|
272
|
+
})
|
|
273
|
+
}
|
|
@@ -143,7 +143,7 @@ export async function askRadio<T>(
|
|
|
143
143
|
title: string,
|
|
144
144
|
message: string = '',
|
|
145
145
|
items: T[],
|
|
146
|
-
prefill: T = items[0]
|
|
146
|
+
prefill: T = items[0]!,
|
|
147
147
|
label?: (string & keyof T) | Mapper<T, string>
|
|
148
148
|
): Promise<T> {
|
|
149
149
|
let labelFunc = ($: T) => Object.print($, label)
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<q-dialog
|
|
3
|
+
ref="dialogRef"
|
|
4
|
+
@hide="onDialogHide"
|
|
5
|
+
>
|
|
6
|
+
<q-card style="width: 400px">
|
|
7
|
+
<q-card-section>
|
|
8
|
+
<p class="text-h6">{{ title }}</p>
|
|
9
|
+
<p v-html="message" />
|
|
10
|
+
<div style="max-height: 340px; overflow-y: auto">
|
|
11
|
+
<div v-for="item in items">
|
|
12
|
+
<q-checkbox
|
|
13
|
+
v-model="select"
|
|
14
|
+
:val="item"
|
|
15
|
+
:label="item"
|
|
16
|
+
/>
|
|
17
|
+
</div>
|
|
18
|
+
<div v-for="item in newItems">
|
|
19
|
+
<div class="row q-pr-md">
|
|
20
|
+
<q-checkbox
|
|
21
|
+
class="col-auto"
|
|
22
|
+
v-model="item.checked"
|
|
23
|
+
:val="item.val"
|
|
24
|
+
/>
|
|
25
|
+
<q-input
|
|
26
|
+
class="col"
|
|
27
|
+
v-model="item.val"
|
|
28
|
+
:label="newLabel"
|
|
29
|
+
dense
|
|
30
|
+
/>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
</q-card-section>
|
|
35
|
+
|
|
36
|
+
<q-card-actions align="right">
|
|
37
|
+
<q-btn
|
|
38
|
+
label="Cancel"
|
|
39
|
+
flat
|
|
40
|
+
@click="onDialogCancel"
|
|
41
|
+
/>
|
|
42
|
+
<q-btn
|
|
43
|
+
label="OK"
|
|
44
|
+
flat
|
|
45
|
+
@click="onDialogOK(final)"
|
|
46
|
+
:disable="
|
|
47
|
+
![...items, ...newItems.pluck('val')].includesEvery(
|
|
48
|
+
final
|
|
49
|
+
) || !isValid(final)
|
|
50
|
+
"
|
|
51
|
+
/>
|
|
52
|
+
</q-card-actions>
|
|
53
|
+
</q-card>
|
|
54
|
+
</q-dialog>
|
|
55
|
+
</template>
|
|
56
|
+
|
|
57
|
+
<script lang="ts" setup>
|
|
58
|
+
import { useDialogPluginComponent } from 'quasar'
|
|
59
|
+
import { computed, ref, watch } from 'vue'
|
|
60
|
+
|
|
61
|
+
defineEmits([...useDialogPluginComponent.emits])
|
|
62
|
+
|
|
63
|
+
const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
|
|
64
|
+
useDialogPluginComponent()
|
|
65
|
+
|
|
66
|
+
const props = defineProps<{
|
|
67
|
+
title: string
|
|
68
|
+
message: string
|
|
69
|
+
items: string[]
|
|
70
|
+
prefill: string[]
|
|
71
|
+
newLabel: string
|
|
72
|
+
isValid: (_: string[]) => boolean
|
|
73
|
+
}>()
|
|
74
|
+
|
|
75
|
+
let select = ref([...props.prefill.match(props.items)])
|
|
76
|
+
|
|
77
|
+
let newItems = ref<{ val: string; checked: boolean }[]>([
|
|
78
|
+
{ val: '', checked: false },
|
|
79
|
+
])
|
|
80
|
+
|
|
81
|
+
let final = computed(() => {
|
|
82
|
+
return [
|
|
83
|
+
...select.value.sortedBy(props.items),
|
|
84
|
+
...newItems.value.match('checked').pluck('val'),
|
|
85
|
+
]
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
watch(
|
|
89
|
+
newItems,
|
|
90
|
+
() => {
|
|
91
|
+
if (newItems.value.at(-1)?.val !== '') {
|
|
92
|
+
newItems.value.push({ val: '', checked: false })
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
{ deep: true }
|
|
96
|
+
)
|
|
97
|
+
</script>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
ref="dialogRef"
|
|
4
4
|
@hide="onDialogHide"
|
|
5
5
|
>
|
|
6
|
-
<q-card style="
|
|
6
|
+
<q-card style="width: 400px; max-width: 600px">
|
|
7
7
|
<q-card-section class="q-pb-xs">
|
|
8
8
|
<p class="text-h6">{{ title }}</p>
|
|
9
9
|
<p v-html="message" />
|
|
@@ -14,30 +14,50 @@
|
|
|
14
14
|
<q-input
|
|
15
15
|
v-if="spec.type === 'string'"
|
|
16
16
|
v-model="spec.value"
|
|
17
|
-
:label="field"
|
|
17
|
+
:label="spec.label ?? field"
|
|
18
|
+
:hint="spec.hint"
|
|
18
19
|
/>
|
|
19
20
|
<q-input
|
|
20
21
|
v-if="spec.type === 'number'"
|
|
21
22
|
v-model.number="spec.value"
|
|
22
|
-
:label="field"
|
|
23
|
+
:label="spec.label ?? field"
|
|
23
24
|
type="number"
|
|
25
|
+
:hint="spec.hint"
|
|
24
26
|
/>
|
|
25
27
|
<q-checkbox
|
|
26
28
|
v-if="spec.type === 'boolean'"
|
|
27
29
|
v-model="spec.value"
|
|
28
|
-
:label="field"
|
|
30
|
+
:label="spec.label ?? field"
|
|
31
|
+
/>
|
|
32
|
+
<q-input
|
|
33
|
+
v-if="spec.type === 'date'"
|
|
34
|
+
v-model="spec.value"
|
|
35
|
+
:label="spec.label ?? field"
|
|
36
|
+
type="date"
|
|
37
|
+
:hint="spec.hint"
|
|
38
|
+
/>
|
|
39
|
+
<q-input
|
|
40
|
+
v-if="spec.type === 'time'"
|
|
41
|
+
v-model="spec.value"
|
|
42
|
+
:label="spec.label ?? field"
|
|
43
|
+
type="time"
|
|
44
|
+
:hint="spec.hint"
|
|
29
45
|
/>
|
|
30
46
|
<q-select
|
|
31
47
|
v-if="spec.type === 'select'"
|
|
32
48
|
v-model="spec.value"
|
|
33
49
|
:options="spec.options"
|
|
34
|
-
:label="field"
|
|
50
|
+
:label="spec.label ?? field"
|
|
51
|
+
:hint="spec.hint"
|
|
35
52
|
/>
|
|
36
53
|
<qx-input-autocomplete
|
|
37
54
|
v-if="spec.type === 'autocomplete'"
|
|
38
55
|
v-model="spec.value"
|
|
39
56
|
:autocomplete="spec.options"
|
|
40
|
-
:label="field"
|
|
57
|
+
:label="spec.label ?? field"
|
|
58
|
+
:hint="spec.hint"
|
|
59
|
+
:no-filter="spec.noFilter"
|
|
60
|
+
:immediate="spec.immediate"
|
|
41
61
|
/>
|
|
42
62
|
</div>
|
|
43
63
|
<div
|
|
@@ -68,7 +88,7 @@
|
|
|
68
88
|
|
|
69
89
|
<script lang="ts" setup>
|
|
70
90
|
import { useDialogPluginComponent } from 'quasar'
|
|
71
|
-
import { computed, reactive, ref } from 'vue'
|
|
91
|
+
import { computed, reactive, ref, watch } from 'vue'
|
|
72
92
|
|
|
73
93
|
defineEmits([...useDialogPluginComponent.emits])
|
|
74
94
|
|
|
@@ -77,20 +97,37 @@ const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
|
|
|
77
97
|
|
|
78
98
|
type row = Record<string, string | number | boolean>
|
|
79
99
|
|
|
80
|
-
type prefill = Record<
|
|
100
|
+
export type prefill = Record<
|
|
81
101
|
string,
|
|
82
|
-
| { type: 'string'; value: string }
|
|
83
|
-
| { type: 'number'; value: number }
|
|
84
|
-
| { type: 'boolean'; value: boolean }
|
|
85
|
-
| { type: '
|
|
86
|
-
| { type: '
|
|
102
|
+
| { type: 'string'; value: string; label?: string; hint?: string }
|
|
103
|
+
| { type: 'number'; value: number; label?: string; hint?: string }
|
|
104
|
+
| { type: 'boolean'; value: boolean; label?: string }
|
|
105
|
+
| { type: 'date'; value: string; label?: string; hint?: string }
|
|
106
|
+
| { type: 'time'; value: string; label?: string; hint?: string }
|
|
107
|
+
| {
|
|
108
|
+
type: 'select'
|
|
109
|
+
value: string
|
|
110
|
+
options: string[]
|
|
111
|
+
label?: string
|
|
112
|
+
hint?: string
|
|
113
|
+
}
|
|
114
|
+
| {
|
|
115
|
+
type: 'autocomplete'
|
|
116
|
+
value: string
|
|
117
|
+
options: string[]
|
|
118
|
+
label?: string
|
|
119
|
+
hint?: string
|
|
120
|
+
noFilter?: boolean
|
|
121
|
+
immediate?: boolean
|
|
122
|
+
}
|
|
87
123
|
>
|
|
88
124
|
|
|
89
|
-
const { title, message, prefill, validators } = defineProps<{
|
|
125
|
+
const { title, message, prefill, validators, onChange } = defineProps<{
|
|
90
126
|
title: string
|
|
91
127
|
message: string
|
|
92
128
|
prefill: prefill
|
|
93
129
|
validators: [(_: row) => boolean, string][]
|
|
130
|
+
onChange: (current: prefill, old: prefill) => void
|
|
94
131
|
}>()
|
|
95
132
|
|
|
96
133
|
const content = reactive(JSON.clone(prefill))
|
|
@@ -103,4 +140,9 @@ function err(): false | string {
|
|
|
103
140
|
}
|
|
104
141
|
return false
|
|
105
142
|
}
|
|
143
|
+
|
|
144
|
+
watch(
|
|
145
|
+
() => JSON.stringify(content),
|
|
146
|
+
(newbie, oldie) => onChange(content, JSON.parse(oldie))
|
|
147
|
+
)
|
|
106
148
|
</script>
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<q-dialog
|
|
3
|
+
ref="dialogRef"
|
|
4
|
+
@hide="onDialogHide"
|
|
5
|
+
>
|
|
6
|
+
<q-card style="width: 400px">
|
|
7
|
+
<q-card-section>
|
|
8
|
+
<p class="text-h6">{{ title }}</p>
|
|
9
|
+
<p v-html="message" />
|
|
10
|
+
<div style="max-height: 340px; overflow-y: auto">
|
|
11
|
+
<div v-for="item in items">
|
|
12
|
+
<q-radio
|
|
13
|
+
v-model="select"
|
|
14
|
+
:val="item"
|
|
15
|
+
:label="item"
|
|
16
|
+
/>
|
|
17
|
+
</div>
|
|
18
|
+
<div class="row q-pr-md">
|
|
19
|
+
<q-radio
|
|
20
|
+
class="col-auto"
|
|
21
|
+
v-model="select"
|
|
22
|
+
:val="add"
|
|
23
|
+
/>
|
|
24
|
+
<q-input
|
|
25
|
+
class="col"
|
|
26
|
+
v-model="add"
|
|
27
|
+
:label="newLabel"
|
|
28
|
+
dense
|
|
29
|
+
/>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
</q-card-section>
|
|
33
|
+
|
|
34
|
+
<q-card-actions align="right">
|
|
35
|
+
<q-btn
|
|
36
|
+
label="Cancel"
|
|
37
|
+
flat
|
|
38
|
+
@click="onDialogCancel"
|
|
39
|
+
/>
|
|
40
|
+
<q-btn
|
|
41
|
+
label="OK"
|
|
42
|
+
flat
|
|
43
|
+
@click="onDialogOK(select)"
|
|
44
|
+
:disable="
|
|
45
|
+
![...items, add].includes(select) || !isValid(select)
|
|
46
|
+
"
|
|
47
|
+
/>
|
|
48
|
+
</q-card-actions>
|
|
49
|
+
</q-card>
|
|
50
|
+
</q-dialog>
|
|
51
|
+
</template>
|
|
52
|
+
|
|
53
|
+
<script lang="ts" setup>
|
|
54
|
+
import { useDialogPluginComponent } from 'quasar'
|
|
55
|
+
import { ref, watch } from 'vue'
|
|
56
|
+
|
|
57
|
+
defineEmits([...useDialogPluginComponent.emits])
|
|
58
|
+
|
|
59
|
+
const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
|
|
60
|
+
useDialogPluginComponent()
|
|
61
|
+
|
|
62
|
+
const props = defineProps<{
|
|
63
|
+
title: string
|
|
64
|
+
message: string
|
|
65
|
+
items: string[]
|
|
66
|
+
prefill: string
|
|
67
|
+
newLabel: string
|
|
68
|
+
isValid: (_: string) => boolean
|
|
69
|
+
}>()
|
|
70
|
+
|
|
71
|
+
let select = ref(props.prefill)
|
|
72
|
+
let add = ref('')
|
|
73
|
+
|
|
74
|
+
watch(add, () => {
|
|
75
|
+
select.value = add.value
|
|
76
|
+
})
|
|
77
|
+
</script>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Dialog, QDialogOptions } from 'quasar'
|
|
2
|
+
import type { Component } from 'vue'
|
|
3
|
+
|
|
4
|
+
export async function base(component: Component, props: any) {
|
|
5
|
+
return new Promise<any>((resolve, reject) =>
|
|
6
|
+
Dialog.create({
|
|
7
|
+
component,
|
|
8
|
+
componentProps: {
|
|
9
|
+
persistent: true,
|
|
10
|
+
...props,
|
|
11
|
+
},
|
|
12
|
+
})
|
|
13
|
+
.onOk((data: any) => resolve(data))
|
|
14
|
+
.onCancel(() => reject('dialog cancelled by user.'))
|
|
15
|
+
)
|
|
16
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import dialogForm from './custom/dialogForm.vue'
|
|
2
|
+
import { base } from './custom_base'
|
|
3
|
+
|
|
4
|
+
type FormPrefill = Record<
|
|
5
|
+
string,
|
|
6
|
+
| string
|
|
7
|
+
| number
|
|
8
|
+
| boolean
|
|
9
|
+
| { type: 'string'; value: string; label?: string; hint?: string }
|
|
10
|
+
| { type: 'number'; value: number; label?: string; hint?: string }
|
|
11
|
+
| { type: 'boolean'; value: boolean; label?: string }
|
|
12
|
+
| { type: 'date'; value: string; label?: string; hint?: string }
|
|
13
|
+
| { type: 'time'; value: string; label?: string; hint?: string }
|
|
14
|
+
| {
|
|
15
|
+
type: 'select'
|
|
16
|
+
value: string
|
|
17
|
+
options: string[]
|
|
18
|
+
label?: string
|
|
19
|
+
hint?: string
|
|
20
|
+
}
|
|
21
|
+
| {
|
|
22
|
+
type: 'autocomplete'
|
|
23
|
+
value: string
|
|
24
|
+
options: string[]
|
|
25
|
+
label?: string
|
|
26
|
+
hint?: string
|
|
27
|
+
noFilter?: boolean
|
|
28
|
+
immediate?: boolean
|
|
29
|
+
}
|
|
30
|
+
>
|
|
31
|
+
|
|
32
|
+
type FormPrefillStandard<T extends FormPrefill> = {
|
|
33
|
+
[P in keyof T]: T[P] extends object
|
|
34
|
+
? T[P]
|
|
35
|
+
: T[P] extends string
|
|
36
|
+
? { type: 'string'; value: string; label?: string; hint?: string }
|
|
37
|
+
: T[P] extends number
|
|
38
|
+
? { type: 'number'; value: number; label?: string; hint?: string }
|
|
39
|
+
: T[P] extends boolean
|
|
40
|
+
? { type: 'boolean'; value: boolean; label?: string }
|
|
41
|
+
: never
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
type FormFlat<T extends FormPrefill> = {
|
|
45
|
+
[P in keyof T]: T[P] extends object ? T[P]['value'] : T[P]
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Ask for an objects.
|
|
50
|
+
*/
|
|
51
|
+
export async function askForm<T extends FormPrefill>(
|
|
52
|
+
title: string,
|
|
53
|
+
message: string,
|
|
54
|
+
prefill: T,
|
|
55
|
+
validators: [(_: FormFlat<T>) => boolean, string][] = [[$ => true, '']],
|
|
56
|
+
onChange: (
|
|
57
|
+
current: FormPrefillStandard<T>,
|
|
58
|
+
old: FormPrefillStandard<T>
|
|
59
|
+
) => void = (c, o) => {}
|
|
60
|
+
): Promise<FormFlat<T>> {
|
|
61
|
+
const standardPrefill = Object.mapValues(prefill, $ => {
|
|
62
|
+
if (typeof $ === 'string') return { type: 'string', value: $ }
|
|
63
|
+
if (typeof $ === 'number') return { type: 'number', value: $ }
|
|
64
|
+
if (typeof $ === 'boolean') return { type: 'boolean', value: $ }
|
|
65
|
+
return $
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
return await base(dialogForm, {
|
|
69
|
+
title,
|
|
70
|
+
message,
|
|
71
|
+
prefill: standardPrefill,
|
|
72
|
+
validators,
|
|
73
|
+
onChange,
|
|
74
|
+
})
|
|
75
|
+
}
|
|
@@ -9,7 +9,7 @@ type onfulfilled<T, U> = ((value: T) => Promisable<U>) | undefined | null
|
|
|
9
9
|
type onrejected<U> = ((reason: any) => Promisable<U>) | undefined | null
|
|
10
10
|
|
|
11
11
|
abstract class BuilderUI {
|
|
12
|
-
private
|
|
12
|
+
private isSilence: boolean = false
|
|
13
13
|
private isConfirm: boolean = false
|
|
14
14
|
private confirmContent: { title: string; msg: string } = {
|
|
15
15
|
title: '',
|
|
@@ -21,7 +21,7 @@ abstract class BuilderUI {
|
|
|
21
21
|
protected abstract dataLogic(): Promise<void>
|
|
22
22
|
|
|
23
23
|
protected async run() {
|
|
24
|
-
if (this.
|
|
24
|
+
if (this.isSilence) ui.loadingOff()
|
|
25
25
|
|
|
26
26
|
if (this.isConfirm) {
|
|
27
27
|
let { title, msg } = this.confirmContent
|
|
@@ -32,7 +32,7 @@ abstract class BuilderUI {
|
|
|
32
32
|
|
|
33
33
|
if (this.isNotify) ui.onNotify(this.notifyContent)
|
|
34
34
|
|
|
35
|
-
if (this.
|
|
35
|
+
if (this.isSilence) ui.loadingOn()
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
confirm(title: string, ...msgs: string[]): this {
|
|
@@ -52,8 +52,17 @@ abstract class BuilderUI {
|
|
|
52
52
|
return this
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
/**
|
|
56
|
+
* @deprecated
|
|
57
|
+
*/
|
|
55
58
|
slience(): this {
|
|
56
|
-
this.
|
|
59
|
+
this.isSilence = true
|
|
60
|
+
this.isNotify = false
|
|
61
|
+
return this
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
silence(): this {
|
|
65
|
+
this.isSilence = true
|
|
57
66
|
this.isNotify = false
|
|
58
67
|
return this
|
|
59
68
|
}
|