diff --git a/frontend/src/pages/entity-configuration.vue b/frontend/src/pages/entity-configuration.vue index f06e66c..b105dc9 100644 --- a/frontend/src/pages/entity-configuration.vue +++ b/frontend/src/pages/entity-configuration.vue @@ -2,13 +2,24 @@ import { onMounted, reactive, ref } from 'vue' import { auth } from '@/auth' - const fieldTypes = ['TEXT', 'NUMBER', 'BOOLEAN', 'DATE', 'EMAIL', 'PHONE'] as const + const fieldTypes = ['TEXT', 'NUMBER', 'BOOLEAN', 'DATE', 'EMAIL', 'PHONE', 'RELATIONSHIP', 'USER'] as const type FieldType = typeof fieldTypes[number] + type RelationshipType = 'ONE_TO_ONE' | 'ONE_TO_MANY' + + interface FieldDraft { + name: string + type: FieldType + targetEntityId?: number + relationshipType: RelationshipType + } interface EntityField { id: number name: string type: FieldType + targetEntityId?: number + targetEntityName?: string + relationshipType?: RelationshipType } interface EntityDefinition { @@ -24,10 +35,12 @@ const newEntityName = ref('') const editingEntityId = ref() const editingEntityName = ref('') - const newFields = reactive>({}) + const newFields = reactive>({}) const editingFieldId = ref() const editingFieldName = ref('') const editingFieldType = ref('TEXT') + const editingTargetEntityId = ref() + const editingRelationshipType = ref('ONE_TO_ONE') function request (url: string, method = 'GET', values?: Record) { return fetch(url, { @@ -54,7 +67,7 @@ } function ensureNewField (entityId: number) { - newFields[entityId] ??= { name: '', type: 'TEXT' } + newFields[entityId] ??= { name: '', type: 'TEXT', relationshipType: 'ONE_TO_ONE' } } async function addEntity () { @@ -101,13 +114,19 @@ const name = draft.name.trim() if (!name) return await mutate(async () => { - const response = await request(`/api/entity-definitions/${entity.id}/fields`, 'POST', { + const values: Record = { name, type: draft.type, - }) + } + if (draft.type === 'RELATIONSHIP') { + if (!draft.targetEntityId) return + values.targetEntityId = String(draft.targetEntityId) + values.relationshipType = draft.relationshipType + } + const response = await request(`/api/entity-definitions/${entity.id}/fields`, 'POST', values) if (!response.ok) throw new Error('Field create failed') entity.fields.push(await response.json() as EntityField) - newFields[entity.id] = { name: '', type: 'TEXT' } + newFields[entity.id] = { name: '', type: 'TEXT', relationshipType: 'ONE_TO_ONE' } }) } @@ -115,16 +134,24 @@ editingFieldId.value = field.id editingFieldName.value = field.name editingFieldType.value = field.type + editingTargetEntityId.value = field.targetEntityId + editingRelationshipType.value = field.relationshipType ?? 'ONE_TO_ONE' } async function saveField (entity: EntityDefinition, field: EntityField) { const name = editingFieldName.value.trim() if (!name) return await mutate(async () => { - const response = await request(`/api/entity-definitions/${entity.id}/fields/${field.id}`, 'PATCH', { + const values: Record = { name, type: editingFieldType.value, - }) + } + if (editingFieldType.value === 'RELATIONSHIP') { + if (!editingTargetEntityId.value) return + values.targetEntityId = String(editingTargetEntityId.value) + values.relationshipType = editingRelationshipType.value + } + const response = await request(`/api/entity-definitions/${entity.id}/fields/${field.id}`, 'PATCH', values) if (!response.ok) throw new Error('Field update failed') Object.assign(field, await response.json() as EntityField) editingFieldId.value = undefined @@ -152,6 +179,22 @@ } } + function typeLabel (type: FieldType) { + if (type === 'RELATIONSHIP') return 'Relationship' + if (type === 'USER') return 'User reference' + return type.charAt(0) + type.slice(1).toLowerCase() + } + + function relationshipLabel (type?: RelationshipType) { + return type === 'ONE_TO_MANY' ? 'One to many' : 'One to one' + } + + function targetName (field: EntityField) { + return field.targetEntityName + ?? entities.value.find(entity => entity.id === field.targetEntityId)?.name + ?? 'Unknown entity' + } + onMounted(loadEntities) @@ -205,15 +248,40 @@ + +