File

src/app/modules/sourcing/components/transcripts/transcripts.component.ts

Metadata

selector app-transcripts
styleUrls transcripts.component.scss
templateUrl transcripts.component.html

Inputs

contentMetaData

Outputs

closePopup $event type: EventEmitter

Constructor

constructor(fb: UntypedFormBuilder, cd: ChangeDetectorRef, sourcingService: SourcingService, transcriptService: TranscriptService, helperService: HelperService, searchService: any, actionService: ActionService, activeRoute: ActivatedRoute, toasterService: any, configService: any, resourceService: any)

Methods

getLanguage
getLanguage(index: any)
Returns: void
getFileControl
getFileControl(index: any)
Returns: void
getFileNameControl
getFileNameControl(index: any)
Returns: void
getLanguageControl
getLanguageControl(index: any)
Returns: void
setFile
setFile(index: any, value: any)
Returns: void
getFile
getFile(index: any)
Returns: void
addItem
addItem(data: any)
Returns: void
createItem
createItem(data: any)
Returns: any
attachFile
attachFile(event: any, index: any)
Returns: void
fileValidation
fileValidation(file: any)
Returns: void
detectMimeType
detectMimeType(extn: any)
Returns: void
replaceFile
replaceFile(index: any)
Returns: void
reset
reset(index: any)
Returns: void
download
download(identifier: any)
Returns: void
setFormValues
setFormValues(transcriptsMeta: any)
Returns: void
languageChange
languageChange(language: any, index: any)
Returns: void
submit
submit()
Returns: void
enableDisableAddItemButton
enableDisableAddItemButton()
Returns: void
createOrUpdateAsset
createOrUpdateAsset(item: any)
Returns: Observable<any>
uploadToBlob
uploadToBlob(response: any, item: any)
Returns: Observable<any>
generatePreSignedUrl
generatePreSignedUrl(asset: any, item: any)
Returns: Observable<any>
updateAssetWithURL
updateAssetWithURL(item: any)
Returns: Observable<any>
updateContent
updateContent(transcriptMeta: any)
Returns: Observable<any>
getAssetList
getAssetList()
Returns: void
contentRead
contentRead(identifier: any)
Returns: Observable<any>
showLoader
showLoader()
Returns: void
hideLoader
hideLoader()
Returns: void
close
close()
Returns: void

Properties

Public acceptedFileFormats
acceptedFileFormats: any
Public acceptFileExtensions
acceptFileExtensions: any
activeRoute
activeRoute: ActivatedRoute
Public assetList
assetList: any[]
configService
configService: any
createAssetReq
createAssetReq: { 'asset': { 'name': string; 'mimeType': any; 'primaryCategory': string; 'mediaType': string; 'la...
Public disableAddItemBtn
disableAddItemBtn: boolean
Default value: true
Public disableDoneBtn
disableDoneBtn: boolean
Default value: true
helperService
helperService: HelperService
items
items: any
Public langControl
langControl: string
Default value: language
Public languageOptions
languageOptions: any
languages
languages: any
Public loader
loader: boolean
Default value: true
Public mimeType
mimeType: any
resourceService
resourceService: any
Public supportedLanguages
supportedLanguages: any
Public transcriptForm
transcriptForm: any
transcripts
transcripts: any
Public uploadInProgress
uploadInProgress: boolean
Default value: false
Public userRole
userRole: string
Default value: contributor
import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { UntypedFormArray, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { forkJoin, Observable, of, throwError } from 'rxjs';
import { catchError, map, switchMap } from 'rxjs/operators';
import _, { forEach } from 'lodash';
import { TranscriptMetadata } from './transcript';
import { SearchService } from '@sunbird/core';
import { ActivatedRoute } from '@angular/router';
import { ToasterService, ConfigService, ResourceService } from '@sunbird/shared';
import { ActionService } from '../../../core/services/action/action.service';
import { HelperService } from '../../../sourcing/services/helper.service';
import { TranscriptService } from '../../../core/services/transcript/transcript.service';
import { SourcingService } from '../../../sourcing/services/sourcing/sourcing.service';

@Component({
  selector: 'app-transcripts',
  templateUrl: './transcripts.component.html',
  styleUrls: ['./transcripts.component.scss']
})

export class TranscriptsComponent implements OnInit {
  @Input() contentMetaData;
  @Output() closePopup = new EventEmitter<any>();
  public transcriptForm: UntypedFormGroup;
  public langControl = 'language';
  public languageOptions;
  public supportedLanguages;
  public assetList = [];
  public loader = true;
  public disableDoneBtn = true;
  public disableAddItemBtn = true;
  public uploadInProgress = false;

  // @Todo -> contributor/ sourcing reviewer/ contribution reviewer/ sourcing admin/ contribution org admin
  public userRole = 'contributor';
  public acceptedFileFormats;
  public mimeType;
  public acceptFileExtensions;

  constructor(private fb: UntypedFormBuilder,
    private cd: ChangeDetectorRef,
    private sourcingService: SourcingService,
    private transcriptService: TranscriptService,
    public helperService: HelperService,
    private searchService: SearchService,
    private actionService: ActionService,
    public activeRoute: ActivatedRoute,
    private toasterService: ToasterService,
    public configService: ConfigService,
    public resourceService: ResourceService
  ) {
    const languages = (<HTMLInputElement>document.getElementById('sunbirdTranscriptSupportedLanguages')) ?
      // tslint:disable-next-line:max-line-length
      (<HTMLInputElement>document.getElementById('sunbirdTranscriptSupportedLanguages')).value : '[{"language":"English","languageCode":"en"},{"language":"Hindi","languageCode":"hi"},{"language":"Assamese","languageCode":"as"},{"language":"Bengali","languageCode":"bn"},{"language":"Gujarati","languageCode":"gu"},{"language":"Kannada","languageCode":"ka"},{"language":"Marathi","languageCode":"mr"},{"language":"Odia","languageCode":"or"},{"language":"Tamil","languageCode":"ta"},{"language":"Telugu","languageCode":"te"}]';

    this.supportedLanguages = JSON.parse(languages);
    this.languageOptions = _.sortBy(_.map(this.supportedLanguages , 'language'));


    // tslint:disable-next-line:max-line-length
    const sunbirdTranscriptFileFormat = (<HTMLInputElement>document.getElementById('sunbirdTranscriptFileFormat')) ? (<HTMLInputElement>document.getElementById('sunbirdTranscriptFileFormat')).value : 'srt';
    this.acceptedFileFormats = sunbirdTranscriptFileFormat.split(',').map((item) => {
      return item.trim();
    });

    this.acceptFileExtensions = this.acceptedFileFormats.map(item => {
      return '.' + item;
    }).toString();
  }

  ngOnInit(): void {
    this.transcriptForm = this.fb.group({
      items: this.fb.array([])
    });

    this.contentRead(this.contentMetaData.identifier).subscribe(content => {
      this.hideLoader();
      this.contentMetaData.transcripts = _.get(content, 'transcripts') || [];
      if (this.contentMetaData.transcripts.length) {
        this.setFormValues(this.contentMetaData.transcripts);
      }
      this.addItem();
    });

    this.getAssetList();
  }

  get items(): UntypedFormArray {
    return this.transcriptForm.get('items') as UntypedFormArray;
  }

  getLanguage(index) {
    return this.items.controls[index].get('language').value;
  }

  getFileControl(index) {
    return this.items.controls[index].get('transcriptFile');
  }

  getFileNameControl(index) {
    return this.items.controls[index].get('fileName');
  }

  getLanguageControl(index) {
    return this.items.controls[index].get('language');
  }

  setFile(index, value) {
    return this.items.controls[index].get('transcriptFile')['file'] = value;
  }

  getFile(index) {
    return this.items.controls[index].get('transcriptFile')['file'];
  }

  addItem(data?): void {
    this.items.push(this.createItem(data));
    this.disableAddItemBtn = true;
  }

  createItem(data?): UntypedFormGroup {
    return this.fb.group({
      identifier: [data ? data.identifier : null],
      language: [data ? data.language : null],
      languageCode: [data ? data.languageCode : null],
      transcriptFile: '',
      fileName: [data ? data.artifactUrl.split('/').pop() : null]
    });
  }

  get transcripts() {
    return this.transcriptForm.get('transcripts') as UntypedFormArray;
  }

  get languages() {
    return this.transcriptForm.get('languages') as UntypedFormArray;
  }

  attachFile(event, index) {
    if (!this.getLanguageControl(index).value) {
      event.target.value = '';
      this.toasterService.warning('Please select language first');
      return false;
    }

    this.disableDoneBtn = false;
    const file = event.target.files[0];
    if (!this.fileValidation(file)) {
      event.target.value = '';
      return false;
    }

    if (event.target.files && event.target.files.length) {
      const [file] = event.target.files;
      this.setFile(index, file);
      this.getFileNameControl(index).patchValue(file.name);
    }

    this.enableDisableAddItemButton();
  }

  fileValidation(file) {
    const extn = file.name.split('.').pop();
    if (!this.acceptedFileFormats.includes(extn)) {
      this.toasterService.error(`Invalid file type (supported type: ${this.acceptFileExtensions})`);
      return false;
    }
    this.mimeType = this.detectMimeType(extn);
    return true;
  }

  detectMimeType(extn) {
    const appFilesConfig = this.configService.contentCategoryConfig.sourcingConfig.files;
    let thisFileMimetype = '';

    _.forEach(appFilesConfig, (item, key) => {
      if (item === extn) {
        thisFileMimetype = key;
      }
    });

    return thisFileMimetype;
  }


  replaceFile(index) {
    document.getElementById('attachFileInput' + index).click();
  }

  reset(index) {
    this.disableDoneBtn = false;
    this.getFileControl(index).reset();
    this.getFileNameControl(index).reset();
    this.getLanguageControl(index).reset();
    this.enableDisableAddItemButton();
  }

  download(identifier) {
    const item = _.find(this.contentMetaData.transcripts, e => e.identifier === identifier);
    if (_.get(item, 'artifactUrl')) {
      window.open(_.get(item, 'artifactUrl'), '_blank');
    } else {
      this.toasterService.error('Something went wrong');
    }
  }

  setFormValues(transcriptsMeta) {
    transcriptsMeta.forEach((element) => {
      this.addItem(element);
    });
  }

  languageChange(language, index) {
    if (language) {
      forEach(this.items.controls, (e, i) => {
        if (e.get('language').value && i !== index) {
          if (e.get('language').value === language) {
            this.items.controls[index].get('language').reset();
            this.toasterService.warning(language + ' is already selected');
            return true;
          }
        }
      });
    }

    this.disableDoneBtn = false;
    this.enableDisableAddItemButton();
  }

  submit() {
    if (!this.items['controls'].length) {
      this.closePopup.emit();
      return true;
    } else {
      for (let item of this.items['controls']) {
        if ((item.get('transcriptFile')['file'] || item.get('fileName').value)
          && !item.get('language').value) {
          this.toasterService.warning('Please select language for transcript file');
          return false;
        }
      }
    }

    this.uploadInProgress = true;
    this.disableDoneBtn = true;
    const transcriptMeta = [];
    const assetRequest = [];

    for (let item of this.items['controls']) {
      let transcriptMetadata: TranscriptMetadata = {};
      let orgAsset;

      if (item.get('identifier').value) {
        orgAsset = _.find(this.assetList, e => e.identifier === item.get('identifier').value);
      }

      if (item.get('fileName').value && item.get('language').value) {
        let forkReq;
        // if selected then upload it
        if (item.get('transcriptFile')['file']) {
          forkReq = this.createOrUpdateAsset(item).pipe(
            switchMap(asset => {
              transcriptMetadata.language = item.get('language').value;
              transcriptMetadata.identifier = _.get(asset, 'result.identifier');
              const seletedLanguage = _.find(this.supportedLanguages, (lan) => {
                return lan.language.toLowerCase() === transcriptMetadata.language.toLowerCase();
              });
              if (seletedLanguage.languageCode) {
                transcriptMetadata.languageCode = seletedLanguage.languageCode;
              }
              return this.generatePreSignedUrl(asset, item);
            }),
            switchMap((rsp) => {
              item['preSignedResponse'] = rsp;
              const signedURL = item['preSignedResponse'].result.pre_signed_url;
              transcriptMetadata.artifactUrl = signedURL.split('?')[0];
              transcriptMeta.push(transcriptMetadata);
              return this.uploadToBlob(rsp, item);
            }),
            switchMap(response => {
              return this.updateAssetWithURL(item);
            })
          );
        } else {
          // Update only asset language only
          forkReq = this.createOrUpdateAsset(item).pipe(switchMap((rs) => {
            transcriptMetadata.identifier = _.get(orgAsset, 'identifier');
            transcriptMetadata.language = item.get('language').value;
            const seletedLanguage = _.find(this.supportedLanguages, (lan) => {
              return lan.language.toLowerCase() === transcriptMetadata.language.toLowerCase();
            });
            if (seletedLanguage.languageCode) {
              transcriptMetadata.languageCode = seletedLanguage.languageCode;
            }
            transcriptMetadata.artifactUrl = _.get(orgAsset, 'artifactUrl');
            transcriptMeta.push(transcriptMetadata);
            return of(transcriptMetadata);
          }));
        }
        assetRequest.push(forkReq);
      }
    }

    if (assetRequest && assetRequest.length) {
      forkJoin(assetRequest).subscribe(response => {
        this.updateContent(transcriptMeta).subscribe(response => {
          this.toasterService.success(this.resourceService?.messages?.smsg?.transcriptUpdate);
          this.closePopup.emit();
        }, error => {
          console.log('Something went wrong', error);
          this.closePopup.emit();
        });
      }, error => {
        console.log(error);
        this.closePopup.emit();
      });
    } else if (!_.isEmpty(this.contentMetaData.transcripts)) {
      this.updateContent(transcriptMeta).subscribe(response => {
        this.toasterService.success(this.resourceService?.messages?.smsg?.transcriptUpdate);
        this.closePopup.emit();
      }, error => {
        console.log('Something went wrong', error);
        this.closePopup.emit();
      });
    } else {
      this.closePopup.emit();
    }
  }

  enableDisableAddItemButton() {
    const itemCnt = this.items['controls'].length - 1;
    const lastItem = this.items['controls'][itemCnt];

    if (lastItem.get('fileName').value && lastItem.get('language').value) {
      this.disableAddItemBtn = false;
    } else {
      this.disableAddItemBtn = true;
    }
  }

  createOrUpdateAsset(item): Observable<any> {
    const identifier = item.get('identifier').value;
    const req = _.clone(this.createAssetReq);
    req.asset['name'] = item.get('fileName').value;
    req.asset['language'].push(item.get('language').value);

    if (identifier) {
      const asset = _.find(this.assetList, em => em.identifier === identifier);
      req.asset['versionKey'] = _.get(asset, 'versionKey');
      return this.sourcingService.updateAsset(req, identifier);
    } else {
      return this.sourcingService.createAsset(req);
    }
  }

  uploadToBlob(response, item): Observable<any> {
    try {
      const signedURL = response.result.pre_signed_url;
      const headers = this.helperService.addCloudStorageProviderHeaders();
      const config = {
        processData: false,
        contentType: 'Asset',
        headers: headers
      };

      return this.transcriptService.http.put(signedURL, item.get('transcriptFile')['file'], config);
    } catch (err) {
      console.log(err);
    }
  }

  generatePreSignedUrl(asset, item): Observable<any> {
    try {
      const req = {
        'content': {
          'fileName': item.get('fileName').value
        }
      };
      return this.sourcingService.generatePreSignedUrl(req, _.get(asset, 'result.identifier'));
    } catch (err) {
      throw err;
    }
  }

  updateAssetWithURL(item): Observable<any> {
    const signedURL = item['preSignedResponse'].result.pre_signed_url;
    const fileURL = signedURL.split('?')[0];
    const formData = new FormData();
    formData.append('fileUrl', fileURL);
    formData.append('mimeType', this.mimeType);

    const request = {
      data: formData
    };

    return this.sourcingService.uploadAsset(request, item['preSignedResponse'].result.identifier);
  }

  updateContent(transcriptMeta): Observable<any> {
    const req = {
      content: {
        versionKey: this.contentMetaData.versionKey,
        transcripts: transcriptMeta
      }
    };

    return this.helperService.updateContent(req, this.contentMetaData.identifier);
  }

  get createAssetReq() {
    return {
      'asset': {
        'name': '',
        'mimeType': this.mimeType,
        'primaryCategory': 'Video transcript',
        'mediaType': 'text',
        'language': []
      }
    };
  }

  getAssetList(): void {
    const transcripts = _.get(this.contentMetaData, 'transcripts') || [];
    const identifier = _.map(transcripts, e => e.identifier);
    if (identifier && identifier.length) {
      const req = {
        'filters': {
          'primaryCategory': 'Video transcript',
          'status': [],
          'identifier': identifier
        },
        'fields': ['versionKey']
      };

      this.searchService.compositeSearch(req).subscribe(res => {
        this.hideLoader();
        if (_.get(res, 'responseCode') === 'OK') {
          this.assetList = _.get(res, 'result.content');
        }
      }, err => {
        console.log('Something went wrong', err);
      });
    } else {
      this.hideLoader();
    }
  }

  contentRead(identifier): Observable<any> {
    const option = {
      url: `${this.configService.urlConFig.URLS.DOCKCONTENT.GET}/${identifier}`
    };
    return this.actionService.get(option).pipe(map((data: any) => data.result.content), catchError(err => {
      const errInfo = {
        errorMsg: 'Unable to read the Content, Please Try Again',
        telemetryPageId: '',
        telemetryCdata: '',
        env: this.activeRoute.snapshot.data.telemetry.env,
        request: option
      };
      return throwError(this.sourcingService.apiErrorHandling(err, errInfo));
    }));
  }

  showLoader(): void {
    this.loader = true;
  }

  hideLoader(): void {
    this.loader = false;
  }

  close() {
    this.closePopup.emit();
  }
}

results matching ""

    No results matching ""