@ramathibodi/nuxt-commons 0.1.37 → 0.1.39
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/runtime/components/ExportCSV.vue +51 -18
- package/dist/runtime/components/ImportCSV.vue +63 -12
- package/dist/runtime/components/document/Form.vue +43 -0
- package/dist/runtime/components/document/TemplateBuilder.vue +198 -62
- package/dist/runtime/components/form/Iterator.vue +256 -230
- package/dist/runtime/components/form/Pad.vue +4 -2
- package/dist/runtime/components/form/SignPad.vue +1 -1
- package/dist/runtime/components/form/Table.vue +163 -137
- package/dist/runtime/components/form/images/Capture.vue +83 -76
- package/dist/runtime/components/form/images/Edit.vue +19 -11
- package/dist/runtime/components/master/Autocomplete.vue +43 -130
- package/dist/runtime/components/master/label.vue +20 -19
- package/dist/runtime/components/model/Autocomplete.vue +23 -17
- package/dist/runtime/components/model/label.vue +8 -5
- package/dist/runtime/composables/document/template.d.ts +23 -1
- package/dist/runtime/composables/document/template.js +70 -54
- package/dist/runtime/composables/document/templateFormHidden.d.ts +2 -0
- package/dist/runtime/composables/document/templateFormHidden.js +10 -0
- package/dist/runtime/composables/document/templateFormTable.d.ts +2 -0
- package/dist/runtime/composables/document/templateFormTable.js +9 -0
- package/package.json +2 -2
package/dist/module.json
CHANGED
|
@@ -1,43 +1,76 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import {ref} from 'vue'
|
|
2
|
+
import { ref } from 'vue'
|
|
3
3
|
import * as XLSX from 'xlsx'
|
|
4
|
-
import {VBtn} from 'vuetify/components/VBtn'
|
|
5
|
-
import {useAlert} from '../composables/alert'
|
|
4
|
+
import { VBtn } from 'vuetify/components/VBtn'
|
|
5
|
+
import { useAlert } from '../composables/alert'
|
|
6
6
|
|
|
7
7
|
interface ExportButtonProps extends /* @vue-ignore */ InstanceType<typeof VBtn['$props']> {
|
|
8
8
|
fileName?: string
|
|
9
|
+
sheetName?: string
|
|
9
10
|
modelValue?: object[]
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
const props = withDefaults(defineProps<ExportButtonProps>(), {
|
|
13
14
|
fileName: 'download',
|
|
15
|
+
sheetName: 'Sheet1',
|
|
14
16
|
})
|
|
15
17
|
|
|
16
18
|
const alert = useAlert()
|
|
17
19
|
const loading = ref(false)
|
|
18
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Triggers file export
|
|
23
|
+
*/
|
|
19
24
|
function exportFile() {
|
|
20
|
-
if (props.modelValue && Array.isArray(props.modelValue)) {
|
|
25
|
+
if (props.modelValue && Array.isArray(props.modelValue) && props.modelValue.length > 0) {
|
|
21
26
|
loading.value = true
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
const workbook = XLSX.utils.book_new()
|
|
30
|
+
const worksheet = XLSX.utils.json_to_sheet(flattenNestedFields(props.modelValue))
|
|
31
|
+
const fileName = `${props.fileName}.xlsx`
|
|
32
|
+
|
|
33
|
+
XLSX.utils.book_append_sheet(workbook, worksheet, props.sheetName)
|
|
34
|
+
XLSX.writeFile(workbook, fileName)
|
|
35
|
+
} catch (error: any) {
|
|
36
|
+
alert?.addAlert({ message: `Export failed: ${error.message}`, alertType: 'error' })
|
|
37
|
+
} finally {
|
|
38
|
+
loading.value = false
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
30
41
|
alert?.addAlert({ message: 'Invalid or no data to export', alertType: 'error' })
|
|
31
42
|
}
|
|
32
43
|
}
|
|
33
44
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Recursively flattens nested fields for export
|
|
47
|
+
* @param items - Array of objects to flatten
|
|
48
|
+
*/
|
|
49
|
+
function flattenNestedFields(items: any[]) {
|
|
50
|
+
return items.map((item: any) => {
|
|
51
|
+
return flattenObject(item)
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Recursively flattens an object, converting nested keys into dot-separated keys
|
|
57
|
+
* @param obj - Object to flatten
|
|
58
|
+
* @param parentKey - Parent key (for recursion)
|
|
59
|
+
* @param separator - Separator for nested keys
|
|
60
|
+
*/
|
|
61
|
+
function flattenObject(obj: any, parentKey = '', separator = '.') {
|
|
62
|
+
return Object.keys(obj).reduce((acc: any, key: string) => {
|
|
63
|
+
const newKey = parentKey ? `${parentKey}${separator}${key}` : key
|
|
64
|
+
const value = obj[key]
|
|
65
|
+
|
|
66
|
+
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
67
|
+
Object.assign(acc, flattenObject(value, newKey, separator))
|
|
68
|
+
} else {
|
|
69
|
+
acc[newKey] = typeof value === 'object' ? JSON.stringify(value) : value
|
|
38
70
|
}
|
|
39
|
-
|
|
40
|
-
|
|
71
|
+
|
|
72
|
+
return acc
|
|
73
|
+
}, {})
|
|
41
74
|
}
|
|
42
75
|
</script>
|
|
43
76
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import * as XLSX from 'xlsx'
|
|
3
|
-
import {ref} from 'vue'
|
|
4
|
-
import {useAlert} from '../composables/alert'
|
|
3
|
+
import { ref } from 'vue'
|
|
4
|
+
import { useAlert } from '../composables/alert'
|
|
5
5
|
|
|
6
6
|
const alert = useAlert()
|
|
7
7
|
const emit = defineEmits<{
|
|
@@ -23,15 +23,17 @@ function uploadedFile(files: File[] | File | undefined) {
|
|
|
23
23
|
|
|
24
24
|
const fileExtension = files.name.slice(files.name.lastIndexOf('.')).toLowerCase()
|
|
25
25
|
if (!['.xlsx', '.csv'].includes(fileExtension)) {
|
|
26
|
-
alert?.addAlert({ message:
|
|
26
|
+
alert?.addAlert({ message: `Please upload a file with .csv or .xlsx extension only (${files.name})`, alertType: 'error' })
|
|
27
27
|
return
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
const reader = new FileReader()
|
|
31
31
|
reader.onload = (e: ProgressEvent<FileReader>) => {
|
|
32
32
|
const workbook = XLSX.read(e.target?.result)
|
|
33
|
-
const
|
|
34
|
-
|
|
33
|
+
const parsedData = parseAndAggregateColumns(
|
|
34
|
+
XLSX.utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[0]])
|
|
35
|
+
)
|
|
36
|
+
emit('import', parsedData)
|
|
35
37
|
loading.value = false
|
|
36
38
|
fileBtnRef.value.reset()
|
|
37
39
|
}
|
|
@@ -39,14 +41,63 @@ function uploadedFile(files: File[] | File | undefined) {
|
|
|
39
41
|
reader.readAsArrayBuffer(files)
|
|
40
42
|
}
|
|
41
43
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Recursively aggregates nested columns and properties.
|
|
46
|
+
* @param items - Array of data from the Excel sheet
|
|
47
|
+
*/
|
|
48
|
+
const parseAndAggregateColumns = (items: any[]) => {
|
|
49
|
+
return items.map((item: any) => {
|
|
50
|
+
const aggregatedItem: any = {}
|
|
51
|
+
|
|
52
|
+
for (const key in item) {
|
|
53
|
+
if (key.includes('.')) {
|
|
54
|
+
// Extract root key and subKey
|
|
55
|
+
const [rootKey, ...subKeys] = key.split('.')
|
|
56
|
+
|
|
57
|
+
// Recursively aggregate subKeys
|
|
58
|
+
aggregatedItem[rootKey] = aggregatedItem[rootKey] || {}
|
|
59
|
+
assignNestedValue(aggregatedItem[rootKey], subKeys, parseIfJson(item[key]))
|
|
60
|
+
} else {
|
|
61
|
+
// Directly assign root-level properties
|
|
62
|
+
aggregatedItem[key] = parseIfJson(item[key])
|
|
63
|
+
}
|
|
46
64
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
65
|
+
|
|
66
|
+
return aggregatedItem
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Recursively assigns a value to a nested key structure.
|
|
72
|
+
* @param obj - The object to assign to
|
|
73
|
+
* @param keys - Array of keys leading to the final property
|
|
74
|
+
* @param value - The value to assign
|
|
75
|
+
*/
|
|
76
|
+
const assignNestedValue = (obj: any, keys: string[], value: any) => {
|
|
77
|
+
const [currentKey, ...remainingKeys] = keys
|
|
78
|
+
if (remainingKeys.length === 0) {
|
|
79
|
+
obj[currentKey] = value
|
|
80
|
+
} else {
|
|
81
|
+
obj[currentKey] = obj[currentKey] || {}
|
|
82
|
+
assignNestedValue(obj[currentKey], remainingKeys, value)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Attempt to parse a value as JSON or array.
|
|
88
|
+
* @param value - The value to parse
|
|
89
|
+
*/
|
|
90
|
+
const parseIfJson = (value: any) => {
|
|
91
|
+
if (typeof value === 'string') {
|
|
92
|
+
try {
|
|
93
|
+
return JSON.parse(value)
|
|
94
|
+
} catch {
|
|
95
|
+
// If parsing fails, return the original value
|
|
96
|
+
return value
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return value
|
|
100
|
+
}
|
|
50
101
|
</script>
|
|
51
102
|
|
|
52
103
|
<template>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import {ref, withDefaults,watch,computed} from 'vue'
|
|
3
|
+
import {graphqlOperation} from '#imports'
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
templateCode: string
|
|
7
|
+
parentTemplates?: string|string[]
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
11
|
+
parentTemplates: (): string[] => [],
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
const template = ref<any>()
|
|
15
|
+
const templateScript = ref<string>()
|
|
16
|
+
|
|
17
|
+
const parentTemplates = computed(()=>{
|
|
18
|
+
if (typeof props.parentTemplates === 'string') {
|
|
19
|
+
if (props.parentTemplates && props.parentTemplates!="") return props.parentTemplates.split("|")
|
|
20
|
+
else return []
|
|
21
|
+
} else {
|
|
22
|
+
return props.parentTemplates
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
const parentTemplatesNext = computed(()=>{
|
|
27
|
+
return [...parentTemplates.value,props.templateCode]
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
watch(()=>props.templateCode,()=>{
|
|
31
|
+
if (!parentTemplates.value.includes(props.templateCode) && props.templateCode) {
|
|
32
|
+
if (graphqlOperation["documentTemplateByTemplateCode"]) {
|
|
33
|
+
graphqlOperation["documentTemplateByTemplateCode"].call(["*"],{templateCode: props.templateCode}).then((result: any)=>{
|
|
34
|
+
template.value = result.editTemplate
|
|
35
|
+
templateScript.value = result.templateScript
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
},{immediate: true})
|
|
40
|
+
</script>
|
|
41
|
+
<template>
|
|
42
|
+
<form-pad :template="template" :template-script="templateScript" :parent-templates="parentTemplatesNext"></form-pad>
|
|
43
|
+
</template>
|
|
@@ -2,7 +2,15 @@
|
|
|
2
2
|
import {computed, ref, watch} from 'vue'
|
|
3
3
|
import * as prettier from 'prettier'
|
|
4
4
|
import prettierPluginHtml from 'prettier/plugins/html'
|
|
5
|
-
import {useDocumentTemplate, validationRulesRegex} from '../../composables/document/template'
|
|
5
|
+
import {useDocumentTemplate, validationRulesRegex,optionStringToChoiceObject} from '../../composables/document/template'
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
title?: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
12
|
+
title: "Document Template"
|
|
13
|
+
})
|
|
6
14
|
|
|
7
15
|
const emit = defineEmits(['update:modelValue'])
|
|
8
16
|
const modelValue = defineModel<string>()
|
|
@@ -49,6 +57,33 @@ const headers = ref([
|
|
|
49
57
|
},
|
|
50
58
|
])
|
|
51
59
|
|
|
60
|
+
const formTableHeaders = ref([
|
|
61
|
+
{
|
|
62
|
+
title: 'Title',
|
|
63
|
+
key: 'title',
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
title: 'Key',
|
|
67
|
+
key: 'key',
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
title: 'Width',
|
|
71
|
+
key: 'width',
|
|
72
|
+
},
|
|
73
|
+
])
|
|
74
|
+
|
|
75
|
+
const choiceHeaders = ref([
|
|
76
|
+
{
|
|
77
|
+
title: 'Label',
|
|
78
|
+
key: 'label',
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
title: 'Value',
|
|
82
|
+
key: 'value',
|
|
83
|
+
},
|
|
84
|
+
])
|
|
85
|
+
|
|
86
|
+
|
|
52
87
|
function isValidJsonArrayOfObjects(str: string | undefined) {
|
|
53
88
|
try {
|
|
54
89
|
const parsed = JSON.parse(str as string)
|
|
@@ -72,17 +107,48 @@ async function convertToAdvanceMode() {
|
|
|
72
107
|
modelValue.value = await prettier.format(useDocumentTemplate(templateItems.value).replaceAll('>', '>\n'), { parser: 'html', plugins: [prettierPluginHtml] })
|
|
73
108
|
}
|
|
74
109
|
}
|
|
110
|
+
const inputTypeChoice = ref([
|
|
111
|
+
{ label: 'Text Field', value: 'VTextField' },
|
|
112
|
+
{ label: 'Text Area', value: 'VTextarea' },
|
|
113
|
+
{ label: 'Text Date Picker', value: 'FormDate' },
|
|
114
|
+
{ label: 'Text Time Picker', value: 'FormTime' },
|
|
115
|
+
{ label: 'Text Date & Time Picker', value: 'FormDateTime' },
|
|
116
|
+
{ label: 'Select Dropdown', value: 'VSelect' },
|
|
117
|
+
{ label: 'Select Combobox', value: 'VCombobox' },
|
|
118
|
+
{ label: 'Autocomplete', value: 'VAutocomplete' },
|
|
119
|
+
{ label: 'Autocomplete from Master', value: 'MasterAutocomplete' },
|
|
120
|
+
{ label: 'Radio Buttons', value: 'VRadio' },
|
|
121
|
+
{ label: 'Radio Buttons Inline', value: 'VRadioInline' },
|
|
122
|
+
{ label: 'Checkbox', value: 'VCheckbox' },
|
|
123
|
+
{ label: 'Switch', value: 'VSwitch' },
|
|
124
|
+
{ label: 'File Upload', value: 'FormFile' },
|
|
125
|
+
{ label: 'Signature Pad', value: 'FormSignPad' },
|
|
126
|
+
{ label: 'Table', value: 'FormTable' },
|
|
127
|
+
{ label: '[Decoration] Header', value: 'Header' },
|
|
128
|
+
{ label: '[Decoration] Separator', value: 'Separator' },
|
|
129
|
+
{ label: '[Advanced] Hidden Field', value: 'FormHidden' },
|
|
130
|
+
{ label: '[Advanced] Inherit Form', value: 'DocumentForm' },
|
|
131
|
+
{ label: '[Advanced] Custom Code', value: 'CustomCode' },
|
|
132
|
+
]);
|
|
133
|
+
|
|
134
|
+
const requireOption = ref(['VSelect', 'VAutocomplete', 'VCombobox', 'VRadio', 'VRadioInline', 'MasterAutocomplete','FormTable','DocumentForm'])
|
|
135
|
+
const notRequireVariable = ref(['Header', 'Separator', 'CustomCode','DocumentForm'])
|
|
136
|
+
const notRequireLabel = ref(['Separator', 'CustomCode', 'FormFile', 'FormHidden','DocumentForm'])
|
|
137
|
+
const notRequireWidth = ref(['Separator', 'FormHidden','DocumentForm'])
|
|
138
|
+
const notRequireOptions = ref(['Separator','CustomCode', 'FormFile'])
|
|
139
|
+
const notRequireRules = ref(['Separator','Header','CustomCode','FormHidden','DocumentForm'])
|
|
140
|
+
const notRequireInputAttributes = ref(['CustomCode','Header', 'FormHidden','DocumentForm'])
|
|
141
|
+
const notRequireColumnAttributes = ref(['Separator', 'FormHidden','DocumentForm'])
|
|
142
|
+
const notRequireAdvancedSetting = ref(['Separator','CustomCode', 'FormHidden'])
|
|
75
143
|
|
|
76
|
-
const
|
|
77
|
-
const requireOption = ref(['VSelect', 'VAutocomplete', 'VCombobox', 'VRadio', 'VRadioInline', 'MasterAutocomplete'])
|
|
78
|
-
const notRequireVariable = ref(['Header', 'Separator', 'CustomCode'])
|
|
79
|
-
const notRequireLabel = ref(['Separator', 'CustomCode', 'FormFile', 'FormSignPad', 'FormTable', 'FormHidden'])
|
|
80
|
-
const notRequireOptions = ref(['CustomCode', 'FormSignPad', 'FormFile', 'FormTable'])
|
|
81
|
-
const notRequireRules = ref(['CustomCode', 'FormSignPad', 'FormFile', 'FormTable' ,'FormHidden'])
|
|
82
|
-
const notRequireInputAttributes = ref(['CustomCode', 'FormHidden'])
|
|
83
|
-
const notRequireColumnAttributes = ref(['Separator', 'FormHidden'])
|
|
144
|
+
const hasSpecificOption = ref(['FormHidden','FormTable'])
|
|
84
145
|
|
|
85
|
-
const choiceOption = ref(['VSelect', '
|
|
146
|
+
const choiceOption = ref(['VRadio', 'VRadioInline','VSelect', 'VAutocomplete', 'VCombobox'])
|
|
147
|
+
const inputOptionsLabel = ref<Record<string,string>>({
|
|
148
|
+
'MasterAutocomplete' : "Group Key",
|
|
149
|
+
'Header' : "Class",
|
|
150
|
+
'DocumentForm': "Template Code",
|
|
151
|
+
})
|
|
86
152
|
|
|
87
153
|
const ruleOptions = (inputType: string) => (value: any) => {
|
|
88
154
|
if (choiceOption.value.includes(inputType) && !(/^[^'",]+(,[^'",]+)*$/.test(value))) return 'Invalid options format'
|
|
@@ -96,7 +162,7 @@ const ruleOptions = (inputType: string) => (value: any) => {
|
|
|
96
162
|
v-if="!isAdvanceMode"
|
|
97
163
|
v-model="templateItems"
|
|
98
164
|
:headers="headers"
|
|
99
|
-
title="
|
|
165
|
+
:title="props.title"
|
|
100
166
|
>
|
|
101
167
|
<template #toolbarItems>
|
|
102
168
|
<VBtn
|
|
@@ -118,19 +184,20 @@ const ruleOptions = (inputType: string) => (value: any) => {
|
|
|
118
184
|
v-model="data.inputType"
|
|
119
185
|
label="Input Type"
|
|
120
186
|
:items="inputTypeChoice"
|
|
187
|
+
item-title="label"
|
|
188
|
+
item-value="value"
|
|
189
|
+
:return-object="false"
|
|
121
190
|
:rules="[rules.require()]"
|
|
122
191
|
/>
|
|
123
192
|
</v-col>
|
|
124
|
-
<v-col
|
|
125
|
-
v-if="data.inputType!='Separator'"
|
|
126
|
-
cols="1"
|
|
127
|
-
>
|
|
193
|
+
<v-col cols="1" v-if="!notRequireWidth.includes(data.inputType)">
|
|
128
194
|
<v-text-field
|
|
129
195
|
v-model="data.width"
|
|
130
196
|
label="Width"
|
|
131
197
|
:rules="[rules.require()]"
|
|
132
198
|
type="number"
|
|
133
199
|
/>
|
|
200
|
+
<form-hidden v-model="data.inputOptions" :item-value="data.inputType" :hook="()=>undefined"></form-hidden>
|
|
134
201
|
</v-col>
|
|
135
202
|
<v-col cols="4" v-if="!notRequireLabel.includes(data.inputType)">
|
|
136
203
|
<v-text-field
|
|
@@ -150,32 +217,67 @@ const ruleOptions = (inputType: string) => (value: any) => {
|
|
|
150
217
|
v-if="!notRequireOptions.includes(data.inputType)"
|
|
151
218
|
cols="12"
|
|
152
219
|
>
|
|
220
|
+
<form-pad v-model="data.inputOptions" v-if="data.inputType=='FormTable'">
|
|
221
|
+
<template #default="{data: optionData}">
|
|
222
|
+
<v-row dense>
|
|
223
|
+
<v-col cols="12">
|
|
224
|
+
<form-table v-model="optionData.headers" :headers="formTableHeaders" title="Headers">
|
|
225
|
+
<template #form="{data: headerData,rules}">
|
|
226
|
+
<v-container fluid>
|
|
227
|
+
<v-row dense>
|
|
228
|
+
<v-col cols="6"><v-text-field v-model="headerData.title" label="Title"></v-text-field></v-col>
|
|
229
|
+
<v-col cols="3"><v-text-field v-model="headerData.key" label="Key" :rules="[rules.require()]"></v-text-field></v-col>
|
|
230
|
+
<v-col cols="3"><v-text-field v-model="headerData.width" label="Width"></v-text-field></v-col>
|
|
231
|
+
</v-row>
|
|
232
|
+
</v-container>
|
|
233
|
+
</template>
|
|
234
|
+
</form-table>
|
|
235
|
+
</v-col>
|
|
236
|
+
<v-col cols="12">
|
|
237
|
+
<document-template-builder v-model="optionData.formTemplate" title="Form Template"></document-template-builder>
|
|
238
|
+
</v-col>
|
|
239
|
+
</v-row>
|
|
240
|
+
</template>
|
|
241
|
+
</form-pad>
|
|
242
|
+
<form-pad v-model="data.inputOptions" v-if="data.inputType=='FormHidden'">
|
|
243
|
+
<template #default="{data: optionData}">
|
|
244
|
+
<v-row dense>
|
|
245
|
+
<v-col cols="12">
|
|
246
|
+
<v-text-field
|
|
247
|
+
v-model="optionData.hook"
|
|
248
|
+
label="Hook"
|
|
249
|
+
:rules="[rules.require()]"
|
|
250
|
+
/>
|
|
251
|
+
</v-col>
|
|
252
|
+
<v-col cols="12">
|
|
253
|
+
<v-text-field
|
|
254
|
+
v-model="optionData.itemValue"
|
|
255
|
+
label="Item Value"
|
|
256
|
+
/>
|
|
257
|
+
</v-col>
|
|
258
|
+
</v-row>
|
|
259
|
+
</template>
|
|
260
|
+
</form-pad>
|
|
261
|
+
<form-table v-model="data.inputOptions" :headers="choiceHeaders" title="Choices" v-if="choiceOption.includes(data.inputType) && (!data.inputOptions || typeof data.inputOptions === 'object')">
|
|
262
|
+
<template #form="{data: optionData,rules}">
|
|
263
|
+
<v-container fluid>
|
|
264
|
+
<v-row dense>
|
|
265
|
+
<v-col cols="6"><v-text-field v-model="optionData.label" label="Label"></v-text-field></v-col>
|
|
266
|
+
<v-col cols="6"><v-text-field v-model="optionData.value" label="Value" :rules="[rules.require()]"></v-text-field></v-col>
|
|
267
|
+
</v-row>
|
|
268
|
+
</v-container>
|
|
269
|
+
</template>
|
|
270
|
+
</form-table>
|
|
271
|
+
<form-hidden v-model="data.inputOptions" :itemValue="data.inputOptions" :hook="(option: any)=>optionStringToChoiceObject(option)" v-if="choiceOption.includes(data.inputType) && data.inputOptions && typeof data.inputOptions === 'string'"></form-hidden>
|
|
153
272
|
<v-textarea
|
|
154
273
|
v-model="data.inputOptions"
|
|
155
|
-
label="Input Options"
|
|
274
|
+
:label="inputOptionsLabel[data.inputType] || 'Input Options'"
|
|
156
275
|
auto-grow
|
|
157
276
|
:rules="[rules.requireIf(requireOption.includes(data.inputType)), ruleOptions(data.inputType)]"
|
|
277
|
+
v-if="!hasSpecificOption.includes(data.inputType) && !choiceOption.includes(data.inputType)"
|
|
158
278
|
/>
|
|
159
279
|
</v-col>
|
|
160
|
-
|
|
161
|
-
<v-text-field
|
|
162
|
-
v-model="data.validationRules"
|
|
163
|
-
label="Validation Rules"
|
|
164
|
-
:rules="[rules.regex(validationRulesRegex)]"
|
|
165
|
-
/>
|
|
166
|
-
</v-col>
|
|
167
|
-
<v-col v-if="data.inputType!='CustomCode'">
|
|
168
|
-
<v-text-field
|
|
169
|
-
v-model="data.inputAttributes"
|
|
170
|
-
label="Input Attributes"
|
|
171
|
-
/>
|
|
172
|
-
</v-col>
|
|
173
|
-
<v-col v-if="data.inputType!='Separator'">
|
|
174
|
-
<v-text-field
|
|
175
|
-
v-model="data.columnAttributes"
|
|
176
|
-
label="Column Attributes"
|
|
177
|
-
/>
|
|
178
|
-
</v-col>
|
|
280
|
+
|
|
179
281
|
<v-col
|
|
180
282
|
v-if="data.inputType=='CustomCode'"
|
|
181
283
|
cols="12"
|
|
@@ -186,25 +288,67 @@ const ruleOptions = (inputType: string) => (value: any) => {
|
|
|
186
288
|
:rules="[rules.require()]"
|
|
187
289
|
/>
|
|
188
290
|
</v-col>
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
v-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
291
|
+
</v-row>
|
|
292
|
+
<v-row dense>
|
|
293
|
+
<v-col>
|
|
294
|
+
<v-expansion-panels>
|
|
295
|
+
<v-expansion-panel v-if="!notRequireRules.includes(data.inputType)">
|
|
296
|
+
<v-expansion-panel-title collapse-icon="mdi mdi-minus" expand-icon="mdi mdi-plus" class="font-weight-bold">Validations</v-expansion-panel-title>
|
|
297
|
+
<v-expansion-panel-text>
|
|
298
|
+
<v-container fluid>
|
|
299
|
+
<v-row dense>
|
|
300
|
+
<v-col cols="12">
|
|
301
|
+
<v-text-field
|
|
302
|
+
v-model="data.validationRules"
|
|
303
|
+
label="Validation Rules"
|
|
304
|
+
:rules="[rules.regex(validationRulesRegex)]"
|
|
305
|
+
/>
|
|
306
|
+
<b>Available rules :</b> require, requireIf(condition), requireTrue, requireTrueIf(condition), numeric, range(min,max), integer, unique, length(length), lengthGreater(length), lengthLess(length), telephone, email, regex(regex), idcard, DateFuture, DatetimeFuture, DateHappen, DatetimeHappen, DateAfter(date), DateBefore(Date), DateEqual(date)
|
|
307
|
+
</v-col>
|
|
308
|
+
</v-row>
|
|
309
|
+
</v-container>
|
|
310
|
+
</v-expansion-panel-text>
|
|
311
|
+
</v-expansion-panel>
|
|
312
|
+
<v-expansion-panel v-if="!notRequireAdvancedSetting.includes(data.inputType)">
|
|
313
|
+
<v-expansion-panel-title collapse-icon="mdi mdi-minus" expand-icon="mdi mdi-plus" class="font-weight-bold">Advanced settings</v-expansion-panel-title>
|
|
314
|
+
<v-expansion-panel-text>
|
|
315
|
+
<v-container fluid>
|
|
316
|
+
<v-row dense>
|
|
317
|
+
<v-col cols="12" md="6" v-if="!notRequireInputAttributes.includes(data.inputType)">
|
|
318
|
+
<v-text-field
|
|
319
|
+
v-model="data.inputAttributes"
|
|
320
|
+
label="Input Attributes"
|
|
321
|
+
/>
|
|
322
|
+
</v-col>
|
|
323
|
+
<v-col cols="12" md="6" v-if="!notRequireColumnAttributes.includes(data.inputType)">
|
|
324
|
+
<v-text-field
|
|
325
|
+
v-model="data.columnAttributes"
|
|
326
|
+
label="Column Attributes"
|
|
327
|
+
/>
|
|
328
|
+
</v-col>
|
|
329
|
+
<v-col cols="12" md="6">
|
|
330
|
+
<v-text-field
|
|
331
|
+
v-model="data.conditionalDisplay"
|
|
332
|
+
label="Conditional Display"
|
|
333
|
+
/>
|
|
334
|
+
</v-col>
|
|
335
|
+
<v-col cols="12" md="6">
|
|
336
|
+
<v-text-field
|
|
337
|
+
v-model="data.computedValue"
|
|
338
|
+
label="Computed Value"
|
|
339
|
+
/>
|
|
340
|
+
</v-col>
|
|
341
|
+
<v-col cols="12" md="6">
|
|
342
|
+
<v-text-field
|
|
343
|
+
v-model="data.retrievedValue"
|
|
344
|
+
label="Retrieved Value"
|
|
345
|
+
/>
|
|
346
|
+
</v-col>
|
|
347
|
+
</v-row>
|
|
348
|
+
</v-container>
|
|
349
|
+
</v-expansion-panel-text>
|
|
350
|
+
</v-expansion-panel>
|
|
351
|
+
</v-expansion-panels>
|
|
208
352
|
</v-col>
|
|
209
353
|
</v-row>
|
|
210
354
|
</v-container>
|
|
@@ -223,14 +367,6 @@ const ruleOptions = (inputType: string) => (value: any) => {
|
|
|
223
367
|
<template v-if="props.item.inputAttributes">
|
|
224
368
|
<b>Input Attributes :</b> {{ props.item.inputAttributes }}<br>
|
|
225
369
|
</template>
|
|
226
|
-
<template v-if="props.item.inputType=='FormTable'">
|
|
227
|
-
<b>Form Table :</b><br>
|
|
228
|
-
<span style="white-space: pre-line">{{ props.item.inputFormTable }}</span>
|
|
229
|
-
</template>
|
|
230
|
-
<template v-if="props.item.inputType=='FormHidden'">
|
|
231
|
-
<b>Form Hidden :</b><br>
|
|
232
|
-
<span style="white-space: pre-line">{{ props.item.inputFormHidden }}</span>
|
|
233
|
-
</template>
|
|
234
370
|
</template>
|
|
235
371
|
</FormTable>
|
|
236
372
|
<FormCodeEditor
|