mirror of
https://github.com/aelve/guide.git
synced 2024-12-23 21:02:13 +03:00
Rename pros/cons to traits
This commit is contained in:
parent
88ad776ae4
commit
dd47e83637
151
src/Main.hs
151
src/Main.hs
@ -50,26 +50,26 @@ type Uid = Int
|
|||||||
randomUid :: MonadIO m => m Uid
|
randomUid :: MonadIO m => m Uid
|
||||||
randomUid = liftIO $ randomRIO (0, 10^(9::Int))
|
randomUid = liftIO $ randomRIO (0, 10^(9::Int))
|
||||||
|
|
||||||
data ProCon = ProCon {
|
data Trait = Trait {
|
||||||
_proConUid :: Uid,
|
_traitUid :: Uid,
|
||||||
_proConContent :: Text }
|
_traitContent :: Text }
|
||||||
|
|
||||||
makeFields ''ProCon
|
makeFields ''Trait
|
||||||
|
|
||||||
data ItemKind = HackageLibrary | Library | Unknown
|
data ItemKind = HackageLibrary | Library | Unknown
|
||||||
|
|
||||||
data Item = Item {
|
data Item = Item {
|
||||||
_itemUid :: Uid,
|
_itemUid :: Uid,
|
||||||
_itemName :: Text,
|
_itemName :: Text,
|
||||||
_itemPros :: [ProCon],
|
_itemPros :: [Trait],
|
||||||
_itemCons :: [ProCon],
|
_itemCons :: [Trait],
|
||||||
_itemLink :: Maybe Url,
|
_itemLink :: Maybe Url,
|
||||||
_itemKind :: ItemKind }
|
_itemKind :: ItemKind }
|
||||||
|
|
||||||
makeFields ''Item
|
makeFields ''Item
|
||||||
|
|
||||||
proConById :: Uid -> Lens' Item ProCon
|
traitById :: Uid -> Lens' Item Trait
|
||||||
proConById uid' = singular $
|
traitById uid' = singular $
|
||||||
(pros.each . filtered ((== uid') . view uid)) `failing`
|
(pros.each . filtered ((== uid') . view uid)) `failing`
|
||||||
(cons.each . filtered ((== uid') . view uid))
|
(cons.each . filtered ((== uid') . view uid))
|
||||||
|
|
||||||
@ -103,17 +103,17 @@ sampleState = do
|
|||||||
let lensItem = Item {
|
let lensItem = Item {
|
||||||
_itemUid = 12,
|
_itemUid = 12,
|
||||||
_itemName = "lens",
|
_itemName = "lens",
|
||||||
_itemPros = [ProCon 121 "the standard lenses library",
|
_itemPros = [Trait 121 "the standard lenses library",
|
||||||
ProCon 122 "batteries included"],
|
Trait 122 "batteries included"],
|
||||||
_itemCons = [ProCon 123 "huge"],
|
_itemCons = [Trait 123 "huge"],
|
||||||
_itemLink = Nothing,
|
_itemLink = Nothing,
|
||||||
_itemKind = HackageLibrary }
|
_itemKind = HackageLibrary }
|
||||||
let microlensItem = Item {
|
let microlensItem = Item {
|
||||||
_itemUid = 13,
|
_itemUid = 13,
|
||||||
_itemName = "microlens",
|
_itemName = "microlens",
|
||||||
_itemPros = [ProCon 131 "very small",
|
_itemPros = [Trait 131 "very small",
|
||||||
ProCon 132 "good for libraries"],
|
Trait 132 "good for libraries"],
|
||||||
_itemCons = [ProCon 133 "doesn't have advanced features"],
|
_itemCons = [Trait 133 "doesn't have advanced features"],
|
||||||
_itemLink = Just "https://github.com/aelve/microlens",
|
_itemLink = Just "https://github.com/aelve/microlens",
|
||||||
_itemKind = HackageLibrary }
|
_itemKind = HackageLibrary }
|
||||||
let lensesCategory = Category {
|
let lensesCategory = Category {
|
||||||
@ -130,6 +130,9 @@ itemVar = "item" <//> var
|
|||||||
categoryVar :: Path '[Uid]
|
categoryVar :: Path '[Uid]
|
||||||
categoryVar = "category" <//> var
|
categoryVar = "category" <//> var
|
||||||
|
|
||||||
|
traitVar :: Path '[Uid]
|
||||||
|
traitVar = "trait" <//> var
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = runSpock 8080 $ spockT id $ do
|
main = runSpock 8080 $ spockT id $ do
|
||||||
middleware (staticPolicy (addBase "static"))
|
middleware (staticPolicy (addBase "static"))
|
||||||
@ -163,17 +166,17 @@ main = runSpock 8080 $ spockT id $ do
|
|||||||
item <- withGlobal $ use (itemById itemId)
|
item <- withGlobal $ use (itemById itemId)
|
||||||
renderMode <- param' "mode"
|
renderMode <- param' "mode"
|
||||||
lucid $ renderItemInfo renderMode item
|
lucid $ renderItemInfo renderMode item
|
||||||
-- Item pros-cons
|
-- All item traits
|
||||||
Spock.get (itemVar <//> "pros-cons") $ \itemId -> do
|
Spock.get (itemVar <//> "traits") $ \itemId -> do
|
||||||
item <- withGlobal $ use (itemById itemId)
|
item <- withGlobal $ use (itemById itemId)
|
||||||
renderMode <- param' "mode"
|
renderMode <- param' "mode"
|
||||||
lucid $ renderItemProsCons renderMode item
|
lucid $ renderItemTraits renderMode item
|
||||||
-- Pro/con
|
-- A single trait
|
||||||
Spock.get (itemVar <//> "pro-con" <//> var) $
|
Spock.get (itemVar <//> traitVar) $
|
||||||
\itemId thingId -> do
|
\itemId traitId -> do
|
||||||
thing <- withGlobal $ use (itemById itemId . proConById thingId)
|
trait <- withGlobal $ use (itemById itemId . traitById traitId)
|
||||||
renderMode <- param' "mode"
|
renderMode <- param' "mode"
|
||||||
lucid $ renderProCon renderMode itemId thing
|
lucid $ renderTrait renderMode itemId trait
|
||||||
|
|
||||||
-- The add/set methods return rendered parts of the structure (added
|
-- The add/set methods return rendered parts of the structure (added
|
||||||
-- categories, changed items, etc) so that the Javascript part could take
|
-- categories, changed items, etc) so that the Javascript part could take
|
||||||
@ -196,14 +199,14 @@ main = runSpock 8080 $ spockT id $ do
|
|||||||
categoryById catId . description .= content'
|
categoryById catId . description .= content'
|
||||||
use (categoryById catId)
|
use (categoryById catId)
|
||||||
lucid $ renderCategoryDescription Editable changedCategory
|
lucid $ renderCategoryDescription Editable changedCategory
|
||||||
-- Pro/con
|
-- Trait
|
||||||
Spock.post (itemVar <//> "pro-con" <//> var) $
|
Spock.post (itemVar <//> traitVar) $
|
||||||
\itemId thingId -> do
|
\itemId traitId -> do
|
||||||
content' <- param' "content"
|
content' <- param' "content"
|
||||||
changedThing <- withGlobal $ do
|
changedTrait <- withGlobal $ do
|
||||||
itemById itemId . proConById thingId . content .= content'
|
itemById itemId . traitById traitId . content .= content'
|
||||||
use (itemById itemId . proConById thingId)
|
use (itemById itemId . traitById traitId)
|
||||||
lucid $ renderProCon Editable itemId changedThing
|
lucid $ renderTrait Editable itemId changedTrait
|
||||||
|
|
||||||
-- Add methods
|
-- Add methods
|
||||||
Spock.subcomponent "add" $ do
|
Spock.subcomponent "add" $ do
|
||||||
@ -237,16 +240,16 @@ main = runSpock 8080 $ spockT id $ do
|
|||||||
Spock.post (itemVar <//> "pro") $ \itemId -> do
|
Spock.post (itemVar <//> "pro") $ \itemId -> do
|
||||||
content' <- param' "content"
|
content' <- param' "content"
|
||||||
uid' <- randomUid
|
uid' <- randomUid
|
||||||
let newThing = ProCon uid' content'
|
let newTrait = Trait uid' content'
|
||||||
withGlobal $ itemById itemId . pros %= (++ [newThing])
|
withGlobal $ itemById itemId . pros %= (++ [newTrait])
|
||||||
lucid $ renderProCon Editable itemId newThing
|
lucid $ renderTrait Editable itemId newTrait
|
||||||
-- Con (argument against a library)
|
-- Con (argument against a library)
|
||||||
Spock.post (itemVar <//> "con") $ \itemId -> do
|
Spock.post (itemVar <//> "con") $ \itemId -> do
|
||||||
content' <- param' "content"
|
content' <- param' "content"
|
||||||
uid' <- randomUid
|
uid' <- randomUid
|
||||||
let newThing = ProCon uid' content'
|
let newTrait = Trait uid' content'
|
||||||
withGlobal $ itemById itemId . cons %= (++ [newThing])
|
withGlobal $ itemById itemId . cons %= (++ [newTrait])
|
||||||
lucid $ renderProCon Editable itemId newThing
|
lucid $ renderTrait Editable itemId newTrait
|
||||||
|
|
||||||
renderRoot :: GlobalState -> HtmlT IO ()
|
renderRoot :: GlobalState -> HtmlT IO ()
|
||||||
renderRoot globalState = do
|
renderRoot globalState = do
|
||||||
@ -278,7 +281,7 @@ renderCategoryTitle editable category =
|
|||||||
textButton "cancel" $
|
textButton "cancel" $
|
||||||
js_setCategoryTitleMode (titleNode, category^.uid, Editable)
|
js_setCategoryTitleMode (titleNode, category^.uid, Editable)
|
||||||
|
|
||||||
-- TODO: render descriptions and pros/cons as Markdown
|
-- TODO: render descriptions and traits as Markdown
|
||||||
|
|
||||||
renderCategoryDescription :: Editable -> Category -> HtmlT IO ()
|
renderCategoryDescription :: Editable -> Category -> HtmlT IO ()
|
||||||
renderCategoryDescription editable category =
|
renderCategoryDescription editable category =
|
||||||
@ -311,7 +314,7 @@ renderItem :: Item -> HtmlT IO ()
|
|||||||
renderItem item =
|
renderItem item =
|
||||||
div_ [class_ "item"] $ do
|
div_ [class_ "item"] $ do
|
||||||
renderItemInfo Normal item
|
renderItemInfo Normal item
|
||||||
renderItemProsCons Normal item
|
renderItemTraits Normal item
|
||||||
|
|
||||||
renderItemInfo :: Editable -> Item -> HtmlT IO ()
|
renderItemInfo :: Editable -> Item -> HtmlT IO ()
|
||||||
renderItemInfo editable item =
|
renderItemInfo editable item =
|
||||||
@ -336,52 +339,52 @@ renderItemInfo editable item =
|
|||||||
where
|
where
|
||||||
hackageLink = "https://hackage.haskell.org/package/" <> item^.name
|
hackageLink = "https://hackage.haskell.org/package/" <> item^.name
|
||||||
|
|
||||||
renderItemProsCons :: Editable -> Item -> HtmlT IO ()
|
renderItemTraits :: Editable -> Item -> HtmlT IO ()
|
||||||
renderItemProsCons editable item =
|
renderItemTraits editable item =
|
||||||
div_ [class_ "pros-cons"] $ do
|
div_ [class_ "traits"] $ do
|
||||||
this <- thisNode
|
this <- thisNode
|
||||||
case editable of
|
case editable of
|
||||||
Normal -> textButton "edit" $
|
Normal -> textButton "edit" $
|
||||||
js_setItemProsConsMode (this, item^.uid, Editable)
|
js_setItemTraitsMode (this, item^.uid, Editable)
|
||||||
Editable -> textButton "edit off" $
|
Editable -> textButton "edit off" $
|
||||||
js_setItemProsConsMode (this, item^.uid, Normal)
|
js_setItemTraitsMode (this, item^.uid, Normal)
|
||||||
div_ [class_ "pros"] $ do
|
div_ [class_ "traits-group"] $ do
|
||||||
p_ "Pros:"
|
p_ "Pros:"
|
||||||
case editable of
|
case editable of
|
||||||
Normal ->
|
Normal ->
|
||||||
ul_ $ mapM_ (renderProCon Normal (item^.uid)) (item^.pros)
|
ul_ $ mapM_ (renderTrait Normal (item^.uid)) (item^.pros)
|
||||||
Editable -> do
|
Editable -> do
|
||||||
listNode <- ul_ $ do
|
listNode <- ul_ $ do
|
||||||
mapM_ (renderProCon Editable (item^.uid)) (item^.pros)
|
mapM_ (renderTrait Editable (item^.uid)) (item^.pros)
|
||||||
thisNode
|
thisNode
|
||||||
let handler s = js_addPro (listNode, item^.uid, s)
|
let handler s = js_addPro (listNode, item^.uid, s)
|
||||||
input_ [type_ "text", placeholder_ "add pro", submitFunc handler]
|
input_ [type_ "text", placeholder_ "add pro", submitFunc handler]
|
||||||
div_ [class_ "cons"] $ do
|
div_ [class_ "traits-group"] $ do
|
||||||
p_ "Cons:"
|
p_ "Cons:"
|
||||||
case editable of
|
case editable of
|
||||||
Normal ->
|
Normal ->
|
||||||
ul_ $ mapM_ (renderProCon Normal (item^.uid)) (item^.cons)
|
ul_ $ mapM_ (renderTrait Normal (item^.uid)) (item^.cons)
|
||||||
Editable -> do
|
Editable -> do
|
||||||
listNode <- ul_ $ do
|
listNode <- ul_ $ do
|
||||||
mapM_ (renderProCon Editable (item^.uid)) (item^.cons)
|
mapM_ (renderTrait Editable (item^.uid)) (item^.cons)
|
||||||
thisNode
|
thisNode
|
||||||
let handler s = js_addCon (listNode, item^.uid, s)
|
let handler s = js_addCon (listNode, item^.uid, s)
|
||||||
input_ [type_ "text", placeholder_ "add con", submitFunc handler]
|
input_ [type_ "text", placeholder_ "add con", submitFunc handler]
|
||||||
|
|
||||||
renderProCon :: Editable -> Uid -> ProCon -> HtmlT IO ()
|
renderTrait :: Editable -> Uid -> Trait -> HtmlT IO ()
|
||||||
renderProCon Normal _ proCon = li_ (toHtml (proCon^.content))
|
renderTrait Normal _ trait = li_ (toHtml (trait^.content))
|
||||||
renderProCon Editable itemId proCon = li_ $ do
|
renderTrait Editable itemId trait = li_ $ do
|
||||||
this <- thisNode
|
this <- thisNode
|
||||||
toHtml (proCon^.content)
|
toHtml (trait^.content)
|
||||||
textButton "edit" $
|
textButton "edit" $
|
||||||
js_setProConMode (this, itemId, proCon^.uid, InEdit)
|
js_setTraitMode (this, itemId, trait^.uid, InEdit)
|
||||||
renderProCon InEdit itemId thing = li_ $ do
|
renderTrait InEdit itemId trait = li_ $ do
|
||||||
this <- thisNode
|
this <- thisNode
|
||||||
let handler s = js_submitProConEdit
|
let handler s = js_submitTraitEdit
|
||||||
(this, itemId, thing^.uid, s)
|
(this, itemId, trait^.uid, s)
|
||||||
input_ [type_ "text", value_ (thing^.content), submitFunc handler]
|
input_ [type_ "text", value_ (trait^.content), submitFunc handler]
|
||||||
textButton "cancel" $
|
textButton "cancel" $
|
||||||
js_setProConMode (this, itemId, thing^.uid, Editable)
|
js_setTraitMode (this, itemId, trait^.uid, Editable)
|
||||||
|
|
||||||
-- Utils
|
-- Utils
|
||||||
|
|
||||||
@ -423,8 +426,6 @@ instance JSParams a => JSFunction (a -> JS) where
|
|||||||
makeJSFunction fName _ = \args ->
|
makeJSFunction fName _ = \args ->
|
||||||
fName <> "(" <> T.intercalate "," (jsParams args) <> ");"
|
fName <> "(" <> T.intercalate "," (jsParams args) <> ");"
|
||||||
|
|
||||||
-- TODO: rename pros/cons to traits
|
|
||||||
|
|
||||||
allJSFunctions :: JSFunction a => [a]
|
allJSFunctions :: JSFunction a => [a]
|
||||||
allJSFunctions = [
|
allJSFunctions = [
|
||||||
-- Utilities
|
-- Utilities
|
||||||
@ -434,11 +435,11 @@ allJSFunctions = [
|
|||||||
js_addPro, js_addCon,
|
js_addPro, js_addCon,
|
||||||
-- Render-as-editable methods
|
-- Render-as-editable methods
|
||||||
js_setCategoryTitleMode, js_setCategoryDescriptionMode,
|
js_setCategoryTitleMode, js_setCategoryDescriptionMode,
|
||||||
js_setItemInfoMode, js_setItemProsConsMode,
|
js_setItemInfoMode, js_setItemTraitsMode,
|
||||||
js_setProConMode,
|
js_setTraitMode,
|
||||||
-- Set methods
|
-- Set methods
|
||||||
js_submitCategoryTitleEdit,
|
js_submitCategoryTitleEdit,
|
||||||
js_submitProConEdit,
|
js_submitTraitEdit,
|
||||||
js_submitCategoryDescriptionEdit ]
|
js_submitCategoryDescriptionEdit ]
|
||||||
|
|
||||||
js_replaceWithData :: JSFunction a => a
|
js_replaceWithData :: JSFunction a => a
|
||||||
@ -539,26 +540,26 @@ js_setItemInfoMode = makeJSFunction "setItemInfoMode" [text|
|
|||||||
}
|
}
|
||||||
|]
|
|]
|
||||||
|
|
||||||
js_setItemProsConsMode :: JSFunction a => a
|
js_setItemTraitsMode :: JSFunction a => a
|
||||||
js_setItemProsConsMode = makeJSFunction "setItemProsConsMode" [text|
|
js_setItemTraitsMode = makeJSFunction "setItemTraitsMode" [text|
|
||||||
function setItemProsConsMode(node, itemId, mode) {
|
function setItemTraitsMode(node, itemId, mode) {
|
||||||
$.get("/render/item/"+itemId+"/pros-cons", {mode: mode})
|
$.get("/render/item/"+itemId+"/traits", {mode: mode})
|
||||||
.done(replaceWithData(node));
|
.done(replaceWithData(node));
|
||||||
}
|
}
|
||||||
|]
|
|]
|
||||||
|
|
||||||
js_setProConMode :: JSFunction a => a
|
js_setTraitMode :: JSFunction a => a
|
||||||
js_setProConMode = makeJSFunction "setProConMode" [text|
|
js_setTraitMode = makeJSFunction "setTraitMode" [text|
|
||||||
function setProConMode(node, itemId, thingId, mode) {
|
function setTraitMode(node, itemId, traitId, mode) {
|
||||||
$.get("/render/item/"+itemId+"/pro-con/"+thingId, {mode: mode})
|
$.get("/render/item/"+itemId+"/trait/"+traitId, {mode: mode})
|
||||||
.done(replaceWithData(node));
|
.done(replaceWithData(node));
|
||||||
}
|
}
|
||||||
|]
|
|]
|
||||||
|
|
||||||
js_submitProConEdit :: JSFunction a => a
|
js_submitTraitEdit :: JSFunction a => a
|
||||||
js_submitProConEdit = makeJSFunction "submitProConEdit" [text|
|
js_submitTraitEdit = makeJSFunction "submitTraitEdit" [text|
|
||||||
function submitProConEdit(node, itemId, thingId, s) {
|
function submitTraitEdit(node, itemId, traitId, s) {
|
||||||
$.post("/set/item/"+itemId+"/pro-con/"+thingId, {content: s})
|
$.post("/set/item/"+itemId+"/trait/"+traitId, {content: s})
|
||||||
.done(replaceWithData(node));
|
.done(replaceWithData(node));
|
||||||
}
|
}
|
||||||
|]
|
|]
|
||||||
|
@ -5,10 +5,10 @@
|
|||||||
border: 1px solid;
|
border: 1px solid;
|
||||||
margin: 5px; }
|
margin: 5px; }
|
||||||
|
|
||||||
.pros-cons {
|
.traits {
|
||||||
display: flex }
|
display: flex }
|
||||||
|
|
||||||
.pros, .cons {
|
.traits-group {
|
||||||
margin: 0px 5px; }
|
margin: 0px 5px; }
|
||||||
|
|
||||||
.anchor {
|
.anchor {
|
||||||
|
Loading…
Reference in New Issue
Block a user