Browse Source

feat: custom relation - WIP

pull/8367/head
Pranav C 5 months ago
parent
commit
6155444885
  1. 270
      packages/nc-gui/components/smartsheet/column/LinkAdvancedOptions.vue
  2. 53
      packages/nc-gui/components/smartsheet/column/LinkedToAnotherRecordOptions.vue
  3. 19
      packages/nocodb/src/helpers/columnHelpers.ts
  4. 144
      packages/nocodb/src/services/columns.service.ts

270
packages/nc-gui/components/smartsheet/column/LinkAdvancedOptions.vue

@ -1,6 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { useColumnCreateStoreOrThrow, useVModel } from '#imports' import { useColumnCreateStoreOrThrow, useVModel, computed, inject, MetaInj, ref, useI18n,useBase, storeToRefs, useMetas } from '#imports'
import {ModelTypes} from "nocodb-sdk"; import {isVirtualCol, ModelTypes, RelationTypes, UITypes} from "nocodb-sdk";
import type {ColumnType} from "nocodb-sdk";
const props = defineProps<{ const props = defineProps<{
value: any value: any
@ -10,6 +11,8 @@ const emit = defineEmits(['update:value'])
const { t } = useI18n() const { t } = useI18n()
const meta = inject(MetaInj, ref())
const vModel = useVModel(props, 'value', emit) const vModel = useVModel(props, 'value', emit)
const { validateInfos, setAdditionalValidations, onDataTypeChange } = useColumnCreateStoreOrThrow() const { validateInfos, setAdditionalValidations, onDataTypeChange } = useColumnCreateStoreOrThrow()
@ -17,80 +20,11 @@ const { validateInfos, setAdditionalValidations, onDataTypeChange } = useColumnC
const baseStore = useBase() const baseStore = useBase()
const { tables } = storeToRefs(baseStore) const { tables } = storeToRefs(baseStore)
setAdditionalValidations({ const { metas, getMeta } = useMetas()
'custom.colId': [
{
validator: (_, value: string) => { const isMm = computed(() => vModel.value.type === RelationTypes.MANY_TO_MANY)
return new Promise((resolve, reject) => {
if (value?.length > 59) {
return reject(t('msg.length59Required'))
}
resolve(true)
})
},
},
],
'custom.refTableId': [
{
validator: (_, value: string) => {
return new Promise((resolve, reject) => {
if (value?.length > 59) {
return reject(t('msg.length59Required'))
}
resolve(true)
})
},
},
],
'custom.refColId': [
{
validator: (_, value: string) => {
return new Promise((resolve, reject) => {
if (value?.length > 59) {
return reject(t('msg.length59Required'))
}
resolve(true)
})
},
},
],
'custom.juncTableId': [
{
validator: (_, value: string) => {
return new Promise((resolve, reject) => {
if (value?.length > 59) {
return reject(t('msg.length59Required'))
}
resolve(true)
})
},
},
],
'custom.juncColId': [
{
validator: (_, value: string) => {
return new Promise((resolve, reject) => {
if (value?.length > 59) {
return reject(t('msg.length59Required'))
}
resolve(true)
})
},
},
],
'custom.juncRefColId': [
{
validator: (_, value: string) => {
return new Promise((resolve, reject) => {
if (value?.length > 59) {
return reject(t('msg.length59Required'))
}
resolve(true)
})
},
},
],
})
// set default value // set default value
vModel.value.custom = { vModel.value.custom = {
@ -107,51 +41,90 @@ const refTables = computed(() =>{
}) })
const columns = $computed(() => { const columns = computed(() => {
if (!tables || !tables.length) { if (!meta.value?.columns) {
return [] return []
} }
return meta.value?.columns; return meta.value.columns;
}) })
const refTableColumns = $computed(() => { const refTableColumns = computed(() => {
if (!vModel.value.custom?.refTableId) { if (!vModel.value.custom?.ref_model_id || !metas.value[vModel.value.custom?.ref_model_id]) {
return [] return []
} }
return tables.find(table => table.id === vModel.value.custom?.refTableId)?.columns;
return metas.value[vModel.value.custom?.ref_model_id]?.columns.filter(
(c: ColumnType) => !isVirtualCol(c.uidt as UITypes),
)
}) })
const juncTableColumns = $computed(() => { const juncTableColumns = computed(() => {
if (!vModel.value.custom?.juncTableId) { if (!vModel.value.custom?.junc_model_id || !metas.value[vModel.value.custom?.junc_model_id]) {
return [] return []
} }
return tables.find(table => table.id === vModel.value.custom?.juncTableId)?.columns;
return metas.value[vModel.value.custom?.junc_model_id]?.columns.filter(
(c: ColumnType) => !isVirtualCol(c.uidt as UITypes),
)
}) })
const filterOption = (value: string, option: { key: string }) => option.key.toLowerCase().includes(value.toLowerCase()) const filterOption = (value: string, option: { key: string }) => option.key.toLowerCase().includes(value.toLowerCase())
const onModelIdChange =async (modelId:string) =>{
await getMeta(modelId)
await onDataTypeChange()
}
</script> </script>
<template> <template>
<div> <div v-if="validateInfos">
<div class="flex flex-row space-x-2"> <div class="flex flex-row space-x-2">
<a-form-item <a-form-item
class="flex w-full pb-2 mt-4 nc-ltar-child-table" class="flex w-full pb-2 mt-4 nc-ltar-child-table"
:label="$t('labels.childTable')" label="Column"
v-bind="validateInfos.childId" v-bind="validateInfos['custom.column_id']"
> >
<a-select <a-select
v-model:value="vModel.custom.refTableId" v-model:value="vModel.custom.column_id"
show-search show-search
:filter-option="filterOption" :filter-option="filterOption"
dropdown-class-name="nc-dropdown-ltar-child-table" dropdown-class-name="nc-dropdown-ltar-child-table"
@change="onDataTypeChange" @change="onDataTypeChange"
> >
<a-select-option v-for="table of refTables" :key="table.title" :value="table.id"> <a-select-option v-for="column of columns" :key="column.title" :value="column.id">
<div class="flex w-full items-center gap-2">
<div class="min-w-5 flex items-center justify-center">
<GeneralTableIcon :meta="column" class="text-gray-500" />
</div>
<NcTooltip class="flex-1 truncate" show-on-truncate-only>
<template #title>{{ column.title }}</template>
<span>{{ column.title }}</span>
</NcTooltip>
</div>
</a-select-option>
</a-select>
</a-form-item>
</div>
<div class="flex flex-row space-x-2">
<a-form-item
class="flex w-full pb-2 mt-4 nc-ltar-child-table"
label="Ref table"
v-bind="validateInfos['custom.ref_model_id']"
>
<a-select
v-model:value="vModel.custom.ref_model_id"
show-search
:filter-option="filterOption"
dropdown-class-name="nc-dropdown-ltar-child-table"
@change="onModelIdChange(vModel.custom.ref_model_id)"
>
<a-select-option v-for="table of tables" :key="table.title" :value="table.id">
<div class="flex w-full items-center gap-2"> <div class="flex w-full items-center gap-2">
<div class="min-w-5 flex items-center justify-center"> <div class="min-w-5 flex items-center justify-center">
<GeneralTableIcon :meta="table" class="text-gray-500" /> <GeneralTableIcon :meta="table" class="text-gray-500" />
@ -164,6 +137,123 @@ const filterOption = (value: string, option: { key: string }) => option.key.toLo
</a-select-option> </a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
<a-form-item
class="flex w-full pb-2 mt-4 nc-ltar-child-table"
label="Ref column"
v-bind="validateInfos['custom.ref_column_id']"
>
<a-select
v-model:value="vModel.custom.ref_column_id"
show-search
:filter-option="filterOption"
dropdown-class-name="nc-dropdown-ltar-child-table"
@change="onDataTypeChange"
>
<a-select-option v-for="column of refTableColumns" :key="column.title" :value="column.id">
<div class="flex w-full items-center gap-2">
<div class="min-w-5 flex items-center justify-center">
<GeneralTableIcon :meta="column" class="text-gray-500" />
</div>
<NcTooltip class="flex-1 truncate" show-on-truncate-only>
<template #title>{{ column.title }}</template>
<span>{{ column.title }}</span>
</NcTooltip>
</div>
</a-select-option>
</a-select>
</a-form-item>
</div> </div>
<template v-if="isMm">
<div class="flex flex-row space-x-2">
<a-form-item
class="flex w-full pb-2 mt-4 nc-ltar-child-table"
label="Junction table"
v-bind="validateInfos['custom.junc_model_id']"
>
<a-select
v-model:value="vModel.custom.junc_model_id"
show-search
:filter-option="filterOption"
dropdown-class-name="nc-dropdown-ltar-child-table"
@change="onModelIdChange(vModel.custom.ref_model_id)"
>
<a-select-option v-for="table of tables" :key="table.title" :value="table.id">
<div class="flex w-full items-center gap-2">
<div class="min-w-5 flex items-center justify-center">
<GeneralTableIcon :meta="table" class="text-gray-500" />
</div>
<NcTooltip class="flex-1 truncate" show-on-truncate-only>
<template #title>{{ table.title }}</template>
<span>{{ table.title }}</span>
</NcTooltip>
</div>
</a-select-option>
</a-select>
</a-form-item>
</div>
<div class="flex flex-row space-x-2">
<a-form-item
class="flex w-full pb-2 mt-4 nc-ltar-child-table"
label="Column in jn table"
v-bind="validateInfos['custom.junc_column_id']"
>
<a-select
v-model:value="vModel.custom.junc_column_id"
show-search
:filter-option="filterOption"
dropdown-class-name="nc-dropdown-ltar-child-table"
@change="onDataTypeChange"
>
<a-select-option v-for="column of juncTableColumns" :key="column.title" :value="column.id">
<div class="flex w-full items-center gap-2">
<div class="min-w-5 flex items-center justify-center">
<GeneralTableIcon :meta="column" class="text-gray-500" />
</div>
<NcTooltip class="flex-1 truncate" show-on-truncate-only>
<template #title>{{ column.title }}</template>
<span>{{ column.title }}</span>
</NcTooltip>
</div>
</a-select-option>
</a-select>
</a-form-item>
<a-form-item
class="flex w-full pb-2 mt-4 nc-ltar-child-table"
label="Ref column in jn table"
v-bind="validateInfos['custom.junc_ref_column_id']"
>
<a-select
v-model:value="vModel.custom.junc_ref_column_id"
show-search
:filter-option="filterOption"
dropdown-class-name="nc-dropdown-ltar-child-table"
@change="onDataTypeChange"
>
<a-select-option v-for="column of juncTableColumns" :key="column.title" :value="column.id">
<div class="flex w-full items-center gap-2">
<div class="min-w-5 flex items-center justify-center">
<GeneralTableIcon :meta="column" class="text-gray-500" />
</div>
<NcTooltip class="flex-1 truncate" show-on-truncate-only>
<template #title>{{ column.title }}</template>
<span>{{ column.title }}</span>
</NcTooltip>
</div>
</a-select-option>
</a-select>
</a-form-item>
</div>
</template>
</div> </div>
</template> </template>

53
packages/nc-gui/components/smartsheet/column/LinkedToAnotherRecordOptions.vue

@ -157,10 +157,53 @@ const handleUpdateRefTable = () => {
updateFieldName() updateFieldName()
}) })
} }
const oneToOneEnabled = ref(false)
const cusValidators = {
'custom.column_id': [
{ required: true, message: t('general.required') }
],
'custom.ref_model_id': [
{ required: true, message: t('general.required') }
],
'custom.ref_column_id': [
{ required: true, message: t('general.required') }
],
}
const cusJuncTableValidations = {
'custom.junc_model_id': [
{ required: true, message: t('general.required') }
],
'custom.junc_column_id': [
{ required: true, message: t('general.required') }
],
'custom.junc_ref_column_id': [
{ required: true, message: t('general.required') }
],
}
const onCustomSwitchToggle = () =>{
if(vModel.value?.is_custom_ltar)
setAdditionalValidations({
childId: [],
...cusValidators,
...(vModel.value.type === RelationTypes.MANY_TO_MANY ? cusJuncTableValidations : {})
})
else
setAdditionalValidations({
childId: [{ required: true, message: t('general.required') }],
})
}
</script> </script>
<template> <template>
<div class="w-full flex flex-col gap-4"> <div class="w-full flex flex-col mb-2 mt-4">
<div class="pb-2">
<a-switch v-model:checked="vModel.is_custom_ltar" size="small" name="Custom" @change="onCustomSwitchToggle"/> Custom
</div>
<div class="border-2 p-6">
<div class="flex flex-col gap-4"> <div class="flex flex-col gap-4">
<a-form-item :label="$t('labels.relationType')" v-bind="validateInfos.type" class="nc-ltar-relation-type"> <a-form-item :label="$t('labels.relationType')" v-bind="validateInfos.type" class="nc-ltar-relation-type">
<a-radio-group v-model:value="linkType" name="type" v-bind="validateInfos.type" :disabled="isEdit"> <a-radio-group v-model:value="linkType" name="type" v-bind="validateInfos.type" :disabled="isEdit">
@ -186,6 +229,13 @@ const handleUpdateRefTable = () => {
</a-form-item> </a-form-item>
<a-form-item class="flex w-full nc-ltar-child-table" v-bind="validateInfos.childId"> <a-form-item class="flex w-full nc-ltar-child-table" v-bind="validateInfos.childId">
<LazySmartsheetColumnLinkAdvancedOptions v-if="vModel.is_custom_ltar" v-model:value="vModel" class="mt-2" />
<template v-else>
<a-form-item
class="flex w-full pb-2 mt-4 nc-ltar-child-table"
:label="$t('labels.childTable')"
v-bind="validateInfos.childId"
>
<a-select <a-select
v-model:value="referenceTableChildId" v-model:value="referenceTableChildId"
show-search show-search
@ -211,6 +261,7 @@ const handleUpdateRefTable = () => {
</a-select-option> </a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
</template>
<div v-if="isEeUI" class="w-full flex-col"> <div v-if="isEeUI" class="w-full flex-col">
<div class="flex gap-2 items-center" :class="{ 'mb-2': limitRecToView }"> <div class="flex gap-2 items-center" :class="{ 'mb-2': limitRecToView }">

19
packages/nocodb/src/helpers/columnHelpers.ts

@ -43,6 +43,8 @@ export async function createHmAndBtColumn(
columnMeta = null, columnMeta = null,
isLinks = false, isLinks = false,
colExtra?: any, colExtra?: any,
parentColumn?: Column,
isCustom = false
) { ) {
// save bt column // save bt column
{ {
@ -60,7 +62,7 @@ export async function createHmAndBtColumn(
// db_type: // db_type:
fk_child_column_id: childColumn.id, fk_child_column_id: childColumn.id,
fk_parent_column_id: parent.primaryKey.id, fk_parent_column_id: parentColumn?.id || parent.primaryKey.id,
fk_related_model_id: parent.id, fk_related_model_id: parent.id,
virtual, virtual,
// if self referencing treat it as system field to hide from ui // if self referencing treat it as system field to hide from ui
@ -68,6 +70,10 @@ export async function createHmAndBtColumn(
fk_col_name: fkColName, fk_col_name: fkColName,
fk_index_name: fkColName, fk_index_name: fkColName,
...(type === 'bt' ? colExtra : {}), ...(type === 'bt' ? colExtra : {}),
meta: {
...(colExtra?.meta || {}),
custom: isCustom
}
}); });
} }
// save hm column // save hm column
@ -80,6 +86,7 @@ export async function createHmAndBtColumn(
...(columnMeta || {}), ...(columnMeta || {}),
plural: columnMeta?.plural || pluralize(child.title), plural: columnMeta?.plural || pluralize(child.title),
singular: columnMeta?.singular || singularize(child.title), singular: columnMeta?.singular || singularize(child.title),
custom: isCustom
}; };
await Column.insert(context, { await Column.insert(context, {
@ -89,7 +96,7 @@ export async function createHmAndBtColumn(
type: 'hm', type: 'hm',
fk_target_view_id: childView?.id, fk_target_view_id: childView?.id,
fk_child_column_id: childColumn.id, fk_child_column_id: childColumn.id,
fk_parent_column_id: parent.primaryKey.id, fk_parent_column_id: parentColumn?.id || parent.primaryKey.id,
fk_related_model_id: child.id, fk_related_model_id: child.id,
virtual, virtual,
system: isSystemCol, system: isSystemCol,
@ -128,6 +135,8 @@ export async function createOOColumn(
isSystemCol = false, isSystemCol = false,
columnMeta = null, columnMeta = null,
colExtra?: any, colExtra?: any,
parentColumn?: Column,
isCustom = false
) { ) {
// save bt column // save bt column
{ {
@ -144,7 +153,7 @@ export async function createOOColumn(
// Child View ID is given for relation from parent to child. not for child to parent // Child View ID is given for relation from parent to child. not for child to parent
fk_target_view_id: null, fk_target_view_id: null,
fk_child_column_id: childColumn.id, fk_child_column_id: childColumn.id,
fk_parent_column_id: parent.primaryKey.id, fk_parent_column_id: parentColumn?.id || parent.primaryKey.id,
fk_related_model_id: parent.id, fk_related_model_id: parent.id,
virtual, virtual,
// if self referencing treat it as system field to hide from ui // if self referencing treat it as system field to hide from ui
@ -157,6 +166,7 @@ export async function createOOColumn(
// one-to-one relation is combination of both hm and bt to identify table which have // one-to-one relation is combination of both hm and bt to identify table which have
// foreign key column(similar to bt) we are adding a boolean flag `bt` under meta // foreign key column(similar to bt) we are adding a boolean flag `bt` under meta
bt: true, bt: true,
custom: isCustom
}, },
}); });
} }
@ -176,6 +186,7 @@ export async function createOOColumn(
...(columnMeta || {}), ...(columnMeta || {}),
plural: columnMeta?.plural || pluralize(child.title), plural: columnMeta?.plural || pluralize(child.title),
singular: columnMeta?.singular || singularize(child.title), singular: columnMeta?.singular || singularize(child.title),
custom: isCustom
}; };
await Column.insert(context, { await Column.insert(context, {
@ -185,7 +196,7 @@ export async function createOOColumn(
type: 'oo', type: 'oo',
fk_target_view_id: childView?.id, fk_target_view_id: childView?.id,
fk_child_column_id: childColumn.id, fk_child_column_id: childColumn.id,
fk_parent_column_id: parent.primaryKey.id, fk_parent_column_id: parentColumn?.id || parent.primaryKey.id,
fk_related_model_id: child.id, fk_related_model_id: child.id,
virtual, virtual,
system: isSystemCol, system: isSystemCol,

144
packages/nocodb/src/services/columns.service.ts

@ -2178,6 +2178,7 @@ export class ColumnsService {
ncMeta, ncMeta,
); );
const parentTable = await parentColumn.getModel(context, ncMeta); const parentTable = await parentColumn.getModel(context, ncMeta);
const custom = column.meta?.custom;
switch (relationColOpt.type) { switch (relationColOpt.type) {
case 'bt': case 'bt':
@ -2192,6 +2193,7 @@ export class ColumnsService {
parentTable, parentTable,
sqlMgr, sqlMgr,
ncMeta, ncMeta,
custom,
}); });
} }
break; break;
@ -2206,6 +2208,7 @@ export class ColumnsService {
parentTable, parentTable,
sqlMgr, sqlMgr,
ncMeta, ncMeta,
custom,
}); });
} }
break; break;
@ -2224,6 +2227,7 @@ export class ColumnsService {
ncMeta, ncMeta,
); );
if (!custom) {
await this.deleteHmOrBtRelation( await this.deleteHmOrBtRelation(
context, context,
{ {
@ -2255,6 +2259,7 @@ export class ColumnsService {
}, },
true, true,
); );
}
const columnsInRelatedTable: Column[] = await relationColOpt const columnsInRelatedTable: Column[] = await relationColOpt
.getRelatedTable(context, ncMeta) .getRelatedTable(context, ncMeta)
.then((m) => m.getColumns(context, ncMeta)); .then((m) => m.getColumns(context, ncMeta));
@ -2287,6 +2292,7 @@ export class ColumnsService {
ncMeta, ncMeta,
); );
if (!custom) {
if (mmTable) { if (mmTable) {
// delete bt columns in m2m table // delete bt columns in m2m table
await mmTable.getColumns(context, ncMeta); await mmTable.getColumns(context, ncMeta);
@ -2348,6 +2354,7 @@ export class ColumnsService {
} }
} }
} }
}
break; break;
} }
} }
@ -2450,6 +2457,7 @@ export class ColumnsService {
sqlMgr, sqlMgr,
ncMeta = Noco.ncMeta, ncMeta = Noco.ncMeta,
virtual, virtual,
custom = false,
}: { }: {
relationColOpt: LinkToAnotherRecordColumn; relationColOpt: LinkToAnotherRecordColumn;
source: Source; source: Source;
@ -2460,10 +2468,12 @@ export class ColumnsService {
sqlMgr: SqlMgrv2; sqlMgr: SqlMgrv2;
ncMeta?: MetaService; ncMeta?: MetaService;
virtual?: boolean; virtual?: boolean;
custom?: boolean;
}, },
ignoreFkDelete = false, ignoreFkDelete = false,
) => { ) => {
if (childTable) { if (childTable) {
if (!custom) {
let foreignKeyName; let foreignKeyName;
// if relationColOpt is not provided, extract it from child table // if relationColOpt is not provided, extract it from child table
@ -2507,6 +2517,7 @@ export class ColumnsService {
} }
} }
} }
}
if (!relationColOpt) return; if (!relationColOpt) return;
const columnsInRelatedTable: Column[] = await relationColOpt const columnsInRelatedTable: Column[] = await relationColOpt
@ -2532,7 +2543,7 @@ export class ColumnsService {
// delete virtual columns // delete virtual columns
await Column.delete(context, relationColOpt.fk_column_id, ncMeta); await Column.delete(context, relationColOpt.fk_column_id, ncMeta);
if (!ignoreFkDelete) { if (!ignoreFkDelete && !custom) {
const cTable = await Model.getWithInfo( const cTable = await Model.getWithInfo(
context, context,
{ {
@ -2603,6 +2614,7 @@ export class ColumnsService {
sqlMgr, sqlMgr,
ncMeta = Noco.ncMeta, ncMeta = Noco.ncMeta,
virtual, virtual,
custom = false,
}: { }: {
relationColOpt: LinkToAnotherRecordColumn; relationColOpt: LinkToAnotherRecordColumn;
source: Source; source: Source;
@ -2613,10 +2625,12 @@ export class ColumnsService {
sqlMgr: SqlMgrv2; sqlMgr: SqlMgrv2;
ncMeta?: MetaService; ncMeta?: MetaService;
virtual?: boolean; virtual?: boolean;
custom?: boolean;
}, },
ignoreFkDelete = false, ignoreFkDelete = false,
) => { ) => {
if (childTable) { if (childTable) {
if (!custom) {
let foreignKeyName; let foreignKeyName;
// if relationColOpt is not provided, extract it from child table // if relationColOpt is not provided, extract it from child table
@ -2660,6 +2674,7 @@ export class ColumnsService {
} }
} }
} }
}
if (!relationColOpt) return; if (!relationColOpt) return;
const columnsInRelatedTable: Column[] = await relationColOpt const columnsInRelatedTable: Column[] = await relationColOpt
@ -2685,7 +2700,7 @@ export class ColumnsService {
// delete virtual columns // delete virtual columns
await Column.delete(context, relationColOpt.fk_column_id, ncMeta); await Column.delete(context, relationColOpt.fk_column_id, ncMeta);
if (!ignoreFkDelete) { if (!ignoreFkDelete && !custom) {
const cTable = await Model.getWithInfo( const cTable = await Model.getWithInfo(
context, context,
{ {
@ -2754,8 +2769,131 @@ export class ColumnsService {
base: Base; base: Base;
reuse?: ReusableParams; reuse?: ReusableParams;
colExtra?: any; colExtra?: any;
}, }) {
if ((param.column as any).is_custom_ltar) {
validateParams(['custom'], param.column as any);
validateParams(
['column_id', 'ref_model_id', 'ref_column_id'],
(param.column as any).custom,
);
const ltarCustomPRops: {
column_id: string;
ref_model_id: string;
ref_column_id: string;
junc_model_id: string;
junc_column_id: string;
junc_ref_column_id: string;
} = (param.column as any).custom;
const child = await Model.get(ltarCustomPRops.ref_model_id);
const parent = await Model.get(param.tableId);
const childColumn = await Column.get({
colId: ltarCustomPRops.ref_column_id,
});
const parentColumn = await Column.get({
colId: ltarCustomPRops.column_id,
});
if (
(param.column as LinkToAnotherColumnReqType).type === 'hm' ||
(param.column as LinkToAnotherColumnReqType).type === 'bt'
) { ) {
await createHmAndBtColumn(
child,
parent,
childColumn,
(param.column as LinkToAnotherColumnReqType).type as RelationTypes,
(param.column as LinkToAnotherColumnReqType).title,
null,
(param.column as LinkToAnotherColumnReqType).virtual,
null,
param.column['meta'],
true,
param.colExtra,
parentColumn,
true,
);
} else if ((param.column as LinkToAnotherColumnReqType).type === 'oo') {
await createOOColumn(
child,
parent,
childColumn,
(param.column as LinkToAnotherColumnReqType).type as RelationTypes,
(param.column as LinkToAnotherColumnReqType).title,
null,
(param.column as LinkToAnotherColumnReqType).virtual,
null,
param.column['meta'],
param.colExtra,
parentColumn,
true,
);
} else if ((param.column as LinkToAnotherColumnReqType).type === 'mm') {
await Column.insert({
title: getUniqueColumnAliasName(
await child.getColumns(),
pluralize(parent.title),
),
uidt: param.column.uidt,
type: 'mm',
// ref_db_alias
fk_model_id: child.id,
// db_type:
fk_child_column_id: childColumn.id,
fk_parent_column_id: parentColumn.id,
fk_mm_model_id: ltarCustomPRops.junc_model_id,
fk_mm_child_column_id: ltarCustomPRops.junc_ref_column_id,
fk_mm_parent_column_id: ltarCustomPRops.junc_column_id,
fk_related_model_id: parent.id,
virtual: (param.column as LinkToAnotherColumnReqType).virtual,
meta: {
plural: pluralize(parent.title),
singular: singularize(parent.title),
custom: true,
},
// if self referencing treat it as system field to hide from ui
system: parent.id === child.id,
});
await Column.insert({
title: getUniqueColumnAliasName(
await parent.getColumns(),
param.column.title ?? pluralize(child.title),
),
uidt: param.column.uidt,
type: 'mm',
fk_model_id: parent.id,
fk_mm_model_id: ltarCustomPRops.junc_model_id,
fk_mm_child_column_id: ltarCustomPRops.junc_column_id,
fk_mm_parent_column_id: ltarCustomPRops.junc_ref_column_id,
fk_child_column_id: parentColumn.id,
fk_parent_column_id: childColumn.id,
fk_related_model_id: child.id,
virtual: (param.column as LinkToAnotherColumnReqType).virtual,
meta: {
plural: param.column['meta']?.plural || pluralize(child.title),
singular:
param.column['meta']?.singular || singularize(child.title),
custom: true,
},
// column_order and view_id if provided
...param.colExtra,
});
}
return;
}
validateParams(['parentId', 'childId', 'type'], param.column); validateParams(['parentId', 'childId', 'type'], param.column);
const reuse = param.reuse ?? {}; const reuse = param.reuse ?? {};

Loading…
Cancel
Save