Skip to content

Commit 0d82b7b

Browse files
tea-artistteable-bot
andauthored
[sync] fix(link-field): add bottom padding to filter records container (#2432)
Synced from teableio/teable-ee@5e99422 Co-authored-by: teable-bot <bot@teable.io>
1 parent d24c705 commit 0d82b7b

File tree

206 files changed

+9732
-2658
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

206 files changed

+9732
-2658
lines changed

apps/nestjs-backend/package.json

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,13 @@
8585
"@types/passport-openidconnect": "0.1.3",
8686
"@types/pause": "0.1.3",
8787
"@types/sharedb": "3.3.10",
88+
"@types/sockjs": "0.3.36",
89+
"@types/sockjs-client": "1.5.4",
90+
"sockjs-client": "1.6.1",
8891
"@types/stream-json": "1.7.8",
8992
"@types/through2": "2.0.41",
9093
"@types/unzipper": "0.10.11",
91-
"@types/ws": "8.5.10",
92-
"@vitest/coverage-v8": "2.1.5",
94+
"@vitest/coverage-v8": "4.0.17",
9395
"copy-webpack-plugin": "12.0.2",
9496
"cross-env": "7.0.3",
9597
"dotenv-flow": "4.1.0",
@@ -113,22 +115,22 @@
113115
"typescript": "5.4.3",
114116
"unplugin-swc": "1.4.4",
115117
"vite-tsconfig-paths": "4.3.2",
116-
"vitest": "2.1.5",
118+
"vitest": "4.0.17",
117119
"vitest-mock-extended": "2.0.2",
118120
"webpack": "5.91.0"
119121
},
120122
"dependencies": {
121-
"@ai-sdk/amazon-bedrock": "4.0.0-beta.97",
122-
"@ai-sdk/anthropic": "3.0.0-beta.87",
123-
"@ai-sdk/azure": "3.0.0-beta.102",
124-
"@ai-sdk/cohere": "3.0.0-beta.52",
125-
"@ai-sdk/deepseek": "2.0.0-beta.54",
126-
"@ai-sdk/google": "3.0.0-beta.77",
127-
"@ai-sdk/mistral": "3.0.0-beta.53",
128-
"@ai-sdk/openai": "3.0.0-beta.100",
129-
"@ai-sdk/openai-compatible": "2.0.0-beta.52",
130-
"@ai-sdk/togetherai": "2.0.0-beta.53",
131-
"@ai-sdk/xai": "3.0.0-beta.60",
123+
"@ai-sdk/amazon-bedrock": "4.0.9",
124+
"@ai-sdk/anthropic": "3.0.7",
125+
"@ai-sdk/azure": "3.0.7",
126+
"@ai-sdk/cohere": "3.0.4",
127+
"@ai-sdk/deepseek": "2.0.4",
128+
"@ai-sdk/google": "3.0.5",
129+
"@ai-sdk/mistral": "3.0.5",
130+
"@ai-sdk/openai": "3.0.7",
131+
"@ai-sdk/openai-compatible": "2.0.4",
132+
"@ai-sdk/togetherai": "2.0.4",
133+
"@ai-sdk/xai": "3.0.10",
132134
"@aws-sdk/client-s3": "3.609.0",
133135
"@aws-sdk/lib-storage": "3.609.0",
134136
"@aws-sdk/s3-request-presigner": "3.609.0",
@@ -170,9 +172,9 @@
170172
"@teable/core": "workspace:^",
171173
"@teable/db-main-prisma": "workspace:^",
172174
"@teable/openapi": "workspace:^",
173-
"@teamwork/websocket-json-stream": "2.0.0",
175+
"@an-epiphany/websocket-json-stream": "1.2.0",
174176
"@valibot/to-json-schema": "1.3.0",
175-
"ai": "6.0.0-beta.156",
177+
"ai": "6.0.14",
176178
"ajv": "8.12.0",
177179
"archiver": "7.0.1",
178180
"axios": "1.7.7",
@@ -234,13 +236,13 @@
234236
"reflect-metadata": "0.2.1",
235237
"rxjs": "7.8.1",
236238
"sharedb": "4.1.2",
239+
"sockjs": "0.3.24",
237240
"sharp": "0.33.3",
238241
"stream-json": "1.9.1",
239242
"through2": "4.0.2",
240243
"transliteration": "2.3.5",
241244
"ts-pattern": "5.0.8",
242245
"unzipper": "0.12.3",
243-
"ws": "8.18.0",
244246
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz",
245247
"zod": "4.1.8",
246248
"zod-validation-error": "4.0.2"

apps/nestjs-backend/src/app.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import { PluginModule } from './features/plugin/plugin.module';
3636
import { PluginContextMenuModule } from './features/plugin-context-menu/plugin-context-menu.module';
3737
import { PluginPanelModule } from './features/plugin-panel/plugin-panel.module';
3838
import { SelectionModule } from './features/selection/selection.module';
39+
import { CanaryModule } from './features/canary';
3940
import { AdminOpenApiModule } from './features/setting/open-api/admin-open-api.module';
4041
import { SettingOpenApiModule } from './features/setting/open-api/setting-open-api.module';
4142
import { ShareModule } from './features/share/share.module';
@@ -81,6 +82,7 @@ export const appModules = {
8182
ExportOpenApiModule,
8283
PinModule,
8384
AdminOpenApiModule,
85+
CanaryModule,
8486
SettingOpenApiModule,
8587
OAuthModule,
8688
TrashModule,

apps/nestjs-backend/src/bootstrap.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import type { INestApplication } from '@nestjs/common';
44
import { ValidationPipe } from '@nestjs/common';
55
import { ConfigService } from '@nestjs/config';
66
import { NestFactory } from '@nestjs/core';
7-
import { WsAdapter } from '@nestjs/platform-ws';
87
import { json, urlencoded } from 'express';
98
import helmet from 'helmet';
109
import isPortReachable from 'is-port-reachable';
@@ -16,13 +15,9 @@ import { GlobalExceptionFilter } from './filter/global-exception.filter';
1615
import { setupSwagger } from './swagger';
1716
import otelSDK from './tracing';
1817

19-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
20-
declare const module: any;
21-
2218
const host = 'localhost';
2319

2420
export async function setUpAppMiddleware(app: INestApplication, configService: ConfigService) {
25-
app.useWebSocketAdapter(new WsAdapter(app));
2621
app.useGlobalFilters(new GlobalExceptionFilter(configService));
2722
app.useGlobalPipes(
2823
new ValidationPipe({ transform: true, stopAtFirstError: true, forbidUnknownValues: false })
@@ -51,11 +46,6 @@ export async function bootstrap() {
5146
const app = await NestFactory.create(AppModule, { bufferLogs: true });
5247
const configService = app.get(ConfigService);
5348

54-
if (module.hot) {
55-
module.hot.accept();
56-
module.hot.dispose(() => app.close());
57-
}
58-
5949
const logger = app.get(Logger);
6050
app.useLogger(logger);
6151
app.flushLogs();

apps/nestjs-backend/src/db-provider/filter-query/cell-value-filter.abstract.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ export abstract class AbstractCellValueFilter implements ICellValueFilterInterfa
387387

388388
const { mode, numberOfDays, exactDate } = filterValueByDate;
389389
const {
390-
formatting: { timeZone, date: dateFormat },
390+
formatting: { timeZone, date: dateFormat, time: timeFormat },
391391
} = dateFieldOptions;
392392

393393
const dateUtil = new DateUtil(timeZone);
@@ -435,6 +435,12 @@ export abstract class AbstractCellValueFilter implements ICellValueFilterInterfa
435435

436436
const parsedDate = dateUtil.date(exactDate);
437437

438+
// When timeFormat is set (not 'None'), preserve the exact time precision
439+
// This fixes the bug where minute-level filtering doesn't work
440+
if (timeFormat && timeFormat !== 'None') {
441+
return [parsedDate, parsedDate];
442+
}
443+
438444
switch (dateFormat) {
439445
case DateFormattingPreset.Y:
440446
return [parsedDate.startOf('year'), parsedDate.endOf('year')];

apps/nestjs-backend/src/db-provider/filter-query/postgres/cell-value-filter/single-value/string-cell-value-filter.adapter.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ export class StringCellValueFilterAdapter extends CellValueFilterPostgres {
1818
): Knex.QueryBuilder {
1919
if (isFieldReferenceValue(value)) {
2020
const ref = this.resolveFieldReference(value);
21-
builderClient.whereRaw(`LOWER(${this.tableColumnRef}) = LOWER(${ref})`);
21+
builderClient.whereRaw(`${this.tableColumnRef} = ${ref}`);
2222
return builderClient;
2323
}
2424
const parseValue = this.field.cellValueType === CellValueType.Number ? Number(value) : value;
25-
builderClient.whereRaw(`LOWER(${this.tableColumnRef}) = LOWER(?)`, [parseValue]);
25+
builderClient.whereRaw(`${this.tableColumnRef} = ?`, [parseValue]);
2626
return builderClient;
2727
}
2828

@@ -35,11 +35,11 @@ export class StringCellValueFilterAdapter extends CellValueFilterPostgres {
3535
const { cellValueType } = this.field;
3636
if (isFieldReferenceValue(value)) {
3737
const ref = this.resolveFieldReference(value);
38-
builderClient.whereRaw(`LOWER(${this.tableColumnRef}) IS DISTINCT FROM LOWER(${ref})`);
38+
builderClient.whereRaw(`${this.tableColumnRef} IS DISTINCT FROM ${ref}`);
3939
return builderClient;
4040
}
4141
const parseValue = cellValueType === CellValueType.Number ? Number(value) : value;
42-
builderClient.whereRaw(`LOWER(${this.tableColumnRef}) IS DISTINCT FROM LOWER(?)`, [parseValue]);
42+
builderClient.whereRaw(`${this.tableColumnRef} IS DISTINCT FROM ?`, [parseValue]);
4343
return builderClient;
4444
}
4545

apps/nestjs-backend/src/db-provider/filter-query/sqlite/cell-value-filter/single-value/string-cell-value-filter.adapter.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ export class StringCellValueFilterAdapter extends CellValueFilterSqlite {
1818
): Knex.QueryBuilder {
1919
if (isFieldReferenceValue(value)) {
2020
const ref = this.resolveFieldReference(value);
21-
builderClient.whereRaw(`LOWER(${this.tableColumnRef}) = LOWER(${ref})`);
21+
builderClient.whereRaw(`${this.tableColumnRef} = ${ref}`);
2222
return builderClient;
2323
}
2424
const parseValue = this.field.cellValueType === CellValueType.Number ? Number(value) : value;
25-
builderClient.whereRaw(`LOWER(${this.tableColumnRef}) = LOWER(?)`, [parseValue]);
25+
builderClient.whereRaw(`${this.tableColumnRef} = ?`, [parseValue]);
2626
return builderClient;
2727
}
2828

@@ -35,11 +35,11 @@ export class StringCellValueFilterAdapter extends CellValueFilterSqlite {
3535
const { cellValueType } = this.field;
3636
if (isFieldReferenceValue(value)) {
3737
const ref = this.resolveFieldReference(value);
38-
builderClient.whereRaw(`LOWER(ifnull(${this.tableColumnRef}, '')) != LOWER(${ref})`);
38+
builderClient.whereRaw(`${this.tableColumnRef} != ${ref}`);
3939
return builderClient;
4040
}
4141
const parseValue = cellValueType === CellValueType.Number ? Number(value) : value;
42-
builderClient.whereRaw(`LOWER(ifnull(${this.tableColumnRef}, '')) != LOWER(?)`, [parseValue]);
42+
builderClient.whereRaw(`${this.tableColumnRef} != ?`, [parseValue]);
4343
return builderClient;
4444
}
4545

apps/nestjs-backend/src/features/auth/permission.service.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ export class PermissionService {
174174
},
175175
});
176176
}
177+
this.cls.set('spaceId', spaceId);
177178
return { baseId, spaceId };
178179
}
179180

@@ -198,6 +199,7 @@ export class PermissionService {
198199
},
199200
});
200201
}
202+
this.cls.set('spaceId', spaceId);
201203
return { spaceId };
202204
}
203205
private async isBaseIdAllowedForResource(
@@ -259,6 +261,11 @@ export class PermissionService {
259261
);
260262
}
261263

264+
// set the spaceId to the cls when the user operate in a space
265+
if (resourceId.startsWith(IdPrefix.Space)) {
266+
this.cls.set('spaceId', resourceId);
267+
}
268+
262269
if (
263270
resourceId.startsWith(IdPrefix.Base) &&
264271
!(await this.isBaseIdAllowedForResource(
@@ -318,6 +325,7 @@ export class PermissionService {
318325
}
319326
);
320327
}
328+
this.cls.set('spaceId', spaceId);
321329
return getPermissions(role);
322330
}
323331

apps/nestjs-backend/src/features/base/base.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Module } from '@nestjs/common';
22
import { DbProvider } from '../../db-provider/db.provider';
33
import { AttachmentsStorageModule } from '../attachments/attachments-storage.module';
44
import { StorageModule } from '../attachments/plugins/storage.module';
5+
import { CanaryModule } from '../canary';
56
import { CollaboratorModule } from '../collaborator/collaborator.module';
67
import { FieldDuplicateModule } from '../field/field-duplicate/field-duplicate.module';
78
import { FieldModule } from '../field/field.module';
@@ -29,6 +30,7 @@ import { DbConnectionService } from './db-connection.service';
2930
@Module({
3031
controllers: [BaseController],
3132
imports: [
33+
CanaryModule,
3234
CollaboratorModule,
3335
FieldModule,
3436
FieldOpenApiModule,

apps/nestjs-backend/src/features/base/base.service.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import { ATTACHMENT_LG_THUMBNAIL_HEIGHT } from '../attachments/constant';
4141
import StorageAdapter from '../attachments/plugins/adapter';
4242
import { getPublicFullStorageUrl } from '../attachments/plugins/utils';
4343
import { PermissionService } from '../auth/permission.service';
44+
import { CanaryService } from '../canary';
4445
import { CollaboratorService } from '../collaborator/collaborator.service';
4546
import { GraphService } from '../graph/graph.service';
4647
import { TableOpenApiService } from '../table/open-api/table-open-api.service';
@@ -60,6 +61,7 @@ export class BaseService {
6061
private readonly tableOpenApiService: TableOpenApiService,
6162
private readonly graphService: GraphService,
6263
private readonly attachmentsStorageService: AttachmentsStorageService,
64+
private readonly canaryService: CanaryService,
6365
@InjectDbProvider() private readonly dbProvider: IDbProvider,
6466
@ThresholdConfig() private readonly thresholdConfig: IThresholdConfig
6567
) {}
@@ -119,6 +121,10 @@ export class BaseService {
119121
const { role, collaboratorType } = template
120122
? { role: Role.Viewer, collaboratorType: CollaboratorType.Base }
121123
: await this.getRoleByBaseId(baseId, base.spaceId);
124+
125+
// Check if this base's space is in canary release
126+
const isCanary = await this.canaryService.isSpaceInCanary(base.spaceId);
127+
122128
return {
123129
...base,
124130
role,
@@ -127,6 +133,7 @@ export class BaseService {
127133
template?.baseId === baseId
128134
? { id: template.id, headers: this.permissionService.generateTemplateHeader(template.id) }
129135
: undefined,
136+
isCanary: isCanary || undefined, // Only include if true
130137
};
131138
}
132139

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { Module } from '@nestjs/common';
2+
import { SettingModule } from '../setting/setting.module';
3+
import { CanaryService } from './canary.service';
4+
5+
@Module({
6+
imports: [SettingModule],
7+
exports: [CanaryService],
8+
providers: [CanaryService],
9+
})
10+
export class CanaryModule {}

0 commit comments

Comments
 (0)