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 @@ -87,7 +87,7 @@

.connections-divider {
position: relative;
margin: 44px auto 52px;
margin: 24px auto 32px;
width: calc(100% - 16px);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ <h1 class="mat-headline-4 pageTitle__name" data-testid="company-name">{{companyN
<app-own-connections
[currentUser]="currentUser"
[connections]="ownConnections"
[isDemo]="isDemo">
[isDemo]="isDemo"
[companyId]="currentUser?.company?.id">
</app-own-connections>

<mat-divider *ngIf="testConnections && testConnections.length"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@

@media (prefers-color-scheme: dark) {
.testConnectionLink {
background: #404040;
border: 1px solid #404040;
background: #2a2a2a;
border: 1px solid #2a2a2a;
}

.testConnectionLink:hover {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<h1 *ngIf="!isDemo" class="mat-display-1">Explore demo admin panels</h1>
<h1 *ngIf="!isDemo" class="mat-display-1">Explore demo panels</h1>

Copilot AI Feb 16, 2026

Copy link

Choose a reason for hiding this comment

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

The text was shortened from "Explore demo admin panels" to "Explore demo panels". While this is more concise, consider whether "admin" is an important qualifier that helps users understand what these demo panels are for.

Suggested change
<h1 *ngIf="!isDemo" class="mat-display-1">Explore demo panels</h1>
<h1 *ngIf="!isDemo" class="mat-display-1">Explore demo admin panels</h1>

Copilot uses AI. Check for mistakes.
<h1 *ngIf="isDemo" class="mat-display-1">Try out a demo admin panel</h1>

<ul class="testConnections">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
:host {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
flex-grow: 1;
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
}

.empty-state {
Expand Down Expand Up @@ -53,24 +54,23 @@
}

.addConnectionLink {
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
border-radius: 4px;
box-shadow:
0px 1px 3px 0px rgba(0, 0, 0, 0.2),
0px 2px 2px 0px rgba(0, 0, 0, 0.12),
0px 0px 2px 0px rgba(0, 0, 0, 0.14);
color: inherit;
font-weight: 600;
padding: 12px;
text-decoration: none;
height: 100%;
transition:
box-shadow 200ms,
background 200ms,
border 200ms;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 4px;
border-radius: 4px;
box-shadow:
0px 1px 3px 0px rgba(0, 0, 0, 0.2),
0px 2px 2px 0px rgba(0, 0, 0, 0.12),
0px 0px 2px 0px rgba(0, 0, 0, 0.14);
color: inherit;
font-weight: 600;
padding: 8px;
text-decoration: none;
height: 100%;
min-height: 90px;
transition: box-shadow 200ms, background 200ms, border 200ms;
}

.addConnectionLink:hover {
Expand All @@ -81,10 +81,10 @@
}

@media (prefers-color-scheme: dark) {
.addConnectionLink {
background: #404040;
border: 1px solid #404040;
}
.addConnectionLink {
background: #2a2a2a;
border: 1px solid #2a2a2a;
}

.addConnectionLink:hover {
background: #212121;
Expand All @@ -97,26 +97,41 @@
}

.addConnectionLink__iconBox {
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
background-color: #fff;
border-radius: 4px;
height: 40px;
width: 40px;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
height: 32px;
width: 32px;
}

.addConnectionLink__icon {
flex-shrink: 0;
height: 30px;
width: 30px;
flex-shrink: 0;
height: 28px;
width: 28px;
}

@media (prefers-color-scheme: dark) {
.addConnectionLink__icon[data-mat-icon-name="mongodb"],
.addConnectionLink__icon[data-mat-icon-name="mysql"],
.addConnectionLink__icon[data-mat-icon-name="dynamodb"],
.addConnectionLink__icon[data-mat-icon-name="mssql"] {
Comment on lines +115 to +118

Copilot AI Feb 16, 2026

Copy link

Choose a reason for hiding this comment

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

The CSS selector using data-mat-icon-name attribute won't work because Angular Material's mat-icon component doesn't automatically set this attribute when using the [svgIcon] binding. To make this work, you need to either:

  1. Add [attr.data-mat-icon-name]="supportedDatabase" to the mat-icon element in the template (line 14 of the HTML file)
  2. Or use a different CSS approach such as adding a class based on the database type
Suggested change
.addConnectionLink__icon[data-mat-icon-name="mongodb"],
.addConnectionLink__icon[data-mat-icon-name="mysql"],
.addConnectionLink__icon[data-mat-icon-name="dynamodb"],
.addConnectionLink__icon[data-mat-icon-name="mssql"] {
.addConnectionLink__icon {

Copilot uses AI. Check for mistakes.
filter: brightness(2);
}
}

.addConnectionLink__label {
text-align: center;
}

.addConnectionLink__subLabel {
display: block;
font-weight: 400;
opacity: 0.6;
font-size: 12px;
margin-top: -2px;
}

.showAllButton {
margin-top: 20px;
margin-bottom: -56px;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<h1 *ngIf="isDemo" class="mat-display-1">Create you own test connection</h1>
<h1 *ngIf="isDemo" class="mat-display-1">Create your own test connection</h1>

<div *ngIf="!connections?.length && connections !== null" class="empty-state">
<h1 *ngIf="(currentUser?.role === 'ADMIN' || currentUser?.role === 'DB_ADMIN') && !isDemo" class="mat-display-1">
Create your first connection
Create first connection

Copilot AI Feb 16, 2026

Copy link

Choose a reason for hiding this comment

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

The text was changed from "Create your first connection" to "Create first connection", removing the word "your". This makes the text less personal and slightly more abrupt. While this may be intentional for brevity, consider whether this aligns with the overall tone of the application's user interface.

Suggested change
Create first connection
Create your first connection

Copilot uses AI. Check for mistakes.
</h1>
<ul class="supportedDatabases">
<li *ngFor="let supportedDatabase of supportedOrderedDatabases">
Expand All @@ -13,7 +13,10 @@ <h1 *ngIf="(currentUser?.role === 'ADMIN' || currentUser?.role === 'DB_ADMIN') &
<div class="addConnectionLink__iconBox">
<mat-icon [svgIcon]="supportedDatabase" class="addConnectionLink__icon"></mat-icon>
</div>
<span class="addConnectionLink__label">{{ supportedDatabasesTitles[supportedDatabase] }}</span>
<span class="addConnectionLink__label">
{{ getMainTitle(supportedDatabase) }}
<span *ngIf="getSubTitle(supportedDatabase)" class="addConnectionLink__subLabel">{{ getSubTitle(supportedDatabase) }}</span>
</span>
</a>
</li>
</ul>
Expand Down Expand Up @@ -80,7 +83,7 @@ <h2 class="connectionInfo__connectionTitle">{{ connectionItem.displayTitle }}</h
Add database
</a>-->

<div *ngIf="!connections?.length && connections !== null && !isDemo" class="empty-state_bottom">
<div *ngIf="!connections?.length && connections !== null && !isDemo && hasMultipleMembers" class="empty-state_bottom">
<p class="mat-body-1 empty-state__text">
Invited to a company but don't see your admin panel?
</p>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CommonModule } from '@angular/common';
import { Component, Input } from '@angular/core';
import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { RouterModule } from '@angular/router';
Expand All @@ -8,6 +8,7 @@ import posthog from 'posthog-js';
import { supportedDatabasesTitles, supportedOrderedDatabases } from 'src/app/consts/databases';
import { ConnectionItem } from 'src/app/models/connection';
import { UiSettings } from 'src/app/models/ui-settings';
import { CompanyService } from 'src/app/services/company.service';
import { UiSettingsService } from 'src/app/services/ui-settings.service';

@Component({
Expand All @@ -16,18 +17,24 @@ import { UiSettingsService } from 'src/app/services/ui-settings.service';
templateUrl: './own-connections.component.html',
styleUrl: './own-connections.component.css',
})
export class OwnConnectionsComponent {

export class OwnConnectionsComponent implements OnInit, OnChanges {
protected posthog = posthog;
@Input() currentUser: User;
@Input() connections: ConnectionItem[] = null;
@Input() isDemo: boolean = false;
@Input() companyId: string;

public displayedCardCount: number = 3;
public connectionsListCollapsed: boolean;
public supportedDatabasesTitles = supportedDatabasesTitles;
public supportedOrderedDatabases = supportedOrderedDatabases;
public hasMultipleMembers: boolean = false;

constructor(private _uiSettings: UiSettingsService) {}
constructor(
private _uiSettings: UiSettingsService,
private _companyService: CompanyService
) {}

ngOnInit() {
this._uiSettings.getUiSettings().subscribe((settings: UiSettings) => {
Expand All @@ -36,6 +43,14 @@ export class OwnConnectionsComponent {
});
}

ngOnChanges(changes: SimpleChanges) {
if (changes['companyId'] && this.companyId) {
this._companyService.fetchCompanyMembers(this.companyId).subscribe((members: any[]) => {
this.hasMultipleMembers = members && members.length > 1;
});
Comment on lines +47 to +50

Copilot AI Feb 16, 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 ngOnChanges lifecycle hook and the hasMultipleMembers feature lack test coverage. Consider adding tests to verify that:

  1. hasMultipleMembers is set to true when the company has more than one member
  2. hasMultipleMembers is set to false when there is only one member
  3. The method only fetches company members when companyId changes and is defined
Suggested change
if (changes['companyId'] && this.companyId) {
this._companyService.fetchCompanyMembers(this.companyId).subscribe((members: any[]) => {
this.hasMultipleMembers = members && members.length > 1;
});
const companyIdChange = changes['companyId'];
if (companyIdChange && companyIdChange.currentValue && companyIdChange.currentValue !== companyIdChange.previousValue) {
const companyId = companyIdChange.currentValue;
this._companyService.fetchCompanyMembers(companyId).subscribe((members: any[] = []) => {
const safeMembers = Array.isArray(members) ? members : [];
this.hasMultipleMembers = safeMembers.length > 1;
});
} else if (companyIdChange && !companyIdChange.currentValue) {
// Reset flag if companyId becomes undefined or falsy
this.hasMultipleMembers = false;

Copilot uses AI. Check for mistakes.
Comment on lines +48 to +50

Copilot AI Feb 16, 2026

Copy link

Choose a reason for hiding this comment

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

The subscription to fetchCompanyMembers in ngOnChanges is not being cleaned up, which could lead to memory leaks. The subscription should be stored and unsubscribed in ngOnDestroy, or you should use the async pipe in the template, or add .pipe(take(1)) to automatically unsubscribe after the first emission.

Copilot uses AI. Check for mistakes.
}
Comment on lines +47 to +51

Copilot AI Feb 16, 2026

Copy link

Choose a reason for hiding this comment

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

The ngOnChanges hook will be called on every change detection cycle when any input changes, not just when companyId changes. The condition checks if companyId exists, but ngOnChanges will still trigger whenever any of the other inputs (currentUser, connections, isDemo) change. Consider adding a check to verify that companyId has actually changed from its previous value: if (changes['companyId'] && this.companyId && !changes['companyId'].firstChange && changes['companyId'].currentValue !== changes['companyId'].previousValue) or simply check changes['companyId'].firstChange to only fetch on initial load.

Copilot uses AI. Check for mistakes.
}

showMore() {
this.displayedCardCount = this.connections.length;
this._uiSettings.updateGlobalSetting('connectionsListCollapsed', false);
Expand All @@ -45,4 +60,16 @@ export class OwnConnectionsComponent {
this.displayedCardCount = 3;
this._uiSettings.updateGlobalSetting('connectionsListCollapsed', true);
}

getMainTitle(database: string): string {
const title = this.supportedDatabasesTitles[database] || database;
const match = title.match(/^([^(]+)/);
return match ? match[1].trim() : title;
Comment on lines +66 to +67

Copilot AI Feb 16, 2026

Copy link

Choose a reason for hiding this comment

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

The regex pattern /^([^(]+)/ will match from the beginning up to (but not including) the first opening parenthesis. However, for databases without parentheses (like "PostgreSQL", "MongoDB", "Redis", etc.), this regex will match the entire string. While this works, it's more efficient to simply use split or check for the presence of a parenthesis first. Consider simplifying to: const index = title.indexOf('('); return index > 0 ? title.substring(0, index).trim() : title;

Suggested change
const match = title.match(/^([^(]+)/);
return match ? match[1].trim() : title;
const index = title.indexOf('(');
return index > 0 ? title.substring(0, index).trim() : title;

Copilot uses AI. Check for mistakes.
}

getSubTitle(database: string): string {
const title = this.supportedDatabasesTitles[database] || database;
const match = title.match(/(\([^)]+\))/);
return match ? match[1] : '';
}
Comment on lines +64 to +74

Copilot AI Feb 16, 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 methods getMainTitle and getSubTitle lack test coverage. Since this component has a test file (own-connections.component.spec.ts) with basic setup, consider adding unit tests for these methods to ensure they correctly parse database titles with and without parentheses, such as "MySQL (MariaDB)" → main: "MySQL", sub: "(MariaDB)" and "PostgreSQL" → main: "PostgreSQL", sub: "".

Copilot uses AI. Check for mistakes.
}
Loading