|
1 | 1 | module UnisonLocal.Page.HomePage exposing (..) |
2 | 2 |
|
| 3 | +import Code.BranchRef as BranchRef exposing (BranchSlug(..)) |
| 4 | +import Dict exposing (Dict) |
| 5 | +import Html exposing (Html, div, h2, p, text) |
| 6 | +import Json.Decode as Decode |
| 7 | +import Lib.HttpApi as HttpApi |
| 8 | +import Lib.Util as Util |
| 9 | +import RemoteData exposing (RemoteData(..), WebData) |
3 | 10 | import UI.PageContent as PageContent |
4 | 11 | import UI.PageLayout as PageLayout exposing (PageFooter(..)) |
5 | | -import UI.StatusBanner as StatusBanner |
| 12 | +import UI.PageTitle as PageTitle |
| 13 | +import UI.Tag as Tag |
| 14 | +import UnisonLocal.Api as LocalApi |
6 | 15 | import UnisonLocal.AppContext exposing (AppContext) |
7 | 16 | import UnisonLocal.AppDocument as AppDocument exposing (AppDocument) |
8 | 17 | import UnisonLocal.AppHeader as AppHeader |
| 18 | +import UnisonLocal.Link as Link |
| 19 | +import UnisonLocal.ProjectName as ProjectName exposing (ProjectName) |
| 20 | + |
| 21 | + |
| 22 | + |
| 23 | +-- MODEL |
9 | 24 |
|
10 | 25 |
|
11 | 26 | type alias Model = |
12 | | - () |
| 27 | + { projects : Projects } |
| 28 | + |
| 29 | + |
| 30 | +type alias Projects = |
| 31 | + -- Since a `Dict` requires a key of type `comparable` |
| 32 | + -- `ProjectName` is made available in the value |
| 33 | + -- for further processing |
| 34 | + Dict String ( ProjectName, List BranchSlug ) |
13 | 35 |
|
14 | 36 |
|
15 | 37 | init : AppContext -> ( Model, Cmd Msg ) |
16 | | -init _ = |
17 | | - ( (), Cmd.none ) |
| 38 | +init appContext = |
| 39 | + ( { projects = Dict.empty } |
| 40 | + , fetchProjects |
| 41 | + |> HttpApi.perform appContext.api |
| 42 | + ) |
| 43 | + |
| 44 | + |
| 45 | + |
| 46 | +-- UPDATE |
18 | 47 |
|
19 | 48 |
|
20 | 49 | type Msg |
21 | | - = NoOp |
| 50 | + = FetchProjectsFinished (WebData (List ProjectName)) |
| 51 | + | FetchProjectBranchesFinished (WebData ( ProjectName, List BranchSlug )) |
22 | 52 |
|
23 | 53 |
|
24 | 54 | update : AppContext -> Msg -> Model -> ( Model, Cmd Msg ) |
25 | | -update _ _ model = |
26 | | - ( model, Cmd.none ) |
| 55 | +update appContext msg model = |
| 56 | + case msg of |
| 57 | + FetchProjectsFinished (Success projectNames) -> |
| 58 | + ( { projects = |
| 59 | + projectNames |
| 60 | + |> List.map |
| 61 | + (\p -> |
| 62 | + ( ProjectName.toString p |
| 63 | + , ( p, [] ) |
| 64 | + ) |
| 65 | + ) |
| 66 | + |> Dict.fromList |
| 67 | + } |
| 68 | + , projectNames |
| 69 | + |> List.map |
| 70 | + (fetchProjectBranches |
| 71 | + >> HttpApi.perform appContext.api |
| 72 | + ) |
| 73 | + |> Cmd.batch |
| 74 | + ) |
| 75 | + |
| 76 | + FetchProjectBranchesFinished (Success ( projectName, branches )) -> |
| 77 | + ( { model |
| 78 | + | projects = |
| 79 | + model.projects |
| 80 | + |> Dict.insert |
| 81 | + (ProjectName.toString projectName) |
| 82 | + ( projectName, branches ) |
| 83 | + } |
| 84 | + , Cmd.none |
| 85 | + ) |
| 86 | + |
| 87 | + _ -> |
| 88 | + ( model, Cmd.none ) |
| 89 | + |
| 90 | + |
| 91 | + |
| 92 | +-- EFFECTS |
| 93 | + |
| 94 | + |
| 95 | +fetchProjects : HttpApi.ApiRequest (List ProjectName) Msg |
| 96 | +fetchProjects = |
| 97 | + LocalApi.projects |
| 98 | + |> HttpApi.toRequest decodeProjectList (RemoteData.fromResult >> FetchProjectsFinished) |
| 99 | + |
| 100 | + |
| 101 | +fetchProjectBranches : |
| 102 | + ProjectName |
| 103 | + -> HttpApi.ApiRequest ( ProjectName, List BranchSlug ) Msg |
| 104 | +fetchProjectBranches projectName = |
| 105 | + let |
| 106 | + decodeWithProjectName = |
| 107 | + decodeBranchList |
| 108 | + |> Decode.map (Tuple.pair projectName) |
| 109 | + in |
| 110 | + LocalApi.projectBranches projectName |
| 111 | + |> HttpApi.toRequest decodeWithProjectName (RemoteData.fromResult >> FetchProjectBranchesFinished) |
| 112 | + |
| 113 | + |
| 114 | + |
| 115 | +-- DECODE |
| 116 | + |
| 117 | + |
| 118 | +decodeProjectList : Decode.Decoder (List ProjectName) |
| 119 | +decodeProjectList = |
| 120 | + Decode.list <| |
| 121 | + Decode.field "projectName" ProjectName.decode |
| 122 | + |
| 123 | + |
| 124 | +decodeBranchList : Decode.Decoder (List BranchSlug) |
| 125 | +decodeBranchList = |
| 126 | + let |
| 127 | + branchSlugDecode = |
| 128 | + Decode.map BranchRef.branchSlugFromString Decode.string |
| 129 | + |> Decode.andThen (Util.decodeFailInvalid "Invalid BranchName") |
| 130 | + in |
| 131 | + Decode.list <| |
| 132 | + Decode.field "branchName" branchSlugDecode |
| 133 | + |
| 134 | + |
| 135 | + |
| 136 | +-- VIEW |
| 137 | + |
| 138 | + |
| 139 | +viewProjectList : Projects -> List (Html Msg) |
| 140 | +viewProjectList projects = |
| 141 | + let |
| 142 | + branchTag projectName branchName = |
| 143 | + let |
| 144 | + branchRef = |
| 145 | + BranchRef.projectBranchRef branchName |
| 146 | + |
| 147 | + branchRootLink = |
| 148 | + Link.projectBranchRoot projectName branchRef |
| 149 | + in |
| 150 | + branchRef |
| 151 | + |> BranchRef.toTag |
| 152 | + |> Tag.withClick branchRootLink |
| 153 | + |> Tag.view |
| 154 | + |
| 155 | + branchList projectName branches = |
| 156 | + case branches of |
| 157 | + [] -> |
| 158 | + [ text "No branches" ] |
| 159 | + |
| 160 | + branchNames -> |
| 161 | + branchNames |
| 162 | + |> List.map (branchTag projectName) |
| 163 | + |> List.intersperse (text " ") |
| 164 | + |
| 165 | + projectItem projectName branches = |
| 166 | + div [] |
| 167 | + [ h2 [] [ text <| ProjectName.toString projectName ] |
| 168 | + , p [] (branchList projectName branches) |
| 169 | + ] |
| 170 | + in |
| 171 | + projects |
| 172 | + |> Dict.toList |
| 173 | + |> List.map |
| 174 | + (\( _, ( projectName, branches ) ) -> |
| 175 | + projectItem projectName branches |
| 176 | + ) |
27 | 177 |
|
28 | 178 |
|
29 | 179 | view : Model -> AppDocument Msg |
30 | | -view _ = |
| 180 | +view { projects } = |
31 | 181 | let |
32 | 182 | appHeader = |
33 | 183 | AppHeader.appHeader |
34 | 184 |
|
35 | 185 | page = |
36 | 186 | PageLayout.centeredNarrowLayout |
37 | 187 | (PageContent.oneColumn |
38 | | - [ StatusBanner.info "Type `ui` from within a Project in UCM to view that project." |
39 | | - ] |
| 188 | + (viewProjectList projects) |
| 189 | + |> PageContent.withPageTitle (PageTitle.title "Open a project branch") |
40 | 190 | ) |
41 | 191 | (PageFooter []) |
42 | 192 | |> PageLayout.withSubduedBackground |
|
0 commit comments