11import * as React from "react" ;
22import { connect } from "react-redux" ;
33import { RouteComponentProps } from "react-router" ;
4- import { List , Row , Col , Table , Tag , Alert , Tooltip , Switch , Button , Icon , Card , Collapse } from "antd" ;
4+ import { List , Row , Col , Table , Tag , Alert , Tooltip , Switch , Button , Icon , Collapse } from "antd" ;
55import { IAppStore } from "reducers" ;
6- import { IAnalysisState , IIssue , IWarning , fetchAnalysis , buildLogTogglePanels , IBuildGroup } from "modules/analyzes" ;
6+ import { IAnalysisState , IIssue , IWarning , fetchAnalysis , buildLogTogglePanels , IBuildLog , IBuildGroup } from "modules/analyzes" ;
77import { processWarning } from "modules/utils/strings" ;
88import moment from "moment" ;
99import Helmet from "react-helmet" ;
@@ -19,6 +19,7 @@ moment.locale("en");
1919
2020const hideCodeToggleKey = "hideCode" ;
2121const showBuildLogToggleKey = "showBuildLog" ;
22+ const showPrevAnalyzesToggleKey = "showPrevAnalyzes" ;
2223
2324interface IStateProps {
2425curAnalysis ?:IAnalysisState ;
@@ -29,7 +30,7 @@ interface IStateProps {
2930}
3031
3132interface IDispatchProps {
32- fetchAnalysis ( owner :string , name :string , prNumber ?:number , analysisGuid ?:string ) :void ;
33+ fetchAnalysis ( owner :string , name :string , prNumber ?:number , commitSha ?: string , analysisGuid ?:string ) :void ;
3334toggle ( name :string , value ?:boolean ) :void ;
3435buildLogTogglePanels ( keys :string [ ] ) :void ;
3536}
@@ -44,7 +45,7 @@ class Report extends React.Component<IProps> {
4445private fetchAnalysis ( ) {
4546const p = this . props . match . params ;
4647const qs = queryString . parse ( this . props . location . search ) ;
47- this . props . fetchAnalysis ( p . owner , p . name , Number ( p . prNumber ) , qs . analysisGuid ) ;
48+ this . props . fetchAnalysis ( p . owner , p . name , Number ( p . prNumber ) , qs . commit_sha , qs . analysisGuid ) ;
4849}
4950
5051public componentWillMount ( ) {
@@ -486,85 +487,42 @@ class Report extends React.Component<IProps> {
486487) ;
487488}
488489
489- public render ( ) {
490- switch ( this . props . lastApiErrorCode ) {
491- case "NEED_AUTH_TO_ACCESS_PRIVATE_REPO" :
492- return this . renderNeedAuthError ( ) ;
493- case "NEED_PRIVATE_ACCESS_TOKEN_TO_ACCESS_PRIVATE_REPO" :
494- return this . renderNeedPrivateAccessTokenError ( ) ;
495- case "NO_ACCESS_TO_PRIVATE_REPO_OR_DOESNT_EXIST" :
496- this . renderNoAccessOrDoesntExistError ( ) ;
497- }
498-
499- if ( this . props . curAnalysis === null ) {
500- return getLoader ( ) ;
501- }
502-
503- const rj = this . props . curAnalysis . ResultJSON ;
504- const issues = ( rj && rj . GolangciLintRes && rj . GolangciLintRes . Issues ) ?rj . GolangciLintRes . Issues :[ ] ;
505-
506- const linterToIssues :any = { } ;
507- for ( const i of issues ) {
508- if ( ! linterToIssues [ i . FromLinter ] ) {
509- linterToIssues [ i . FromLinter ] = [ ] ;
510- }
511-
512- linterToIssues [ i . FromLinter ] . push ( i ) ;
513- }
514-
515- const ca = this . props . curAnalysis ;
516- console . info ( "rendering ca" , ca ) ;
517- const sourceLinkBase = `https://github.com/${ ca . GithubRepoName } /blob/${ ca . CommitSHA } ` ;
518-
519- const blocks :JSX . Element [ ] = [ ] ;
520- for ( const linterName of Object . keys ( linterToIssues ) ) {
521- const block = this . renderIssuesFromLinterBlock ( linterName , linterToIssues [ linterName ] , sourceLinkBase ) ;
522- blocks . push ( block ) ;
523- }
524-
525- const title = ca . GithubPullRequestNumber ?
526- `Report for Pull Request${ ca . GithubRepoName } #${ ca . GithubPullRequestNumber } ` :
527- `Report for Repo${ ca . GithubRepoName } ` ;
528-
529- const buildLog = ( ca . ResultJSON && ca . ResultJSON . BuildLog ) ?ca . ResultJSON . BuildLog :null ;
530-
531- const needShowBuildLog = this . props . toggleMap [ showBuildLogToggleKey ] ;
532- let buildLogArea :JSX . Element = null ;
533- if ( needShowBuildLog && buildLog ) {
534- buildLogArea = (
535- < div className = "report-build-log" >
536- < Collapse
537- bordered = { false }
538- activeKey = { this . props . buildLogActivePanels }
539- onChange = { ( activePanels :string [ ] ) => this . props . buildLogTogglePanels ( activePanels ) }
540- >
541- { buildLog . Groups . map ( ( group , i ) => (
542- < Collapse . Panel
543- header = {
544- < >
545- < span className = "report-build-log-group-panel-text" >
546- { group . Name + ( group . Name !== "run goenvbuild" ?` (${ this . formatDuration ( group . Duration / 1000000 ) } )` :"" ) }
547- </ span >
548- { this . doesGroupHaveError ( group ) ?
549- < span className = "report-build-log-group-panel-tag" > < Tag color = "red" > error</ Tag > </ span > :
550- null }
551- </ >
552- }
553- key = { i . toString ( ) }
554- className = "report-build-log-group-panel"
555- >
556- < pre className = "report-build-log-group-panel-text" > { this . getBuildGroupText ( group ) } </ pre >
557- </ Collapse . Panel >
558- ) ) }
559- </ Collapse >
560- </ div >
561- ) ;
562- }
490+ private renderBuildLogArea ( buildLog :IBuildLog ) :JSX . Element {
491+ return (
492+ < div className = "report-build-log" >
493+ < Collapse
494+ bordered = { false }
495+ activeKey = { this . props . buildLogActivePanels }
496+ onChange = { ( activePanels :string [ ] ) => this . props . buildLogTogglePanels ( activePanels ) }
497+ >
498+ { buildLog . Groups . map ( ( group , i ) => (
499+ < Collapse . Panel
500+ header = {
501+ < >
502+ < span className = "report-build-log-group-panel-text" >
503+ { group . Name + ( group . Name !== "run goenvbuild" ?` (${ this . formatDuration ( group . Duration / 1000000 ) } )` :"" ) }
504+ </ span >
505+ { this . doesGroupHaveError ( group ) ?
506+ < span className = "report-build-log-group-panel-tag" > < Tag color = "red" > error</ Tag > </ span > :
507+ null }
508+ </ >
509+ }
510+ key = { i . toString ( ) }
511+ className = "report-build-log-group-panel"
512+ >
513+ < pre className = "report-build-log-group-panel-text" > { this . getBuildGroupText ( group ) } </ pre >
514+ </ Collapse . Panel >
515+ ) ) }
516+ </ Collapse >
517+ </ div >
518+ ) ;
519+ }
563520
564- const toolBar = (
521+ private renderToolBar ( ca :IAnalysisState , issues :IIssue [ ] , buildLog :IBuildLog , needShowBuildLog :boolean ) :JSX . Element {
522+ return (
565523< Row type = "flex" justify = "end" >
566524< div className = "report-toolbar" >
567- { buildLog && (
525+ { buildLog && (
568526< span className = "report-toolbar-build-log-btn" >
569527< Button
570528onClick = { ( ) => this . props . toggle ( showBuildLogToggleKey ) }
@@ -584,6 +542,56 @@ class Report extends React.Component<IProps> {
584542</ div >
585543</ Row >
586544) ;
545+ }
546+
547+ private renderPrevAnalyzesTable ( ca :IAnalysisState ) {
548+ const columns = [
549+ {
550+ key :"columnA" ,
551+ dataIndex :"a" ,
552+ title :"a" ,
553+ } ,
554+ {
555+ key :"columnB" ,
556+ dataIndex :"b" ,
557+ title :"a" ,
558+ } ,
559+ ] ;
560+
561+ const rows = [ ] ;
562+ for ( const a of ca . PreviousAnalyzes ) {
563+ const link = (
564+ < Link
565+ onClick = { ( ) => this . props . toggle ( showPrevAnalyzesToggleKey ) }
566+ to = { `/r/github.com/${ ca . GithubRepoName } /pulls/${ ca . GithubPullRequestNumber } ?commit_sha=${ a . CommitSHA } ` }
567+ >
568+ { a . CommitSHA . substring ( 0 , 7 ) }
569+ </ Link >
570+ ) ;
571+ rows . push ( {
572+ key :a . CommitSHA ,
573+ a :moment ( a . CreatedAt ) . fromNow ( ) ,
574+ b :link ,
575+ } ) ;
576+ }
577+
578+ return (
579+ < Table
580+ className = "prev-analyzes-table"
581+ showHeader = { false }
582+ columns = { columns }
583+ pagination = { false }
584+ sortDirections = { [ ] }
585+ dataSource = { rows } />
586+ ) ;
587+ }
588+
589+ private renderBody ( ca :IAnalysisState , blocks :JSX . Element [ ] , toolBar :JSX . Element , buildLogArea :JSX . Element ) :JSX . Element {
590+ const title = ca . GithubPullRequestNumber ?
591+ `Report for Pull Request${ ca . GithubRepoName } #${ ca . GithubPullRequestNumber } ` :
592+ `Report for Repo${ ca . GithubRepoName } ` ;
593+
594+ const prevAnalyzes = this . props . toggleMap [ showPrevAnalyzesToggleKey ] && this . renderPrevAnalyzesTable ( ca ) ;
587595
588596return (
589597< Row >
@@ -628,10 +636,74 @@ class Report extends React.Component<IProps> {
628636</ Button >
629637</ Link >
630638) }
639+ { ca . GithubPullRequestNumber && ca . PreviousAnalyzes && ca . PreviousAnalyzes . length && (
640+ < span className = "prev-analyzes-btn" >
641+ < Button onClick = { ( ) => this . props . toggle ( showPrevAnalyzesToggleKey ) } >
642+ < Icon type = { this . props . toggleMap [ showPrevAnalyzesToggleKey ] ?"up" :"down" } />
643+ { `${ this . props . toggleMap [ showPrevAnalyzesToggleKey ] ?"Hide" :"Show" } Previous Analyzes` }
644+ </ Button >
645+ </ span >
646+ ) }
647+ { prevAnalyzes && (
648+ < Row >
649+ < Col xs = { 12 } >
650+ { prevAnalyzes }
651+ </ Col >
652+ </ Row >
653+ ) }
631654</ Col >
632655</ Row >
633656) ;
634657}
658+
659+ public render ( ) {
660+ switch ( this . props . lastApiErrorCode ) {
661+ case "NEED_AUTH_TO_ACCESS_PRIVATE_REPO" :
662+ return this . renderNeedAuthError ( ) ;
663+ case "NEED_PRIVATE_ACCESS_TOKEN_TO_ACCESS_PRIVATE_REPO" :
664+ return this . renderNeedPrivateAccessTokenError ( ) ;
665+ case "NO_ACCESS_TO_PRIVATE_REPO_OR_DOESNT_EXIST" :
666+ this . renderNoAccessOrDoesntExistError ( ) ;
667+ }
668+
669+ if ( this . props . curAnalysis === null ) {
670+ return getLoader ( ) ;
671+ }
672+
673+ const rj = this . props . curAnalysis . ResultJSON ;
674+ const issues = ( rj && rj . GolangciLintRes && rj . GolangciLintRes . Issues ) ?rj . GolangciLintRes . Issues :[ ] ;
675+
676+ const linterToIssues :any = { } ;
677+ for ( const i of issues ) {
678+ if ( ! linterToIssues [ i . FromLinter ] ) {
679+ linterToIssues [ i . FromLinter ] = [ ] ;
680+ }
681+
682+ linterToIssues [ i . FromLinter ] . push ( i ) ;
683+ }
684+
685+ const ca = this . props . curAnalysis ;
686+ console . info ( "rendering ca" , ca ) ;
687+ const sourceLinkBase = `https://github.com/${ ca . GithubRepoName } /blob/${ ca . CommitSHA } ` ;
688+
689+ const blocks :JSX . Element [ ] = [ ] ;
690+ for ( const linterName of Object . keys ( linterToIssues ) ) {
691+ const block = this . renderIssuesFromLinterBlock ( linterName , linterToIssues [ linterName ] , sourceLinkBase ) ;
692+ blocks . push ( block ) ;
693+ }
694+
695+ const buildLog = ( ca . ResultJSON && ca . ResultJSON . BuildLog ) ?ca . ResultJSON . BuildLog :null ;
696+
697+ const needShowBuildLog = this . props . toggleMap [ showBuildLogToggleKey ] ;
698+ let buildLogArea :JSX . Element = null ;
699+ if ( needShowBuildLog && buildLog ) {
700+ buildLogArea = this . renderBuildLogArea ( buildLog ) ;
701+ }
702+
703+ const toolBar = this . renderToolBar ( ca , issues , buildLog , needShowBuildLog ) ;
704+
705+ return this . renderBody ( ca , blocks , toolBar , buildLogArea ) ;
706+ }
635707}
636708
637709interface IParams {