From 2d4011a45611f633ca2959412d644138b91ae2a6 Mon Sep 17 00:00:00 2001 From: Lyubov Voloshko Date: Thu, 14 May 2026 13:21:54 +0000 Subject: [PATCH 1/3] feat: extract database schema editor into standalone page Move AI schema generation from the dashboard into a dedicated edit-database-schema component with its own route. Add a schema edit button to connection cards and update the tables list with an edit-schema action. Co-Authored-By: Claude Opus 4.6 --- frontend/src/app/app-routing.module.ts | 9 ++++ .../own-connections.component.css | 14 ++++++ .../own-connections.component.html | 9 ++++ .../own-connections.component.ts | 3 +- .../dashboard/dashboard.component.css | 28 ----------- .../dashboard/dashboard.component.html | 23 +++------ .../dashboard/dashboard.component.ts | 10 +--- .../db-tables-list.component.css | 46 +---------------- .../db-tables-list.component.html | 15 ------ .../db-tables-list.component.ts | 1 - .../edit-database-schema.component.css} | 50 +++++++++++++------ .../edit-database-schema.component.html} | 22 ++++---- .../edit-database-schema.component.ts} | 29 ++++++++--- .../src/app/services/table-schema.service.ts | 27 ++++++++-- 14 files changed, 137 insertions(+), 149 deletions(-) rename frontend/src/app/components/{dashboard/db-generate-schema/db-generate-schema.component.css => edit-database-schema/edit-database-schema.component.css} (91%) rename frontend/src/app/components/{dashboard/db-generate-schema/db-generate-schema.component.html => edit-database-schema/edit-database-schema.component.html} (89%) rename frontend/src/app/components/{dashboard/db-generate-schema/db-generate-schema.component.ts => edit-database-schema/edit-database-schema.component.ts} (83%) diff --git a/frontend/src/app/app-routing.module.ts b/frontend/src/app/app-routing.module.ts index 4430a0b03..6a03cf3a2 100644 --- a/frontend/src/app/app-routing.module.ts +++ b/frontend/src/app/app-routing.module.ts @@ -160,6 +160,15 @@ const routes: Routes = [ loadComponent: () => import('./components/connect-db/connect-db.component').then((m) => m.ConnectDBComponent), canActivate: [AuthGuard], }, + { + path: 'edit-database-schema/:connection-id', + loadComponent: () => + import('./components/edit-database-schema/edit-database-schema.component').then( + (m) => m.EditDatabaseSchemaComponent, + ), + canActivate: [AuthGuard], + title: 'Edit Database Schema | Rocketadmin', + }, { path: 'connection-settings/:connection-id', loadComponent: () => diff --git a/frontend/src/app/components/connections-list/own-connections/own-connections.component.css b/frontend/src/app/components/connections-list/own-connections/own-connections.component.css index ed3b1a23f..2638a5434 100644 --- a/frontend/src/app/components/connections-list/own-connections/own-connections.component.css +++ b/frontend/src/app/components/connections-list/own-connections/own-connections.component.css @@ -320,6 +320,8 @@ .connectionInfo { display: flex; flex-direction: column; + min-width: 0; + flex: 1; } .connectionInfo .connectionInfo__connectionTitle { @@ -331,6 +333,18 @@ width: 100%; } +/* ── Schema button inside card ── */ + +.connectionSchemaButton { + margin-left: auto; + flex-shrink: 0; + color: rgba(255, 255, 255, 0.7); +} + +.connectionSchemaButton:hover { + color: #fff; +} + /* ── Show more / less ── */ .showAllButton { diff --git a/frontend/src/app/components/connections-list/own-connections/own-connections.component.html b/frontend/src/app/components/connections-list/own-connections/own-connections.component.html index 6a16db4a8..e446491f0 100644 --- a/frontend/src/app/components/connections-list/own-connections/own-connections.component.html +++ b/frontend/src/app/components/connections-list/own-connections/own-connections.component.html @@ -30,6 +30,15 @@

Create your first connection

{{ $any(connectionItem).displayTitle }}

{{ supportedDatabasesTitles[connectionItem.connection.type] }} + @if (connectionItem.accessLevel === 'edit') { + + schema + + } diff --git a/frontend/src/app/components/connections-list/own-connections/own-connections.component.ts b/frontend/src/app/components/connections-list/own-connections/own-connections.component.ts index c098ffffc..c70d85a07 100644 --- a/frontend/src/app/components/connections-list/own-connections/own-connections.component.ts +++ b/frontend/src/app/components/connections-list/own-connections/own-connections.component.ts @@ -3,6 +3,7 @@ import { Component, Input, OnChanges, OnInit, SimpleChanges, signal } from '@ang import { MatButtonModule } from '@angular/material/button'; import { MatDialog } from '@angular/material/dialog'; import { MatIconModule } from '@angular/material/icon'; +import { MatTooltipModule } from '@angular/material/tooltip'; import { Router, RouterModule } from '@angular/router'; import posthog from 'posthog-js'; import { firstValueFrom } from 'rxjs'; @@ -33,7 +34,7 @@ import { @Component({ selector: 'app-own-connections', - imports: [CommonModule, RouterModule, MatIconModule, MatButtonModule], + imports: [CommonModule, RouterModule, MatIconModule, MatButtonModule, MatTooltipModule], templateUrl: './own-connections.component.html', styleUrl: './own-connections.component.css', }) diff --git a/frontend/src/app/components/dashboard/dashboard.component.css b/frontend/src/app/components/dashboard/dashboard.component.css index 082580985..85b80f884 100644 --- a/frontend/src/app/components/dashboard/dashboard.component.css +++ b/frontend/src/app/components/dashboard/dashboard.component.css @@ -315,31 +315,3 @@ display: none !important; } -.schema-editor-panel { - position: fixed; - bottom: 0; - left: 0; - right: 0; - height: 0; - background: var(--mat-sidenav-content-background-color); - border-top: 1px solid rgba(0, 0, 0, 0.12); - box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.12); - overflow: hidden; - transition: height 0.3s ease; - z-index: 100; -} - -.schema-editor-panel--open { - height: 380px; -} - -.table-preview-content--panel-open { - padding-bottom: 380px; -} - -@media (prefers-color-scheme: dark) { - .schema-editor-panel { - border-top-color: rgba(255, 255, 255, 0.12); - box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.4); - } -} diff --git a/frontend/src/app/components/dashboard/dashboard.component.html b/frontend/src/app/components/dashboard/dashboard.component.html index 1db0ed844..ce14e4441 100644 --- a/frontend/src/app/components/dashboard/dashboard.component.html +++ b/frontend/src/app/components/dashboard/dashboard.component.html @@ -21,12 +21,12 @@ - - + @@ -87,12 +87,11 @@ [connectionID]="connectionID" [selectedTable]="selectedTableName" [uiSettings]="uiSettings" - (expandSidebar)="toggleSideBar()" - (editStructure)="onEditStructure()"> + (expandSidebar)="toggleSideBar()"> -
+
@@ -129,24 +128,14 @@ (applyFilter)="applyFilter($event)">
- - -
- - -
diff --git a/frontend/src/app/components/dashboard/dashboard.component.ts b/frontend/src/app/components/dashboard/dashboard.component.ts index cb63df8f9..0523da15a 100644 --- a/frontend/src/app/components/dashboard/dashboard.component.ts +++ b/frontend/src/app/components/dashboard/dashboard.component.ts @@ -37,7 +37,7 @@ import { DbTableFiltersDialogComponent } from './db-table-view/db-table-filters- import { DbTableRowViewComponent } from './db-table-view/db-table-row-view/db-table-row-view.component'; import { DbTableViewComponent } from './db-table-view/db-table-view.component'; import { TablesDataSource } from './db-tables-data-source'; -import { DbGenerateSchemaComponent } from './db-generate-schema/db-generate-schema.component'; +import { EditDatabaseSchemaComponent } from '../edit-database-schema/edit-database-schema.component'; import { DbTablesListComponent } from './db-tables-list/db-tables-list.component'; interface DataToActivateActions { @@ -56,7 +56,7 @@ interface DataToActivateActions { MatIconModule, MatDialogModule, MatSidenavModule, - DbGenerateSchemaComponent, + EditDatabaseSchemaComponent, DbTablesListComponent, DbTableViewComponent, DbTableAiPanelComponent, @@ -103,7 +103,6 @@ export class DashboardComponent implements OnInit, OnDestroy { public uiSettings: ConnectionSettingsUI; public tableFolders: any[] = []; public isConfiguring: boolean = false; - public showSchemaEditor: boolean = false; constructor( private _connections: ConnectionsService, @@ -451,14 +450,9 @@ export class DashboardComponent implements OnInit, OnDestroy { this._uiSettings.updateConnectionSetting(this.connectionID, 'shownTableTitles', this.shownTableTitles); } - onEditStructure() { - this.showSchemaEditor = true; - } - onSchemaApplied() { setTimeout(() => { this.noTablesError = false; - this.showSchemaEditor = false; this.loading = true; this.getData(); }, 1500); diff --git a/frontend/src/app/components/dashboard/db-tables-list/db-tables-list.component.css b/frontend/src/app/components/dashboard/db-tables-list/db-tables-list.component.css index d96a7a8ff..c0d0821fe 100644 --- a/frontend/src/app/components/dashboard/db-tables-list/db-tables-list.component.css +++ b/frontend/src/app/components/dashboard/db-tables-list/db-tables-list.component.css @@ -445,7 +445,7 @@ .expanded-container.has-custom-folders .add-folder-button-container { order: 4; /* After folders section */ position: sticky; - bottom: 40px; + bottom: 0; background-color: #ffffff; padding: 8px 16px; z-index: 10; @@ -459,50 +459,6 @@ } } -/* Edit structure button container */ -.edit-structure-button-container { - order: 5; /* Always at the very bottom */ - position: sticky; - bottom: 0; - background-color: #ffffff; - padding: 8px 16px; - z-index: 10; - margin-left: 16px; - margin-right: 16px; - margin-top: 4px; - margin-bottom: 8px; - width: calc(100% - 32px); - box-sizing: border-box; -} - -.expanded-container.has-custom-folders .edit-structure-button-container { - padding: 0 16px 8px; - margin-top: 0; - margin-left: 0; - margin-right: 0; - width: 100%; -} - -.edit-structure-button { - width: 100%; -} - -.edit-structure-button mat-icon { - font-size: 18px; - width: 18px; - height: 18px; -} - -@media (prefers-color-scheme: dark) { - .edit-structure-button-container { - background-color: #303030; - } - - .expanded-container.has-custom-folders .edit-structure-button-container { - background-color: #303030; - } -} - .search-input ::ng-deep * { background-color: transparent !important; } diff --git a/frontend/src/app/components/dashboard/db-tables-list/db-tables-list.component.html b/frontend/src/app/components/dashboard/db-tables-list/db-tables-list.component.html index b5b5a6c4d..c9270f948 100644 --- a/frontend/src/app/components/dashboard/db-tables-list/db-tables-list.component.html +++ b/frontend/src/app/components/dashboard/db-tables-list/db-tables-list.component.html @@ -61,13 +61,6 @@
- -
- construction -
- -
- -
-
diff --git a/frontend/src/app/components/dashboard/db-tables-list/db-tables-list.component.ts b/frontend/src/app/components/dashboard/db-tables-list/db-tables-list.component.ts index 2a34b892c..214853121 100644 --- a/frontend/src/app/components/dashboard/db-tables-list/db-tables-list.component.ts +++ b/frontend/src/app/components/dashboard/db-tables-list/db-tables-list.component.ts @@ -75,7 +75,6 @@ export class DbTablesListComponent implements OnInit, OnChanges { @Input() uiSettings: any; @Output() expandSidebar = new EventEmitter(); - @Output() editStructure = new EventEmitter(); private _connections = inject(ConnectionsService); protected canEditConnection = () => this._connections.canEditConnection(); diff --git a/frontend/src/app/components/dashboard/db-generate-schema/db-generate-schema.component.css b/frontend/src/app/components/edit-database-schema/edit-database-schema.component.css similarity index 91% rename from frontend/src/app/components/dashboard/db-generate-schema/db-generate-schema.component.css rename to frontend/src/app/components/edit-database-schema/edit-database-schema.component.css index 344a74b11..04e1525cd 100644 --- a/frontend/src/app/components/dashboard/db-generate-schema/db-generate-schema.component.css +++ b/frontend/src/app/components/edit-database-schema/edit-database-schema.component.css @@ -1,6 +1,6 @@ :host { display: flex; - height: 100%; + height: calc(100vh - 44px); } .schema-chat { @@ -13,6 +13,36 @@ position: relative; } +.schema-chat--routed { + max-width: 860px; + margin: 0 auto; + padding: 0 16px; + height: calc(100vh - var(--mat-toolbar-standard-height)); +} + +/* ── Header (routed page) ── */ + +.schema-chat__header { + display: flex; + align-items: center; + gap: 8px; + padding: var(--top-margin) 0 16px; + flex-shrink: 0; + width: 100%; +} + +.schema-chat__back-button { + flex-shrink: 0; +} + +.schema-chat__title { + font-size: 20px; + font-weight: 600; + margin: 0 !important; +} + +/* ── Close button (embedded panel) ── */ + .schema-chat__close-button { position: absolute; top: 8px; @@ -27,11 +57,13 @@ flex-direction: column; align-items: center; justify-content: center; - flex: 1; + flex: 1 1 0; gap: 16px; padding: 24px; max-width: 500px; margin: 0 auto; + min-height: 0; + overflow-y: auto; } .schema-chat__welcome-icon { @@ -246,17 +278,6 @@ } } -.schema-chat__rollback { - margin-top: 6px; -} - -.schema-chat__rollback summary { - cursor: pointer; - font-size: 12px; - opacity: 0.6; - margin-bottom: 4px; -} - .schema-chat__actions { display: flex; justify-content: flex-end; @@ -265,6 +286,7 @@ .schema-chat__actions button mat-icon { margin-right: 4px; + margin-bottom: -4px; font-size: 18px; height: 18px; width: 18px; @@ -312,7 +334,7 @@ .schema-chat__form { width: 100%; max-width: 700px; - padding: 0 16px 16px; + padding: 0 16px 32px; flex-shrink: 0; } diff --git a/frontend/src/app/components/dashboard/db-generate-schema/db-generate-schema.component.html b/frontend/src/app/components/edit-database-schema/edit-database-schema.component.html similarity index 89% rename from frontend/src/app/components/dashboard/db-generate-schema/db-generate-schema.component.html rename to frontend/src/app/components/edit-database-schema/edit-database-schema.component.html index 5a85af2bf..532845102 100644 --- a/frontend/src/app/components/dashboard/db-generate-schema/db-generate-schema.component.html +++ b/frontend/src/app/components/edit-database-schema/edit-database-schema.component.html @@ -1,4 +1,12 @@ -
+
+ @if (isRoutedPage()) { +
+ + arrow_back + +

Edit Database Schema

+
+ } @if (showClose) {
{{ change.forwardSql }}
- @if (change.rollbackSql) { -
- Rollback SQL -
{{ change.rollbackSql }}
-
- }
}
@@ -125,7 +127,7 @@ } @else {
- {{showClose ? 'Describe the changes you need...' : 'Describe the database you need...'}} + {{showClose || isRoutedPage() ? 'Describe the changes you need...' : 'Describe the database you need...'}}