File

src/app/modules/certificate/components/certificate-details/certificate-details.component.ts

Implements

OnInit OnDestroy

Metadata

Index

Properties
Methods

Constructor

constructor(activatedRoute: ActivatedRoute, certificateService: CertificateService, resourceService: ResourceService, configService: ConfigService, userService: UserService, playerService: PublicPlayerService, router: Router, tenantService: TenantService, CsCertificateService: CsCertificateService, toasterService: ToasterService)
Parameters :
Name Type Optional
activatedRoute ActivatedRoute No
certificateService CertificateService No
resourceService ResourceService No
configService ConfigService No
userService UserService No
playerService PublicPlayerService No
router Router No
tenantService TenantService No
CsCertificateService CsCertificateService No
toasterService ToasterService No

Methods

certificateVerify
certificateVerify()

It will call the validate cert. api and course_details api (after taking courseId)

Returns : void
getCodeLength
getCodeLength(event: any)

To handle verify button enable/disable fucntionality

Parameters :
Name Type Optional
event any No
Returns : void
getCourseVideoUrl
getCourseVideoUrl(courseId: string)

to get the certtificate video url and courseId from that url

Parameters :
Name Type Optional
courseId string No
Returns : void
navigateToCoursesPage
navigateToCoursesPage()

To redirect to courses tab (for mobile device, they will handle 'href' change)

Returns : void
ngOnDestroy
ngOnDestroy()
Returns : void
ngOnInit
ngOnInit()
Returns : void
playContent
playContent(contentId: string)

to play content on the certificate details page

Parameters :
Name Type Optional
contentId string No
Returns : void
processVideoUrl
processVideoUrl(url: string)
Parameters :
Name Type Optional
url string No
Returns : void
setTelemetryData
setTelemetryData()

To set the telemetry

Returns : void
validateCertificate
validateCertificate()

Function to validate certificate if URL has data params

Returns : void
validateTCertificate
validateTCertificate()

Function to validate certificate if URL has t params

Returns : void

Properties

Public activatedRoute
Type : ActivatedRoute
certificateCode
Type : string
Public certificateService
Type : CertificateService
codeInputField
Type : ElementRef
Decorators :
@ViewChild('codeInputField')
Public configService
Type : ConfigService
contentId
Type : string
courseName
Type : string
enableVerifyButton
Default value : false
error
Default value : false
instance
Type : string
isInvalidCertificate
Type : boolean
Default value : false
issuedOn
Type : string
loader
Type : boolean
logo
Type : string
pageId
Type : string
playerConfig
Type : PlayerConfig
Public playerService
Type : PublicPlayerService
recipient
Type : string

To store the certificate details data

Public resourceService
Type : ResourceService
Public router
Type : Router
showVideoThumbnail
Default value : true
telemetryCdata
Type : Array<literal type>
Default value : []
telemetryImpressionData
Type : IImpressionEventInput
tenantDataSubscription
Type : Subscription
tenantName
Type : string
Public tenantService
Type : TenantService
Public userService
Type : UserService
validateRCCertificate
Type : boolean
Default value : false
viewCertificate
Type : boolean
watchVideoLink
Type : string
wrongCertificateCode
Default value : false
import { PublicPlayerService } from '@sunbird/public';
import {CertificateService, UserService, TenantService} from '@sunbird/core';
import { ServerResponse, ResourceService, ConfigService, PlayerConfig, ToasterService } from '@sunbird/shared';
import { Component, OnInit, ViewChild, ElementRef, OnDestroy, Inject } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import * as _ from 'lodash-es';
import dayjs from 'dayjs';
import { IImpressionEventInput } from '@sunbird/telemetry';
import { Subscription} from 'rxjs';
import { CsCertificateService } from '@project-sunbird/client-services/services/certificate/interface';

@Component({
  selector: 'app-certificate-details',
  templateUrl: './certificate-details.component.html',
  styleUrls: ['./certificate-details.component.scss']
})
export class CertificateDetailsComponent implements OnInit , OnDestroy {
  loader: boolean;
  viewCertificate: boolean;
  error = false;
  enableVerifyButton = false;
  certificateCode: string;
  wrongCertificateCode = false;
  instance: string;
  telemetryImpressionData: IImpressionEventInput;
  telemetryCdata: Array<{}> = [];
  pageId: string;
  playerConfig: PlayerConfig;
  contentId: string;
  showVideoThumbnail = true;
  logo: string;
  tenantName: string;
  tenantDataSubscription: Subscription;

  /** To store the certificate details data */
  recipient: string;
  courseName: string;
  issuedOn: string;
  watchVideoLink: string;
  validateRCCertificate: boolean = false;
  @ViewChild('codeInputField') codeInputField: ElementRef;
  isInvalidCertificate: boolean = false;

  constructor(
    public activatedRoute: ActivatedRoute,
    public certificateService: CertificateService,
    public resourceService: ResourceService,
    public configService: ConfigService,
    public userService: UserService,
    public playerService: PublicPlayerService,
    public router: Router,
    public tenantService: TenantService,
    @Inject('CS_CERTIFICATE_SERVICE') private CsCertificateService: CsCertificateService,
    private toasterService: ToasterService,
  ) { }

  ngOnInit() {
    this.instance = _.upperCase(this.resourceService.instance);
    this.pageId = this.activatedRoute.snapshot.data.telemetry.pageid;
    if (_.get(this.activatedRoute, 'snapshot.queryParams.data')) {
      this.validateRCCertificate = true;
      this.validateCertificate();
    } else if (_.get(this.activatedRoute, 'snapshot.queryParams.t')) {
      this.validateRCCertificate = true;
      this.validateTCertificate();
    }
    this.setTelemetryData();
    this.tenantDataSubscription = this.tenantService.tenantData$.subscribe(data => {
      if (data && !data.err && data.tenantData) {
        this.logo = data.tenantData.logo;
        this.tenantName = data.tenantData.titleName;
      }
    });
  }

  /** It will call the validate cert. api and course_details api (after taking courseId) */
  certificateVerify() {
    this.loader = true;
    const request = {
      request: {
        'certId': this.activatedRoute.snapshot.params.uuid,
        'accessCode': _.trim(this.certificateCode),
        'verifySignature': true,
      }
    };
    this.certificateService.validateCertificate(request).subscribe(
      (data: ServerResponse) => {
        if (_.get(data, 'result.response.related.certVideoUrl')) {
          this.watchVideoLink = _.get(data, 'result.response.related.certVideoUrl');
          this.processVideoUrl(this.watchVideoLink);
        } else {
          this.getCourseVideoUrl(_.get(data, 'result.response.related.courseId'));
        }
        const certData = _.get(data, 'result.response.json');
        this.loader = false;
        this.viewCertificate = true;
        this.recipient = _.get(certData, 'recipient.name');
        this.courseName = _.get(certData, 'badge.name');
        this.issuedOn = dayjs(new Date(_.get(certData, 'issuedOn'))).format('DD MMM YYYY');
      },
      (err) => {
        this.wrongCertificateCode = true;
        this.loader = false;
        this.codeInputField.nativeElement.value = '';
        this.codeInputField.nativeElement.focus();
        this.enableVerifyButton = false;
      }
    );
  }
  /** To handle verify button enable/disable fucntionality */
  getCodeLength(event: any) {
    this.wrongCertificateCode = false;
    if (event.target.value.length === 6) {
      this.enableVerifyButton = true;
    } else {
      this.enableVerifyButton = false;
    }
  }
  /** To redirect to courses tab (for mobile device, they will handle 'href' change) */
  navigateToCoursesPage() {
    if (this.activatedRoute.snapshot.queryParams.clientId === 'android') {
      window.location.href = '/explore-course';
    } else {
      this.router.navigate(['/explore-course']);
    }
  }
  /** To set the telemetry*/
  setTelemetryData() {
    const context = { env: this.activatedRoute.snapshot.data.telemetry.env };
    if (_.get(this.activatedRoute, 'snapshot.queryParams.clientId') === 'android' &&
    _.get(this.activatedRoute, 'snapshot.queryParams.context')) {
      const telemetryData = JSON.parse(decodeURIComponent(_.get(this.activatedRoute, 'snapshot.queryParams.context')));
      context['env'] = telemetryData.env;
    }
    this.telemetryImpressionData = {
      context: context,
      edata: {
        type: this.activatedRoute.snapshot.data.telemetry.type,
        pageid: this.pageId,
        uri: this.router.url
      }
    };
    this.telemetryCdata = [
      {
        id: 'course:qrcode:scan:cert',
        type: 'Feature'
      },
      {
        id: 'SB-13854',
        type: 'Task'
      }
    ];
  }

  /** to get the certtificate video url and courseId from that url */
  getCourseVideoUrl(courseId: string) {
    this.playerService.getCollectionHierarchy(courseId).subscribe(
      (response: ServerResponse) => {
        this.watchVideoLink = _.get(response, 'result.content.certVideoUrl');
        this.processVideoUrl(this.watchVideoLink);
      }, (error) => {
      });
  }

  processVideoUrl(url: string) {
    if (url) {
      const splitedData = url.split('/');
      splitedData.forEach((value) => {
        if (value.includes('do_')) {
          this.contentId = value;
        }
      });
    }
  }

  /** to play content on the certificate details page */
  playContent(contentId: string) {
    this.showVideoThumbnail = false;
    const option = { params: this.configService.appConfig.ContentPlayer.contentApiQueryParams };
    this.playerService.getContent(contentId, option).subscribe(
      (response) => {
        const contentDetails = {
          contentId: contentId,
          contentData: response.result.content
        };
        this.playerConfig = this.playerService.getConfig(contentDetails);
      },
      (err) => {
      });
  }

  ngOnDestroy() {
    if (this.tenantDataSubscription) {
      this.tenantDataSubscription.unsubscribe();
    }
  }

  /**
   * @description
   * Function to validate certificate if URL has `data` params
   */
  validateCertificate() {
    this.loader = true;
    let url = _.get(this.activatedRoute, 'snapshot.queryParams.data').toString();
    url = url.replace(/ /g, "+");
    this.CsCertificateService
      .getEncodedData(url)
      .then((resp) => {
        let requestBody = {
          certificateData: resp,
          schemaName: 'certificate',
          certificateId: _.get(this.activatedRoute, 'snapshot.params.uuid'),
        };
        this.CsCertificateService.verifyCertificate(requestBody, {
          apiPath: '/learner/certreg/v2',
          apiPathLegacy: '/certreg/v1',
          rcApiPath: '/learner/rc/${schemaName}/v1',
        }).subscribe(
          (data) => {
            const certData = _.get(data, 'certificateData');
            this.loader = false;
            if (_.get(data, 'verified')) {
              this.viewCertificate = true;
              this.recipient = _.get(certData, 'issuedTo');
              this.courseName = _.get(certData, 'trainingName');
              this.issuedOn = dayjs(new Date(_.get(certData, 'issuanceDate'))).format('DD MMM YYYY');
            } else {
              this.viewCertificate = false;
              this.isInvalidCertificate = true;
            }
          },
          (err) => {
            this.loader = false;
            this.viewCertificate = false;
            this.isInvalidCertificate = true;
            this.toasterService.error(this.resourceService.messages.emsg.m0005);
          }
        );
      }).catch(error => {
        this.viewCertificate = false;
        this.isInvalidCertificate = true;
      });
  }
  /**
   * @description
   * Function to validate certificate if URL has `t` params
   */
  validateTCertificate() {
    let requestBody = {
      schemaName: 'certificate',
      certificateId: _.get(this.activatedRoute, 'snapshot.params.uuid'),
    };
    this.CsCertificateService.verifyCertificate(requestBody, {
      apiPath: '/learner/certreg/v2',
      apiPathLegacy: '/certreg/v1',
      rcApiPath: '/learner/rc/${schemaName}/v1',
    }).subscribe(
      (data) => {
        const certData = _.get(data, 'certificateData');
        this.loader = false;
        if (_.get(data, 'verified')) {
          this.viewCertificate = true;
          this.recipient = _.get(certData, 'issuedTo');
          this.courseName = _.get(certData, 'trainingName');
          this.issuedOn = dayjs(new Date(_.get(certData, 'issuanceDate'))).format('DD MMM YYYY');
        } else {
          this.viewCertificate = false;
          this.isInvalidCertificate = true;
        }
      },
      (err) => {
        this.loader = false;
        this.toasterService.error(this.resourceService.messages.emsg.m0005);
        this.viewCertificate = false;
        this.isInvalidCertificate = true;
      }
    );
  }
}
<div class="sb-certificatePage-bg" [appTelemetryImpression]="telemetryImpressionData">
  <div *ngIf="!viewCertificate && !validateRCCertificate" class="sb-certificatePage" [class.loading]="loader" [class.error]="error">
    <div class="sb-certificatePage-overlay"></div>
    <div class="sb-certificatePage-header">
      <img alt="{{tenantName}}" src="{{logo}}" class="sb-certificatePage-logo" />
    </div>
    <div class="sb-certificatePage-desc mb-auto m-0">
      <div class="sb-certificatePage-loader">
        <p>{{resourceService?.frmelmnts?.lbl?.verifyingCertificate}}</p>
        <img src="assets/images/loader.gif" class="sb-certificatePage-loader-img" alt="Loader"/>
      </div>
      <img src="assets/images/certificate.png" class="sb-certificatePage-desc-img" alt="Certificate Desc"/>
    </div>
    <div class="sb-certificatePage-form mb-auto">
      <div class="sb-form-field-group">
      <label *ngIf="!wrongCertificateCode" class="sb-certificatePage-label" for="certificate">
        {{resourceService?.frmelmnts?.lbl?.enterCertificateCode}}
      </label>
      <label *ngIf="wrongCertificateCode" class="sb-field-error-label sb-certificatePage-label sb-color-error" for="certificate">
        {{resourceService?.frmelmnts?.lbl?.enterValidCertificateCode}}
      </label>
      <div class="sb-certificatePage-field sb-field" id="certificate">
        <input #codeInputField (keyup)="getCodeLength($event)" (keydown.space)="$event.preventDefault();" [(ngModel)]="certificateCode" type="text" maxlength="6" pattern="^[-a-zA-Z0-9@\.+_]+$" required autofocus name="certificate" class="sb-form-control text-center"/>
        <button [disabled]="!enableVerifyButton" type="button" class="sb-btn sb-btn-primary sb-btn-normal width-100 mt-32" (click)="certificateVerify()" tabindex="0"
        appTelemetryInteract [telemetryInteractEdata]="{id:'verify-certificate-button' , type:'click' , pageid:pageId }"
        [telemetryInteractCdata]="telemetryCdata">
          {{resourceService?.frmelmnts?.btn?.verify}}
        </button>
      </div>
    </div>
  </div>
</div>
<div *ngIf="viewCertificate && !validateRCCertificate">
<div  class="sb-certificatePage sb-certificate-view sb-certificatePage-flexHeight">
    <div class="sb-certificatePage-header">
      <img alt="{{tenantName}}" src="{{logo}}" class="sb-certificatePage-logo"/>
    </div>
    <div class="sb-certificatePage-holder-details mb-auto">
      <img src="assets/images/badge.svg" class="sb-icon-badge mt-24 mb-8" alt="Badge"/>
      <p *ngIf="recipient" class="sb-certificatePage-holder-desc sb-certificatePage-holder-desc-primary">
        {{resourceService?.frmelmnts?.lbl?.certificateIssuedTo}}
      </p>
      <h4 *ngIf="recipient" class="sb-certificatePage-holder-name">
        {{recipient}}
      </h4>
      <p *ngIf="courseName && issuedOn" class="sb-certificatePage-holder-desc">
        {{resourceService?.frmelmnts?.lbl?.completingCourseSuccessfully}} 
        <strong class="d-block">“{{courseName}}”</strong>
        <span class="d-block">{{resourceService?.frmelmnts?.lbl?.onDiksha | interpolate:'{instance}':instance}}<strong> {{issuedOn}}</strong></span>
      </p>
      
    </div>

  </div>

  <div class="sb-mobileDevice text-center" *ngIf="watchVideoLink">
    <div class="sb-mobileDevice-screen">
      <div class="sb-mobileDevice-sensors">
        <div class="sb-mobileDevice-sensor"></div>
        <div class="sb-mobileDevice-speaker"></div>
        <div class="sb-mobileDevice-sensor"></div>
      </div>
      <div class="player-thumbnail" appTelemetryInteract [telemetryInteractEdata]="{id:'watch-video-button' , type:'click' , pageid:pageId }" (click)="playContent(contentId)" tabindex="0" *ngIf="showVideoThumbnail"></div>
      <div class="h-100 certificate-area-player" *ngIf="!showVideoThumbnail">
        <app-player class="content-player" [overlayImagePath]="'assets/images/featured-content.jpg'" [pageId]="pageId" [isSingleContent]="false" [playerConfig]="playerConfig"></app-player>
    </div>
    </div>
  </div>
  
  <div  class="sb-certificatePage sb-certificate-view min-height-auto">
    <div class="sb-certificatePage-holder-details">
      <a appTelemetryInteract [telemetryInteractEdata]="{id:'return-to-courses-button' , type:'click' , pageid:pageId }" (click)="navigateToCoursesPage()" tabindex="0" class="mt-32 width-100 d-flex flex-jc-space-between p-8 cursor-pointer sb-btn-arrow" title="Return to Courses">
        {{resourceService?.frmelmnts?.lbl?.returnToCourses}} <i class="angle right icon"></i>
      </a>
    </div>
  </div>
</div>

<!-- RC Certificate validation -->
<div *ngIf="validateRCCertificate && viewCertificate">

  <div class="sb-certificatePage sb-certificate-view sb-certificatePage-flexHeight">
    <div class="sb-certificatePage-header">
      <img alt="{{tenantName}}" src="{{logo}}" class="sb-certificatePage-logo" />
    </div>
    <div class="sb-certificatePage-holder-details mb-auto">
      <img src="assets/images/badge.svg" class="sb-icon-badge mt-24 mb-8" alt="Badge" />
      <p *ngIf="recipient" class="sb-certificatePage-holder-desc sb-certificatePage-holder-desc-primary">
        {{resourceService?.frmelmnts?.lbl?.certificateIssuedTo}}
      </p>
      <h4 *ngIf="recipient" class="sb-certificatePage-holder-name">
        {{recipient}}
      </h4>
      <p *ngIf="courseName && issuedOn" class="sb-certificatePage-holder-desc">
        {{resourceService?.frmelmnts?.lbl?.completingCourseSuccessfully}}
        <strong class="d-block">“{{courseName}}”</strong>
        <span class="d-block">{{resourceService?.frmelmnts?.lbl?.onDiksha | interpolate:'{instance}':instance}}<strong>
            {{issuedOn}}</strong></span>
      </p>
    </div>
  </div>

</div>

<div *ngIf="validateRCCertificate && !viewCertificate && isInvalidCertificate" class="sb-certificatePage" [class.loading]="loader" [class.error]="error">

  <div class="sb-certificatePage sb-certificate-view sb-certificatePage-flexHeight">
    <div class="sb-certificatePage-header">
      <img alt="{{tenantName}}" src="{{logo}}" class="sb-certificatePage-logo" />
    </div>
    <div class="sb-certificatePage-holder-details mb-auto">
      <img class="mr-8" src="assets/images/exclamation.svg" width="20px">
      {{resourceService?.frmelmnts?.cert?.imsg?.rcInvalid}}
    </div>
  </div>

</div>
<!-- RC Certificate validation -->
</div>

./certificate-details.component.scss

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


.sb-mobileDevice {
    .sb-mobileDevice-screen {
      height: calvulteRem(202.5px);
      width: calculateRem(360px);
      border: calculateRem(10px) solid var(--black);
      border-radius: calculateRem(15px);
      margin: 0 auto;
      position: relative;
      overflow: hidden;
      .sb-mobileDevice-sensors {
        position: absolute;
        z-index: 9;
        top: 50%;
        transform: translateY(-50%);
        margin: auto;
        left: 0;
        background: var(--black);
        padding: calculateRem(10px) calculateRem(5px) calculateRem(10px) 0;
        border-top-right-radius: calculateRem(25px);
        border-bottom-right-radius: calculateRem(25px);
        .sb-mobileDevice-sensor {
          width: calculateRem(8px);
          height: calculateRem(8px);
          background: var(--black);
          border-radius: 50%;
        }
        .sb-mobileDevice-speaker {
          width: calculateRem(5px);
          height: calculateRem(74px);
          background: var(--black);
          border-radius: calculateRem(10px);
          margin: calculateRem(10px) 0 calculateRem(10px) calculateRem(1px);
        }
      }
      .sb-mobileDevice-videoScreen {
        width: 100%;
        height: 100%;
        cursor: pointer;
        border-radius: calculateRem(5px);
        border: none;
      }
      @media only screen and (min-width: 540px) {
        height: calculateRem(340px);
        width: calculateRem(680px);
      }
      @media only screen and (min-width: 769px) {
        height: calculateRem(400px);
        max-width: calculateRem(800px);
      }
    }
  }

  .player-thumbnail {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    background: url(../../../../../assets/images/featured-content.jpg) no-repeat;
    background-size: cover;
    background-position: center;
    height: 100%;
    cursor: pointer;
    border-radius: calculateRem(5px);
  }

  ::ng-deep {
    .certificate-area-player {
      .contentViewerIframeShadow {
        height:100% !important;
      }
    }
  }
 
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""