@hostlink/nuxt-light 1.22.2 → 1.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/module.json +1 -1
- package/dist/module.mjs +15 -0
- package/dist/runtime/components/L/CustomField/Add.vue +94 -0
- package/dist/runtime/components/L/CustomField/List.vue +35 -0
- package/dist/runtime/components/L/System/Setting/developer.vue +20 -3
- package/dist/runtime/components/L/ValidationInput.vue +105 -0
- package/dist/runtime/components/l-date-picker.vue +4 -0
- package/dist/runtime/components/l-file-manager-labels.vue +6 -1
- package/dist/runtime/components/l-file-manager.vue +0 -4
- package/dist/runtime/components/l-group-select.vue +115 -0
- package/dist/runtime/components/l-input.vue +1 -1
- package/dist/runtime/components/l-table.vue +1 -1
- package/dist/runtime/components/l-time-picker.vue +4 -0
- package/dist/runtime/formkit/DatePicker.vue +4 -0
- package/dist/runtime/formkit/GroupSelect.vue +34 -0
- package/dist/runtime/formkit/Input.vue +4 -0
- package/dist/runtime/formkit/Repeater.vue +35 -38
- package/dist/runtime/formkit/TimePicker.vue +4 -0
- package/dist/runtime/formkit/index.js +6 -0
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/light.d.ts +6 -1123
- package/dist/runtime/model/CustomField.d.ts +26 -0
- package/dist/runtime/model/CustomField.js +25 -0
- package/dist/runtime/pages/CustomField/[custom_field_id]/edit.vue +64 -0
- package/dist/runtime/pages/CustomField/index.vue +43 -0
- package/dist/runtime/pages/Role/add2.vue +68 -0
- package/dist/runtime/pages/System/database/table.vue +2 -2
- package/dist/runtime/pages/System/setting.vue +3 -0
- package/dist/runtime/plugin.js +2 -0
- package/package.json +2 -2
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -5,6 +5,16 @@ import { quasar } from '@quasar/vite-plugin';
|
|
|
5
5
|
|
|
6
6
|
const resolver = createResolver(import.meta.url);
|
|
7
7
|
const routes = [
|
|
8
|
+
{
|
|
9
|
+
name: "CustomField",
|
|
10
|
+
path: "/CustomField",
|
|
11
|
+
file: resolver.resolve("./runtime/pages/CustomField/index.vue")
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
name: "CustomField-custom_field_id-edit",
|
|
15
|
+
path: "/CustomField/:custom_field_id/edit",
|
|
16
|
+
file: resolver.resolve("./runtime/pages/CustomField/[custom_field_id]/edit.vue")
|
|
17
|
+
},
|
|
8
18
|
{
|
|
9
19
|
name: "EventLog",
|
|
10
20
|
path: "/EventLog",
|
|
@@ -75,6 +85,11 @@ const routes = [
|
|
|
75
85
|
path: "/Role/add",
|
|
76
86
|
file: resolver.resolve("./runtime/pages/Role/add.vue")
|
|
77
87
|
},
|
|
88
|
+
{
|
|
89
|
+
name: "Role-add2",
|
|
90
|
+
path: "/Role/add2",
|
|
91
|
+
file: resolver.resolve("./runtime/pages/Role/add2.vue")
|
|
92
|
+
},
|
|
78
93
|
{
|
|
79
94
|
name: "System-fs",
|
|
80
95
|
path: "/System/fs",
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { useDialogPluginComponent, useQuasar } from 'quasar'
|
|
3
|
+
import { m, q } from "#imports"
|
|
4
|
+
const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } = useDialogPluginComponent()
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
defineProps({
|
|
8
|
+
models: {
|
|
9
|
+
type: Array,
|
|
10
|
+
required: true
|
|
11
|
+
}
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
const $q = useQuasar()
|
|
15
|
+
|
|
16
|
+
defineEmits([
|
|
17
|
+
// REQUIRED; need to specify some events that your
|
|
18
|
+
// component will emit through useDialogPluginComponent()
|
|
19
|
+
...useDialogPluginComponent.emits
|
|
20
|
+
])
|
|
21
|
+
|
|
22
|
+
const types = [
|
|
23
|
+
{ label: 'Text', value: 'text' },
|
|
24
|
+
{ label: 'Textarea', value: 'textarea' },
|
|
25
|
+
{ label: 'Select', value: 'select' },
|
|
26
|
+
{ label: 'Date', value: 'date' },
|
|
27
|
+
{ label: 'Time', value: 'time' }
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
const onOKClick = async (value) => {
|
|
31
|
+
try {
|
|
32
|
+
await m("addCustomField", {
|
|
33
|
+
data: value
|
|
34
|
+
})
|
|
35
|
+
//show success message
|
|
36
|
+
$q.notify({
|
|
37
|
+
icon: 'sym_o_check',
|
|
38
|
+
message: 'Custom Field added successfully',
|
|
39
|
+
color: 'positive',
|
|
40
|
+
})
|
|
41
|
+
onDialogOK()
|
|
42
|
+
|
|
43
|
+
} catch (e) {
|
|
44
|
+
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
</script>
|
|
51
|
+
<template>
|
|
52
|
+
<q-dialog ref="dialogRef" full-width>
|
|
53
|
+
<q-card class="q-dialog-plugin">
|
|
54
|
+
<q-toolbar>
|
|
55
|
+
<q-toolbar-title>Add Custom Field</q-toolbar-title>
|
|
56
|
+
<q-space />
|
|
57
|
+
<q-btn dense flat icon="sym_o_close" v-close-popup />
|
|
58
|
+
</q-toolbar>
|
|
59
|
+
|
|
60
|
+
<form-kit type="l-form"
|
|
61
|
+
:value="{ type: 'text', order: 1, options: [], default_value: '', placeholder: '', validation: '' }"
|
|
62
|
+
#default="{ value, node }" @submit="onOKClick">
|
|
63
|
+
<form-kit type="l-input" name="name" label="Name" validation="required" />
|
|
64
|
+
|
|
65
|
+
<form-kit type="l-select" name="model" label="Model" :options="models" validation="required" />
|
|
66
|
+
|
|
67
|
+
<form-kit type="l-select" name="type" label="Type" :options="types" validation="required" />
|
|
68
|
+
|
|
69
|
+
<form-kit type="hidden" name="validation" />
|
|
70
|
+
<l-validation-input v-model="value.validation" @update:model-value="node.at('validation').input($event)"
|
|
71
|
+
:type="value.type" />
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
<form-kit type="l-input" name="label" label="Label" validation="required" />
|
|
75
|
+
|
|
76
|
+
<form-kit type="hidden" name="options" />
|
|
77
|
+
<template v-if="value.type === 'select'">
|
|
78
|
+
<form-kit type="l-select" label="Options" name="options" use-input use-chips multiple
|
|
79
|
+
hide-dropdown-icon input-debounce="0" new-value-mode="add-unique" stack-label outlined
|
|
80
|
+
placeholder="Press enter to add new option" />
|
|
81
|
+
</template>
|
|
82
|
+
|
|
83
|
+
<form-kit type="l-input" name="default_value" label="Default Value" />
|
|
84
|
+
|
|
85
|
+
<form-kit type="l-input" name="placeholder" label="Placeholder" />
|
|
86
|
+
|
|
87
|
+
<form-kit type="l-input" input-type="number" name="order" label="Order" number />
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
</form-kit>
|
|
91
|
+
|
|
92
|
+
</q-card>
|
|
93
|
+
</q-dialog>
|
|
94
|
+
</template>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { q } from '#imports'
|
|
3
|
+
|
|
4
|
+
import type { QListProps } from 'quasar';
|
|
5
|
+
|
|
6
|
+
export interface LCustomFieldListProps extends QListProps {
|
|
7
|
+
model: String,
|
|
8
|
+
data: { [key: string]: any }
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const props = withDefaults(defineProps<LCustomFieldListProps>(), {
|
|
12
|
+
bordered: true,
|
|
13
|
+
separator: true,
|
|
14
|
+
dense: true,
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
const { app } = await q({
|
|
19
|
+
app: {
|
|
20
|
+
customFieldSchema: {
|
|
21
|
+
__args: {
|
|
22
|
+
model: props.model
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
const { customFieldSchema } = app
|
|
28
|
+
</script>
|
|
29
|
+
<template>
|
|
30
|
+
<q-list v-bind="$props">
|
|
31
|
+
<l-item v-for="field in customFieldSchema" :label="field.label">
|
|
32
|
+
{{ data[field.name] }}
|
|
33
|
+
</l-item>
|
|
34
|
+
</q-list>
|
|
35
|
+
</template>
|
|
@@ -6,7 +6,8 @@ const $q = useQuasar()
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
export interface LSystemSettingDeveloperProps {
|
|
9
|
-
mode: string
|
|
9
|
+
mode: string,
|
|
10
|
+
custom_field_models: string,
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
const modelValue = defineModel<LSystemSettingDeveloperProps>({
|
|
@@ -19,6 +20,14 @@ if (modelValue.value.mode != 'prod') {
|
|
|
19
20
|
modelValue.value.mode = 'prod'
|
|
20
21
|
}
|
|
21
22
|
|
|
23
|
+
//split the custom_field_models by comma
|
|
24
|
+
if (modelValue.value.custom_field_models != "") {
|
|
25
|
+
modelValue.value.custom_field_models = modelValue.value.custom_field_models.split(',')
|
|
26
|
+
} else {
|
|
27
|
+
modelValue.value.custom_field_models = []
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
22
31
|
const onSubmit = async (d: LSystemSettingDeveloperProps) => {
|
|
23
32
|
let data: { name: string, value: string }[] = [];
|
|
24
33
|
Object.keys(d).forEach((key) => {
|
|
@@ -39,13 +48,21 @@ const onSubmit = async (d: LSystemSettingDeveloperProps) => {
|
|
|
39
48
|
</script>
|
|
40
49
|
<template>
|
|
41
50
|
<FormKit type="l-form" :bordered="false" :value="{
|
|
42
|
-
mode: modelValue.mode
|
|
43
|
-
|
|
51
|
+
mode: modelValue.mode,
|
|
52
|
+
custom_field_models: modelValue.custom_field_models
|
|
53
|
+
}" @submit="onSubmit" #default="{ value }">
|
|
54
|
+
|
|
55
|
+
<form-kit type="l-select" name="custom_field_models" label="Custom Field Model" use-input use-chips multiple
|
|
56
|
+
hide-dropdown-icon input-debounce="0" new-value-mode="add-unique" />
|
|
57
|
+
|
|
44
58
|
<FormKit label="Mode" type="l-select" :options="[
|
|
45
59
|
{ label: 'Production', value: 'prod' },
|
|
46
60
|
{ label: 'Development', value: 'dev' },
|
|
47
61
|
|
|
48
62
|
]" name="mode" validation="required">
|
|
63
|
+
|
|
49
64
|
</FormKit>
|
|
65
|
+
|
|
66
|
+
|
|
50
67
|
</FormKit>
|
|
51
68
|
</template>
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { computed, watch, reactive } from 'vue';
|
|
3
|
+
const model = defineModel({
|
|
4
|
+
type: String,
|
|
5
|
+
default: ""
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
const props = defineProps({
|
|
9
|
+
type: {
|
|
10
|
+
type: String,
|
|
11
|
+
default: "text"
|
|
12
|
+
}
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
const isRequired = computed(() => {
|
|
16
|
+
return model.value.split("|").includes("required");
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const isEmail = computed(() => {
|
|
20
|
+
return model.value.split("|").includes("email");
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const isNumber = computed(() => {
|
|
24
|
+
return model.value.split("|").includes("number");
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const lenghtMin = computed(() => {
|
|
28
|
+
const length = model.value.split("|").find((v) => v.includes("length"));
|
|
29
|
+
if (length) {
|
|
30
|
+
return length.split(":")[1].split(",")[0];
|
|
31
|
+
}
|
|
32
|
+
return 0;
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const lenghtMax = computed(() => {
|
|
36
|
+
const length = model.value.split("|").find((v) => v.includes("length"));
|
|
37
|
+
if (length) {
|
|
38
|
+
return length.split(":")[1].split(",")[1];
|
|
39
|
+
}
|
|
40
|
+
return 0;
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
const form = reactive({
|
|
45
|
+
required: isRequired.value,
|
|
46
|
+
email: isEmail.value,
|
|
47
|
+
number: isNumber.value,
|
|
48
|
+
length_min: lenghtMin.value,
|
|
49
|
+
length_max: lenghtMax.value
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
watch(form, () => {
|
|
53
|
+
|
|
54
|
+
//repack the validation string
|
|
55
|
+
let validation = [];
|
|
56
|
+
if (form.required) {
|
|
57
|
+
validation.push("required");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
if (props.type == "text") {
|
|
62
|
+
if (form.email) {
|
|
63
|
+
validation.push("email");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (form.number) {
|
|
67
|
+
validation.push("number");
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (form.length_min > 0 || form.length_max > 0) {
|
|
71
|
+
|
|
72
|
+
if (form.length_max > 0) {
|
|
73
|
+
validation.push(`length:${form.length_min},${form.length_max}`);
|
|
74
|
+
} else {
|
|
75
|
+
validation.push(`length:${form.length_min}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
model.value = validation.join("|");
|
|
81
|
+
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
</script>
|
|
85
|
+
|
|
86
|
+
<template>
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
<q-checkbox left-label v-model="form.required" label="Required" :color="$light.color" />
|
|
90
|
+
|
|
91
|
+
<q-checkbox left-label v-model="form.email" label="Email" :color="$light.color" v-if="type == 'text'" />
|
|
92
|
+
|
|
93
|
+
<q-checkbox left-label v-model="form.number" label="Number" :color="$light.color" v-if="type == 'text'" />
|
|
94
|
+
|
|
95
|
+
<l-row v-if="type = 'text'">
|
|
96
|
+
<l-col :md="6">
|
|
97
|
+
<q-input label="Length min" v-model="form.length_min" type="number" stack-label outlined dense :min="0" />
|
|
98
|
+
</l-col>
|
|
99
|
+
<l-col :md="6">
|
|
100
|
+
<q-input label="Length max" v-model="form.length_max" type="number" stack-label outlined dense :min="0" />
|
|
101
|
+
</l-col>
|
|
102
|
+
</l-row>
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
</template>
|
|
@@ -156,5 +156,9 @@ const date_attrs = computed(() => {
|
|
|
156
156
|
</q-popup-proxy>
|
|
157
157
|
</q-btn>
|
|
158
158
|
</template>
|
|
159
|
+
|
|
160
|
+
<template v-for="(s, name) in $slots" v-slot:[name]="props" :key="name">
|
|
161
|
+
<slot :name="name" v-bind="props ?? {}"></slot>
|
|
162
|
+
</template>
|
|
159
163
|
</q-input>
|
|
160
164
|
</template>
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import collect from "collect.js";
|
|
3
|
+
|
|
4
|
+
import { computed, onMounted, useAttrs, ref } from "vue";
|
|
5
|
+
|
|
6
|
+
const props = defineProps({
|
|
7
|
+
options: {
|
|
8
|
+
type: Array,
|
|
9
|
+
required: true,
|
|
10
|
+
},
|
|
11
|
+
emitValue: {
|
|
12
|
+
type: Boolean,
|
|
13
|
+
default: true,
|
|
14
|
+
},
|
|
15
|
+
mapOptions: {
|
|
16
|
+
type: Boolean,
|
|
17
|
+
default: true,
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const userString = ref("");
|
|
22
|
+
const items = computed(() => {
|
|
23
|
+
|
|
24
|
+
//filter out items based on user input
|
|
25
|
+
|
|
26
|
+
const filteredItems = collect(props.options)
|
|
27
|
+
.filter((item) => {
|
|
28
|
+
if (userString.value === "") {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
return item.label.toLowerCase().includes(userString.value);
|
|
32
|
+
})
|
|
33
|
+
.toArray();
|
|
34
|
+
|
|
35
|
+
const groups = collect(filteredItems).unique("group").pluck("group").sort();
|
|
36
|
+
|
|
37
|
+
const options = collect();
|
|
38
|
+
groups.each((group) => {
|
|
39
|
+
const items = collect(filteredItems).where("group", group).toArray();
|
|
40
|
+
options
|
|
41
|
+
.push({ label: group, is_group: true, disable: true })
|
|
42
|
+
.push(...items);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
return options.toArray();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const model = defineModel();
|
|
49
|
+
|
|
50
|
+
const attrs = useAttrs();
|
|
51
|
+
const handleItemUniqueByGroup = (items) => {
|
|
52
|
+
return;
|
|
53
|
+
if (!attrs.hasOwnProperty("multiple") || attrs.multiple === false) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
/*
|
|
57
|
+
model.value = collect(items)
|
|
58
|
+
.unique((item) => {
|
|
59
|
+
// Allow selecting multiple items that are not grouped
|
|
60
|
+
if (item.group === null) {
|
|
61
|
+
return item.value;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return item.group;
|
|
65
|
+
})
|
|
66
|
+
.toArray(); */
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
onMounted(() => {
|
|
70
|
+
//這個功能是為了避免在多選的情況下,選擇同一個group的item
|
|
71
|
+
// handleItemUniqueByGroup(model.value);
|
|
72
|
+
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const filterFn = (val, update, abort) => {
|
|
76
|
+
if (val === "") {
|
|
77
|
+
update(() => {
|
|
78
|
+
userString.value = "";
|
|
79
|
+
});
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const needle = val.toLowerCase();
|
|
84
|
+
update(() => {
|
|
85
|
+
userString.value = needle;
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
</script>
|
|
90
|
+
|
|
91
|
+
<template>
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
<q-select v-model="model" v-bind="$light.getInputProps($props)" :options="items" @update:model-value="handleItemUniqueByGroup"
|
|
95
|
+
input-debounce="0" @filter="filterFn" :color="$light.color" :style="$light.styles.input"
|
|
96
|
+
:emit-value="emitValue" :map-options="mapOptions">
|
|
97
|
+
<template v-slot:option="scope">
|
|
98
|
+
<q-item v-if="scope.opt.is_group" v-bind="{ ...scope.itemProps }" class="text-xs bg-grey-4" :key="scope.opt.label">
|
|
99
|
+
<q-item-section class="!cursor-default">
|
|
100
|
+
{{ scope.opt.label || "Ungroup" }}
|
|
101
|
+
</q-item-section>
|
|
102
|
+
</q-item>
|
|
103
|
+
<q-item v-else v-bind="{ ...scope.itemProps }" :key="scope.opt.value">
|
|
104
|
+
<q-item-section class="q-pl-md">{{ scope.opt.label }}</q-item-section>
|
|
105
|
+
</q-item>
|
|
106
|
+
</template>
|
|
107
|
+
<template v-slot:no-option>
|
|
108
|
+
<q-item>
|
|
109
|
+
<q-item-section class="text-grey">
|
|
110
|
+
No results
|
|
111
|
+
</q-item-section>
|
|
112
|
+
</q-item>
|
|
113
|
+
</template>
|
|
114
|
+
</q-select>
|
|
115
|
+
</template>
|
|
@@ -550,7 +550,7 @@ const onAdd = () => {
|
|
|
550
550
|
v-model:minimized="minimized" v-model:maximized="maximized">
|
|
551
551
|
|
|
552
552
|
<q-toolbar v-if="addComponent">
|
|
553
|
-
<q-btn icon="sym_o_add" :label="$t('Add')" :color="$light.color" @click="onAdd" v-if="addComponent" />
|
|
553
|
+
<q-btn icon="sym_o_add" :label="$t('Add')" :color="$light.color" @click="onAdd" v-if="addComponent" outline />
|
|
554
554
|
</q-toolbar>
|
|
555
555
|
|
|
556
556
|
|
|
@@ -33,5 +33,9 @@ const value = computed({
|
|
|
33
33
|
<template v-for="(s, name) in $slots" v-slot:[name]="props" :key="name">
|
|
34
34
|
<slot :name="name" v-bind="props ?? {}"></slot>
|
|
35
35
|
</template>
|
|
36
|
+
|
|
37
|
+
<template v-if="context.help" #hint>
|
|
38
|
+
{{ context.help }}
|
|
39
|
+
</template>
|
|
36
40
|
</l-date-picker>
|
|
37
41
|
</template>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { getErrorMessage } from 'formkit-quasar';
|
|
3
|
+
import { computed } from 'vue'
|
|
4
|
+
const props = defineProps({
|
|
5
|
+
context: Object
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
const { error, errorMessage } = getErrorMessage(props.context.node);
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
const value = computed({
|
|
13
|
+
get: () => props.context.value,
|
|
14
|
+
set: (val) => props.context.node.input(val)
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
let clearable = false;
|
|
19
|
+
if (props.context.state.required) { //no clearable
|
|
20
|
+
clearable = false;
|
|
21
|
+
} else {
|
|
22
|
+
clearable = true;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
</script>
|
|
26
|
+
<template>
|
|
27
|
+
<l-group-select v-model="value" :label="context.label" v-bind="context.attrs" :error="error"
|
|
28
|
+
:error-message="errorMessage" :required="context.state.required"
|
|
29
|
+
:disable="context.disabled">
|
|
30
|
+
<template v-for="(s, name) in $slots" v-slot:[name]="props" :key="name">
|
|
31
|
+
<slot :name="name" v-bind="props ?? {}"></slot>
|
|
32
|
+
</template>
|
|
33
|
+
</l-group-select>
|
|
34
|
+
</template>
|
|
@@ -64,5 +64,9 @@ const label = computed(() => {
|
|
|
64
64
|
<template v-for="(s, name) in $slots" v-slot:[name]="props" :key="name">
|
|
65
65
|
<slot :name="name" v-bind="props ?? {}"></slot>
|
|
66
66
|
</template>
|
|
67
|
+
|
|
68
|
+
<template v-if="context.help" #hint>
|
|
69
|
+
{{ context.help }}
|
|
70
|
+
</template>
|
|
67
71
|
</l-input>
|
|
68
72
|
</template>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { computed } from 'vue'
|
|
3
|
-
import { useDragAndDrop } from "@formkit/drag-and-drop/vue";
|
|
3
|
+
import { useDragAndDrop, dragAndDrop } from "@formkit/drag-and-drop/vue";
|
|
4
4
|
import { animations } from "@formkit/drag-and-drop";
|
|
5
5
|
|
|
6
6
|
const props = defineProps({
|
|
@@ -69,49 +69,46 @@ const isAllowMoveDown = (index) => {
|
|
|
69
69
|
|
|
70
70
|
</script>
|
|
71
71
|
|
|
72
|
+
<style>
|
|
73
|
+
.cursor-grab{cursor:grab}.cursor-grabbing{cursor:grabbing}
|
|
74
|
+
</style>
|
|
75
|
+
|
|
72
76
|
<template>
|
|
73
77
|
<FormKit type="list" v-model="localValue" dynamic #default="{ items, node, value }" :name="node.name">
|
|
78
|
+
{{ sortable }}
|
|
74
79
|
|
|
75
|
-
<
|
|
80
|
+
<q-list bordered separator ref="parent">
|
|
76
81
|
<FormKit type="group" v-for="(item, index) in items" :index="index" :key="item">
|
|
77
|
-
<q-
|
|
78
|
-
<q-
|
|
79
|
-
<div class="
|
|
80
|
-
<
|
|
81
|
-
<div class="q-mb-xs" v-if="sortable">
|
|
82
|
-
<q-btn icon="sym_o_drag_handle" dense unelevated :color="$light.color"
|
|
83
|
-
style="cursor: grab;" class="l-repeater-handle">
|
|
84
|
-
</q-btn>
|
|
85
|
-
</div>
|
|
86
|
-
<div class="q-mb-xs" v-if="sortable">
|
|
87
|
-
<!-- up -->
|
|
88
|
-
<q-btn type="button" @click="onMoveUp(index)" icon="sym_o_arrow_upward"
|
|
89
|
-
:color="$light.color" dense unelevated :disable="!isAllowMoveUp(index)" />
|
|
90
|
-
</div>
|
|
91
|
-
|
|
92
|
-
<div class="q-mb-xs">
|
|
93
|
-
<q-btn type="button" @click="onRemove" icon="sym_o_remove" :color="$light.color"
|
|
94
|
-
dense unelevated :disable="!isAllowRemove" />
|
|
95
|
-
</div>
|
|
96
|
-
<div class="q-mb-xs" v-if="sortable">
|
|
97
|
-
<!-- down -->
|
|
98
|
-
<q-btn type="button" @click="onMoveDown(index)" icon="sym_o_arrow_downward"
|
|
99
|
-
:color="$light.color" dense unelevated :disable="!isAllowMoveDown(index)" />
|
|
100
|
-
</div>
|
|
101
|
-
</div>
|
|
102
|
-
|
|
103
|
-
<div class="col">
|
|
104
|
-
<slot v-bind="{ value: localValue[index] }"></slot>
|
|
105
|
-
</div>
|
|
82
|
+
<q-item class="q-pa-xs">
|
|
83
|
+
<q-item-section avatar class="">
|
|
84
|
+
<div class="l-repeater-handle cursor-grab active:cursor-grabbing" v-if="sortable">
|
|
85
|
+
<q-icon name="sym_o_drag_indicator" :color="$light.color" size="sm" />
|
|
106
86
|
</div>
|
|
107
|
-
</q-
|
|
108
|
-
|
|
87
|
+
</q-item-section>
|
|
88
|
+
|
|
89
|
+
<q-item-section >
|
|
90
|
+
<slot v-bind="{ value: localValue[index] }"></slot>
|
|
91
|
+
</q-item-section>
|
|
92
|
+
|
|
93
|
+
<q-item-section side>
|
|
94
|
+
<!-- up -->
|
|
95
|
+
<q-btn type="button" @click="onMoveUp(index)" icon="sym_o_arrow_upward" :color="$light.color"
|
|
96
|
+
dense flat :disable="!isAllowMoveUp(index)" />
|
|
97
|
+
|
|
98
|
+
<q-btn type="button" @click="onRemove" icon="sym_o_delete" :color="$light.color" dense
|
|
99
|
+
:disable="!isAllowRemove" flat />
|
|
100
|
+
<!-- down -->
|
|
101
|
+
<q-btn type="button" @click="onMoveDown(index)" icon="sym_o_arrow_downward"
|
|
102
|
+
:color="$light.color" dense flat :disable="!isAllowMoveDown(index)" />
|
|
103
|
+
|
|
104
|
+
</q-item-section>
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
</q-item>
|
|
108
|
+
|
|
109
109
|
</FormKit>
|
|
110
|
-
</div>
|
|
111
110
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
:disable="localValue.length >= max" unelevated></q-btn>
|
|
115
|
-
</q-toolbar>
|
|
111
|
+
</q-list>
|
|
112
|
+
<q-btn @click="onAdd" label="Add" icon="sym_o_add" :color="$light.color" outline />
|
|
116
113
|
</FormKit>
|
|
117
114
|
</template>
|
|
@@ -29,5 +29,9 @@ const label = computed(() => {
|
|
|
29
29
|
<template v-for="(s, name) in $slots" v-slot:[name]="props" :key="name">
|
|
30
30
|
<slot :name="name" v-bind="props ?? {}"></slot>
|
|
31
31
|
</template>
|
|
32
|
+
|
|
33
|
+
<template v-if="context.help" #hint>
|
|
34
|
+
{{ context.help }}
|
|
35
|
+
</template>
|
|
32
36
|
</l-time-picker>
|
|
33
37
|
</template>
|