diff --git a/frontend/src/app/app.component.html b/frontend/src/app/app.component.html
index a298447e3..481c5b81a 100644
--- a/frontend/src/app/app.component.html
+++ b/frontend/src/app/app.component.html
@@ -153,7 +153,7 @@
class="nav-bar__upgrade-button"
angulartics2On="click"
angularticsAction="Demo navbar: Create account is clicked"
- (click)="logoutAndRedirectToRegistration()">
+ (click)="logoutAndRedirectToRegistration(); posthog.capture('Demo navbar: Create account is clicked')">
Create account
diff --git a/frontend/src/app/app.component.ts b/frontend/src/app/app.component.ts
index be3676613..307789763 100644
--- a/frontend/src/app/app.component.ts
+++ b/frontend/src/app/app.component.ts
@@ -15,6 +15,7 @@ import { User } from '@sentry/angular';
import amplitude from 'amplitude-js';
import { Angulartics2, Angulartics2Amplitude, Angulartics2OnModule } from 'angulartics2';
import { differenceInMilliseconds } from 'date-fns';
+import posthog from 'posthog-js';
import { Subject } from 'rxjs';
import { filter } from 'rxjs/operators';
import { environment } from '../environments/environment';
@@ -23,6 +24,7 @@ import { Connection } from './models/connection';
import { AuthService } from './services/auth.service';
import { CompanyService } from './services/company.service';
import { ConnectionsService } from './services/connections.service';
+import { PosthogService } from './services/posthog.service';
import { TablesService } from './services/tables.service';
import { UiSettingsService } from './services/ui-settings.service';
import { UserService } from './services/user.service';
@@ -53,6 +55,7 @@ amplitude.getInstance().init('9afd282be91f94da735c11418d5ff4f5');
],
})
export class AppComponent {
+ protected posthog = posthog;
public isSaas = (environment as any).saas;
public appVersion = version;
userActivity;
@@ -95,6 +98,7 @@ export class AppComponent {
private angulartics2: Angulartics2,
private domSanitizer: DomSanitizer,
private matIconRegistry: MatIconRegistry,
+ _posthog: PosthogService,
) {
this.matIconRegistry.addSvgIcon(
'mysql',
@@ -167,6 +171,7 @@ export class AppComponent {
this.angulartics2.eventTrack.next({
action: 'Demo account is logged in',
});
+ posthog.capture('Demo account is logged in');
});
}
});
diff --git a/frontend/src/app/components/api-keys/api-keys.component.html b/frontend/src/app/components/api-keys/api-keys.component.html
index e72126991..0c776eaa3 100644
--- a/frontend/src/app/components/api-keys/api-keys.component.html
+++ b/frontend/src/app/components/api-keys/api-keys.component.html
@@ -18,6 +18,7 @@
API Keys
data-testid="api-key-input"
angulartics2On="change"
angularticsAction="API Keys: api key title is edited"
+ (change)="posthog.capture('API Keys: api key title is edited')"
[(ngModel)]="generatingAPIkeyTitle">
{
- this.title.setTitle(`API Keys | ${tabTitle || 'Rocketadmin'}`);
- });
- this.getAPIkeys();
- }
+ ngOnInit(): void {
+ this._company.getCurrentTabTitle().subscribe((tabTitle) => {
+ this.title.setTitle(`API Keys | ${tabTitle || 'Rocketadmin'}`);
+ });
+ this.getAPIkeys();
+ }
- getAPIkeys() {
- this._userService.getAPIkeys().subscribe(res => this.apiKeys = res);
- }
+ getAPIkeys() {
+ this._userService.getAPIkeys().subscribe((res) => (this.apiKeys = res));
+ }
- generateAPIkey() {
- this.submitting = true;
- this._userService.generateAPIkey(this.generatingAPIkeyTitle).subscribe(res => {
- this.generatedAPIkeyHash = res.hash;
- this.generatingAPIkeyTitle = '';
- this.getAPIkeys();
- this.submitting = false;
- this.angulartics2.eventTrack.next({
- action: 'API Keys: key generated successfully',
- });
- }, () => {
- this.submitting = false;
- });
- }
+ generateAPIkey() {
+ this.submitting = true;
+ this._userService.generateAPIkey(this.generatingAPIkeyTitle).subscribe(
+ (res) => {
+ this.generatedAPIkeyHash = res.hash;
+ this.generatingAPIkeyTitle = '';
+ this.getAPIkeys();
+ this.submitting = false;
+ this.angulartics2.eventTrack.next({
+ action: 'API Keys: key generated successfully',
+ });
+ posthog.capture('API Keys: key generated successfully');
+ },
+ () => {
+ this.submitting = false;
+ },
+ );
+ }
- deleteAPIkey(apiKey: ApiKey) {
- const deleteConfirmation = this.dialog.open(ApiKeyDeleteDialogComponent, {
- width: '25em',
- data: apiKey
- });
+ deleteAPIkey(apiKey: ApiKey) {
+ const deleteConfirmation = this.dialog.open(ApiKeyDeleteDialogComponent, {
+ width: '25em',
+ data: apiKey,
+ });
- deleteConfirmation.afterClosed().subscribe(action => {
- if (action === 'delete') {
- this.getAPIkeys();
- this.angulartics2.eventTrack.next({
- action: 'API Keys: key deleted successfully',
- });
- }
- });
- }
+ deleteConfirmation.afterClosed().subscribe((action) => {
+ if (action === 'delete') {
+ this.getAPIkeys();
+ this.angulartics2.eventTrack.next({
+ action: 'API Keys: key deleted successfully',
+ });
+ posthog.capture('API Keys: key deleted successfully');
+ }
+ });
+ }
- showCopyNotification(message: string) {
- this._notifications.showSuccessSnackbar(message);
- }
+ showCopyNotification(message: string) {
+ this._notifications.showSuccessSnackbar(message);
+ }
}
diff --git a/frontend/src/app/components/audit/audit.component.html b/frontend/src/app/components/audit/audit.component.html
index e5a170145..7e6c2ca45 100644
--- a/frontend/src/app/components/audit/audit.component.html
+++ b/frontend/src/app/components/audit/audit.component.html
@@ -7,6 +7,7 @@ Audit
Show all
@@ -23,6 +24,7 @@ Audit
Show all
{{user.email}}
@@ -103,7 +105,7 @@ Rocketadmin can not find any tables
+ (click)="openInfoLogDialog(element); posthog.capture('Audit: view changes is clicked')">
Details
diff --git a/frontend/src/app/components/audit/audit.component.ts b/frontend/src/app/components/audit/audit.component.ts
index 4bfb7ad20..2969e8f5a 100644
--- a/frontend/src/app/components/audit/audit.component.ts
+++ b/frontend/src/app/components/audit/audit.component.ts
@@ -2,9 +2,9 @@ import { AsyncPipe, NgClass, NgForOf, NgIf } from '@angular/common';
import { Component, OnInit, ViewChild } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
-import { MatIconModule } from '@angular/material/icon';
import { MatDialog } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatIconModule } from '@angular/material/icon';
import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator';
import { MatSelectModule } from '@angular/material/select';
import { MatTableModule } from '@angular/material/table';
@@ -12,6 +12,7 @@ import { Title } from '@angular/platform-browser';
import { RouterModule } from '@angular/router';
import { User } from '@sentry/angular';
import { Angulartics2OnModule } from 'angulartics2';
+import posthog from 'posthog-js';
import { merge } from 'rxjs';
import { take, tap } from 'rxjs/operators';
import { normalizeTableName } from 'src/app/lib/normalize';
@@ -52,6 +53,7 @@ import { InfoDialogComponent } from './info-dialog/info-dialog.component';
styleUrls: ['./audit.component.css'],
})
export class AuditComponent implements OnInit {
+ protected posthog = posthog;
public isSaas = (environment as any).saas;
public connectionID: string;
public accesLevel: string;
diff --git a/frontend/src/app/components/branding/branding.component.html b/frontend/src/app/components/branding/branding.component.html
index b6fdf3181..4cce16f50 100644
--- a/frontend/src/app/components/branding/branding.component.html
+++ b/frontend/src/app/components/branding/branding.component.html
@@ -25,6 +25,7 @@ Branding
data-testid="custom-domain-input"
angulartics2On="change"
angularticsAction="Company: custom domain is edited"
+ (change)="posthog.capture('Company: custom domain is edited')"
placeholder="e.g. {{companyCustomDomainPlaceholder}}"
[readonly]="currentUser.role === 'DB_ADMIN' || isCustomDomain"
[(ngModel)]="companyCustomDomainHostname">
@@ -95,6 +96,7 @@ Branding
data-testid="custom-tab-title-input"
angulartics2On="change"
angularticsAction="Company: tab title domain is edited"
+ (change)="posthog.capture('Company: tab title domain is edited')"
placeholder="e.g. {{company.name}}"
[readonly]="currentUser.role === 'DB_ADMIN'"
[(ngModel)]="companyTabTitle">
diff --git a/frontend/src/app/components/branding/branding.component.ts b/frontend/src/app/components/branding/branding.component.ts
index 7c095ccb6..e8d2ef665 100644
--- a/frontend/src/app/components/branding/branding.component.ts
+++ b/frontend/src/app/components/branding/branding.component.ts
@@ -1,3 +1,4 @@
+import { NgIf } from '@angular/common';
import { Component, CUSTOM_ELEMENTS_SCHEMA, OnDestroy, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
@@ -6,265 +7,288 @@ import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatTooltipModule } from '@angular/material/tooltip';
-import { NgIf } from '@angular/common';
+import { Title } from '@angular/platform-browser';
import { Angulartics2, Angulartics2OnModule } from 'angulartics2';
+import posthog from 'posthog-js';
import { Subscription } from 'rxjs';
-import { Title } from '@angular/platform-browser';
-
-import { AlertComponent } from '../ui-components/alert/alert.component';
+import { Company } from 'src/app/models/company';
import { CompanyService } from 'src/app/services/company.service';
import { UserService } from 'src/app/services/user.service';
-import { Company } from 'src/app/models/company';
-import { ProfileSidebarComponent } from '../profile/profile-sidebar/profile-sidebar.component';
-import { DeleteDomainDialogComponent } from '../company/delete-domain-dialog/delete-domain-dialog.component';
import { environment } from 'src/environments/environment';
+import { DeleteDomainDialogComponent } from '../company/delete-domain-dialog/delete-domain-dialog.component';
+import { ProfileSidebarComponent } from '../profile/profile-sidebar/profile-sidebar.component';
import { PlaceholderBrandingComponent } from '../skeletons/placeholder-branding/placeholder-branding.component';
+import { AlertComponent } from '../ui-components/alert/alert.component';
@Component({
- selector: 'app-branding',
- templateUrl: './branding.component.html',
- styleUrls: ['./branding.component.css'],
- imports: [
- NgIf,
- FormsModule,
- MatFormFieldModule,
- MatInputModule,
- MatButtonModule,
- MatIconModule,
- MatTooltipModule,
- Angulartics2OnModule,
- AlertComponent,
- ProfileSidebarComponent,
- PlaceholderBrandingComponent,
- ],
- schemas: [CUSTOM_ELEMENTS_SCHEMA]
+ selector: 'app-branding',
+ templateUrl: './branding.component.html',
+ styleUrls: ['./branding.component.css'],
+ imports: [
+ NgIf,
+ FormsModule,
+ MatFormFieldModule,
+ MatInputModule,
+ MatButtonModule,
+ MatIconModule,
+ MatTooltipModule,
+ Angulartics2OnModule,
+ AlertComponent,
+ ProfileSidebarComponent,
+ PlaceholderBrandingComponent,
+ ],
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class BrandingComponent implements OnInit, OnDestroy {
- public isSaas = (environment as any).saas;
- public company: Company = null;
- public currentPlan: string;
- public currentUser: any;
-
- public companyCustomDomain: {
- id: string,
- companyId: string,
- hostname: string,
- } = {
- id: null,
- companyId: '',
- hostname: '',
- };
-
- public companyCustomDomainHostname: string;
- public companyCustomDomainPlaceholder: string;
- public companyCustomDomainThirdLevel: string;
- public submittingCustomDomain: boolean = false;
- public isCustomDomain: boolean = false;
-
- public submittingLogo: boolean = false;
- public submittingFavicon: boolean = false;
-
- public companyTabTitle: string;
- public submittingTabTitle: boolean = false;
-
- get whiteLabelSettings(): {logo: string, favicon: string, tabTitle: string} {
- return this._company.whiteLabelSettings || { logo: '', favicon: '', tabTitle: '' };
- }
-
- get isDemo() {
- return this._user.isDemo;
- }
-
- private subscriptions: Subscription[] = [];
-
- constructor(
- private _company: CompanyService,
- private _user: UserService,
- private dialog: MatDialog,
- private angulartics2: Angulartics2,
- private title: Title
- ) {}
-
- ngOnInit() {
- this.isCustomDomain = this._company.isCustomDomain() && this.isSaas;
-
- const titleSub = this._company.getCurrentTabTitle().subscribe(tabTitle => {
- this.companyTabTitle = tabTitle;
- this.title.setTitle(`Branding | ${tabTitle || 'Rocketadmin'}`);
- });
- this.subscriptions.push(titleSub);
-
- const userSub = this._user.cast.subscribe(user => {
- this.currentUser = user;
- });
- this.subscriptions.push(userSub);
-
- this._company.fetchCompany().subscribe(res => {
- this.company = res;
- this.setCompanyPlan(res.subscriptionLevel);
- if (this.isCustomDomain) {
- this.companyCustomDomainHostname = res.custom_domain;
- } else {
- this.getCompanyCustomDomain(res.id);
- }
- });
-
- const castSub = this._company.cast.subscribe(arg => {
- if (arg === 'domain') {
- this.getCompanyCustomDomain(this.company.id);
- } else if (arg === 'updated-white-label-settings') {
- this._company.getWhiteLabelProperties(this.company.id).subscribe();
- }
- });
- this.subscriptions.push(castSub);
- }
-
- ngOnDestroy() {
- this.subscriptions.forEach(sub => sub.unsubscribe());
- }
-
- getCompanyCustomDomain(companyId: string) {
- this._company.getCustomDomain(companyId).subscribe(res => {
- if (res.success) {
- this.companyCustomDomain = res.domain_info;
- this.companyCustomDomainHostname = res.domain_info.hostname;
- this.companyCustomDomainThirdLevel = this.companyCustomDomainHostname.split('.')[0];
- } else {
- this.companyCustomDomain = {
- id: null,
- companyId: companyId,
- hostname: ''
- };
- this.companyCustomDomainHostname = '';
- this.companyCustomDomainPlaceholder = `${this.company.name.toLowerCase().replace(/[^a-z0-9]/g, '')}.example.com`;
- this.companyCustomDomainThirdLevel = this.companyCustomDomainPlaceholder.split('.')[0];
- }
- });
- }
-
- setCompanyPlan(subscriptionLevel: string) {
- if (subscriptionLevel) {
- this.currentPlan = subscriptionLevel.slice(0, -5).toLowerCase();
- } else {
- this.currentPlan = 'free';
- }
- }
-
- handleChangeCompanyDomain() {
- this.submittingCustomDomain = true;
- if (this.companyCustomDomain.id) {
- this._company.updateCustomDomain(this.company.id, this.companyCustomDomain.id).subscribe(() => {
- this.submittingCustomDomain = false;
- this.angulartics2.eventTrack.next({
- action: 'Company: domain is updated successfully',
- });
- });
- } else {
- this._company.createCustomDomain(this.company.id, this.companyCustomDomainHostname).subscribe(() => {
- this.submittingCustomDomain = false;
- this.angulartics2.eventTrack.next({
- action: 'Company: domain is created successfully',
- });
- });
- }
- }
-
- handleDeleteDomainDialogOpen() {
- this.dialog.open(DeleteDomainDialogComponent, {
- width: '25em',
- data: { companyId: this.company.id, domain: this.companyCustomDomainHostname }
- });
- }
-
- onCompanyLogoSelected(event: any) {
- this.submittingLogo = true;
-
- const input = event.target as HTMLInputElement;
- const file = input.files?.[0];
- let companyLogoFile: File | null = null;
-
- if (file) {
- companyLogoFile = file;
- } else {
- companyLogoFile = null;
- }
-
- this._company.uploadLogo(this.company.id, companyLogoFile).subscribe(_res => {
- this.submittingLogo = false;
- this.angulartics2.eventTrack.next({
- action: 'Company: logo is uploaded successfully',
- });
- }, _err => {
- this.submittingLogo = false;
- });
- }
-
- removeLogo() {
- this.submittingLogo = true;
- this._company.removeLogo(this.company.id).subscribe(_res => {
- this.submittingLogo = false;
- this.angulartics2.eventTrack.next({
- action: 'Company: logo is removed successfully',
- });
- }, _err => {
- this.submittingLogo = false;
- });
- }
-
- onFaviconSelected(event: any) {
- this.submittingFavicon = true;
-
- const input = event.target as HTMLInputElement;
- const file = input.files?.[0];
- let faviconFile: File | null = null;
-
- if (file) {
- faviconFile = file;
- } else {
- faviconFile = null;
- }
-
- this._company.uploadFavicon(this.company.id, faviconFile).subscribe(_res => {
- this.submittingFavicon = false;
- this.angulartics2.eventTrack.next({
- action: 'Company: favicon is uploaded successfully',
- });
- }, _err => {
- this.submittingFavicon = false;
- });
- }
-
- removeFavicon() {
- this.submittingFavicon = true;
- this._company.removeFavicon(this.company.id).subscribe(_res => {
- this.submittingFavicon = false;
- this.angulartics2.eventTrack.next({
- action: 'Company: favicon is removed successfully',
- });
- }, _err => {
- this.submittingFavicon = false;
- });
- }
-
- updateTabTitle() {
- this.submittingTabTitle = true;
- this._company.updateTabTitle(this.company.id, this.companyTabTitle).subscribe(() => {
- this.submittingTabTitle = false;
- this.angulartics2.eventTrack.next({
- action: 'Company: tab title is updated successfully',
- });
- }, _err => {
- this.submittingTabTitle = false;
- });
- }
-
- deleteTabTitle() {
- this.submittingTabTitle = true;
- this._company.removeTabTitle(this.company.id).subscribe(() => {
- this.submittingTabTitle = false;
- this.angulartics2.eventTrack.next({
- action: 'Company: tab title is deleted successfully',
- });
- });
- }
+ protected posthog = posthog;
+ public isSaas = (environment as any).saas;
+ public company: Company = null;
+ public currentPlan: string;
+ public currentUser: any;
+
+ public companyCustomDomain: {
+ id: string;
+ companyId: string;
+ hostname: string;
+ } = {
+ id: null,
+ companyId: '',
+ hostname: '',
+ };
+
+ public companyCustomDomainHostname: string;
+ public companyCustomDomainPlaceholder: string;
+ public companyCustomDomainThirdLevel: string;
+ public submittingCustomDomain: boolean = false;
+ public isCustomDomain: boolean = false;
+
+ public submittingLogo: boolean = false;
+ public submittingFavicon: boolean = false;
+
+ public companyTabTitle: string;
+ public submittingTabTitle: boolean = false;
+
+ get whiteLabelSettings(): { logo: string; favicon: string; tabTitle: string } {
+ return this._company.whiteLabelSettings || { logo: '', favicon: '', tabTitle: '' };
+ }
+
+ get isDemo() {
+ return this._user.isDemo;
+ }
+
+ private subscriptions: Subscription[] = [];
+
+ constructor(
+ private _company: CompanyService,
+ private _user: UserService,
+ private dialog: MatDialog,
+ private angulartics2: Angulartics2,
+ private title: Title,
+ ) {}
+
+ ngOnInit() {
+ this.isCustomDomain = this._company.isCustomDomain() && this.isSaas;
+
+ const titleSub = this._company.getCurrentTabTitle().subscribe((tabTitle) => {
+ this.companyTabTitle = tabTitle;
+ this.title.setTitle(`Branding | ${tabTitle || 'Rocketadmin'}`);
+ });
+ this.subscriptions.push(titleSub);
+
+ const userSub = this._user.cast.subscribe((user) => {
+ this.currentUser = user;
+ });
+ this.subscriptions.push(userSub);
+
+ this._company.fetchCompany().subscribe((res) => {
+ this.company = res;
+ this.setCompanyPlan(res.subscriptionLevel);
+ if (this.isCustomDomain) {
+ this.companyCustomDomainHostname = res.custom_domain;
+ } else {
+ this.getCompanyCustomDomain(res.id);
+ }
+ });
+
+ const castSub = this._company.cast.subscribe((arg) => {
+ if (arg === 'domain') {
+ this.getCompanyCustomDomain(this.company.id);
+ } else if (arg === 'updated-white-label-settings') {
+ this._company.getWhiteLabelProperties(this.company.id).subscribe();
+ }
+ });
+ this.subscriptions.push(castSub);
+ }
+
+ ngOnDestroy() {
+ this.subscriptions.forEach((sub) => sub.unsubscribe());
+ }
+
+ getCompanyCustomDomain(companyId: string) {
+ this._company.getCustomDomain(companyId).subscribe((res) => {
+ if (res.success) {
+ this.companyCustomDomain = res.domain_info;
+ this.companyCustomDomainHostname = res.domain_info.hostname;
+ this.companyCustomDomainThirdLevel = this.companyCustomDomainHostname.split('.')[0];
+ } else {
+ this.companyCustomDomain = {
+ id: null,
+ companyId: companyId,
+ hostname: '',
+ };
+ this.companyCustomDomainHostname = '';
+ this.companyCustomDomainPlaceholder = `${this.company.name.toLowerCase().replace(/[^a-z0-9]/g, '')}.example.com`;
+ this.companyCustomDomainThirdLevel = this.companyCustomDomainPlaceholder.split('.')[0];
+ }
+ });
+ }
+
+ setCompanyPlan(subscriptionLevel: string) {
+ if (subscriptionLevel) {
+ this.currentPlan = subscriptionLevel.slice(0, -5).toLowerCase();
+ } else {
+ this.currentPlan = 'free';
+ }
+ }
+
+ handleChangeCompanyDomain() {
+ this.submittingCustomDomain = true;
+ if (this.companyCustomDomain.id) {
+ this._company.updateCustomDomain(this.company.id, this.companyCustomDomain.id).subscribe(() => {
+ this.submittingCustomDomain = false;
+ this.angulartics2.eventTrack.next({
+ action: 'Company: domain is updated successfully',
+ });
+ posthog.capture('Company: domain is updated successfully');
+ });
+ } else {
+ this._company.createCustomDomain(this.company.id, this.companyCustomDomainHostname).subscribe(() => {
+ this.submittingCustomDomain = false;
+ this.angulartics2.eventTrack.next({
+ action: 'Company: domain is created successfully',
+ });
+ posthog.capture('Company: domain is created successfully');
+ });
+ }
+ }
+
+ handleDeleteDomainDialogOpen() {
+ this.dialog.open(DeleteDomainDialogComponent, {
+ width: '25em',
+ data: { companyId: this.company.id, domain: this.companyCustomDomainHostname },
+ });
+ }
+
+ onCompanyLogoSelected(event: any) {
+ this.submittingLogo = true;
+
+ const input = event.target as HTMLInputElement;
+ const file = input.files?.[0];
+ let companyLogoFile: File | null = null;
+
+ if (file) {
+ companyLogoFile = file;
+ } else {
+ companyLogoFile = null;
+ }
+
+ this._company.uploadLogo(this.company.id, companyLogoFile).subscribe(
+ (_res) => {
+ this.submittingLogo = false;
+ this.angulartics2.eventTrack.next({
+ action: 'Company: logo is uploaded successfully',
+ });
+ posthog.capture('Company: logo is uploaded successfully');
+ },
+ (_err) => {
+ this.submittingLogo = false;
+ },
+ );
+ }
+
+ removeLogo() {
+ this.submittingLogo = true;
+ this._company.removeLogo(this.company.id).subscribe(
+ (_res) => {
+ this.submittingLogo = false;
+ this.angulartics2.eventTrack.next({
+ action: 'Company: logo is removed successfully',
+ });
+ posthog.capture('Company: logo is removed successfully');
+ },
+ (_err) => {
+ this.submittingLogo = false;
+ },
+ );
+ }
+
+ onFaviconSelected(event: any) {
+ this.submittingFavicon = true;
+
+ const input = event.target as HTMLInputElement;
+ const file = input.files?.[0];
+ let faviconFile: File | null = null;
+
+ if (file) {
+ faviconFile = file;
+ } else {
+ faviconFile = null;
+ }
+
+ this._company.uploadFavicon(this.company.id, faviconFile).subscribe(
+ (_res) => {
+ this.submittingFavicon = false;
+ this.angulartics2.eventTrack.next({
+ action: 'Company: favicon is uploaded successfully',
+ });
+ posthog.capture('Company: favicon is uploaded successfully');
+ },
+ (_err) => {
+ this.submittingFavicon = false;
+ },
+ );
+ }
+
+ removeFavicon() {
+ this.submittingFavicon = true;
+ this._company.removeFavicon(this.company.id).subscribe(
+ (_res) => {
+ this.submittingFavicon = false;
+ this.angulartics2.eventTrack.next({
+ action: 'Company: favicon is removed successfully',
+ });
+ posthog.capture('Company: favicon is removed successfully');
+ },
+ (_err) => {
+ this.submittingFavicon = false;
+ },
+ );
+ }
+
+ updateTabTitle() {
+ this.submittingTabTitle = true;
+ this._company.updateTabTitle(this.company.id, this.companyTabTitle).subscribe(
+ () => {
+ this.submittingTabTitle = false;
+ this.angulartics2.eventTrack.next({
+ action: 'Company: tab title is updated successfully',
+ });
+ posthog.capture('Company: tab title is updated successfully');
+ },
+ (_err) => {
+ this.submittingTabTitle = false;
+ },
+ );
+ }
+
+ deleteTabTitle() {
+ this.submittingTabTitle = true;
+ this._company.removeTabTitle(this.company.id).subscribe(() => {
+ this.submittingTabTitle = false;
+ this.angulartics2.eventTrack.next({
+ action: 'Company: tab title is deleted successfully',
+ });
+ posthog.capture('Company: tab title is deleted successfully');
+ });
+ }
}
diff --git a/frontend/src/app/components/charts/chart-delete-dialog/chart-delete-dialog.component.ts b/frontend/src/app/components/charts/chart-delete-dialog/chart-delete-dialog.component.ts
index 40f2fdc51..98a5c4899 100644
--- a/frontend/src/app/components/charts/chart-delete-dialog/chart-delete-dialog.component.ts
+++ b/frontend/src/app/components/charts/chart-delete-dialog/chart-delete-dialog.component.ts
@@ -4,6 +4,7 @@ import { MatButtonModule } from '@angular/material/button';
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { MatIconModule } from '@angular/material/icon';
import { Angulartics2 } from 'angulartics2';
+import posthog from 'posthog-js';
import { SavedQuery } from 'src/app/models/saved-query';
import { SavedQueriesService } from 'src/app/services/saved-queries.service';
@@ -30,6 +31,7 @@ export class ChartDeleteDialogComponent {
this.angulartics2.eventTrack.next({
action: 'Charts: saved query deleted successfully',
});
+ posthog.capture('Charts: saved query deleted successfully');
this.submitting.set(false);
this.dialogRef.close(true);
},
diff --git a/frontend/src/app/components/charts/chart-edit/chart-edit.component.ts b/frontend/src/app/components/charts/chart-edit/chart-edit.component.ts
index 6cf393fbc..a6d5538ae 100644
--- a/frontend/src/app/components/charts/chart-edit/chart-edit.component.ts
+++ b/frontend/src/app/components/charts/chart-edit/chart-edit.component.ts
@@ -14,6 +14,7 @@ import { Title } from '@angular/platform-browser';
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
import { CodeEditorModule } from '@ngstack/code-editor';
import { Angulartics2 } from 'angulartics2';
+import posthog from 'posthog-js';
import { finalize } from 'rxjs/operators';
import { ChartType, TestQueryResult } from 'src/app/models/saved-query';
import { ConnectionsService } from 'src/app/services/connections.service';
@@ -206,6 +207,7 @@ export class ChartEditComponent implements OnInit {
this.angulartics2.eventTrack.next({
action: 'Charts: test query executed',
});
+ posthog.capture('Charts: test query executed');
}
saveQuery(): void {
@@ -246,6 +248,7 @@ export class ChartEditComponent implements OnInit {
this.angulartics2.eventTrack.next({
action: 'Charts: saved query updated',
});
+ posthog.capture('Charts: saved query updated');
} else {
this._savedQueries
.createSavedQuery(this.connectionId(), payload)
@@ -256,6 +259,7 @@ export class ChartEditComponent implements OnInit {
this.angulartics2.eventTrack.next({
action: 'Charts: saved query created',
});
+ posthog.capture('Charts: saved query created');
}
}
diff --git a/frontend/src/app/components/charts/charts-list/charts-list.component.ts b/frontend/src/app/components/charts/charts-list/charts-list.component.ts
index ce79515eb..f211fcaa3 100644
--- a/frontend/src/app/components/charts/charts-list/charts-list.component.ts
+++ b/frontend/src/app/components/charts/charts-list/charts-list.component.ts
@@ -4,25 +4,26 @@ import { toSignal } from '@angular/core/rxjs-interop';
import { FormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
-import { MatTableModule } from '@angular/material/table';
import { MatDialog } from '@angular/material/dialog';
import { MatDividerModule } from '@angular/material/divider';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatMenuModule } from '@angular/material/menu';
+import { MatTableModule } from '@angular/material/table';
import { MatTooltipModule } from '@angular/material/tooltip';
import { Title } from '@angular/platform-browser';
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
import { Angulartics2 } from 'angulartics2';
+import posthog from 'posthog-js';
import { ChartType, SavedQuery } from 'src/app/models/saved-query';
import { ConnectionsService } from 'src/app/services/connections.service';
import { SavedQueriesService } from 'src/app/services/saved-queries.service';
import { ChartMiniPreviewComponent } from '../../dashboards/chart-mini-preview/chart-mini-preview.component';
+import { DashboardsSidebarComponent } from '../../dashboards/dashboards-sidebar/dashboards-sidebar.component';
import { PlaceholderTableDataComponent } from '../../skeletons/placeholder-table-data/placeholder-table-data.component';
import { AlertComponent } from '../../ui-components/alert/alert.component';
import { ChartDeleteDialogComponent } from '../chart-delete-dialog/chart-delete-dialog.component';
-import { DashboardsSidebarComponent } from '../../dashboards/dashboards-sidebar/dashboards-sidebar.component';
@Component({
selector: 'app-charts-list',
@@ -123,12 +124,14 @@ export class ChartsListComponent implements OnInit {
this.angulartics2.eventTrack.next({
action: 'Charts: create chart page opened',
});
+ posthog.capture('Charts: create chart page opened');
}
trackEditPageOpened(): void {
this.angulartics2.eventTrack.next({
action: 'Charts: edit chart page opened',
});
+ posthog.capture('Charts: edit chart page opened');
}
openQuery(query: SavedQuery): void {
@@ -144,6 +147,7 @@ export class ChartsListComponent implements OnInit {
this.angulartics2.eventTrack.next({
action: 'Charts: delete chart dialog opened',
});
+ posthog.capture('Charts: delete chart dialog opened');
}
formatUpdatedAt(date: string): string {
diff --git a/frontend/src/app/components/company-member-invitation/company-member-invitation.component.ts b/frontend/src/app/components/company-member-invitation/company-member-invitation.component.ts
index 959cdb93e..04c6ba7db 100644
--- a/frontend/src/app/components/company-member-invitation/company-member-invitation.component.ts
+++ b/frontend/src/app/components/company-member-invitation/company-member-invitation.component.ts
@@ -1,81 +1,82 @@
-import { ActivatedRoute, ParamMap, Router } from '@angular/router';
-import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
+import { Component, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
+import { MatDividerModule } from '@angular/material/divider';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
-import { MatDividerModule } from '@angular/material/divider';
+import { ActivatedRoute, ParamMap, Router } from '@angular/router';
+import { Angulartics2 } from 'angulartics2';
+import posthog from 'posthog-js';
import { map } from 'rxjs/operators';
import { AuthService } from 'src/app/services/auth.service';
import { CompanyService } from 'src/app/services/company.service';
-import { Angulartics2 } from 'angulartics2';
import { PlaceholderCompanyInvitationComponent } from '../skeletons/placeholder-company-invitation/placeholder-company-invitation.component';
-import { BannerComponent } from '../ui-components/banner/banner.component';
import { AlertComponent } from '../ui-components/alert/alert.component';
+import { BannerComponent } from '../ui-components/banner/banner.component';
import { UserPasswordComponent } from '../ui-components/user-password/user-password.component';
@Component({
- selector: 'app-company-member-invitation',
- templateUrl: './company-member-invitation.component.html',
- styleUrls: ['./company-member-invitation.component.css'],
- imports: [
- CommonModule,
- FormsModule,
- MatButtonModule,
- MatFormFieldModule,
- MatInputModule,
- MatDividerModule,
- PlaceholderCompanyInvitationComponent,
- BannerComponent,
- AlertComponent,
- UserPasswordComponent
- ]
+ selector: 'app-company-member-invitation',
+ templateUrl: './company-member-invitation.component.html',
+ styleUrls: ['./company-member-invitation.component.css'],
+ imports: [
+ CommonModule,
+ FormsModule,
+ MatButtonModule,
+ MatFormFieldModule,
+ MatInputModule,
+ MatDividerModule,
+ PlaceholderCompanyInvitationComponent,
+ BannerComponent,
+ AlertComponent,
+ UserPasswordComponent,
+ ],
})
export class CompanyMemberInvitationComponent implements OnInit {
+ public token: string;
+ public companyName: string = null;
+ public password: string = '';
+ public userName: string;
+ public submitting: boolean;
+ public checkingLink: boolean = true;
+ public isLinkAvailable: boolean = false;
- public token: string;
- public companyName: string = null;
- public password: string = '';
- public userName: string;
- public submitting: boolean;
- public checkingLink: boolean = true;
- public isLinkAvailable: boolean = false;
-
- constructor(
- private _auth: AuthService,
- private _company: CompanyService,
- private router: Router,
- private route: ActivatedRoute,
- private angulartics2: Angulartics2,
- ) {}
-
- ngOnInit(): void {
- this.route.paramMap
- .pipe(
- map((params: ParamMap) => {
- this.token = params.get('verification-token');
- const companyId = params.get('company-id');
- this._company.fetchCompanyName(companyId).subscribe(res => this.companyName = res.name);
- this._auth.checkInvitationAvailability(this.token).subscribe(res => {
- this.isLinkAvailable = res.success;
- this.checkingLink = false;
- })
- })
- ).subscribe();
- }
+ constructor(
+ private _auth: AuthService,
+ private _company: CompanyService,
+ private router: Router,
+ private route: ActivatedRoute,
+ private angulartics2: Angulartics2,
+ ) {}
- updatePasswordField(updatedValue: string) {
- this.password = updatedValue;
- }
+ ngOnInit(): void {
+ this.route.paramMap
+ .pipe(
+ map((params: ParamMap) => {
+ this.token = params.get('verification-token');
+ const companyId = params.get('company-id');
+ this._company.fetchCompanyName(companyId).subscribe((res) => (this.companyName = res.name));
+ this._auth.checkInvitationAvailability(this.token).subscribe((res) => {
+ this.isLinkAvailable = res.success;
+ this.checkingLink = false;
+ });
+ }),
+ )
+ .subscribe();
+ }
- acceptInvitation() {
- this._auth.acceptCompanyInvitation(this.token, this.password, this.userName).subscribe(() => {
- this.angulartics2.eventTrack.next({
- action: 'Company invitation: invitation is accepted successfully',
- });
- this.router.navigate(['/connections-list'])
- })
- }
+ updatePasswordField(updatedValue: string) {
+ this.password = updatedValue;
+ }
+ acceptInvitation() {
+ this._auth.acceptCompanyInvitation(this.token, this.password, this.userName).subscribe(() => {
+ this.angulartics2.eventTrack.next({
+ action: 'Company invitation: invitation is accepted successfully',
+ });
+ posthog.capture('Company invitation: invitation is accepted successfully');
+ this.router.navigate(['/connections-list']);
+ });
+ }
}
diff --git a/frontend/src/app/components/company/company.component.html b/frontend/src/app/components/company/company.component.html
index b9d84b6e8..8940685a8 100644
--- a/frontend/src/app/components/company/company.component.html
+++ b/frontend/src/app/components/company/company.component.html
@@ -21,6 +21,7 @@
@@ -163,6 +167,7 @@