File

src/app/modules/shared-feature/components/global-consent-pii/global-consent-pii.component.ts

Implements

OnInit

Metadata

Index

Properties
Methods
Inputs
Outputs

Constructor

constructor(csUserService: CsUserService, toasterService: ToasterService, userService: UserService, resourceService: ResourceService, tncService: TncService, utilService: UtilService, popupControlService: PopupControlService, activatedRoute: ActivatedRoute, coursesService: CoursesService, router: Router, generaliseLabelService: GeneraliseLabelService)
Parameters :
Name Type Optional
csUserService CsUserService No
toasterService ToasterService No
userService UserService No
resourceService ResourceService No
tncService TncService No
utilService UtilService No
popupControlService PopupControlService No
activatedRoute ActivatedRoute No
coursesService CoursesService No
router Router No
generaliseLabelService GeneraliseLabelService No

Inputs

collection
Type : any
consentConfig
Type : any
isglobalConsent
Type : any
profileInfo
Type : any
showConsentPopup
Type : any
type
Type : any

Outputs

close
Type : EventEmitter
consentShare
Type : EventEmitter

Methods

checkQueryParams
checkQueryParams()
Returns : void
fetchTncData
fetchTncData()
Returns : void
getDeclarationReqObject
getDeclarationReqObject(usersProfile)
Parameters :
Name Optional
usersProfile No
Returns : { operation: string; userId: any; orgId: any; info: any; }
getUserConsent
getUserConsent()
Returns : void
getUserInformation
getUserInformation()
Returns : void
ngOnDestroy
ngOnDestroy()
Returns : void
ngOnInit
ngOnInit()
Returns : void
removeQueryParam
removeQueryParam()
Returns : void
saveConsent
saveConsent()
Returns : void
showAndHidePopup
showAndHidePopup(mode: boolean)
Parameters :
Name Type Optional
mode boolean No
Returns : void
toggleEditSetting
toggleEditSetting()
Returns : void
updateUserConsent
updateUserConsent(isActive: boolean)
Parameters :
Name Type Optional
isActive boolean No
Returns : void
updateUserDeclaration
updateUserDeclaration(request)
Parameters :
Name Optional
request No
Returns : void

Properties

consentPii
Type : string
Default value : 'Yes'
editSetting
Default value : false
Public generaliseLabelService
Type : GeneraliseLabelService
instance
Type : string
isDataShareOn
Default value : false
isOpen
Default value : false
isTncAgreed
Default value : false
lastUpdatedOn
Type : string
Default value : ''
Public popupControlService
Type : PopupControlService
profileDetailsModal
Decorators :
@ViewChild('profileDetailsModal')
Public resourceService
Type : ResourceService
showSettingsPage
Type : boolean
showTncPopup
Default value : false
termsAndConditionLink
Type : string
Public tncService
Type : TncService
unsubscribe
Default value : new Subject<void>()
userInformation
Type : []
Default value : []
Public userService
Type : UserService
Private usersProfile
Type : any
Public utilService
Type : UtilService
import { Component, Inject, Input, OnInit, ViewChild, Output, EventEmitter } from '@angular/core';
import { Consent, ConsentStatus } from '@project-sunbird/client-services/models';
import { CsUserService } from '@project-sunbird/client-services/services/user/interface';
import { TncService, UserService, CoursesService, GeneraliseLabelService } from '@sunbird/core';
import { ResourceService, ServerResponse, ToasterService, UtilService } from '@sunbird/shared';
import * as _ from 'lodash-es';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { PopupControlService } from '../../../../service/popup-control.service';
import { ActivatedRoute, Router } from '@angular/router';

@Component({
  selector: 'app-global-consent-pii',
  templateUrl: './global-consent-pii.component.html',
  styleUrls: ['./global-consent-pii.component.scss']
})
export class GlobalConsentPiiComponent implements OnInit {

  @Input() collection;
  @Input() type;
  @Input() showConsentPopup;
  @Input() consentConfig;
  @Input() isglobalConsent;
  @Input() profileInfo;
  @ViewChild('profileDetailsModal') profileDetailsModal;
  @Output() close = new EventEmitter<any>();
  @Output() consentShare = new EventEmitter<any>();
  isOpen = false;
  instance: string;
  consentPii = 'Yes';
  isDataShareOn = false;
  lastUpdatedOn = '';
  userInformation = [];
  editSetting = false;
  isTncAgreed = false;
  // showConsentPopup = false;
  showTncPopup = false;
  termsAndConditionLink: string;
  unsubscribe = new Subject<void>();
  private usersProfile: any;
  showSettingsPage: boolean;
  constructor(
    @Inject('CS_USER_SERVICE') private csUserService: CsUserService,
    private toasterService: ToasterService,
    public userService: UserService,
    public resourceService: ResourceService,
    public tncService: TncService,
    public utilService: UtilService,
    public popupControlService: PopupControlService,
    private activatedRoute: ActivatedRoute,
    private coursesService: CoursesService,
    private router: Router,
    public generaliseLabelService: GeneraliseLabelService
  ) {
    this.instance = (<HTMLInputElement>document.getElementById('instance'))
      ? (<HTMLInputElement>document.getElementById('instance')).value.toUpperCase() : 'SUNBIRD';
  }

  ngOnInit() {
    this.usersProfile = _.cloneDeep(this.userService.userProfile);
    this.getUserInformation();
    this.getUserConsent();
    if (this.isglobalConsent || this.type === 'program-consent') {
      this.showSettingsPage = false;
    } else {
      this.showSettingsPage = true;
    }
    this.checkQueryParams();

    this.coursesService.revokeConsent
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((res) => {
        this.updateUserConsent(false);
      });
  }

  checkQueryParams() {
    this.activatedRoute.queryParams
      .pipe(takeUntil(this.unsubscribe))
      .subscribe(response => {
        if (response.consent) {
          if (this.type === 'course-consent' || this.type === 'global-consent') {
            this.showConsentPopup = true;
          }
          this.removeQueryParam();
        }
      });
  }

  getUserInformation() {
    this.userInformation['name'] = this.usersProfile.lastName ?
     `${this.usersProfile.firstName} ${this.usersProfile.lastName}` : this.usersProfile.firstName;
    this.userInformation['userid'] = this.usersProfile.userId;
    this.userInformation['emailId'] = this.usersProfile.email;
    this.userInformation['phone'] = this.usersProfile.phone;
    if (this.usersProfile && this.usersProfile.externalIds) {
      _.forEach(this.usersProfile.externalIds, (externaleId) => {
        if (externaleId.provider === this.usersProfile.channel) {
          this.userInformation['externalId'] = externaleId.id;
        }
      });
    }

    if (_.get(this.usersProfile, 'userLocations.length')) {
      this.usersProfile.userLocations.forEach(locDetail => {
        switch (locDetail.type) {
          case 'state':
            this.userInformation['state'] = locDetail.name;
            break;
          case 'district':
            this.userInformation['district'] = locDetail.name;
            break;
          case 'block':
            this.userInformation['block'] = locDetail.name;
            break;
          case 'school':
            this.userInformation['schoolName'] = locDetail.name;
            this.userInformation['schoolId'] = locDetail.code;
            break;
        }
      });
    }

    if (_.get(this.usersProfile, 'declarations.length')) {
      for (const [key, value] of Object.entries(this.usersProfile.declarations[0].info)) {
        switch (key) {
          case 'declared-email':
            this.userInformation['emailId'] = value;
            break;
          case 'declared-phone':
            this.userInformation['phone'] = value;
            break;
          case 'declared-school-udise-code':
            this.userInformation['schoolId'] = this.userInformation['schoolId'] || value;
            break;
          case 'declared-school-name':
            this.userInformation['schoolName'] = this.userInformation['schoolName'] || value;
            break;
        }
      }
    }

    if (this.profileInfo) {
      this.userInformation = _.assign(this.userInformation, this.profileInfo);
    }
  }

  fetchTncData() {
    this.tncService.getTncConfig().pipe(takeUntil(this.unsubscribe)).subscribe((data: ServerResponse) => {
      const response = _.get(data, 'result.response.value');
      if (response) {
        try {
          const tncConfig = this.utilService.parseJson(response);
          const version = _.get(tncConfig, 'latestVersion') || {};
          this.termsAndConditionLink = tncConfig[version].url;
        } catch (e) {
          this.toasterService.error(_.get(this.resourceService, 'messages.fmsg.m0004'));
        }
      }
    }, () => {
      this.toasterService.error(_.get(this.resourceService, 'messages.fmsg.m0004'));
    }
    );
  }

  saveConsent() {
    const isActive = _.upperCase(this.consentPii) === 'YES';

    if (isActive) {
      this.showConsentPopup = true;
    } else {
      this.updateUserConsent(isActive);
    }

    this.toggleEditSetting();
  }

  toggleEditSetting() {
    this.editSetting = !this.editSetting;
  }

  showAndHidePopup(mode: boolean) {
    this.showTncPopup = mode;
    this.popupControlService.changePopupStatus(true);
  }

  getUserConsent() {
    const request = {
      userId: this.userService.userid,
      consumerId: '',
      objectId: ''
    };
    if (this.type === 'course-consent') {
      request.consumerId = this.collection ? this.collection.channel : '';
      request.objectId = this.collection ? this.collection.identifier : '';
    } else if ( this.type === 'global-consent') {
      request.consumerId = this.userService.channel;
      request.objectId = this.userService.channel;
      const declReq = [];
      if (this.getDeclarationReqObject(this.usersProfile)) {
        declReq.push(this.getDeclarationReqObject(this.usersProfile));
        this.updateUserDeclaration(declReq);
      }
    } else if(this.type === 'program-consent'){
      request.consumerId = this.collection.rootOrganisations;
      request.objectId = this.collection.programId
    }
    this.csUserService.getConsent(request, { apiPath: '/learner/user/v1' })
      .pipe(takeUntil(this.unsubscribe))
      .subscribe(res => {
        if (this.type === 'global-consent') {
          this.showConsentPopup = false;
          this.type = '';
          this.isglobalConsent = false;
        }
        this.isDataShareOn = _.get(res, 'consents[0].status') === ConsentStatus.ACTIVE;
        this.consentPii = this.isDataShareOn ? 'No' : 'Yes';
        this.lastUpdatedOn = _.get(res, 'consents[0].lastUpdatedOn') || '';
      }, error => {
        console.error('error', error);
        if (error.code === 'HTTP_CLIENT_ERROR' && _.get(error, 'response.responseCode') === 404) {
          this.showConsentPopup = true;
        } else {
          this.toasterService.error(_.get(this.resourceService, 'messages.fmsg.m0004'));
        }
      });
  }

  updateUserConsent(isActive: boolean) {
    this.showConsentPopup = false;
    const request: Consent = {
      status: isActive ? ConsentStatus.ACTIVE : ConsentStatus.REVOKED,
      userId: this.userService.userid,
      consumerId: '',
      objectId: '',
      objectType: ''
    };
    if (this.type === 'course-consent') {
      request.consumerId = this.collection ? this.collection.channel : '';
      request.objectId = this.collection ? this.collection.identifier : '';
      request.objectType = 'Collection';
    } else if ( this.type === 'global-consent') {
      request.consumerId = this.userService.channel;
      request.objectId = this.userService.channel;
      request.objectType = 'Organisation';
    } else if(this.type === 'program-consent'){
      request.consumerId = this.collection.rootOrganisations;
      request.objectId = this.collection.programId;
      request.objectType = 'Program'
    }
    this.csUserService.updateConsent(request, { apiPath: '/learner/user/v1' })
      .pipe(takeUntil(this.unsubscribe))
      .subscribe(() => {
        if(this.type === 'program-consent'){
          this.consentShare.emit({consent:true})
        }
        this.type !== 'program-consent' && this.toasterService.success(_.get(this.resourceService, 'messages.smsg.dataSettingSubmitted'));
        this.getUserConsent();
        this.close.emit();
        this.popupControlService.changePopupStatus(true);
      }, error => {
        this.isTncAgreed = false;
        this.toasterService.error(_.get(this.resourceService, 'messages.emsg.m0005'));
        console.error('Error while updating user consent', error);
        if(this.type === 'program-consent'){
          this.consentShare.emit({consent:false})
        }
      });
  }

  removeQueryParam() {
    this.router.navigate([], {
      queryParams: { 'consent': null },
      queryParamsHandling: 'merge',
      replaceUrl: true
    });
  }

  updateUserDeclaration(request) {
    this.csUserService.updateUserDeclarations(request, { apiPath: '/learner/user/v1' })
      .pipe(takeUntil(this.unsubscribe))
      .subscribe(() => {
        this.toasterService.success(_.get(this.resourceService, 'messages.smsg.m0037'));
    }, err => {
      this.toasterService.error(this.resourceService.messages.emsg.m0052);
    });
  }
  getDeclarationReqObject(usersProfile) {
    let userExternalId = null;
    if (usersProfile && usersProfile.externalIds) {
      _.forEach(usersProfile.externalIds, (externaleId) => {
        if (externaleId.provider === usersProfile.channel) {
          userExternalId = externaleId.id;
        }
      });
    }
    const info: any = {
      'declared-ext-id': userExternalId,
      'declared-phone': '',
      'declared-email': ''
    };
    const declarationObj = {
      operation: 'add',
      userId : usersProfile.userId,
      orgId: usersProfile.rootOrgId,
      info: info
    };
    if (userExternalId) {
      return declarationObj;
    } else {
      return null;
    }

  }

  ngOnDestroy() {
    this.unsubscribe.next();
    this.unsubscribe.complete();
    if (_.get(this.profileDetailsModal, 'deny')) {
      this.profileDetailsModal.deny();
    }
  }

}
<mat-accordion class="sb-mat-accordion mb-16" *ngIf="showSettingsPage">
  <mat-expansion-panel>
    <mat-expansion-panel-header>
      <mat-panel-title class="sb-mat-accordion__title">
        {{resourceService?.frmelmnts?.lbl?.dataSetting}}
      </mat-panel-title>
    </mat-expansion-panel-header>
    <div class="sb-mat-accordion__content" role="region" id="dataSetting"
      aria-labelledby="dataSetting">
      <label class="fnormal font-weight-normal text-uppercase">{{resourceService?.frmelmnts?.lbl?.dataSharingIs}}
        <span>{{ isDataShareOn ? resourceService?.frmelmnts?.lbl?.on : resourceService?.frmelmnts?.lbl?.off }}</span>
      </label>

      <p class="fsmall mb-0" *ngIf="isDataShareOn">{{resourceService?.frmelmnts?.lbl?.dataShareOnNote}}</p>
      <p class="fsmall mb-0" *ngIf="!isDataShareOn">{{resourceService?.frmelmnts?.lbl?.dataShareOffNote}}</p>
      <label class="fsmall font-weight-normal data-labels"
        *ngIf="lastUpdatedOn">{{resourceService?.frmelmnts?.lbl?.lastUpdatedOn}} {{lastUpdatedOn | date
        :'dd/MM/yyyy'}}</label>

      <div class="d-flex flex-ai-end flex-jc-flex-end">
        <button class="sb-btn sb-btn-normal sb-btn-link sb-btn-link-primary font-weight-bold"
          (click)="toggleEditSetting()" tabindex="0">
          {{ editSetting ? resourceService?.frmelmnts?.btn?.close : resourceService?.frmelmnts?.lbl?.editSetting }}
        </button>
      </div>

      <div *ngIf="editSetting" class="sb-update-data-settings">
        <hr>
        <label
          class="fsmall mb-0 font-weight-bold data-labels">{{resourceService?.frmelmnts?.lbl?.updateSetting}}</label>
        <div class="d-flex py-8 flex-w-wrap">
          <div class="sb-radio-btn-checkbox sb-radio-btn-primary">
            <input [value]="'Yes'" id="shareConsent" type="radio" [(ngModel)]="consentPii">
            <label for="shareConsent" class="fsmall">{{resourceService?.frmelmnts?.lbl?.shareProfileDetails}}</label>
          </div>
          <div class="sb-radio-btn-checkbox sb-radio-btn-primary">
            <input [value]="'No'" id="noShareContent" type="radio" [(ngModel)]="consentPii">
            <label for="noShareContent"
              class="fsmall">{{resourceService?.frmelmnts?.lbl?.notShareProfileDetails}}</label>
          </div>
        </div>
        <button class="sb-btn sb-btn-normal sb-btn-outline-primary w-100 text-uppercase" tabindex="0"
          (click)="saveConsent()">{{resourceService?.frmelmnts?.btn?.save}}</button>
      </div>
    </div>
  </mat-expansion-panel>
</mat-accordion>

<app-modal-wrapper *ngIf="showConsentPopup" [config]="{disableClose: true, size: 'normal', panelClass: ['overflow-visible', 'material-modal']}"
  (dismiss)="showConsentPopup = false;" #profileDetailsModal>
  <ng-template sbModalContent>
    <div class="sb-mat__modal">

          <!--Header-->
          <div mat-dialog-title class="mb-0 px-16">
            <div class="title">{{resourceService?.frmelmnts?.lbl?.consentsharedetail}}</div>
          </div>
          <!--/Header-->

          <!--Content-->
          <div class="sb-mat__modal__content d-flex flex-dc o-y-visible lineHeight-normal">
            <div class="profile-fields">
              <div class="d-flex mb-16 fnormal">
                <label
                  class="font-weight-bold profile-field-label">{{resourceService?.frmelmnts?.lbl?.dashboardsortbyusername}}<span
                    class="mx-8">:</span></label>
                <div class="font-weight-normal">{{userInformation.name || '-'}}</div>
              </div>
              <div class="d-flex mb-16 fnormal">
                <label class="font-weight-bold profile-field-label">{{resourceService?.frmelmnts?.lbl?.state}}<span
                    class="mx-8">:</span></label>
                <div class="font-weight-normal">{{userInformation.state || '-'}}</div>
              </div>
              <div class="d-flex mb-16 fnormal">
                <label class="font-weight-bold profile-field-label">{{resourceService?.frmelmnts?.lbl?.userId}}<span
                    class="mx-8">:</span></label>
                <div class="font-weight-normal">{{userInformation.userid || '-'}}</div>
              </div>
              <div class="d-flex mb-16 fnormal">
                <label class="font-weight-bold profile-field-label">{{resourceService?.frmelmnts?.lbl?.externalId}}<span
                    class="mx-8">:</span></label>
                <div class="font-weight-normal">{{userInformation.externalId || '-'}}</div>
              </div>

              <div class="d-flex mb-16 fnormal">
                <label class="font-weight-bold profile-field-label">{{resourceService?.frmelmnts?.lbl?.district}}<span
                    class="mx-8">:</span></label>
                <div class="font-weight-normal">{{userInformation.district || '-'}}</div>
              </div>

              <div class="d-flex mb-16 fnormal">
                <label class="font-weight-bold profile-field-label">{{resourceService?.frmelmnts?.lbl?.block}}<span
                    class="mx-8">:</span></label>
                <div class="font-weight-normal">{{userInformation.block || '-'}}</div>
              </div>

              <div class="d-flex mb-16 fnormal">
                <label class="font-weight-bold profile-field-label">{{resourceService?.frmelmnts?.lbl?.schoolId}}<span
                    class="mx-8">:</span></label>
                <div class="font-weight-normal">{{userInformation.schoolId || '-'}}</div>
              </div>

              <div class="d-flex mb-16 fnormal">
                <label class="font-weight-bold profile-field-label">{{resourceService?.frmelmnts?.lbl?.schoolName}}<span
                    class="mx-8">:</span></label>
                <div class="font-weight-normal">{{userInformation.schoolName || '-'}}</div>
              </div>

              <div class="d-flex mb-16 fnormal">
                <label
                  class="font-weight-bold profile-field-label">{{resourceService?.frmelmnts?.lbl?.mobileNumber}}<span
                    class="mx-8">:</span></label>
                <div class="font-weight-normal">{{userInformation.phone || '-'}}</div>
              </div>

              <div class="d-flex mb-16 fnormal">
                <label class="font-weight-bold profile-field-label">{{resourceService?.frmelmnts?.lbl?.emailId}}<span
                    class="mx-8">:</span></label>
                <div class="font-weight-normal">{{userInformation.emailId || '-'}}</div>
              </div>
            </div>
            <div class="mb-16 fnormal font-weight-normal" *ngIf="type === 'course-consent' || type === 'program-consent'">
              <img src="../../../../../../assets/images/info-icon.svg" width="14px" height="14px" class="mr-8"
                alt="info">{{resourceService?.frmelmnts?.lbl?.canEditProfileDetails}}
            </div>

            <p class="mb-0fnormal font-weight-normal">
              <input type="checkbox" [(ngModel)]="isTncAgreed" class="mr-8" aria-label="term and condition checkbox">
              {{consentConfig.tncText | interpolate:'{instance}': instance}}
              <a class="sb-color-primary" href="javascript:void(0)" tabindex="0"
                (click)="showTncPopup=true">{{consentConfig.tncLink | interpolate:'{instance}':
                resourceService?.instance}}</a>
            </p>
          </div>
          <!--/Content-->
          <!--Actions-->
          <div class="sb-mat__modal__actions">
            <button class="sb-btn  sb-btn-normal sb-btn-outline-primary text-uppercase" tabindex="0"
              (click)="updateUserConsent(false)"
              *ngIf="type === 'course-consent' || type === 'program-consent'">{{resourceService?.frmelmnts?.lbl?.dontShare}}</button>
            <button type="button" tabindex="0" [ngClass]="{'sb-btn-disabled': !isTncAgreed}" [disabled]="!isTncAgreed"
              class="sb-btn sb-btn-normal sb-btn-primary text-uppercase ml-8" (click)="updateUserConsent(true)"
              *ngIf="type === 'global-consent'">{{resourceService?.frmelmnts?.lbl?.continue}}</button>
            <button type="button" tabindex="0" [ngClass]="{'sb-btn-disabled': !isTncAgreed}" [disabled]="!isTncAgreed"
            class="sb-btn sb-btn-normal sb-btn-primary text-uppercase ml-8" (click)="updateUserConsent(true)"
            *ngIf="type === 'course-consent' || type === 'program-consent'">{{resourceService?.frmelmnts?.lbl?.share}}</button>
          </div>
          <!--/Actions-->


    </div>
  </ng-template>
</app-modal-wrapper>

<app-tnc-popup (close)="showAndHidePopup(false)" [tncUrl]="termsAndConditionLink" *ngIf="showTncPopup">
</app-tnc-popup>

./global-consent-pii.component.scss

@use "@project-sunbird/sb-styles/assets/mixins/mixins" as *;

.sb-modal-profile-details {
    input[type="checkbox"] {
        width: calculateRem(16px);
        height: calculateRem(16px);
        position: relative;
        top: calculateRem(2px);
    }
}

.profile-fields{
word-break: break-all;
    .profile-field-label{
        width: calculateRem(150px);
        @media screen and (max-width:768px) {
          width: auto;
        }
    }
}

Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""