diff --git a/intro/part4/README.md b/intro/part4/README.md new file mode 100644 index 0000000..bd69f36 --- /dev/null +++ b/intro/part4/README.md @@ -0,0 +1,21 @@ +# Part 3 + +This is just like last time, except first we'll install the `elm/browser` package so we can create an interactive app in the browser, instead of static HTML. + +To install the package, `cd` into the `part3/` directory and run: + +```shell +elm install elm/browser +``` + +Then build everything the same way as last time: + +```shell +elm make src/Main.elm --output elm.js +``` + +Finally, open `index.html` in your browser. + +## Exercise + +Open `src/Main.elm` in your editor and resolve the TODOs there. diff --git a/intro/part4/elm-package.json b/intro/part4/elm-package.json new file mode 100644 index 0000000..f5ba1c5 --- /dev/null +++ b/intro/part4/elm-package.json @@ -0,0 +1,15 @@ +{ + "version": "1.0.0", + "summary": "helpful summary of your project, less than 80 characters", + "repository": "https://github.com/user/project.git", + "license": "BSD3", + "source-directories": [ + "." + ], + "exposed-modules": [], + "dependencies": { + "elm-lang/core": "5.1.1 <= v < 6.0.0", + "elm-lang/html": "2.0.0 <= v < 3.0.0" + }, + "elm-version": "0.18.0 <= v < 0.19.0" +} diff --git a/intro/part4/elm.json b/intro/part4/elm.json new file mode 100644 index 0000000..dd41cae --- /dev/null +++ b/intro/part4/elm.json @@ -0,0 +1,24 @@ +{ + "type": "application", + "source-directories": [ + "src" + ], + "elm-version": "0.19.0", + "dependencies": { + "direct": { + "elm/browser": "1.0.0", + "elm/core": "1.0.0", + "elm/html": "1.0.0" + }, + "indirect": { + "elm/json": "1.0.0", + "elm/time": "1.0.0", + "elm/url": "1.0.0", + "elm/virtual-dom": "1.0.0" + } + }, + "test-dependencies": { + "direct": {}, + "indirect": {} + } +} \ No newline at end of file diff --git a/intro/part4/index.html b/intro/part4/index.html new file mode 100644 index 0000000..3860a04 --- /dev/null +++ b/intro/part4/index.html @@ -0,0 +1,15 @@ + + + + + Elm Workshop + + + + +
+ + + diff --git a/intro/part4/src/Article.elm b/intro/part4/src/Article.elm new file mode 100644 index 0000000..833e956 --- /dev/null +++ b/intro/part4/src/Article.elm @@ -0,0 +1,21 @@ +module Article exposing (feed, tags) + +-- For now, this module only holds hardcoded data. +-- +-- In future exercises, it will read data from the server! + + +tags = + [ "elm" + , "fun" + , "programming" + , "dragons" + ] + + +feed = + [ { title = "Elm is fun!", description = "Elm", body = "I've really been enjoying it!", tags = [ "elm", "fun" ], slug = "elm-is-fun--zb6nba" } + , { title = "Who says undefined isn't a function anyway?", description = "Functions", body = "Quite frankly I think undefined can be anything it wants to be,if it believes in itself.", slug = "who-says-undefined-isnt-a-function-anyway-t39ope", tags = [ "programming" ] } + , { title = "This compiler is pretty neat", description = "Elm", body = "It tells me about problems in my code. How neat is that?", tags = [ "compilers", "elm" ], slug = "this-compiler-is-pretty-neat-9ycui8" } + , { title = "Are dragons real?", description = "dragons", body = "Do Komodo Dragons count? I think they should. It's right there in the name!", tags = [ "dragons" ], slug = "are-dragons-real-467lsh" } + ] diff --git a/intro/part4/src/Main.elm b/intro/part4/src/Main.elm new file mode 100644 index 0000000..ba447ff --- /dev/null +++ b/intro/part4/src/Main.elm @@ -0,0 +1,148 @@ +module Main exposing (main) + +import Article +import Browser +import Html exposing (..) +import Html.Attributes exposing (..) +import Html.Events exposing (onClick) + + +-- MODEL + + +type alias Model = + { tags : List String + , selectedTag : String + + {- 👉 TODO: change this `allArticles` annotation to the following: + + allArticles : List Article + + + 💡 HINT: You'll need to move the existing annotation to a `type alias`. + -} + , allArticles : + List + { title : String + , description : String + , body : String + , tags : List String + , slug : String + } + } + + +{-| 👉 TODO: Replace this comment with a type annotation for `initialModel` +-} +initialModel = + { tags = Article.tags + , selectedTag = "elm" + , allArticles = Article.feed + } + + + +-- UPDATE + + +type alias Msg = + { description : String + , data : String + } + + +{-| 👉 TODO: Replace this comment with a type annotation for `update` +-} +update msg model = + if msg.description == "ClickedTag" then + { model | selectedTag = msg.data } + else + model + + + +-- VIEW + + +{-| 👉 TODO: Replace this comment with a type annotation for `view` +-} +view model = + let + articles = + List.filter (\article -> List.member model.selectedTag article.tags) + model.allArticles + + feed = + List.map viewArticle articles + in + div [ class "home-page" ] + [ viewBanner + , div [ class "container page" ] + [ div [ class "row" ] + [ div [ class "col-md-9" ] feed + , div [ class "col-md-3" ] + [ div [ class "sidebar" ] + [ p [] [ text "Popular Tags" ] + , viewTags model + ] + ] + ] + ] + ] + + +{-| 👉 TODO: Replace this comment with a type annotation for `view` +-} +viewArticle article = + div [ class "article-preview" ] + [ h1 [] [ text article.title ] + , p [] [ text article.description ] + , span [] [ text "Read more..." ] + ] + + +{-| 👉 TODO: Replace this comment with a type annotation for `view` +-} +viewBanner : Html Msg +viewBanner = + div [ class "banner" ] + [ div [ class "container" ] + [ h1 [ class "logo-font" ] [ text "conduit" ] + , p [] [ text "A place to share your knowledge." ] + ] + ] + + +{-| 👉 TODO: Replace this comment with a type annotation for `view` +-} +viewTag selectedTagName tagName = + let + otherClass = + if tagName == selectedTagName then + "tag-selected" + else + "tag-default" + in + button + [ class ("tag-pill " ++ otherClass) + , onClick { description = "ClickedTag", data = tagName } + ] + [ text tagName ] + + +viewTags : Model -> Html Msg +viewTags model = + div [ class "tag-list" ] (List.map (viewTag model.selectedTag) model.tags) + + + +-- MAIN + + +main : Program () Model Msg +main = + Browser.sandbox + { init = initialModel + , view = view + , update = update + }