Browse Source

Merge pull request #8399 from nocodb/nc-one-to-one

Nc one to one
pull/8402/head
Pranav C 7 months ago committed by GitHub
parent
commit
d54b4e0381
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 6
      packages/nc-gui/components/smartsheet/column/LinkedToAnotherRecordOptions.vue
  2. 21
      packages/nc-gui/components/smartsheet/header/VirtualCell.vue
  3. 4
      packages/nc-gui/components/virtual-cell/OneToOne.vue
  4. 2
      packages/nc-gui/components/virtual-cell/components/UnLinkedItems.vue
  5. 1
      packages/nc-gui/lang/en.json
  6. 9
      packages/nocodb/src/db/BaseModelSqlv2.ts
  7. 13
      packages/nocodb/src/services/columns.service.ts
  8. 2
      tests/playwright/pages/Dashboard/Details/FieldsPage.ts
  9. 2
      tests/playwright/pages/Dashboard/Grid/Column/index.ts

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

@ -53,8 +53,6 @@ const refTables = computed(() => {
const filterOption = (value: string, option: { key: string }) => option.key.toLowerCase().includes(value.toLowerCase())
const isLinks = computed(() => vModel.value.uidt === UITypes.Links && vModel.value.type !== RelationTypes.ONE_TO_ONE)
const oneToOneEnabled = ref(false)
</script>
<template>
@ -62,9 +60,9 @@ const oneToOneEnabled = ref(false)
<div class="border-2 p-6">
<a-form-item v-bind="validateInfos.type" class="nc-ltar-relation-type">
<a-radio-group v-model:value="vModel.type" name="type" v-bind="validateInfos.type" class="!flex flex-col gap-2">
<a-radio value="hm" @dblclick="oneToOneEnabled = !oneToOneEnabled">{{ $t('title.hasMany') }}</a-radio>
<a-radio value="oo">{{ $t('title.oneToOne') }}</a-radio>
<a-radio value="hm">{{ $t('title.hasMany') }}</a-radio>
<a-radio value="mm">{{ $t('title.manyToMany') }}</a-radio>
<a-radio v-if="oneToOneEnabled" value="oo">{{ $t('title.oneToOne') }}</a-radio>
</a-radio-group>
</a-form-item>

21
packages/nc-gui/components/smartsheet/header/VirtualCell.vue

@ -1,5 +1,13 @@
<script setup lang="ts">
import type { ColumnReqType, ColumnType, FormulaType, LinkToAnotherRecordType, LookupType, RollupType } from 'nocodb-sdk'
import {
type ColumnReqType,
type ColumnType,
type FormulaType,
type LinkToAnotherRecordType,
type LookupType,
type RollupType,
isLinksOrLTAR,
} from 'nocodb-sdk'
import { RelationTypes, UITypes, UITypesName, substituteColumnIdWithAliasInFormula } from 'nocodb-sdk'
import {
ColumnInj,
@ -12,6 +20,7 @@ import {
isHm,
isLookup,
isMm,
isOo,
isRollup,
isVirtualColRequired,
provide,
@ -57,7 +66,7 @@ const colOptions = computed(() => column.value?.colOptions)
const tableTile = computed(() => meta?.value?.title)
const relationColumnOptions = computed<LinkToAnotherRecordType | null>(() => {
if (isMm(column.value) || isHm(column.value) || isBt(column.value)) {
if (isLinksOrLTAR(column.value)) {
return column.value?.colOptions as LinkToAnotherRecordType
} else if ((column?.value?.colOptions as LookupType | RollupType)?.fk_relation_column_id) {
return meta?.value?.columns?.find(
@ -101,6 +110,8 @@ const tooltipMsg = computed(() => {
return `'${tableTile.value}' & '${relatedTableTitle.value}' ${t('labels.manyToMany')}`
} else if (isBt(column.value)) {
return `'${column?.value?.title}' ${t('labels.belongsTo')} '${relatedTableTitle.value}'`
} else if (isOo(column.value)) {
return `'${tableTile.value}' & '${relatedTableTitle.value}' ${t('labels.oneToOne')}`
} else if (isLookup(column.value)) {
return `'${childColumn.value.title}' from '${relatedTableTitle.value}' (${childColumn.value.uidt})`
} else if (isFormula(column.value)) {
@ -116,6 +127,10 @@ const tooltipMsg = computed(() => {
return column?.value?.title || ''
})
const showTooltipAlways = computed(() => {
return isLinksOrLTAR(column.value) || isFormula(column.value) || isRollup(column.value) || isLookup(column.value)
})
const columnOrder = ref<Pick<ColumnReqType, 'column_order'> | null>(null)
const columnTypeName = computed(() => {
@ -172,7 +187,7 @@ const openDropDown = (e: Event) => {
</NcTooltip>
<LazySmartsheetHeaderVirtualCellIcon v-else />
</template>
<NcTooltip placement="bottom" class="truncate name pl-1" show-on-truncate-only>
<NcTooltip placement="bottom" class="truncate name pl-1" :show-on-truncate-only="!showTooltipAlways">
<template #title>
{{ tooltipMsg }}
</template>

4
packages/nc-gui/components/virtual-cell/OneToOne.vue

@ -55,7 +55,9 @@ const value = computed(() => {
if (cellValue?.value) {
return cellValue?.value
} else if (isNew.value) {
return state?.value?.[column?.value.title as string]
const columnTitle = column?.value.title as string
const columnValue = state?.value?.[columnTitle]
return Array.isArray(columnValue) ? columnValue[0] : columnValue
}
return null
})

2
packages/nc-gui/components/virtual-cell/components/UnLinkedItems.vue

@ -142,7 +142,7 @@ const newRowState = computed(() => {
const relatedTableColOpt = colInRelatedTable?.colOptions as LinkToAnotherRecordType
if (!relatedTableColOpt) return {}
if (relatedTableColOpt.type === RelationTypes.BELONGS_TO) {
if (relatedTableColOpt.type === RelationTypes.BELONGS_TO || relatedTableColOpt.type === RelationTypes.ONE_TO_ONE) {
return {
[colInRelatedTable.title as string]: row?.value?.row,
}

1
packages/nc-gui/lang/en.json

@ -714,6 +714,7 @@
"hasMany": "has many",
"belongsTo": "belongs to",
"manyToMany": "have many to many relation",
"oneToOne": "have one to one relation",
"extraConnectionParameters": "Extra connection parameters",
"commentsOnly": "Comments only",
"documentation": "Documentation",

9
packages/nocodb/src/db/BaseModelSqlv2.ts

@ -3314,16 +3314,17 @@ class BaseModelSqlv2 {
await childModel.getColumns();
if (isBt) {
// if array then extract value from first element
const colVal = Array.isArray(nestedData)
? nestedData[0]?.[childModel.primaryKey.title]
: nestedData[childModel.primaryKey.title];
// todo: unlink the ref record
preInsertOps.push(async () => {
return this.dbDriver(this.getTnPath(childModel.table_name))
.update({
[childCol.column_name]: null,
})
.where(
childCol.column_name,
nestedData[childModel.primaryKey.title],
)
.where(childCol.column_name, colVal)
.toQuery();
});

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

@ -5,6 +5,7 @@ import {
isCreatedOrLastModifiedTimeCol,
isLinksOrLTAR,
isVirtualCol,
RelationTypes,
substituteColumnAliasWithIdInFormula,
substituteColumnIdWithAliasInFormula,
UITypes,
@ -18,7 +19,6 @@ import type {
ColumnReqType,
LinkToAnotherColumnReqType,
LinkToAnotherRecordType,
RelationTypes,
UserType,
} from 'nocodb-sdk';
import type CustomKnex from '~/db/CustomKnex';
@ -2417,9 +2417,9 @@ export class ColumnsService {
};
await sqlMgr.sqlOpPlus(source, 'tableUpdate', tableUpdateBody);
// delete foreign key column
await Column.delete(childColumn.id, ncMeta);
}
// delete foreign key column
await Column.delete(childColumn.id, ncMeta);
};
deleteOoRelation = async (
@ -2492,7 +2492,7 @@ export class ColumnsService {
const columnsInRelatedTable: Column[] = await relationColOpt
.getRelatedTable(ncMeta)
.then((m) => m.getColumns(ncMeta));
const relType = relationColOpt.type === 'bt' ? 'hm' : 'bt';
const relType = RelationTypes.ONE_TO_ONE;
for (const c of columnsInRelatedTable) {
if (c.uidt !== UITypes.LinkToAnotherRecord) continue;
const colOpt = await c.getColOptions<LinkToAnotherRecordColumn>(ncMeta);
@ -2562,9 +2562,10 @@ export class ColumnsService {
};
await sqlMgr.sqlOpPlus(source, 'tableUpdate', tableUpdateBody);
// delete foreign key column
await Column.delete(childColumn.id, ncMeta);
}
// delete foreign key column
await Column.delete(childColumn.id, ncMeta);
};
async createLTARColumn(param: {

2
tests/playwright/pages/Dashboard/Details/FieldsPage.ts

@ -186,7 +186,7 @@ export class FieldsPage extends BasePage {
case 'Links':
await this.addOrEditColumn
.locator('.nc-ltar-relation-type >> .ant-radio')
.nth(relationType === 'Has Many' ? 0 : 1)
.nth(relationType === 'Has Many' ? 1 : 2)
.click();
await this.addOrEditColumn.locator('.ant-select-single').nth(1).click();
await this.rootPage.locator(`.nc-ltar-child-table >> input[type="search"]`).fill(childTable);

2
tests/playwright/pages/Dashboard/Grid/Column/index.ts

@ -173,7 +173,7 @@ export class ColumnPageObject extends BasePage {
case 'Links':
await this.get()
.locator('.nc-ltar-relation-type >> .ant-radio')
.nth(relationType === 'Has Many' ? 0 : 1)
.nth(relationType === 'Has Many' ? 1 : 2)
.click();
await this.get().locator('.ant-select-single').nth(1).click();
await this.rootPage.locator(`.nc-ltar-child-table >> input[type="search"]`).fill(childTable);

Loading…
Cancel
Save