diff --git a/scripts/deleteUnUsableIosIcon.js b/scripts/deleteUnUsableIosIcon.js index 618d4049d6..f6747d2601 100644 --- a/scripts/deleteUnUsableIosIcon.js +++ b/scripts/deleteUnUsableIosIcon.js @@ -134,7 +134,9 @@ function deleteUnUsableIosIcon(ionicIconFilePath) { "arrow-up-circle-outline.svg", "arrow-down-circle-outline.svg", "caret-forward-circle.svg", - "ribbon.svg" + "ribbon.svg", + "chevron-up.svg", + "chevron-down.svg" ].includes(file))) { fs.unlinkSync(ionicIconFilePath + '/' + file); } diff --git a/src/app/manage-learn/core/services/attachment/attachment.service.ts b/src/app/manage-learn/core/services/attachment/attachment.service.ts index 6deff67007..8cefeff622 100644 --- a/src/app/manage-learn/core/services/attachment/attachment.service.ts +++ b/src/app/manage-learn/core/services/attachment/attachment.service.ts @@ -140,7 +140,7 @@ export class AttachmentService { await actionSheet.present(); return actionSheet.onDidDismiss(); } - takePicture(sourceType: PictureSourceType, mediaType: MediaType = this.camera.MediaType.ALLMEDIA) { + async takePicture(sourceType: PictureSourceType, mediaType: MediaType = this.camera.MediaType.ALLMEDIA) { var options: CameraOptions = { quality: 20, sourceType: sourceType, @@ -150,15 +150,15 @@ export class AttachmentService { destinationType: this.camera.DestinationType.FILE_URI }; - this.camera + await this.camera .getPicture(options) - .then((imagePath) => { + .then(async(imagePath) => { if (this.platform.is("android") && sourceType === this.camera.PictureSourceType.PHOTOLIBRARY) { let newFilePath = imagePath; if (!newFilePath.includes("file://")) { newFilePath = "file://" + imagePath } - this.checkForFileSizeRestriction(newFilePath).then(isValidFile => { + await this.checkForFileSizeRestriction(newFilePath).then(isValidFile => { if (isValidFile) { this.filePath .resolveNativePath(newFilePath) @@ -169,7 +169,7 @@ export class AttachmentService { } }) } else { - this.checkForFileSizeRestriction(imagePath).then(isValidFile => { + await this.checkForFileSizeRestriction(imagePath).then(isValidFile => { if (isValidFile) { this.copyFile(imagePath); } @@ -329,13 +329,13 @@ export class AttachmentService { this.payload = payload; switch (type) { case 'openCamera': - this.takePicture(this.camera.PictureSourceType.CAMERA); + await this.takePicture(this.camera.PictureSourceType.CAMERA); break; case 'openGallery': - this.takePicture(this.camera.PictureSourceType.PHOTOLIBRARY); + await this.takePicture(this.camera.PictureSourceType.PHOTOLIBRARY); break; case 'openFiles': - this.openFile(); + await this.openFile(); break; } } diff --git a/src/app/manage-learn/core/services/utils.service.ts b/src/app/manage-learn/core/services/utils.service.ts index bfec1a93b2..fd80c5d823 100644 --- a/src/app/manage-learn/core/services/utils.service.ts +++ b/src/app/manage-learn/core/services/utils.service.ts @@ -20,6 +20,8 @@ import { Events } from '@app/util/events'; import { Location } from "@angular/common"; import { ToastService } from "./toast/toast.service"; import { TranslateService } from "@ngx-translate/core"; +import { PopoverController } from "@ionic/angular"; +import { PiiConsentPopupComponent } from "../../shared"; @Injectable({ providedIn: "root" @@ -41,6 +43,7 @@ export class UtilsService { filters: any = {}; statuses = statuses; numberTasksCompleted =0; + consentPopup constructor( @Inject("PROFILE_SERVICE") private profileService: ProfileService, @Inject("AUTH_SERVICE") public authService: AuthService, @@ -54,6 +57,7 @@ export class UtilsService { private location : Location, private toast : ToastService, private translate: TranslateService, + private popoverCtrl : PopoverController ) { this.events.subscribe("loggedInProfile:update", _ => { @@ -780,4 +784,42 @@ return data; ]; return tabs; } + + async showConsentPopup(type){ + let componentProps={} + switch (type) { + case 'program': + componentProps={ + consentMessage1 : "FRMELEMNTS_LBL_CONSENT_POPUP_MSG1", + consentMessage2 : "FRMELEMNTS_LBL_CONSENT_POPUP_POLICY_MSG", + consentMessage3 : "FRMELEMNTS_LBL_CONSENT_POPUP_MSG2", + redirectLink : RouterLinks.TERM_OF_USE + } + break; + + default: + componentProps={ + consentMessage1 : "FRMELEMNTS_LBL_CONSENT_POPUP_MSG1", + consentMessage2 : "FRMELEMNTS_LBL_CONSENT_POPUP_POLICY_MSG", + consentMessage3 : "FRMELEMNTS_LBL_CONSENT_POPUP_MSG2", + redirectLink : RouterLinks.TERM_OF_USE + } + break; + } + this.consentPopup = await this.popoverCtrl.create({ + component : PiiConsentPopupComponent, + componentProps : componentProps, + cssClass: 'sb-popover back-drop-hard', + backdropDismiss: false + }) + await this.consentPopup.present() + let {data} = await this.consentPopup.onDidDismiss() + return data + } + + async closeConsentPopup(){ + this.consentPopup ? await this.consentPopup.dismiss() : null + } + + } \ No newline at end of file diff --git a/src/app/manage-learn/programs/program-details/program-details.component.html b/src/app/manage-learn/programs/program-details/program-details.component.html new file mode 100644 index 0000000000..f6c1a634da --- /dev/null +++ b/src/app/manage-learn/programs/program-details/program-details.component.html @@ -0,0 +1,50 @@ + + +
{{programDetails?.programName}}
+
{{description}} + + {{ (showMore ? 'READ_LESS' : 'READ_MORE') | translate }} + +
+
+ + {{"FRMELEMNTS_LBL_JOIN_PROGRAM_POPUP" | translate}} + + +
+ {{"FRMELEMNTS_MSG_PROGRAM_JOINED" | translate:{'date':(endDate | date: 'd/M/yyyy')} }} +
+
+
+ +
+ + +
+ + +
+
{{data?.sectionName}}
+
+ +
+
+
+
+ + +
+
+
+ +
+ +
+
+
{{"EMPTY_SEARCH_RESULTS" | translate}}.
+
{{"FRMELEMNTS_MSG_NO_SOLUTIONS_FOR_PROGRAM" | translate:{'type':selectedSection} }}
+
+ + +
\ No newline at end of file diff --git a/src/app/manage-learn/programs/program-details/program-details.component.scss b/src/app/manage-learn/programs/program-details/program-details.component.scss new file mode 100644 index 0000000000..463a39c4d8 --- /dev/null +++ b/src/app/manage-learn/programs/program-details/program-details.component.scss @@ -0,0 +1,79 @@ +@import 'src/assets/styles/_custom-mixins'; +@import "src/assets/styles/variables"; +@import "src/assets/styles/_variables.scss"; + +.details-block{ + margin-left: 0px; + padding: 15px; + .title{ + font-size: 18px; + font-weight: 700; + padding: 0px 15px; + margin-bottom: 10px; + color: $black; + } + .description{ + color: $black; + padding: 0px 15px; + font-weight: 600; + } +} + +.hr-line { + height: 1px; + border: 1px solid map-get($colors, medium_gray); + margin: 10px 0px; +} + +.program-joined-message{ + background-color: map-get($colors, light_red); + padding: 10px; + font-weight: 700; + margin: 0px 15px; + border-radius: 10px; + font-size: 12px; +} + +.read-more{ + color: $blue; + text-decoration-line: underline; + font-weight: 600; +} + +.section-filter{ + background-color: var(--app-secondary-background); + border-radius: 25px; +} + +.section-card{ + border-radius: 25px !important; + padding: 5px; + margin: 10px 0px; + background-color: var(--app-secondary-background); + .icon{ + background-color: $white; + box-shadow: var(--button-style-shadow); + height: 22px; + border-radius: 50%; + } +} + +.section-details{ + .section-name{ + font-size: 18px; + font-weight: 600; + color: map-get($colors, bright_blue); + text-transform:capitalize; + } + ion-icon{ + font-size: 22px; + } +} + +.no-data{ + margin: 100px 0px 50px 0px; + .message-1{ + font-size: 16px; + margin-bottom: 10px; + } +} \ No newline at end of file diff --git a/src/app/manage-learn/programs/program-details/program-details.component.ts b/src/app/manage-learn/programs/program-details/program-details.component.ts new file mode 100644 index 0000000000..cc88b4880d --- /dev/null +++ b/src/app/manage-learn/programs/program-details/program-details.component.ts @@ -0,0 +1,174 @@ +import { Component, OnInit } from '@angular/core'; +import { AppHeaderService } from '@app/services'; +import { LibraryFiltersLayout } from '@project-sunbird/common-consumption'; +import { TranslateService } from '@ngx-translate/core'; +import { GenericPopUpService } from '../../shared'; +import { ActivatedRoute } from '@angular/router'; +import { urlConstants } from '../../core/constants/urlConstants'; +import { LoaderService, UtilsService, ToastService } from '../../core'; +import { KendraApiService } from '../../core/services/kendra-api.service'; + +@Component({ + selector: 'app-program-details', + templateUrl: './program-details.component.html', + styleUrls: ['./program-details.component.scss'], +}) +export class ProgramDetailsComponent implements OnInit { + headerConfig = { + showHeader : true, + showBurgerMenu : false, + actionButtons : [] + } + filtersList : any = [] + selectedFilterIndex = 0 + layout = LibraryFiltersLayout.ROUND + selectedSection: any + showMore:boolean=false + description + characterLimit = 150 + programDetails:any={} + solutionsList:any=[] + filteredList:any=[] + sharingStatus='ACTIVE' + endDate=Date() + programId + count = 0; + limit = 25; + page = 1; + + constructor(private headerService: AppHeaderService, private translate: TranslateService, private popupService: GenericPopUpService, + private activatedRoute: ActivatedRoute, private loader: LoaderService, private utils: UtilsService, private kendraService: KendraApiService, + private toastService: ToastService) { + this.translate.get(['ALL','FRMELEMNTS_LBL_PROJECTS','FRMELEMNTS_LBL_OBSERVATIONS','FRMELEMNTS_LBL_COURSES','FRMELEMNTS_LBL_SURVEY']).subscribe((translation)=>{ + this.filtersList = Object.keys(translation).map(translateItem => { return translation[translateItem]}) + }) + activatedRoute.params.subscribe((param)=>{ + this.programId = param.id + this.getSolutions() + }) + } + + ngOnInit() {} + + ionViewWillEnter(){ + this.headerConfig = this.headerService.getDefaultPageConfig() + this.headerConfig.showHeader = true + this.headerConfig.showBurgerMenu = false + this.headerConfig.actionButtons = [] + this.headerService.updatePageConfig(this.headerConfig) + } + + async getSolutions() { + this.loader.startLoader(); + let payload = await this.utils.getProfileInfo(); + if (payload) { + const config = { + url:`${urlConstants.API_URLS.SOLUTIONS_LISTING}${this.programId}?page=${this.page}&limit=${this.limit}&search=`, + payload: payload, + }; + this.kendraService.post(config).subscribe( + (success) => { + this.loader.stopLoader(); + if (success.result.data) { + this.programDetails = success.result + this.count = success.result.count; + this.formatList() + this.readMoreOrLess() + } + }, + (error) => { + this.loader.stopLoader(); + } + ); + } else { + this.loader.stopLoader(); + } + } + + readMoreOrLess(){ + if(this.showMore){ + this.description = this.programDetails.description + }else{ + if(this.programDetails.description.length > this.characterLimit){ + this.description = this.programDetails.description.slice(0,this.characterLimit)+'...' + }else{ + this.description = this.programDetails.description + } + } + } + + formatList(){ + this.programDetails.data.forEach(data => { + let sectionName=data.type=='improvementProject'?'projects':data.type=='survey'?data.type:data.type+'s' + let index = this.solutionsList.findIndex((val)=>{return val.sectionName==sectionName}) + if(index!==-1){ + this.solutionsList[index].sectionList.push(data) + }else{ + let order=data.type=='improvementProject'?0:data.type=='observation'?1:data.type=='course'?2:3 + this.solutionsList.push({sectionName:sectionName,sectionList:[data],order:order}) + } + }); + this.filteredList=this.solutionsList.sort((a,b)=>{return a.order - b.order}) + } + + onFilterChange(event){ + this.selectedFilterIndex = event.data.index + this.filteredList=this.solutionsList + this.selectedSection = '' + if(event.data.index!==0){ + this.filteredList = this.solutionsList.filter((data)=>{ + return data.sectionName == event.data.text.toLowerCase() + }) + this.selectedSection = event.data.text.toLowerCase() + } + } + + joinProgram(){ + this.popupService.showJoinProgramForProjectPopup("FRMELEMNTS_LBL_JOIN_PROGRAM_POPUP",this.programDetails.programName,'program', + "FRMELEMNTS_LBL_JOIN_PROGRAM_POPUP","FRMELEMNTS_LBL_JOIN_PROGRAM_MSG2").then( + (data:any)=>{ + if(data){ + this.showConsentPopup() + } + } + ) + } + + showConsentPopup(message?){ + this.utils.showConsentPopup('program').then((data)=>{ + if(data!==undefined){ + this.programDetails.programJoined = true + if(message){ + this.toastService.openToast(message) + } + } + }) + } + + cardClick(){ + if(!this.programDetails.programJoined){ + this.joinProgram() + } + } + + save(event){ + let message + this.translate.get(['FRMELEMNTS_MSG_DATA_SETTINGS_UPDATE_SUCCESS']).subscribe((msg)=>{ + message = msg['FRMELEMNTS_MSG_DATA_SETTINGS_UPDATE_SUCCESS'] + }) + if(this.sharingStatus!==event){ + this.showConsentPopup(message) + this.sharingStatus=event + }else{ + this.toastService.openToast(message) + } + } + + ionViewWillLeave(){ + this.utils.closeConsentPopup() + } + + selectSection(name){ + this.selectedSection = name + } +} \ No newline at end of file diff --git a/src/app/manage-learn/programs/program-listing/program-listing.component.ts b/src/app/manage-learn/programs/program-listing/program-listing.component.ts index 947581ba81..657eddef6c 100644 --- a/src/app/manage-learn/programs/program-listing/program-listing.component.ts +++ b/src/app/manage-learn/programs/program-listing/program-listing.component.ts @@ -84,7 +84,7 @@ export class ProgramListingComponent implements OnInit { } selectedProgram(id) { - this.router.navigate([`/${RouterLinks.PROGRAM}/${RouterLinks.SOLUTIONS}`, id]); + this.router.navigate([`/${RouterLinks.PROGRAM}/${RouterLinks.DETAILS}`,id]); } handleNavBackButton() { diff --git a/src/app/manage-learn/programs/programs.module.ts b/src/app/manage-learn/programs/programs.module.ts index 612a1d86f5..df3be49646 100644 --- a/src/app/manage-learn/programs/programs.module.ts +++ b/src/app/manage-learn/programs/programs.module.ts @@ -9,6 +9,8 @@ import { RouterLinks } from '@app/app/app.constant'; import { TranslateModule } from '@ngx-translate/core'; import { FormsModule } from '@angular/forms'; import { CoreModule } from '../core/core.module'; +import { ProgramDetailsComponent } from './program-details/program-details.component'; +import { CommonConsumptionModule } from '@project-sunbird/common-consumption'; const routes: Routes = [ { @@ -19,10 +21,14 @@ const routes: Routes = [ path: `${RouterLinks.SOLUTIONS}/:id`, component: SolutionListingComponent, }, + { + path: `${RouterLinks.DETAILS}/:id`, + component: ProgramDetailsComponent, + }, ]; @NgModule({ - declarations: [ProgramListingComponent, SolutionListingComponent], + declarations: [ProgramListingComponent, SolutionListingComponent, ProgramDetailsComponent], imports: [ CommonModule, RouterModule.forChild(routes), @@ -31,6 +37,7 @@ const routes: Routes = [ IonicModule, FormsModule, CoreModule, + CommonConsumptionModule, ], entryComponents:[] }) diff --git a/src/app/manage-learn/project/add-file/add-file.page.ts b/src/app/manage-learn/project/add-file/add-file.page.ts index f47e7cb40d..f32d874dbb 100644 --- a/src/app/manage-learn/project/add-file/add-file.page.ts +++ b/src/app/manage-learn/project/add-file/add-file.page.ts @@ -65,6 +65,7 @@ export class AddFilePage implements OnInit { this.description = params.taskId ? actions.TASK_FILE_DESCRIPTION.label : actions.PROJECT_FILE_DESCRIPTION.label; this.taskId = params.taskId; }) + this.updateRemarks = _.debounce(this.updateRemarks,1500) } ngOnInit() { } @@ -75,14 +76,7 @@ export class AddFilePage implements OnInit { } handleHeaderEvents($event) { - if ($event.name == 'back') { - if (JSON.stringify(this.projectCopy) !== JSON.stringify(this.project) || - JSON.stringify(this.projectCopy.tasks[this.taskIndex]) !== JSON.stringify(this.task)) { - this.pageExitConfirm(); - } else { - this.location.back() - } - } + this.location.back() } getProject() { this.db.query({ _id: this.projectId }).then( @@ -110,6 +104,7 @@ export class AddFilePage implements OnInit { } else { this.project.remarks = this.remarks } + this.update('save') } setHeaderConfig() { @@ -164,20 +159,24 @@ export class AddFilePage implements OnInit { delete(index) { this.attachments.splice(index, 1); - this.task.isEdit = true; this.update('delete'); + this.task.isEdit = true; } - onAction(event) { + async onAction(event) { if(!this.taskId){ - this.popupService.showPPPForProjectPopUp('FRMELEMNTS_LBL_EVIDENCES_CONTENT_POLICY', 'FRMELEMNTS_LBL_EVIDENCES_CONTENT_POLICY_TEXT', 'FRMELEMNTS_LBL_EVIDENCES_CONTENT_POLICY_LABEL', 'FRMELEMNTS_LBL_UPLOAD_EVIDENCES', 'https://diksha.gov.in/term-of-use.html', 'contentPolicy').then((data: any) => { + this.popupService.showPPPForProjectPopUp('FRMELEMNTS_LBL_EVIDENCES_CONTENT_POLICY', 'FRMELEMNTS_LBL_EVIDENCES_CONTENT_POLICY_TEXT', 'FRMELEMNTS_LBL_EVIDENCES_CONTENT_POLICY_LABEL', 'FRMELEMNTS_LBL_UPLOAD_EVIDENCES', 'https://diksha.gov.in/term-of-use.html', 'contentPolicy').then(async(data: any) => { if (data.isClicked) { if(data.isChecked){ if (event == 'openLink') { this.toggleLinkModal(); return; } - this.attachmentService.openAttachmentSource(event, this.attachments); + await this.attachmentService.openAttachmentSource(event, this.attachments); + setTimeout(() => { + this.update('save') + }, 1000); + }else{ this.toast.showMessage('FRMELEMNTS_MSG_EVIDENCES_CONTENT_POLICY_REJECT', 'danger'); } @@ -188,7 +187,10 @@ export class AddFilePage implements OnInit { this.toggleLinkModal(); return; } - this.attachmentService.openAttachmentSource(event, this.attachments); + await this.attachmentService.openAttachmentSource(event, this.attachments); + setTimeout(() => { + this.update('save') + }, 1000); } } @@ -197,13 +199,11 @@ export class AddFilePage implements OnInit { if (this.taskId) { this.task.attachments = this.attachments; this.task.remarks = this.remarks; + this.location.back(); if (JSON.stringify(this.projectCopy.tasks[this.taskIndex]) !== JSON.stringify(this.task)) { this.task.isEdit = true; this.project.isEdit = true; - this.taskId ? this.update(): this.update('submit'); this.toast.showMessage('FRMELEMNTS_LBL_FILES_ATTACHED', 'success') - } else { - this.location.back(); } } else { if (this.network.isNetworkAvailable) { @@ -223,6 +223,7 @@ export class AddFilePage implements OnInit { this.project.attachments = this.project?.attachments.concat(this.projectService.getLinks(event)); } this.toast.showMessage('FRMELEMNTS_MSG_SUCCESSFULLY_ATTACHED', 'success'); + this.update('save')   } this.toggleLinkModal(); } @@ -237,11 +238,8 @@ export class AddFilePage implements OnInit { .update(this.project) .then((success) => { this.project._rev = success.rev; - if (type == 'submit') { - this.attachments = []; - this.doSyncAction(type === 'submit'); - }else{ - this.location.back(); + if(type !== 'save'){ + this.location.back() } }) } @@ -255,35 +253,6 @@ export class AddFilePage implements OnInit { } } - async pageExitConfirm() { - let data; - this.translate.get(["FRMELEMNTS_MSG_ATTACHMENT_PAGE_EXIT_CONFIRM", "FRMELEMNTS_BTN_EXIT_PAGE", "FRMELEMNTS_BTN_YES_PAGE", "FRMELEMNTS_LBL_YES", "NO"]).subscribe((text) => { - data = text; - }); - const alert = await this.alert.create({ - cssClass: 'central-alert', - header: data['FRMELEMNTS_BTN_EXIT_PAGE'], - message: data['FRMELEMNTS_MSG_ATTACHMENT_PAGE_EXIT_CONFIRM'], - buttons: [ - { - text: this.taskId ? data["FRMELEMNTS_BTN_YES_PAGE"] : data["FRMELEMNTS_LBL_YES"], - handler: () => { }, - }, { - text: data["NO"], - role: "cancel", - cssClass: "secondary", - handler: (blah) => { - }, - }, - ], - }); - await alert.present(); - let resp = await alert.onDidDismiss(); - if (resp.role !== 'cancel') { - this.location.back(); - } - } - async submitProjectConfirmation() { let data; this.translate.get(["FRMELEMNTS_MSG_SUBMIT_PROJECT", "FRMELEMNTS_LBL_SUBMIT_IMPROVEMENT", "CANCEL", "FRMELEMNTS_BTN_SUBMIT"]).subscribe((text) => { @@ -316,7 +285,8 @@ export class AddFilePage implements OnInit { this.project.attachments = this.attachments; this.project.remarks = this.remarks; // this.project.status = statusType.submitted; - this.update('submit'); + this.attachments = []; + this.doSyncAction(true); }, 0) this.router.navigate([`${RouterLinks.PROJECT}/${RouterLinks.DETAILS}`], { queryParams: { diff --git a/src/app/manage-learn/shared/components/index.ts b/src/app/manage-learn/shared/components/index.ts index fc933f6ff8..1f4ac8a221 100644 --- a/src/app/manage-learn/shared/components/index.ts +++ b/src/app/manage-learn/shared/components/index.ts @@ -32,4 +32,6 @@ export * from './attachment-lists/attachment-lists.component'; export * from './report-list/report-list.component'; export * from './entity-search-local/entity-search-local.component'; export * from './start-improvement/start-improvement.component'; -export * from './join-program/join-program.component' +export * from './join-program/join-program.component'; +export * from './share-profile-data/share-profile-data.component'; +export * from './pii-consent-popup/pii-consent-popup.component' diff --git a/src/app/manage-learn/shared/components/join-program/join-program.component.html b/src/app/manage-learn/shared/components/join-program/join-program.component.html index ada73dd23c..7564ec88a5 100644 --- a/src/app/manage-learn/shared/components/join-program/join-program.component.html +++ b/src/app/manage-learn/shared/components/join-program/join-program.component.html @@ -11,7 +11,7 @@