Add some parsing stuff to finished/ for Tag

This commit is contained in:
Richard Feldman
2018-05-04 19:30:58 -04:00
parent 82e848ba97
commit 2bd0c78583
24 changed files with 2565 additions and 48 deletions

View File

@@ -3,15 +3,12 @@ module Data.Article
( Article
, Body
, Slug
, Tag
, bodyToHtml
, bodyToMarkdownString
, decoder
, decoderWithBody
, slugParser
, slugToString
, tagDecoder
, tagToString
)
import Data.Article.Author as Author exposing (Author)
@@ -110,24 +107,6 @@ slugToString (Slug slug) =
-- TAGS --
type Tag
= Tag String
tagToString : Tag -> String
tagToString (Tag slug) =
slug
tagDecoder : Decoder Tag
tagDecoder =
Decode.map Tag Decode.string
-- BODY --

View File

@@ -0,0 +1,55 @@
module Data.Article.Tag
exposing
( Tag
, decoder
, encode
, listParser
, toString
)
import Json.Decode as Decode exposing (Decoder)
import Json.Encode as Encode exposing (Value)
import Parser exposing ((|.), (|=), Parser, end, ignore, keep, oneOrMore, repeat, zeroOrMore)
type Tag
= Tag String
toString : Tag -> String
toString (Tag str) =
str
encode : Tag -> Value
encode (Tag str) =
Encode.string str
decoder : Decoder Tag
decoder =
Decode.map Tag Decode.string
listParser : Parser (List Tag)
listParser =
Parser.succeed (List.map Tag)
|. ignore zeroOrMore isWhitespace
|= repeat zeroOrMore tag
|. end
-- INTERNAL --
tag : Parser String
tag =
keep oneOrMore (\char -> not (isWhitespace char))
|. ignore zeroOrMore isWhitespace
isWhitespace : Char -> Bool
isWhitespace char =
-- Treat hashtags and commas as effectively whitespace; ignore them.
char == '#' || char == ',' || char == ' '

View File

@@ -1,6 +1,7 @@
module Page.Article.Editor exposing (Model, Msg, initEdit, initNew, update, view)
import Data.Article as Article exposing (Article, Body)
import Data.Article.Tag as Tag exposing (Tag)
import Data.Session exposing (Session)
import Data.User exposing (User)
import Html exposing (..)
@@ -8,6 +9,7 @@ import Html.Attributes exposing (attribute, class, defaultValue, disabled, href,
import Html.Events exposing (onInput, onSubmit)
import Http
import Page.Errored exposing (PageLoadError, pageLoadError)
import Parser
import Request.Article
import Route
import Task exposing (Task)
@@ -26,7 +28,7 @@ type alias Model =
, title : String
, body : String
, description : String
, tags : List String
, tags : String
, isSaving : Bool
}
@@ -38,7 +40,7 @@ initNew =
, title = ""
, body = ""
, description = ""
, tags = []
, tags = ""
, isSaving = False
}
@@ -60,7 +62,7 @@ initEdit session slug =
, title = article.title
, body = Article.bodyToMarkdownString article.body
, description = article.description
, tags = article.tags
, tags = String.join " " article.tags
, isSaving = False
}
)
@@ -121,7 +123,7 @@ viewForm model =
, Form.input
[ placeholder "Enter tags"
, onInput SetTags
, defaultValue (String.join " " model.tags)
, defaultValue model.tags
]
[]
, button [ class "btn btn-lg pull-xs-right btn-primary", disabled model.isSaving ]
@@ -152,10 +154,24 @@ update user msg model =
[] ->
case model.editingArticle of
Nothing ->
user.token
|> Request.Article.create model
|> Http.send CreateCompleted
|> pair { model | errors = [], isSaving = True }
case Parser.run Tag.listParser model.tags of
Ok tags ->
let
request =
Request.Article.create
{ tags = tags
, title = model.title
, body = model.body
, description = model.description
}
user.token
in
request
|> Http.send CreateCompleted
|> pair { model | errors = [], isSaving = True }
Err _ ->
( { model | errors = [ ( Tags, "Invalid tags." ) ] }, Cmd.none )
Just slug ->
user.token
@@ -173,7 +189,7 @@ update user msg model =
( { model | description = description }, Cmd.none )
SetTags tags ->
( { model | tags = tagsFromString tags }, Cmd.none )
( { model | tags = tags }, Cmd.none )
SetBody body ->
( { model | body = body }, Cmd.none )
@@ -217,6 +233,7 @@ type Field
= Form
| Title
| Body
| Tags
type alias Error =
@@ -235,14 +252,6 @@ modelValidator =
-- INTERNAL --
tagsFromString : String -> List String
tagsFromString str =
str
|> String.split " "
|> List.map String.trim
|> List.filter (not << String.isEmpty)
redirectToArticle : Article.Slug -> Cmd msg
redirectToArticle =
Route.modifyUrl << Route.Article

View File

@@ -3,7 +3,7 @@ module Page.Home exposing (Model, Msg, init, update, view)
{-| The homepage. You can get here via either the / or /#/ routes.
-}
import Data.Article as Article exposing (Tag)
import Data.Article.Tag as Tag exposing (Tag)
import Data.Session exposing (Session)
import Html exposing (..)
import Html.Attributes exposing (attribute, class, classList, href, id, placeholder)
@@ -100,7 +100,7 @@ viewTag tagName =
, href "javascript:void(0)"
, onClick (SelectTag tagName)
]
[ text (Article.tagToString tagName) ]
[ text (Tag.toString tagName) ]

View File

@@ -14,8 +14,9 @@ module Request.Article
, update
)
import Data.Article as Article exposing (Article, Body, Tag, slugToString)
import Data.Article as Article exposing (Article, Body, slugToString)
import Data.Article.Feed as Feed exposing (Feed)
import Data.Article.Tag as Tag exposing (Tag)
import Data.AuthToken exposing (AuthToken, withAuthorization)
import Data.User as User exposing (Username)
import Http
@@ -68,7 +69,7 @@ defaultListConfig =
list : ListConfig -> Maybe AuthToken -> Http.Request Feed
list config maybeToken =
[ ( "tag", Maybe.map Article.tagToString config.tag )
[ ( "tag", Maybe.map Tag.toString config.tag )
, ( "author", Maybe.map User.usernameToString config.author )
, ( "favorited", Maybe.map User.usernameToString config.favorited )
, ( "limit", Just (toString config.limit) )
@@ -114,7 +115,7 @@ feed config token =
tags : Http.Request (List Tag)
tags =
Decode.field "tags" (Decode.list Article.tagDecoder)
Decode.field "tags" (Decode.list Tag.decoder)
|> Http.get (apiUrl "/tags")
@@ -169,7 +170,7 @@ type alias CreateConfig record =
| title : String
, description : String
, body : String
, tags : List String
, tags : List Tag
}
@@ -194,7 +195,7 @@ create config token =
[ ( "title", Encode.string config.title )
, ( "description", Encode.string config.description )
, ( "body", Encode.string config.body )
, ( "tagList", Encode.list (List.map Encode.string config.tags) )
, ( "tagList", Encode.list (List.map Tag.encode config.tags) )
]
body =

View File

@@ -1,6 +1,6 @@
module Request.Article.Comments exposing (delete, list, post)
import Data.Article as Article exposing (Article, Tag, slugToString)
import Data.Article as Article exposing (Article, slugToString)
import Data.Article.Comment as Comment exposing (Comment, CommentId)
import Data.AuthToken exposing (AuthToken, withAuthorization)
import Http

View File

@@ -16,8 +16,9 @@ overkill, so we use simpler APIs instead.
-}
import Data.Article as Article exposing (Article, Tag)
import Data.Article as Article exposing (Article)
import Data.Article.Feed exposing (Feed)
import Data.Article.Tag as Tag exposing (Tag)
import Data.AuthToken exposing (AuthToken)
import Data.Session exposing (Session)
import Data.User exposing (Username)
@@ -126,7 +127,7 @@ sourceName source =
"Global Feed"
TagFeed tagName ->
"#" ++ Article.tagToString tagName
"#" ++ Tag.toString tagName
FavoritedFeed username ->
"Favorited Articles"