App detail page, stylin', icons

This commit is contained in:
3wc 2021-04-20 01:31:11 +02:00
parent e932010e81
commit cc3ee90f0b
5 changed files with 263 additions and 16 deletions

View File

@ -11,9 +11,12 @@
"elm/html": "1.0.0",
"elm/http": "2.0.0",
"elm/json": "1.1.3",
"elm/url": "1.0.0"
"elm/url": "1.0.0",
"pablohirafuji/elm-markdown": "2.0.5"
},
"indirect": {
"elm/bytes": "1.0.8",
"elm/file": "1.0.5",
"elm/time": "1.0.0",
"elm/virtual-dom": "1.0.2"
}
@ -25,8 +28,6 @@
},
"indirect": {
"avh4/elm-fifo": "1.0.4",
"elm/bytes": "1.0.8",
"elm/file": "1.0.5",
"elm/random": "1.0.0"
}
}

View File

@ -6,7 +6,10 @@
<!-- CSS goes here -->
<link rel="stylesheet" href="/style.css">
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
<!--<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.3/css/fontawesome.min.css">-->
<script src="https://kit.fontawesome.com/60c2d44730.js" crossorigin="anonymous"></script>
</head>
<body>
<!-- JavaScript goes here -->

View File

@ -1,8 +1,17 @@
body {
}
.container-fluid {
min-height: 92vh;
}
.card-img-top {
width: 100%;
height: 8vw;
object-fit: cover;
}
i.fa, i.fab {
display: inline-block;
margin-right: 0.3rem;
}

228
src/Pages/App_String.elm Normal file
View File

@ -0,0 +1,228 @@
module Pages.App_String exposing (Model, Msg, Params, page)
import Html exposing (Html, button, div, h2, h5, img, text, ul, li, a, p, span)
import Html.Attributes exposing (src, style, class, alt, href)
import Html.Events exposing (onClick)
import Http
import Markdown
import Json.Decode as Decode
import Spa.Document exposing (Document)
import Spa.Page as Page exposing (Page)
import Spa.Url as Url exposing (Url)
page : Page Params Model Msg
page =
Page.element
{ init = init
, update = update
, view = view
, subscriptions = subscriptions
}
-- INIT
type alias Params =
{ app : String
}
type alias App =
{ name : String
, category : String
, repository : Maybe String
, versions : Maybe (List String)
, icon : Maybe String
, status : String
}
type alias Model =
{ url : Url Params
, status : Status
, readme : String
}
type Status
= Failure
| Loading
| Success App
init : Url Params -> ( Model, Cmd Msg )
init url =
( { url = url, status = Loading, readme = "" }, loadData )
default_image : String
default_image = "http://localhost:8000/logo.png"
-- UPDATE
type Msg
= MorePlease
| GotApps (Result Http.Error (List App))
| GotText (Result Http.Error String)
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
MorePlease ->
( { model | status = Loading }, loadData )
GotApps result ->
case result of
Ok apps ->
let
apps_filtered = List.filter (\app -> app.name == model.url.params.app) apps
in
case List.head apps_filtered of
Nothing ->
( { model | status = Failure }, Cmd.none )
Just item ->
( { model | status = Success (item) }, Cmd.none )
Err _ ->
( { model | status = Failure }, Cmd.none )
GotText result ->
case result of
Ok content ->
( { model | readme = content }, Cmd.none )
Err _ ->
( { model | status = Failure }, Cmd.none )
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.none
-- VIEW
view : Model -> Document Msg
view model =
{ title = "abra app"
, body = [ body model ]
}
body : Model -> Html Msg
body model =
div [ class "pt-3" ]
[ case model.status of
Failure ->
div [ ]
[ text "I could not load a random cat for some reason. "
, button [ onClick MorePlease ] [ text "Try Again!" ]
]
Loading ->
text "Loading..."
Success app ->
div []
[ div [ class "row" ]
[ viewApp app model.readme ]
]
]
viewStatusBadge : App -> Html Msg
viewStatusBadge app =
let
status_class =
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: " ++ app.status) ]
viewApp : App -> String -> Html Msg
viewApp app readme =
let
icon_url =
case app.icon of
Just "" ->
default_image
Just i ->
i
Nothing ->
default_image
repository_link =
case app.repository of
Just i ->
a [ class "card-link", href i ] [ text "code" ]
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" ]
[ span [ class "card-link badge badge-secondary" ] [ text app.category ]
, viewStatusBadge app
, repository_link
, a [ class "card-link", href "http://example.com" ] [ text "homepage" ]
]
, img [ class "card-img-top", src icon_url, alt ("icon for " ++ app.name) ] []
, div [ class "card-body" ]
[ div [] (Markdown.toHtml Nothing readme)
]
, div [ class "card-footer" ]
[]
]
]
-- HTTP
loadData : Cmd Msg
loadData =
Cmd.batch
[ Http.get
{ url = "http://localhost:8000/abra-apps-list.json"
, expect = Http.expectJson GotApps appListDecoder }
, Http.get
{ url = "http://localhost:1234/coop-cloud/adapt_authoring/raw/branch/main/README.md"
, expect = Http.expectString GotText }
]
featuresDecoder =
(Decode.oneOf
[ Decode.at [ "status" ] Decode.string
, Decode.succeed ""
]
)
appDecoder : Decode.Decoder App
appDecoder =
Decode.map6
App
(Decode.field "name" Decode.string)
(Decode.field "category" Decode.string)
(Decode.maybe (Decode.field "repository" Decode.string))
(Decode.succeed Nothing)
(Decode.maybe (Decode.field "icon" Decode.string))
(Decode.at [ "features" ] featuresDecoder)
appListDecoder : Decode.Decoder (List App)
appListDecoder =
Decode.list appDecoder

View File

@ -1,10 +1,11 @@
module Pages.Top exposing (Model, Msg, Params, page)
import Html exposing (Html, button, div, h2, h5, img, text, ul, li, a, p, span)
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.Events exposing (onClick)
import Http
import Json.Decode as Decode
import Spa.Generated.Route as Route
import Spa.Document exposing (Document)
import Spa.Page as Page exposing (Page)
import Spa.Url as Url exposing (Url)
@ -95,8 +96,8 @@ body model =
[ viewApps model
]
renderStatusBadge : App -> Html Msg
renderStatusBadge app =
viewStatusBadge : App -> Html Msg
viewStatusBadge app =
let
status_class =
case app.status of
@ -114,8 +115,8 @@ renderStatusBadge app =
span [ class ("card-link badge " ++ status_class) ]
[ text ("Score: " ++ app.status) ]
viewAppName : App -> Html Msg
viewAppName app =
viewApp : App -> Html Msg
viewApp app =
let
icon_url =
case app.icon of
@ -127,8 +128,12 @@ viewAppName app =
default_image
repository_link =
case app.repository of
Just i ->
a [ class "card-link", href i ] [ text "Code" ]
Just link ->
a [ class "card-link", href link ]
[
i [ class "fab fa-git-alt" ] []
, text "Code"
]
Nothing ->
text ""
in
@ -136,12 +141,13 @@ viewAppName app =
[ div [ class "card" ]
[ img [ class "card-img-top", src icon_url, alt ("icon for " ++ app.name) ] []
, div [ class "card-body" ]
[ h5 [ class "card-title" ] [ text app.name ]
, repository_link
]
[ h5 [ class "card-title" ]
[ a [ href (Route.toString <| Route.App_String { app = app.name } ) ] [ text app.name ] ]
, repository_link
]
, div [ class "card-footer" ]
[ span [ class "card-link badge badge-secondary" ] [ text app.category ]
, renderStatusBadge app
, viewStatusBadge app
]
]
]
@ -161,7 +167,7 @@ viewApps model =
Success apps ->
div []
[ div [ class "row" ]
(List.map viewAppName (List.sortBy .name apps))
(List.map viewApp (List.sortBy .name apps))
]
-- HTTP