Skip to content

Commit

Permalink
feat: Timezone fix final final (#3027)
Browse files Browse the repository at this point in the history
* Added changes

* Added new changes

* Added changes

* Added more changes

* Added more changes

* Added newer changes

* added newer fixes

* Added a new change

---------

Co-authored-by: julias0 <[email protected]>
  • Loading branch information
Julias0 and Julias0 authored May 29, 2024
1 parent 28abe7f commit 1e5640c
Show file tree
Hide file tree
Showing 13 changed files with 370 additions and 117 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@
"test": "ng test --watch=false --browsers=ChromeHeadless",
"test-basic": "ng test",
"test:no-parallel": "ng test",
"lint": "ng lint",
"lint": "eslint -c .eslintrc.json",
"e2e": "ng e2e",
"postinstall": "npx jetify",
"format:check": "prettier --write ./src",
"prepare": "husky install",
"lint:diff": "eslint -c .eslintrc.json $(git diff --name-only --diff-filter=ACMRTUXB origin/$GITHUB_BASE_REF | grep -E \"(.js$|.ts$|.tsx$)\")"
"lint:diff": "eslint -c .eslintrc.json $(git diff --name-only --diff-filter=ACMRTUXB origin/$GITHUB_BASE_REF | grep -E \"(.js$|.ts$|.tsx$)\")",
"lint:diff:local": "eslint --fix -c .eslintrc.json $(git diff --name-only --diff-filter=ACMRTUXB origin/master | grep -E '(.js$|.ts$|.tsx$)')"
},
"resolutions": {
"webpack": "^5.0.0"
Expand Down
18 changes: 13 additions & 5 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Component, OnInit, EventEmitter, NgZone, ViewChild } from '@angular/core';
import { Platform, MenuController, NavController } from '@ionic/angular';
import { from, concat, Observable, noop } from 'rxjs';
import { switchMap, shareReplay, filter } from 'rxjs/operators';
import { from, concat, Observable, noop, forkJoin } from 'rxjs';
import { switchMap, shareReplay, filter, take } from 'rxjs/operators';
import { Router, NavigationEnd, NavigationStart } from '@angular/router';
import { AuthService } from 'src/app/core/services/auth.service';
import { UserEventService } from 'src/app/core/services/user-event.service';
Expand Down Expand Up @@ -104,6 +104,7 @@ export class AppComponent implements OnInit {
await StatusBar.setStyle({
style: Style.Default,
});

setTimeout(async () => await SplashScreen.hide(), 1000);

/*
Expand Down Expand Up @@ -147,8 +148,12 @@ export class AppComponent implements OnInit {
ngOnInit(): void {
this.setupNetworkWatcher();

// This was done as a security fix for appknox
// eslint-disable-next-line
if ((window as any) && (window as any).localStorage) {
const lstorage = (window as any).localStorage;
// eslint-disable-next-line
const lstorage = (window as any).localStorage as { removeItem: (key: string) => void };
// eslint-disable-next-line
Object.keys(lstorage)
.filter((key) => key.match(/^fyle/))
.forEach((key) => lstorage.removeItem(key));
Expand All @@ -158,10 +163,13 @@ export class AppComponent implements OnInit {
this.isOnline = isOnline;
});

from(this.routerAuthService.isLoggedIn()).subscribe((loggedInStatus) => {
forkJoin({
loggedInStatus: this.routerAuthService.isLoggedIn(),
isOnline: this.isConnected$.pipe(take(1)),
}).subscribe(({ loggedInStatus, isOnline }) => {
this.isUserLoggedIn = loggedInStatus;
if (loggedInStatus) {
if (this.isOnline) {
if (isOnline) {
this.sidemenuRef.showSideMenuOnline();
} else {
this.sidemenuRef.showSideMenuOffline();
Expand Down
78 changes: 41 additions & 37 deletions src/app/auth/switch-org/switch-org.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import { ResendEmailVerification } from 'src/app/core/models/resend-email-verifi
import { RouterAuthService } from 'src/app/core/services/router-auth.service';
import { TransactionService } from 'src/app/core/services/transaction.service';
import { DeepLinkService } from 'src/app/core/services/deep-link.service';
import { UnflattenedTransaction } from 'src/app/core/models/unflattened-transaction.model';
import { ExpensesService } from 'src/app/core/services/platform/v1/spender/expenses.service';

@Component({
Expand All @@ -38,11 +37,11 @@ import { ExpensesService } from 'src/app/core/services/platform/v1/spender/expen
styleUrls: ['./switch-org.page.scss'],
})
export class SwitchOrgPage implements OnInit, AfterViewChecked {
@ViewChild('search') searchRef: ElementRef;
@ViewChild('search') searchRef: ElementRef<HTMLElement>;

@ViewChild('content') contentRef: ElementRef;
@ViewChild('content') contentRef: ElementRef<HTMLElement>;

@ViewChild('searchOrgsInput') searchOrgsInput: ElementRef;
@ViewChild('searchOrgsInput') searchOrgsInput: ElementRef<HTMLInputElement>;

orgs$: Observable<Org[]>;

Expand Down Expand Up @@ -88,15 +87,15 @@ export class SwitchOrgPage implements OnInit, AfterViewChecked {
private expensesService: ExpensesService
) {}

ngOnInit() {
ngOnInit(): void {
this.isIos = this.platform.is('ios');
}

ngAfterViewChecked() {
ngAfterViewChecked(): void {
this.cdRef.detectChanges();
}

ionViewWillEnter() {
ionViewWillEnter(): void {
const that = this;
that.searchInput = '';
that.isLoading = true;
Expand All @@ -108,11 +107,14 @@ export class SwitchOrgPage implements OnInit, AfterViewChecked {
that.cdRef.detectChanges();
});

const choose = that.activatedRoute.snapshot.params.choose && JSON.parse(that.activatedRoute.snapshot.params.choose);
const choose =
that.activatedRoute.snapshot.params.choose &&
(JSON.parse(that.activatedRoute.snapshot.params.choose as string) as boolean);
const isFromInviteLink: boolean =
that.activatedRoute.snapshot.params.invite_link && JSON.parse(that.activatedRoute.snapshot.params.invite_link);
const orgId = that.activatedRoute.snapshot.params.orgId;
const txnId = this.activatedRoute.snapshot.params.txnId;
that.activatedRoute.snapshot.params.invite_link &&
(JSON.parse(that.activatedRoute.snapshot.params.invite_link as string) as boolean);
const orgId = that.activatedRoute.snapshot.params.orgId as string;
const txnId = this.activatedRoute.snapshot.params.txnId as string;

if (orgId && txnId) {
return this.redirectToExpensePage(orgId, txnId);
Expand Down Expand Up @@ -148,15 +150,16 @@ export class SwitchOrgPage implements OnInit, AfterViewChecked {
this.trackSwitchOrgLaunchTime();
});

this.filteredOrgs$ = fromEvent(this.searchOrgsInput.nativeElement, 'keyup').pipe(
map((event: any) => event.srcElement.value),
// eslint-disable-next-line
this.filteredOrgs$ = fromEvent<{ srcElement: { value: string } }>(this.searchOrgsInput.nativeElement, 'keyup').pipe(
map((event) => event.srcElement.value),
startWith(''),
distinctUntilChanged(),
switchMap((searchText) => currentOrgs$.pipe(map((orgs) => this.getOrgsWhichContainSearchText(orgs, searchText))))
);
}

setSentryUser(eou: ExtendedOrgUser) {
setSentryUser(eou: ExtendedOrgUser): void {
if (eou) {
Sentry.setUser({
id: eou.us.email + ' - ' + eou.ou.id,
Expand All @@ -170,7 +173,7 @@ export class SwitchOrgPage implements OnInit, AfterViewChecked {
return this.routerAuthService.resendVerificationLink(email, orgId);
}

showToastNotification(msg: string) {
showToastNotification(msg: string): void {
const toastMessageData = {
message: msg,
};
Expand All @@ -182,7 +185,7 @@ export class SwitchOrgPage implements OnInit, AfterViewChecked {
this.trackingService.showToastMessage({ ToastContent: toastMessageData.message });
}

redirectToExpensePage(orgId: string, txnId: string) {
redirectToExpensePage(orgId: string, txnId: string): void {
from(this.loaderService.showLoader())
.pipe(
switchMap(() => this.orgService.switchOrg(orgId)),
Expand All @@ -208,7 +211,7 @@ export class SwitchOrgPage implements OnInit, AfterViewChecked {
});
}

logoutIfSingleOrg(orgs: Org[]) {
logoutIfSingleOrg(orgs: Org[]): void {
/*
* Case: When a user is added to an SSO org but hasn't verified their account through the link.
* After showing the alert, the user will be redirected to the sign-in page since there is no other org they are a part of.
Expand All @@ -219,12 +222,12 @@ export class SwitchOrgPage implements OnInit, AfterViewChecked {
}
}

handleDismissPopup(action = 'cancel', email: string, orgId: string, orgs: Org[]) {
handleDismissPopup(action = 'cancel', email: string, orgId: string, orgs: Org[]): void {
if (action === 'resend') {
// If user clicks on resend Button, Resend Invite to the user and then logout if user have only one org.
this.resendInvite(email, orgId)
.pipe(
catchError((error) => {
catchError((error: Error) => {
this.showToastNotification('Verification link could not be sent. Please try again!');
return throwError(() => error);
})
Expand All @@ -238,7 +241,7 @@ export class SwitchOrgPage implements OnInit, AfterViewChecked {
}
}

async showEmailNotVerifiedAlert() {
async showEmailNotVerifiedAlert(): Promise<void> {
const eou$ = from(this.authService.getEou());
forkJoin({
eou: eou$,
Expand Down Expand Up @@ -266,13 +269,13 @@ export class SwitchOrgPage implements OnInit, AfterViewChecked {
});
await popover.present();

const { data } = await popover.onWillDismiss();
const { data } = await popover.onWillDismiss<{ action: string }>();

this.handleDismissPopup(data?.action, email, orgId, orgs);
});
}

navigateToSetupPage(roles: string[]) {
navigateToSetupPage(roles: string[]): void {
if (roles.includes('OWNER')) {
this.router.navigate(['/', 'post_verification', 'setup_account']);
} else {
Expand Down Expand Up @@ -338,7 +341,7 @@ export class SwitchOrgPage implements OnInit, AfterViewChecked {
return of(null);
}

async proceed(isFromInviteLink?: boolean) {
async proceed(isFromInviteLink?: boolean): Promise<void> {
const pendingDetails$ = this.userService.isPendingDetails().pipe(shareReplay(1));
const eou$ = from(this.authService.getEou());
const roles$ = from(this.authService.getRoles().pipe(shareReplay(1)));
Expand All @@ -356,7 +359,7 @@ export class SwitchOrgPage implements OnInit, AfterViewChecked {
this.checkUserAppVersion();
}

checkUserAppVersion() {
checkUserAppVersion(): void {
this.deviceService
.getDeviceInfo()
.pipe(
Expand All @@ -378,7 +381,7 @@ export class SwitchOrgPage implements OnInit, AfterViewChecked {
});
}

trackSwitchOrg(org: Org, originalEou) {
trackSwitchOrg(org: Org, originalEou: ExtendedOrgUser): void {
const isDestinationOrgActive = originalEou.ou && originalEou.ou.org_id === org.id;
const isCurrentOrgPrimary = originalEou.ou && originalEou.ou.is_primary;
from(this.authService.getEou()).subscribe((currentEou) => {
Expand All @@ -398,7 +401,7 @@ export class SwitchOrgPage implements OnInit, AfterViewChecked {
});
}

async switchOrg(org: Org) {
async switchOrg(org: Org): Promise<void> {
// Tracking the time on click of switch org
performance.mark(PerfTrackers.onClickSwitchOrg);
const originalEou = await this.authService.getEou();
Expand All @@ -414,7 +417,7 @@ export class SwitchOrgPage implements OnInit, AfterViewChecked {
this.recentLocalStorageItemsService.clearRecentLocalStorageCache();
from(this.proceed()).subscribe(noop);
},
async (err) => {
async () => {
await this.secureStorageService.clearAll();
await this.storageService.clearAll();
this.userEventService.logout();
Expand All @@ -424,7 +427,7 @@ export class SwitchOrgPage implements OnInit, AfterViewChecked {
);
}

signOut() {
signOut(): void {
try {
forkJoin({
device: this.deviceService.getDeviceInfo(),
Expand Down Expand Up @@ -452,36 +455,36 @@ export class SwitchOrgPage implements OnInit, AfterViewChecked {
}
}

getOrgsWhichContainSearchText(orgs: Org[], searchText: string) {
getOrgsWhichContainSearchText(orgs: Org[], searchText: string): Org[] {
return orgs.filter((org) =>
Object.values(org)
.map((value) => value && value.toString().toLowerCase())
.map((value: string | Date | number | boolean) => value && value.toString().toLowerCase())
.filter((value) => !!value)
.some((value) => value.toLowerCase().includes(searchText.toLowerCase()))
);
}

resetSearch() {
resetSearch(): void {
this.searchInput = '';
const searchInputElement = this.searchOrgsInput.nativeElement as HTMLInputElement;
const searchInputElement = this.searchOrgsInput.nativeElement;
searchInputElement.value = '';
searchInputElement.dispatchEvent(new Event('keyup'));
}

openSearchBar() {
openSearchBar(): void {
this.contentRef.nativeElement.classList.add('switch-org__content-container__content-block--hide');
this.searchRef.nativeElement.classList.add('switch-org__content-container__search-block--show');
setTimeout(() => this.searchOrgsInput.nativeElement.focus(), 200);
}

cancelSearch() {
cancelSearch(): void {
this.resetSearch();
this.searchOrgsInput.nativeElement.blur();
this.contentRef.nativeElement.classList.remove('switch-org__content-container__content-block--hide');
this.searchRef.nativeElement.classList.remove('switch-org__content-container__search-block--show');
}

trackSwitchOrgLaunchTime() {
trackSwitchOrgLaunchTime(): void {
try {
if (performance.getEntriesByName('switch org launch time').length === 0) {
// Time taken to land on switch org page after sign-in
Expand All @@ -492,17 +495,18 @@ export class SwitchOrgPage implements OnInit, AfterViewChecked {

const measureLaunchTime = performance.getEntriesByName('switch org launch time');

// eslint-disable-next-line @typescript-eslint/dot-notation
// eslint-disable-next-line
const loginMethod = performance.getEntriesByName('login start time')[0]['detail'];

// Converting the duration to seconds and fix it to 3 decimal places
const launchTimeDuration = (measureLaunchTime[0]?.duration / 1000)?.toFixed(3);

this.trackingService.switchOrgLaunchTime({
'Switch org launch time': launchTimeDuration,
// eslint-disable-next-line
'Login method': loginMethod,
});
}
} catch (error) {}
} catch (_) {}
}
}
Loading

0 comments on commit 1e5640c

Please sign in to comment.