diff --git a/src/Pages/App_String.elm b/src/Pages/App_String.elm index 770c787..a3d3fbd 100644 --- a/src/Pages/App_String.elm +++ b/src/Pages/App_String.elm @@ -1,19 +1,20 @@ module Pages.App_String exposing (Model, Msg, Params, page) -import Regex -import Html exposing (Html, button, div, h2, h5, img, text, ul, li, a, p, span, i) -import Html.Attributes exposing (src, style, class, alt, href) +import Html exposing (Html, a, button, div, h2, h5, i, img, li, p, span, text, ul) +import Html.Attributes exposing (alt, class, href, src, style) import Html.Events exposing (onClick) import Http -import Markdown import Json.Decode as Decode import Json.Decode.Extra as Decode exposing (andMap) +import Markdown +import Regex import Spa.Document exposing (Document) import Spa.Generated.Route as Route import Spa.Page as Page exposing (Page) import Spa.Url as Url exposing (Url) + -- INIT @@ -26,9 +27,11 @@ page = , subscriptions = subscriptions } + type alias Params = - { app : String - } + { app : String + } + type alias App = { name : String @@ -43,7 +46,8 @@ type alias App = , description : Maybe String } -type alias Model = + +type alias Model = { url : Url Params , status : Status , readme : String @@ -62,8 +66,15 @@ init url = default_image : String + + + -- FIXME: change to absolute URL, if this works? -default_image = "/logo.png" + + +default_image = + "/logo.png" + -- UPDATE @@ -84,18 +95,20 @@ update msg model = GotApps result -> case result of Ok apps -> - let - -- TODO better way of getting a single app? - apps_filtered = List.filter (\app -> app.slug == model.url.params.app) apps - in - case List.head apps_filtered of - Nothing -> - ( { model | status = Failure }, Cmd.none ) - Just item -> - ( { model | status = Success (item) }, loadREADME item) + let + -- TODO better way of getting a single app? + apps_filtered = + List.filter (\app -> app.slug == model.url.params.app) apps + in + case List.head apps_filtered of + Nothing -> + ( { model | status = Failure }, Cmd.none ) + + Just item -> + ( { model | status = Success item }, loadREADME item ) Err _ -> - ( { model | status = Failure } , Cmd.none ) + ( { model | status = Failure }, Cmd.none ) GotText result -> case result of @@ -103,15 +116,19 @@ update msg model = -- update model.content with the loaded README let -- remove HTML comments - pattern = "" - maybeRegex = Regex.fromString pattern - regex = Maybe.withDefault Regex.never maybeRegex + pattern = + "" + + maybeRegex = + Regex.fromString pattern + + regex = + Maybe.withDefault Regex.never maybeRegex in - ( { model | readme = Regex.replace regex (\_ -> "") content }, Cmd.none ) + ( { model | readme = Regex.replace regex (\_ -> "") content }, Cmd.none ) Err _ -> - ( { model | status = Failure } , Cmd.none ) - + ( { model | status = Failure }, Cmd.none ) subscriptions : Model -> Sub Msg @@ -135,8 +152,10 @@ title model = case model.status of Loading -> "loading – abra apps" + Failure -> "error –- abra apps" + Success app -> app.name ++ " – abra apps" @@ -154,20 +173,20 @@ body model = ] Loading -> - div [ class "d-flex align-items-center", style "height" "89vh" ] - [ div [ class "spinner-border m-auto text-light" ] - [ - span [ class "sr-only" ] [ text "Loading..." ] - ] - ] + div [ class "d-flex align-items-center", style "height" "89vh" ] + [ div [ class "spinner-border m-auto text-light" ] + [ span [ class "sr-only" ] [ text "Loading..." ] + ] + ] Success app -> div [] [ div [ class "row" ] - [ viewApp app model.readme ] + [ viewApp app model.readme ] ] ] + viewStatusBadge : App -> Html Msg viewStatusBadge app = let @@ -175,17 +194,22 @@ viewStatusBadge app = case app.status of "1" -> "badge-success" + "2" -> "badge-info" + "3" -> "badge-warning" - "4" -> + + "4" -> "badge-danger" + _ -> "badge-dark" in - span [ class ("card-link badge " ++ status_class) ] - [ text ("Score: " ++ app.status) ] + span [ class ("card-link badge " ++ status_class) ] + [ text ("Score: " ++ app.status) ] + viewApp : App -> String -> Html Msg viewApp app readme = @@ -194,89 +218,104 @@ viewApp app readme = case app.icon of Just "" -> default_image + Just i -> i + Nothing -> default_image - repository_link = + + repository_link = case app.repository of Just link -> - a [ class "card-link", href link ] - [ i [ class "fab fa-git-alt" ] [] - , text "code" ] + a [ class "card-link", href link ] + [ i [ class "fab fa-git-alt" ] [] + , text "code" + ] + Nothing -> text "" - website_link = + + website_link = case app.website of Just link -> case link of "" -> text "" + _ -> - a [ class "card-link", href link ] - [ i [ class "fas fa-home" ] [] - , text "homepage" ] + a [ class "card-link", href link ] + [ i [ class "fas fa-home" ] [] + , text "homepage" + ] + Nothing -> text "" - in - div [ class "col-md-6 col-sm-10 mb-3 offset-md-3 offset-sm-1" ] - [ div [ class "card" ] - [ div [ class "card-header" ] - [ a - [ class "btn btn-sm border border-secondary card-link" - , href (Route.toString Route.Top)] - [ text "← back" ] - , span [ class "card-link badge badge-secondary" ] [ text app.category ] - , viewStatusBadge app - , repository_link - , website_link + in + div [ class "col-md-6 col-sm-10 mb-3 offset-md-3 offset-sm-1" ] + [ div [ class "card" ] + [ div [ class "card-header" ] + [ a + [ class "btn btn-sm border border-secondary card-link" + , href (Route.toString Route.Top) ] - , img [ class "card-img-top", src icon_url, alt ("icon for " ++ app.name) ] [] - , div [ class "card-body" ] - -- render Markdown with no special options - [ div [] (Markdown.toHtml Nothing readme) - ] - , div [ class "card-footer" ] - [] + [ text "← back" ] + , span [ class "card-link badge badge-secondary" ] [ text app.category ] + , viewStatusBadge app + , repository_link + , website_link ] + , img [ class "card-img-top", src icon_url, alt ("icon for " ++ app.name) ] [] + , div [ class "card-body" ] + -- render Markdown with no special options + [ div [] (Markdown.toHtml Nothing readme) + ] + , div [ class "card-footer" ] + [] ] + ] + + -- HTTP loadApp : Cmd Msg loadApp = - Http.get - { url = "/abra-apps.json" - , expect = Http.expectJson GotApps appListDecoder } + Http.get + { url = "/abra-apps.json" + , expect = Http.expectJson GotApps appListDecoder + } loadREADME : App -> Cmd Msg -loadREADME app = +loadREADME app = let - repository_link = + repository_link = case app.repository of Just link -> - a [ class "card-link", href link ] - [ i [ class "fab fa-git-alt" ] [] - , text "code" ] + a [ class "card-link", href link ] + [ i [ class "fab fa-git-alt" ] [] + , text "code" + ] + Nothing -> text "" in - Http.get - -- FIXME use live Gitea link - { url = "https://cors-container.herokuapp.com/https://git.autonomic.zone/coop-cloud/" ++ app.slug ++ "/raw/branch/" ++ app.default_branch ++ "/README.md" - , expect = Http.expectString GotText } + Http.get + -- FIXME use live Gitea link + { url = "https://cors-container.herokuapp.com/https://git.autonomic.zone/coop-cloud/" ++ app.slug ++ "/raw/branch/" ++ app.default_branch ++ "/README.md" + , expect = Http.expectString GotText + } featuresDecoder : Decode.Decoder String featuresDecoder = -- get features.status if it's there - (Decode.oneOf + Decode.oneOf [ Decode.at [ "status" ] Decode.string , Decode.succeed "" ] - ) appDecoder : Decode.Decoder App @@ -300,6 +339,6 @@ appListDecoder = |> Decode.map buildApp -buildApp : List (String, App) -> (List App) +buildApp : List ( String, App ) -> List App buildApp apps = - List.map (\(slug, app) -> { app | slug = slug}) apps + List.map (\( slug, app ) -> { app | slug = slug }) apps diff --git a/src/Pages/Top.elm b/src/Pages/Top.elm index 301e262..3fddd23 100644 --- a/src/Pages/Top.elm +++ b/src/Pages/Top.elm @@ -1,17 +1,17 @@ module Pages.Top exposing (Model, Msg, Params, page) -import Html exposing (Html, button, div, h2, h5, img, text, ul, li, a, p, span, i) -import Html.Attributes exposing (src, style, class, alt, href) +import Html exposing (Html, a, button, div, h2, h5, i, img, li, p, span, text, ul) +import Html.Attributes exposing (alt, class, href, src, style) import Html.Events exposing (onClick) import Http -import Maybe exposing (withDefault) import Json.Decode as Decode import Json.Decode.Extra as Decode exposing (andMap) -import Spa.Generated.Route as Route +import Maybe exposing (withDefault) import Spa.Document exposing (Document) +import Spa.Generated.Route as Route import Spa.Page as Page exposing (Page) import Spa.Url as Url exposing (Url) -import Util exposing (by, andThen, Direction(..)) +import Util exposing (Direction(..), andThen, by) page : Page Params Model Msg @@ -23,12 +23,15 @@ page = , subscriptions = subscriptions } + + -- INIT type alias Params = () + type alias App = { name : String , category : String @@ -55,7 +58,9 @@ init { params } = default_image : String -default_image = "/logo.png" +default_image = + "/logo.png" + -- UPDATE @@ -103,6 +108,7 @@ body model = [ viewApps model ] + viewStatusBadge : App -> Html Msg viewStatusBadge app = let @@ -110,17 +116,22 @@ viewStatusBadge app = case app.status of 1 -> "badge-success" + 2 -> "badge-info" + 3 -> "badge-warning" + 4 -> "badge-danger" + _ -> "badge-dark" in - span [ class ("card-link badge " ++ status_class) ] - [ text ("Score: " ++ String.fromInt app.status) ] + span [ class ("card-link badge " ++ status_class) ] + [ text ("Score: " ++ String.fromInt app.status) ] + viewApp : App -> Html Msg viewApp app = @@ -129,53 +140,63 @@ viewApp app = case app.icon of Just "" -> default_image + Just i -> i + Nothing -> default_image + repository_link = case app.repository of Just link -> a [ class "card-link", href link ] - [ - i [ class "fab fa-git-alt" ] [] - , text "code" + [ i [ class "fab fa-git-alt" ] [] + , text "code" ] + Nothing -> text "" + website_link = case app.website of Just link -> case link of "" -> text "" + _ -> a [ class "card-link", href link ] [ i [ class "fas fa-home" ] [] - , text "homepage" ] + , text "homepage" + ] + Nothing -> text "" - app_href = Route.toString <| Route.App_String { app = app.slug } - in - div [ class "col-md-4 mb-3 col-sm-12" ] - [ div [ class "card" ] - [ img [ class "card-img-top", src icon_url, alt ("icon for " ++ app.name) ] [] - , div [ class "card-body" ] - [ h5 [ class "card-title" ] - [ a [ href app_href ] [ text app.name ] ] - , p [] [ text (withDefault "" app.description) ] - , repository_link - , website_link - , a [ class "card-link", href app_href ] - [ i [ class "fas fa-book" ] [] - , text "docs" ] - ] - , div [ class "card-footer" ] - [ span [ class "card-link badge badge-secondary" ] [ text app.category ] - , viewStatusBadge app + + app_href = + Route.toString <| Route.App_String { app = app.slug } + in + div [ class "col-md-4 mb-3 col-sm-12" ] + [ div [ class "card" ] + [ img [ class "card-img-top", src icon_url, alt ("icon for " ++ app.name) ] [] + , div [ class "card-body" ] + [ h5 [ class "card-title" ] + [ a [ href app_href ] [ text app.name ] ] + , p [] [ text (withDefault "" app.description) ] + , repository_link + , website_link + , a [ class "card-link", href app_href ] + [ i [ class "fas fa-book" ] [] + , text "docs" ] ] + , div [ class "card-footer" ] + [ span [ class "card-link badge badge-secondary" ] [ text app.category ] + , viewStatusBadge app + ] ] + ] viewApps : Model -> Html Msg @@ -192,19 +213,25 @@ viewApps model = Loading -> div [ class "d-flex align-items-center", style "height" "89vh" ] [ div [ class "spinner-border m-auto text-light" ] - [ - span [ class "sr-only" ] [ text "Loading..." ] + [ span [ class "sr-only" ] [ text "Loading..." ] ] ] + Success apps -> div [] [ div [ class "row" ] - (List.map viewApp (apps |> List.sortWith - (by .status ASC - |> andThen (String.toLower << .name) ASC)) - ) + (List.map viewApp + (apps + |> List.sortWith + (by .status ASC + |> andThen (String.toLower << .name) ASC + ) + ) + ) ] + + -- HTTP @@ -215,12 +242,12 @@ loadApps = , expect = Http.expectJson GotApps appListDecoder } + featuresDecoder = - (Decode.oneOf + Decode.oneOf [ Decode.at [ "status" ] Decode.int , Decode.succeed 5 ] - ) appDecoder : Decode.Decoder App @@ -244,6 +271,6 @@ appListDecoder = |> Decode.map buildApp -buildApp : List (String, App) -> (List App) +buildApp : List ( String, App ) -> List App buildApp apps = - List.map (\(slug, app) -> { app | slug = slug}) apps + List.map (\( slug, app ) -> { app | slug = slug }) apps