File

src/app/profile-settings/profile-settings.page.ts

Implements

OnInit OnDestroy AfterViewInit

Metadata

Index

Properties
Methods
Accessors

Constructor

constructor(profileService: ProfileService, frameworkService: FrameworkService, frameworkUtilService: FrameworkUtilService, formAndFrameworkUtilService: FormAndFrameworkUtilService, translate: TranslateService, telemetryGeneratorService: TelemetryGeneratorService, appGlobalService: AppGlobalService, events: Events, scanner: SunbirdQRScanner, platform: Platform, commonUtilService: CommonUtilService, container: ContainerService, headerService: AppHeaderService, router: Router, appVersion: AppVersion, alertCtrl: AlertController, location: Location, splashScreenService: SplashScreenService, activatedRoute: ActivatedRoute, profileHandler: ProfileHandler, segmentationTagService: SegmentationTagService, onboardingConfigurationService: OnboardingConfigurationService)
Parameters :
Name Type Optional
profileService ProfileService No
frameworkService FrameworkService No
frameworkUtilService FrameworkUtilService No
formAndFrameworkUtilService FormAndFrameworkUtilService No
translate TranslateService No
telemetryGeneratorService TelemetryGeneratorService No
appGlobalService AppGlobalService No
events Events No
scanner SunbirdQRScanner No
platform Platform No
commonUtilService CommonUtilService No
container ContainerService No
headerService AppHeaderService No
router Router No
appVersion AppVersion No
alertCtrl AlertController No
location Location No
splashScreenService SplashScreenService No
activatedRoute ActivatedRoute No
profileHandler ProfileHandler No
segmentationTagService SegmentationTagService No
onboardingConfigurationService OnboardingConfigurationService No

Methods

Private addAttributeSubscription
addAttributeSubscription()
Returns : void
boardClicked
boardClicked(e?: Event)
Parameters :
Name Type Optional
e Event Yes
Returns : void
cancelEvent
cancelEvent(category?: string)
Parameters :
Name Type Optional
category string Yes
Returns : void
Async dismissPopup
dismissPopup()
Returns : any
extractProfileForTelemetry
extractProfileForTelemetry(formVal)
Parameters :
Name Optional
formVal No
Returns : any
Async fetchSyllabusList
fetchSyllabusList()
Returns : any
generateCategorySubmitTelemetry
generateCategorySubmitTelemetry(category: string)
Parameters :
Name Type Optional
category string No
Returns : void
Private getCategoriesAndUpdateAttributes
getCategoriesAndUpdateAttributes()
Returns : void
handleActiveScanner
handleActiveScanner()
Returns : void
handleBackButton
handleBackButton(isNavBack)
Parameters :
Name Optional
isNavBack No
Returns : void
handleDeviceBackButton
handleDeviceBackButton()
Returns : void
handleHeaderEvents
handleHeaderEvents($event)
Parameters :
Name Optional
$event No
Returns : void
hideOnboardingSplashScreen
hideOnboardingSplashScreen()
Returns : void
ionViewDidEnter
ionViewDidEnter()
Returns : void
ionViewWillEnter
ionViewWillEnter()
Returns : void
ionViewWillLeave
ionViewWillLeave()
Returns : void
ngAfterViewInit
ngAfterViewInit()
Returns : void
ngOnDestroy
ngOnDestroy()
Returns : void
Async ngOnInit
ngOnInit()
Returns : any
onCategoryCliked
onCategoryCliked(category: string)
Parameters :
Name Type Optional
category string No
Returns : void
Private onGradeChange
onGradeChange()
Returns : Observable<string[]>
Private onMediumChange
onMediumChange()
Returns : Observable<string[]>
onSubmitAttempt
onSubmitAttempt()
Returns : void
Private onSyllabusChange
onSyllabusChange()
Returns : Observable<string[]>
openQRScanner
openQRScanner()
Returns : void
Private populateCData
populateCData(formControllerValues, correlationType)
Parameters :
Name Optional
formControllerValues No
correlationType No
Returns : Array<CorrelationData>
Private redirectToInitialRoute
redirectToInitialRoute()
Returns : void
Private resetProfileSettingsForm
resetProfileSettingsForm()
Returns : void
Public setAriaLabel
setAriaLabel()
Returns : void
Private Async submitProfileSettingsForm
submitProfileSettingsForm()
Returns : any
Private updateAttributeStreamsnSetValidators
updateAttributeStreamsnSetValidators(attributes: literal type)
Parameters :
Name Type Optional
attributes literal type No
Returns : Array<any>

Properties

Private Optional activeSessionProfile
Type : Profile
animatedQRImageRef
Type : ElementRef
Decorators :
@ViewChild('animatedQRImage', {static: false})
appName
Type : string
boardOptions
Type : object
Default value : { title: this.commonUtilService.translateMessage('BOARD_OPTION_TEXT'), cssClass: 'ftue-changes' }
boardSelect
Type : any
Decorators :
@ViewChild('boardSelect', {static: false})
btnColor
Type : string
Default value : '#8FC4FF'
categories
Type : []
Default value : []
classOptions
Type : object
Default value : { title: this.commonUtilService.translateMessage('GRADE_OPTION_TEXT'), cssClass: 'select-box' }
Private formControlSubscriptions
Type : Subscription
Private framework
Type : Framework
Public gradeList
Type : literal type[]
Default value : []
gradeSelect
Type : any
Decorators :
@ViewChild('gradeSelect', {static: false})
Private headerObservable
Type : any
Public hideBackButton
Default value : true
isInitialScreen
Default value : false
loader
Type : any
Public mediumList
Type : literal type[]
Default value : []
mediumOptions
Type : object
Default value : { title: this.commonUtilService.translateMessage('MEDIUM_OPTION_TEXT'), cssClass: 'select-box' }
mediumSelect
Type : any
Decorators :
@ViewChild('mediumSelect', {static: false})
Private navParams
Type : any
Public pageId
Type : string
Default value : 'ProfileSettingsPage'
Public platform
Type : Platform
Public profileSettingsForm
Type : FormGroup
showQRScanner
Default value : true
Public supportedProfileAttributes
Type : literal type
Default value : {}
Public syllabusList
Type : literal type[]
Default value : []
Private unregisterBackButton
Type : Subscription

Accessors

syllabusControl
getsyllabusControl()
boardControl
getboardControl()
mediumControl
getmediumControl()
gradeControl
getgradeControl()
import { FormAndFrameworkUtilService } from './../../services/formandframeworkutil.service';
import { AfterViewInit, Component, ElementRef, Inject, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { combineLatest, Observable, Subscription } from 'rxjs';
import { delay, tap } from 'rxjs/operators';
import { ActivatedRoute, NavigationExtras, Router } from '@angular/router';
import { AppVersion } from '@ionic-native/app-version/ngx';
import { TranslateService } from '@ngx-translate/core';
import { FormControl, FormGroup } from '@angular/forms';
import { OnboardingScreenType, ProfileConstants, RouterLinks } from '@app/app/app.constant';
import { GUEST_STUDENT_TABS, GUEST_TEACHER_TABS, initTabs } from '@app/app/module.service';
import {
  Environment,
  ImpressionType,
  InteractSubtype,
  InteractType,
  PageId,
  CorReleationDataType,
  AuditType
} from '@app/services/telemetry-constants';
import {
  Framework,
  FrameworkCategoryCode,
  FrameworkCategoryCodesGroup,
  FrameworkService,
  FrameworkUtilService,
  GetFrameworkCategoryTermsRequest,
  GetSuggestedFrameworksRequest,
  Profile,
  ProfileService,
  ProfileType,
  CorrelationData,
  AuditState} from 'sunbird-sdk';
import {
  AppGlobalService,
  AppHeaderService,
  CommonUtilService,
  ContainerService,
  OnboardingConfigurationService,
  SunbirdQRScanner,
  TelemetryGeneratorService
} from 'services';
import { AlertController, Platform } from '@ionic/angular';
import { Events } from '@app/util/events';
import { Location } from '@angular/common';
import { SplashScreenService } from '@app/services/splash-screen.service';
import { CachedItemRequestSourceFrom } from '@project-sunbird/sunbird-sdk';
import { ProfileHandler } from '@app/services/profile-handler';
import { SegmentationTagService } from '@app/services/segmentation-tag/segmentation-tag.service';

@Component({
  selector: 'app-profile-settings',
  templateUrl: './profile-settings.page.html',
  styleUrls: ['./profile-settings.page.scss'],
})
export class ProfileSettingsPage implements OnInit, OnDestroy, AfterViewInit {
  public pageId = 'ProfileSettingsPage';
  @ViewChild('boardSelect', { static: false }) boardSelect: any;
  @ViewChild('mediumSelect', { static: false }) mediumSelect: any;
  @ViewChild('gradeSelect', { static: false }) gradeSelect: any;
  @ViewChild('animatedQRImage', { static: false }) animatedQRImageRef: ElementRef;

  private framework: Framework;
  private navParams: any;
  private activeSessionProfile?: Profile;
  private unregisterBackButton: Subscription;
  private headerObservable: any;
  private formControlSubscriptions: Subscription;
  loader: any;
  btnColor = '#8FC4FF';
  appName: string;
  showQRScanner = true;
  categories = [];

  public profileSettingsForm: FormGroup;
  public hideBackButton = true;

  public syllabusList: { name: string, code: string }[] = [];
  public mediumList: { name: string, code: string }[] = [];
  public gradeList: { name: string, code: string }[] = [];

  public supportedProfileAttributes: { [key: string]: string } = {};

  boardOptions = {
    title: this.commonUtilService.translateMessage('BOARD_OPTION_TEXT'),
    cssClass: 'ftue-changes'
  };
  mediumOptions = {
    title: this.commonUtilService.translateMessage('MEDIUM_OPTION_TEXT'),
    cssClass: 'select-box'
  };
  classOptions = {
    title: this.commonUtilService.translateMessage('GRADE_OPTION_TEXT'),
    cssClass: 'select-box'
  };

  get syllabusControl(): FormControl {
    return this.profileSettingsForm.get('syllabus') as FormControl;
  }

  get boardControl(): FormControl {
    return this.profileSettingsForm.get('board') as FormControl;
  }

  get mediumControl(): FormControl {
    return this.profileSettingsForm.get('medium') as FormControl;
  }

  get gradeControl(): FormControl {
    return this.profileSettingsForm.get('grade') as FormControl;
  }

  isInitialScreen = false;
  
  constructor(
    @Inject('PROFILE_SERVICE') private profileService: ProfileService,
    @Inject('FRAMEWORK_SERVICE') private frameworkService: FrameworkService,
    @Inject('FRAMEWORK_UTIL_SERVICE') private frameworkUtilService: FrameworkUtilService,
    private formAndFrameworkUtilService: FormAndFrameworkUtilService,
    private translate: TranslateService,
    private telemetryGeneratorService: TelemetryGeneratorService,
    private appGlobalService: AppGlobalService,
    private events: Events,
    private scanner: SunbirdQRScanner,
    public platform: Platform,
    private commonUtilService: CommonUtilService,
    private container: ContainerService,
    private headerService: AppHeaderService,
    private router: Router,
    private appVersion: AppVersion,
    private alertCtrl: AlertController,
    private location: Location,
    private splashScreenService: SplashScreenService,
    private activatedRoute: ActivatedRoute,
    private profileHandler: ProfileHandler,
    private segmentationTagService: SegmentationTagService,
    private onboardingConfigurationService: OnboardingConfigurationService
  ) {
    this.profileSettingsForm = new FormGroup({
      syllabus: new FormControl([]),
      board: new FormControl([]),
      medium: new FormControl([]),
      grade: new FormControl([])
    });
  }

  async ngOnInit() {
    this.getCategoriesAndUpdateAttributes();
    this.handleActiveScanner();
    this.appVersion.getAppName().then((appName) => {
      this.appName = (appName).toUpperCase();
    });

    this.activeSessionProfile = await this.profileService.getActiveSessionProfile({
      requiredFields: ProfileConstants.REQUIRED_FIELDS
    }).toPromise();
    await this.fetchSyllabusList();
    this.showQRScanner = !!(this.onboardingConfigurationService.getOnboardingConfig('profile-settings'));
  }


  ngAfterViewInit() {
    plugins['webViewChecker'].getCurrentWebViewPackageInfo()
      .then((packageInfo) => {
        this.formAndFrameworkUtilService.getWebviewConfig().then((webviewVersion) => {
          if (parseInt(packageInfo.versionName.split('.')[0], 10) <= webviewVersion) {
            this.animatedQRImageRef.nativeElement.style.width =
              this.animatedQRImageRef.nativeElement.style.height = 'auto';
            this.animatedQRImageRef.nativeElement.style.minWidth =
              this.animatedQRImageRef.nativeElement.style.minHeight = 0;
          }
        }).catch(() => {
          if (parseInt(packageInfo.versionName.split('.')[0], 10) <= 54) {
            this.animatedQRImageRef.nativeElement.style.width =
              this.animatedQRImageRef.nativeElement.style.height = 'auto';
            this.animatedQRImageRef.nativeElement.style.minWidth =
              this.animatedQRImageRef.nativeElement.style.minHeight = 0;
          }
        });
      });
  }

  private redirectToInitialRoute() {
    const snapshot = this.activatedRoute.snapshot;
    if (snapshot.queryParams && snapshot.queryParams.reOnboard) {
      this.showQRScanner = false;
      const userTypeSelectionRoute = new URL(window.location.origin + `/${RouterLinks.USER_TYPE_SELECTION}`);
      const languageSettingRoute = new URL(window.location.origin + `/${RouterLinks.LANGUAGE_SETTING}`);

      userTypeSelectionRoute.searchParams.set('onReload', 'true');
      languageSettingRoute.searchParams.set('onReload', 'true');

      window.history.pushState({}, '', userTypeSelectionRoute.toString());
      window.history.pushState({}, '', languageSettingRoute.toString());
      this.hideBackButton = false;
    }

    if(this.onboardingConfigurationService.initialOnboardingScreenName === OnboardingScreenType.PROFILE_SETTINGS) {
      this.isInitialScreen = true;
    }
  }

  ngOnDestroy() {
    this.formControlSubscriptions.unsubscribe();
  }

  handleActiveScanner() {
    const navigation = this.router.getCurrentNavigation();
    if (navigation && navigation.extras && navigation.extras.state) {
      this.navParams = navigation.extras.state;
    }

    if (this.navParams && this.navParams.stopScanner) {
      setTimeout(() => {
        this.scanner.stopScanner();
      }, 500);
    }
  }

  ionViewWillEnter() {
    if (this.router.url === '/' + RouterLinks.PROFILE_SETTINGS) {
      setTimeout(() => {
        this.telemetryGeneratorService.generateImpressionTelemetry(
          ImpressionType.VIEW, '',
          PageId.ONBOARDING_PROFILE_PREFERENCES,
          Environment.ONBOARDING
        );

        /* New Telemetry */
        this.telemetryGeneratorService.generateImpressionTelemetry(
          ImpressionType.PAGE_REQUEST, '',
          PageId.SCAN_OR_MANUAL,
          Environment.ONBOARDING
        );
      }, 350);
    }

    this.handleDeviceBackButton();
    // after qr scan if bmc is not populated then show only BMC
    if (history.state && history.state.showFrameworkCategoriesMenu) {
      this.showQRScanner = false;
    }
    this.headerObservable = this.headerService.headerEventEmitted$.subscribe(eventName => {
      this.handleHeaderEvents(eventName);
    });

    if (history.state && history.state.hideBackButton !== undefined) {
      this.hideBackButton = history.state.hideBackButton;
    } else if (this.navParams) {
      this.hideBackButton = Boolean(this.navParams.hideBackButton);
    }

    // should be called everytime when entered to this page
    this.redirectToInitialRoute();
    this.headerService.hideHeader();
  }

  ionViewDidEnter() {
    this.hideOnboardingSplashScreen();
  }

  hideOnboardingSplashScreen() {
    if (this.navParams && this.navParams.forwardMigration) {
      this.splashScreenService.handleSunbirdSplashScreenActions();
    }
  }

  ionViewWillLeave() {
    this.headerObservable.unsubscribe();
    if (this.unregisterBackButton) {
      this.unregisterBackButton.unsubscribe();
    }
  }

  async dismissPopup() {
    const activePortal = await this.alertCtrl.getTop();

    if (activePortal) {
      activePortal.dismiss();
    } else if (this.isInitialScreen && this.showQRScanner) {
      this.commonUtilService.showExitPopUp(PageId.PROFILE_SETTINGS, Environment.ONBOARDING, false);
    } else if (!this.hideBackButton) {
      this.location.back();
    }
  }

  cancelEvent(category?: string) {
    let correlationList: Array<CorrelationData> = [];

    /* New Telemetry */
    switch (category) {
      case 'board':
        correlationList = this.populateCData(this.syllabusControl.value, CorReleationDataType.BOARD);
        break;
      case 'medium':
        correlationList = this.populateCData(this.mediumControl.value, CorReleationDataType.MEDIUM);
        break;
      case 'grade':
        correlationList = this.populateCData(this.gradeControl.value, CorReleationDataType.CLASS);
        break;
    }
    correlationList.push({ id: PageId.POPUP_CATEGORY, type: CorReleationDataType.CHILD_UI });
    this.telemetryGeneratorService.generateInteractTelemetry(
      InteractType.SELECT_CANCEL, '',
      Environment.ONBOARDING,
      PageId.MANUAL_PROFILE,
      undefined,
      undefined,
      undefined,
      correlationList
    );
  }

  extractProfileForTelemetry(formVal): any {
    const profileReq: any = {};
    profileReq.board = formVal.syllabus;
    profileReq.medium = formVal.medium;
    profileReq.grade = formVal.grades;
    return profileReq;
  }

  handleDeviceBackButton() {
    this.unregisterBackButton = this.platform.backButton.subscribeWithPriority(10, () => {
      this.handleBackButton(false);
    });
  }

  handleHeaderEvents($event) {
    if($event.name === 'back')
    {
      this.handleBackButton(true);
    }
  }

  handleBackButton(isNavBack) {
    this.telemetryGeneratorService.generateBackClickedTelemetry(PageId.ONBOARDING_PROFILE_PREFERENCES, Environment.ONBOARDING, isNavBack);
    /* New Telemetry */
    this.telemetryGeneratorService.generateBackClickedNewTelemetry(
      !isNavBack,
      Environment.ONBOARDING,
      this.showQRScanner ? PageId.SCAN_OR_MANUAL : PageId.MANUAL_PROFILE
    );

    if (this.showQRScanner === false) {
      this.showQRScanner = true;
      this.resetProfileSettingsForm();
    } else {
      this.dismissPopup();
    }
  }

  openQRScanner() {
    this.telemetryGeneratorService.generateInteractTelemetry(
      InteractType.TOUCH,
      InteractSubtype.QRCodeScanClicked,
      Environment.ONBOARDING,
      PageId.ONBOARDING_PROFILE_PREFERENCES,
    );
    /* New Telemetry */
    this.telemetryGeneratorService.generateInteractTelemetry(
      InteractType.SELECT_QRSCANER, '',
      Environment.ONBOARDING,
      PageId.SCAN_OR_MANUAL
    );
    this.scanner.startScanner(PageId.ONBOARDING_PROFILE_PREFERENCES, true).then((scannedData) => {
      if (scannedData === 'skip') {
        this.telemetryGeneratorService.generateImpressionTelemetry(
          ImpressionType.VIEW, '',
          PageId.ONBOARDING_PROFILE_PREFERENCES,
          Environment.ONBOARDING
        );
        this.showQRScanner = false;

        this.resetProfileSettingsForm();
      }
    });
  }

  onSubmitAttempt() {
    if (this.profileSettingsForm.valid) {
      this.appGlobalService.generateSaveClickedTelemetry(this.extractProfileForTelemetry(this.profileSettingsForm.value), 'passed',
        PageId.ONBOARDING_PROFILE_PREFERENCES, InteractSubtype.FINISH_CLICKED);
      /* New Telemetry */
      let correlationList: Array<CorrelationData> = [];
      correlationList = this.populateCData(this.syllabusControl.value, CorReleationDataType.BOARD);
      correlationList = correlationList.concat(this.populateCData(this.mediumControl.value, CorReleationDataType.MEDIUM));
      correlationList = correlationList.concat(this.populateCData(this.gradeControl.value, CorReleationDataType.CLASS));
      this.telemetryGeneratorService.generateInteractTelemetry(
        InteractType.SELECT_SUBMIT, '',
        Environment.ONBOARDING,
        PageId.MANUAL_PROFILE,
        undefined,
        undefined,
        undefined,
        correlationList
      );
      this.submitProfileSettingsForm();
      return;
    }

    for (const [control, selector] of [
      [this.syllabusControl, this.boardSelect],
      [this.mediumControl, this.mediumSelect],
      [this.gradeControl, this.gradeSelect]
    ]) {
      if (!control.value.length) {
        if (!this.profileSettingsForm.value.board.length) {
          this.appGlobalService.generateSaveClickedTelemetry(this.extractProfileForTelemetry(this.profileSettingsForm.value), 'failed',
            PageId.ONBOARDING_PROFILE_PREFERENCES, InteractSubtype.FINISH_CLICKED);
          const values = new Map();
          values['board'] = 'na';
          this.telemetryGeneratorService.generateInteractTelemetry(
            InteractType.TOUCH,
            'submit-clicked',
            Environment.HOME,
            PageId.ONBOARDING_PROFILE_PREFERENCES,
            undefined,
            values
          );
        } else if (!this.profileSettingsForm.value.medium.length) {
          this.appGlobalService.generateSaveClickedTelemetry(this.extractProfileForTelemetry(this.profileSettingsForm.value), 'failed',
            PageId.ONBOARDING_PROFILE_PREFERENCES, InteractSubtype.FINISH_CLICKED);
          const values = new Map();
          values['medium'] = 'na';
          this.telemetryGeneratorService.generateInteractTelemetry(
            InteractType.TOUCH,
            'submit-clicked',
            Environment.HOME,
            PageId.ONBOARDING_PROFILE_PREFERENCES,
            undefined,
            values
          );
        } else if (!this.profileSettingsForm.value.grade.length) {
          this.appGlobalService.generateSaveClickedTelemetry(this.extractProfileForTelemetry(this.profileSettingsForm.value), 'failed',
            PageId.ONBOARDING_PROFILE_PREFERENCES, InteractSubtype.FINISH_CLICKED);
          const values = new Map();
          values['grades'] = 'na';
          this.telemetryGeneratorService.generateInteractTelemetry(
            InteractType.TOUCH,
            'submit-clicked',
            Environment.HOME,
            PageId.ONBOARDING_PROFILE_PREFERENCES,
            undefined,
            values
          );
        }
        if (selector) {
          selector.open();
        }
        return;
      }
    }
  }

  async fetchSyllabusList() {
    this.loader = await this.commonUtilService.getLoader();
    await this.loader.present();

    const getSuggestedFrameworksRequest: GetSuggestedFrameworksRequest = {
      from: CachedItemRequestSourceFrom.SERVER,
      language: this.translate.currentLang,
      requiredCategories: FrameworkCategoryCodesGroup.DEFAULT_FRAMEWORK_CATEGORIES
    };

    this.frameworkUtilService.getActiveChannelSuggestedFrameworkList(getSuggestedFrameworksRequest).toPromise()
      .then(async (frameworks: Framework[]) => {

        if (!frameworks || !frameworks.length) {
          await this.loader.dismiss();
          this.commonUtilService.showToast('NO_DATA_FOUND');
          return;
        }
        this.syllabusList = frameworks.map(r => ({ name: r.name, code: r.identifier }));


        /* New Telemetry */
        const correlationList: Array<CorrelationData> = [];
        correlationList.push({ id: this.syllabusList.length.toString(), type: CorReleationDataType.BOARD_COUNT });
        this.telemetryGeneratorService.generatePageLoadedTelemetry(
          PageId.SCAN_OR_MANUAL,
          Environment.ONBOARDING,
          undefined,
          undefined,
          undefined,
          undefined,
          correlationList
        );
        await this.loader.dismiss();
      });
  }

  private onSyllabusChange(): Observable<string[]> {
    return this.syllabusControl.valueChanges.pipe(
      tap(async (value) => {
        if (!Array.isArray(value)) {
          this.syllabusControl.patchValue([value]);
          return;
        }

        if (!value.length) {
          return;
        }

        await this.commonUtilService.getLoader().then((loader) => {
          this.loader = loader;
          this.loader.present();
        });

        try {
          this.framework = await this.frameworkService.getFrameworkDetails({
            from: CachedItemRequestSourceFrom.SERVER,
            frameworkId: value[0],
            requiredCategories: FrameworkCategoryCodesGroup.DEFAULT_FRAMEWORK_CATEGORIES
          }).toPromise();

          /* New Telemetry */
          this.generateCategorySubmitTelemetry('board');

          const boardCategoryTermsRequet: GetFrameworkCategoryTermsRequest = {
            frameworkId: this.framework.identifier,
            requiredCategories: [FrameworkCategoryCode.BOARD],
            currentCategoryCode: FrameworkCategoryCode.BOARD,
            language: this.translate.currentLang
          };

          const boardTerm = (await this.frameworkUtilService.getFrameworkCategoryTerms(boardCategoryTermsRequet).toPromise())
            .find(b => b.name === (this.syllabusList.find((s) => s.code === value[0]).name));

          this.boardControl.patchValue([boardTerm.code]);

          const nextCategoryTermsRequet: GetFrameworkCategoryTermsRequest = {
            frameworkId: this.framework.identifier,
            requiredCategories: [FrameworkCategoryCode.MEDIUM],
            prevCategoryCode: FrameworkCategoryCode.BOARD,
            currentCategoryCode: FrameworkCategoryCode.MEDIUM,
            language: this.translate.currentLang,
            selectedTermsCodes: this.boardControl.value
          };

          this.mediumList = (await this.frameworkUtilService.getFrameworkCategoryTerms(nextCategoryTermsRequet).toPromise())
            .map(t => ({ name: t.name, code: t.code }));

        } catch (e) {
          console.error(e);
        } finally {
          this.mediumControl.patchValue([]);
          this.loader.dismiss();
        }
      })
    );
  }

  private onMediumChange(): Observable<string[]> {
    return this.mediumControl.valueChanges.pipe(
      tap(async () => {

        /* New Telemetry */
        this.generateCategorySubmitTelemetry('medium');

        await this.commonUtilService.getLoader().then((loader) => {
          this.loader = loader;
          this.loader.present();
        });

        try {
          const nextCategoryTermsRequet: GetFrameworkCategoryTermsRequest = {
            frameworkId: this.framework.identifier,
            requiredCategories: [FrameworkCategoryCode.GRADE_LEVEL],
            prevCategoryCode: FrameworkCategoryCode.MEDIUM,
            currentCategoryCode: FrameworkCategoryCode.GRADE_LEVEL,
            language: this.translate.currentLang,
            selectedTermsCodes: this.mediumControl.value
          };

          this.gradeList = (await this.frameworkUtilService.getFrameworkCategoryTerms(nextCategoryTermsRequet).toPromise())
            .map(t => ({ name: t.name, code: t.code }));

        } catch (e) {
          console.error(e);
        } finally {
          this.gradeControl.patchValue([]);
          this.loader.dismiss();
        }
      })
    );
  }

  private onGradeChange(): Observable<string[]> {
    return this.gradeControl.valueChanges.pipe(
      tap(async () => {

        /* New Telemetry */
        this.generateCategorySubmitTelemetry('grade');

      })
    );
  }

  private async submitProfileSettingsForm() {
    await this.commonUtilService.getLoader().then((loader) => {
      this.loader = loader;
    });
    const updateProfileRequest: Profile = {
      ...this.activeSessionProfile,
      syllabus: this.syllabusControl.value,
      board: this.boardControl.value,
      medium: this.mediumControl.value,
      grade: this.gradeControl.value,
      profileType: (this.navParams && this.navParams.selectedUserType) || this.activeSessionProfile.profileType
    };

    this.profileService.updateProfile(updateProfileRequest).toPromise()
      .then(async (profile: Profile) => {
        this.segmentationTagService.refreshSegmentTags(profile);
        if (this.commonUtilService.isAccessibleForNonStudentRole(updateProfileRequest.profileType)) {
          initTabs(this.container, GUEST_TEACHER_TABS);
        } else if (updateProfileRequest.profileType === ProfileType.STUDENT) {
          initTabs(this.container, GUEST_STUDENT_TABS);
        }
        this.segmentationTagService.createSegmentTags(profile);
        this.events.publish('refresh:profile');
        this.appGlobalService.guestUserProfile = profile;
        await this.commonUtilService.handleToTopicBasedNotification();
        setTimeout(async () => {
          this.commonUtilService.showToast('PROFILE_UPDATE_SUCCESS');
          if (await this.commonUtilService.isDeviceLocationAvailable()) {
            this.appGlobalService.setOnBoardingCompleted();
            this.router.navigate([`/${RouterLinks.TABS}`]);
          } else {
            const navigationExtras: NavigationExtras = {
              state: {
                isShowBackButton: true
              }
            };
            this.router.navigate([RouterLinks.DISTRICT_MAPPING], navigationExtras);
          }
        }, 2000);
        this.events.publish('onboarding-card:completed', { isOnBoardingCardCompleted: true });
        this.events.publish('refresh:profile');
        this.appGlobalService.guestUserProfile = profile;

        this.telemetryGeneratorService.generateProfilePopulatedTelemetry(
          PageId.ONBOARDING_PROFILE_PREFERENCES, profile, 'manual', Environment.ONBOARDING
        );
        let correlationlist: Array<CorrelationData> = [{ id: PageId.MANUAL_PROFILE, type: CorReleationDataType.FROM_PAGE }];
        correlationlist = correlationlist.concat(this.populateCData(this.boardControl.value, CorReleationDataType.BOARD));
        correlationlist = correlationlist.concat(this.populateCData(this.mediumControl.value, CorReleationDataType.MEDIUM));
        correlationlist = correlationlist.concat(this.populateCData(this.gradeControl.value, CorReleationDataType.CLASS));
        correlationlist.push({ id: PageId.MANUAL, type: CorReleationDataType.FILL_MODE });
        this.telemetryGeneratorService.generateAuditTelemetry(
          Environment.ONBOARDING,
          AuditState.AUDIT_UPDATED,
          undefined,
          AuditType.SET_PROFILE,
          undefined,
          undefined,
          undefined,
          correlationlist
        );
        this.loader = await this.commonUtilService.getLoader(2000);
        await this.loader.present();
      })
      .catch(async () => {
        await this.loader.dismiss();
        this.commonUtilService.showToast('PROFILE_UPDATE_FAILED');
      });
  }

  private populateCData(formControllerValues, correlationType): Array<CorrelationData> {
    const correlationList: Array<CorrelationData> = [];
    if (formControllerValues) {
      formControllerValues.forEach((value) => {
        correlationList.push({
          id: value,
          type: correlationType
        });
      });
    }
    return correlationList;
  }

  private resetProfileSettingsForm() {
    this.profileSettingsForm.reset({
      syllabus: [],
      board: [],
      medium: [],
      grade: []
    });
  }

  boardClicked(e?: Event) {
    if (e) {
      e.stopPropagation();
      e.preventDefault();
    }

    this.showQRScanner = false;

    /* New Telemetry */
    this.telemetryGeneratorService.generatePageLoadedTelemetry(
      PageId.MANUAL_PROFILE,
      Environment.ONBOARDING
    );

    const correlationList: Array<CorrelationData> = [];
    correlationList.push({ id: this.syllabusList.length.toString(), type: CorReleationDataType.BOARD_COUNT });
    this.telemetryGeneratorService.generateInteractTelemetry(
      InteractType.SELECT_CATEGORY, '',
      Environment.ONBOARDING,
      PageId.SCAN_OR_MANUAL,
      undefined,
      undefined,
      undefined,
      correlationList
    );

    setTimeout(() => {
      this.boardSelect.open();
      this.setAriaLabel();
    }, 0);
  }

  onCategoryCliked(category: string) {
    const correlationList: Array<CorrelationData> = [];
    const correlationData: CorrelationData = new CorrelationData();
    switch (category) {
      case 'board':
        correlationData.id = this.syllabusList.length.toString();
        correlationData.type = CorReleationDataType.BOARD_COUNT;
        break;
      case 'medium':
        correlationData.id = this.mediumList.length.toString();
        correlationData.type = CorReleationDataType.MEDIUM_COUNT;
        break;
      case 'grade':
        correlationData.id = this.gradeList.length.toString();
        correlationData.type = CorReleationDataType.CLASS_COUNT;
        break;
    }
    correlationList.push(correlationData);
    this.telemetryGeneratorService.generateInteractTelemetry(
      InteractType.SELECT_CATEGORY, '',
      Environment.ONBOARDING,
      PageId.MANUAL_PROFILE,
      undefined,
      undefined,
      undefined,
      correlationList
    );
  }

  generateCategorySubmitTelemetry(category: string) {
    let correlationList: Array<CorrelationData> = [];
    switch (category) {
      case 'board':
        if (!this.syllabusControl.value.length) {
          return;
        }
        correlationList = this.populateCData(this.syllabusControl.value, CorReleationDataType.BOARD);
        break;
      case 'medium':
        if (!this.mediumControl.value.length) {
          return;
        }
        correlationList = this.populateCData(this.mediumControl.value, CorReleationDataType.MEDIUM);
        break;
      case 'grade':
        if (!this.gradeControl.value.length) {
          return;
        }
        correlationList = this.populateCData(this.gradeControl.value, CorReleationDataType.CLASS);
        break;
    }
    correlationList.push({ id: PageId.POPUP_CATEGORY, type: CorReleationDataType.CHILD_UI });
    this.telemetryGeneratorService.generateInteractTelemetry(
      InteractType.SELECT_SUBMIT, '',
      Environment.ONBOARDING,
      PageId.MANUAL_PROFILE,
      undefined,
      undefined,
      undefined,
      correlationList
    );
  }

  private updateAttributeStreamsnSetValidators(attributes: { [key: string]: string }): Array<any> {
    const subscriptionArray = [];
    Object.keys(attributes).forEach((attribute) => {
      console.log('attribute', attribute);
      switch (attribute) {
        case 'board':
          subscriptionArray.push(this.onSyllabusChange());
          this.boardControl.setValidators((c) => c.value.length ? undefined : { length: 'NOT_SELECTED' });
          break;
        case 'medium':
          subscriptionArray.push(this.onMediumChange());
          this.mediumControl.setValidators((c) => c.value.length ? undefined : { length: 'NOT_SELECTED' });
          break;
        case 'gradeLevel':
          subscriptionArray.push(this.onGradeChange());
          this.gradeControl.setValidators((c) => c.value.length ? undefined : { length: 'NOT_SELECTED' });
          break;
      }
    });
    subscriptionArray.push(this.profileSettingsForm.valueChanges.pipe(
      delay(250),
      tap(() => {
        this.btnColor = this.profileSettingsForm.valid ? '#006DE5' : '#8FC4FF';
      })
    ));
    return subscriptionArray;
  }

  public setAriaLabel() {
    const selectDomTag = document.getElementsByTagName('ion-select');
    Object.values(selectDomTag).forEach(element => {
      if(element.multiple === false)
      {
        element.setAttribute('aria-label',   'single select');
      }
      else{
      element.setAttribute('aria-label',   'multiple select');
      }
      element.setAttribute('tabindex', '0');
    });
}

private addAttributeSubscription() {
  const subscriptionArray: Array<any> = this.updateAttributeStreamsnSetValidators(this.supportedProfileAttributes);
  this.formControlSubscriptions = combineLatest(subscriptionArray).subscribe();
}

  private getCategoriesAndUpdateAttributes() {
    this.formAndFrameworkUtilService.getFrameworkCategoryList().then((categories) => {
      if (categories && categories.supportedFrameworkConfig && categories.supportedAttributes) {
        this.categories = categories.supportedFrameworkConfig;
        this.supportedProfileAttributes = categories.supportedAttributes;
        this.addAttributeSubscription();
      }
    });
  }

}
<ion-content class="padding-bottom-if-header">
	<div class="">
		<form [formGroup]="profileSettingsForm" class="ps-container">
			<div  role="button" aria-label="back" (click)="handleBackButton(true)" class='back-btn-container'>
				<img src="assets/imgs/ic_back_black.svg" *ngIf="!hideBackButton && !(showQRScanner && isInitialScreen)"
					 class="top-back-button" alt="back">
			</div>
			<div class="qr-container ui-container" *ngIf="showQRScanner">
				<div class="qr-content">
					<img #animatedQRImage class="qr-img" src="assets/imgs/qr_with_book.svg" alt="qr book scanner">
					<div class="qr-instruction-container text-center">
						<div class="qr-instruction">
							<div class="title"  tabindex="0" role="heading" aria-level="1">{{'APP_QR_CODE' | translate: {'%s': appName} }}</div>
							<div class="sub-title" tabindex="0" role="contentinfo">{{'QR_CODE_DETAILS' | translate}}</div>
						</div>
						<div class="qr-btn-container">
							<div class="qr-btn" role="button" tabindex="0" (click)="openQRScanner()">
								<img src="assets/imgs/ic_qr_scanner.svg" alt="">
								<span>{{'SCAN_TAP' | translate}}</span>
							</div>
						</div>
					</div>
				</div>
				<div class="qr-board">
					<div class="or-container" tabindex="0">
						<span class="or-circle">{{'OR' | translate}}</span>
					</div>
					<div class="fill-in-style msg-size">
						<div class="fill-in-head" tabindex="0" role="heading" aria-level="2">{{'NO_QR_CODE_QSTN' | translate}}</div>
						<div class="fill-in-content" tabindex="0" >{{'PROVIDE_BELOW_INFO' | translate}}</div>
					</div>

					<div class="board-select-dummy" (click)="boardClicked($event)" *ngIf="categories && categories.length>0">
						<ion-item appCustomIonSelect>
							<ion-label position="stacked" class="label-font text-uppercase align-text">
								{{categories[0].label | translateJson}}</ion-label>
							<ion-select multiple="false" class="ion-text-capitalize" formControlName="syllabus"
										[interfaceOptions]="boardOptions" (ionCancel)="cancelEvent()"
										okText="{{'BTN_SUBMIT' | translate}}" cancelText="{{'CANCEL' | translate}}"
										placeholder="{{categories[0].placeHolder | translateJson}}">
								<ion-select-option *ngFor="let eachSyllabus of syllabusList" value="{{eachSyllabus.code}}">
									{{eachSyllabus.name}}&lrm;</ion-select-option>
							</ion-select>
						</ion-item>
						<div class="ps-board">
							<div class="ps-board-label">{{categories[0].label | translateJson}}</div>
							<button class="sb-btn-secondary sb-btn-md PR35 W100 ellipsis btn-block">
								{{categories[0].placeHolder | translateJson}}
								<img class="arrow-icon" src="assets/imgs/ic_back_black.svg" alt="">
							</button>
						</div>
					</div>
				</div>
			</div>
			<div novalidate class="form-position" *ngIf="!showQRScanner">
				<div *ngFor="let category of categories">
					<ion-item *ngIf="!!supportedProfileAttributes['board'] && category.code=== 'category1'" appCustomIonSelect (click)="onCategoryCliked('board')">
						<ion-label position="stacked" class="label-font text-uppercase align-text">{{category.label | translateJson}}
						</ion-label>
						<ion-select multiple="false" #boardSelect class="ion-text-capitalize" formControlName="syllabus"
							[disabled]="!syllabusList.length" [interfaceOptions]="boardOptions" (ionCancel)="cancelEvent('board')"
							okText="{{'BTN_SUBMIT' | translate}}" cancelText="{{'CANCEL' | translate}}"
							placeholder="{{category.placeHolder | translateJson}}">
							<ion-select-option *ngFor="let eachSyllabus of syllabusList" value="{{eachSyllabus.code}}">
								{{eachSyllabus.name | aliased}}&lrm;</ion-select-option>
						</ion-select>
					</ion-item>

					<ion-item *ngIf="!!supportedProfileAttributes['medium'] && category.code=== 'category2'" appCustomIonSelect (click)="onCategoryCliked('medium')">
						<ion-label position="stacked" class="label-font text-uppercase align-text">{{category.label | translateJson}}
						</ion-label>
						<ion-select formControlName="medium" #mediumSelect multiple="true" class="ion-text-capitalize"
							[interfaceOptions]="mediumOptions" (ionCancel)="cancelEvent('medium')" okText="{{'BTN_SUBMIT' | translate}}"
							cancelText="{{'CANCEL' | translate}}" [disabled]="!mediumList.length || !boardControl.value.length"
							placeholder="{{category.placeHolder | translateJson}}">
							<ion-select-option *ngFor="let medium of mediumList" class="ion-text-capitalize"
								value="{{medium.code}}">
								{{medium.name}}</ion-select-option>
						</ion-select>
					</ion-item>
	
					<ion-item *ngIf="!!supportedProfileAttributes['gradeLevel'] && category.code=== 'category3'" appCustomIonSelect (click)="onCategoryCliked('grade')">
						<ion-label position="stacked" class="label-font text-uppercase align-text">{{category.label | translateJson}}
						</ion-label>
						<ion-select multiple="true" #gradeSelect class="ion-text-capitalize" formControlName="grade"
							[interfaceOptions]="classOptions" okText="{{'BTN_SUBMIT' | translate}}"
							cancelText="{{'CANCEL' | translate}}" [disabled]="!gradeList.length || !mediumControl.value.length"
							(ionCancel)="cancelEvent('grade')" placeholder="{{category.placeHolder | translateJson}}">
							<ion-select-option *ngFor="let grade of gradeList" class="ion-text-capitalize"
								value="{{grade.code}}">
								{{grade.name}}</ion-select-option>
						</ion-select>
					</ion-item>
				</div>

			</div>
		</form>
	</div>
</ion-content>

<div class="ion-padding ion-no-border" style="background: white;" *ngIf="!showQRScanner">
	<button class="sb-btn sb-btn-md sb-btn-primary PR35 W100 ellipsis btn-block ion-text-uppercase"
		[style.background-color]="btnColor" (click)="onSubmitAttempt()">
		{{ 'CONTINUE' | translate }}
		<img class="arrow-icon" src="assets/imgs/ic_back.svg" [class.animate]="profileSettingsForm.valid" alt="">
	</button>
</div>

./profile-settings.page.scss

@import "src/assets/styles/variables";
@import "src/assets/styles/_custom-mixins";
@import "src/assets/styles/_variables.scss";
:host {
  .scroll-content,
  .fixed-content {
    padding-bottom: 53px;
  }

  /* This should be item-ios only as we are targeting mode as iOS for radio-button */
  .item-ios {
    background-color: #{map-get($colors, white_f7)};
  }

  .button-inner {
    display: initial !important;
  }

  ion-icon {
    @include ltr {
      float: right !important;
    }

    @include rtl {
      float: left !important;
    }
  }

  ion-label.align-text {
    @include ltr {
      align-self: stretch;
    }
    @include rtl {
      align-self: end;
    }
  }

  ion-list[inset] {
    margin: 0 !important;
  }

  /* Change height of the ion-item*/
  .item-block {
    min-height: 5.5rem !important;
  }

  .back-button {
    display: block !important;
  }

  .fill-in-style {
    font-size: 0.75rem;
    text-align: center;
    margin-top: 40px;
    @include padding(0, 5px);
    .fill-in-head{
      font-weight: bold;
      font-size: 1rem;
      margin-bottom: 8px;
    }
    .fill-in-content{
      font-size: $font-size-base;
    }
  }
  .item-select-disabled {
    .label-md {
      color: #{map-get($colors, medium_gray)};
      opacity: 1;
    }
  }

  .padding-bottom-if-header {
    padding-bottom: 80px !important;
  }
  .board-select-dummy{
    .ps-board{
      display: none;
    }
    width: 100vw;
    margin: 0 auto;
    ion-item{
      // z-index: -1;
      pointer-events: none;
      display: block;
    }
  }
  .ps-container{
    display: flex;
    flex-direction: column;
    width: 100vw;
    height: 100%;
    .qr-container {
      background-color: #EDF4F9;
      display: flex;
      flex-direction: column;
      flex-grow: 1;
      flex-shrink: 1;
      height: 100vh;
    }
    .form-position{
      flex-grow: 1;
      flex-shrink: 1;
      margin-top: 50px;
    }
  }
  .qr-board{
      flex-grow: 0;
      flex-shrink: 0;
      padding-bottom: 40px;
      position: relative;
      &::after{
        content: '';
        display: block;
        width: 125%;
        height: 100%;
        background: white;
        border-top-left-radius: 50%;
        border-top-right-radius: 50%;
        position: absolute;
        top: 0;
        left: -12.5%;
        z-index: 0;
      }

      & > div {
        position: relative;
        z-index: 1;
      }

      .or-container{
        position: absolute;
        left: 0;
        right: 0;
        top: -0.938rem;
        .or-circle {
          display: block;
          width: 3.75rem;
          height: 1.875rem;
          border-radius: 15px;
          background-color: #555;
          text-align: center;
          color: map-get($colors, white);
          font-size: 1rem;
          line-height: 1.88rem;
          margin: 0 auto;
        }
      }
  }

  .back-btn-container{
    height: 2rem;
    @include ltr() {
      top: 0;
      left: 0;
    }
    @include rtl() {
      top: 0;
      right: 0;
    }
    flex-grow: 0;
    flex-shrink: 0;
    .top-back-button{
      position: absolute;
      width: 1.875rem;
      @include ltr() {
        left: 1rem;
        transform: rotate(180deg);
      }
      @include rtl() {
        right: 1rem;
        transform: rotate(0deg);
      }
    }
  }

  .qr-content {
    display: flex;
    flex-direction: column;
    flex-grow: 1;
    flex-shrink: 1;
    height: 0;
    padding: 0 32px;

    padding-top: 50px;

    .qr-img{
      object-fit: contain;
      min-width: 0;
      min-height: 0;
      width: auto;
      height: 100%;
      flex-shrink: 1;
    }
  }
  .qr-instruction-container {
    flex-grow: 0;
    flex-shrink: 0;
    padding-top: 16px;
    padding-bottom: 40px;
    .qr-instruction {
      .title {
        display: block;
        font-weight: bold;
        color: #024F9D;
      }
      .sub-title {
        padding: 8px 10% 0 10%;
        font-size: $font-size-base;
      }
    }
    .qr-btn-container {
      text-align: center;
      margin-top: 16px;
      .qr-btn {
        display: inline-block;
        background-color: map-get($colors, primary);
        padding: 10px 20px;
        text-align: center;
        color: $blue;
        border-radius: 5px;
        box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
        img {
          vertical-align: middle;
        }
        span {
          display: inline-block;
          vertical-align: middle;
          font-size: 1.25rem;
          padding-left: 10px;
        }
      }
    }
  }

  .item-label-stacked ion-select {
    border: 1px solid map-get($colors, primary);
    border-radius: 5px;
    margin-top: 16px;
    padding-left: 8px;
    padding-right: 10px !important;
    .select-icon {
      .select-icon-inner {
        border: solid blue;
        border-width: 0 2px 2px 0;
        display: inline-block;
        padding: 4px;
        transform: rotate(45deg);
        animation: upDownAnimate 5s linear infinite;
        animation-duration: 0.9s;
      }
    }
    // Not getting used because of shadow DOM
    .select-placeholder {
      color: map-get($colors, primary);
      padding-left: 10px;
    }
  }
  .ios .item-label-stacked ion-select {
    margin-top: 0px;
  }
  ion-item.item-label-stacked {
    --border-width: 0;
    --highlight-background: transparent;
  }
  .item-select ion-label {
    color: map-get($colors, primary);
  }

  .item-label-stacked.item-select-disabled {
    ion-label {
      color: map-get($colors, primary_black);
    }

    ion-select {
      border-color: map-get($colors, primary_black);
      // Inside Shadow DOM
      .select-icon {
        .select-icon-inner {
          border-color: map-get($colors, primary_black);
          animation: none;
        }
      }
      // Inside Shadow DOM
      .select-placeholder {
        color: map-get($colors, primary_black);
      }
    }
  }

  .item-label-stacked.item-has-value {
    label {
      color: #{$gray-800};
    }
    ion-select {
      border-color: #{$gray-300};
      .select-text {
        padding-left: 10px;
        font-weight: bold;
        color: #{$gray-800};
      }
      .select-icon {
        .select-icon-inner {
          border-color: #{$gray-800};
          animation: none;
        }
      }
    }
  }
  img.arrow-icon {
    display: inline-block;
    width: 1.375rem;
    margin-top: -3px;
    float: right;

    &.animate {
      position: relative;
      animation: dropDown 5s linear infinite;
      animation-duration: 0.9s;
    }

    @include rtl {
      transform: rotate(180deg);
      float: left !important;
    }
  }

  ion-label {
    opacity: 1;
    color: map-get($colors, dark_gray);
  }
}


.item-label-stacked ion-select {
  border: 1px solid map-get($colors, primary);
  margin-top: 16px;
  padding-right: 10px !important;
  .select-icon {
    .select-icon-inner {
      border: solid blue;
      border-width: 0 2px 2px 0;
      display: inline-block;
      padding: 4px;
      transform: rotate(45deg);
      animation: upDownAnimate 5s linear infinite;
      animation-duration: 0.9s;
    }
  }
  // Not getting used because of shadow DOM
  .select-placeholder {
    color: map-get($colors, primary);
    padding-left: 10px;
  }
}

@keyframes upDownAnimate {
  0% {right: 0;}
  50% {right: 10px;}
  100% {right: 0;}
}

.framework-item {
  padding: 14px;
}

.sb-btn-secondary{
  background-color: map-get($colors, white);
  color: $blue !important;
}

// ************* iOS start*************
.back-btn-container-ios{
  height: 2rem;
  @include ltr() {
    top: 3.125rem;
    left: 0;
    position: relative;
  }
  @include rtl() {
    top: 0;
    right: 0;
  }
  flex-grow: 0;
  flex-shrink: 0;
  .top-back-button{
    position: absolute;
    width: 1.875rem;
    @include ltr() {
      left: 1rem;
      transform: rotate(180deg);
    }
    @include rtl() {
      right: 1rem;
      transform: rotate(0deg);
    }
  }
}
// ************* iOS end **************
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""