Remove part12

This commit is contained in:
Richard Feldman
2016-09-06 17:51:02 -07:00
parent fa3140351c
commit 6ba29d9277
11 changed files with 0 additions and 664 deletions

1
part12/.gitignore vendored
View File

@@ -1 +0,0 @@
!Auth.elm

View File

@@ -1,136 +0,0 @@
module Main exposing (..)
import Page.Home
import Page.Repository
import Navigation
import Page exposing (Page(..))
import Tuple2
import Html exposing (Html, div, h1, header, text, span)
import Html.Attributes exposing (class)
import Html.App as Html
type Model
= Home Page.Home.Model
| Repository Page.Repository.Model
| NotFound
type Msg
= HomeMsg Page.Home.Msg
| RepositoryMsg Page.Repository.Msg
main : Program Never
main =
Navigation.program (Navigation.makeParser Page.parser)
{ init = init
, subscriptions = subscriptions
, view = view
, update = update
, urlUpdate = urlUpdate
}
subscriptions : Model -> Sub Msg
subscriptions model =
case model of
Home pageModel ->
-- TODO use Sub.map to translate from Page.Home.subscriptions
Sub.none
Repository pageModel ->
-- Repository has no subscriptions, so there's nothing to translate!
Sub.none
NotFound ->
-- NotFound has no subscriptions, so there's nothing to translate!
Sub.none
init : Result String Page -> ( Model, Cmd Msg )
init result =
case result of
Ok (Page.Home) ->
-- TODO use Html.map to translate from Page.Home.view
( NotFound, Cmd.none )
Ok (Page.Repository repoOwner repoName) ->
-- TODO use Html.map to translate from Page.Repository.view
( NotFound, Cmd.none )
Ok (Page.NotFound) ->
( NotFound, Cmd.none )
Err err ->
( NotFound, Cmd.none )
view : Model -> Html Msg
view model =
withHeader <|
case model of
Home pageModel ->
-- TODO use Html.map to translate from Page.Home.view
text "Nothing to see here yet. Still need to translate Home!"
Repository pageModel ->
-- TODO use Html.map to translate from Page.Repository.view
text "Nothing to see here yet. Still need to translate Repository!"
NotFound ->
h1 [] [ text "Page Not Found" ]
withHeader : Html msg -> Html msg
withHeader innerContent =
div [ class "content" ]
[ header []
[ h1 [] [ text "ElmHub" ]
, span [ class "tagline" ] [ text "Like GitHub, but for Elm things." ]
]
, innerContent
]
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case ( msg, model ) of
( HomeMsg pageMsg, Home pageModel ) ->
-- TODO use Tuple2.mapEach and (Cmd.map HomeMsg)
-- to translate from Page.Home.update
--
-- mapEach : (a -> newA) -> (b -> newB) -> ( a, b ) -> ( newA, newB )
( model, Cmd.none )
( RepositoryMsg pageMsg, Repository pageModel ) ->
-- TODO use Tuple2.mapEach and (Cmd.map RepositoryMsg)
-- to translate from Page.Repository.update
( model, Cmd.none )
_ ->
( model, Cmd.none )
urlUpdate : Result String Page -> Model -> ( Model, Cmd Msg )
urlUpdate result model =
case result of
Ok (Page.Home) ->
-- TODO use Tuple2.mapEach and (Cmd.map HomeMsg)
-- to translate from Page.Home.init
--
-- mapEach : (a -> newA) -> (b -> newB) -> ( a, b ) -> ( newA, newB )
( model, Cmd.none )
Ok (Page.Repository repoOwner repoName) ->
-- TODO use Tuple2.mapEach and (Cmd.map RepositoryMsg)
-- to translate from Page.Repository.init
--
-- HINT: Page.Repository.init is a function that takes 2 arguments.
( model, Cmd.none )
Ok (Page.NotFound) ->
( NotFound, Cmd.none )
Err err ->
( NotFound, Cmd.none )

View File

@@ -1,26 +0,0 @@
module Page exposing (..)
import Navigation
import UrlParser exposing (Parser, (</>), format, int, s, string)
import String
type Page
= Home
| Repository String String
| NotFound
pageParser : Parser (Page -> a) a
pageParser =
UrlParser.oneOf
[ format Home (s "")
, format Repository (s "repositories" </> string </> string)
]
parser : Navigation.Location -> Result String Page
parser location =
location.pathname
|> String.dropLeft 1
|> UrlParser.parse identity pageParser

View File

@@ -1,166 +0,0 @@
port module Page.Home exposing (..)
import Html exposing (..)
import Html.Attributes exposing (class, target, href, property, defaultValue)
import Html.Events exposing (..)
import Auth
import Json.Decode exposing (Decoder)
import Json.Decode.Pipeline exposing (decode, required)
import Navigation
type alias SearchResult =
{ id : Int
, name : String
, stars : Int
}
searchResultDecoder : Decoder SearchResult
searchResultDecoder =
decode SearchResult
|> required "id" Json.Decode.int
|> required "full_name" Json.Decode.string
|> required "stargazers_count" Json.Decode.int
getQueryString : String -> String
getQueryString query =
-- See https://developer.github.com/v3/search/#example for how to customize!
"access_token="
++ Auth.token
++ "&q="
++ query
++ "+language:elm&sort=stars&order=desc"
responseDecoder : Decoder (List SearchResult)
responseDecoder =
Json.Decode.at [ "items" ] (Json.Decode.list searchResultDecoder)
type alias Model =
{ query : String
, results : List SearchResult
, errorMessage : Maybe String
}
initialQuery : String
initialQuery =
"tutorial"
init : ( Model, Cmd Msg )
init =
( { query = initialQuery
, results = []
, errorMessage = Nothing
}
, githubSearch (getQueryString initialQuery)
)
view : Model -> Html Msg
view model =
div []
[ input [ class "search-query", onInput SetQuery, defaultValue model.query ] []
, button [ class "search-button", onClick Search ] [ text "Search" ]
, viewErrorMessage model.errorMessage
, ul [ class "results" ] (List.map viewSearchResult model.results)
]
viewErrorMessage : Maybe String -> Html a
viewErrorMessage errorMessage =
case errorMessage of
Just message ->
div [ class "error" ] [ text message ]
Nothing ->
text ""
viewSearchResult : SearchResult -> Html Msg
viewSearchResult result =
li []
[ span [ class "star-count" ] [ text (toString result.stars) ]
, a [ onClick (Visit ("/repositories/" ++ result.name)) ]
[ text result.name ]
, button [ class "hide-result", onClick (DeleteById result.id) ]
[ text "X" ]
]
type Msg
= Search
| Visit String
| SetQuery String
| DeleteById Int
| HandleSearchResponse (List SearchResult)
| HandleSearchError (Maybe String)
| DoNothing
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
Visit url ->
( model, Navigation.newUrl url )
Search ->
( model, githubSearch (getQueryString model.query) )
SetQuery query ->
( { model | query = query }, Cmd.none )
HandleSearchResponse results ->
( { model | results = results }, Cmd.none )
HandleSearchError error ->
( { model | errorMessage = error }, Cmd.none )
DeleteById idToHide ->
let
newResults =
model.results
|> List.filter (\{ id } -> id /= idToHide)
newModel =
{ model | results = newResults }
in
( newModel, Cmd.none )
DoNothing ->
( model, Cmd.none )
decodeGithubResponse : Json.Decode.Value -> Msg
decodeGithubResponse value =
case Json.Decode.decodeValue responseDecoder value of
Ok results ->
HandleSearchResponse results
Err err ->
HandleSearchError (Just err)
decodeResponse : Json.Decode.Value -> Msg
decodeResponse json =
case Json.Decode.decodeValue responseDecoder json of
Err err ->
HandleSearchError (Just err)
Ok results ->
HandleSearchResponse results
subscriptions : Model -> Sub Msg
subscriptions _ =
githubResponse decodeResponse
port githubSearch : String -> Cmd msg
port githubResponse : (Json.Decode.Value -> msg) -> Sub msg

View File

@@ -1,136 +0,0 @@
module Page.Repository exposing (..)
import Html exposing (..)
import Html.Attributes exposing (class, target, href, property, defaultValue, src)
import Auth
import Http
import Task
import Json.Decode exposing (Decoder, int, string, list)
import Json.Decode.Pipeline exposing (decode, required)
type alias Model =
{ repoOwner : String
, repoName : String
, repository : Maybe Repository
}
type alias Repository =
{ id : Int
, issues : Int
, forks : Int
, watchers : Int
, owner : User
, description : String
}
type alias User =
{ id : Int
, username : String
, avatarUrl : String
, profileUrl : String
}
userDecoder : Decoder User
userDecoder =
decode User
|> required "id" int
|> required "login" string
|> required "avatar_url" string
|> required "url" string
repoDecoder : Decoder Repository
repoDecoder =
decode Repository
|> required "id" int
|> required "open_issues_count" int
|> required "forks" int
|> required "watchers" int
|> required "owner" userDecoder
|> required "description" string
init : String -> String -> ( Model, Cmd Msg )
init repoOwner repoName =
( { repoOwner = repoOwner
, repoName = repoName
, repository = Nothing
}
, getRepoInfo repoOwner repoName
)
view : Model -> Html Msg
view model =
let
ownerUrl =
"https://github.com/" ++ model.repoOwner
repoUrl =
ownerUrl ++ "/" ++ model.repoName
details =
model.repository
|> Maybe.map viewDetails
|> Maybe.withDefault (text "")
in
div []
[ h2 []
[ a [ href repoUrl ] [ text model.repoName ] ]
, details
]
viewDetails : Repository -> Html Msg
viewDetails repo =
div []
[ p [ class "repo-description" ] [ text repo.description ]
, h3 []
[ a [ href repo.owner.profileUrl ]
[ img [ class "profile-photo", src repo.owner.avatarUrl ] []
, text repo.owner.username
]
]
, table []
[ tbody []
[ tr [] [ th [] [ text "issues" ], td [] [ text (toString repo.issues) ] ]
, tr [] [ th [] [ text "forks" ], td [] [ text (toString repo.forks) ] ]
, tr [] [ th [] [ text "watchers" ], td [] [ text (toString repo.watchers) ] ]
]
]
]
type Msg
= HandleRepoError Http.Error
| HandleRepoResponse Repository
getRepoInfo : String -> String -> Cmd Msg
getRepoInfo repoOwner repoName =
let
url =
"https://api.github.com/repos/"
++ repoOwner
++ "/"
++ repoName
++ "?access_token="
++ Auth.token
|> Debug.log "getRepoInfo"
in
Http.get repoDecoder url
|> Task.perform HandleRepoError HandleRepoResponse
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
HandleRepoError err ->
( model, Cmd.none )
HandleRepoResponse repository ->
( { model | repository = Just repository }, Cmd.none )

View File

@@ -1,21 +0,0 @@
Part 10
=======
## Installation
```bash
elm-package install
```
(Answer `y` when prompted.)
## Building
```bash
elm-live Main.elm --open --pushstate --output=elm.js
```
## References
* [Navigation package documentation](http://package.elm-lang.org/packages/elm-lang/navigation/latest)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -1,21 +0,0 @@
{
"version": "1.0.0",
"summary": "Like GitHub, but for Elm stuff.",
"repository": "https://github.com/rtfeldman/elm-workshop.git",
"license": "BSD-3-Clause",
"source-directories": [
".",
".."
],
"exposed-modules": [],
"dependencies": {
"Fresheyeball/elm-tuple-extra": "2.1.0 <= v < 3.0.0",
"NoRedInk/elm-decode-pipeline": "1.1.2 <= v < 2.0.0",
"elm-lang/core": "4.0.1 <= v < 5.0.0",
"elm-lang/html": "1.0.0 <= v < 2.0.0",
"elm-lang/navigation": "1.0.0 <= v < 2.0.0",
"evancz/elm-http": "3.0.1 <= v < 4.0.0",
"evancz/url-parser": "1.0.0 <= v < 2.0.0"
},
"elm-version": "0.17.0 <= v < 0.18.0"
}

File diff suppressed because one or more lines are too long

View File

@@ -1,32 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>ElmHub</title>
<script type="text/javascript" src="/github.js"></script>
<script type="text/javascript" src="/elm.js"></script>
<link rel="stylesheet" href="/style.css">
<link rel="icon" type="image/png" href="/elm-hub.png">
</head>
<body>
<div id="elm-landing-pad"></div>
</body>
<script type="text/javascript">
// documentation: https://github.com/michael/github
var github = new Github();
var app = Elm.Main.embed(document.getElementById("elm-landing-pad"));
function searchGithub(query) {
github.getSearch(query).repositories({}, function (err, repositories) {
app.ports.githubResponse.send(repositories);
});
}
app.ports.githubSearch.subscribe(searchGithub);
</script>
</html>

View File

@@ -1,123 +0,0 @@
.content {
width: 960px;
margin: 0 auto;
padding: 30px;
font-family: Helvetica, Arial, serif;
}
header {
position: relative;
padding: 6px 12px;
height: 36px;
background-color: rgb(96, 181, 204);
}
h1 {
color: white;
font-weight: normal;
margin: 0;
}
.tagline {
color: #eee;
position: absolute;
right: 16px;
top: 12px;
font-size: 24px;
font-style: italic;
}
.results {
list-style-image: url('http://img-cache.cdn.gaiaonline.com/76bd5c99d8f2236e9d3672510e933fdf/http://i278.photobucket.com/albums/kk81/d3m3nt3dpr3p/Tiny-Star-Icon.png');
list-style-position: inside;
padding: 0;
}
.results li {
font-size: 18px;
margin-bottom: 16px;
}
.star-count {
font-weight: bold;
margin-right: 16px;
}
a {
color: rgb(96, 181, 204);
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
.search-query {
padding: 8px;
font-size: 24px;
margin-bottom: 18px;
margin-top: 36px;
}
.search-button {
padding: 8px 16px;
font-size: 24px;
color: white;
border: 1px solid #ccc;
background-color: rgb(96, 181, 204);
margin-left: 12px
}
.search-button:hover {
color: rgb(96, 181, 204);
background-color: white;
}
.hide-result {
background-color: transparent;
border: 0;
font-weight: bold;
font-size: 18px;
margin-left: 18px;
cursor: pointer;
}
.hide-result:hover {
color: rgb(96, 181, 204);
}
button:focus, input:focus {
outline: none;
}
.error {
background-color: #FF9632;
padding: 20px;
box-sizing: border-box;
overflow-x: auto;
font-family: monospace;
font-size: 18px;
}
a {
cursor: pointer;
}
.repo-description {
font-size: 18px;
}
.profile-photo {
width: 32px;
margin-right: 10px;
}
th {
text-align: left;
}
th, td {
font-size: 18px;
padding-right: 20px;
}