1+ const DEV = 0 ;
2+
3+ let bar_options = {
4+ axisX :{ onlyInteger :true } ,
5+ axisY :{ offset :100 , showGrid :false } ,
6+ horizontalBars :true ,
7+ reverseData :true
8+ } ;
9+
10+ let github_user = null ;
11+ if ( document . location . hash ) {
12+ github_user = document . location . hash . replace ( '#' , '' ) ;
13+ } else {
14+ document . location . href = '/' ;
15+ }
16+ // Set these values here because they are outside of vue's scope.
17+ document . title = `CoderStats(${ github_user } )` ;
18+ document . getElementsByClassName ( 'brand' ) [ 0 ] . textContent = document . title ;
19+
20+ let url_user = `https://api.github.com/users/${ github_user } ` ,
21+ url_repos = `${ url_user } /repos?sort=pushed&per_page=100` ,
22+ months_short = 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec' . split ( ' ' ) ;
23+
24+ if ( DEV ) {
25+ url_user = '/data/user.json' ;
26+ url_repos = '/data/repos.json' ;
27+ }
28+
29+ let coder = new Vue ( {
30+ el :'#coder' ,
31+ data :{
32+ repos :[ ] ,
33+ response :{ } ,
34+ sort_orders :{ } ,
35+ sort_key :'' ,
36+ user :null
37+ } ,
38+ computed :{
39+ // Only repos the user actually pushed at, i.e. no forks with no user commits.
40+ repos_pushed :function ( ) {
41+ return this . repos . filter ( d => d . pushed_at > d . created_at ) ;
42+ } ,
43+ repos_pushed_ratio :function ( ) {
44+ return this . repos . length ?this . repos_pushed . length / this . repos . length :0 ;
45+ } ,
46+ languages :function ( ) {
47+ return d3 . nest ( )
48+ . key ( d => d . language )
49+ . rollup ( leaves => leaves . length )
50+ . entries ( this . repos_pushed . filter ( d => d . language ) )
51+ . sort ( ( a , b ) => b . value - a . value ) ;
52+ } ,
53+ issues :function ( ) {
54+ return this . repoRanking ( 'open_issues_count' ) ;
55+ } ,
56+ forks :function ( ) {
57+ return this . repoRanking ( 'forks_count' ) ;
58+ } ,
59+ stars :function ( ) {
60+ return this . repoRanking ( 'stargazers_count' ) ;
61+ } ,
62+ total_forks :function ( ) {
63+ return d3 . sum ( this . forks , d => d . forks_count ) ;
64+ } ,
65+ total_issues :function ( ) {
66+ return d3 . sum ( this . issues , d => d . open_issues_count ) ;
67+ } ,
68+ total_stars :function ( ) {
69+ return d3 . sum ( this . stars , d => d . stargazers_count ) ;
70+ }
71+ } ,
72+ filters :{
73+ fixURL :value => {
74+ if ( ! value . startsWith ( 'http' ) ) {
75+ value = `http://${ value } ` ;
76+ }
77+ return value ;
78+ } ,
79+ formatDate :value => {
80+ let dt = new Date ( value ) ;
81+ return `${ dt . getDate ( ) } ${ months_short [ dt . getMonth ( ) ] } ${ dt . getYear ( ) + 1900 } ` ;
82+ } ,
83+ formatURL :value => {
84+ return value . split ( '://' ) . pop ( ) . replace ( / \/ $ / , '' ) ;
85+ }
86+ } ,
87+ created :function ( ) {
88+ this . fetchRepos ( ) ;
89+ this . fetchUser ( ) ;
90+ } ,
91+ updated :function ( ) {
92+ let language_ranking = this . languages . slice ( 0 , 10 ) ;
93+ new Chartist . Bar ( '#language-ranking' , {
94+ labels :language_ranking . map ( d => d . key ) ,
95+ series :[ language_ranking . map ( d => d . value ) ]
96+ } , bar_options ) ;
97+
98+ this . rankingGraph ( this . issues . slice ( 0 , 10 ) , 'open_issues_count' , '#issues-ranking' ) ;
99+ this . rankingGraph ( this . forks . slice ( 0 , 10 ) , 'forks_count' , '#forks-ranking' ) ;
100+ this . rankingGraph ( this . stars . slice ( 0 , 10 ) , 'stargazers_count' , '#stars-ranking' ) ;
101+ } ,
102+ methods :{
103+ fetchRepos :function ( ) {
104+ this . $http . get ( url_repos ) . then ( response => {
105+ this . response . repos = response ;
106+ this . repos = response . body ;
107+ } ) ;
108+ } ,
109+ fetchUser :function ( ) {
110+ this . $http . get ( url_user ) . then ( response => {
111+ this . response . user = response ;
112+ this . user = response . body ;
113+ if ( ! this . user . name ) this . user . name = this . user . login ;
114+ } ) ;
115+ } ,
116+ order :function ( key ) {
117+ // asc is default, because sort orders are initially unset
118+ return this . sort_orders [ key ] < 0 ?'dsc' :'asc' ;
119+ } ,
120+ rankingGraph :function ( series , property , selector ) {
121+ if ( series . length ) {
122+ new Chartist . Bar ( selector , {
123+ labels :series . map ( d => d . name ) ,
124+ series :[ series . map ( d => d [ property ] ) ]
125+ } , bar_options ) ;
126+ }
127+ } ,
128+ repoRanking :function ( property ) {
129+ return this . repos_pushed . filter ( d => d [ property ] )
130+ . sort ( ( a , b ) => b [ property ] - a [ property ] ) ;
131+ } ,
132+ sortBy :function ( key , type = 'number' ) {
133+ let default_value = type === 'string' ?'' :0 ;
134+ this . sort_key = key ;
135+ this . sort_orders [ key ] = ( this . sort_orders [ key ] || 1 ) * - 1 ;
136+ this . repos . sort ( ( a , b ) => {
137+ let x = a [ key ] || default_value ,
138+ y = b [ key ] || default_value ;
139+ if ( type === 'string' ) {
140+ x = x . toLowerCase ( ) ;
141+ y = y . toLowerCase ( ) ;
142+ }
143+ return ( x === y ?0 :x > y ?1 :- 1 ) * this . sort_orders [ key ] ;
144+ } ) ;
145+ }
146+ }
147+ } ) ;