Skip to content

Commit

Permalink
feat: Added deep link redirection support for sms opt in (#3162)
Browse files Browse the repository at this point in the history
  • Loading branch information
arjunaj5 committed Aug 7, 2024
1 parent a9af115 commit 7de5ce5
Show file tree
Hide file tree
Showing 7 changed files with 194 additions and 2 deletions.
34 changes: 34 additions & 0 deletions src/app/auth/switch-org/switch-org.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,12 @@ export class SwitchOrgPage implements OnInit, AfterViewChecked {
(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;
const openSMSOptInDialog = this.activatedRoute.snapshot.params.openSMSOptInDialog as string;

if (orgId && txnId) {
return this.redirectToExpensePage(orgId, txnId);
} else if (openSMSOptInDialog === 'true' && orgId) {
return this.redirectToDashboard(orgId);
} else if (!choose) {
from(that.loaderService.showLoader())
.pipe(switchMap(() => from(that.proceed(isFromInviteLink))))
Expand All @@ -133,6 +136,7 @@ export class SwitchOrgPage implements OnInit, AfterViewChecked {
}
});
}

this.activeOrg$ = this.orgService.getCurrentOrg();
this.primaryOrg$ = this.orgService.getPrimaryOrg();

Expand Down Expand Up @@ -187,6 +191,36 @@ export class SwitchOrgPage implements OnInit, AfterViewChecked {
this.trackingService.showToastMessage({ ToastContent: toastMessageData.message });
}

redirectToDashboard(orgId: string): void {
from(this.loaderService.showLoader('Please wait...', 2000))
.pipe(
switchMap(() => this.orgService.switchOrg(orgId)),
switchMap(() => {
globalCacheBusterNotifier.next();
this.userEventService.clearTaskCache();
this.recentLocalStorageItemsService.clearRecentLocalStorageCache();
return from(this.authService.getEou());
}),
map((eou) => {
this.setSentryUser(eou);
}),
finalize(() => this.loaderService.hideLoader())
)
.subscribe({
next: () => {
this.router.navigate([
'/',
'enterprise',
'my_dashboard',
{
openSMSOptInDialog: true,
},
]);
},
error: () => this.router.navigate(['/', 'auth', 'switch_org']),
});
}

redirectToExpensePage(orgId: string, txnId: string): void {
from(this.loaderService.showLoader())
.pipe(
Expand Down
21 changes: 21 additions & 0 deletions src/app/core/services/deep-link.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,27 @@ describe('DeepLinkService', () => {
]);
});

it('should navigate to the dashboard when the URI contains "/my_dashboard" along with advance request ID', () => {
const orgId = 'oroX1Q9TTEO';
const referrer = 'transactional_email';
const openSMSOptInDialog = true;

deepLinkService.redirect({
redirect_uri: `${baseURL}/my_dashboard?org_id=${orgId}&open_sms_dialog=${openSMSOptInDialog}&referrer=${referrer}`,
});

expect(router.navigate).toHaveBeenCalledOnceWith([
'/',
'deep_link_redirection',
{
sub_module: 'my_dashboard',
openSMSOptInDialog,
orgId,
referrer,
},
]);
});

it('should redirect to deep link redirection page with correct orgId and txnId', () => {
deepLinkService.redirect({
redirect_uri: `${baseURL}/orOTDe765hQp/txMLI4Cc5zY5`,
Expand Down
13 changes: 13 additions & 0 deletions src/app/core/services/deep-link.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,19 @@ export class DeepLinkService {
orgId,
txnId,
});
} else if (redirectUri.match('my_dashboard')) {
// https://staging1.fyle.tech/app/main/#/my_dashboard?org_id=oroX1Q9TTEOg&open_sms_dialog=true&referrer=transactional_email
const referrer = redirectUri.match(/referrer=(\w+)/)?.[1];
const orgId = redirectUri.match(/org_id=(\w+)/)?.[1];
const openSMSOptInDialog = redirectUri.includes('open_sms_dialog=true');
const properties = {
sub_module: 'my_dashboard',
openSMSOptInDialog,
orgId,
referrer,
};
this.trackingService.smsDeepLinkOpened(properties);
this.router.navigate(['/', 'deep_link_redirection', properties]);
} else {
this.router.navigate(['/', 'auth', 'switch_org', { choose: true }]);
}
Expand Down
13 changes: 13 additions & 0 deletions src/app/deep-link-redirection/deep-link-redirection.page.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,19 @@ describe('DeepLinkRedirectionPage', () => {
tick(500);
expect(component.redirectToAdvReqModule).toHaveBeenCalledTimes(1);
}));

it('should call redirectToDashboardModule() if the sub_module is my_dashboard', fakeAsync(() => {
activeroutemock.snapshot.params = {
sub_module: 'my_dashboard',
orgId: 'oroX1Q9TTEO',
referrer: 'transactional_email',
};
spyOn(component, 'redirectToDashboardModule').and.stub();
component.ionViewWillEnter();
fixture.detectChanges();
tick(500);
expect(component.redirectToDashboardModule).toHaveBeenCalledTimes(1);
}));
});

it('should call switchOrg method of authService', () => {
Expand Down
57 changes: 57 additions & 0 deletions src/app/deep-link-redirection/deep-link-redirection.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,66 @@ export class DeepLinkRedirectionPage {
this.redirectToExpenseModule();
} else if (subModule === 'advReq') {
this.redirectToAdvReqModule();
} else if (subModule === 'my_dashboard') {
this.redirectToDashboardModule();
}
}

async redirectToDashboardModule(): Promise<void> {
const openSMSOptInDialog = this.activatedRoute.snapshot.params.openSMSOptInDialog as string;
const orgId = this.activatedRoute.snapshot.params.orgId as string;

const eou$ = from(this.loaderService.showLoader('Loading....')).pipe(
switchMap(() => from(this.authService.getEou())),
catchError(() => {
this.switchOrg();
return EMPTY;
}),
shareReplay(1)
);

// If orgId is the same as the current user orgId, then redirect to the dashboard page
eou$
.pipe(
filter((eou) => orgId === eou.ou.org_id),
finalize(() => from(this.loaderService.hideLoader()))
)
.subscribe({
next: () => {
this.router.navigate([
'/',
'enterprise',
'my_dashboard',
{
openSMSOptInDialog,
},
]);
},
error: () => this.switchOrg(),
});

// If orgId is the diferent from the current user orgId, then redirect to switch org with orgId and openSMSOptInDialog
eou$
.pipe(
filter((eou) => orgId !== eou.ou.org_id),
finalize(() => from(this.loaderService.hideLoader()))
)
.subscribe({
next: () => {
this.router.navigate([
'/',
'auth',
'switch_org',
{
openSMSOptInDialog,
orgId,
},
]);
},
error: () => this.switchOrg(),
});
}

async redirectToAdvReqModule(): Promise<void> {
await this.loaderService.showLoader('Loading....');
const currentEou = await this.authService.getEou();
Expand Down
13 changes: 13 additions & 0 deletions src/app/fyle/dashboard/dashboard.page.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import { AuthService } from 'src/app/core/services/auth.service';
import { apiEouRes } from 'src/app/core/mock-data/extended-org-user.data';
import { properties } from 'src/app/core/mock-data/modal-properties.data';
import { featureConfigOptInData } from 'src/app/core/mock-data/feature-config.data';
import { MatSnackBar } from '@angular/material/snack-bar';
import { SnackbarPropertiesService } from 'src/app/core/services/snackbar-properties.service';

describe('DashboardPage', () => {
let component: DashboardPage;
Expand Down Expand Up @@ -94,6 +96,8 @@ describe('DashboardPage', () => {
const modalPropertiesSpy = jasmine.createSpyObj('ModalPropertiesService', ['getModalDefaultProperties']);
const authServiceSpy = jasmine.createSpyObj('AuthService', ['getEou', 'refreshEou']);
const modalControllerSpy = jasmine.createSpyObj('ModalController', ['create']);
const matSnackBarSpy = jasmine.createSpyObj('MatSnackBar', ['openFromComponent']);
const snackbarPropertiesSpy = jasmine.createSpyObj('SnackbarPropertiesService', ['setSnackbarProperties']);

TestBed.configureTestingModule({
declarations: [DashboardPage],
Expand All @@ -119,6 +123,7 @@ describe('DashboardPage', () => {
queryParams: {
state: 'tasks',
},
params: {},
},
},
},
Expand All @@ -127,6 +132,14 @@ describe('DashboardPage', () => {
{ provide: ModalPropertiesService, useValue: modalPropertiesSpy },
{ provide: AuthService, useValue: authServiceSpy },
{ provide: ModalController, useValue: modalControllerSpy },
{
provide: MatSnackBar,
useValue: matSnackBarSpy,
},
{
provide: SnackbarPropertiesService,
useValue: snackbarPropertiesSpy,
},
],
schemas: [NO_ERRORS_SCHEMA],
}).compileComponents();
Expand Down
45 changes: 43 additions & 2 deletions src/app/fyle/dashboard/dashboard.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ import { PromoteOptInModalComponent } from 'src/app/shared/components/promote-op
import { AuthService } from 'src/app/core/services/auth.service';
import { ExtendedOrgUser } from 'src/app/core/models/extended-org-user.model';
import { DashboardState } from 'src/app/core/enums/dashboard-state.enum';
import { FyOptInComponent } from 'src/app/shared/components/fy-opt-in/fy-opt-in.component';
import { MatSnackBar } from '@angular/material/snack-bar';
import { ToastMessageComponent } from 'src/app/shared/components/toast-message/toast-message.component';
import { SnackbarPropertiesService } from 'src/app/core/services/snackbar-properties.service';

@Component({
selector: 'app-dashboard',
Expand Down Expand Up @@ -90,7 +94,9 @@ export class DashboardPage {
private utilityService: UtilityService,
private featureConfigService: FeatureConfigService,
private modalProperties: ModalPropertiesService,
private authService: AuthService
private authService: AuthService,
private matSnackBar: MatSnackBar,
private snackbarProperties: SnackbarPropertiesService
) {}

get displayedTaskCount(): number {
Expand Down Expand Up @@ -153,6 +159,26 @@ export class DashboardPage {
);
}

async openSMSOptInDialog(extendedOrgUser: ExtendedOrgUser): Promise<void> {
const optInModal = await this.modalController.create({
component: FyOptInComponent,
componentProps: {
extendedOrgUser,
},
});

return await optInModal.present();
}

showInfoToastMessage(message: string): void {
const panelClass = 'msb-info';
this.matSnackBar.openFromComponent(ToastMessageComponent, {
...this.snackbarProperties.setSnackbarProperties('information', { message }),
panelClass,
});
this.trackingService.showToastMessage({ ToastContent: message });
}

ionViewWillEnter(): void {
this.setupNetworkWatcher();
this.registerBackButtonAction();
Expand All @@ -170,11 +196,26 @@ export class DashboardPage {
this.orgSettings$ = this.orgSettingsService.get().pipe(shareReplay(1));
this.specialCategories$ = this.categoriesService.getMileageOrPerDiemCategories().pipe(shareReplay(1));
this.homeCurrency$ = this.currencyService.getHomeCurrency().pipe(shareReplay(1));
this.eou$ = from(this.authService.getEou());
this.eou$ = from(this.authService.getEou()).pipe(shareReplay(1));
this.isUserFromINCluster$ = from(this.utilityService.isUserFromINCluster());

this.setShowOptInBanner();

const openSMSOptInDialog = this.activatedRoute.snapshot.params.openSMSOptInDialog as string;
if (openSMSOptInDialog === 'true') {
this.eou$
.pipe(
map((eou) => {
if (eou.ou.mobile_verified) {
this.showInfoToastMessage('You are already opted into text messaging!');
} else {
this.openSMSOptInDialog(eou);
}
})
)
.subscribe();
}

forkJoin({
orgSettings: this.orgSettings$,
specialCategories: this.specialCategories$,
Expand Down

0 comments on commit 7de5ce5

Please sign in to comment.