diff --git a/library/ws-widget/collection/src/lib/_common/content-toc/app-toc-about/app-toc-about.component.html b/library/ws-widget/collection/src/lib/_common/content-toc/app-toc-about/app-toc-about.component.html index 608ca302f6..9c12c8e6ee 100644 --- a/library/ws-widget/collection/src/lib/_common/content-toc/app-toc-about/app-toc-about.component.html +++ b/library/ws-widget/collection/src/lib/_common/content-toc/app-toc-about/app-toc-about.component.html @@ -19,9 +19,10 @@ - - + arrow_downward + @@ -31,7 +32,7 @@ [height]="'148px'"> -
+
No certificate image
@@ -41,12 +42,28 @@
- + +
+ + certificate image +
+ +
+
+
+
@@ -77,7 +94,7 @@
- +
diff --git a/library/ws-widget/collection/src/lib/_common/content-toc/app-toc-about/app-toc-about.component.scss b/library/ws-widget/collection/src/lib/_common/content-toc/app-toc-about/app-toc-about.component.scss index d5a8ca4c31..afa265b372 100644 --- a/library/ws-widget/collection/src/lib/_common/content-toc/app-toc-about/app-toc-about.component.scss +++ b/library/ws-widget/collection/src/lib/_common/content-toc/app-toc-about/app-toc-about.component.scss @@ -445,7 +445,7 @@ $mob-title-line-count: 2; .ceritificate-image { display: flex; - max-width: 248px; + // max-width: 248px; margin: auto; width: 100%; border-radius: 8px; @@ -509,3 +509,82 @@ $mob-title-line-count: 2; -webkit-box-orient: vertical; word-wrap: break-word; } +.img-container { + position: relative; + + .view-cert { + visibility: hidden; + display: none; + } + + &:hover { + display: block; + z-index: 99999; + .view-cert { + visibility: visible; + position: absolute; + left: 0; + top: 0; + text-align: center; + opacity: 1; + transition: opacity 0.35s ease; + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + background-color: #000000b5; + border-radius: 8px; + button { + color: white; + border: 1px solid white; + padding: 8px; + background: transparent; + border-radius: 12px; + cursor: pointer; + z-index: 999999; + } + } + } +} +.view-certificate { + visibility: visible !important; + display: block; + position: absolute; + /* width: 500px; */ + left: 0; + top: 0; + text-align: center; + opacity: 1; + background-color: #000000b5; + border-radius: 8px; + transition: opacity 0.35s ease; + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + + button { + color: white; + border: 1px solid white; + padding: 8px; + background: transparent; + border-radius: 12px; + cursor: pointer; + z-index: 999999; + width: 150px; + } +} + +.uploader-status ::ng-deep .mat-progress-spinner circle, .mat-spinner circle { + stroke: #ffffff; +} +.uploader-status ::ng-deep .mat-progress-spinner svg { + width: 24px !important; + height: 24px !important; +} +.uploader-status ::ng-deep .mat-progress-spinner { + width: 24px !important; + height: 24px !important; +} diff --git a/library/ws-widget/collection/src/lib/_common/content-toc/app-toc-about/app-toc-about.component.ts b/library/ws-widget/collection/src/lib/_common/content-toc/app-toc-about/app-toc-about.component.ts index 8aa582d0bc..c3e01148df 100644 --- a/library/ws-widget/collection/src/lib/_common/content-toc/app-toc-about/app-toc-about.component.ts +++ b/library/ws-widget/collection/src/lib/_common/content-toc/app-toc-about/app-toc-about.component.ts @@ -18,7 +18,7 @@ import { NsContentStripWithTabs } from '../../../content-strip-with-tabs/content import { AppTocService } from '@ws/app/src/lib/routes/app-toc/services/app-toc.service' import { NsContent, RatingService } from '@sunbird-cb/collection/src/public-api' -import { LoggerService, ConfigurationsService } from '@sunbird-cb/utils-v2' +import { LoggerService, ConfigurationsService, WidgetContentService } from '@sunbird-cb/utils-v2' import { TimerService } from '@ws/app/src/lib/routes/app-toc/services/timer.service' import { HandleClaimService } from '../content-services/handle-claim.service' import { LoadCheckService } from '@ws/app/src/lib/routes/app-toc/services/load-check.service' @@ -83,6 +83,7 @@ export class AppTocAboutComponent implements OnInit, OnChanges, AfterViewInit, O private reviewDataService: ReviewComponentDataService, private handleClaimService: HandleClaimService, private resetRatingsService: ResetRatingsService, + private contentSvc: WidgetContentService ) { this.resetRatingsService.resetRatings$.subscribe((_res: any) => { this.fetchRatingSummary() @@ -150,6 +151,7 @@ export class AppTocAboutComponent implements OnInit, OnChanges, AfterViewInit, O private destroySubject$ = new Subject() viewMoreTags = false timerUnsubscribe: any + downloadCertificateBool = false strip: NsContentStripWithTabs.IContentStripUnit = { key: 'blendedPrograms', @@ -695,11 +697,30 @@ export class AppTocAboutComponent implements OnInit, OnChanges, AfterViewInit, O } handleOpenCertificateDialog() { - const cet = this.content && this.content.certificateObj.certData - this.dialog.open(CertificateDialogComponent, { - width: '1200px', - data: { cet, certId: this.content && this.content.certificateObj.certId }, - }) + this.downloadCertificateBool = true + const certId = this.content && this.content.certificateObj.certId + if (this.content && this.content.certificateObj && !this.content.certificateObj.certData) { + this.contentSvc.downloadCert(certId).subscribe(response => { + if (this.content) { + this.downloadCertificateBool = false + this.content['certificateObj']['certData'] = response.result.printUri + this.dialog.open(CertificateDialogComponent, { + width: '1200px', + data: { cet: response.result.printUri, certId: this.content && this.content.certificateObj.certId }, + }) + } + }, (error: any) => { + this.downloadCertificateBool = false + this.loggerService.error('CERTIFICATE FETCH ERROR >', error) + this.matSnackBar.open('Unable to View Certificate, due to some error!') + }) + } else { + this.downloadCertificateBool = false + this.dialog.open(CertificateDialogComponent, { + width: '1200px', + data: { cet: this.content && this.content.certificateObj.certData, certId: this.content && this.content.certificateObj.certId }, + }) + } } checkValidJSON(str: any) { diff --git a/package.json b/package.json index 5efb6a4b81..23539649ad 100644 --- a/package.json +++ b/package.json @@ -47,13 +47,13 @@ "@project-sunbird/sb-styles": "0.0.7", "@project-sunbird/sunbird-quml-player": "0.0.6", "@project-sunbird/telemetry-sdk": "0.0.26", - "@sunbird-cb/consumption": "0.0.72", + "@sunbird-cb/consumption": "0.0.73", "@sunbird-cb/design-system": "0.0.2", "@sunbird-cb/discussions-ui-v8": "2.1.3", "@sunbird-cb/micro-surveys": "^2.0.17", "@sunbird-cb/rain-dashboards": "0.4.33", "@sunbird-cb/resolver-v2": "0.0.7", - "@sunbird-cb/utils-v2": "0.0.8", + "@sunbird-cb/utils-v2": "0.0.10", "@types/file-saver": "^2.0.1", "@types/uuid": "^8.3.1", "bootstrap": "5.1.2", diff --git a/project/ws/app/src/lib/routes/app-toc/components/app-toc-home/app-toc-home.component.ts b/project/ws/app/src/lib/routes/app-toc/components/app-toc-home/app-toc-home.component.ts index 31c52f1856..00e599fcca 100755 --- a/project/ws/app/src/lib/routes/app-toc/components/app-toc-home/app-toc-home.component.ts +++ b/project/ws/app/src/lib/routes/app-toc/components/app-toc-home/app-toc-home.component.ts @@ -979,8 +979,20 @@ export class AppTocHomeComponent implements OnInit, OnDestroy, AfterViewChecked, this.tocSvc.checkModuleWiseData(this.content) this.enrolledCourseData = enrolledCourse this.currentCourseBatchId = enrolledCourse.batchId - this.downloadCert(enrolledCourse.issuedCertificates) - + // this.downloadCert(enrolledCourse.issuedCertificates) + if (enrolledCourse && enrolledCourse.issuedCertificates && + enrolledCourse.issuedCertificates.length) { + const certificate: any = enrolledCourse.issuedCertificates.sort((a: any, b: any) => + new Date(b.lastIssuedOn).getTime() - new Date(a.lastIssuedOn).getTime()) + const certId = certificate[0].identifier + this.certId = certId + if (this.content) { + this.content['certificateObj'] = { + certId, + certData: '', + } + } + } this.content.completionPercentage = enrolledCourse.completionPercentage || 0 this.content.completionStatus = enrolledCourse.status || 0 if (this.contentReadData && this.contentReadData.cumulativeTracking) { @@ -1098,22 +1110,22 @@ export class AppTocHomeComponent implements OnInit, OnDestroy, AfterViewChecked, return batchId } - downloadCert(certIdArr: any) { - if (certIdArr && certIdArr.length && certIdArr.length > 0) { - certIdArr.sort((a: any, b: any) => new Date(b.lastIssuedOn).getTime() - new Date(a.lastIssuedOn).getTime()) - const certId = certIdArr[0].identifier - this.certId = certId + // downloadCert(certIdArr: any) { + // if (certIdArr && certIdArr.length && certIdArr.length > 0) { + // certIdArr.sort((a: any, b: any) => new Date(b.lastIssuedOn).getTime() - new Date(a.lastIssuedOn).getTime()) + // const certId = certIdArr[0].identifier + // this.certId = certId - this.contentSvc.downloadCert(certId).subscribe(response => { - if (this.content) { - this.content['certificateObj'] = { - certData: response.result.printUri, - certId: this.certId, - } - } - }) - } - } + // this.contentSvc.downloadCert(certId).subscribe(response => { + // if (this.content) { + // this.content['certificateObj'] = { + // certData: response.result.printUri, + // certId: this.certId, + // } + // } + // }) + // } + // } public handleAutoBatchAssign() { if (this.forPreview) { diff --git a/project/ws/app/src/lib/routes/karma-programs/karma-programs-microsite-v2/karma-programs-microsite-v2.component.ts b/project/ws/app/src/lib/routes/karma-programs/karma-programs-microsite-v2/karma-programs-microsite-v2.component.ts index 2dc1760289..7ea143c309 100644 --- a/project/ws/app/src/lib/routes/karma-programs/karma-programs-microsite-v2/karma-programs-microsite-v2.component.ts +++ b/project/ws/app/src/lib/routes/karma-programs/karma-programs-microsite-v2/karma-programs-microsite-v2.component.ts @@ -69,7 +69,7 @@ export class KarmaProgramsMicrositeV2Component implements OnInit { } } - + richTextContent(content: any) { return this.sanitizer.bypassSecurityTrustHtml(content) } diff --git a/src/app/competency-passbook/competency-card-details/competency-card-details.component.html b/src/app/competency-passbook/competency-card-details/competency-card-details.component.html index ab3eb25cb6..541ed4af98 100644 --- a/src/app/competency-passbook/competency-card-details/competency-card-details.component.html +++ b/src/app/competency-passbook/competency-card-details/competency-card-details.component.html @@ -69,19 +69,33 @@ - arrow_downward - + arrow_downward +
- + + -
- {{ eachCert?.courseName }} certificate +
+ + + {{ eachCert?.courseName }} certificate + + + {{ eachCert?.courseName }} certificate + +
+ +
diff --git a/src/app/competency-passbook/competency-card-details/competency-card-details.component.scss b/src/app/competency-passbook/competency-card-details/competency-card-details.component.scss index e977d8dda2..cc019e6f83 100644 --- a/src/app/competency-passbook/competency-card-details/competency-card-details.component.scss +++ b/src/app/competency-passbook/competency-card-details/competency-card-details.component.scss @@ -55,7 +55,6 @@ $text-primary: #1B4CA1; .img-div { width: 280px; - height: 160px; border-radius: 8px; img { @@ -126,3 +125,84 @@ $title-line-count: 2; } } } + + +.img-container { + position: relative; + + .view-cert { + visibility: hidden; + display: none; + } + + &:hover { + display: block; + z-index: 99999; + .view-cert { + visibility: visible; + position: absolute; + left: 0; + top: 0; + text-align: center; + opacity: 1; + transition: opacity 0.35s ease; + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + background-color: #000000b5; + border-radius: 8px; + button { + color: white; + border: 1px solid white; + padding: 8px; + background: transparent; + border-radius: 12px; + cursor: pointer; + z-index: 999999; + } + } + } +} +.view-certificate { + visibility: visible !important; + display: block; + position: absolute; + /* width: 500px; */ + left: 0; + top: 0; + text-align: center; + opacity: 1; + background-color: #000000b5; + border-radius: 8px; + transition: opacity 0.35s ease; + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + + button { + color: white; + border: 1px solid white; + padding: 8px; + background: transparent; + border-radius: 12px; + cursor: pointer; + z-index: 999999; + width: 150px; + } +} + +.uploader-status ::ng-deep .mat-progress-spinner circle, .mat-spinner circle { + stroke: #ffffff; +} +.uploader-status ::ng-deep .mat-progress-spinner svg { + width: 24px !important; + height: 24px !important; +} +.uploader-status ::ng-deep .mat-progress-spinner { + width: 24px !important; + height: 24px !important; +} \ No newline at end of file diff --git a/src/app/competency-passbook/competency-card-details/competency-card-details.component.ts b/src/app/competency-passbook/competency-card-details/competency-card-details.component.ts index 165d9e4e9f..3a8bacee18 100644 --- a/src/app/competency-passbook/competency-card-details/competency-card-details.component.ts +++ b/src/app/competency-passbook/competency-card-details/competency-card-details.component.ts @@ -11,6 +11,8 @@ import { CompetencyPassbookService } from '../competency-passbook.service' import { TranslateService } from '@ngx-translate/core' import { MultilingualTranslationsService, EventService, WsEvents } from '@sunbird-cb/utils-v2' import { environment } from 'src/environments/environment' +import { MatDialog } from '@angular/material' +import { CertificateDialogComponent } from '@sunbird-cb/collection/src/lib/_common/certificate-dialog/certificate-dialog.component' @Component({ selector: 'ws-competency-card-details', @@ -37,6 +39,7 @@ export class CompetencyCardDetailsComponent implements OnInit, AfterViewInit, On private translate: TranslateService, private langtranslations: MultilingualTranslationsService, private events: EventService, + private dialog: MatDialog, ) { this.langtranslations.languageSelectedObservable.subscribe(() => { if (localStorage.getItem('websiteLanguage')) { @@ -58,8 +61,8 @@ export class CompetencyCardDetailsComponent implements OnInit, AfterViewInit, On this.certificateData.forEach((obj: any) => { obj.courseName = obj.courseName.charAt(0).toUpperCase() + obj.courseName.slice(1) if (obj.identifier) { - obj['loading'] = true - this.getCertificateSVG(obj) + obj['loading'] = false + // this.getCertificateSVG(obj) this.updatedTime = this.updatedTime ? (new Date(this.updatedTime) > new Date(obj.lastIssuedOn)) ? this.updatedTime : obj.lastIssuedOn : obj.lastIssuedOn } @@ -78,20 +81,35 @@ export class CompetencyCardDetailsComponent implements OnInit, AfterViewInit, On }) } - getCertificateSVG(obj: any): void { + getCertificateSVG(obj: any, type?: string): void { // tslint: disable-next-line - this.cpService.fetchCertificate(obj.identifier) - .pipe(takeUntil(this.destroySubject$)) - .subscribe(res => { - // tslint: disable-next-line - obj['printURI'] = res.result.printUri - obj['loading'] = false - }, (error: HttpErrorResponse) => { - if (!error.ok) { + obj['loading'] = true + if (obj && obj.printURI) { + if (type === 'DOWNLOAD') { + this.handleDownloadCertificatePDF(obj.printURI) + } + if (type === 'SHARE') { + this.shareCertificate(obj.identifier) + } obj['loading'] = false - obj['error'] = 'Failed to fetch Certificate' + } else { + this.cpService.fetchCertificate(obj.identifier) + .pipe(takeUntil(this.destroySubject$)) + .subscribe(res => { + // tslint: disable-next-line + obj['printURI'] = res.result.printUri + obj['loading'] = false + this.dialog.open(CertificateDialogComponent, { + width: '1200px', + data: { cet: res.result.printUri, certId: obj.identifier }, + }) + }, (error: HttpErrorResponse) => { + if (!error.ok) { + obj['loading'] = false + obj['error'] = 'Failed to fetch Certificate' + } + }) } - }) } async handleDownloadCertificatePDF(uriData: any): Promise { diff --git a/src/app/competency-passbook/competency-passbook.module.ts b/src/app/competency-passbook/competency-passbook.module.ts index ea2cb54cc5..223d9f77ea 100644 --- a/src/app/competency-passbook/competency-passbook.module.ts +++ b/src/app/competency-passbook/competency-passbook.module.ts @@ -1,7 +1,7 @@ import { NgModule } from '@angular/core' import { CommonModule } from '@angular/common' import { RouterModule } from '@angular/router' -import { MatIconModule, MatMenuModule, MatTabsModule } from '@angular/material' +import { MatIconModule, MatMenuModule, MatProgressSpinnerModule, MatTabsModule } from '@angular/material' import { CbpFiltersModule } from '@sunbird-cb/collection/src/lib/_common/cbp-filters/cbp-filters.module' import { SkeletonLoaderModule } from '@sunbird-cb/collection/src/lib/_common/skeleton-loader/skeleton-loader.module' @@ -15,6 +15,7 @@ import { CompetencyCardDetailsComponent } from './competency-card-details/compet import { CompetencyPassbookSideBarComponent } from './../component/competency-passbook-side-bar/competency-passbook-side-bar.component' import { CompetencySearchComponent } from './competency-search/competency-search.component' import { TranslateModule } from '@ngx-translate/core' +import { DialogComponentsModule } from '@sunbird-cb/consumption' @NgModule({ declarations: [ @@ -30,11 +31,13 @@ import { TranslateModule } from '@ngx-translate/core' MatIconModule, MatMenuModule, MatTabsModule, + MatProgressSpinnerModule, CompetencyPassbookRoutingModule, SkeletonLoaderModule, PipeSafeSanitizerModule, CbpFiltersModule, TranslateModule, + DialogComponentsModule, ], exports: [ TranslateModule,