Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ <h1 class="mat-h1 connectForm__fullLine">
</h1>

<mat-form-field appearance="outline" class="connectForm__title">
<mat-label>Connection name</mat-label>
<mat-label>Connection title</mat-label>
<input matInput name="title" #title="ngModel"
data-testid="connection-title-input"
angulartics2On="change"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<h1 mat-dialog-title>Name your connection</h1>

<mat-dialog-content class="rename-dialog__content">
<p class="rename-dialog__description">Give your hosted database a friendly name so you can find it easily.</p>
<p class="rename-dialog__description">Give your hosted database a friendly title so you can find it easily.</p>
<mat-form-field appearance="outline" class="rename-dialog__field">
<mat-label>Connection name</mat-label>
<mat-label>Connection title</mat-label>
<input matInput [(ngModel)]="title" placeholder="e.g. Production DB, Staging, My App" (keyup.enter)="save()" cdkFocusInitial>
</mat-form-field>
</mat-dialog-content>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.rename-dialog__field {
margin-top: 12px;
margin-bottom: -12px;

Copilot AI Apr 6, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation is inconsistent (mixed tabs/spaces) on the margin-bottom line, which will trip linters/formatters and makes diffs noisy. Reformat to match the surrounding CSS indentation.

Suggested change
margin-bottom: -12px;
margin-bottom: -12px;

Copilot uses AI. Check for mistakes.
width: 100%;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<h1 mat-dialog-title>Rename <strong>{{ data.databaseName }}</strong></h1>
<mat-dialog-content>
<mat-form-field appearance="outline" class="rename-dialog__field">
<mat-label>Connection name</mat-label>

Copilot AI Apr 6, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UI terminology is inconsistent: elsewhere the app now uses “Connection title” (e.g., connect-db.component.html:12 and connections-list/hosted-database-rename-dialog.component.html:6), but this dialog still says “Connection name”. Update the label to match the established wording.

Suggested change
<mat-label>Connection name</mat-label>
<mat-label>Connection title</mat-label>

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Inconsistent label: should be "Connection title".

This label says "Connection name" but the PR updates other templates to use "Connection title" (see connect-db.component.html line 12 and connections-list/hosted-database-rename-dialog line 6). Update for consistency.

-		<mat-label>Connection name</mat-label>
+		<mat-label>Connection title</mat-label>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<mat-label>Connection name</mat-label>
<mat-label>Connection title</mat-label>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/src/app/components/hosted-databases/hosted-database-rename-dialog/hosted-database-rename-dialog.component.html`
at line 4, Update the mat-label text in the hosted-database-rename-dialog
template: replace the existing "Connection name" label used in
hosted-database-rename-dialog.component.html with "Connection title" so it
matches the other templates (e.g., connect-db.component.html and
connections-list/hosted-database-rename-dialog) and keeps the UI wording
consistent.

<input matInput [(ngModel)]="title" placeholder="e.g. Production DB, Staging, My App"
(keyup.enter)="save()" cdkFocusInitial>
</mat-form-field>
</mat-dialog-content>
<mat-dialog-actions align="end">
<button type="button" mat-flat-button mat-dialog-close>Cancel</button>
<button type="button" mat-flat-button color="accent"
[disabled]="!title.trim() || submitting()"
(click)="save()">
{{ submitting() ? 'Saving...' : 'Save' }}
</button>
</mat-dialog-actions>
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { Component, inject, signal } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { firstValueFrom } from 'rxjs';
import posthog from 'posthog-js';
import { FoundHostedDatabase } from 'src/app/models/hosted-database';
import { ConnectionsService } from 'src/app/services/connections.service';
import { NotificationsService } from 'src/app/services/notifications.service';

@Component({
selector: 'app-hosted-databases-rename-dialog',
templateUrl: './hosted-database-rename-dialog.component.html',
styleUrls: ['./hosted-database-rename-dialog.component.css'],
imports: [MatDialogModule, MatButtonModule, MatFormFieldModule, MatInputModule, FormsModule],
})
export class HostedDatabasesRenameDialogComponent {
private _connectionsService = inject(ConnectionsService);
private _notifications = inject(NotificationsService);
private _dialogRef = inject(MatDialogRef<HostedDatabasesRenameDialogComponent>);

protected data: FoundHostedDatabase = inject(MAT_DIALOG_DATA);
protected title = this.data.title || this.data.databaseName || '';
protected submitting = signal(false);

async save(): Promise<void> {
const title = this.title.trim();
if (!title || this.submitting()) return;

this.submitting.set(true);

try {
const connections = await firstValueFrom(this._connectionsService.fetchConnections());
const match = connections?.find(
(item) =>
item.connection.host === this.data.hostname &&
item.connection.database === this.data.databaseName,
);

if (!match) {
this._notifications.showErrorSnackbar('Matching connection not found.');
this.submitting.set(false);
return;
}

await firstValueFrom(this._connectionsService.updateConnectionTitle(match.connection.id, title));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Handle potential null connection ID.

The Connection interface defines id as string | null. If match.connection.id is null, updateConnectionTitle will receive null instead of a valid string ID.

🛡️ Proposed fix
 			if (!match) {
 				this._notifications.showErrorSnackbar('Matching connection not found.');
 				this.submitting.set(false);
 				return;
 			}

+			if (!match.connection.id) {
+				this._notifications.showErrorSnackbar('Connection ID is missing.');
+				this.submitting.set(false);
+				return;
+			}
+
 			await firstValueFrom(this._connectionsService.updateConnectionTitle(match.connection.id, title));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/src/app/components/hosted-databases/hosted-database-rename-dialog/hosted-database-rename-dialog.component.ts`
at line 48, The call to updateConnectionTitle is passing match.connection.id
which can be null per the Connection type; add a null-check before awaiting
firstValueFrom so you only call updateConnectionTitle when match.connection.id
is a non-null string (e.g., guard on match.connection.id or throw/return early
if null), and handle the null case appropriately (show validation/error or
disable submit). Ensure the change is applied around the await
firstValueFrom(this._connectionsService.updateConnectionTitle(match.connection.id,
title)) invocation in HostedDatabaseRenameDialogComponent so
updateConnectionTitle always receives a string ID.

posthog.capture('Hosted Databases: database renamed', { databaseName: this.data.databaseName });
this._connectionsService.fetchConnections().subscribe();
this._dialogRef.close(title);
} finally {
this.submitting.set(false);
}
Comment on lines +34 to +54

Copilot AI Apr 6, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fetchConnections() and updateConnectionTitle() can complete without emitting (they return EMPTY on errors), which makes firstValueFrom(...) throw an EmptyError. Because this method has no catch, a failed request will reject the click handler Promise and can log an unhandled rejection while leaving the dialog open. Handle the error explicitly (add a catch that keeps the dialog open and shows feedback, or use firstValueFrom(..., { defaultValue: ... }) and branch on the result).

Copilot uses AI. Check for mistakes.
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ <h1 class="mat-h1">Hosted Databases</h1>
</div>
</div>
<div class="db-card__actions">
<button type="button" mat-icon-button
matTooltip="Change connection title"
(click)="renameDatabase(db)">
<mat-icon>edit</mat-icon>
</button>
Comment on lines +50 to +54

Copilot AI Apr 6, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new mat-icon-button relies on a tooltip for meaning but has no accessible name. Add an aria-label (or visually hidden text) so screen readers can identify the action.

Copilot uses AI. Check for mistakes.
<button type="button" mat-icon-button
matTooltip="Reset password"
(click)="resetPassword(db)">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { UserService } from 'src/app/services/user.service';
import { ProfileSidebarComponent } from '../profile/profile-sidebar/profile-sidebar.component';
import { AlertComponent } from '../ui-components/alert/alert.component';
import { HostedDatabaseDeleteDialogComponent } from './hosted-database-delete-dialog/hosted-database-delete-dialog.component';
import { HostedDatabasesRenameDialogComponent } from './hosted-database-rename-dialog/hosted-database-rename-dialog.component';
import { HostedDatabaseResetPasswordDialogComponent } from './hosted-database-reset-password-dialog/hosted-database-reset-password-dialog.component';

@Component({
Expand Down Expand Up @@ -64,6 +65,20 @@ export class HostedDatabasesComponent implements OnInit {
});
}

renameDatabase(db: FoundHostedDatabase): void {
const dialogRef = this._dialog.open(HostedDatabasesRenameDialogComponent, {
width: '28em',
maxWidth: '95vw',
data: db,
});

dialogRef.afterClosed().subscribe(async (newTitle) => {
if (newTitle) {
await this._loadDatabases();
}
});
Comment on lines +75 to +79

Copilot AI Apr 6, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

afterClosed().subscribe(async ...) creates a Promise that RxJS will ignore; if _loadDatabases() rejects, it can surface as an unhandled promise rejection. Prefer subscribing with a non-async callback and explicitly handling the Promise (e.g., call _loadDatabases() without await and handle errors), or use an RxJS operator (switchMap/from) to chain the async work.

Copilot uses AI. Check for mistakes.
}

resetPassword(db: FoundHostedDatabase): void {
this._dialog.open(HostedDatabaseResetPasswordDialogComponent, {
width: '32em',
Expand Down
Loading