@bagelink/vue 1.4.14 → 1.4.18
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/components/ImportData.vue.d.ts +2 -1
- package/dist/components/ImportData.vue.d.ts.map +1 -1
- package/dist/components/Slider.vue.d.ts +6 -0
- package/dist/components/Slider.vue.d.ts.map +1 -1
- package/dist/index.cjs +436 -164
- package/dist/index.mjs +437 -165
- package/dist/style.css +11 -5
- package/dist/utils/useSearch.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/components/ImportData.vue +20 -247
- package/src/components/Slider.vue +508 -85
- package/src/components/lightbox/Lightbox.vue +1 -1
- package/src/styles/text.css +8 -0
- package/src/utils/useSearch.ts +22 -3
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts" generic="T">
|
|
2
2
|
import type { BglFormSchemaT, Option } from '@bagelink/vue'
|
|
3
|
+
import type { MaybeRefOrGetter } from 'vue'
|
|
3
4
|
import type { Field } from '../types/BagelForm'
|
|
4
5
|
import {
|
|
5
6
|
Btn,
|
|
@@ -13,13 +14,12 @@ import {
|
|
|
13
14
|
useExcel,
|
|
14
15
|
DragOver,
|
|
15
16
|
} from '@bagelink/vue'
|
|
16
|
-
import { computed, reactive, ref, watch, watchEffect } from 'vue'
|
|
17
|
+
import { computed, reactive, ref, watch, watchEffect, toValue } from 'vue'
|
|
17
18
|
|
|
18
19
|
import { useSchemaField } from '../composables/useSchemaField'
|
|
19
20
|
import { formatString } from '../utils/strings'
|
|
20
21
|
import TextInput from './form/inputs/TextInput.vue'
|
|
21
22
|
|
|
22
|
-
// Add interface for schema items
|
|
23
23
|
interface SchemaItem {
|
|
24
24
|
id: string
|
|
25
25
|
label: string
|
|
@@ -56,7 +56,7 @@ interface Transformation {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
const props = defineProps<{
|
|
59
|
-
schema?: BglFormSchemaT<T
|
|
59
|
+
schema?: MaybeRefOrGetter<BglFormSchemaT<T>>
|
|
60
60
|
title?: string
|
|
61
61
|
}>()
|
|
62
62
|
|
|
@@ -91,57 +91,40 @@ const dataTypeOptions = [
|
|
|
91
91
|
{ value: DATA_TYPES.BOOLEAN, label: 'Boolean' }
|
|
92
92
|
]
|
|
93
93
|
|
|
94
|
-
// Component state
|
|
95
94
|
const file = ref<File | null>(null)
|
|
96
95
|
const fileData = ref<any[]>([])
|
|
97
96
|
const sheetNames = ref<string[]>([])
|
|
98
97
|
const selectedSheet = ref<string>('')
|
|
99
98
|
const hasHeaders = ref(true)
|
|
100
|
-
const fieldMapping = reactive<Record<string, string>>({})
|
|
101
99
|
const isLoading = ref(false)
|
|
102
100
|
const showPreviewModal = ref(false)
|
|
103
101
|
const previewData = ref<any[]>([])
|
|
104
102
|
const mappingComplete = ref(false)
|
|
105
103
|
const fileHeaders = ref<string[]>([])
|
|
106
|
-
|
|
107
|
-
// New state for constant values and transformations
|
|
108
|
-
const defaultValues = reactive<Record<string, any>>({})
|
|
109
|
-
|
|
110
|
-
// State for transformations
|
|
111
|
-
const transformations = reactive<Record<string, Transformation[]>>({})
|
|
112
104
|
const showTransformDialog = ref(false)
|
|
113
105
|
const selectedTransformField = ref<SchemaItem | null>(null)
|
|
106
|
+
const showRelatedDialog = ref(false)
|
|
107
|
+
const selectedRelationField = ref<SchemaItem | null>(null)
|
|
108
|
+
const selectedSourceValue = ref('')
|
|
109
|
+
const selectedTargetValue = ref('')
|
|
110
|
+
const showRelatedTransformDialog = ref(false)
|
|
111
|
+
const selectedRelatedTransformField = ref<{ parentId: string, field: SchemaItem } | null>(null)
|
|
112
|
+
const selectedRelatedSourceValue = ref('')
|
|
113
|
+
const selectedRelatedTargetValue = ref('')
|
|
114
114
|
|
|
115
|
-
|
|
115
|
+
const fieldMapping = reactive<Record<string, string>>({})
|
|
116
|
+
const defaultValues = reactive<Record<string, any>>({})
|
|
117
|
+
const transformations = reactive<Record<string, Transformation[]>>({})
|
|
116
118
|
const fieldDataTypes = reactive<Record<string, string>>({})
|
|
117
|
-
|
|
118
|
-
// State for related data
|
|
119
119
|
const relatedFiles = reactive<Record<string, File | null>>({})
|
|
120
120
|
const relatedFileData = reactive<Record<string, any[]>>({})
|
|
121
121
|
const relatedFileMappings = reactive<Record<string, Record<string, string>>>({})
|
|
122
|
-
const showRelatedDialog = ref(false)
|
|
123
|
-
const selectedRelationField = ref<SchemaItem | null>(null)
|
|
124
122
|
const relatedKeyField = reactive<Record<string, string>>({})
|
|
125
123
|
const parentKeyField = reactive<Record<string, string>>({})
|
|
126
|
-
|
|
127
|
-
// Improve the transformations management
|
|
128
|
-
const selectedSourceValue = ref('')
|
|
129
|
-
const selectedTargetValue = ref('')
|
|
130
|
-
|
|
131
|
-
// State for related field data types
|
|
132
124
|
const relatedFieldDataTypes = reactive<Record<string, string>>({})
|
|
133
|
-
|
|
134
|
-
// State for related default values
|
|
135
125
|
const relatedDefaultValues = reactive<Record<string, Record<string, any>>>({})
|
|
136
|
-
|
|
137
|
-
// State for related transformations
|
|
138
126
|
const relatedTransformations = reactive<Record<string, Record<string, Transformation[]>>>({})
|
|
139
|
-
const showRelatedTransformDialog = ref(false)
|
|
140
|
-
const selectedRelatedTransformField = ref<{ parentId: string, field: SchemaItem } | null>(null)
|
|
141
|
-
const selectedRelatedSourceValue = ref('')
|
|
142
|
-
const selectedRelatedTargetValue = ref('')
|
|
143
127
|
|
|
144
|
-
// Set up schema field rendering
|
|
145
128
|
const formData = ref<any>({})
|
|
146
129
|
const { renderField } = useSchemaField<any, any>({
|
|
147
130
|
mode: 'form',
|
|
@@ -149,7 +132,6 @@ const { renderField } = useSchemaField<any, any>({
|
|
|
149
132
|
onUpdateModelValue: (field: Field<any>, value: any) => {
|
|
150
133
|
if (!field.id) return
|
|
151
134
|
|
|
152
|
-
// Check if this is a related field (id contains a dot)
|
|
153
135
|
if (field.id.includes('.')) {
|
|
154
136
|
const [parentId, childId] = field.id.split('.')
|
|
155
137
|
if (!relatedDefaultValues[parentId]) {
|
|
@@ -157,19 +139,15 @@ const { renderField } = useSchemaField<any, any>({
|
|
|
157
139
|
}
|
|
158
140
|
relatedDefaultValues[parentId][childId] = value
|
|
159
141
|
} else {
|
|
160
|
-
// Regular field
|
|
161
142
|
defaultValues[field.id] = value
|
|
162
143
|
}
|
|
163
144
|
}
|
|
164
145
|
})
|
|
165
146
|
|
|
166
|
-
// Add function to get unique source values for a field
|
|
167
147
|
function getUniqueSourceValues(fieldId: string): any[] {
|
|
168
148
|
if (!fieldMapping[fieldId] || !fileData.value || fileData.value.length === 0) {
|
|
169
149
|
return []
|
|
170
150
|
}
|
|
171
|
-
|
|
172
|
-
// Get all values from the mapped column
|
|
173
151
|
const allValues = fileData.value
|
|
174
152
|
.map(row => row[fieldMapping[fieldId]])
|
|
175
153
|
.filter(value => value !== undefined && value !== null && value !== '')
|
|
@@ -191,7 +169,6 @@ const availableSourceValues = computed(() => {
|
|
|
191
169
|
return getUniqueSourceValues(selectedTransformField.value.id)
|
|
192
170
|
})
|
|
193
171
|
|
|
194
|
-
// Create options array from unique values
|
|
195
172
|
const sourceValueOptions = computed(() => {
|
|
196
173
|
return availableSourceValues.value.map(value => ({
|
|
197
174
|
value: String(value),
|
|
@@ -199,17 +176,11 @@ const sourceValueOptions = computed(() => {
|
|
|
199
176
|
}))
|
|
200
177
|
})
|
|
201
178
|
|
|
202
|
-
// Fix the findMatchingTargetValue function to handle Option types correctly
|
|
203
179
|
function findMatchingTargetValue(sourceValue: string, options: Option[]): string | null {
|
|
204
180
|
if (!sourceValue || !options || !Array.isArray(options) || options.length === 0) return null
|
|
205
|
-
|
|
206
|
-
// Convert sourceValue to string and lowercase for comparison
|
|
207
181
|
const lowerSourceValue = String(sourceValue).toLowerCase().trim()
|
|
208
|
-
|
|
209
|
-
// First try exact match
|
|
210
182
|
const exactMatch = options.find((option) => {
|
|
211
183
|
const optionObj = typeof option === 'object' && option !== null ? option : { value: String(option), label: String(option) }
|
|
212
|
-
// Make sure option and label exist and is a string
|
|
213
184
|
if (!optionObj) return false
|
|
214
185
|
const optionLabel = `${optionObj.label}`.toLowerCase().trim()
|
|
215
186
|
return optionLabel === lowerSourceValue
|
|
@@ -229,7 +200,6 @@ function findMatchingTargetValue(sourceValue: string, options: Option[]): string
|
|
|
229
200
|
|
|
230
201
|
const optionLabel = `${optionObj.label}`.toLowerCase().trim()
|
|
231
202
|
|
|
232
|
-
// Try contains match
|
|
233
203
|
return lowerSourceValue.includes(optionLabel) || optionLabel.includes(lowerSourceValue)
|
|
234
204
|
})
|
|
235
205
|
|
|
@@ -243,7 +213,6 @@ function findMatchingTargetValue(sourceValue: string, options: Option[]): string
|
|
|
243
213
|
return null
|
|
244
214
|
}
|
|
245
215
|
|
|
246
|
-
// Watch for changes in selected source value and auto-match if enabled
|
|
247
216
|
watch(selectedSourceValue, (newValue) => {
|
|
248
217
|
if (selectedTransformField.value?.options) {
|
|
249
218
|
const matchedValue = findMatchingTargetValue(newValue, selectedTransformField.value.options)
|
|
@@ -253,22 +222,18 @@ watch(selectedSourceValue, (newValue) => {
|
|
|
253
222
|
}
|
|
254
223
|
})
|
|
255
224
|
|
|
256
|
-
// Add a transformation
|
|
257
225
|
function addTransformation(fieldId: string) {
|
|
258
226
|
if (!transformations[fieldId]) {
|
|
259
227
|
transformations[fieldId] = []
|
|
260
228
|
}
|
|
261
229
|
|
|
262
230
|
if (selectedSourceValue.value && selectedTargetValue.value) {
|
|
263
|
-
// Check if this source value already has a transformation
|
|
264
231
|
const existingIndex = transformations[fieldId].findIndex(t => t.sourceValue === selectedSourceValue.value
|
|
265
232
|
)
|
|
266
233
|
|
|
267
234
|
if (existingIndex >= 0) {
|
|
268
|
-
// Update existing transformation
|
|
269
235
|
transformations[fieldId][existingIndex].targetValue = selectedTargetValue.value
|
|
270
236
|
} else {
|
|
271
|
-
// Add new transformation
|
|
272
237
|
transformations[fieldId].push({
|
|
273
238
|
fieldId,
|
|
274
239
|
sourceValue: selectedSourceValue.value,
|
|
@@ -280,7 +245,6 @@ function addTransformation(fieldId: string) {
|
|
|
280
245
|
}
|
|
281
246
|
}
|
|
282
247
|
|
|
283
|
-
// Create a revised function to extract fields from the schema structure without duplicates
|
|
284
248
|
function getAllFields(schema: any[]): any[] {
|
|
285
249
|
if (!schema || !Array.isArray(schema)) return []
|
|
286
250
|
|
|
@@ -312,18 +276,11 @@ function getAllFields(schema: any[]): any[] {
|
|
|
312
276
|
if (item && item.id && item.label) {
|
|
313
277
|
addFieldIfNew(item)
|
|
314
278
|
}
|
|
315
|
-
|
|
316
|
-
// Containers with children (like flex divs)
|
|
317
279
|
if (item && item.children && Array.isArray(item.children)) {
|
|
318
|
-
// Process each child
|
|
319
280
|
item.children.forEach((child: any) => {
|
|
320
|
-
// Regular fields
|
|
321
281
|
if (child && child.id && child.label) {
|
|
322
|
-
// Check if it's an array field
|
|
323
282
|
if (child.$el === 'array' && child.attrs && child.attrs.schema) {
|
|
324
|
-
// Add the array field itself (phones, emails)
|
|
325
283
|
addFieldIfNew(child)
|
|
326
|
-
|
|
327
284
|
if (Array.isArray(child.attrs.schema)) {
|
|
328
285
|
child.attrs.schema.forEach((schemaItem: SchemaItem) => {
|
|
329
286
|
if (schemaItem && schemaItem.id && schemaItem.label) {
|
|
@@ -339,7 +296,6 @@ function getAllFields(schema: any[]): any[] {
|
|
|
339
296
|
} else if (schemaItem.attrs && schemaItem.attrs.options) {
|
|
340
297
|
qualifiedField.options = schemaItem.attrs.options
|
|
341
298
|
}
|
|
342
|
-
|
|
343
299
|
addFieldIfNew(qualifiedField)
|
|
344
300
|
}
|
|
345
301
|
})
|
|
@@ -355,26 +311,19 @@ function getAllFields(schema: any[]): any[] {
|
|
|
355
311
|
return allFields
|
|
356
312
|
}
|
|
357
313
|
|
|
358
|
-
|
|
359
|
-
const schemaFields = computed(() => {
|
|
360
|
-
return getAllFields(props.schema || [])
|
|
361
|
-
})
|
|
314
|
+
const schemaFields = computed(() => getAllFields(toValue(props.schema) || []))
|
|
362
315
|
|
|
363
|
-
// Update the isFieldRequired function to handle the special case for array fields
|
|
364
316
|
function isFieldRequired(field: any): boolean {
|
|
365
317
|
if (field.isArrayField && field.parentField) {
|
|
366
318
|
return false
|
|
367
319
|
}
|
|
368
320
|
|
|
369
|
-
// For regular fields, check the standard required attributes
|
|
370
321
|
return (field.attrs && field.attrs.required === true)
|
|
371
322
|
|| (field.required === true)
|
|
372
323
|
|| (field.attrs && field.attrs.attrs && field.attrs.attrs.required === true)
|
|
373
324
|
}
|
|
374
325
|
|
|
375
|
-
// Add a function to get field display information including conditional requirements
|
|
376
326
|
function getFieldDescription(field: any): { description: string, isConditional: boolean } {
|
|
377
|
-
// For array child fields, show they're conditionally required
|
|
378
327
|
if (field.isArrayField && field.parentField) {
|
|
379
328
|
const parentLabel = schemaFields.value.find(f => f.id === field.parentField)?.label || field.parentField
|
|
380
329
|
return {
|
|
@@ -382,8 +331,6 @@ function getFieldDescription(field: any): { description: string, isConditional:
|
|
|
382
331
|
isConditional: true
|
|
383
332
|
}
|
|
384
333
|
}
|
|
385
|
-
|
|
386
|
-
// No special handling needed
|
|
387
334
|
return {
|
|
388
335
|
description: '',
|
|
389
336
|
isConditional: false
|
|
@@ -405,12 +352,10 @@ async function parseFile(file: File) {
|
|
|
405
352
|
}
|
|
406
353
|
}
|
|
407
354
|
|
|
408
|
-
// Replace loadSheetData function with simplified version
|
|
409
355
|
async function loadSheetData() {
|
|
410
356
|
if (!file.value || !selectedSheet.value) return
|
|
411
357
|
isLoading.value = true
|
|
412
358
|
try {
|
|
413
|
-
// Use the readSheetData utility from our composable
|
|
414
359
|
const { headers, data } = await readSheetData(file.value, selectedSheet.value, hasHeaders.value)
|
|
415
360
|
|
|
416
361
|
fileHeaders.value = headers
|
|
@@ -424,21 +369,16 @@ async function loadSheetData() {
|
|
|
424
369
|
}
|
|
425
370
|
}
|
|
426
371
|
|
|
427
|
-
// Add a function to check if a field is related to an array parent that's already mapped
|
|
428
372
|
function checkArrayFieldConflicts() {
|
|
429
|
-
// Get all array parent fields that are currently mapped
|
|
430
373
|
const mappedArrayParents = new Set()
|
|
431
|
-
const mappedArrayChildren = new Map()
|
|
374
|
+
const mappedArrayChildren = new Map()
|
|
432
375
|
|
|
433
|
-
// Identify which array parents and children are mapped
|
|
434
376
|
Object.keys(fieldMapping).forEach((fieldId: string) => {
|
|
435
377
|
const field = schemaFields.value.find(f => f.id === fieldId)
|
|
436
378
|
if (field) {
|
|
437
379
|
if (field.$el === 'array') {
|
|
438
|
-
// This is an array parent
|
|
439
380
|
mappedArrayParents.add(field.id)
|
|
440
381
|
} else if (field.isArrayField && field.parentField) {
|
|
441
|
-
// This is an array child
|
|
442
382
|
if (!mappedArrayChildren.has(field.parentField)) {
|
|
443
383
|
mappedArrayChildren.set(field.parentField, new Set())
|
|
444
384
|
}
|
|
@@ -447,7 +387,6 @@ function checkArrayFieldConflicts() {
|
|
|
447
387
|
}
|
|
448
388
|
})
|
|
449
389
|
|
|
450
|
-
// For each array parent that's mapped, disable its children
|
|
451
390
|
for (const parentId of mappedArrayParents) {
|
|
452
391
|
const childFields = schemaFields.value.filter(f => f.parentField === parentId)
|
|
453
392
|
childFields.forEach((child: any) => {
|
|
@@ -456,7 +395,6 @@ function checkArrayFieldConflicts() {
|
|
|
456
395
|
})
|
|
457
396
|
}
|
|
458
397
|
|
|
459
|
-
// For each array child that's mapped, disable its parent
|
|
460
398
|
for (const [parentId, childIds] of mappedArrayChildren.entries()) {
|
|
461
399
|
if (childIds.size > 0) {
|
|
462
400
|
const parentField = schemaFields.value.find(f => f.id === parentId)
|
|
@@ -468,14 +406,11 @@ function checkArrayFieldConflicts() {
|
|
|
468
406
|
}
|
|
469
407
|
}
|
|
470
408
|
|
|
471
|
-
// Modify the resetMapping function to call checkArrayFieldConflicts
|
|
472
409
|
function resetMapping() {
|
|
473
|
-
// Reset field mapping
|
|
474
410
|
Object.keys(fieldMapping).forEach((key: string) => {
|
|
475
411
|
delete fieldMapping[key]
|
|
476
412
|
})
|
|
477
413
|
|
|
478
|
-
// Reset disabled state on all fields
|
|
479
414
|
schemaFields.value.forEach((field: any) => {
|
|
480
415
|
field.disabled = false
|
|
481
416
|
field.disabledReason = ''
|
|
@@ -522,38 +457,29 @@ function resetMapping() {
|
|
|
522
457
|
})
|
|
523
458
|
}
|
|
524
459
|
|
|
525
|
-
// Check for array field conflicts
|
|
526
460
|
checkArrayFieldConflicts()
|
|
527
461
|
checkMappingComplete()
|
|
528
462
|
}
|
|
529
463
|
|
|
530
|
-
// Simplify the checkMappingComplete function to match canProcessData
|
|
531
464
|
function checkMappingComplete() {
|
|
532
|
-
// Use the same logic as canProcessData for consistency
|
|
533
465
|
if (!file.value || (Object.keys(fieldMapping).length === 0 && Object.keys(defaultValues).length === 0)) {
|
|
534
466
|
mappingComplete.value = false
|
|
535
467
|
return
|
|
536
468
|
}
|
|
537
469
|
|
|
538
|
-
// Get strictly required fields (non-conditional)
|
|
539
470
|
const requiredFields = schemaFields.value.filter((field) => {
|
|
540
|
-
// Exclude array children which are conditionally required
|
|
541
471
|
if (field.isArrayField && field.parentField) return false
|
|
542
472
|
|
|
543
|
-
// Check various ways a field might be marked as required
|
|
544
473
|
return (field.attrs && field.attrs.required === true)
|
|
545
474
|
|| (field.required === true)
|
|
546
475
|
|| (field.attrs && field.attrs.attrs && field.attrs.attrs.required === true)
|
|
547
476
|
})
|
|
548
477
|
|
|
549
|
-
// If no strictly required fields, we just need at least one mapping or default value
|
|
550
478
|
if (requiredFields.length === 0) {
|
|
551
479
|
mappingComplete.value = Object.keys(fieldMapping).some(key => !!fieldMapping[key])
|
|
552
480
|
|| Object.keys(defaultValues).length > 0
|
|
553
481
|
return
|
|
554
482
|
}
|
|
555
|
-
|
|
556
|
-
// Check that all required fields are mapped or have default values
|
|
557
483
|
mappingComplete.value = requiredFields.every(field => !!fieldMapping[field.id] || hasDefaultValue(field.id))
|
|
558
484
|
}
|
|
559
485
|
|
|
@@ -566,34 +492,24 @@ function showPreview() {
|
|
|
566
492
|
const mappedRow: MappedRow = {}
|
|
567
493
|
|
|
568
494
|
schemaFields.value.forEach((field) => {
|
|
569
|
-
// Skip array fields as they're handled separately
|
|
570
495
|
if (field.isArrayField || field.$el === 'array') return
|
|
571
|
-
|
|
572
|
-
// Get value from mapping or use default
|
|
573
496
|
let value: any = null
|
|
574
497
|
let useDefault = false
|
|
575
498
|
|
|
576
499
|
if (fieldMapping[field.id] && sourceRow[fieldMapping[field.id]] !== undefined) {
|
|
577
500
|
value = sourceRow[fieldMapping[field.id]]
|
|
578
|
-
// Use default value as fallback if the mapped value is empty
|
|
579
501
|
if (value === '' && defaultValues[field.id] !== undefined) {
|
|
580
502
|
value = defaultValues[field.id]
|
|
581
503
|
useDefault = true
|
|
582
504
|
}
|
|
583
505
|
} else if (defaultValues[field.id] !== undefined) {
|
|
584
|
-
// Use default value if no direct mapping or mapping is empty
|
|
585
506
|
value = defaultValues[field.id]
|
|
586
507
|
useDefault = true
|
|
587
508
|
}
|
|
588
509
|
|
|
589
|
-
|
|
590
|
-
if (value === null) {
|
|
591
|
-
return
|
|
592
|
-
}
|
|
510
|
+
if (value === null) return
|
|
593
511
|
|
|
594
|
-
// Apply transformations if any exist and not using default value
|
|
595
512
|
if (!useDefault && transformations[field.id] && transformations[field.id].length > 0) {
|
|
596
|
-
// Find matching transformation
|
|
597
513
|
const transform = transformations[field.id].find(t => t.sourceValue == value || t.sourceValue === String(value)
|
|
598
514
|
)
|
|
599
515
|
if (transform) {
|
|
@@ -601,21 +517,17 @@ function showPreview() {
|
|
|
601
517
|
}
|
|
602
518
|
}
|
|
603
519
|
|
|
604
|
-
// Apply data type conversion
|
|
605
520
|
const dataType = fieldDataTypes[field.id] || DATA_TYPES.STRING
|
|
606
521
|
value = convertValueByType(value, dataType)
|
|
607
522
|
|
|
608
523
|
if (field.id.includes('.')) {
|
|
609
|
-
// Handle dot notation for nested objects
|
|
610
524
|
const parts = field.id.split('.')
|
|
611
525
|
const rootField = parts[0]
|
|
612
526
|
|
|
613
|
-
// Create nested structure
|
|
614
527
|
if (!mappedRow[rootField]) {
|
|
615
528
|
mappedRow[rootField] = {}
|
|
616
529
|
}
|
|
617
530
|
|
|
618
|
-
// Handle multi-level nesting
|
|
619
531
|
let current = mappedRow[rootField]
|
|
620
532
|
for (let i = 1; i < parts.length - 1; i++) {
|
|
621
533
|
if (!current[parts[i]]) {
|
|
@@ -624,51 +536,41 @@ function showPreview() {
|
|
|
624
536
|
current = current[parts[i]]
|
|
625
537
|
}
|
|
626
538
|
|
|
627
|
-
// Set the value at the final level
|
|
628
539
|
current[parts[parts.length - 1]] = value
|
|
629
540
|
} else {
|
|
630
541
|
mappedRow[field.id] = value
|
|
631
542
|
}
|
|
632
543
|
})
|
|
633
544
|
|
|
634
|
-
// Process array child fields
|
|
635
545
|
const arrayChildFields = schemaFields.value.filter(field => field.isArrayField && field.parentField)
|
|
636
546
|
|
|
637
|
-
// Process each array field
|
|
638
547
|
arrayChildFields.forEach((childField) => {
|
|
639
548
|
const [parentId, childId] = childField.id.split('.')
|
|
640
549
|
if (!parentId || !childId) return
|
|
641
550
|
|
|
642
|
-
// Get value from mapping or use default
|
|
643
551
|
let value: any = null
|
|
644
552
|
let useDefault = false
|
|
645
553
|
|
|
646
554
|
if (fieldMapping[childField.id] && sourceRow[fieldMapping[childField.id]] !== undefined) {
|
|
647
555
|
value = sourceRow[fieldMapping[childField.id]]
|
|
648
|
-
// Use default value as fallback if the mapped value is empty
|
|
649
556
|
if (value === '' && defaultValues[childField.id] !== undefined) {
|
|
650
557
|
value = defaultValues[childField.id]
|
|
651
558
|
useDefault = true
|
|
652
559
|
}
|
|
653
560
|
} else if (defaultValues[childField.id] !== undefined) {
|
|
654
|
-
// Use default value if no direct mapping
|
|
655
561
|
value = defaultValues[childField.id]
|
|
656
562
|
useDefault = true
|
|
657
563
|
}
|
|
658
564
|
|
|
659
|
-
// Skip if no value
|
|
660
565
|
if (value === null) {
|
|
661
566
|
return
|
|
662
567
|
}
|
|
663
568
|
|
|
664
|
-
// Create the array structure if it doesn't exist
|
|
665
569
|
if (!mappedRow[parentId]) {
|
|
666
570
|
mappedRow[parentId] = []
|
|
667
571
|
}
|
|
668
572
|
|
|
669
|
-
// Apply transformations if any exist and not using default
|
|
670
573
|
if (!useDefault && transformations[childField.id] && transformations[childField.id].length > 0) {
|
|
671
|
-
// Find matching transformation
|
|
672
574
|
const transform = transformations[childField.id].find(t => t.sourceValue == value || t.sourceValue === String(value)
|
|
673
575
|
)
|
|
674
576
|
if (transform) {
|
|
@@ -676,71 +578,57 @@ function showPreview() {
|
|
|
676
578
|
}
|
|
677
579
|
}
|
|
678
580
|
|
|
679
|
-
// Apply data type conversion for array fields
|
|
680
581
|
const dataType = fieldDataTypes[childField.id] || DATA_TYPES.STRING
|
|
681
582
|
value = convertValueByType(value, dataType)
|
|
682
583
|
|
|
683
|
-
// Add the array item with the proper structure
|
|
684
584
|
mappedRow[parentId].push({
|
|
685
585
|
[childId]: value
|
|
686
586
|
})
|
|
687
587
|
})
|
|
688
588
|
|
|
689
|
-
// Handle related file data
|
|
690
589
|
Object.keys(relatedFiles).forEach((fieldId) => {
|
|
691
590
|
if (!relatedFiles[fieldId] || !relatedKeyField[fieldId] || !parentKeyField[fieldId]) {
|
|
692
591
|
return
|
|
693
592
|
}
|
|
694
593
|
|
|
695
|
-
// Get parent key value from this row
|
|
696
594
|
const parentKeyValue = sourceRow[parentKeyField[fieldId]]
|
|
697
595
|
if (!parentKeyValue) return
|
|
698
596
|
|
|
699
|
-
// Create the array structure if it doesn't exist
|
|
700
597
|
if (!mappedRow[fieldId]) {
|
|
701
598
|
mappedRow[fieldId] = []
|
|
702
599
|
}
|
|
703
600
|
|
|
704
|
-
// Find matching rows in related data
|
|
705
601
|
const matchingRows = relatedFileData[fieldId].filter(relatedRow => relatedRow[relatedKeyField[fieldId]] == parentKeyValue
|
|
706
602
|
|| relatedRow[relatedKeyField[fieldId]] === parentKeyValue.toString()
|
|
707
603
|
)
|
|
708
604
|
|
|
709
|
-
// Add each matching row as an item in the array
|
|
710
605
|
matchingRows.forEach((matchingRow) => {
|
|
711
606
|
const mappedItem: Record<string, any> = {}
|
|
712
607
|
|
|
713
|
-
// Apply mappings from related file
|
|
714
608
|
if (selectedRelationField.value?.attrs?.schema) {
|
|
715
609
|
selectedRelationField.value.attrs.schema.forEach((schemaItem: SchemaItem) => {
|
|
716
610
|
if (!schemaItem.id) return
|
|
717
611
|
|
|
718
|
-
// Get value from related mapping or use default
|
|
719
612
|
let value: any = null
|
|
720
613
|
let useDefault = false
|
|
721
614
|
|
|
722
615
|
if (relatedFileMappings[fieldId][schemaItem.id]
|
|
723
616
|
&& matchingRow[relatedFileMappings[fieldId][schemaItem.id]] !== undefined) {
|
|
724
617
|
value = matchingRow[relatedFileMappings[fieldId][schemaItem.id]]
|
|
725
|
-
// Use default as fallback for empty values
|
|
726
618
|
if (value === '' && relatedDefaultValues[fieldId][schemaItem.id] !== undefined) {
|
|
727
619
|
value = relatedDefaultValues[fieldId][schemaItem.id]
|
|
728
620
|
useDefault = true
|
|
729
621
|
}
|
|
730
622
|
} else if (relatedDefaultValues[fieldId][schemaItem.id] !== undefined) {
|
|
731
|
-
// Use default value if no mapping
|
|
732
623
|
value = relatedDefaultValues[fieldId][schemaItem.id]
|
|
733
624
|
useDefault = true
|
|
734
625
|
}
|
|
735
626
|
|
|
736
|
-
// Skip if no value
|
|
737
627
|
if (value === null) return
|
|
738
628
|
|
|
739
|
-
// Apply transformations if any exist and not using default
|
|
740
629
|
if (!useDefault
|
|
741
630
|
&& relatedTransformations[fieldId][schemaItem.id]
|
|
742
631
|
&& relatedTransformations[fieldId][schemaItem.id].length > 0) {
|
|
743
|
-
// Find matching transformation
|
|
744
632
|
const transform = relatedTransformations[fieldId][schemaItem.id].find(t => t.sourceValue == value || t.sourceValue === String(value)
|
|
745
633
|
)
|
|
746
634
|
if (transform) {
|
|
@@ -748,24 +636,20 @@ function showPreview() {
|
|
|
748
636
|
}
|
|
749
637
|
}
|
|
750
638
|
|
|
751
|
-
// Apply data type conversion
|
|
752
639
|
const fullChildId = `${fieldId}.${schemaItem.id}`
|
|
753
640
|
const dataType = relatedFieldDataTypes[fullChildId] || DATA_TYPES.STRING
|
|
754
641
|
value = convertValueByType(value, dataType)
|
|
755
642
|
|
|
756
|
-
// Add to mapped item
|
|
757
643
|
mappedItem[schemaItem.id] = value
|
|
758
644
|
})
|
|
759
645
|
}
|
|
760
646
|
|
|
761
|
-
// Only add item if it has at least one value
|
|
762
647
|
if (Object.keys(mappedItem).length > 0) {
|
|
763
648
|
mappedRow[fieldId].push(mappedItem)
|
|
764
649
|
}
|
|
765
650
|
})
|
|
766
651
|
})
|
|
767
652
|
|
|
768
|
-
// Check if this row has any data (not empty)
|
|
769
653
|
const hasData = Object.values(mappedRow).some((value) => {
|
|
770
654
|
if (value === null || value === undefined) return false
|
|
771
655
|
if (value === '') return false
|
|
@@ -773,39 +657,30 @@ function showPreview() {
|
|
|
773
657
|
return true
|
|
774
658
|
})
|
|
775
659
|
|
|
776
|
-
// Only add rows that have data
|
|
777
660
|
if (hasData) {
|
|
778
661
|
mappedData.push(mappedRow)
|
|
779
662
|
}
|
|
780
663
|
}
|
|
781
664
|
|
|
782
|
-
// Update the preview data with all non-empty rows
|
|
783
665
|
previewData.value = mappedData
|
|
784
|
-
|
|
785
|
-
// Show the modal
|
|
786
666
|
showPreviewModal.value = true
|
|
787
667
|
}
|
|
788
668
|
|
|
789
|
-
// Create a function to convert our schema fields to Spreadsheet column config
|
|
790
669
|
function createSpreadsheetColumns() {
|
|
791
670
|
return schemaFields.value
|
|
792
671
|
.filter((field) => {
|
|
793
672
|
return field.$el !== 'array'
|
|
794
673
|
})
|
|
795
674
|
.map((field) => {
|
|
796
|
-
// Create a column config for each field
|
|
797
675
|
return {
|
|
798
676
|
key: field.id,
|
|
799
677
|
title: field.label,
|
|
800
|
-
// Special formatting for array child fields
|
|
801
678
|
formatter: field.isArrayField ? formatArrayChildValue : undefined
|
|
802
679
|
}
|
|
803
680
|
})
|
|
804
681
|
}
|
|
805
682
|
|
|
806
|
-
// Helper function to format array child values for display
|
|
807
683
|
function formatArrayChildValue(value: any, row: any, fieldId: string): string {
|
|
808
|
-
// For array child fields, we need to check if it's in the parent array
|
|
809
684
|
const field = schemaFields.value.find(f => f.id === fieldId)
|
|
810
685
|
if (!field || !field.isArrayField || !field.parentField) return value
|
|
811
686
|
|
|
@@ -813,7 +688,6 @@ function formatArrayChildValue(value: any, row: any, fieldId: string): string {
|
|
|
813
688
|
const parentArray = row[parentId]
|
|
814
689
|
|
|
815
690
|
if (Array.isArray(parentArray) && parentArray.length > 0) {
|
|
816
|
-
// Extract values from the parent array
|
|
817
691
|
return parentArray
|
|
818
692
|
.map(item => item[childId])
|
|
819
693
|
.filter(val => val !== undefined)
|
|
@@ -823,7 +697,6 @@ function formatArrayChildValue(value: any, row: any, fieldId: string): string {
|
|
|
823
697
|
return ''
|
|
824
698
|
}
|
|
825
699
|
|
|
826
|
-
// Add computed for spreadsheet columns
|
|
827
700
|
const spreadsheetColumns = computed(() => createSpreadsheetColumns())
|
|
828
701
|
|
|
829
702
|
function processData() {
|
|
@@ -885,21 +758,19 @@ async function handleFilesUploaded(files: FileList) {
|
|
|
885
758
|
isLoading.value = false
|
|
886
759
|
}
|
|
887
760
|
}
|
|
888
|
-
|
|
761
|
+
|
|
889
762
|
watchEffect(() => {
|
|
890
763
|
if (selectedSheet.value) {
|
|
891
764
|
loadSheetData()
|
|
892
765
|
}
|
|
893
766
|
})
|
|
894
767
|
|
|
895
|
-
// Function to check if field has default value
|
|
896
768
|
function hasDefaultValue(fieldId: string): boolean {
|
|
897
769
|
return defaultValues[fieldId] !== undefined
|
|
898
770
|
&& defaultValues[fieldId] !== null
|
|
899
771
|
&& defaultValues[fieldId] !== ''
|
|
900
772
|
}
|
|
901
773
|
|
|
902
|
-
// Function to open transformation dialog
|
|
903
774
|
function openTransformDialog(field: SchemaItem) {
|
|
904
775
|
try {
|
|
905
776
|
if (!field.options) {
|
|
@@ -920,20 +791,17 @@ function openTransformDialog(field: SchemaItem) {
|
|
|
920
791
|
}
|
|
921
792
|
}
|
|
922
793
|
|
|
923
|
-
// Function to remove a transformation
|
|
924
794
|
function removeTransformation(fieldId: string, index: number) {
|
|
925
795
|
if (transformations[fieldId] && transformations[fieldId].length > index) {
|
|
926
796
|
transformations[fieldId].splice(index, 1)
|
|
927
797
|
}
|
|
928
798
|
}
|
|
929
799
|
|
|
930
|
-
// Function to open related file dialog
|
|
931
800
|
function openRelatedDialog(field: SchemaItem) {
|
|
932
801
|
selectedRelationField.value = field
|
|
933
802
|
showRelatedDialog.value = true
|
|
934
803
|
}
|
|
935
804
|
|
|
936
|
-
// Function to process related file
|
|
937
805
|
async function processRelatedFile(fieldId: string, files: File[] | FileList) {
|
|
938
806
|
if (!files) return
|
|
939
807
|
const file = files[0]
|
|
@@ -941,15 +809,12 @@ async function processRelatedFile(fieldId: string, files: File[] | FileList) {
|
|
|
941
809
|
relatedFiles[fieldId] = file
|
|
942
810
|
|
|
943
811
|
try {
|
|
944
|
-
// First get sheet names
|
|
945
812
|
const sheets = await getSheetNames(file)
|
|
946
813
|
const selectedSheet = sheets.length > 0 ? sheets[0] : ''
|
|
947
814
|
|
|
948
|
-
// Use the first sheet instead of an empty string
|
|
949
815
|
const { data } = await readSheetData(file, selectedSheet, true)
|
|
950
816
|
relatedFileData[fieldId] = data
|
|
951
817
|
|
|
952
|
-
// Initialize mapping if not exists
|
|
953
818
|
if (!relatedFileMappings[fieldId]) {
|
|
954
819
|
relatedFileMappings[fieldId] = {}
|
|
955
820
|
}
|
|
@@ -958,7 +823,6 @@ async function processRelatedFile(fieldId: string, files: File[] | FileList) {
|
|
|
958
823
|
}
|
|
959
824
|
}
|
|
960
825
|
|
|
961
|
-
// Add function to auto-populate transformations for a field
|
|
962
826
|
function autoPopulateTransformations(fieldId: string) {
|
|
963
827
|
try {
|
|
964
828
|
const field = schemaFields.value.find(f => f.id === fieldId)
|
|
@@ -967,7 +831,6 @@ function autoPopulateTransformations(fieldId: string) {
|
|
|
967
831
|
return
|
|
968
832
|
}
|
|
969
833
|
|
|
970
|
-
// Ensure options are available either directly or from attrs
|
|
971
834
|
let fieldOptions = field.options || (field.attrs && field.attrs.options)
|
|
972
835
|
|
|
973
836
|
if (!fieldMapping[fieldId] || !fileData.value || fileData.value.length === 0) {
|
|
@@ -980,7 +843,6 @@ function autoPopulateTransformations(fieldId: string) {
|
|
|
980
843
|
return
|
|
981
844
|
}
|
|
982
845
|
|
|
983
|
-
// Ensure options is an array
|
|
984
846
|
if (!Array.isArray(fieldOptions)) {
|
|
985
847
|
console.warn('Options is not an array for field:', fieldId)
|
|
986
848
|
fieldOptions = []
|
|
@@ -988,7 +850,6 @@ function autoPopulateTransformations(fieldId: string) {
|
|
|
988
850
|
|
|
989
851
|
const uniqueValues = getUniqueSourceValues(fieldId)
|
|
990
852
|
|
|
991
|
-
// Initialize transformations array if needed
|
|
992
853
|
if (!transformations[fieldId]) {
|
|
993
854
|
transformations[fieldId] = []
|
|
994
855
|
}
|
|
@@ -996,21 +857,17 @@ function autoPopulateTransformations(fieldId: string) {
|
|
|
996
857
|
let matchCount = 0
|
|
997
858
|
const unmatchedValues: string[] = []
|
|
998
859
|
|
|
999
|
-
// For each unique value, try to find a matching target
|
|
1000
860
|
uniqueValues.forEach((sourceValue) => {
|
|
1001
861
|
const strSourceValue = String(sourceValue)
|
|
1002
862
|
const matchedValue = findMatchingTargetValue(strSourceValue, fieldOptions)
|
|
1003
863
|
|
|
1004
864
|
if (matchedValue) {
|
|
1005
|
-
// Check if this source value already has a transformation
|
|
1006
865
|
const existingIndex = transformations[fieldId].findIndex(t => t.sourceValue === strSourceValue
|
|
1007
866
|
)
|
|
1008
867
|
|
|
1009
868
|
if (existingIndex >= 0) {
|
|
1010
|
-
// Update existing transformation
|
|
1011
869
|
transformations[fieldId][existingIndex].targetValue = matchedValue
|
|
1012
870
|
} else {
|
|
1013
|
-
// Add new transformation
|
|
1014
871
|
transformations[fieldId].push({
|
|
1015
872
|
fieldId,
|
|
1016
873
|
sourceValue: strSourceValue,
|
|
@@ -1024,7 +881,6 @@ function autoPopulateTransformations(fieldId: string) {
|
|
|
1024
881
|
}
|
|
1025
882
|
})
|
|
1026
883
|
|
|
1027
|
-
// Provide some feedback about how many matches were found
|
|
1028
884
|
if (matchCount === 0) {
|
|
1029
885
|
alert(`No automatic matches found. Try creating transformations manually.`)
|
|
1030
886
|
} else {
|
|
@@ -1036,9 +892,7 @@ function autoPopulateTransformations(fieldId: string) {
|
|
|
1036
892
|
}
|
|
1037
893
|
}
|
|
1038
894
|
|
|
1039
|
-
// Function to detect date format from string
|
|
1040
895
|
function detectDateFormat(value: string): RegExp | null {
|
|
1041
|
-
// Common date formats
|
|
1042
896
|
const formats = [
|
|
1043
897
|
/^\d{4}-\d{2}-\d{2}$/, // YYYY-MM-DD
|
|
1044
898
|
/^\d{2}\/\d{2}\/\d{4}$/, // MM/DD/YYYY
|
|
@@ -1055,30 +909,22 @@ function detectDateFormat(value: string): RegExp | null {
|
|
|
1055
909
|
return null
|
|
1056
910
|
}
|
|
1057
911
|
|
|
1058
|
-
// Function to parse date string based on detected format
|
|
1059
912
|
function parseDate(value: string): Date | null {
|
|
1060
913
|
if (!value) return null
|
|
1061
914
|
|
|
1062
|
-
// Try parsing ISO format first
|
|
1063
915
|
const isoDate = new Date(value)
|
|
1064
916
|
if (!Number.isNaN(isoDate.getTime())) {
|
|
1065
917
|
return isoDate
|
|
1066
918
|
}
|
|
1067
|
-
|
|
1068
|
-
// Try parsing other formats
|
|
1069
919
|
const format = detectDateFormat(value)
|
|
1070
920
|
if (format) {
|
|
1071
|
-
// Handle specific formats
|
|
1072
921
|
if (/^\d{2}\/\d{2}\/\d{4}$/.test(value)) {
|
|
1073
|
-
// MM/DD/YYYY
|
|
1074
922
|
const [month, day, year] = value.split('/').map(Number)
|
|
1075
923
|
return new Date(year, month - 1, day)
|
|
1076
924
|
} else if (/^\d{2}\.\d{2}\.\d{4}$/.test(value)) {
|
|
1077
|
-
// DD.MM.YYYY
|
|
1078
925
|
const [day, month, year] = value.split('.').map(Number)
|
|
1079
926
|
return new Date(year, month - 1, day)
|
|
1080
927
|
} else if (/^\d{1,2}\s[a-z]{3,9}\s\d{4}$/i.test(value)) {
|
|
1081
|
-
// D MMM YYYY or D MMMM YYYY
|
|
1082
928
|
return new Date(value)
|
|
1083
929
|
}
|
|
1084
930
|
}
|
|
@@ -1086,12 +932,10 @@ function parseDate(value: string): Date | null {
|
|
|
1086
932
|
return null
|
|
1087
933
|
}
|
|
1088
934
|
|
|
1089
|
-
// Replace convertValueByType function with simplified version using composable utilities
|
|
1090
935
|
function convertValueByType(value: any, dataType: string): any {
|
|
1091
936
|
if (value === null || value === undefined || value === '') {
|
|
1092
937
|
return null
|
|
1093
938
|
}
|
|
1094
|
-
|
|
1095
939
|
try {
|
|
1096
940
|
switch (dataType) {
|
|
1097
941
|
case DATA_TYPES.STRING:
|
|
@@ -1110,24 +954,18 @@ function convertValueByType(value: any, dataType: string): any {
|
|
|
1110
954
|
if (['false', 'no', '0', 'off'].includes(lowercased)) return false
|
|
1111
955
|
}
|
|
1112
956
|
return Boolean(value)
|
|
1113
|
-
|
|
1114
957
|
case DATA_TYPES.DATE:
|
|
1115
958
|
case DATA_TYPES.DATETIME:
|
|
1116
|
-
// Handle Excel serial dates
|
|
1117
959
|
if (isExcelSerialDate(value)) {
|
|
1118
960
|
const date = excelSerialDateToJSDate(value)
|
|
1119
961
|
return formatDate(date, dataType === DATA_TYPES.DATETIME)
|
|
1120
962
|
}
|
|
1121
|
-
|
|
1122
|
-
// Handle string dates
|
|
1123
963
|
if (typeof value === 'string') {
|
|
1124
964
|
const dateObj = parseDate(value)
|
|
1125
965
|
if (dateObj) {
|
|
1126
966
|
return formatDate(dateObj, dataType === DATA_TYPES.DATETIME)
|
|
1127
967
|
}
|
|
1128
968
|
}
|
|
1129
|
-
|
|
1130
|
-
// Handle Date objects
|
|
1131
969
|
if (value instanceof Date) {
|
|
1132
970
|
return formatDate(value, dataType === DATA_TYPES.DATETIME)
|
|
1133
971
|
}
|
|
@@ -1161,28 +999,22 @@ function detectDataType(value: any): string {
|
|
|
1161
999
|
}
|
|
1162
1000
|
|
|
1163
1001
|
if (typeof value === 'string') {
|
|
1164
|
-
// Check if it's a date string
|
|
1165
1002
|
if (detectDateFormat(value) || !Number.isNaN(new Date(value).getTime())) {
|
|
1166
1003
|
return DATA_TYPES.DATE
|
|
1167
1004
|
}
|
|
1168
1005
|
}
|
|
1169
|
-
|
|
1170
|
-
// Default to string
|
|
1171
1006
|
return DATA_TYPES.STRING
|
|
1172
1007
|
}
|
|
1173
1008
|
|
|
1174
|
-
// Function to guess data types for all mapped fields
|
|
1175
1009
|
function guessDataTypes(): void {
|
|
1176
1010
|
schemaFields.value.forEach((field) => {
|
|
1177
1011
|
if (!fieldDataTypes[field.id] && fieldMapping[field.id]) {
|
|
1178
|
-
// Get sample values from the first few rows
|
|
1179
1012
|
const sampleValues = fileData.value
|
|
1180
1013
|
.slice(0, 5)
|
|
1181
1014
|
.map(row => row[fieldMapping[field.id]])
|
|
1182
1015
|
.filter(value => value !== undefined && value !== null && value !== '')
|
|
1183
1016
|
|
|
1184
1017
|
if (sampleValues.length > 0) {
|
|
1185
|
-
// Detect most common type
|
|
1186
1018
|
const types = sampleValues.map(detectDataType)
|
|
1187
1019
|
const typeCount: Record<string, number> = {}
|
|
1188
1020
|
|
|
@@ -1190,7 +1022,6 @@ function guessDataTypes(): void {
|
|
|
1190
1022
|
typeCount[type] = (typeCount[type] || 0) + 1
|
|
1191
1023
|
})
|
|
1192
1024
|
|
|
1193
|
-
// Get the most common type
|
|
1194
1025
|
let maxCount = 0
|
|
1195
1026
|
let mostCommonType = DATA_TYPES.STRING
|
|
1196
1027
|
|
|
@@ -1209,12 +1040,9 @@ function guessDataTypes(): void {
|
|
|
1209
1040
|
})
|
|
1210
1041
|
}
|
|
1211
1042
|
|
|
1212
|
-
// Function to open transformation dialog for related fields
|
|
1213
1043
|
function openRelatedTransformDialog(parentId: string, field: SchemaItem) {
|
|
1214
1044
|
try {
|
|
1215
1045
|
console.log('Opening related transform dialog for field:', field.id, 'in parent:', parentId)
|
|
1216
|
-
|
|
1217
|
-
// Make sure to set options property from attrs if needed
|
|
1218
1046
|
if (!field.options) {
|
|
1219
1047
|
field.options = []
|
|
1220
1048
|
}
|
|
@@ -1228,7 +1056,6 @@ function openRelatedTransformDialog(parentId: string, field: SchemaItem) {
|
|
|
1228
1056
|
|
|
1229
1057
|
selectedRelatedTransformField.value = { parentId, field }
|
|
1230
1058
|
|
|
1231
|
-
// Initialize transformations structure if needed
|
|
1232
1059
|
if (!relatedTransformations[parentId]) {
|
|
1233
1060
|
relatedTransformations[parentId] = {}
|
|
1234
1061
|
}
|
|
@@ -1239,7 +1066,6 @@ function openRelatedTransformDialog(parentId: string, field: SchemaItem) {
|
|
|
1239
1066
|
|
|
1240
1067
|
showRelatedTransformDialog.value = true
|
|
1241
1068
|
|
|
1242
|
-
// Reset selected values
|
|
1243
1069
|
selectedRelatedSourceValue.value = ''
|
|
1244
1070
|
selectedRelatedTargetValue.value = ''
|
|
1245
1071
|
} catch (error) {
|
|
@@ -1248,7 +1074,6 @@ function openRelatedTransformDialog(parentId: string, field: SchemaItem) {
|
|
|
1248
1074
|
}
|
|
1249
1075
|
}
|
|
1250
1076
|
|
|
1251
|
-
// Function to get unique source values for a related field
|
|
1252
1077
|
function getRelatedUniqueSourceValues(parentId: string, fieldId: string): any[] {
|
|
1253
1078
|
if (!relatedFileMappings[parentId][fieldId]
|
|
1254
1079
|
|| !relatedFileData[parentId]
|
|
@@ -1256,28 +1081,22 @@ function getRelatedUniqueSourceValues(parentId: string, fieldId: string): any[]
|
|
|
1256
1081
|
return []
|
|
1257
1082
|
}
|
|
1258
1083
|
|
|
1259
|
-
// Get all values from the mapped column in the related file
|
|
1260
1084
|
const allValues = relatedFileData[parentId]
|
|
1261
1085
|
.map(row => row[relatedFileMappings[parentId][fieldId]])
|
|
1262
1086
|
.filter(value => value !== undefined && value !== null && value !== '')
|
|
1263
1087
|
|
|
1264
|
-
// Create a unique set of values
|
|
1265
1088
|
const uniqueValues = [...new Set(allValues)]
|
|
1266
1089
|
|
|
1267
|
-
// Filter out values that already have transformations
|
|
1268
1090
|
return uniqueValues.filter((value) => {
|
|
1269
1091
|
if (!relatedTransformations[parentId][fieldId]
|
|
1270
1092
|
|| relatedTransformations[parentId][fieldId].length === 0) {
|
|
1271
1093
|
return true
|
|
1272
1094
|
}
|
|
1273
|
-
|
|
1274
|
-
// Return false if this value already has a transformation
|
|
1275
1095
|
return !relatedTransformations[parentId][fieldId].some(t => t.sourceValue == value || t.sourceValue === value.toString()
|
|
1276
1096
|
)
|
|
1277
1097
|
})
|
|
1278
1098
|
}
|
|
1279
1099
|
|
|
1280
|
-
// Computed for available related source values
|
|
1281
1100
|
const availableRelatedSourceValues = computed(() => {
|
|
1282
1101
|
if (!selectedRelatedTransformField.value) {
|
|
1283
1102
|
return []
|
|
@@ -1287,7 +1106,6 @@ const availableRelatedSourceValues = computed(() => {
|
|
|
1287
1106
|
return getRelatedUniqueSourceValues(parentId, field.id)
|
|
1288
1107
|
})
|
|
1289
1108
|
|
|
1290
|
-
// Create options array from unique related values
|
|
1291
1109
|
const relatedSourceValueOptions = computed(() => {
|
|
1292
1110
|
return availableRelatedSourceValues.value.map(value => ({
|
|
1293
1111
|
value: String(value),
|
|
@@ -1295,7 +1113,6 @@ const relatedSourceValueOptions = computed(() => {
|
|
|
1295
1113
|
}))
|
|
1296
1114
|
})
|
|
1297
1115
|
|
|
1298
|
-
// Function to add a related transformation
|
|
1299
1116
|
function addRelatedTransformation(parentId: string, fieldId: string) {
|
|
1300
1117
|
if (!relatedTransformations[parentId]) {
|
|
1301
1118
|
relatedTransformations[parentId] = {}
|
|
@@ -1306,30 +1123,24 @@ function addRelatedTransformation(parentId: string, fieldId: string) {
|
|
|
1306
1123
|
}
|
|
1307
1124
|
|
|
1308
1125
|
if (selectedRelatedSourceValue.value && selectedRelatedTargetValue.value) {
|
|
1309
|
-
// Check if this source value already has a transformation
|
|
1310
1126
|
const existingIndex = relatedTransformations[parentId][fieldId].findIndex(
|
|
1311
1127
|
t => t.sourceValue === selectedRelatedSourceValue.value
|
|
1312
1128
|
)
|
|
1313
1129
|
|
|
1314
1130
|
if (existingIndex >= 0) {
|
|
1315
|
-
// Update existing transformation
|
|
1316
1131
|
relatedTransformations[parentId][fieldId][existingIndex].targetValue = selectedRelatedTargetValue.value
|
|
1317
1132
|
} else {
|
|
1318
|
-
// Add new transformation
|
|
1319
1133
|
relatedTransformations[parentId][fieldId].push({
|
|
1320
1134
|
fieldId,
|
|
1321
1135
|
sourceValue: selectedRelatedSourceValue.value,
|
|
1322
1136
|
targetValue: selectedRelatedTargetValue.value
|
|
1323
1137
|
})
|
|
1324
1138
|
}
|
|
1325
|
-
|
|
1326
|
-
// Reset selection
|
|
1327
1139
|
selectedRelatedSourceValue.value = ''
|
|
1328
1140
|
selectedRelatedTargetValue.value = ''
|
|
1329
1141
|
}
|
|
1330
1142
|
}
|
|
1331
1143
|
|
|
1332
|
-
// Function to remove a related transformation
|
|
1333
1144
|
function removeRelatedTransformation(parentId: string, fieldId: string, index: number) {
|
|
1334
1145
|
if (relatedTransformations[parentId][fieldId]
|
|
1335
1146
|
&& relatedTransformations[parentId][fieldId].length > index) {
|
|
@@ -1337,7 +1148,6 @@ function removeRelatedTransformation(parentId: string, fieldId: string, index: n
|
|
|
1337
1148
|
}
|
|
1338
1149
|
}
|
|
1339
1150
|
|
|
1340
|
-
// Function to auto-populate transformations for a related field
|
|
1341
1151
|
function autoPopulateRelatedTransformations(parentId: string, fieldId: string) {
|
|
1342
1152
|
try {
|
|
1343
1153
|
const field = selectedRelatedTransformField.value?.field
|
|
@@ -1346,7 +1156,6 @@ function autoPopulateRelatedTransformations(parentId: string, fieldId: string) {
|
|
|
1346
1156
|
return
|
|
1347
1157
|
}
|
|
1348
1158
|
|
|
1349
|
-
// Ensure options are available either directly or from attrs
|
|
1350
1159
|
let fieldOptions = field.options || (field.attrs && field.attrs.options)
|
|
1351
1160
|
|
|
1352
1161
|
if (!relatedFileMappings[parentId][fieldId]
|
|
@@ -1361,7 +1170,6 @@ function autoPopulateRelatedTransformations(parentId: string, fieldId: string) {
|
|
|
1361
1170
|
return
|
|
1362
1171
|
}
|
|
1363
1172
|
|
|
1364
|
-
// Ensure options is an array
|
|
1365
1173
|
if (!Array.isArray(fieldOptions)) {
|
|
1366
1174
|
console.warn('Options is not an array for related field:', fieldId)
|
|
1367
1175
|
fieldOptions = []
|
|
@@ -1369,7 +1177,6 @@ function autoPopulateRelatedTransformations(parentId: string, fieldId: string) {
|
|
|
1369
1177
|
|
|
1370
1178
|
const uniqueValues = getRelatedUniqueSourceValues(parentId, fieldId)
|
|
1371
1179
|
|
|
1372
|
-
// Initialize transformations array if needed
|
|
1373
1180
|
if (!relatedTransformations[parentId]) {
|
|
1374
1181
|
relatedTransformations[parentId] = {}
|
|
1375
1182
|
}
|
|
@@ -1381,14 +1188,12 @@ function autoPopulateRelatedTransformations(parentId: string, fieldId: string) {
|
|
|
1381
1188
|
let matchCount = 0
|
|
1382
1189
|
const unmatchedValues: string[] = []
|
|
1383
1190
|
|
|
1384
|
-
// For each unique value, try to find a matching target
|
|
1385
1191
|
uniqueValues.forEach((sourceValue) => {
|
|
1386
1192
|
const strSourceValue = String(sourceValue)
|
|
1387
1193
|
|
|
1388
1194
|
const matchedValue = findMatchingTargetValue(strSourceValue, fieldOptions)
|
|
1389
1195
|
|
|
1390
1196
|
if (matchedValue) {
|
|
1391
|
-
// Check if this source value already has a transformation
|
|
1392
1197
|
const existingIndex = relatedTransformations[parentId][fieldId].findIndex(
|
|
1393
1198
|
t => t.sourceValue === strSourceValue
|
|
1394
1199
|
)
|
|
@@ -1410,8 +1215,6 @@ function autoPopulateRelatedTransformations(parentId: string, fieldId: string) {
|
|
|
1410
1215
|
unmatchedValues.push(strSourceValue)
|
|
1411
1216
|
}
|
|
1412
1217
|
})
|
|
1413
|
-
|
|
1414
|
-
// Provide feedback about matches
|
|
1415
1218
|
if (matchCount === 0) {
|
|
1416
1219
|
alert(`No automatic matches found. Try creating transformations manually.`)
|
|
1417
1220
|
} else {
|
|
@@ -1423,15 +1226,12 @@ function autoPopulateRelatedTransformations(parentId: string, fieldId: string) {
|
|
|
1423
1226
|
}
|
|
1424
1227
|
}
|
|
1425
1228
|
|
|
1426
|
-
// Initialize default value structure for a field
|
|
1427
1229
|
function initDefaultValue(fieldId: string) {
|
|
1428
|
-
// Make sure the field has an entry in defaultValues
|
|
1429
1230
|
if (defaultValues[fieldId] === undefined) {
|
|
1430
1231
|
defaultValues[fieldId] = null
|
|
1431
1232
|
}
|
|
1432
1233
|
}
|
|
1433
1234
|
|
|
1434
|
-
// Initialize related default value structure
|
|
1435
1235
|
function initRelatedDefaultValue(parentId: string, fieldId: string) {
|
|
1436
1236
|
if (!relatedDefaultValues[parentId]) {
|
|
1437
1237
|
relatedDefaultValues[parentId] = {}
|
|
@@ -1441,12 +1241,9 @@ function initRelatedDefaultValue(parentId: string, fieldId: string) {
|
|
|
1441
1241
|
}
|
|
1442
1242
|
}
|
|
1443
1243
|
|
|
1444
|
-
// Helper function to prepare a field with default values for rendering
|
|
1445
1244
|
function getFieldWithDefaults(field: any) {
|
|
1446
|
-
// Get the current field type to render proper input
|
|
1447
1245
|
let fieldType = field.$el || 'text'
|
|
1448
1246
|
|
|
1449
|
-
// If datatype is set, adjust the field type accordingly
|
|
1450
1247
|
if (fieldDataTypes[field.id]) {
|
|
1451
1248
|
switch (fieldDataTypes[field.id]) {
|
|
1452
1249
|
case DATA_TYPES.NUMBER:
|
|
@@ -1461,7 +1258,6 @@ function getFieldWithDefaults(field: any) {
|
|
|
1461
1258
|
}
|
|
1462
1259
|
}
|
|
1463
1260
|
|
|
1464
|
-
// Update formData with current value to support the renderField function
|
|
1465
1261
|
if (field.id) {
|
|
1466
1262
|
formData.value[field.id] = defaultValues[field.id]
|
|
1467
1263
|
}
|
|
@@ -1473,12 +1269,8 @@ function getFieldWithDefaults(field: any) {
|
|
|
1473
1269
|
}
|
|
1474
1270
|
}
|
|
1475
1271
|
|
|
1476
|
-
// Add a helper function for related fields too
|
|
1477
1272
|
function getRelatedFieldWithDefaults(parentId: string, field: any) {
|
|
1478
|
-
// Get the current field type to render proper input
|
|
1479
1273
|
let fieldType = field.$el || 'text'
|
|
1480
|
-
|
|
1481
|
-
// If datatype is set, adjust the field type accordingly
|
|
1482
1274
|
const fullFieldId = `${parentId}.${field.id}`
|
|
1483
1275
|
if (relatedFieldDataTypes[fullFieldId]) {
|
|
1484
1276
|
switch (relatedFieldDataTypes[fullFieldId]) {
|
|
@@ -1529,22 +1321,16 @@ function getRelatedFieldWithDefaults(parentId: string, field: any) {
|
|
|
1529
1321
|
</Card>
|
|
1530
1322
|
</DragOver>
|
|
1531
1323
|
</div>
|
|
1532
|
-
|
|
1533
|
-
<!-- Loading indicator -->
|
|
1534
1324
|
<div v-if="isLoading" class="loading-container">
|
|
1535
1325
|
<div class="spinner" />
|
|
1536
1326
|
<p>Processing your file...</p>
|
|
1537
1327
|
</div>
|
|
1538
1328
|
|
|
1539
|
-
<!-- Step 2: Sheet selection and configuration -->
|
|
1540
1329
|
<div class="overflow h-100p">
|
|
1541
1330
|
<div v-if="file && !isLoading && sheetNames.length > 0" class="config-section flex gap-05 pb-2 m_flex-wrap">
|
|
1542
1331
|
<Btn v-tooltip="'Change File'" class="px-1" color="gray" @click="file = null">
|
|
1543
1332
|
<Icon icon="draft" size="1.5" weight="300" />
|
|
1544
|
-
<p
|
|
1545
|
-
{{ file.name }}
|
|
1546
|
-
</p>
|
|
1547
|
-
<!-- <Icon icon="edit" size="0.75" /> -->
|
|
1333
|
+
<p v-text="file.name" />
|
|
1548
1334
|
</Btn>
|
|
1549
1335
|
<SelectInput v-if="sheetNames.length > 1" v-model="selectedSheet" :options="sheetNames" label="Select Sheet" />
|
|
1550
1336
|
<CheckInput
|
|
@@ -1552,12 +1338,7 @@ function getRelatedFieldWithDefaults(parentId: string, field: any) {
|
|
|
1552
1338
|
style="--bgl-accent-color: var(--bgl-black); --bgl-primary: var(--bgl-black);"
|
|
1553
1339
|
/>
|
|
1554
1340
|
</div>
|
|
1555
|
-
|
|
1556
|
-
<!-- Step 3: Field Mapping -->
|
|
1557
1341
|
<div v-if="file && !isLoading && fileHeaders.length > 0">
|
|
1558
|
-
<!-- <h3 class="mt-0">
|
|
1559
|
-
Map Fields
|
|
1560
|
-
</h3> -->
|
|
1561
1342
|
<p class="label pb-1 border-bottom mb-1">
|
|
1562
1343
|
Match each required field to a column from your file, set default values, or configure transformations
|
|
1563
1344
|
</p>
|
|
@@ -1644,8 +1425,6 @@ function getRelatedFieldWithDefaults(parentId: string, field: any) {
|
|
|
1644
1425
|
</div>
|
|
1645
1426
|
</div>
|
|
1646
1427
|
</div>
|
|
1647
|
-
|
|
1648
|
-
<!-- Transformation Modal -->
|
|
1649
1428
|
<Modal v-model:visible="showTransformDialog" title="Configure Transformations" width="800">
|
|
1650
1429
|
<div v-if="selectedTransformField">
|
|
1651
1430
|
<div class="flex space-between gap-1 mb-1 border-bottom pb-05 m_flex-wrap">
|
|
@@ -1718,8 +1497,6 @@ function getRelatedFieldWithDefaults(parentId: string, field: any) {
|
|
|
1718
1497
|
</div>
|
|
1719
1498
|
</div>
|
|
1720
1499
|
</Modal>
|
|
1721
|
-
|
|
1722
|
-
<!-- Related File Modal -->
|
|
1723
1500
|
<Modal v-model:visible="showRelatedDialog" title="Configure Related Data" width="900">
|
|
1724
1501
|
<div v-if="selectedRelationField">
|
|
1725
1502
|
<p class="pb-05">
|
|
@@ -1819,7 +1596,6 @@ function getRelatedFieldWithDefaults(parentId: string, field: any) {
|
|
|
1819
1596
|
</div>
|
|
1820
1597
|
</Modal>
|
|
1821
1598
|
|
|
1822
|
-
<!-- Preview Modal -->
|
|
1823
1599
|
<Modal v-model:visible="showPreviewModal" title="Data Preview & Edit" width="90vw">
|
|
1824
1600
|
<div>
|
|
1825
1601
|
<Spreadsheet
|
|
@@ -1840,7 +1616,6 @@ function getRelatedFieldWithDefaults(parentId: string, field: any) {
|
|
|
1840
1616
|
</div>
|
|
1841
1617
|
</Modal>
|
|
1842
1618
|
|
|
1843
|
-
<!-- Related Transformation Modal -->
|
|
1844
1619
|
<Modal v-model:visible="showRelatedTransformDialog" title="Configure Related Transformations" width="800">
|
|
1845
1620
|
<div v-if="selectedRelatedTransformField">
|
|
1846
1621
|
<p>Create transformations for <strong>{{ selectedRelatedTransformField.field.label }}</strong> in {{ selectedRelationField?.label }}</p>
|
|
@@ -1929,9 +1704,7 @@ function getRelatedFieldWithDefaults(parentId: string, field: any) {
|
|
|
1929
1704
|
</div>
|
|
1930
1705
|
|
|
1931
1706
|
<div>
|
|
1932
|
-
<Btn @click="showRelatedTransformDialog = false"
|
|
1933
|
-
Close
|
|
1934
|
-
</Btn>
|
|
1707
|
+
<Btn value="Close" @click="showRelatedTransformDialog = false" />
|
|
1935
1708
|
</div>
|
|
1936
1709
|
</div>
|
|
1937
1710
|
</Modal>
|