11use std:: collections:: HashMap ;
22
3- use leptos:: {
4- component, create_local_resource, error:: Result , island, serde_json:: json, view, Fragment ,
5- IntoView , SignalGet ,
6- } ;
3+ use leptos:: { component, serde_json:: json, view, Await , IntoView } ;
74use serde:: { Deserialize , Serialize } ;
85
96use crate :: components:: ContributorCard ;
107
8+ // Test this query on: https://docs.github.com/es/graphql/overview/explorer
119const GRAPH_QUERY : & str = r#"
1210query OrganizationContributors {
1311 organization(login: "RustLangES") {
@@ -59,15 +57,18 @@ pub struct ContributionCollection {
5957 issues : u64 ,
6058 #[ serde( rename = "totalRepositoryContributions" ) ]
6159 repository : u64 ,
60+ #[ serde( skip) ]
61+ total : u64 ,
6262}
6363
64- pub async fn fetch_contributors ( ) -> Result < Vec < Contributor > > {
64+ pub async fn fetch_contributors ( ) -> Vec < Contributor > {
6565 let request_body = json ! ( {
6666 "query" : GRAPH_QUERY ,
6767 } ) ;
6868
6969 let mut headers = reqwest:: header:: HeaderMap :: new ( ) ;
7070
71+ headers. append ( "User-Agent" , "RustLangES Automation Agent" . parse ( ) . unwrap ( ) ) ;
7172 headers. append (
7273 "Authorization" ,
7374 format ! ( "Bearer {}" , env!( "GITHUB_API_TOKEN" ) )
@@ -77,15 +78,22 @@ pub async fn fetch_contributors() -> Result<Vec<Contributor>> {
7778
7879 let client = reqwest:: ClientBuilder :: new ( )
7980 . default_headers ( headers)
80- . build ( ) ?;
81+ . build ( )
82+ . unwrap ( ) ;
8183
82- let res: leptos :: serde_json :: Value = client
84+ let res = client
8385 . post ( "https://api.github.com/graphql" )
8486 . json ( & request_body)
8587 . send ( )
86- . await ?
87- . json ( )
88- . await ?;
88+ . await
89+ . unwrap ( )
90+ . text ( )
91+ . await
92+ . unwrap ( ) ;
93+
94+ leptos:: logging:: log!( "Raw: {res:?}" ) ;
95+
96+ let res: leptos:: serde_json:: Value = leptos:: serde_json:: from_str ( & res) . unwrap ( ) ;
8997
9098 let mut res = res[ "data" ] [ "organization" ] [ "repositories" ] [ "nodes" ]
9199 . as_array ( )
@@ -101,57 +109,41 @@ pub async fn fetch_contributors() -> Result<Vec<Contributor>> {
101109 o. contributions_collection . as_mut ( ) ,
102110 c. contributions_collection . as_ref ( ) ,
103111 ) {
104- ( Some ( o) , Some ( c) ) => o. commits += c. commits ,
105- ( Some ( o) , None ) => o. commits += 1 ,
112+ ( Some ( o) , Some ( c) ) => {
113+ o. total = o. total . max (
114+ ( o. commits + o. issues + o. pull_request + o. repository )
115+ . max ( c. commits + c. issues + c. pull_request + c. repository ) ,
116+ )
117+ }
118+ ( Some ( o) , None ) => o. total = 1 ,
106119 _ => { }
107120 }
108121 } )
109122 . or_insert ( c) ;
110123 prev
111124 } )
112125 . into_values ( )
126+ . filter ( |c| {
127+ c. contributions_collection
128+ . as_ref ( )
129+ . is_some_and ( |cc| cc. total != 0 )
130+ } )
113131 . collect :: < Vec < _ > > ( ) ;
114132
115133 res. sort_by_key ( |a| {
116134 a. contributions_collection
117135 . as_ref ( )
118- . map ( |c| c. repository )
136+ . map ( |c| c. total )
119137 . unwrap_or ( 1 )
120138 } ) ;
121139
122140 res. reverse ( ) ;
123141
124- Ok ( res)
142+ res
125143}
126144
127- #[ island ]
145+ #[ component ]
128146pub fn Contributors ( ) -> impl IntoView {
129- let contributors = create_local_resource ( move || ( ) , |( ) | fetch_contributors ( ) ) ;
130-
131- let contributorMapper = |item : & Contributor | {
132- view ! {
133- <ContributorCard
134- name=item. login. clone( )
135- description=item. bio. clone( )
136- link=item. url. clone( )
137- brand_src=item. avatar_url. clone( )
138- twitter=item. twitter_username. clone( )
139- location=item. location. clone( )
140- contributions=item. contributions_collection. as_ref( ) . map( |c| c. commits) . unwrap_or( 1 )
141- />
142- }
143- } ;
144-
145- let contributors_view = move || {
146- let result = contributors
147- . get ( ) ?
148- . ok ( ) ?
149- . iter ( )
150- . map ( contributorMapper)
151- . collect :: < Fragment > ( ) ;
152- Some ( result. into_view ( ) )
153- } ;
154-
155147 view ! {
156148 <section class="bg-orange-300/30 dark:bg-transparent py-16 min-h-[80vh]" >
157149 <div class="flex flex-col gap-y-6 container mx-auto px-4" >
@@ -160,7 +152,22 @@ pub fn Contributors() -> impl IntoView {
160152 <span class="font-alfa-slab text-orange-500" >"Colaboradores" </span>
161153 </h2>
162154 <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-5 gap-6" >
163- { contributors_view}
155+ <Await
156+ future=|| fetch_contributors( )
157+ let : contributors
158+ >
159+ { contributors. iter( ) . map( |item| view! {
160+ <ContributorCard
161+ name=item. login. clone( )
162+ description=item. bio. clone( )
163+ link=item. url. clone( )
164+ brand_src=item. avatar_url. clone( )
165+ twitter=item. twitter_username. clone( )
166+ location=item. location. clone( )
167+ contributions=item. contributions_collection. as_ref( ) . map( |c| c. total) . unwrap_or( 1 )
168+ />
169+ } ) . collect:: <Vec <_>>( ) }
170+ </Await >
164171 </div>
165172 </div>
166173 </section>
0 commit comments