File

src/app/my-groups/my-groups.page.ts

Implements

OnInit OnDestroy

Metadata

Index

Properties
Methods

Constructor

constructor(authService: AuthService, groupService: GroupService, preferences: SharedPreferences, systemSettingsService: SystemSettingsService, profileService: ProfileService, appGlobalService: AppGlobalService, headerService: AppHeaderService, router: Router, commonUtilService: CommonUtilService, popoverCtrl: PopoverController, sbProgressLoader: SbProgressLoader, telemetryGeneratorService: TelemetryGeneratorService, platform: Platform, location: Location)
Parameters :
Name Type Optional
authService AuthService No
groupService GroupService No
preferences SharedPreferences No
systemSettingsService SystemSettingsService No
profileService ProfileService No
appGlobalService AppGlobalService No
headerService AppHeaderService No
router Router No
commonUtilService CommonUtilService No
popoverCtrl PopoverController No
sbProgressLoader SbProgressLoader No
telemetryGeneratorService TelemetryGeneratorService No
platform Platform No
location Location No

Methods

checkIfUserAcceptedGuidelines
checkIfUserAcceptedGuidelines()
Returns : void
Private checkUserLoggedIn
checkUserLoggedIn()
Returns : void
createClassroom
createClassroom()
Returns : void
Async fetchGroupList
fetchGroupList()
Returns : any
Private generateInteractTelemetry
generateInteractTelemetry(interactType, interactSubType, correlationList?, id?)
Parameters :
Name Optional
interactType No
interactSubType No
correlationList Yes
id Yes
Returns : void
goback
goback()
Returns : void
Private handleBackButton
handleBackButton()
Returns : void
handleHeaderEvents
handleHeaderEvents($event)
Parameters :
Name Optional
$event No
Returns : void
Async ionViewDidEnter
ionViewDidEnter()
Returns : any
Async ionViewWillEnter
ionViewWillEnter()
Returns : any
ionViewWillLeave
ionViewWillLeave()
Returns : void
login
login()
Returns : void
navigateToGroupdetailsPage
navigateToGroupdetailsPage(event)
Parameters :
Name Optional
event No
Returns : void
ngOnDestroy
ngOnDestroy()
Returns : void
Async ngOnInit
ngOnInit()
Returns : any
Async openAcceptGuidelinesPopup
openAcceptGuidelinesPopup(shouldUpdateUserLevelGroupTnc, navigationExtras?, event?)
Parameters :
Name Optional
shouldUpdateUserLevelGroupTnc No
navigationExtras Yes
event Yes
Returns : any
Async openinfopopup
openinfopopup()
Returns : any
Private Async updateGroupTnc
updateGroupTnc(latestVersion, managedBy?)
Parameters :
Name Optional
latestVersion No
managedBy Yes
Returns : any

Properties

Public authService
Type : AuthService
Decorators :
@Inject('AUTH_SERVICE')
fontColor
Type : string[]
Default value : ['#AD632D', '#149D88', '#8D6A00', '#635CDC', '#00695C', '#9E9D24', '#FF8F00']
fromRegistrationFlow
Default value : false
groupList
Type : GroupData[]
Default value : []
groupListLoader
Default value : false
Public groupService
Type : GroupService
Decorators :
@Inject('GROUP_SERVICE')
groupTncVersion
Type : string
headerObservable
Type : any
isGroupTncAcceptenceChecked
Type : boolean
isGuestUser
Type : boolean
themeColors
Type : string[]
Default value : ['#FFDFC7', '#C2ECE6', '#FFE59B', '#DAD4FF', '#80CBC4', '#E6EE9C', '#FFE082']
unregisterBackButton
Type : Subscription
userId
Type : string
import { Component, OnInit, Inject, OnDestroy } from '@angular/core';
import { Router, NavigationExtras } from '@angular/router';
import { AppHeaderService } from '@app/services/app-header.service';
import {
  RouterLinks, PreferenceKey,
  SystemSettingsIds, ProfileConstants
} from '../app.constant';
import {
  AuthService, SharedPreferences, GroupService, Group,
  GroupSearchCriteria, CachedItemRequestSourceFrom, SortOrder,
  ObjectType, TelemetryObject,
  GroupUpdateMembersResponse,
  SystemSettingsService,
  GetSystemSettingsRequest,
  SystemSettings,
  ProfileService,
  ServerProfileDetailsRequest,
  AcceptTermsConditionRequest
} from '@project-sunbird/sunbird-sdk';
import {
  CommonUtilService,
  AppGlobalService,
  TelemetryGeneratorService,
  ImpressionType,
  PageId,
  Environment, InteractType, InteractSubtype, ID, CorReleationDataType
} from '@app/services';
import { Platform, PopoverController } from '@ionic/angular';
import { MyGroupsPopoverComponent } from '../components/popups/sb-my-groups-popover/sb-my-groups-popover.component';
import { animationGrowInTopRight } from '../animations/animation-grow-in-top-right';
import { animationShrinkOutTopRight } from '../animations/animation-shrink-out-top-right';
import { SbProgressLoader } from '@app/services/sb-progress-loader.service';
import { Subscription } from 'rxjs';
import { Location } from '@angular/common';
import { GroupGuideLinesPopoverComponent } from '../components/popups/group-guidelines-popup/group-guidelines-popup.component';
import { CsGroupUpdateGroupGuidelinesRequest } from '@project-sunbird/client-services/services/group/interface';

interface GroupData extends Group {
  initial: string;
}
@Component({
  selector: 'app-my-groups',
  templateUrl: './my-groups.page.html',
  styleUrls: ['./my-groups.page.scss'],
})
export class MyGroupsPage implements OnInit, OnDestroy {
  isGuestUser: boolean;
  groupList: GroupData[] = [];
  themeColors: string[] = ['#FFDFC7', '#C2ECE6', '#FFE59B', '#DAD4FF', '#80CBC4', '#E6EE9C', '#FFE082'];
  fontColor: string[] = ['#AD632D', '#149D88', '#8D6A00', '#635CDC', '#00695C', '#9E9D24', '#FF8F00'];
  groupListLoader = false;
  headerObservable: any;
  userId: string;
  unregisterBackButton: Subscription;
  fromRegistrationFlow = false;
  groupTncVersion: string;
  isGroupTncAcceptenceChecked: boolean;
  constructor(
    @Inject('AUTH_SERVICE') public authService: AuthService,
    @Inject('GROUP_SERVICE') public groupService: GroupService,
    @Inject('SHARED_PREFERENCES') private preferences: SharedPreferences,
    @Inject('SYSTEM_SETTINGS_SERVICE') private systemSettingsService: SystemSettingsService,
    @Inject('PROFILE_SERVICE') private profileService: ProfileService,
    private appGlobalService: AppGlobalService,
    private headerService: AppHeaderService,
    private router: Router,
    private commonUtilService: CommonUtilService,
    private popoverCtrl: PopoverController,
    private sbProgressLoader: SbProgressLoader,
    private telemetryGeneratorService: TelemetryGeneratorService,
    private platform: Platform,
    private location: Location
  ) {
    if (this.router.getCurrentNavigation()) {
      const extras = this.router.getCurrentNavigation().extras.state;
      if (extras) {
        this.fromRegistrationFlow = extras.fromRegistrationFlow;
      }
    }
  }

  async ngOnInit() {
    this.isGroupTncAcceptenceChecked = false;
  }

  private checkUserLoggedIn() {
    this.isGuestUser = !this.appGlobalService.isUserLoggedIn();
  }

  async ionViewWillEnter() {
    this.checkUserLoggedIn();
    if (!this.isGuestUser) {
      this.groupListLoader = true;
    }
    this.handleBackButton();
    this.headerService.showHeaderWithBackButton(['groupInfo']);
    this.headerObservable = this.headerService.headerEventEmitted$.subscribe(eventName => {
      this.handleHeaderEvents(eventName);
    });
    try {
      this.userId = await this.appGlobalService.getActiveProfileUid();
      const groupInfoScreen = await this.preferences.getBoolean(PreferenceKey.CREATE_GROUP_INFO_POPUP).toPromise();
      if (!groupInfoScreen) {
        this.openinfopopup();
        this.preferences.putBoolean(PreferenceKey.CREATE_GROUP_INFO_POPUP, true).toPromise().then();
      }
    } catch (err) {
    }
    if (!this.isGuestUser) {
      this.fetchGroupList();
    }
  }

  async ionViewDidEnter() {
    this.sbProgressLoader.hide({ id: 'login' });
    this.telemetryGeneratorService.generateImpressionTelemetry(
      ImpressionType.VIEW,
      '',
      PageId.MY_GROUP,
      Environment.GROUP
    );
  }

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

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

  handleHeaderEvents($event) {
    switch ($event.name) {
      case 'groupInfo':
        this.generateInteractTelemetry(InteractType.TOUCH, InteractSubtype.INFORMATION_ICON_CLICKED);
        this.openinfopopup();
        break;
      case 'back':
        this.telemetryGeneratorService.generateBackClickedTelemetry(PageId.MY_GROUP, Environment.GROUP, true);
        this.goback();
        break;
    }
  }

  private handleBackButton() {
    this.unregisterBackButton = this.platform.backButton.subscribeWithPriority(10, () => {
      this.telemetryGeneratorService.generateBackClickedTelemetry(
        PageId.MY_GROUP,
        Environment.GROUP,
        false);
      this.goback();
    });
  }

  goback() {
    if (this.fromRegistrationFlow) {
      this.router.navigate([RouterLinks.TABS]);
    } else {
      this.location.back();
    }
  }

  createClassroom() {
    this.generateInteractTelemetry(InteractType.SELECT_CREATE_GROUP, InteractSubtype.CREATE_GROUP_CLICKED, undefined, ID.SELECT_CREATE_GROUP);
    this.router.navigate([`/${RouterLinks.MY_GROUPS}/${RouterLinks.CREATE_EDIT_GROUP}`]);
  }

  login() {
    this.generateInteractTelemetry(InteractType.TOUCH, InteractSubtype.LOGIN_CLICKED);
    this.router.navigate([RouterLinks.SIGN_IN], {state: {skipRootNavigation: true, redirectUrlAfterLogin: RouterLinks.MY_GROUPS}});
  }

  async fetchGroupList() {
    this.groupListLoader = true;
    try {
      const groupSearchCriteria: GroupSearchCriteria = {
        from: CachedItemRequestSourceFrom.SERVER,
        request: {
          filters: {
            userId: this.userId
          },
          sort_by: { name: SortOrder.ASC }
        }
      };
      this.groupList = (await this.groupService.search(groupSearchCriteria).toPromise())
        .map<GroupData>((group, index) => {
          return {
            ...group,
            initial: this.commonUtilService.extractInitial(group.name),
            cardBgColor: this.themeColors[index % this.themeColors.length],
            cardTitleColor: this.fontColor[index % this.fontColor.length]
          };
        });
      this.groupListLoader = false;
      if (!this.isGroupTncAcceptenceChecked) {
        this.checkIfUserAcceptedGuidelines();
      }
    } catch (e) {
      console.error(e);
      this.groupListLoader = false;
    }
  }

  navigateToGroupdetailsPage(event) {
    const telemetryObject = new TelemetryObject(event.data.id, ObjectType.GROUP, undefined);
    this.telemetryGeneratorService.generateInteractTelemetry(InteractType.SELECT_GROUP,
      InteractSubtype.GROUP_CLICKED, Environment.GROUP, PageId.MY_GROUP, telemetryObject, undefined, undefined, undefined,
      ID.SELECT_GROUP);
    const navigationExtras: NavigationExtras = {
      state: {
        groupId: event.data.id
      }
    };
    if (event.data && event.data.hasOwnProperty('visited') && event.data.visited === false) {
      this.openAcceptGuidelinesPopup(false, navigationExtras);
    } else {
      this.router.navigate([`/${RouterLinks.MY_GROUPS}/${RouterLinks.MY_GROUP_DETAILS}`], navigationExtras);
    }
  }

  async openinfopopup() {
    const popover = await this.popoverCtrl.create({
      component: MyGroupsPopoverComponent,
      componentProps: {
        title: this.commonUtilService.translateMessage('ANDROID_NOT_SUPPORTED'),
        body: this.commonUtilService.translateMessage('ANDROID_NOT_SUPPORTED_DESC'),
        buttonText: this.commonUtilService.translateMessage('INSTALL_CROSSWALK')
      },
      cssClass: 'popover-my-groups',
      enterAnimation: animationGrowInTopRight,
      leaveAnimation: animationShrinkOutTopRight,
      backdropDismiss: false,
      showBackdrop: true
    });
    await popover.present();
    const { data } = await popover.onDidDismiss();
    if (data === undefined) { // Backdrop clicked
    } else if (data.closeDeletePopOver) { // Close clicked
    } else if (data.canDelete) {
    }
  }

  async openAcceptGuidelinesPopup(shouldUpdateUserLevelGroupTnc, navigationExtras?, event?) {
    const confirm = await this.popoverCtrl.create({
      component: GroupGuideLinesPopoverComponent,
      componentProps: {
        icon: null,
        shouldUpdateUserLevelGroupTnc
      },
      cssClass: 'sb-popover info',
      backdropDismiss: !shouldUpdateUserLevelGroupTnc
    });
    await confirm.present();
    const { data } = await confirm.onDidDismiss();
    if (data == null) {
      return;
    }
    if (data && data.isLeftButtonClicked) {
      let corRelationList = [];
      if (navigationExtras) {
        corRelationList = [{ id: navigationExtras.state.groupId, type: CorReleationDataType.GROUP_ID }];
      }
      if (!shouldUpdateUserLevelGroupTnc) {
        const request: CsGroupUpdateGroupGuidelinesRequest = {
          userId: this.userId,
          groups: [{
            groupId: navigationExtras.state.groupId,
            visited: true
          }]
        };
        this.generateInteractTelemetry(InteractType.INITIATED, '', corRelationList, ID.ACCEPT_GROUP_GUIDELINES);

        try {
          const updateMemberResponse: GroupUpdateMembersResponse = await this.groupService.updateGroupGuidelines(request).toPromise();
          if (updateMemberResponse.error) {
            this.commonUtilService.showToast('SOMETHING_WENT_WRONG');
          } else {
            this.generateInteractTelemetry(InteractType.SUCCESS, '', corRelationList, ID.ACCEPT_GROUP_GUIDELINES);
          }
          this.router.navigate([`/${RouterLinks.MY_GROUPS}/${RouterLinks.MY_GROUP_DETAILS}`], navigationExtras);
          // Incase of close button click data.isLeftButtonClicked = null so we have put the false condition check
        } catch (err) {
          this.commonUtilService.showToast('SOMETHING_WENT_WRONG');
        }
      } else {
        this.updateGroupTnc(this.groupTncVersion);
      }
    }
  }

  checkIfUserAcceptedGuidelines() {
    const getSystemSettingsRequest: GetSystemSettingsRequest = {
      id: SystemSettingsIds.GROUPS_TNC
    };
    this.systemSettingsService.getSystemSettings(getSystemSettingsRequest).toPromise()
      .then((res: SystemSettings) => {
        if (res && res.value) {
          const value = JSON.parse(res.value);
          this.groupTncVersion = value.latestVersion;
          const req: ServerProfileDetailsRequest = {
            userId: this.userId,
            requiredFields: ProfileConstants.REQUIRED_FIELDS,
            from: CachedItemRequestSourceFrom.SERVER
          };
          this.profileService.getServerProfilesDetails(req).toPromise()
            .then((profileDetails) => {
              if (profileDetails.allTncAccepted
                && profileDetails.allTncAccepted.groupsTnc
                && profileDetails.allTncAccepted.groupsTnc.version) {
                if (profileDetails.allTncAccepted.groupsTnc.version !== this.groupTncVersion) {
                  if (this.groupList.length) {
                    this.openAcceptGuidelinesPopup(true);
                  } else {
                    this.updateGroupTnc(this.groupTncVersion, profileDetails.managedBy);
                  }
                }
              } else {
                if (this.groupList.length) {
                  this.openAcceptGuidelinesPopup(true);
                } else {
                  this.updateGroupTnc(this.groupTncVersion, profileDetails.managedBy);
                }
              }
            });
        }
      }).catch(err => {
        console.log('error :', err);
      });
  }

  private async updateGroupTnc(latestVersion, managedBy?) {
    this.isGroupTncAcceptenceChecked = true;
    try {
      const acceptTermsAndConditionsRequest: AcceptTermsConditionRequest = {
        version: latestVersion,
        tncType: 'groupsTnc'
      };
      if (managedBy) {
        const userId = (await this.profileService.getActiveProfileSession().toPromise()).uid;
        acceptTermsAndConditionsRequest.userId = userId;
      }
      const isTCAccepted = await this.profileService.acceptTermsAndConditions(acceptTermsAndConditionsRequest).toPromise();
    } catch (err) {
      console.error('acceptTermsAndConditions err', err);
    }
    if (this.groupList.length) {
      this.generateInteractTelemetry(InteractType.INITIATED, '', [] , ID.ACCEPT_GROUP_GUIDELINES);
      try {
        const groupsData = [];
        this.groupList.forEach((g) => {
          const gdata = {
            groupId: g.id,
            visited: true
          };
          groupsData.push(gdata);
        });
        const request: CsGroupUpdateGroupGuidelinesRequest = {
          userId: this.userId,
          groups: groupsData
        };
        const groupsUpdateResponse = await this.groupService.updateGroupGuidelines(request).toPromise();
        this.generateInteractTelemetry(InteractType.SUCCESS, '', [], ID.ACCEPT_GROUP_GUIDELINES);
        this.fetchGroupList();
      } catch (err) {
        console.log('groupsUpdateResponse err', err);
      }
    }
  }
  private generateInteractTelemetry(interactType, interactSubType, correlationList?, id?) {
    this.telemetryGeneratorService.generateInteractTelemetry(
      interactType,
      interactSubType,
      Environment.GROUP,
      PageId.MY_GROUP,
      undefined,
      undefined,
      undefined,
      correlationList,
      id
    );
  }
}
<ion-content>
  <div class="my-cr-bg" tabindex="0">
    <div class="my-gr-title">
      <h4 class="my-cr-title" tabindex="0">
        {{'MY_GROUPS' | translate}}
      </h4>
      <img *ngIf="!isGuestUser" src="assets/imgs/ic_group_add_blue.svg" alt="user" (click)="createClassroom()" alt="{{'MY_GROUPS' | translate}}">
    </div>
    <div *ngIf="isGuestUser" class="my-cr-card" tabindex="0">
      <div></div>
      <div>
        <div class="my-cr-card-img">
          <img src="assets/imgs/ic_my_groups.svg" alt="My groups">
        </div>
        <p class="my-cr-subtitle">{{'LOGIN_TO_CREATE_GROUP_DESCRIPTION' | translate}}</p>
      </div>
      <div class="my-cr-btn" tabindex="0">
        <button class="sb-btn-large" (click)="login()">{{'SIGN_IN' | translate}}</button>
      </div>
    </div>

    <div *ngIf="!isGuestUser && !groupList.length && !groupListLoader" class="my-cr-card" tabindex="0">
      <div></div>
      <div>
        <div class="my-cr-card-img">
          <img src="assets/imgs/ic_my_groups.svg" alt="My groups">
        </div>
        <p class="my-cr-subtitle">{{'CREATE_GROUP_DESCRIPTION' | translate}}</p>
      </div>
      <div class="my-cr-btn" tabindex="0">
        <button class="sb-btn-large" (click)="createClassroom()">
          <img src="assets/imgs/ic_group_add_white.svg" role="button" alt="Create Group">
          {{'CREATE_GROUP' | translate}}
        </button>
      </div>
    </div>

    <div *ngFor="let group of groupList" class="mg-list-card-container" tabindex="0">
      <sb-group-card [isMobile]="true" [isAdmin]="group.memberRole === 'admin'" [group]="group"
        [cardTitleColor]="group.cardTitleColor" [cardBgColor]="group.cardBgColor"
        (cardClick)="navigateToGroupdetailsPage($event)" [isSuspended]="group.status === 'suspended'" [suspendBadgeText]="'Deactivated'"></sb-group-card>
    </div>
    <div *ngIf="!isGuestUser && !groupList.length && groupListLoader">
      <div *ngFor="let item of [0,1,2,3,4,5,6,7,8,9,10]">
        <sb-group-card [isMobile]="true" [isLoading]="true"></sb-group-card>
      </div>
    </div>

  </div>

</ion-content>

./my-groups.page.scss

@import "src/assets/styles/_variables.scss";
.my-cr-bg {
  height: 100%;
  background: linear-gradient(#E5EDF5, #E5EDF5 88px, white 88px, white 100%);
  padding: 0 8px;
}
.my-gr-title{
  display: flex;
  justify-content: space-between;
  img {
    width: 1.5rem;
  }
}
.my-cr-title{
  color: $blue;
  font-family: "Noto Sans", sans-serif;
  font-size: 1rem;
  font-weight: bold;
  letter-spacing: 0;
  line-height: 1rem;
  padding: 24px 16px 16px;
  margin: 0;
  position: relative;
  img{
    position: absolute;
    right: 1rem;
    top: 1.25rem;
  }
}

.my-cr-card{
  border-radius: 2px;
  background-color: #FFFFFF;
  box-shadow: 0 3px 5px 4px rgba(0,0,0,0.05);
  margin: 0 8px;
  text-align: center;
  display: flex;
  flex-direction: column;
  height: 80vh;
  justify-content: space-between;
}

.my-cr-card-img{
  padding-top: 48px;
  padding-bottom: 16px;
}

.my-cr-subtitle{
  color: $gray-800;
  font-family: "Noto Sans", sans-serif;
  font-size: 1rem;
  letter-spacing: 0;
  line-height: 1.375rem;
  text-align: center;
  padding: 20px 10%;
}

.mg-list-card-container{
  margin-bottom: 8px;
}

.my-cr-btn{
    padding: 0px 8px 24px;
    ion-button{
      --background: $blue !important;
      
    }
    .sb-btn-large{
      padding: 16px 0px 16px 0px;
      img{
        margin-right: 8px;
        position: relative;
        bottom: 0.125rem;
      }
    }
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""