src/app/modules/questionnaire/questionnaire/questionnaire.component.ts
OnInit
selector | app-questionnaire |
styleUrls | ./questionnaire.component.scss |
templateUrl | ./questionnaire.component.html |
Properties |
Methods |
HostListeners |
constructor(layoutService: LayoutService, fb: UntypedFormBuilder, resourceService: ResourceService, activatedRoute: ActivatedRoute, config: ConfigService, observationService: ObservationService, location: Location, observationUtilService: ObservationUtilService, slQService: SlQuestionnaireService, questionnaireService: QuestionnaireService)
|
|||||||||||||||||||||||||||||||||
Parameters :
|
window:beforeunload |
Arguments : '$event'
|
window:beforeunload($event: any)
|
Inherited from
ComponentDeactivate
|
Defined in
ComponentDeactivate:28
|
Async backOrContinue |
backOrContinue()
|
Returns :
any
|
canDeactivate |
canDeactivate()
|
Inherited from
ComponentDeactivate
|
Defined in
ComponentDeactivate:50
|
Returns :
boolean
|
getQuestionnare |
getQuestionnare()
|
Returns :
void
|
goBack |
goBack()
|
Returns :
void
|
initConfiguration |
initConfiguration()
|
Returns :
void
|
ngOnInit |
ngOnInit()
|
Returns :
void
|
Async onSubmit | ||||
onSubmit(save?)
|
||||
Parameters :
Returns :
any
|
Async openAlert | |||||||||
openAlert(msg, showCancel)
|
|||||||||
Parameters :
Returns :
unknown
|
redoLayout |
redoLayout()
|
Returns :
void
|
scrollToContent | ||||
scrollToContent(id)
|
||||
Parameters :
Returns :
void
|
submitEvidence | ||||
submitEvidence(payload)
|
||||
Parameters :
Returns :
void
|
unloadNotification | ||||||
unloadNotification($event: any)
|
||||||
Decorators :
@HostListener('window:beforeunload', ['$event'])
|
||||||
Inherited from
ComponentDeactivate
|
||||||
Defined in
ComponentDeactivate:28
|
||||||
Parameters :
Returns :
void
|
assessmentInfo |
Type : AssessmentInfo
|
canLeave |
Default value : false
|
evidence |
Type : Evidence
|
Public fb |
Type : UntypedFormBuilder
|
FIRST_PANEL_LAYOUT |
layoutConfiguration |
Type : any
|
Public layoutService |
Type : LayoutService
|
pageTitleSrc |
Type : string
|
Default value : 'Observation Form'
|
queryParams |
Type : any
|
questionnaireForm |
Type : UntypedFormGroup
|
Public resourceService |
Type : ResourceService
|
SECOND_PANEL_LAYOUT |
sections |
Type : Section[]
|
svgToDisplay |
Type : string
|
Default value : 'textbooks-banner-img.svg'
|
import { Component, OnInit } from '@angular/core';
import {
COLUMN_TYPE,
LayoutService,
ResourceService,
ConfigService,
} from '@sunbird/shared';
import { UntypedFormGroup, UntypedFormBuilder } from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { ObservationService, ObservationUtilService } from '@sunbird/core';
import { Location } from '@angular/common';
import { ComponentDeactivate } from '../guard/can-deactivate.guard';
import { AssessmentInfo, Evidence, IAssessmentDetails, Section, SlQuestionnaireService } from '@shikshalokam/sl-questionnaire';
import { QuestionnaireService } from '../questionnaire.service';
@Component({
selector: 'app-questionnaire',
templateUrl: './questionnaire.component.html',
styleUrls: ['./questionnaire.component.scss'],
})
export class QuestionnaireComponent
extends ComponentDeactivate
implements OnInit {
pageTitleSrc = 'Observation Form';
svgToDisplay = 'textbooks-banner-img.svg';
layoutConfiguration: any;
FIRST_PANEL_LAYOUT;
SECOND_PANEL_LAYOUT;
questionnaireForm: UntypedFormGroup;
sections: Section[];
evidence: Evidence;
queryParams: any;
assessmentInfo: AssessmentInfo;
canLeave = false;
constructor(
public layoutService: LayoutService,
public fb: UntypedFormBuilder,
public resourceService: ResourceService,
private activatedRoute: ActivatedRoute,
private config: ConfigService,
private observationService: ObservationService,
private location: Location,
private observationUtilService: ObservationUtilService,
private slQService: SlQuestionnaireService,
private questionnaireService: QuestionnaireService
) {
super();
}
canDeactivate() {
if (this.questionnaireForm) {
if (this.questionnaireForm.dirty && !this.canLeave) {
return false;
} else {
return true;
}
}
}
ngOnInit() {
this.initConfiguration();
this.activatedRoute.queryParams.subscribe((params) => {
this.queryParams = params;
this.getQuestionnare();
});
this.questionnaireForm = this.fb.group({});
window.scroll({
top: 0,
left: 0,
behavior: 'smooth',
});
}
getQuestionnare() {
const paramOptions = {
url:
this.config.urlConFig.URLS.OBSERVATION.GET_ASSESSMENT +
`${this.queryParams.observationId}?entityId=${this.queryParams.entityId}&submissionNumber=${this.queryParams.submissionNumber}&ecmMethod=${this.queryParams.evidenceCode}`,
};
this.observationService.post(paramOptions).subscribe(
(data: IAssessmentDetails) => {
this.assessmentInfo = data.result;
this.assessmentInfo = this.slQService.mapSubmissionToAssessment(
this.assessmentInfo
);
this.evidence = data.result.assessment.evidences[0];
this.evidence.startTime = Date.now();
this.sections = this.evidence.sections;
},
(error) => {}
);
}
initConfiguration() {
this.layoutConfiguration = this.layoutService.initlayoutConfig();
this.redoLayout();
}
redoLayout() {
if (this.layoutConfiguration != null) {
this.FIRST_PANEL_LAYOUT = this.layoutService.redoLayoutCSS(
0,
this.layoutConfiguration,
COLUMN_TYPE.threeToNine,
true
);
this.SECOND_PANEL_LAYOUT = this.layoutService.redoLayoutCSS(
1,
this.layoutConfiguration,
COLUMN_TYPE.threeToNine,
true
);
} else {
this.FIRST_PANEL_LAYOUT = this.layoutService.redoLayoutCSS(
0,
null,
COLUMN_TYPE.fullLayout
);
this.SECOND_PANEL_LAYOUT = this.layoutService.redoLayoutCSS(
1,
null,
COLUMN_TYPE.fullLayout
);
}
}
async onSubmit(save?) {
const msg = save
? this.resourceService.frmelmnts.lbl.saveConfirm
: this.resourceService.frmelmnts.lbl.submitConfirm;
const userConfirm = await this.openAlert(msg, true);
if (!userConfirm) {
return;
}
const evidenceData = this.slQService.getEvidenceData(
this.evidence,
this.questionnaireForm.value
);
save ? (evidenceData['status'] = 'draft') : null;
const profile: Object = await this.observationUtilService.getProfileDataList();
if (!profile) {
return;
}
const payload = {...profile, ...{evidence: evidenceData} };
this.submitEvidence(payload);
}
submitEvidence(payload) {
const paramOptions = {
url:
this.config.urlConFig.URLS.OBSERVATION.OBSERVATION_SUBMISSION_UPDATE +
`${this.assessmentInfo.assessment.submissionId}`,
data: payload,
};
this.observationService.post(paramOptions).subscribe(
async (data) => {
if (payload.evidence.status === 'draft') {
this.backOrContinue();
return;
}
const userResponse = await this.openAlert(
this.resourceService.frmelmnts.lbl.successfullySubmitted
);
if (userResponse) {
this.canLeave = true;
this.location.back();
}
},
(error) => {
this.openAlert(
payload.evidence.status === 'draft'
? this.resourceService.frmelmnts.lbl.failedToSave
: this.resourceService.frmelmnts.lbl.submissionFailed
);
}
);
}
async backOrContinue() {
const alertMetaData = await this.observationUtilService.getAlertMetaData();
alertMetaData.content.body.data =
this.resourceService.frmelmnts.lbl.successfullySaved;
alertMetaData.content.body.type = 'text';
alertMetaData.size = 'mini';
alertMetaData.footer.buttons.push({
type: 'accept',
returnValue: true,
buttonText: this.resourceService.frmelmnts.btn.back,
});
alertMetaData.footer.buttons.push({
type: 'cancel',
returnValue: false,
buttonText: this.resourceService.frmelmnts.lbl.continue,
});
alertMetaData.footer.className = 'double-btn';
const response = await this.observationUtilService.showPopupAlert(
alertMetaData
);
if (response) {
this.canLeave = true;
this.location.back();
}
}
async openAlert(msg, showCancel = false) {
const alertMetaData = await this.observationUtilService.getAlertMetaData();
alertMetaData.content.body.data = msg;
alertMetaData.content.body.type = 'text';
alertMetaData.content.title = '';
alertMetaData.size = 'mini';
alertMetaData.footer.buttons.push({
type: 'accept',
returnValue: true,
buttonText: showCancel
? this.resourceService.frmelmnts.btn.yes
: this.resourceService.frmelmnts.btn.ok,
});
alertMetaData.footer.className = 'single-btn';
if (showCancel) {
alertMetaData.footer.buttons.push({
type: 'cancel',
returnValue: false,
buttonText: this.resourceService.frmelmnts.btn.no,
});
alertMetaData.footer.className = 'double-btn';
}
return await this.observationUtilService.showPopupAlert(alertMetaData);
}
scrollToContent(id) {
const element = document.getElementById(id);
const headerOffset = 200;
const elementPosition = element.getBoundingClientRect().top;
const offsetPosition = elementPosition - headerOffset;
window.scrollBy({
top: offsetPosition,
behavior: 'smooth'
});
}
goBack() {
this.location.back();
}
}
<app-landing-section
[textToDisplay]="pageTitleSrc"
[svgToDisplay]="svgToDisplay"
[layoutConfiguration]="layoutConfiguration"
></app-landing-section>
<div [ngClass]="layoutConfiguration ? 'sbt-fluid-content-bg' : ''">
<div
class="sb-g"
[ngClass]="
layoutConfiguration ? 'sb-g sbt-container sbt-page-content' : 'sb-g'
"
>
<div [ngClass]="FIRST_PANEL_LAYOUT">
<div class="sticky-block p-10"
*ngIf="
assessmentInfo?.solution?.criteriaLevelReport &&
assessmentInfo?.solution?.isRubricDriven
"
>
<h5 class="pl-10">{{ resourceService.frmelmnts?.lbl?.sectionName }}</h5>
<div class="sbt-page-content-area sections pl-10">
<div *ngFor="let section of sections;let sectionIndex=index" class="section-list">
<a class="item item--tests" [ngClass]="{'selected': sectionIndex===selectedSectionIndex}" tabindex="0" (click)="scrollToContent(section.code);selectedSectionIndex=sectionIndex">
{{ section.name }}
</a>
</div>
</div>
</div>
</div>
<div [ngClass]="SECOND_PANEL_LAYOUT">
<div>
<button
type="button"
class="
sb-btn
sb-btn-normal
sb-btn-link
sb-btn-link-primary
sb-left-icon-btn
mr-auto
"
tabindex="0" (click)="goBack()"
>
<i class="icon-svg icon-svg--xxs icon-back mr-4"
><svg class="icon icon-svg--primary">
<use xlink:href="assets/images/sprite.svg#arrow-long-left"></use>
</svg>
</i>
{{ resourceService.frmelmnts?.btn?.back }}
</button>
</div>
<div style="position: relative">
<div class="overlay" *ngIf="evidence?.isSubmitted"></div>
<div
*ngFor="let section of sections"
[id]="section.code"
[ngClass]="{ 'evidence-completed': evidence?.isSubmitted }"
>
<div
*ngIf="
assessmentInfo?.solution?.criteriaLevelReport &&
assessmentInfo?.solution?.isRubricDriven
"
class="sbt-page-content-area my-20"
>
<h4 class="sb-color-primary">{{ section.name }}</h4>
</div>
<div
[ngClass]="
layoutConfiguration
? 'sbt-page-content-area'
: 'ui container mt-24'
"
>
<form [formGroup]="questionnaireForm" class="adjust">
<sl-input
[questions]="section.questions"
[questionnaireForm]="questionnaireForm"
></sl-input>
</form>
</div>
</div>
</div>
<div
[ngClass]="{
'd-flex flex-jc-space-evenly': true,
'evidence-completed': evidence?.isSubmitted
}"
class="sticky-footer"
*ngIf="!evidence?.isSubmitted"
>
<button
class="sb-btn sb-btn-normal sb-btn-primary"
type="button"
tabindex="0" (click)="onSubmit('save')"
>
{{ resourceService?.frmelmnts?.btn?.save | translate }}
</button>
<button
[ngClass]="{
'sb-btn sb-btn-normal': true,
'sb-btn-primary': questionnaireForm?.valid,
'sb-btn-disabled': !questionnaireForm?.valid
}"
type="button"
[disabled]="!questionnaireForm?.valid"
tabindex="0" (click)="onSubmit()"
>
{{ resourceService?.frmelmnts?.btn?.submit | translate }}
</button>
</div>
</div>
</div>
</div>
./questionnaire.component.scss
@use "./../../../../../node_modules/@project-sunbird/sb-styles/assets/mixins/mixins" as *;
.sections {
width: 80%;
@media only screen and (min-width: 976px) {
height: 60vh;
overflow: auto;
}
}
.sticky-footer {
position: sticky;
bottom: 0;
z-index: 2;
background-color: var(--sb-card-bg);
padding: calculateRem(15px) 0;
border-radius: calculateRem(5px);
margin: calculateRem(15px) 0;
}
.section-list {
margin-bottom: calculateRem(20px);
z-index: 9;
position: relative;
}
.evidence-completed {
pointer-events: none;
button {
pointer-events: none;
}
}
::ng-deep {
.double-btn{
justify-content: flex-start !important;
flex-direction: row-reverse;
}
.question-card.sb--card {
border-radius: calculateRem(28px);
padding: calculateRem(20px);
width: 100%;
margin-bottom: calculateRem(20px);
.sb-checkbox label,
.sb-radio-btn-checkbox label {
color: var(--body-color);
font-weight: normal;
}
input:focus,
input:focus ~ label {
color: var(--body-color);
}
#range {
background-color: var(--sb-card-bg);
}
.student-card {
background-color: var(--sb-card-bg);
}
.question-date-input,
input:active.question-date-input,
input:focus.question-date-input {
background: var(--cc-sbcard-data1-bg);
color: var(--sb-prominent-filter-title);
}
}
.question-card.sb--card:last-child {
margin-bottom: calculateRem(20px);
}
.question-card.sb--card,
.sb-radio-btn-checkbox {
width: 100%;
background-color: var(--sb-card-bg);
color: var(--primary-color);
}
label {
color: var(--body-color);
}
.valid-response {
color: var(--green);
}
}
.remarks {
margin-top: calculateRem(15px);
}
.overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: transparent;
z-index: 5;
}
.adjust {
margin: calculateRem(15px) calculateRem(5px);
}
.sticky-block {
position: sticky;
top: 33%;
z-index: 9;
a {
color: var(--gray-800);
font-weight: 600;
cursor: pointer;
}
a.selected {
color: var(--primary-color);
}
}