import { Injectable } from '@angular/core' ; import { HttpClient } from '@angular/common/http' ; import { Observable , of , combineLatest } from 'rxjs' ; import { map , catchError , tap , filter } from 'rxjs/operators' ; import { CONFIG } from '../../environments/environment' ; import { Question , QuestionStatus , SearchResults , SearchCriteria , BulkUploadFileInfo , BulkUpload , QueryParams , QueryParam } from '../../shared/model' ; import { Store } from '@ngrx/store' ; import { CoreState } from '../store' ; import { QuestionActions } from '../store/actions' ; import { DbService } from './../db-service' ; @ Injectable ( ) export class QuestionService { constructor ( private store , private questionActions , private http , private dbService ) { } getQuestionOfTheDay ( isNextQuestion ) { let url = `${ CONFIG . functionsUrl }/question/day` ; url = ( isNextQuestion ) ? `${ url }/next` : `${ url }/current` ; return this . http . get < Question > ( url ) ; } getQuestions ( startRow , pageSize , criteria ) { const url = `${ CONFIG . functionsUrl }/question/` ; return this . http . post < SearchResults > ( url + startRow + '/' + pageSize , criteria ) ; } getUserQuestions ( userId , published ) { const collection = ( published ) ? 'questions' : 'unpublished_questions' ; const queryParams = { condition : [ { name : 'created_uid' , comparator : '==' , value : userId } ] , orderBy : [ { name : 'createdOn' , value : 'desc' } ] } ; return this . dbService . valueChanges ( collection , '' , queryParams ) . pipe ( map ( qs => qs . map ( q => Question . getViewModelFromDb ( q ) ) ) , catchError ( error => { console . log ( error ) ; return of ( null ) ; } ) ) ; } getQuestionsForBulkUpload ( bulkUploadFileInfo , published ) { const collection = ( published ) ? 'questions' : 'unpublished_questions' ; const queryParams = { condition : [ { name : 'created_uid' , comparator : '==' , value : bulkUploadFileInfo . created_uid } , { name : 'bulkUploadId' , comparator : '==' , value : bulkUploadFileInfo . id } ] } ; return this . dbService . valueChanges ( collection , '' , queryParams ) . pipe ( map ( qs => qs . map ( q => Question . getViewModelFromDb ( q ) ) ) , catchError ( error => { console . log ( error ) ; return of ( null ) ; } ) ) ; } getUnpublishedQuestions ( flag , filterStatus ? ) { const question_source = ( ! flag ) ? 'question' : 'bulk-question' ; const queryParams = new QueryParams ( ) ; const queryObservables = [ ] ; if ( filterStatus && filterStatus . length > 0 ) { for ( const status of filterStatus ) { queryParams . condition = [ ] ; let queryParam = new QueryParam ( 'source' , '==' , question_source ) ; queryParams . condition . push ( queryParam ) ; queryParam = new QueryParam ( 'status' , '==' , status ) ; queryParams . condition . push ( queryParam ) ; queryObservables . push ( this . dbService . valueChanges ( 'unpublished_questions' , '' , { ... queryParams } ) ) ; } } else { queryParams . condition = [ ] ; queryObservables . push ( this . dbService . valueChanges ( 'unpublished_questions' , '' , queryParams ) ) ; } return combineLatest ( queryObservables ) . pipe ( map ( questions => { return [ ] . concat . apply ( [ ] , questions ) ; } ) ) . pipe ( catchError ( error => { console . log ( error ) ; return of ( null ) ; } ) ) ; } saveQuestion ( question ) { const dbQuestion = Object . assign ( { } , question ) ; if ( ! question . id || question . id === '' ) { dbQuestion [ 'source' ] = 'question' ; dbQuestion [ 'id' ] = this . dbService . createId ( ) ; this . dbService . createDoc ( 'unpublished_questions' , dbQuestion ) . then ( ref => { if ( question . is_draft ) { this . store . dispatch ( this . questionActions . addQuestionDraftSuccess ( dbQuestion [ 'id' ] ) ) ; } else { this . store . dispatch ( this . questionActions . addQuestionSuccess ( ) ) ; } } ) ; } else { this . dbService . setDoc ( 'unpublished_questions' , dbQuestion . id , dbQuestion ) . then ( ref => { if ( dbQuestion . is_draft ) { this . store . dispatch ( this . questionActions . updateQuestionDraftSuccess ( ) ) ; } else { this . store . dispatch ( this . questionActions . addQuestionSuccess ( ) ) ; } } ) ; } return of ( ) ; } saveBulkQuestions ( bulkUpload ) { const dbQuestions = [ ] ; const bulkUploadFileInfo = bulkUpload . bulkUploadFileInfo ; const questions = bulkUpload . questions ; const bulkUploadId = this . dbService . createId ( ) ; this . dbService . upload ( `bulk_upload/${ bulkUploadFileInfo . created_uid }/${ bulkUploadId }-${ bulkUpload . file . name }` , bulkUpload . file ) . then ( ref => { for ( const question of questions ) { if ( question !== null ) { question . bulkUploadId = bulkUploadId ; const dbQuestion = Object . assign ( { } , question ) ; dbQuestion . id = this . dbService . createId ( ) ; dbQuestion . answers = dbQuestion . answers . map ( ( obj ) => { return Object . assign ( { } , obj ) ; } ) ; dbQuestions . push ( dbQuestion ) ; } } this . addBulkUpload ( bulkUploadFileInfo , dbQuestions , bulkUploadId ) ; } ) ; } addBulkUpload ( bulkUploadFileInfo , questions , id ) { const dbFile = Object . assign ( { } , bulkUploadFileInfo ) ; dbFile . id = id ; dbFile . rejected = 0 ; dbFile . approved = 0 ; dbFile . status = 'Under Review' ; this . dbService . setDoc ( 'bulk_uploads' , dbFile [ 'id' ] , dbFile ) . then ( ref => { this . storeQuestion ( 0 , questions ) ; } ) ; } storeQuestion ( index , questions ) { const question = questions [ index ] ; question [ 'source' ] = 'bulk-question' ; this . dbService . setDoc ( 'unpublished_questions' , question . id , question ) . then ( ref => { if ( index === questions . length - 1 ) { this . store . dispatch ( this . questionActions . addQuestionSuccess ( ) ) ; } else { index ++ ; this . storeQuestion ( index , questions ) ; } } ) ; } approveQuestion ( question ) { const dbQuestion = Object . assign ( { } , question ) ; const questionId = dbQuestion . id ; dbQuestion . status = QuestionStatus . APPROVED ; const firestoreInstance = this . dbService . getFireStore ( ) ; firestoreInstance . firestore . runTransaction ( transaction => { return transaction . get ( firestoreInstance . doc ( '/unpublished_questions/' + questionId ) . ref ) . then ( doc => transaction . set ( firestoreInstance . doc ( '/questions/' + questionId ) . ref , dbQuestion ) . delete ( doc . ref ) ) ; } ) ; } saveQuestionImage ( image , fileName ) { const url = `${ CONFIG . functionsUrl }/question/uploadQuestionImage` ; return this . http . post < any > ( url , { image : image } ) ; } getQuestionDownloadUrl ( image ) { return this . dbService . getFireStorageReference ( image ) . getDownloadURL ( ) ; } getUserLatestQuestion ( userId ) { const collection = 'questions' ; const queryParams = { condition : [ { name : 'created_uid' , comparator : '==' , value : userId } ] , orderBy : [ { name : 'createdOn' , value : 'desc' } ] , limit : 1 } ; return this . dbService . valueChanges ( collection , '' , queryParams ) . pipe ( map ( qs => { if ( qs [ 0 ] ) { return Question . getViewModelFromDb ( qs [ 0 ] ) ; } return null ; } ) , catchError ( error => { console . log ( error ) ; return of ( null ) ; } ) ) ; } deleteQuestionImage ( imageName ) { return this . http . delete ( `${ CONFIG . functionsUrl }/question/deleteQuestionImage/${ imageName }` ) ; } }