File

src/app/modules/dashboard/components/course-consumption/course-consumption.component.ts

Description

The course consumption dashboard component

Display course consumption dashboard

Implements

OnDestroy AfterViewInit

Metadata

Index

Properties
Methods

Constructor

constructor(route: Router, consumption: CourseConsumptionService, activatedRoute: ActivatedRoute, searchService: SearchService, rendererService: RendererService, resourceService: ResourceService, navigationhelperService: NavigationHelperService, generaliseLabelService: GeneraliseLabelService)

Default method of CourseConsumptionComponent class

Parameters :
Name Type Optional Description
route Router No

Url navigation

consumption CourseConsumptionService No

To get dashboard data

activatedRoute ActivatedRoute No

To get param(s) from url

searchService SearchService No

To get logged-in user published course(s)

rendererService RendererService No

To get chart service

resourceService ResourceService No

To get language constant

navigationhelperService NavigationHelperService No
generaliseLabelService GeneraliseLabelService No

Methods

getDashboardData
getDashboardData(timePeriod: string, identifier: string)

Function to get dashboard data for given time period and course unique identifier

Parameters :
Name Type Optional Description
timePeriod string No

timePeriod: last 7d/14d/5w

identifier string No

course unique identifier

Example :
getDashboardData(7d, do_xxxxx)
Returns : void
getMyContent
getMyContent()

Get published course(s) of logged-in user

Returns : void
graphNavigation
graphNavigation(step: string)

Function used to switch graph - from Number of user per day to Time spent by day and vice versa

Parameters :
Name Type Optional Description
step string No

next / previous

Returns : void
ngAfterViewInit
ngAfterViewInit()
Returns : void
ngOnDestroy
ngOnDestroy()
Returns : void
onAfterCourseChange
onAfterCourseChange(course: literal type)

Function to change course selection and display selected course data

Parameters :
Name Type Optional Description
course literal type No

course object containg course details

Example :
onAfterCourseChange({name: Course 1, identifier: do_xxxxx})
Returns : boolean
onAfterFilterChange
onAfterFilterChange(timePeriod: string)

Function to change time filter and get selected time period data.

As of now dashboard supports only to show last 7 days, 14 days, and 5 weeks data

Parameters :
Name Type Optional Description
timePeriod string No

timePeriod: last 7d / 14d / 5w

Example :
onAfterFilterChange(7d)
Returns : boolean
validateIdentifier
validateIdentifier(identifier: string)

This function is used to validate given course identifier.

User gets redirect to home page if url contains invalid identifier or valid identifier but logged-in user is not a owner of that identifier

Parameters :
Name Type Optional Description
identifier string No

course unique identifier

Example :
validateIdentifier(do_xxxxx)
Returns : void

Properties

Public activatedRoute
Type : ActivatedRoute

To get params from url

blockData
Type : Array<any>
Default value : []

Contains dashboard block data

chartLegend
Default value : true

To display graph legend

chartType
Type : string
Default value : 'line'

Chart type

Public consumptionService
Type : CourseConsumptionService

To get consumption dashboard data

courseName
Type : string
Default value : ''

Contains course name of selected course

Public generaliseLabelService
Type : GeneraliseLabelService
graphData
Type : any

Contains course consumption line chart data

identifier
Type : string
Default value : ''

Contains selected course identifier

Identifier is needed to construct dashboard api url

interactObject
Type : any
isMultipleCourses
Default value : false

Contains boolean value to hide / show course selection dropdown

myCoursesList
Type : Array<any>
Default value : []

Contains list of published course(s) of logged-in user

Public navigationhelperService
Type : NavigationHelperService
rendererService
Type : RendererService

Chart renderer to call chart service like Line chart service

Currently it supports only line and bar chart

resourceService
Type : ResourceService

To get language constant

Public route
Type : Router

Router to change url

searchService
Type : SearchService

To get logged-in user published course(s)

selectedCourse
Type : any

Selected course details

showDashboard
Default value : false

To hide show graph canvas

showGraph
Type : number
Default value : 0

Contains Graph index to switch between two graphs

showLoader
Default value : true

To show / hide loader

telemetryImpression
Type : IImpressionEventInput

telemetryImpression object for course consumption dashboard page

timePeriod
Type : string
Default value : '7d'

Contains time period - last 7days, 14days, and 5weeks

timePeriodInteractData
Type : IInteractEventEdata
Public unsubscribe
Default value : new Subject<void>()

Variable to gather and unsubscribe all observable subscriptions in this component.

import {takeUntil} from 'rxjs/operators';
import { Component, OnDestroy, AfterViewInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
// Custom service(s)
import { RendererService, CourseConsumptionService } from './../../services';
import { SearchService, GeneraliseLabelService } from '@sunbird/core';
import { ResourceService, ServerResponse, NavigationHelperService } from '@sunbird/shared';
// Interface
import { DashboardData } from './../../interfaces';
import { IImpressionEventInput, IInteractEventEdata } from '@sunbird/telemetry';
import * as _ from 'lodash-es';

import { Subject } from 'rxjs';

/**
 * The course consumption dashboard component
 *
 * Display course consumption dashboard
 */
@Component({
  selector: 'app-course-consumption',
  templateUrl: './course-consumption.component.html',
  styleUrls: ['./course-consumption.component.scss']
})
export class CourseConsumptionComponent implements OnDestroy, AfterViewInit {
  /**
   * Variable to gather and unsubscribe all observable subscriptions in this component.
   */
  public unsubscribe = new Subject<void>();
  timePeriodInteractData: IInteractEventEdata;
  interactObject: any;
  /**
   * Contains time period - last 7days, 14days, and 5weeks
   */
  timePeriod = '7d';

  /**
   * Contains selected course identifier
   *
   * Identifier is needed to construct dashboard api url
   */
  identifier = '';

  /**
   * Contains list of published course(s) of logged-in user
   */
  myCoursesList: Array<any> = [];

  /**
   * Contains course name of selected course
   */
  courseName = '';

  /**
   * Selected course details
   */
  selectedCourse: any;

  /**
   * Contains course consumption line chart data
   */
  graphData: any;

  /**
   * Contains dashboard block data
   */
  blockData: Array<any> = [];

  /**
   * Contains Graph index to switch between two graphs
   */
  showGraph = 0;

  /**
   * To show / hide loader
   */
  showLoader = true;

  /**
   * Contains boolean value to hide / show course selection dropdown
   */
  isMultipleCourses = false;

  /**
   * To display graph legend
   */
  chartLegend = true;

  /**
   * Chart type
   */
  chartType = 'line';

  /**
   * To hide show graph canvas
   */
  showDashboard = false;

  /**
   * To get consumption dashboard data
   */
  public consumptionService: CourseConsumptionService;

  /**
   * Router to change url
   */
  public route: Router;

  /**
   * To get params from url
   */
  public activatedRoute: ActivatedRoute;

  /**
   * To get logged-in user published course(s)
   */
  searchService: SearchService;

  /**
   * Chart renderer to call chart service like Line chart service
   *
   * Currently it supports only line and bar chart
   */
  rendererService: RendererService;

  /**
   * To get language constant
   */
  resourceService: ResourceService;

  /**
	 * telemetryImpression object for course consumption dashboard page
	*/
  telemetryImpression: IImpressionEventInput;

  /**
   * Default method of CourseConsumptionComponent class
   *
   * @param {Router} route Url navigation
   * @param {CourseConsumptionService} consumption To get dashboard data
   * @param {ActivatedRoute} activatedRoute To get param(s) from url
   * @param {SearchService} searchService To get logged-in user published course(s)
   * @param {RendererService} rendererService To get chart service
   * @param {ResourceService} resourceService To get language constant
   */
  constructor(route: Router, consumption: CourseConsumptionService, activatedRoute: ActivatedRoute, searchService: SearchService,
    rendererService: RendererService, resourceService: ResourceService, public navigationhelperService: NavigationHelperService,
    public generaliseLabelService: GeneraliseLabelService) {
    this.consumptionService = consumption;
    this.activatedRoute = activatedRoute;
    this.searchService = searchService;
    this.rendererService = rendererService;
    this.resourceService = resourceService;
    this.route = route;
    // init the default impression event
    this.activatedRoute.params.pipe(
    takeUntil(this.unsubscribe))
    .subscribe(params => {
      if (params.id && params.timePeriod) {
        this.interactObject = { id: params.id, type: 'Course', ver: '1.0' };
        this.isMultipleCourses = false;
        this.showDashboard = true;
        this.getDashboardData(params.timePeriod, params.id);
      }
    }
    );
    this.getMyContent();
  }

  /**
   * Function to get dashboard data for given time period and course unique identifier
   *
   * @param {string} timePeriod  timePeriod: last 7d/14d/5w
   * @param {string} identifier  course unique identifier
   *
   * @example getDashboardData(7d, do_xxxxx)
   */
  getDashboardData(timePeriod: string, identifier: string) {
    this.showLoader = true;
    this.timePeriod = timePeriod ? timePeriod : '7d';
    this.identifier = identifier;
    const params = {
      data: {
        identifier: this.identifier,
        timePeriod: this.timePeriod
      }
    };
    this.consumptionService.getDashboardData(params).pipe(
    takeUntil(this.unsubscribe))
      .subscribe((data: DashboardData) => {
        this.blockData = data.numericData;
        this.graphData = this.rendererService.visualizer(data, this.chartType);
        this.showLoader = false;
      },
      err => {
        this.showLoader = false;
      }
      );
  }

  /**
   * This function is used to validate given course identifier.
   *
   * User gets redirect to home page if url contains invalid identifier or
   * valid identifier but logged-in user is not a owner of that identifier
   *
   * @param {string} identifier course unique identifier
   *
   * @example validateIdentifier(do_xxxxx)
   */
  validateIdentifier(identifier: string) {
    if (identifier) {
      const selectedCourse = _.find(this.myCoursesList, ['identifier', identifier]);
      if (selectedCourse && selectedCourse.identifier) {
        this.courseName = selectedCourse.name;
        this.selectedCourse = selectedCourse;
      } else {
        this.route.navigate(['home']);
      }
    }
  }

  /**
   * Get published course(s) of logged-in user
   */
  getMyContent(): void {
    // First check local storage
    const response = this.searchService.searchedContentList;
    if (response && response.count) {
      this.myCoursesList = response.content;
      if (this.myCoursesList.length === 1) {
        this.identifier = this.myCoursesList[0].identifier;
        this.courseName = this.myCoursesList[0].name;
        this.route.navigate(['dashBoard/activity/course/consumption', this.identifier, this.timePeriod]);
      }
      this.validateIdentifier(this.identifier);
      this.showLoader = false;
    } else {
      // Make search api call
      const searchParams = { status: ['Live'], contentType: ['Course'], params: { lastUpdatedOn: 'desc' } };
      this.searchService.searchContentByUserId(searchParams).pipe(
      takeUntil(this.unsubscribe))
      .subscribe(
        (data: ServerResponse) => {
          if (data.result.count && data.result.content) {
            this.myCoursesList = data.result.content;
            if (data.result.content.length === 1) {
              this.identifier = data.result.content[0].identifier;
              this.courseName = data.result.content[0].name;
              this.route.navigate(['dashBoard/activity/course/consumption', this.identifier, this.timePeriod]);
            } else {
              this.isMultipleCourses = true;
            }
          }
          this.showLoader = false;
          if (this.identifier) {
            this.validateIdentifier(this.identifier);
          }
        },
        (err: ServerResponse) => {
          this.showLoader = false;
        }
      );
    }
  }

  /**
   * Function to change course selection and display selected course data
   *
   * @param {object} course course object containg course details
   *
   * @example onAfterCourseChange({name: Course 1, identifier: do_xxxxx})
   */
  onAfterCourseChange(course: { identifier: string }) {
    if (this.identifier === course.identifier) {
      return false;
    }

    this.route.navigate(['dashBoard/activity/course/consumption', course.identifier, this.timePeriod]);
  }

  /**
   * Function to change time filter and get selected time period data.
   *
   * As of now dashboard supports only to show last 7 days, 14 days, and 5 weeks data
   *
   * @param {string} timePeriod timePeriod: last 7d / 14d / 5w
   *
   * @example onAfterFilterChange(7d)
   */
  onAfterFilterChange(timePeriod: string) {
    if (this.timePeriod === timePeriod) {
      return false;
    }

    this.route.navigate(['dashBoard/activity/course/consumption', this.identifier, timePeriod]);
  }

  /**
   * Function used to switch graph - from Number of user per day to Time spent by day and vice versa
   *
   * @param {string} step next / previous
   */
  graphNavigation(step: string) {
    step === 'next' ? this.showGraph++ : this.showGraph--;
  }

  ngAfterViewInit () {
    setTimeout(() => {
      const params = this.activatedRoute.snapshot.params;
      this.telemetryImpression = {
        context: {
          env: this.activatedRoute.snapshot.data.telemetry.env
        },
        edata: {
          // update the impression event after a course is selected
          uri: 'dashboard/activity/course/consumption/' + params.id + '/' + params.timePeriod,
          type: this.activatedRoute.snapshot.data.telemetry.type,
          pageid: this.activatedRoute.snapshot.data.telemetry.pageid,
          duration: this.navigationhelperService.getPageLoadTime()
        },
        object: {
          id: params.id,
          type: 'Course',
          ver: '1.0'
        }
      };
    });
  }
  ngOnDestroy() {
    this.unsubscribe.next();
    this.unsubscribe.complete();
  }
}
<div class="ui container">
<div class="ui grid">
  <div class="twelve wide column">
    <div class="ui grid mt-20">
      <div class="five wide column float-ContentLeft" *ngIf="myCoursesList && myCoursesList.length === 1">
        <span class="dashBoardSectionHeading">
          <i class="large bar chart icon"></i>
        </span>
        <span class="dashBoardSectionHeading">{{courseName}}</span>
      </div>
      <div class="one wide column" *ngIf="myCoursesList && myCoursesList.length > 1">
        <span class="dashBoardSectionHeading">
          <i class="large bar chart icon pt-5"></i>
        </span>
      </div>
      <div class="four wide column float-ContentLeft course-dropdown" *ngIf="myCoursesList && myCoursesList.length > 1">
        <sui-select class="selection" [(ngModel)]="selectedCourse" (ngModelChange)="onAfterCourseChange($event)" [options]="myCoursesList"
          labelField="name" [placeholder]="'Select Course '" [isSearchable]="true" #select>
          <sui-select-option [ngClass]="{'active': course.identifier === identifier }" *ngFor="let course of select.filteredOptions"
            [value]="course" appTelemetryInteract [telemetryInteractObject]="{ id: course.identifier, type: 'Course', ver: '1.0' }"
            [telemetryInteractEdata]="{id:'courseDropdown',type:'click',pageid:'course-creator-dashboard'}">
          </sui-select-option>
        </sui-select>
      </div>
    </div>
    <!-- Filters -->
    <div class="ui grid mt-10 pl-5" *ngIf="showDashboard">
      <div class="six wide column" *ngIf="myCoursesList && myCoursesList.length > 0">
        <div class="ui text menu float-ContentLeft pt-10">
          <span class="dashBoardMenuItem cursor-pointer active" (click)="onAfterFilterChange('7d')" tabindex="0" [ngClass]="{'active': timePeriod === '7d' }"
            appTelemetryInteract [telemetryInteractObject]="interactObject" [telemetryInteractEdata]="{id:'7d',type:'click',pageid:'course-creator-dashboard'}">
            {{resourceService?.frmelmnts?.lbl?.dashboardsevendaysfilter}}
          </span>&nbsp;&nbsp;&nbsp;&nbsp;
          <span class="dashBoardMenuItem cursor-pointer" (click)="onAfterFilterChange('14d')" tabindex="0" [ngClass]="{'active': timePeriod === '14d' }"
            appTelemetryInteract [telemetryInteractObject]="interactObject" [telemetryInteractEdata]="{id:'14d',type:'click',pageid:'course-creator-dashboard'}">
            {{resourceService?.frmelmnts?.lbl?.dashboardfourteendaysfilter}}
          </span>&nbsp;&nbsp;&nbsp;&nbsp;
          <span class="dashBoardMenuItem cursor-pointer" (click)="onAfterFilterChange('5w')" tabindex="0" [ngClass]="{'active': timePeriod === '5w' }"
            appTelemetryInteract [telemetryInteractObject]="interactObject" [telemetryInteractEdata]="{id:'5w',type:'click',pageid:'course-creator-dashboard'}">
            {{resourceService?.frmelmnts?.lbl?.dashboardfiveweeksfilter}}
          </span>&nbsp;&nbsp;&nbsp;&nbsp;
        </div>
      </div>
      <div class="two wide column"></div>
    </div>
    <!-- Loader -->
    <div class="twelve wide column mt-20" *ngIf="showLoader">
      <app-loader></app-loader>
    </div>
    <!-- Select course div -->
    <div class="ui warning message tweleve wide column" *ngIf="myCoursesList && myCoursesList.length > 1 && !showLoader" [ngStyle]="{'display': showDashboard ? 'none' : '' }">
      <div class="header" [appTelemetryImpression]="telemetryImpression">{{generaliseLabelService?.frmelmnts?.lbl?.dashboardnocourseselected}}</div>
      {{generaliseLabelService?.frmelmnts?.lbl?.dashboardnocourseselecteddesc}}
    </div>
    <!-- Empty course -->
    <div *ngIf="!showLoader" class="mt-20">
      <div class="ui info message" *ngIf="myCoursesList && myCoursesList.length === 0">
        <div class="header" [appTelemetryImpression]="telemetryImpression">{{resourceService?.frmelmnts?.instn?.t0061}}</div>
        <ul class="list">
          <li>{{generaliseLabelService?.frmelmnts?.instn?.t0063}}</li>
        </ul>
      </div>
    </div>
    <!-- Actual dashboard data -->
    <div class="consumption-data-holder" *ngIf="showDashboard && myCoursesList && myCoursesList.length > 0" [ngStyle]="{'display':showLoader ? 'none' : '' }">
      <div class="ui four cards">
        <div class="card" *ngFor="let block of blockData">
          <div class="content center aligned">
            <div class="meta dashBoardCardText">{{block.name}}</div>
            <h2 class="description dashboardCardSubText">{{block.value}}</h2>
          </div>
        </div>
      </div>
      <div class="ui one column grid mt-20" *ngIf="graphData && graphData.length > 0">
        <div class="column">
          <div class="regular slider pt-30 course-graph-holder">
            <div *ngFor="let block of graphData;let graphIndex = index;">
              <div [hidden]="showGraph === graphIndex">
                <div class="ui segment">
                  <canvas baseChart width="300" height="110" [datasets]="block.yaxesData" [labels]="block.xaxesData" [options]="block.chartOptions"
                    [colors]="block.chartColors" [legend]="chartLegend" [chartType]="chartType">
                  </canvas>
                </div>
              </div>
            </div>
            <div class="corse-graph-navigation-btn">
              <button class="ui primary basic compact icon button" (click)="graphNavigation('previous')" tabindex="0" [ngClass]="{'disabled': showGraph <= 0 }"
                appTelemetryInteract [telemetryInteractObject]="interactObject" [telemetryInteractEdata]="{id:'previous',type:'click',pageid:'course-creator-dashboard'}">
                <i class="left arrow icon"></i>
              </button>
              <button class="ui primary basic compact icon button" (click)="graphNavigation('next')" tabindex="0" [ngClass]="{'disabled': showGraph >= graphData.length - 1 }"
                appTelemetryInteract [telemetryInteractObject]="interactObject" [telemetryInteractEdata]="{id:'next',type:'click',pageid:'course-creator-dashboard'}">
                <i class="right arrow icon"></i>
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
</div>

./course-consumption.component.scss


span.dashBoardMenuItem.active {
    color: var(--primary-color);
    font-weight: 700;
}
.dashBoardMenuItem {
    font-weight: 500;
    font-size: 0.9375em;
    color: var(--primary-color);
  }
.ui.cards > .card .meta.dashBoardCardText {
    font-weight: 500;
    font-size: 1.1em;
    color: var(--rc-7c7b7b);
  }
  .ui.cards > .card > .content > .description.dashboardCardSubText {
    font-weight: 500;
    font-size: 1.6em;
    color: var(--gray-800);
  }
  .dashBoardSectionHeading {
    font-weight: bold;
    font-size: 1.4em;
  }
  .float-ContentLeft {
    float: left !important;
  }
  .corse-graph-navigation-btn {
    position: absolute;
    right: 1.6em;
    top: 1.6em;
  }
  .course-graph-holder {
    display: inline;
  }
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""