File

src/app/download-manager/download-manager.page.ts

Implements

DownloadManagerPageInterface OnInit

Metadata

Index

Properties
Methods

Constructor

constructor(contentService: ContentService, deviceInfo: DeviceInfo, storageService: StorageService, ngZone: NgZone, commonUtilService: CommonUtilService, headerService: AppHeaderService, events: Events, popoverCtrl: PopoverController, appGlobalService: AppGlobalService, router: Router, telemetryGeneratorService: TelemetryGeneratorService, formAndFrameworkUtilService: FormAndFrameworkUtilService, db: DbService, storage: LocalStorageService, utils: UtilsService)
Parameters :
Name Type Optional
contentService ContentService No
deviceInfo DeviceInfo No
storageService StorageService No
ngZone NgZone No
commonUtilService CommonUtilService No
headerService AppHeaderService No
events Events No
popoverCtrl PopoverController No
appGlobalService AppGlobalService No
router Router No
telemetryGeneratorService TelemetryGeneratorService No
formAndFrameworkUtilService FormAndFrameworkUtilService No
db DbService No
storage LocalStorageService No
utils UtilsService No

Methods

Private checkAvailableSpace
checkAvailableSpace()
Returns : void
Async closeSelectAllPopup
closeSelectAllPopup()
Returns : any
Private Async deleteAllContents
deleteAllContents(emitedContents)
Parameters :
Name Optional
emitedContents No
Returns : any
Async deleteContents
deleteContents(emitedContents: EmitedContents)
Parameters :
Name Type Optional
emitedContents EmitedContents No
Returns : any
Async deleteObservations
deleteObservations(content)
Parameters :
Name Optional
content No
Returns : any
deleteProjects
deleteProjects(contents)
Parameters :
Name Optional
contents No
Returns : void
Private Async fetchStorageDestination
fetchStorageDestination()
Returns : any
Private generateInteractTelemetry
generateInteractTelemetry(contentCount: number, usedSpace: number, availableSpace: number)
Parameters :
Name Type Optional
contentCount number No
usedSpace number No
availableSpace number No
Returns : void
Private Async getAppName
getAppName()
Returns : unknown
Private Async getAppStorageInfo
getAppStorageInfo()
Async getDownloadedContents
getDownloadedContents(shouldGenerateTelemetry?, ignoreLoader?)
Parameters :
Name Optional
shouldGenerateTelemetry Yes
ignoreLoader Yes
Returns : any
Private handleHeaderEvents
handleHeaderEvents($event)
Parameters :
Name Optional
$event No
Returns : void
Async ionViewWillEnter
ionViewWillEnter()
Returns : any
ionViewWillLeave
ionViewWillLeave()
Returns : void
Async ngOnInit
ngOnInit()
Returns : unknown
onSortCriteriaChange
onSortCriteriaChange(sortAttribute)
Parameters :
Name Optional
sortAttribute No
Returns : void
Private Async presentPopupForLessStorageSpace
presentPopupForLessStorageSpace()
Returns : any
Private redirectToActivedownloads
redirectToActivedownloads()
Returns : void
Private redirectToSettings
redirectToSettings()
Returns : void
Private subscribeContentUpdateEvents
subscribeContentUpdateEvents()
Returns : void

Properties

_toast
Type : any
appName
Type : string
Public commonUtilService
Type : CommonUtilService
defaultImg
Default value : this.commonUtilService.convertFileSrc('assets/imgs/ic_launcher.png')
deleteAllConfirm
Private Optional deletedContentListTitle$
Type : BehaviorSubject<string>
downloadedContents
Type : Content[]
Default value : []
downloadsTab
Type : DownloadsTabComponent
Decorators :
@ViewChild('downloadsTab', {static: false})
headerObservable
Type : any
loader
Type : any
sortCriteria
Type : ContentSortCriteria[]
storageDestination
Type : any
storageInfo
Type : AppStorageInfo
import { Component, OnInit, Inject, NgZone, ViewChild } from '@angular/core';
import { PopoverController } from '@ionic/angular';
import { Events } from '@app/util/events';
import { Router } from '@angular/router';
import {
  Content,
  ContentDeleteRequest,
  ContentDeleteResponse,
  ContentDeleteStatus,
  ContentRequest,
  ContentService,
  ContentSortCriteria,
  ContentSpaceUsageSummaryRequest,
  ContentSpaceUsageSummaryResponse,
  DeviceInfo,
  Profile,
  SortOrder,
  StorageService,
  StorageDestination
} from 'sunbird-sdk';
import { AppGlobalService } from '@app/services/app-global-service.service';
import { AppHeaderService, } from '@app/services/app-header.service';
import { CommonUtilService, } from '@app/services/common-util.service';
import { TelemetryGeneratorService } from '@app/services/telemetry-generator.service';
import { AppStorageInfo, DownloadManagerPageInterface, EmitedContents } from './download-manager.interface';
import { RouterLinks, ContentFilterConfig, EventTopics } from '@app/app/app.constant';
import { SbPopoverComponent } from '@app/app/components/popups/sb-popover/sb-popover.component';
import { PageId, InteractType, Environment, InteractSubtype } from '@app/services/telemetry-constants';
import { FormAndFrameworkUtilService } from '@app/services';
import { featureIdMap } from '../feature-id-map';
import { BehaviorSubject } from 'rxjs';
import {
  SbInsufficientStoragePopupComponent
} from '@app/app/components/popups/sb-insufficient-storage-popup/sb-insufficient-storage-popup';
import { DownloadsTabComponent } from './downloads-tab/downloads-tab.component';
import { finalize, tap, skip, takeWhile } from 'rxjs/operators';
import { ContentUtil } from '@app/util/content-util';
import { DbService } from '../manage-learn/core/services/db.service';
import { UtilsService, LocalStorageService } from '../manage-learn/core';
import { storageKeys } from '../manage-learn/storageKeys';

@Component({
  selector: 'app-download-manager',
  templateUrl: './download-manager.page.html',
  styleUrls: ['./download-manager.page.scss'],
})
export class DownloadManagerPage implements DownloadManagerPageInterface, OnInit {
  headerObservable: any;
  _toast: any;
  storageInfo: AppStorageInfo;
  downloadedContents: Content[] = [];
  defaultImg = this.commonUtilService.convertFileSrc('assets/imgs/ic_launcher.png');
  loader: any;
  deleteAllConfirm;
  appName: string;
  sortCriteria: ContentSortCriteria[];
  storageDestination: any;
  private deletedContentListTitle$?: BehaviorSubject<string>;
  @ViewChild('downloadsTab', { static: false }) downloadsTab: DownloadsTabComponent;

  constructor(
    @Inject('CONTENT_SERVICE') private contentService: ContentService,
    @Inject('DEVICE_INFO') private deviceInfo: DeviceInfo,
    @Inject('STORAGE_SERVICE') private storageService: StorageService,
    private ngZone: NgZone,
    public commonUtilService: CommonUtilService,
    private headerService: AppHeaderService,
    private events: Events,
    private popoverCtrl: PopoverController,
    private appGlobalService: AppGlobalService,
    private router: Router,
    private telemetryGeneratorService: TelemetryGeneratorService,
    private formAndFrameworkUtilService: FormAndFrameworkUtilService,
    private db: DbService,
    private storage: LocalStorageService,
    private utils: UtilsService
  ) {
    this.events.subscribe(EventTopics.LAST_ACCESS_ON, (data) => {
      if (data) {
        this.getDownloadedContents();
      }
    });
  }

  async ngOnInit() {
    this.subscribeContentUpdateEvents();
    return Promise.all(
      [this.getDownloadedContents(true),
      this.getAppName()]
    );
  }

  async ionViewWillEnter() {
    this.events.subscribe('update_header', () => {
      this.headerService.showHeaderWithHomeButton(['download', 'settings']);
    });
    this.headerObservable = this.headerService.headerEventEmitted$.subscribe(eventName => {
      this.handleHeaderEvents(eventName);
    });

    this.headerService.showHeaderWithHomeButton(['download', 'settings']);
    await this.getAppStorageInfo();
    this.getDownloadedContents();
    this.checkAvailableSpace();
    this.fetchStorageDestination();
    this.events.subscribe(EventTopics.HAMBURGER_MENU_CLICKED, () => {
      this.closeSelectAllPopup();
    });
  }

  private async getAppName() {
    return this.commonUtilService.getAppName()
      .then((appName: any) => {
        this.appName = appName;
      });
  }

  private async getAppStorageInfo(): Promise<AppStorageInfo> {
    const req: ContentSpaceUsageSummaryRequest = { paths: [this.storageService.getStorageDestinationDirectoryPath()] };
    return this.contentService.getContentSpaceUsageSummary(req).toPromise()
      .then((res: ContentSpaceUsageSummaryResponse[]) => {
        return this.deviceInfo.getAvailableInternalMemorySize().toPromise()
          .then((size) => {
            this.storageInfo = {
              usedSpace: res[0].sizeOnDevice,
              availableSpace: parseInt(size, 10)
            };
            return this.storageInfo;
          });
      });
  }

  async getDownloadedContents(shouldGenerateTelemetry?, ignoreLoader?) {
    const profile: Profile = this.appGlobalService.getCurrentUser();

    const defaultSortCriteria: ContentSortCriteria[] = [{
      sortAttribute: 'sizeOnDevice',
      sortOrder: SortOrder.DESC
    }];
    const primaryCategories = await this.formAndFrameworkUtilService.getSupportedContentFilterConfig(
      ContentFilterConfig.NAME_DOWNLOADS);
    const requestParams: ContentRequest = {
      uid: profile.uid,
      primaryCategories,
      audience: [],
      sortCriteria: this.sortCriteria || defaultSortCriteria
    };
    if (shouldGenerateTelemetry) {
      await this.getAppStorageInfo();
    }
    await this.contentService.getContents(requestParams).toPromise()
      .then(async data => {
        if (shouldGenerateTelemetry) {
          this.generateInteractTelemetry(data.length, this.storageInfo.usedSpace, this.storageInfo.availableSpace);
        }
        data.forEach((value) => {
          value.contentData['lastUpdatedOn'] = value.lastUpdatedTime;
          value.contentData.appIcon = ContentUtil.getAppIcon(value.contentData.appIcon,
            value.basePath, this.commonUtilService.networkInfo.isNetworkAvailable);
        });
        const query = {
            selector: {
           downloaded: true,
          },
        }; 
        if(this.db.pdb){
          let projectData: any = await this.db.customQuery(query);
          if (projectData.docs) {
            projectData.docs.sort(function (a, b) {
                return  new Date(b.updatedAt || b.syncedAt).valueOf() - new Date(a.updatedAt || a.syncedAt).valueOf() ;
              });
              projectData.docs.map(doc => {
                doc.contentData = { lastUpdatedOn: doc.updatedAt,name:doc.title };
                doc.type = 'project'
                doc.identifier=doc._id;
                data.push(doc)
            })
          }
        }
        this.storage
        .getLocalStorage(storageKeys.downloadedObservations)
        .then(resp => {
          resp.sort(function(a, b) {
            return ( new Date(b.lastViewedAt).valueOf() - new Date(a.lastViewedAt).valueOf());
          });
          resp.map(res => {
            res.contentData = { lastUpdatedOn: res.lastViewedAt, name: res.name, subject:res.programName };
            res.type = 'observation';
            res.identifier = res.programId + res.solutionId;
            data.push(res);
          });
        });
        this.ngZone.run(async () => {
          this.downloadedContents = data;
        });
      });
  }

  private generateInteractTelemetry(contentCount: number, usedSpace: number, availableSpace: number) {
    const valuesMap = {};
    valuesMap['count'] = contentCount;
    valuesMap['spaceTakenByApp'] = this.commonUtilService.fileSizeInMB(usedSpace);
    valuesMap['freeSpace'] = this.commonUtilService.fileSizeInMB(availableSpace);
    this.telemetryGeneratorService.generateExtraInfoTelemetry(valuesMap, PageId.DOWNLOADS);
  }

  async deleteContents(emitedContents: EmitedContents) {
    const projectContents = emitedContents.selectedContents.filter((content) => (content['type'] == 'project'));
    const observationContents = emitedContents.selectedContents.filter( content => (content['type'] == 'observation'));
    emitedContents.selectedContents = emitedContents.selectedContents.filter(content => !content['type'] || (content['type'] != 'project' && content['type'] != 'observation'));

    if (!emitedContents.selectedContents.length) {
      this.deleteProjects(projectContents);
      this.deleteObservations(observationContents);
      return;
    }
    this.deleteProjects(projectContents)
    this.deleteObservations(observationContents);

    const contentDeleteRequest: ContentDeleteRequest = {
      contentDeleteList: emitedContents.selectedContents,
    };

    if (emitedContents.selectedContents.length > 1) {
      await this.deleteAllContents(emitedContents);
    } else {
      this.loader = await this.commonUtilService.getLoader();
      await this.loader.present();

      this.contentService.deleteContent(contentDeleteRequest).toPromise()
        .then(async (data: ContentDeleteResponse[]) => {
          await this.loader.dismiss();
          this.loader = undefined;
          if (data && data[0].status === ContentDeleteStatus.NOT_FOUND) {
            this.commonUtilService.showToast(this.commonUtilService.translateMessage('CONTENT_DELETE_FAILED'));
          } else {
            this.events.publish('savedResources:update', {
              update: true
            });
            this.commonUtilService.showToast(this.commonUtilService.translateMessage('MSG_RESOURCE_DELETED'));
          }
        }).catch(async (error: any) => {
          await this.loader.dismiss();
          this.loader = undefined;
          this.commonUtilService.showToast(this.commonUtilService.translateMessage('CONTENT_DELETE_FAILED'));
        });
    }
  }

  private async deleteAllContents(emitedContents) {
    const valuesMap = {};
    valuesMap['size'] = this.commonUtilService.fileSizeInMB(emitedContents.selectedContentsInfo.totalSize);
    valuesMap['count'] = emitedContents.selectedContentsInfo.count;
    this.telemetryGeneratorService.generateInteractTelemetry(
      InteractType.TOUCH,
      InteractSubtype.DELETE_CLICKED,
      Environment.DOWNLOADS,
      PageId.BULK_DELETE_CONFIRMATION_POPUP, undefined,
      valuesMap,
      undefined,
      featureIdMap.downloadManager.DOWNLOADS_DELETE);
    const contentDeleteRequest: ContentDeleteRequest = {
      contentDeleteList: emitedContents.selectedContents
    };
    this.deletedContentListTitle$ = new BehaviorSubject('0/' + contentDeleteRequest.contentDeleteList.length);
    this.deleteAllConfirm = await this.popoverCtrl.create({
      component: SbPopoverComponent,
      componentProps: {
        sbPopoverHeading: this.commonUtilService.translateMessage('DELETE_PROGRESS'),
        actionsButtons: [
          {
            btntext: this.commonUtilService.translateMessage('CANCEL'),
            btnClass: 'sb-btn sb-btn-sm sb-btn-outline-info cancel-delete'
          },
        ],
        icon: null,
        metaInfo: this.commonUtilService.translateMessage('FILES_DELETED'),
        sbPopoverDynamicMainTitle: this.deletedContentListTitle$
      },
      cssClass: 'sb-popover danger sb-popover-cancel-delete',
    });
    await this.deleteAllConfirm.present();

    this.deleteAllConfirm.onDidDismiss().then((response) => {
      if (response) {
        this.contentService.clearContentDeleteQueue().toPromise();
      }
    });
    this.contentService.enqueueContentDelete(contentDeleteRequest).toPromise();
    this.contentService.getContentDeleteQueue().pipe(
      skip(1),
      takeWhile((list) => !!list.length),
      finalize(async () => {
        this.deletedContentListTitle$
          .next(`${contentDeleteRequest.contentDeleteList.length}/${contentDeleteRequest.contentDeleteList.length}`);

        this.deleteAllConfirm.dismiss();
        this.events.publish('savedResources:update', {
          update: true
        });
      })
    )
      .subscribe((list) => {
        this.deletedContentListTitle$
          .next(`${contentDeleteRequest.contentDeleteList.length - list.length}/${contentDeleteRequest.contentDeleteList.length}`);
      });
  }

  onSortCriteriaChange(sortAttribute): void {
    let sortAttr: string;
    if (sortAttribute.selectedItem === 'CONTENT_SIZE') {
      sortAttr = 'sizeOnDevice';
    } else if (sortAttribute.selectedItem === 'LAST_VIEWED') {
      sortAttr = 'lastUsedOn';
    }
    const valuesMap = {};
    valuesMap['selectedOption'] = sortAttr;
    this.telemetryGeneratorService.generateInteractTelemetry(
      InteractType.TOUCH,
      InteractSubtype.SORT_OPTION_SELECTED,
      Environment.DOWNLOADS,
      PageId.DOWNLOADS,
      undefined,
      valuesMap,
      undefined,
      featureIdMap.downloadManager.DOWNLOADS_SORT
    );
    this.sortCriteria = [{
      sortOrder: SortOrder.DESC,
      sortAttribute: sortAttr
    }];
    this.getDownloadedContents();
  }

  ionViewWillLeave(): void {
    this.events.unsubscribe('update_header');
    this.headerObservable.unsubscribe();
    this.events.unsubscribe(EventTopics.HAMBURGER_MENU_CLICKED);
    this.events.unsubscribe(EventTopics.LAST_ACCESS_ON);
  }

  private subscribeContentUpdateEvents() {
    this.events.subscribe('savedResources:update', async (res) => {
      if (res && res.update) {
        this.getDownloadedContents(false, true);
        await this.getAppStorageInfo();
      }
    });
  }

  private handleHeaderEvents($event) {
    switch ($event.name) {
      case 'download':
        this.redirectToActivedownloads();
        break;
      case 'settings':
        this.closeSelectAllPopup();
        this.redirectToSettings();
        break;
    }
  }
  
  private redirectToActivedownloads() {
    this.telemetryGeneratorService.generateInteractTelemetry(
      InteractType.TOUCH,
      InteractSubtype.ACTIVE_DOWNLOADS_CLICKED,
      Environment.DOWNLOADS,
      PageId.DOWNLOADS);
    this.router.navigate([RouterLinks.ACTIVE_DOWNLOADS]);
  }

  private redirectToSettings() {
    this.telemetryGeneratorService.generateInteractTelemetry(
      InteractType.TOUCH,
      InteractSubtype.SETTINGS_CLICKED,
      Environment.DOWNLOADS,
      PageId.DOWNLOADS);
    this.router.navigate([RouterLinks.STORAGE_SETTINGS]);
  }

  private async fetchStorageDestination() {
    this.storageDestination = await this.storageService.getStorageDestination().toPromise();
  }

  private async presentPopupForLessStorageSpace() {
    this._toast = await this.popoverCtrl.create({
      component: SbInsufficientStoragePopupComponent,
      componentProps: {
        sbPopoverHeading: this.commonUtilService.translateMessage('INSUFFICIENT_STORAGE'),
        sbPopoverMessage: this.storageDestination === StorageDestination.INTERNAL_STORAGE ?
          this.commonUtilService.translateMessage('MOVE_FILES_TO_OTHER_DESTINATION', this.commonUtilService.translateMessage('SD_CARD')) :
          this.commonUtilService.translateMessage('MOVE_FILES_TO_OTHER_DESTINATION', this.commonUtilService.translateMessage(
            'INTERNAL_MEMORY'
          )),
      },
      cssClass: 'sb-popover no-network',
    });
    await this._toast.present();
  }

  private checkAvailableSpace() {
    this.storageService.getStorageDestinationVolumeInfo().pipe(
      tap((volumeInfo) => {
        if (volumeInfo.info.availableSize < 209715200) {
          this.presentPopupForLessStorageSpace();
        }
      })
    )
      .subscribe();
  }

  async closeSelectAllPopup() {
    if (this.downloadsTab && this.downloadsTab.deleteAllConfirm) {
      await this.downloadsTab.deleteAllConfirm.dismiss();
      this.downloadsTab.unSelectAllContents();
    }
  }

  deleteProjects(contents) {

    contents.forEach(async (element) => {
      let project = await this.db.getById(element.contentId)
      project.downloaded = false
      await this.db.delete(project._id, project._rev)
      this.events.publish('savedResources:update', {
        update: true,
      });
      this.commonUtilService.showToast(this.commonUtilService.translateMessage('MSG_RESOURCE_DELETED'));


    });
  }
  async deleteObservations(content) {
    let downloadedObs = await this.storage.getLocalStorage(storageKeys.downloadedObservations);
    const contentIds = content.map(c => c.contentId)
    downloadedObs = downloadedObs.filter(obs => {
      const shouldDelete = contentIds.includes(obs.programId + obs.solutionId)
      if (shouldDelete) {
        obs.downloadedSubmission.forEach(async submission => {
          await this.storage.deleteOneStorage(this.utils.getAssessmentLocalStorageKey(submission));
        });
      } 
      return !shouldDelete
    })
    await this.storage.setLocalStorage(storageKeys.downloadedObservations,downloadedObs);
    this.events.publish("savedResources:update", {update: true});
      this.commonUtilService.showToast(
        this.commonUtilService.translateMessage("MSG_RESOURCE_DELETED")
      );
  }
}
<ion-content hide-header-footer overflow-scroll="true" scrollEvents="true">
  <div class="sb-view-all-container">
    <app-downloads-header [storageInfo]="storageInfo" [appName]="appName"></app-downloads-header>

    <app-no-downloads *ngIf="!downloadedContents.length"></app-no-downloads>

    <app-downloads-tab #downloadsTab *ngIf="downloadedContents.length" [downloadedContents]="downloadedContents"
      (deleteContents)="deleteContents($event)" (sortCriteriaChanged)="onSortCriteriaChange($event)">
    </app-downloads-tab>
  </div>
</ion-content>

./download-manager.page.scss

@import "src/assets/styles/base/_variables.scss";
@import "src/assets/styles/_variables.scss";

    .sb-dw-manager{
        background-color: #{$light-blue-bg};
        border-bottom: 2px solid map-get($colors, white);
    }
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""