import { Injectable } from '@angular/core' ; import { HttpClient } from '@angular/common/http' ; import { LocationStrategy } from '@angular/common' ; import * as marked from 'marked' ; import hljs from 'node_modules/highlight.js/lib/core.js' ; import javascript from 'node_modules/highlight.js/lib/languages/javascript.js' ; import bash from 'node_modules/highlight.js/lib/languages/bash.js' ; import css from 'node_modules/highlight.js/lib/languages/css.js' ; import csharp from 'node_modules/highlight.js/lib/languages/csharp.js' ; import php from 'node_modules/highlight.js/lib/languages/php.js' ; import { BehaviorSubject , Observable , of } from 'rxjs' ; import { map , catchError } from 'rxjs/operators' ; import { ApiResponse , Board , Column , Attachment , Comment , Task } from '../shared/models' ; import { ApiService } from '../shared/services' ; interface MarkedReturn { html : string ; counts : any ; } @ Injectable ( ) export class BoardService extends ApiService { private checkCounts = { total : 0 , complete : 0 } ; private activeBoard = new BehaviorSubject < Board > ( null ) ; private showTaskId = new BehaviorSubject < number > ( null ) ; public activeBoardChanged = this . activeBoard . asObservable ( ) ; public showTaskIdChanged = this . showTaskId . asObservable ( ) ; constructor ( private http , strat ) { super ( strat ) ; this . initMarked ( ) ; hljs . registerLanguage ( 'javascript' , javascript ) ; hljs . registerLanguage ( 'bash' , bash ) ; hljs . registerLanguage ( 'css' , css ) ; hljs . registerLanguage ( 'csharp' , csharp ) ; hljs . registerLanguage ( 'php' , php ) ; } showTask ( id ) { this . showTaskId . next ( id ) ; } async convertMarkdown ( markdown , callback = this . defaultCallback , doCount = false ) { this . checkCounts . total = 0 ; this . checkCounts . complete = 0 ; const retVal = { html : '' , counts : { } } ; retVal . html = callback ( false , marked ( markdown ) ) ; if ( doCount ) { retVal . counts = Object . assign ( { } , this . checkCounts ) ; } return retVal ; } updateActiveBoard ( board ) { if ( ! board ) { return ; } this . convertBoardData ( board ) . then ( newBoard => { this . activeBoard . next ( newBoard ) ; } ) ; } getBoards ( ) { return this . http . get ( this . apiBase + 'boards' ) . pipe ( map ( ( response ) => response ) , catchError ( ( err ) => of ( err . error as ApiResponse ) ) ) ; } toggleCollapsed ( userId , columnId ) { return this . http . post ( this . apiBase + 'users/' + userId + '/cols' , { id : columnId } ) . pipe ( map ( ( response ) => response ) , catchError ( ( err ) => of ( err . error as ApiResponse ) ) ) ; } updateBoard ( board ) { return this . http . post ( this . apiBase + 'boards/' + board . id , board ) . pipe ( map ( ( response ) => response ) , catchError ( ( err ) => of ( err . error as ApiResponse ) ) ) ; } updateColumn ( column ) { return this . http . post ( this . apiBase + 'columns/' + column . id , column ) . pipe ( map ( ( response ) => response ) , catchError ( ( err ) => of ( err . error as ApiResponse ) ) ) ; } addTask ( task ) { return this . http . post ( this . apiBase + 'tasks' , task ) . pipe ( map ( ( response ) => response ) , catchError ( ( err ) => of ( err . error as ApiResponse ) ) ) ; } updateTask ( task ) { return this . http . post ( this . apiBase + 'tasks/' + task . id , task ) . pipe ( map ( ( response ) => response ) , catchError ( ( err ) => of ( err . error as ApiResponse ) ) ) ; } removeTask ( taskId ) { return this . http . delete ( this . apiBase + 'tasks/' + taskId ) . pipe ( map ( ( response ) => response ) , catchError ( ( err ) => of ( err . error as ApiResponse ) ) ) ; } getTaskActivity ( taskId ) { return this . http . get ( this . apiBase + 'activity/task/' + taskId ) . pipe ( map ( ( response ) => response ) , catchError ( ( err ) => of ( err . error as ApiResponse ) ) ) ; } addComment ( comment ) { return this . http . post ( this . apiBase + 'comments' , comment ) . pipe ( map ( ( response ) => response ) , catchError ( ( err ) => of ( err . error as ApiResponse ) ) ) ; } updateComment ( comment ) { return this . http . post ( this . apiBase + 'comments/' + comment . id , comment ) . pipe ( map ( ( response ) => response ) , catchError ( ( err ) => of ( err . error as ApiResponse ) ) ) ; } removeComment ( commentId ) { return this . http . delete ( this . apiBase + 'comments/' + commentId ) . pipe ( map ( ( response ) => response ) , catchError ( ( err ) => of ( err . error as ApiResponse ) ) ) ; } addAttachment ( attachment ) { return this . http . post ( this . apiBase + 'attachments' , attachment ) . pipe ( map ( ( response ) => response ) , catchError ( ( err ) => of ( err . error as ApiResponse ) ) ) ; } uploadAttachment ( data , hash ) { return this . http . post ( this . apiBase + 'upload/' + hash , data ) . pipe ( map ( ( response ) => response ) , catchError ( ( err ) => of ( err . error as ApiResponse ) ) ) ; } removeAttachment ( id ) { return this . http . delete ( this . apiBase + 'attachments/' + id ) . pipe ( map ( ( response ) => response ) , catchError ( ( err ) => of ( err . error as ApiResponse ) ) ) ; } private async convertBoardData ( boardData ) { if ( boardData instanceof Board ) { return boardData ; } return new Board ( + boardData . id , boardData . name , boardData . is_active === '1' , boardData . ownColumn , boardData . ownCategory , boardData . ownAutoAction , boardData . ownIssuetracker , boardData . sharedUser ) ; } private defaultCallback = ( err , text ) => { if ( err ) { return '' ; } return text ; } ; private initMarked ( ) { const renderer = new marked . Renderer ( ) ; renderer . checkbox = isChecked => { const text = '<i class="icon icon-check' + ( isChecked ? '' : '-empty' ) + '"></i>' ; this . checkCounts . total += 1 ; if ( isChecked ) { this . checkCounts . complete += 1 ; } return text ; } ; renderer . link = ( href , title , text ) => { let out = '<a href="' + href + '"' ; if ( title ) { out += ' title="' + title + '"' ; } out += ' target="tb_external" rel="noreferrer">' + text + '</a>' ; return out ; } ; marked . setOptions ( { renderer , smartypants : true , highlight : code => { return hljs . highlightAuto ( code ) . value ; } } ) ; } }