import { AfterViewInit , Component , ElementRef , Inject , OnInit , Optional , ViewChild , ViewContainerRef , } from '@angular/core' ; import { FormControl , FormGroup , Validators } from '@angular/forms' ; import { Store } from '@ngrx/store' ; import { finalize } from 'rxjs/operators' ; import { VcsAccount , VcsError , VcsFileChange } from '../../../../core/vcs' ; import { GitService , WorkspaceService } from '../../../shared' ; import { Dialog , DIALOG_DATA , DialogRef } from '../../../ui/dialog' ; import { MenuItem } from '../../../ui/menu' ; import { VCS_ACCOUNT_DATABASE , VcsAccountDatabase } from '../../vcs-account-database' ; import { GithubAccountsDialogComponent } from '../../vcs-remote' ; import { VCS_ITEM_LIST_MANAGER , VcsItemListManager , VcsItemListManagerFactory } from '../../vcs-view' ; import { CommittedAction } from '../../vcs.actions' ; import { VcsStateWithRoot } from '../../vcs.state' ; import { VcsCommitDialogData } from './vcs-commit-dialog-data' ; import { VcsCommitDialogResult } from './vcs-commit-dialog-result' ; @ Component ( { selector : 'gd-vcs-commit-dialog' , templateUrl : './vcs-commit-dialog.component.html' , styleUrls : [ './vcs-commit-dialog.component.scss' ] , providers : [ Dialog ] , } ) export class VcsCommitDialogComponent implements OnInit , AfterViewInit { @ ViewChild ( 'itemList' ) _itemList : ElementRef < HTMLElement > ; readonly commitFormGroup = new FormGroup ( { author : new FormControl ( null , [ Validators . required ] ) , summary : new FormControl ( '' , [ Validators . required , Validators . maxLength ( 72 ) ] ) , description : new FormControl ( '' ) , } ) ; authorMenuItems : MenuItem [ ] = [ ] ; private itemListManager : VcsItemListManager ; private accounts : VcsAccount [ ] = [ ] ; constructor ( @ Inject ( VCS_ITEM_LIST_MANAGER ) private itemListManagerFactory , private viewContainerRef , @ Optional ( ) @ Inject ( DIALOG_DATA ) public data , private dialog , private dialogRef , @ Inject ( VCS_ACCOUNT_DATABASE ) private accountDB , private workspace , private git , private store ) { } private _commitProcessing = false ; get commitProcessing ( ) : boolean { return this . _commitProcessing ; } get selectedItemsCount ( ) : number { if ( this . itemListManager ) { return this . itemListManager . _selectedItems . size ; } else { return 0 ; } } readonly authorMenuConvertFn = ( value ) : MenuItem => ( { id : value . email , label : `${ value . name } <${ value . email }>` , } ) ; ngOnInit ( ) { if ( ! ( this . data && this . data . fileChanges ) ) { throw new Error ( 'Please input file changes.' ) ; } this . loadAccounts ( ) ; } ngAfterViewInit ( ) { this . itemListManager = this . itemListManagerFactory ( this . _itemList . nativeElement , this . viewContainerRef ) ; Promise . resolve ( null ) . then ( ( ) => { this . itemListManager . initWithFileChanges ( this . data . fileChanges ) . then ( ( ) => this . itemListManager . selectAllItems ( ) ) ; } ) ; } selectAuthor ( item ) { const author = this . accounts . find ( account => account . email === item . id ) ; this . commitFormGroup . get ( 'author' ) . patchValue ( author ) ; } addAuthor ( ) { setTimeout ( ( ) => { this . dialog . open < GithubAccountsDialogComponent > ( GithubAccountsDialogComponent , { width : '480px' , disableBackdropClickClose : true , } ) . afterClosed ( ) . subscribe ( ( ) => this . loadAccounts ( ) ) ; } , 0 ) ; } commit ( ) { if ( this . commitFormGroup . invalid || this . _commitProcessing || this . selectedItemsCount === 0 ) { return ; } const { author , summary , description } = this . commitFormGroup . value ; this . _commitProcessing = true ; this . git . commit ( this . workspace . configs . rootDirPath , author as VcsAccount , { summary , description } , this . getFilesToAdd ( ) ) . pipe ( finalize ( ( ) => this . _commitProcessing = false ) ) . subscribe ( commitId => this . handleCommitSuccess ( commitId ) , error => this . handleCommitFail ( error ) ) ; } closeThisDialog ( result ? ) { this . dialogRef . close ( result ) ; } private async loadAccounts ( ) { const accounts = await this . accountDB . getAllAccounts ( ) ; this . accounts = accounts ; this . authorMenuItems = accounts . map ( account => ( { id : account . email , label : `${ account . name } <${ account . email }>` , } as MenuItem ) ) ; } private getFilesToAdd ( ) { const filesToAdd = [ ] ; const selectedItems = this . itemListManager . getSelectedItems ( ) ; selectedItems . forEach ( ( itemRef ) => { filesToAdd . push ( ... itemRef . _config . fileChanges ) ; } ) ; return filesToAdd ; } private handleCommitSuccess ( commitId ) { this . store . dispatch ( new CommittedAction ( { commitId } ) ) ; this . dialogRef . close ( { committed : true } ) ; } private handleCommitFail ( error ) { console . error ( error ) ; } }