1- use leptos:: { component, view, Fragment , IntoView } ;
2- #[ cfg( not( debug_assertions) ) ]
3- use leptos:: { create_local_resource, error:: Result , serde_json:: json, SignalGet } ;
1+ use std:: collections:: HashMap ;
2+
3+ use leptos:: {
4+ component, create_local_resource, error:: Result , island, serde_json:: json, view, Fragment ,
5+ IntoView , SignalGet ,
6+ } ;
47use serde:: { Deserialize , Serialize } ;
58
69use crate :: components:: ContributorCard ;
710
8- #[ cfg( not( debug_assertions) ) ]
911const GRAPH_QUERY : & str = r#"
1012query OrganizationContributors {
1113 organization(login: "RustLangES") {
1214 repositories(first: 100) {
1315 nodes {
16+ name
1417 collaborators(first: 100) {
1518 nodes {
1619 login
@@ -19,8 +22,11 @@ query OrganizationContributors {
1922 bio
2023 twitterUsername
2124 location
22- contributionsCollection {
25+ contributionsCollection(organizationID: "O_kgDOBHON2w") {
2326 totalCommitContributions
27+ totalPullRequestContributions
28+ totalIssueContributions
29+ totalRepositoryContributions
2430 }
2531 }
2632 }
@@ -31,23 +37,31 @@ query OrganizationContributors {
3137"# ;
3238
3339#[ derive( Clone , Debug , PartialEq , Eq , Serialize , Deserialize ) ]
40+ #[ serde( rename_all = "camelCase" ) ]
3441pub struct Contributor {
3542 login : String ,
3643 avatar_url : String ,
3744 url : String ,
3845 bio : Option < String > ,
3946 twitter_username : Option < String > ,
4047 location : Option < String > ,
41- contributions_collection : ContributionCollection ,
48+ contributions_collection : Option < ContributionCollection > ,
4249}
4350
4451#[ derive( Clone , Debug , PartialEq , Eq , Serialize , Deserialize ) ]
52+ #[ serde( rename_all = "camelCase" ) ]
4553pub struct ContributionCollection {
46- total_commit_contributions : u64 ,
54+ #[ serde( rename = "totalCommitContributions" ) ]
55+ commits : u64 ,
56+ #[ serde( rename = "totalPullRequestContributions" ) ]
57+ pull_request : u64 ,
58+ #[ serde( rename = "totalIssueContributions" ) ]
59+ issues : u64 ,
60+ #[ serde( rename = "totalRepositoryContributions" ) ]
61+ repository : u64 ,
4762}
4863
49- #[ cfg( not( debug_assertions) ) ]
50- async fn fetch_contributors ( ) -> Result < Vec < Contributor > > {
64+ pub async fn fetch_contributors ( ) -> Result < Vec < Contributor > > {
5165 let request_body = json ! ( {
5266 "query" : GRAPH_QUERY ,
5367 } ) ;
@@ -77,84 +91,43 @@ async fn fetch_contributors() -> Result<Vec<Contributor>> {
7791 . as_array ( )
7892 . unwrap_or ( & Vec :: new ( ) )
7993 . iter ( )
80- . flat_map ( |repo| repo[ "contributors" ] [ "nodes" ] . as_array ( ) . unwrap ( ) )
81- . map ( |c| leptos:: serde_json:: from_value :: < Contributor > ( c. clone ( ) ) . map_err ( |e| e. into ( ) ) )
82- . collect :: < Result < Vec < Contributor > > > ( ) ?;
83-
84- res. sort_by_key ( |a| a. contributions_collection . total_commit_contributions ) ;
94+ . flat_map ( |repo| repo[ "collaborators" ] [ "nodes" ] . as_array ( ) . unwrap ( ) )
95+ . filter_map ( |c| leptos:: serde_json:: from_value :: < Contributor > ( c. clone ( ) ) . ok ( ) )
96+ . fold ( HashMap :: new ( ) , |prev, c| {
97+ let mut prev = prev;
98+ prev. entry ( c. login . clone ( ) )
99+ . and_modify ( |o : & mut Contributor | {
100+ match (
101+ o. contributions_collection . as_mut ( ) ,
102+ c. contributions_collection . as_ref ( ) ,
103+ ) {
104+ ( Some ( o) , Some ( c) ) => o. commits += c. commits ,
105+ ( Some ( o) , None ) => o. commits += 1 ,
106+ _ => { }
107+ }
108+ } )
109+ . or_insert ( c) ;
110+ prev
111+ } )
112+ . into_values ( )
113+ . collect :: < Vec < _ > > ( ) ;
114+
115+ res. sort_by_key ( |a| {
116+ a. contributions_collection
117+ . as_ref ( )
118+ . map ( |c| c. repository )
119+ . unwrap_or ( 1 )
120+ } ) ;
85121
86- println ! ( "Result of Github Request: { res:#?}" ) ;
122+ res. reverse ( ) ;
87123
88124 Ok ( res)
89125}
90126
91- #[ cfg_attr( not( debug_assertions) , component) ]
92- #[ cfg( not( debug_assertions) ) ]
127+ #[ island]
93128pub fn Contributors ( ) -> impl IntoView {
94- let contributors_results = create_local_resource ( move || ( ) , |( ) | fetch_contributors ( ) ) ;
95- let contributorMapper = |item : & Contributor | {
96- view ! {
97- <ContributorCard
98- name=item. login. clone( )
99- description=item. bio. clone( )
100- link=item. url. clone( )
101- brand_src=item. avatar_url. clone( )
102- twitter=item. twitter_username. clone( )
103- location=item. location. clone( )
104- contributions=item. contributions_collection. total_commit_contributions
105- />
106- }
107- } ;
129+ let contributors = create_local_resource ( move || ( ) , |( ) | fetch_contributors ( ) ) ;
108130
109- let contributors_view = move || {
110- let contributors = contributors_results. get ( ) ?. ok ( ) ?;
111- let result = contributors
112- . iter ( )
113- . map ( contributorMapper)
114- . collect :: < Fragment > ( ) ;
115- Some ( result. into_view ( ) )
116- } ;
117-
118- view ! {
119- <section class="bg-orange-300/30 dark:bg-transparent py-16" >
120- <div class="flex flex-col gap-y-6 container mx-auto px-4" >
121- <h2 class="text-3xl text-left mb-6" >
122- <span class="font-work-sans font-light" >"Nuestros " </span>
123- <span class="font-alfa-slab text-orange-500" >"Colaboradores" </span>
124- </h2>
125- <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-5 gap-6" >
126- { contributors_view}
127- </div>
128- </div>
129- </section>
130- }
131- }
132-
133- #[ cfg_attr( debug_assertions, component) ]
134- #[ cfg( debug_assertions) ]
135- pub fn Contributors ( ) -> impl IntoView {
136- let contributors = [ Contributor {
137- login : "Phosphorus-M" . to_owned ( ) ,
138- avatar_url : "https://avatars.githubusercontent.com/u/19656993?v=4" . to_owned ( ) ,
139- url : "https://github.com/Phosphorus-M" . to_owned ( ) ,
140- bio : None ,
141- twitter_username : Some ( "Phosphorus_M" . to_owned ( ) ) ,
142- location : Some ( "Argentina" . to_owned ( ) ) ,
143- contributions_collection : ContributionCollection {
144- total_commit_contributions : 499 ,
145- } ,
146- } ,
147- Contributor {
148- login : "SergioRibera" . to_owned ( ) ,
149- avatar_url : "https://avatars.githubusercontent.com/u/56278796?u=9e3dac947b4fd3ca2f1a05024e083c64e4c69cfe&v=4" . to_owned ( ) ,
150- url : "https://github.com/SergioRibera" . to_owned ( ) ,
151- bio : Some ( "22yo Rustacean and Open Source lover\r \n I teach, Promote and Give Technical talks of rust with @RustLangES" . to_owned ( ) ) ,
152- twitter_username : Some ( "sergioribera_rs" . to_owned ( ) ) ,
153- location : Some ( "Santa Cruz de la Sierra, Bolivia" . to_owned ( ) ) ,
154- contributions_collection : ContributionCollection {
155- total_commit_contributions : 2015
156- }
157- } ] ;
158131 let contributorMapper = |item : & Contributor | {
159132 view ! {
160133 <ContributorCard
@@ -164,21 +137,23 @@ pub fn Contributors() -> impl IntoView {
164137 brand_src=item. avatar_url. clone( )
165138 twitter=item. twitter_username. clone( )
166139 location=item. location. clone( )
167- contributions=item. contributions_collection. total_commit_contributions
140+ contributions=item. contributions_collection. as_ref ( ) . map ( |c| c . commits ) . unwrap_or ( 1 )
168141 />
169142 }
170143 } ;
171144
172145 let contributors_view = move || {
173146 let result = contributors
147+ . get ( ) ?
148+ . ok ( ) ?
174149 . iter ( )
175150 . map ( contributorMapper)
176151 . collect :: < Fragment > ( ) ;
177152 Some ( result. into_view ( ) )
178153 } ;
179154
180155 view ! {
181- <section class="bg-orange-300/30 dark:bg-transparent py-16" >
156+ <section class="bg-orange-300/30 dark:bg-transparent py-16 min-h-[80vh] " >
182157 <div class="flex flex-col gap-y-6 container mx-auto px-4" >
183158 <h2 class="text-3xl text-left mb-6" >
184159 <span class="font-work-sans font-light" >"Nuestros " </span>
0 commit comments