Merge pull request #12012 from nocodb/develop

This commit is contained in:
github-actions[bot]
2025-07-31 10:07:34 +00:00
committed by GitHub
15 changed files with 113 additions and 58 deletions

View File

@@ -75,7 +75,7 @@ const saveValue = (targetValue: string) => {
vModel.value = value
}
let savingHandle: any
const onInputKeyUp = (e: KeyboardEvent) => {
const onInputKeyUp = (e: KeyboardEvent, debounce = true) => {
const target: HTMLInputElement = e.target as HTMLInputElement
if (target) {
// mac's double space insert period
@@ -87,9 +87,13 @@ const onInputKeyUp = (e: KeyboardEvent) => {
if (savingHandle) {
clearTimeout(savingHandle)
}
savingHandle = setTimeout(() => {
if (!debounce) {
saveValue(target.value)
}, 100)
} else {
savingHandle = setTimeout(() => {
saveValue(target.value)
}, 100)
}
}
}
// Handle the arrow keys as its default behavior is to increment/decrement the value
@@ -132,6 +136,7 @@ const onInputKeyDown = (e: KeyboardEvent) => {
e.stopPropagation()
return
}
pasteText(target, e.key)
e.preventDefault()
e.stopPropagation()
@@ -153,6 +158,7 @@ const onInputPaste = (e: ClipboardEvent) => {
e.stopPropagation()
pasteText(target, value)
}
const onInputBlur = (e: FocusEvent) => {
emits('blur', e)
if (e.target) {
@@ -194,6 +200,7 @@ onMounted(() => {
style="letter-spacing: 0.06rem; height: 24px !important"
:style="inputStyle"
:disabled="disabled"
@keydown.enter.exact="onInputKeyUp($event, false)"
@keydown.left.stop
@keydown.right.stop
@keydown.delete.stop

View File

@@ -86,9 +86,9 @@ onMounted(() => {
<template>
<CellPercentProgressBar
v-if="parseProp(col!.meta).is_progress && (isForm)"
v-if="parseProp(col!.meta).is_progress && (isForm || isExpandedFormOpen)"
:style="{
...(isForm && { 'min-height': '22px', 'height': '22px' }),
...((isForm || isExpandedFormOpen) && { 'min-height': '22px', 'height': '22px' }),
}"
:is-show-number="true"
:percentage="vModelNumber"

View File

@@ -35,7 +35,7 @@ const slotHasChildren = (name?: string) => {
<span
style="mix-blend-mode: difference; color: #ffffff"
:style="{
'margin-left': `${-Math.min(percentage, 50)}%`,
'margin-left': `${-Math.min(cPercentage, 50)}%`,
}"
>
{{ `${percentage}%` }}
@@ -45,7 +45,7 @@ const slotHasChildren = (name?: string) => {
<span
style="mix-blend-mode: overlay; color: #ffffff"
:style="{
'margin-left': `${-Math.min(percentage, 50)}%`,
'margin-left': `${-Math.min(cPercentage, 50)}%`,
}"
>
{{ `${percentage}%` }}

View File

@@ -220,9 +220,8 @@ const showReadonlyField = computed(() => {
case 'percent': {
return !(
!readOnly.value &&
editEnabled.value &&
(isExpandedFormOpen.value ? localEditEnabled.value || !parseProp(column.value?.meta).is_progress : true)
(!readOnly.value && editEnabled.value) ||
(isExpandedFormOpen.value && (localEditEnabled.value || parseProp(column.value?.meta).is_progress))
)
}

View File

@@ -169,6 +169,8 @@
"upgradeToUseDashboardsSubtitle": "Upgrade to the {plan} plan to use dashboards to visualize your data.",
"upgradeToUsePrivateBases": "Upgrade to unlock private bases",
"upgradeToUsePrivateBasesSubtitle": "Private bases are available on the {plan} plan. Upgrade now to start using them.",
"upgradeLicenseToUsePrivateBases": "Upgrade license to unlock private bases",
"upgradeLicenseToUsePrivateBasesSubtitle": "Private bases are not available in Enterprise Starter license. Upgrade license key to start using them.",
"upgradeToAddMoreAttachmentsInCellSubtitle": "You can only upload at most {limit} {filePlural} to this cell. Upgrade to the {plan} plan to add more files."
},
"general": {
@@ -591,6 +593,7 @@
"Team": "Team",
"Plus": "Plus",
"Business": "Business",
"EnterpriseStarter": "Enterprise Starter",
"Enterprise": "Enterprise"
},
"currentPlan": {

View File

@@ -92,7 +92,7 @@
"marked": "^4.3.0",
"monaco-editor": "^0.52.2",
"monaco-sql-languages": "^0.11.0",
"nocodb-sdk": "0.264.1",
"nocodb-sdk": "workspace:^",
"papaparse": "^5.5.2",
"parse-github-url": "^1.0.3",
"pdfobject": "^2.3.0",

View File

@@ -15,6 +15,7 @@ export interface DashboardType {
password?: string;
fk_custom_url_id?: string;
uuid?: string;
}
export enum WidgetTypes {

View File

@@ -57,11 +57,15 @@ export enum PlanFeatureTypes {
FEATURE_PRIVATE_BASES = 'feature_private_bases',
}
// todo: separate as a new enum
export enum PlanTitles {
FREE = 'Free',
PLUS = 'Plus',
BUSINESS = 'Business',
ENTERPRISE = 'Enterprise',
// on-prem
ENTERPRISE_STARTER = 'EnterpriseStarter',
}
export enum PlanPriceLookupKeys {

View File

@@ -124,7 +124,7 @@
"mysql2": "^3.14.1",
"nanoid": "^3.3.8",
"nc-lib-gui": "0.264.1",
"nocodb-sdk": "0.264.1",
"nocodb-sdk": "workspace:^",
"nodemailer": "^6.10.0",
"object-hash": "^3.0.0",
"object-sizeof": "^2.6.5",

View File

@@ -52,6 +52,7 @@ export default class Noco {
public readonly metaMgr: any;
public readonly metaMgrv2: any;
public env: string;
protected static _nestApp: INestApplication;
protected config: any;
protected requestContext: any;
@@ -89,6 +90,10 @@ export default class Noco {
return this._ncMeta;
}
public static get nestApp() {
return this._nestApp;
}
public static get ncAudit(): AuditService {
return this._ncAudit ?? this._ncMeta;
}
@@ -121,6 +126,7 @@ export default class Noco {
bufferLogs: true,
bodyParser: false,
});
Noco._nestApp = nestApp;
this.initCustomLogger(nestApp);
NcDebug.log('Custom logger initialized');
nestApp.flushLogs();

View File

@@ -1,4 +1,4 @@
import type { NcRequest } from 'nocodb-sdk';
import { NcApiVersion, type NcRequest } from 'nocodb-sdk';
import type { IBaseModelSqlV2 } from '~/db/IBaseModelSqlV2';
import { type AttachmentUrlUploadJobData, JobTypes } from '~/interface/Jobs';
import { EMIT_EVENT } from '~/constants';
@@ -22,6 +22,10 @@ export class AttachmentUrlUploadPreparator {
const postInsertOps: ((rowId: any) => Promise<string>)[] = [];
const preInsertOps: (() => Promise<string>)[] = [];
const postInsertAuditOps: ((rowId: any) => Promise<void>)[] = [];
// return early if not v3
if (baseModel.context.api_version !== NcApiVersion.V3) {
return { postInsertOps, preInsertOps, postInsertAuditOps };
}
for (const col of attachmentCols) {
let attachmentData: { id?: string; url: string }[];
try {
@@ -40,24 +44,27 @@ export class AttachmentUrlUploadPreparator {
} catch {
continue;
}
postInsertOps.push(async (recordId) => {
Noco.eventEmitter.emit(EMIT_EVENT.HANDLE_ATTACHMENT_URL_UPLOAD, {
jobName: JobTypes.AttachmentUrlUpload,
context: baseModel.context,
modelId: baseModel.model.id,
column: col,
recordId,
user: baseModel.context.user,
attachments: attachmentData,
req,
} as AttachmentUrlUploadJobData);
return '';
});
const columnKeyName = dataWrapper(data).getColumnKeyName(col);
// remove temp_ ids so it doesn't get recorded in audit
data[columnKeyName] = JSON.stringify(
attachmentData.filter((dt) => !dt.id?.startsWith('temp_')),
);
// only process when temp id exists
if (attachmentData.some((attr) => attr.id?.startsWith('temp_'))) {
postInsertOps.push(async (recordId) => {
Noco.eventEmitter.emit(EMIT_EVENT.HANDLE_ATTACHMENT_URL_UPLOAD, {
jobName: JobTypes.AttachmentUrlUpload,
context: baseModel.context,
modelId: baseModel.model.id,
column: col,
recordId,
user: baseModel.context.user,
attachments: attachmentData,
req,
} as AttachmentUrlUploadJobData);
return '';
});
const columnKeyName = dataWrapper(data).getColumnKeyName(col);
// remove temp_ ids so it doesn't get recorded in audit
data[columnKeyName] = JSON.stringify(
attachmentData.filter((dt) => !dt.id?.startsWith('temp_')),
);
}
}
return { postInsertOps, preInsertOps, postInsertAuditOps };
}

View File

@@ -3,10 +3,6 @@
!!! Do not edit this file manually !!!
*/
import type { IntegrationEntry } from '@noco-local-integrations/core';
export default [
] as IntegrationEntry[];
export default [] as IntegrationEntry[];

View File

@@ -794,6 +794,33 @@ export default class Column<T = any> implements ColumnType {
if (!col) {
return;
}
// If the column is one of CreatedBy, LastModifiedBy, CreatedAt, or LastModifiedAt
// and it is a system column, then delete its alias columns as well.
// This deletion is only performed through meta-sync because system columns
// cannot be deleted via API calls.
if (
(
[
UITypes.CreatedTime,
UITypes.LastModifiedTime,
UITypes.LastModifiedBy,
UITypes.CreatedBy,
] as UITypes[]
).includes(col.uidt) &&
col.system
) {
const aliasCols = await ncMeta.metaList2(
context.workspace_id,
context.base_id,
MetaTable.COLUMNS,
{
condition: { uidt: col.uidt, system: false },
},
);
for (const aliasCol of aliasCols) {
await Column.delete(context, aliasCol.id, ncMeta);
}
}
// todo: or instead of delete reset related foreign key value to null and handle in BaseModel

View File

@@ -1,11 +1,13 @@
import { Injectable } from '@nestjs/common';
import {
AppEvents,
ClientType,
isAIPromptCol,
isLinksOrLTAR,
isVirtualCol,
ModelTypes,
RelationTypes,
SqlUiFactory,
UITypes,
} from 'nocodb-sdk';
import { pluralize, singularize } from 'inflection';
@@ -276,7 +278,7 @@ export class MetaDiffsService {
}
for (const column of oldMeta.columns) {
if (
[
(<UITypes[]>[
UITypes.LinkToAnotherRecord,
UITypes.Links,
UITypes.Rollup,
@@ -285,8 +287,16 @@ export class MetaDiffsService {
UITypes.QrCode,
UITypes.Barcode,
UITypes.Button,
].includes(column.uidt) ||
isAIPromptCol(column)
]).includes(column.uidt) ||
isAIPromptCol(column) ||
// skip alias columns of CreatedTime, LastModifiedTime, CreatedBy, LastModifiedBy
((<UITypes[]>[
UITypes.CreatedTime,
UITypes.LastModifiedTime,
UITypes.LastModifiedBy,
UITypes.CreatedBy,
]).includes(column.uidt) &&
!column.system)
) {
if (isLinksOrLTAR(column.uidt)) {
virtualRelationColumns.push(column);
@@ -703,6 +713,7 @@ export class MetaDiffsService {
// @ts-ignore
const sqlClient = await NcConnectionMgrv2.getSqlClient(source);
const sqlUi = SqlUiFactory.create({ client: source.type ?? ClientType.PG });
const changes = await this.getMetaDiff(context, sqlClient, base, source);
/* Get all relations */
@@ -831,7 +842,15 @@ export class MetaDiffsService {
{ client: source.type },
{},
);
column.uidt = metaFact.getUIDataType(column);
// check if new type is compatible with old uidt
const allowedDatatypes = sqlUi.getDataTypeListForUiType(column);
// if UIDT not compatible with new type then change uidt
if (!allowedDatatypes?.includes(column.dt)) {
column.uidt = metaFact.getUIDataType(column);
}
column.title = change.column.title;
await Column.update(context, change.column.id, column);
}

22
pnpm-lock.yaml generated
View File

@@ -227,8 +227,8 @@ importers:
specifier: ^0.11.0
version: 0.11.0(antlr4ng-cli@1.0.7)
nocodb-sdk:
specifier: 0.264.1
version: 0.264.1(debug@4.4.1)
specifier: workspace:^
version: link:../nocodb-sdk
papaparse:
specifier: ^5.5.2
version: 5.5.3
@@ -835,8 +835,8 @@ importers:
specifier: 0.264.1
version: 0.264.1
nocodb-sdk:
specifier: 0.264.1
version: 0.264.1(debug@4.4.1)
specifier: workspace:^
version: link:../nocodb-sdk
nodemailer:
specifier: ^6.10.0
version: 6.10.1
@@ -11097,10 +11097,6 @@ packages:
resolution: {integrity: sha512-67n1OfusL/ON57fwFJ6ZurSJa/msYVQmqlz9rCel2HJYj4Zeb8v9TcmRdEW+PV2i9Fm2358umSvzZukhw/E8DA==}
engines: {node: '>=18.20.0 <20 || >=20.12.1'}
nocodb-sdk@0.264.1:
resolution: {integrity: sha512-zaYoSuctL1jr/uqwsDJIml1VsDEaak8qriTtk0jlLoc0bXU5IPUO+IaQpYWe9uKGNT1nujvQezgnmK4kru7xww==}
engines: {node: '>=18'}
node-abi@3.75.0:
resolution: {integrity: sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==}
engines: {node: '>=10'}
@@ -27276,16 +27272,6 @@ snapshots:
json-stringify-safe: 5.0.1
propagate: 2.0.1
nocodb-sdk@0.264.1(debug@4.4.1):
dependencies:
axios: 1.9.0(debug@4.4.1)
chevrotain: 10.5.0
dayjs: 1.11.13
jsep: 1.4.0
validator: 13.15.15
transitivePeerDependencies:
- debug
node-abi@3.75.0:
dependencies:
semver: 7.7.2