Skip to content

Commit 13a2a1c

Browse files
Merge pull request #1136 from rocket-admin/custom-favicon
Custom favicon
2 parents 39faa8f + fb6a9b8 commit 13a2a1c

20 files changed

+230
-75
lines changed

frontend/src/app/app-routing.module.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,12 @@ const routes: Routes = [
4040
{path: 'external/user/email/verify/:verification-token', component: EmailVerificationComponent, title: 'Email verification | Rocketadmin'},
4141
{path: 'external/user/email/change/verify/:change-token', component: EmailChangeComponent, title: 'Email updating | Rocketadmin'},
4242
{path: 'deleted', component: UserDeletedSuccessComponent, title: 'User deleted | Rocketadmin'},
43-
{path: 'connect-db', component: ConnectDBComponent, canActivate: [AuthGuard], title: 'Add new database | Rocketadmin'},
44-
{path: 'connections-list', component: ConnectionsListComponent, canActivate: [AuthGuard], title: 'Connections | Rocketadmin'},
45-
{path: 'user-settings', component: UserSettingsComponent, canActivate: [AuthGuard], title: 'User settings | Rocketadmin'},
43+
{path: 'connect-db', component: ConnectDBComponent, canActivate: [AuthGuard]},
44+
{path: 'connections-list', component: ConnectionsListComponent, canActivate: [AuthGuard]},
45+
{path: 'user-settings', component: UserSettingsComponent, canActivate: [AuthGuard]},
4646
// company routes have to be in this specific order
4747
{path: 'company/:company-id/verify/:verification-token', pathMatch: 'full', component: CompanyMemberInvitationComponent, title: 'Invitation | Rocketadmin'},
48-
{path: 'company', pathMatch: 'full', component: CompanyComponent, title: 'Company settings | Rocketadmin', canActivate: [AuthGuard]},
48+
{path: 'company', pathMatch: 'full', component: CompanyComponent, canActivate: [AuthGuard]},
4949
{path: 'change-password', component: PasswordChangeComponent, canActivate: [AuthGuard]},
5050
{path: 'upgrade', component: UpgradeComponent, canActivate: [AuthGuard], title: 'Upgrade | Rocketadmin'},
5151
{path: 'upgrade/payment', component: PaymentFormComponent, canActivate: [AuthGuard], title: 'Payment | Rocketadmin'},

frontend/src/app/app.component.spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,8 @@ describe('AppComponent', () => {
244244
});
245245

246246
it('should handle user login flow when cast emits user with expires', fakeAsync(() => {
247+
mockCompanyService.getWhiteLabelProperties.and.returnValue(of({logo: '', favicon: ''}));
248+
247249
const expirationDate = new Date(Date.now() + 10_000); // 10s from now
248250
app['currentFeatureNotificationId'] = 'some-id';
249251

frontend/src/app/app.component.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,8 +260,6 @@ export class AppComponent {
260260
document.head.appendChild(favicon16);
261261
document.head.appendChild(favicon32);
262262
}
263-
264-
// this.whiteLabelSettingsLoaded = true;
265263
})
266264
this._uiSettings.getUiSettings().subscribe(settings => {
267265
this.isFeatureNotificationShown = (settings?.globalSettings?.lastFeatureNotificationId !== this.currentFeatureNotificationId)

frontend/src/app/components/audit/audit.component.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
1+
import { Component, OnInit, ViewChild } from '@angular/core';
22
import { AsyncPipe, NgClass, NgForOf, NgIf } from '@angular/common';
33
import { Subscription, merge } from 'rxjs';
44

@@ -27,6 +27,7 @@ import { normalizeTableName } from 'src/app/lib/normalize';
2727
import { tap } from 'rxjs/operators';
2828
import { BannerComponent } from '../ui-components/banner/banner.component';
2929
import { PlaceholderTableDataComponent } from '../skeletons/placeholder-table-data/placeholder-table-data.component';
30+
import { CompanyService } from 'src/app/services/company.service';
3031

3132
@Component({
3233
selector: 'app-audit',
@@ -50,7 +51,7 @@ import { PlaceholderTableDataComponent } from '../skeletons/placeholder-table-da
5051
templateUrl: './audit.component.html',
5152
styleUrls: ['./audit.component.css']
5253
})
53-
export class AuditComponent implements OnInit, OnDestroy {
54+
export class AuditComponent implements OnInit {
5455
public isSaas = (environment as any).saas;
5556
public connectionID: string;
5657
public accesLevel: string;
@@ -73,6 +74,7 @@ export class AuditComponent implements OnInit, OnDestroy {
7374
private _connections: ConnectionsService,
7475
private _tables: TablesService,
7576
private _users: UsersService,
77+
private _companyService: CompanyService,
7678
public dialog: MatDialog,
7779
private title: Title
7880
) { }
@@ -89,7 +91,9 @@ export class AuditComponent implements OnInit, OnDestroy {
8991

9092
ngOnInit(): void {
9193
this.getTitleSubscription = this._connections.getCurrentConnectionTitle().subscribe(connectionTitle => {
92-
this.title.setTitle(`Audit - ${connectionTitle} | Rocketadmin`);
94+
this.title.setTitle(`Audit - ${connectionTitle} | ${this._companyService.companyTabTitle || 'Rocketadmin'}`);
95+
96+
this.getTitleSubscription.unsubscribe();
9397
});
9498
this.connectionID = this._connections.currentConnectionID;
9599
this.accesLevel = this._connections.currentConnectionAccessLevel;
@@ -120,10 +124,6 @@ export class AuditComponent implements OnInit, OnDestroy {
120124
})
121125
}
122126

123-
ngOnDestroy() {
124-
this.getTitleSubscription.unsubscribe();
125-
}
126-
127127
loadLogsPage() {
128128
this.dataSource.fetchLogs({
129129
connectionID: this.connectionID,

frontend/src/app/components/company/company.component.css

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,16 +263,22 @@
263263
position: relative;
264264
}
265265

266+
.white-label-settings-images {
267+
display: flex;
268+
gap: 24px;
269+
margin-top: 16px;
270+
margin-bottom: 24px;
271+
}
272+
266273
.upload-logo-form {
267274
display: flex;
268275
align-items: center;
269276
gap: 8px;
270-
margin-top: 8px;
271277
}
272278

273279
.white-label-preview {
274280
height: auto;
275-
margin-top: 20px;
281+
margin-top: 8px;
276282
width: 100%;
277283
}
278284

frontend/src/app/components/company/company.component.html

Lines changed: 64 additions & 32 deletions
Large diffs are not rendered by default.

frontend/src/app/components/company/company.component.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ describe('CompanyComponent', () => {
113113
fakeCompanyService.getCustomDomain.and.returnValue(of(mockCompanyDomain));
114114
fakeCompanyService.updateCompanyName.and.returnValue(of({}));
115115
fakeCompanyService.updateCompanyMemberRole.and.returnValue(of({}));
116+
fakeCompanyService.getCurrentTabTitle = jasmine.createSpy().and.returnValue(of('Rocketadmin'));
116117
fakeUserService.cast = of(mockMembers[1]);
117118

118119
beforeEach(async () => {

frontend/src/app/components/company/company.component.ts

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import { PlaceholderTableDataComponent } from '../skeletons/placeholder-table-da
2626
import { NgIf } from '@angular/common';
2727
import { RouterModule } from '@angular/router';
2828
import { DeleteDomainDialogComponent } from './delete-domain-dialog/delete-domain-dialog.component';
29+
import { Title } from '@angular/platform-browser';
30+
import { Subscription } from 'rxjs';
2931

3032
@Component({
3133
selector: 'app-company',
@@ -68,11 +70,11 @@ export class CompanyComponent {
6870
public companyCustomDomain: {
6971
id: string,
7072
companyId: string,
71-
hostname: string
73+
hostname: string,
7274
} = {
7375
id: null,
7476
companyId: '',
75-
hostname: ''
77+
hostname: '',
7678
};
7779

7880
public companyCustomDomainHostname: string;
@@ -84,17 +86,21 @@ export class CompanyComponent {
8486
public submittingLogo: boolean = false;
8587
public submittingFavicon: boolean = false;
8688

87-
get whiteLabelSettings(): {logo: string, favicon: string} {
88-
return this._company.whiteLabelSettings || { logo: '', favicon: '' };
89+
public companyTabTitle: string;
90+
public submittingTabTitle: boolean = false;
91+
92+
get whiteLabelSettings(): {logo: string, favicon: string, tabTitle: string} {
93+
return this._company.whiteLabelSettings || { logo: '', favicon: '', tabTitle : '' };
8994
}
9095

96+
private getTitleSubscription: Subscription;
97+
9198
constructor(
9299
public _company: CompanyService,
93100
public _user: UserService,
94-
// private _notifications: NotificationsService,
95101
public dialog: MatDialog,
96102
private angulartics2: Angulartics2,
97-
// private title: Title
103+
private title: Title
98104
) { }
99105

100106
ngOnInit() {
@@ -103,6 +109,11 @@ export class CompanyComponent {
103109
this.isCustomDomain = true;
104110
}
105111

112+
this.getTitleSubscription = this._company.getCurrentTabTitle().subscribe(title => {
113+
this.companyTabTitle = title;
114+
this.title.setTitle(`Company settings | ${title || 'Rocketadmin'}`);
115+
});
116+
106117
this._company.fetchCompany().subscribe(res => {
107118
this.company = res;
108119
this.setCompanyPlan(res.subscriptionLevel);
@@ -127,14 +138,19 @@ export class CompanyComponent {
127138
this.getCompanyMembers(this.company.id);
128139
} else if (arg === 'domain') {
129140
this.getCompanyCustomDomain(this.company.id);
130-
}
131-
else if (arg === 'updated-white-label-settings') {
141+
} else if (arg === 'updated-white-label-settings') {
132142
// this.submittingLogo = true;
133143
this._company.getWhiteLabelProperties(this.company.id).subscribe();
134-
};
144+
}
135145
});
136146
}
137147

148+
ngOnDestroy() {
149+
if (this.getTitleSubscription) {
150+
this.getTitleSubscription.unsubscribe();
151+
}
152+
}
153+
138154
getCompanyMembers(companyId: string) {
139155
this._company.fetchCompanyMembers(companyId).subscribe(res => {
140156
if (this.company.invitations) {
@@ -372,4 +388,26 @@ export class CompanyComponent {
372388
this.submittingFavicon = false;
373389
});
374390
}
391+
392+
updateTabTitle() {
393+
this.submittingTabTitle = true;
394+
this._company.updateTabTitle(this.company.id, this.companyTabTitle).subscribe(() => {
395+
this.submittingTabTitle = false;
396+
this.angulartics2.eventTrack.next({
397+
action: 'Company: tab title is updated successfully',
398+
});
399+
}, err => {
400+
this.submittingTabTitle = false;
401+
});
402+
}
403+
404+
deleteTabTitle() {
405+
this.submittingTabTitle = true;
406+
this._company.removeTabTitle(this.company.id).subscribe(() => {
407+
this.submittingTabTitle = false;
408+
this.angulartics2.eventTrack.next({
409+
action: 'Company: tab title is deleted successfully',
410+
});
411+
});
412+
}
375413
}

frontend/src/app/components/connect-db/connect-db.component.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as ipaddr from 'ipaddr.js';
22

33
import { Alert, AlertActionType, AlertType } from 'src/app/models/alert';
44
import { Angulartics2, Angulartics2Module } from 'angulartics2';
5-
import { Component, NgZone, OnDestroy, OnInit } from '@angular/core';
5+
import { Component, NgZone, OnInit } from '@angular/core';
66
import { Connection, ConnectionType, DBtype, TestConnection } from 'src/app/models/connection';
77

88
import { AccessLevel } from 'src/app/models/user';
@@ -42,6 +42,7 @@ import { UserService } from 'src/app/services/user.service';
4242
import { environment } from 'src/environments/environment';
4343
import googlIPsList from 'src/app/consts/google-IP-addresses';
4444
import isIP from 'validator/lib/isIP';
45+
import { CompanyService } from 'src/app/services/company.service';
4546

4647
@Component({
4748
selector: 'app-connect-db',
@@ -73,7 +74,7 @@ import isIP from 'validator/lib/isIP';
7374
Angulartics2Module
7475
]
7576
})
76-
export class ConnectDBComponent implements OnInit, OnDestroy {
77+
export class ConnectDBComponent implements OnInit {
7778

7879
public isSaas = (environment as any).saas;
7980
public connectionID: string | null = null;
@@ -103,6 +104,7 @@ export class ConnectDBComponent implements OnInit, OnDestroy {
103104
private _connections: ConnectionsService,
104105
private _notifications: NotificationsService,
105106
public _user: UserService,
107+
private _company: CompanyService,
106108
private ngZone: NgZone,
107109
public router: Router,
108110
public dialog: MatDialog,
@@ -113,8 +115,14 @@ export class ConnectDBComponent implements OnInit, OnDestroy {
113115
ngOnInit() {
114116
this.connectionID = this._connections.currentConnectionID;
115117

116-
if (this.connectionID) this.getTitleSubscription = this._connections.getCurrentConnectionTitle().subscribe(connectionTitle => {
117-
this.title.setTitle(`Edit connection ${connectionTitle} | Rocketadmin`);
118+
this.getTitleSubscription = this._connections.getCurrentConnectionTitle().subscribe(connectionTitle => {
119+
if (this.connectionID) {
120+
this.title.setTitle(`Credentials — ${connectionTitle} | ${this._company.companyTabTitle || 'Rocketadmin'}`);
121+
} else {
122+
this.title.setTitle(`Add new database | ${this._company.companyTabTitle || 'Rocketadmin'}`);
123+
}
124+
125+
this.getTitleSubscription.unsubscribe();
118126
});
119127

120128
if (!this.connectionID) {
@@ -126,10 +134,6 @@ export class ConnectDBComponent implements OnInit, OnDestroy {
126134
};
127135
}
128136

129-
ngOnDestroy() {
130-
if (this.connectionID && !this.connectionToken) this.getTitleSubscription.unsubscribe();
131-
}
132-
133137
get db():Connection {
134138
return this._connections.currentConnection;
135139
}

frontend/src/app/components/connection-settings/connection-settings.component.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { PlaceholderConnectionSettingsComponent } from '../skeletons/placeholder
2525
import { AlertComponent } from '../ui-components/alert/alert.component';
2626
import { ZapierComponent } from './zapier/zapier.component';
2727
import { MatTabsModule } from '@angular/material/tabs';
28+
import { CompanyService } from 'src/app/services/company.service';
2829

2930
@Component({
3031
selector: 'app-connection-settings',
@@ -76,13 +77,14 @@ export class ConnectionSettingsComponent implements OnInit, OnDestroy {
7677
constructor(
7778
private _connections: ConnectionsService,
7879
private _tables: TablesService,
80+
private _company: CompanyService,
7981
private title: Title,
8082
@Inject(Angulartics2) private angulartics2: Angulartics2
8183
) { }
8284

8385
ngOnInit(): void {
8486
this.getTitleSubscription = this._connections.getCurrentConnectionTitle().subscribe(connectionTitle => {
85-
this.title.setTitle(`Settings - ${connectionTitle} | Rocketadmin`);
87+
this.title.setTitle(`Settings - ${connectionTitle} | ${this._company.companyTabTitle || 'Rocketadmin'}`);
8688
});
8789

8890
this.connectionID = this._connections.currentConnectionID;

0 commit comments

Comments
 (0)