import { Injectable } from '@angular/core' ; import { AngularFirestore } from '@angular/fire/firestore' ; import { AngularFireFunctions } from '@angular/fire/functions' ; import * as firebase from 'firebase' ; import { forkJoin , Observable } from 'rxjs' ; import { filter , map , mergeMap , switchMap , take , tap } from 'rxjs/operators' ; import { MatDialog , MatDialogConfig } from '@angular/material' ; import { v4 as uuid } from 'uuid' ; import { DialogConfirmationComponent } from '@shared/dialog/confirmation/dialog-confirmation.component' ; import { IProject , ProjectModel , RepositoryModel } from '@shared/models/index.model' ; import { ActivityService } from './activity.service' ; import { AuthenticationService } from './authentication.service' ; import { RepositoryService } from './repository.service' ; @ Injectable ( { providedIn : 'root' , } ) export class ProjectService { param afs param authService param activityService param dialog param repositoryService constructor ( private afs , private authService , private activityService , private dialog , private fns , private repositoryService ) { } param data public create ( data ) { const project = new ProjectModel ( { uid : uuid ( ) , ... data , access : { admin : [ this . authService . profile . uid ] } , createdOn : firebase . firestore . Timestamp . fromDate ( new Date ( ) ) , updatedOn : firebase . firestore . Timestamp . fromDate ( new Date ( ) ) , } ) ; return this . activityService . start ( ) . pipe ( tap ( ( ) => this . repositoryService . refresh ( ) ) , switchMap ( ( ) => this . afs . collection < IProject > ( 'projects' ) . doc ( project . uid ) . set ( project . toData ( ) ) ) , map ( ( ) => project ) , take ( 1 ) ) ; } param projectUid public showDeleteDialog ( projectUid ) { let dialogConfig = new MatDialogConfig ( ) ; dialogConfig = { width : '500px' , data : { title : 'Delete Project' , content : 'Are you sure you want to delete?' , } , } ; return this . dialog . open ( DialogConfirmationComponent , dialogConfig ) . afterClosed ( ) . pipe ( filter ( ( result ) => ! ! result ) , switchMap ( ( ) => this . delete ( projectUid ) ) ) ; } param uid public delete ( uid ) { return this . activityService . start ( ) . pipe ( switchMap ( ( ) => this . afs . collection < IProject > ( 'projects' ) . doc < IProject > ( uid ) . delete ( ) ) , take ( 1 ) ) ; } /**
     * Find top 10 public projects list
     */ public findPublicProjects ( ) { return this . activityService . start ( ) . pipe ( switchMap ( ( ) => this . afs . collection < IProject > ( 'projects' , ( ref ) => ref . where ( 'type' , '==' , 'public' ) . orderBy ( 'updatedOn' , 'desc' ) . limit ( 10 ) ) . valueChanges ( ) ) , map ( ( projects ) => projects . map ( ( project ) => new ProjectModel ( project ) ) ) ) ; } /**
     * Find all private projects list
     */ public findMyProjects ( ) { return this . activityService . start ( ) . pipe ( switchMap ( ( ) => this . afs . collection < IProject > ( 'projects' , ( ref ) => ref . where ( 'access.admin' , 'array-contains' , this . authService . profile . uid ) . orderBy ( 'updatedOn' , 'desc' ) ) . valueChanges ( ) ) , map ( ( projects ) => projects . map ( ( project ) => new ProjectModel ( project ) ) ) ) ; } param uid public findOneById ( uid ) { return this . activityService . start ( ) . pipe ( switchMap ( ( ) => this . afs . collection < IProject > ( 'projects' ) . doc < IProject > ( uid ) . valueChanges ( ) ) , map ( ( project ) => new ProjectModel ( project ) ) ) ; } param data public save ( data ) { return this . findOneById ( data . uid ) . pipe ( take ( 1 ) , map ( ( project ) => ( { ... project . toData ( ) , ... data , updatedOn : firebase . firestore . Timestamp . fromDate ( new Date ( ) ) , } ) ) , switchMap ( ( project ) => this . afs . collection < IProject > ( 'projects' ) . doc < IProject > ( project . uid ) . set ( project , { merge : true } ) ) ) ; } TODO param project param repositories public saveRepositories ( project , repositories ) { if ( ! repositories . length ) { return this . activityService . start ( ) . pipe ( switchMap ( ( ) => this . afs . collection < IProject > ( 'projects' ) . doc < IProject > ( project . uid ) . set ( { repositories : [ ] , updatedOn : firebase . firestore . Timestamp . fromDate ( new Date ( ) ) , } , { merge : true } ) ) , take ( 1 ) ) ; } return this . activityService . start ( ) . pipe ( mergeMap ( ( ) => forkJoin ( ... repositories . map ( ( repository ) => this . repositoryService . loadRepository ( repository ) ) ) ) , switchMap ( ( ) => this . afs . collection < IProject > ( 'projects' ) . doc < IProject > ( project . uid ) . set ( { repositories : repositories . map ( ( repo ) => repo . uid ) , updatedOn : firebase . firestore . Timestamp . fromDate ( new Date ( ) ) , } , { merge : true } ) ) , take ( 1 ) ) ; } /**
     * Find top 4 popular projects by views
     */ public getPopularProjects ( ) { return this . activityService . start ( ) . pipe ( switchMap ( ( ) => this . afs . collection < IProject > ( 'projects' , ( ref ) => ref . where ( 'type' , '==' , 'public' ) . orderBy ( 'views' , 'desc' ) . limit ( 4 ) ) . valueChanges ( ) ) , map ( ( projects ) => projects . map ( ( project ) => new ProjectModel ( project ) ) ) ) ; } param projectUid param counter public updateFollowers ( projectUid , increase ) { const callable = this . fns . httpsCallable ( 'updateProjectFollowers' ) ; return callable ( { projectUid , increase } ) ; } }