@@ -29,6 +29,10 @@ interface DiffCache {
2929 diff : JSX . Element ;
3030 whitespace ?: boolean ;
3131 revert ?: ( ) => void ;
32+ testAction ?: {
33+ text : string ;
34+ url : string ;
35+ }
3236}
3337
3438interface GithubProps {
@@ -639,9 +643,9 @@ class GithubComponent extends data.Component<GithubProps, GithubState> {
639643 </ h3 >
640644 { needsCommit && < CommmitComponent parent = { this } needsToken = { needsToken } githubId = { githubId } master = { master } gs = { gs } isBlocks = { isBlocksMode } needsCommit = { needsCommit } user = { user } pullStatus = { pullStatus } pullRequest = { pr } /> }
641645 { diffFiles && < DiffView parent = { this } diffFiles = { diffFiles } cacheKey = { gs . commit . sha } allowRevert = { true } showWhitespaceDiff = { true } blocksMode = { isBlocksMode } showConflicts = { true } /> }
646+ < HistoryZone parent = { this } needsToken = { needsToken } githubId = { githubId } master = { master } gs = { gs } isBlocks = { isBlocksMode } needsCommit = { needsCommit } user = { user } pullStatus = { pullStatus } pullRequest = { pr } />
642647 { master && < ReleaseZone parent = { this } needsToken = { needsToken } githubId = { githubId } master = { master } gs = { gs } isBlocks = { isBlocksMode } needsCommit = { needsCommit } user = { user } pullStatus = { pullStatus } pullRequest = { pr } /> }
643648 { ! isBlocksMode && < ExtensionZone parent = { this } needsToken = { needsToken } githubId = { githubId } master = { master } gs = { gs } isBlocks = { isBlocksMode } needsCommit = { needsCommit } user = { user } pullStatus = { pullStatus } pullRequest = { pr } /> }
644- < HistoryZone parent = { this } needsToken = { needsToken } githubId = { githubId } master = { master } gs = { gs } isBlocks = { isBlocksMode } needsCommit = { needsCommit } user = { user } pullStatus = { pullStatus } pullRequest = { pr } />
645649 < div > </ div >
646650 </ div >
647651 </ div >
@@ -731,6 +735,10 @@ class DiffView extends sui.StatelessUIElement<DiffViewProps> {
731735 { ! ! cache . revert && < sui . Button className = "small" icon = "undo" text = { lf ( "Revert" ) }
732736 ariaLabel = { lf ( "Revert file" ) } title = { lf ( "Revert file" ) }
733737 textClass = { "landscape only" } onClick = { cache . revert } /> }
738+ { ! ! cache . testAction && < sui . Link className = "small button" icon = "external"
739+ ariaLabel = { cache . testAction . text } textClass = { "landscape only" }
740+ text = { cache . testAction . text } href = { cache . testAction . url }
741+ target = "_blank" /> }
734742 { jsxEls . legendJSX }
735743 { showConflicts && ! ! jsxEls . conflicts && < p > { lf ( "Merge conflicts found. Resolve them before commiting." ) } </ p > }
736744 { ! ! cache . revert && ! ! deletedFiles . length &&
@@ -778,8 +786,15 @@ class DiffView extends sui.StatelessUIElement<DiffViewProps> {
778786 if ( virtualF == f . file ) virtualF = undefined ;
779787
780788 cache . file = f
781- if ( this . props . allowRevert )
789+ if ( this . props . allowRevert ) {
782790 cache . revert = ( ) => this . props . parent . revertFileAsync ( f , deletedFiles , addedFiles , virtualF ) ;
791+ if ( / \. m d $ / . test ( cache . file . name ) ) {
792+ cache . testAction = {
793+ text : lf ( "Preview as Tutorial" ) ,
794+ url : `#tutorial:${ this . props . parent . props . parent . state . header . id } :${ cache . file . name . replace ( / \. [ a - z ] + $ / , '' ) } `
795+ }
796+ }
797+ }
783798 cache . diff = createDiff ( )
784799 return cache . diff ;
785800 }
@@ -1253,7 +1268,7 @@ interface CommitViewProps {
12531268 githubId : pxt . github . ParsedRepo ;
12541269 commit : pxt . github . CommitInfo ;
12551270 expanded : boolean ;
1256- onClick ?: ( ) => void ;
1271+ onClick ?: ( e : React . MouseEvent < HTMLDivElement > ) => void ;
12571272}
12581273
12591274interface CommitViewState {
@@ -1341,8 +1356,8 @@ class CommitView extends sui.UIElement<CommitViewProps, CommitViewState> {
13411356 return < div className = { `ui item link` } role = "button" onClick = { onClick } onKeyDown = { sui . fireClickOnEnter } >
13421357 < div className = "content" >
13431358 { expanded && < sui . Button loading = { loading } className = "right floated" text = { lf ( "Restore" ) } onClick = { this . handleRestore } onKeyDown = { sui . fireClickOnEnter } /> }
1344- < div className = "header " >
1345- { date . toLocaleString ( ) }
1359+ < div className = "meta " >
1360+ < span > { date . toLocaleTimeString ( ) } </ span >
13461361 </ div >
13471362 < div className = "description" > { commit . message } </ div >
13481363 { expanded && diffFiles && < DiffView parent = { parent } blocksMode = { false } diffFiles = { diffFiles } cacheKey = { commit . sha } /> }
@@ -1354,6 +1369,7 @@ class CommitView extends sui.UIElement<CommitViewProps, CommitViewState> {
13541369interface HistoryState {
13551370 expanded ?: boolean ;
13561371 selectedCommit ?: pxt . github . CommitInfo ;
1372+ selectedDay ?: string ;
13571373}
13581374
13591375class HistoryZone extends sui . UIElement < GitHubViewProps , HistoryState > {
@@ -1365,17 +1381,27 @@ class HistoryZone extends sui.UIElement<GitHubViewProps, HistoryState> {
13651381 handleLoadClick ( ) {
13661382 pxt . tickEvent ( "github.history.load" , undefined , { interactiveConsent : true } ) ;
13671383 const { expanded } = this . state ;
1368- this . setState ( { expanded : ! expanded , selectedCommit : undefined } )
1384+ this . setState ( { expanded : ! expanded , selectedCommit : undefined , selectedDay : undefined } )
13691385 }
13701386
13711387 renderCore ( ) {
13721388 const { githubId, gs, parent } = this . props ;
1373- const { selectedCommit, expanded } = this . state ;
1389+ const { selectedCommit, expanded, selectedDay } = this . state ;
13741390 const inverted = ! ! pxt . appTarget . appTheme . invertedGitHub ;
13751391 const commits = expanded &&
1376- this . getData ( `gh-commits:${ gs . repo } #${ gs . commit . sha } ` ) as pxt . github . CommitInfo [ ] ;
1392+ this . getData ( `gh-commits:${ githubId . fullName } #${ gs . commit . sha } ` ) as pxt . github . CommitInfo [ ] ;
13771393 const loading = expanded && ! commits ;
13781394
1395+ // group commits by day
1396+ const days : pxt . Map < pxt . github . CommitInfo [ ] > = { } ;
1397+ if ( commits )
1398+ commits . forEach ( commit => {
1399+ const day = new Date ( Date . parse ( commit . author . date ) ) . toLocaleDateString ( ) ;
1400+ let dcommit = days [ day ] ;
1401+ if ( ! dcommit ) dcommit = days [ day ] = [ ] ;
1402+ dcommit . push ( commit ) ;
1403+ } )
1404+
13791405 return < div className = { `ui transparent ${ inverted ? 'inverted' : '' } segment` } >
13801406 < div className = "ui header" > { lf ( "History" ) } </ div >
13811407 { ( loading || ! expanded ) && < div className = "ui field" >
@@ -1388,19 +1414,40 @@ class HistoryZone extends sui.UIElement<GitHubViewProps, HistoryState> {
13881414 { sui . helpIconLink ( "/github/history" , lf ( "Learn more about history of commits." ) ) }
13891415 </ span >
13901416 </ div > }
1391- { commits && < div className = "ui divided items" >
1392- { commits . map ( commit => < CommitView
1393- key = { 'commit' + commit . sha }
1394- onClick = { ( ) => {
1395- pxt . tickEvent ( "github.history.selectcommit" , undefined , { interactiveConsent : true } )
1396- const { selectedCommit } = this . state ;
1397- this . setState ( { selectedCommit : commit == selectedCommit ? undefined : commit } )
1398- } }
1399- commit = { commit }
1400- parent = { parent }
1401- githubId = { githubId }
1402- expanded = { selectedCommit === commit }
1403- /> ) }
1417+ { commits && < div className = "ui items" >
1418+ { Object . keys ( days ) . map ( day =>
1419+ < div role = "button" className = "ui link item"
1420+ key = { "commitday" + day }
1421+ onClick = { e => {
1422+ e . stopPropagation ( ) ;
1423+ pxt . tickEvent ( "github.history.selectday" ) ;
1424+ this . setState ( { selectedDay : selectedDay === day ? undefined : day , selectedCommit : undefined } ) ;
1425+ } }
1426+ onKeyDown = { sui . fireClickOnEnter } >
1427+ < div className = "content" >
1428+ < div className = "ui header" > { day }
1429+ < div className = "ui label" >
1430+ < i className = "long arrow alternate up icon" > </ i > { days [ day ] . length }
1431+ </ div >
1432+ </ div >
1433+ { day === selectedDay &&
1434+ < div className = "ui divided items" >
1435+ { days [ day ] . map ( commit => < CommitView
1436+ key = { 'commit' + commit . sha }
1437+ onClick = { e => {
1438+ e . stopPropagation ( ) ;
1439+ pxt . tickEvent ( "github.history.selectcommit" , undefined , { interactiveConsent : true } )
1440+ const { selectedCommit } = this . state ;
1441+ this . setState ( { selectedCommit : commit == selectedCommit ? undefined : commit } )
1442+ } }
1443+ commit = { commit }
1444+ parent = { parent }
1445+ githubId = { githubId }
1446+ expanded = { selectedCommit === commit }
1447+ /> ) }
1448+ </ div > }
1449+ </ div >
1450+ </ div > ) }
14041451 </ div > }
14051452 </ div >
14061453 }
0 commit comments