File

src/app/modules/questionnaire/questionnaire/questionnaire.component.ts

Extends

ComponentDeactivate

Implements

OnInit

Metadata

Index

Properties
Methods
HostListeners

Constructor

constructor(layoutService: LayoutService, fb: UntypedFormBuilder, resourceService: ResourceService, activatedRoute: ActivatedRoute, config: ConfigService, observationService: ObservationService, location: Location, observationUtilService: ObservationUtilService, slQService: SlQuestionnaireService, questionnaireService: QuestionnaireService)
Parameters :
Name Type Optional
layoutService LayoutService No
fb UntypedFormBuilder No
resourceService ResourceService No
activatedRoute ActivatedRoute No
config ConfigService No
observationService ObservationService No
location Location No
observationUtilService ObservationUtilService No
slQService SlQuestionnaireService No
questionnaireService QuestionnaireService No

HostListeners

window:beforeunload
Arguments : '$event'
window:beforeunload($event: any)
Inherited from ComponentDeactivate

Methods

Async backOrContinue
backOrContinue()
Returns : any
canDeactivate
canDeactivate()
Inherited from ComponentDeactivate
Returns : boolean
getQuestionnare
getQuestionnare()
Returns : void
goBack
goBack()
Returns : void
initConfiguration
initConfiguration()
Returns : void
ngOnInit
ngOnInit()
Returns : void
Async onSubmit
onSubmit(save?)
Parameters :
Name Optional
save Yes
Returns : any
Async openAlert
openAlert(msg, showCancel)
Parameters :
Name Optional Default value
msg No
showCancel No false
Returns : unknown
redoLayout
redoLayout()
Returns : void
scrollToContent
scrollToContent(id)
Parameters :
Name Optional
id No
Returns : void
submitEvidence
submitEvidence(payload)
Parameters :
Name Optional
payload No
Returns : void
unloadNotification
unloadNotification($event: any)
Decorators :
@HostListener('window:beforeunload', ['$event'])
Inherited from ComponentDeactivate
Parameters :
Name Type Optional
$event any No
Returns : void

Properties

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);
  }
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""