@@ -9,9 +9,11 @@ defmodule AlgoraWeb.Org.DashboardLive do
99 alias Algora.Accounts
1010 alias Algora.Bounties
1111 alias Algora.Contracts
12+ alias Algora.Github
1213 alias Algora.Types.USD
1314 alias Algora.Validations
1415 alias Algora.Workspace
16+ alias AlgoraWeb.Components.Logos
1517
1618 require Logger
1719
@@ -61,31 +63,80 @@ defmodule AlgoraWeb.Org.DashboardLive do
6163 end
6264 end
6365
66+ @ impl true
6467 def mount ( _params , _session , socket ) do
68+ % { current_org: current_org } = socket . assigns
69+
6570 experts =
66- socket . assigns . current_user . tech_stack
71+ current_org . tech_stack
6772 |> List . first ( )
6873 |> Accounts . list_experts ( )
6974 |> Enum . take ( 6 )
7075
76+ installations = Workspace . list_installations_by ( connected_user_id: current_org . id , provider: "github" )
77+
7178 if connected? ( socket ) do
79+ Phoenix.PubSub . subscribe ( Algora.PubSub , "auth:#{ socket . id } " )
7280 Bounties . subscribe ( )
7381 end
7482
7583 { :ok ,
7684 socket
85+ |> assign ( :installations , installations )
86+ |> assign ( :oauth_url , Github . authorize_url ( % { socket_id: socket . id } ) )
7787 |> assign ( :bounty_form , to_form ( BountyForm . changeset ( % BountyForm { } , % { } ) ) )
7888 |> assign ( :tip_form , to_form ( TipForm . changeset ( % TipForm { } , % { } ) ) )
7989 |> assign ( :experts , experts )
8090 |> assign_tickets ( )
8191 |> assign_achievements ( ) }
8292 end
8393
94+ @ impl true
8495 def render ( assigns ) do
8596 ~H"""
8697 < div class = "lg:pr-96 " >
8798 < div class = "container mx-auto max-w-7xl space-y-8 p-8 " >
88- < . section >
99+ < . section :if = { @ installations == [ ] } >
100+ < . card >
101+ < . card_header >
102+ < . card_title > GitHub Integration</ . card_title >
103+ < . card_description :if = { @ installations == [ ] } >
104+ Install the Algora app to enable slash commands in your GitHub repositories
105+ </ . card_description >
106+ </ . card_header >
107+ < . card_content >
108+ < div class = "flex flex-col gap-3 " >
109+ <%= if @ installations != [ ] do %>
110+ <%= for installation <- @ installations do %>
111+ < div class = "flex items-center gap-2 " >
112+ < img src = { installation . avatar_url } class = "w-9 h-9 rounded-lg " />
113+ < div >
114+ < p class = "font-medium " > { installation . provider_meta [ "account" ] [ "login" ] } </ p >
115+ < p class = "text-sm text-muted-foreground " >
116+ Algora app is installed in
117+ < strong > { installation . repository_selection } </ strong >
118+ repositories
119+ </ p >
120+ </ div >
121+ </ div >
122+ <% end %>
123+ < . button phx-click = "install_app " class = "ml-auto gap-2 " >
124+ < Logos . github class = "w-4 h-4 mr-2 -ml-1 " />
125+ Manage { ngettext ( "installation" , "installations" , length ( @ installations ) ) }
126+ </ . button >
127+ <% else %>
128+ < div class = "flex flex-col gap-2 " >
129+ < . button phx-click = "install_app " class = "ml-auto gap-2 " >
130+ < Logos . github class = "w-4 h-4 mr-2 -ml-1 " /> Install GitHub App
131+ </ . button >
132+ </ div >
133+ <% end %>
134+ </ div >
135+ </ . card_content >
136+ </ . card >
137+ </ . section >
138+
139+ < . section :if = { @ installations != [ ] } >
89140 < div class = "grid grid-cols-1 gap-8 md:grid-cols-2 " >
90141 { create_bounty ( assigns ) }
91142 { create_tip ( assigns ) }
@@ -191,6 +242,21 @@ defmodule AlgoraWeb.Org.DashboardLive do
191242 """
192243 end
193244
245+ @ impl true
246+ def handle_info ( :bounties_updated , socket ) do
247+ { :noreply , assign_tickets ( socket ) }
248+ end
249+
250+ def handle_info ( { :authenticated , user } , socket ) do
251+ { :noreply , socket |> assign ( :current_user , user ) |> redirect ( external: Github . install_url_select_target ( ) ) }
252+ end
253+
254+ @ impl true
255+ def handle_event ( "install_app" , _params , socket ) do
256+ # TODO: immediately redirect to install_url if user has valid token
257+ { :noreply , push_event ( socket , "open_popup" , % { url: socket . assigns . oauth_url } ) }
258+ end
259+
194260 def handle_event ( "create_bounty" , % { "bounty_form" => params } , socket ) do
195261 changeset =
196262 % BountyForm { }
@@ -251,10 +317,6 @@ defmodule AlgoraWeb.Org.DashboardLive do
251317 end
252318 end
253319
254- def handle_info ( :bounties_updated , socket ) do
255- { :noreply , assign_tickets ( socket ) }
256- end
257-
258320 defp assign_tickets ( socket ) do
259321 tickets =
260322 Bounties.PrizePool . list (
@@ -271,6 +333,7 @@ defmodule AlgoraWeb.Org.DashboardLive do
271333
272334 status_fns = [
273335 { & personalize_status / 1 , "Personalize Algora" } ,
336+ { & install_app_status / 1 , "Install the Algora app" } ,
274337 { & create_bounty_status / 1 , "Create a bounty" } ,
275338 { & reward_bounty_status / 1 , "Reward a bounty" } ,
276339 { & begin_collaboration_status / 1 , "Contract a #{ tech } developer" } ,
@@ -279,7 +342,7 @@ defmodule AlgoraWeb.Org.DashboardLive do
279342
280343 { achievements , _ } =
281344 Enum . reduce_while ( status_fns , { [ ] , false } , fn { status_fn , name } , { acc , found_current } ->
282- status = status_fn . ( socket . assigns . current_user )
345+ status = status_fn . ( socket )
283346
284347 result =
285348 cond do
@@ -296,29 +359,36 @@ defmodule AlgoraWeb.Org.DashboardLive do
296359
297360 defp personalize_status ( _socket ) , do: :completed
298361
299- defp create_bounty_status ( user ) do
300- case Bounties . list_bounties ( owner_id: user . id , limit: 1 ) do
362+ defp install_app_status ( socket ) do
363+ case socket . assigns . installations do
364+ [ ] -> :upcoming
365+ _ -> :completed
366+ end
367+ end
368+
369+ defp create_bounty_status ( socket ) do
370+ case Bounties . list_bounties ( owner_id: socket . assigns . current_user . id , limit: 1 ) do
301371 [ ] -> :upcoming
302372 _ -> :completed
303373 end
304374 end
305375
306- defp reward_bounty_status ( user ) do
307- case Bounties . list_bounties ( owner_id: user . id , status: :paid , limit: 1 ) do
376+ defp reward_bounty_status ( socket ) do
377+ case Bounties . list_bounties ( owner_id: socket . assigns . current_user . id , status: :paid , limit: 1 ) do
308378 [ ] -> :upcoming
309379 _ -> :completed
310380 end
311381 end
312382
313- defp begin_collaboration_status ( user ) do
314- case Contracts . list_contracts ( client_id: user . id , active_or_paid?: true , limit: 1 ) do
383+ defp begin_collaboration_status ( socket ) do
384+ case Contracts . list_contracts ( client_id: socket . assigns . current_user . id , active_or_paid?: true , limit: 1 ) do
315385 [ ] -> :upcoming
316386 _ -> :completed
317387 end
318388 end
319389
320- defp complete_first_contract_status ( user ) do
321- case Contracts . list_contracts ( client_id: user . id , status: :paid , limit: 1 ) do
390+ defp complete_first_contract_status ( socket ) do
391+ case Contracts . list_contracts ( client_id: socket . assigns . current_user . id , status: :paid , limit: 1 ) do
322392 [ ] -> :upcoming
323393 _ -> :completed
324394 end
0 commit comments