WIP - Fix options for picklist field, some progress on multi picklist.
This commit is contained in:
@@ -152,6 +152,7 @@ export class FieldMapperService {
|
||||
'phone': 'text',
|
||||
'picklist': 'select',
|
||||
'multipicklist': 'multiSelect',
|
||||
'multi_picklist': 'multiSelect',
|
||||
'lookup': 'belongsTo',
|
||||
'master-detail': 'belongsTo',
|
||||
'currency': 'currency',
|
||||
|
||||
@@ -336,13 +336,27 @@ export class ObjectService {
|
||||
updated_at: knex.fn.now(),
|
||||
};
|
||||
|
||||
// Store relationDisplayField in UI metadata if provided
|
||||
if (data.relationDisplayField || data.relationObjects || data.relationTypeField) {
|
||||
fieldData.ui_metadata = JSON.stringify({
|
||||
relationDisplayField: data.relationDisplayField,
|
||||
relationObjects: data.relationObjects,
|
||||
relationTypeField: data.relationTypeField,
|
||||
});
|
||||
// Build UI metadata from all sources
|
||||
const uiMetadataObj: any = {};
|
||||
|
||||
// Merge general uiMetadata (options, placeholder, helpText, etc.)
|
||||
if (data.uiMetadata && typeof data.uiMetadata === 'object') {
|
||||
Object.assign(uiMetadataObj, data.uiMetadata);
|
||||
}
|
||||
|
||||
// Store relation-specific fields in UI metadata if provided
|
||||
if (data.relationDisplayField) {
|
||||
uiMetadataObj.relationDisplayField = data.relationDisplayField;
|
||||
}
|
||||
if (data.relationObjects) {
|
||||
uiMetadataObj.relationObjects = data.relationObjects;
|
||||
}
|
||||
if (data.relationTypeField) {
|
||||
uiMetadataObj.relationTypeField = data.relationTypeField;
|
||||
}
|
||||
|
||||
if (Object.keys(uiMetadataObj).length > 0) {
|
||||
fieldData.ui_metadata = JSON.stringify(uiMetadataObj);
|
||||
}
|
||||
|
||||
await knex('field_definitions').insert(fieldData);
|
||||
|
||||
@@ -249,6 +249,51 @@ const handleRelationTypeUpdate = (value: string | null) => {
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
<!-- Multi-Select -->
|
||||
<div v-else-if="field.type === FieldType.MULTI_SELECT" class="space-y-2">
|
||||
<div class="flex flex-wrap gap-1 min-h-[36px] rounded-md border border-input bg-background px-3 py-2">
|
||||
<Badge
|
||||
v-for="selectedVal in (Array.isArray(value) ? value : [])"
|
||||
:key="String(selectedVal)"
|
||||
variant="secondary"
|
||||
class="gap-1 cursor-pointer"
|
||||
@click="value = (value || []).filter((v: any) => v !== selectedVal)"
|
||||
>
|
||||
{{ field.options?.find(o => o.value === selectedVal)?.label || selectedVal }}
|
||||
<span class="text-xs ml-1">×</span>
|
||||
</Badge>
|
||||
<span v-if="!value || (Array.isArray(value) && value.length === 0)" class="text-sm text-muted-foreground">
|
||||
{{ field.placeholder || 'Select options...' }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="space-y-1">
|
||||
<div
|
||||
v-for="option in field.options"
|
||||
:key="String(option.value)"
|
||||
class="flex items-center gap-2"
|
||||
>
|
||||
<Checkbox
|
||||
:id="`${field.id}-${option.value}`"
|
||||
:checked="Array.isArray(value) && value.includes(option.value)"
|
||||
@update:checked="(checked: boolean) => {
|
||||
const current = Array.isArray(value) ? [...value] : []
|
||||
if (checked) {
|
||||
current.push(option.value)
|
||||
} else {
|
||||
const idx = current.indexOf(option.value)
|
||||
if (idx > -1) current.splice(idx, 1)
|
||||
}
|
||||
value = current
|
||||
}"
|
||||
:disabled="field.isReadOnly"
|
||||
/>
|
||||
<Label :for="`${field.id}-${option.value}`" class="text-sm font-normal cursor-pointer">
|
||||
{{ option.label }}
|
||||
</Label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Boolean - Checkbox -->
|
||||
<div v-else-if="field.type === FieldType.BOOLEAN" class="flex items-center gap-2">
|
||||
<Checkbox :id="field.id" v-model:checked="value" :disabled="field.isReadOnly" />
|
||||
|
||||
Reference in New Issue
Block a user