-
-
Notifications
You must be signed in to change notification settings - Fork 18
Backend ai table settings fix #1540
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,78 +1,90 @@ | ||
| import sjson from 'secure-json-parse'; | ||
| import { | ||
| AfterLoad, | ||
| BeforeInsert, | ||
| BeforeUpdate, | ||
| Column, | ||
| Entity, | ||
| JoinColumn, | ||
| ManyToOne, | ||
| PrimaryGeneratedColumn, | ||
| Relation, | ||
| AfterLoad, | ||
| BeforeInsert, | ||
| BeforeUpdate, | ||
| Column, | ||
| CreateDateColumn, | ||
| Entity, | ||
| JoinColumn, | ||
| ManyToOne, | ||
| PrimaryGeneratedColumn, | ||
| Relation, | ||
| UpdateDateColumn, | ||
| } from 'typeorm'; | ||
| import { WidgetTypeEnum } from '../../enums/index.js'; | ||
| import { TableSettingsEntity } from '../table-settings/common-table-settings/table-settings.entity.js'; | ||
|
|
||
| @Entity('table_widget') | ||
| export class TableWidgetEntity { | ||
| @PrimaryGeneratedColumn('uuid') | ||
| id: string; | ||
| @PrimaryGeneratedColumn('uuid') | ||
| id: string; | ||
|
|
||
| @Column() | ||
| field_name: string; | ||
| @Column() | ||
| field_name: string; | ||
|
|
||
| @Column({ default: null, type: 'varchar' }) | ||
| widget_type?: WidgetTypeEnum; | ||
| @Column({ default: null, type: 'varchar' }) | ||
| widget_type?: WidgetTypeEnum; | ||
|
|
||
| @Column('json', { default: null }) | ||
| widget_params: string; | ||
| @Column('json', { default: null }) | ||
| widget_params: string; | ||
|
|
||
| @Column('json', { default: null }) | ||
| widget_options: string; | ||
| @Column('json', { default: null }) | ||
| widget_options: string; | ||
|
|
||
| @Column({ default: null }) | ||
| name?: string; | ||
| @Column({ default: null }) | ||
| name?: string; | ||
|
|
||
| @Column({ default: null }) | ||
| description?: string; | ||
| @Column({ default: null }) | ||
| description?: string; | ||
|
|
||
| @BeforeUpdate() | ||
| stringifyOptionsOnUpdate() { | ||
| try { | ||
| if (this.widget_options) { | ||
| this.widget_options = JSON.stringify(this.widget_options); | ||
| } | ||
| } catch (e) { | ||
| console.error('-> Error widget options stringify ' + e.message); | ||
| } | ||
| } | ||
| @CreateDateColumn({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' }) | ||
| created_at: Date; | ||
|
|
||
| @BeforeInsert() | ||
| stringifyOptions() { | ||
| try { | ||
| if (this.widget_options) { | ||
| this.widget_options = JSON.stringify(this.widget_options); | ||
| } | ||
| } catch (e) { | ||
| console.error('-> Error widget options stringify ' + e.message); | ||
| } | ||
| } | ||
| @UpdateDateColumn({ type: 'timestamp', nullable: true, default: null }) | ||
| updated_at: Date; | ||
|
|
||
| @AfterLoad() | ||
| parseOptions() { | ||
| try { | ||
| if (this.widget_options) { | ||
| this.widget_options = sjson.parse(this.widget_options, null, { | ||
| protoAction: 'remove', | ||
| constructorAction: 'remove', | ||
| }); | ||
| } | ||
| } catch (e) { | ||
| console.error('-> Error widget options parse ' + e.message); | ||
| } | ||
| } | ||
| @BeforeUpdate() | ||
| stringifyOptionsOnUpdate() { | ||
| try { | ||
| if (this.widget_options) { | ||
| this.widget_options = JSON.stringify(this.widget_options); | ||
| } | ||
| } catch (e) { | ||
| console.error('-> Error widget options stringify ' + e.message); | ||
| } | ||
| } | ||
|
|
||
| @ManyToOne(() => TableSettingsEntity, (settings) => settings.table_widgets, { onDelete: 'CASCADE' }) | ||
| @JoinColumn() | ||
| settings: Relation<TableSettingsEntity>; | ||
| @BeforeInsert() | ||
| stringifyOptions() { | ||
| try { | ||
| if (this.widget_options) { | ||
| this.widget_options = JSON.stringify(this.widget_options); | ||
| } | ||
| } catch (e) { | ||
| console.error('-> Error widget options stringify ' + e.message); | ||
| } | ||
| } | ||
|
|
||
| @AfterLoad() | ||
| parseOptions() { | ||
| try { | ||
| if (this.widget_options) { | ||
| this.widget_options = sjson.parse(this.widget_options, null, { | ||
| protoAction: 'remove', | ||
| constructorAction: 'remove', | ||
| }); | ||
| } | ||
| } catch (e) { | ||
| console.error('-> Error widget options parse ' + e.message); | ||
| } | ||
| } | ||
|
|
||
| @ManyToOne( | ||
| () => TableSettingsEntity, | ||
| (settings) => settings.table_widgets, | ||
| { onDelete: 'CASCADE' }, | ||
| ) | ||
| @JoinColumn() | ||
| settings: Relation<TableSettingsEntity>; | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,23 @@ | ||||||||||||||||||||||||||||||||||||||||||
| import { MigrationInterface, QueryRunner } from 'typeorm'; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| export class AddTimeStampColumnsIntoSettingsAndWidgetsEntities1769610545842 implements MigrationInterface { | ||||||||||||||||||||||||||||||||||||||||||
| name = 'AddTimeStampColumnsIntoSettingsAndWidgetsEntities1769610545842'; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| public async up(queryRunner: QueryRunner): Promise<void> { | ||||||||||||||||||||||||||||||||||||||||||
| await queryRunner.query(`ALTER TABLE "personal_table_settings" ADD "created_at" TIMESTAMP NOT NULL DEFAULT now()`); | ||||||||||||||||||||||||||||||||||||||||||
| await queryRunner.query(`ALTER TABLE "personal_table_settings" ADD "updated_at" TIMESTAMP DEFAULT now()`); | ||||||||||||||||||||||||||||||||||||||||||
| await queryRunner.query(`ALTER TABLE "tableSettings" ADD "created_at" TIMESTAMP NOT NULL DEFAULT now()`); | ||||||||||||||||||||||||||||||||||||||||||
| await queryRunner.query(`ALTER TABLE "tableSettings" ADD "updated_at" TIMESTAMP DEFAULT now()`); | ||||||||||||||||||||||||||||||||||||||||||
| await queryRunner.query(`ALTER TABLE "table_widget" ADD "created_at" TIMESTAMP NOT NULL DEFAULT now()`); | ||||||||||||||||||||||||||||||||||||||||||
| await queryRunner.query(`ALTER TABLE "table_widget" ADD "updated_at" TIMESTAMP DEFAULT now()`); | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+8
to
+12
|
||||||||||||||||||||||||||||||||||||||||||
| await queryRunner.query(`ALTER TABLE "personal_table_settings" ADD "updated_at" TIMESTAMP DEFAULT now()`); | |
| await queryRunner.query(`ALTER TABLE "tableSettings" ADD "created_at" TIMESTAMP NOT NULL DEFAULT now()`); | |
| await queryRunner.query(`ALTER TABLE "tableSettings" ADD "updated_at" TIMESTAMP DEFAULT now()`); | |
| await queryRunner.query(`ALTER TABLE "table_widget" ADD "created_at" TIMESTAMP NOT NULL DEFAULT now()`); | |
| await queryRunner.query(`ALTER TABLE "table_widget" ADD "updated_at" TIMESTAMP DEFAULT now()`); | |
| await queryRunner.query(`ALTER TABLE "personal_table_settings" ADD "updated_at" TIMESTAMP`); | |
| await queryRunner.query(`ALTER TABLE "tableSettings" ADD "created_at" TIMESTAMP NOT NULL DEFAULT now()`); | |
| await queryRunner.query(`ALTER TABLE "tableSettings" ADD "updated_at" TIMESTAMP`); | |
| await queryRunner.query(`ALTER TABLE "table_widget" ADD "created_at" TIMESTAMP NOT NULL DEFAULT now()`); | |
| await queryRunner.query(`ALTER TABLE "table_widget" ADD "updated_at" TIMESTAMP`); |
Copilot
AI
Jan 28, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The migration sets DEFAULT now() for the updated_at column, but the entity's @UpdateDateColumn decorator is configured with nullable: true and default: null. This creates a mismatch between the database schema and the entity definition. The updated_at field should not have a default value on insert - it should only be set when a record is updated. Remove DEFAULT now() from this migration query to match the entity definition.
| await queryRunner.query(`ALTER TABLE "personal_table_settings" ADD "updated_at" TIMESTAMP DEFAULT now()`); | |
| await queryRunner.query(`ALTER TABLE "tableSettings" ADD "created_at" TIMESTAMP NOT NULL DEFAULT now()`); | |
| await queryRunner.query(`ALTER TABLE "tableSettings" ADD "updated_at" TIMESTAMP DEFAULT now()`); | |
| await queryRunner.query(`ALTER TABLE "table_widget" ADD "created_at" TIMESTAMP NOT NULL DEFAULT now()`); | |
| await queryRunner.query(`ALTER TABLE "table_widget" ADD "updated_at" TIMESTAMP DEFAULT now()`); | |
| await queryRunner.query(`ALTER TABLE "personal_table_settings" ADD "updated_at" TIMESTAMP`); | |
| await queryRunner.query(`ALTER TABLE "tableSettings" ADD "created_at" TIMESTAMP NOT NULL DEFAULT now()`); | |
| await queryRunner.query(`ALTER TABLE "tableSettings" ADD "updated_at" TIMESTAMP`); | |
| await queryRunner.query(`ALTER TABLE "table_widget" ADD "created_at" TIMESTAMP NOT NULL DEFAULT now()`); | |
| await queryRunner.query(`ALTER TABLE "table_widget" ADD "updated_at" TIMESTAMP`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The migration sets DEFAULT now() for the updated_at column, but the entity's @UpdateDateColumn decorator is configured with nullable: true and default: null. This creates a mismatch between the database schema and the entity definition. The updated_at field should not have a default value on insert - it should only be set when a record is updated. Remove DEFAULT now() from this migration query to match the entity definition.