-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
187 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
{-# LANGUAGE QuasiQuotes, OverloadedStrings, TemplateHaskell #-} | ||
{-# LANGUAGE CPP #-} | ||
module Handler.Poll | ||
( getPollsR | ||
, postPollsR | ||
, getPollR | ||
, postPollR | ||
) where | ||
|
||
import Haskellers | ||
import Control.Monad (unless) | ||
import qualified Data.Text as T | ||
import Data.Time (getCurrentTime) | ||
|
||
getPollsR :: Handler RepHtml | ||
getPollsR = do | ||
polls <- runDB $ selectList [] [LimitTo 5, Desc PollCreated] | ||
mu <- maybeAuth | ||
let isAdmin = maybe False (userAdmin . snd) mu | ||
defaultLayout $(widgetFile "polls") | ||
|
||
postPollsR :: Handler RepHtml | ||
postPollsR = do | ||
(_, u) <- requireAuth | ||
unless (userAdmin u) $ permissionDenied "Must be an admin to create a poll" | ||
t <- runInputPost $ ireq textField "poll" | ||
let ls = filter (not . T.null) $ T.lines t | ||
unless (length ls >= 3) $ invalidArgs ["Need at least a question and two answers"] | ||
let (q:as) = ls | ||
now <- liftIO getCurrentTime | ||
pollid <- runDB $ do | ||
pollid <- insert $ Poll q now | ||
mapM_ (\(a, i) -> insert $ PollOption pollid a i) $ zip as [1..] | ||
return pollid | ||
setMessage "Poll created" | ||
redirect RedirectTemporary $ PollR pollid | ||
|
||
data OptInfo = OptInfo | ||
{ oiAnswer :: T.Text | ||
, oiCount :: Int | ||
, oiRealCount :: Int | ||
} | ||
|
||
oiPercent :: Bool -> OptInfo -> [OptInfo] -> Maybe Int | ||
oiPercent real oi ois | ||
| total == 0 = Nothing | ||
| otherwise = Just $ (f oi * 100) `div` total | ||
where | ||
total = sum $ map f ois | ||
f = if real then oiRealCount else oiCount | ||
|
||
toOI :: (PollOptionId, PollOption) -> YesodDB Haskellers Haskellers OptInfo | ||
toOI (poid, po) = do | ||
x <- count [PollAnswerOption ==. poid] | ||
y <- count [PollAnswerOption ==. poid, PollAnswerReal ==. True] | ||
return $ OptInfo (pollOptionAnswer po) x y | ||
|
||
getPollR :: PollId -> Handler RepHtml | ||
getPollR pollid = do | ||
muid <- maybeAuthId | ||
(poll, ois, options, manswer) <- runDB $ do | ||
poll <- get404 pollid | ||
options <- selectList [PollOptionPoll ==. pollid] [Asc PollOptionPriority] | ||
ois <- mapM toOI options | ||
manswer <- | ||
case muid of | ||
Nothing -> return Nothing | ||
Just uid -> do | ||
ma <- getBy $ UniquePollAnswer pollid uid | ||
case ma of | ||
Nothing -> return Nothing | ||
Just (_, pa) -> do | ||
po <- get404 $ pollAnswerOption pa | ||
return $ Just $ pollOptionAnswer po | ||
return (poll, ois, options, manswer) | ||
defaultLayout $(widgetFile "poll") | ||
|
||
postPollR :: PollId -> Handler RepHtml | ||
postPollR pollid = do | ||
(uid, u) <- requireAuth | ||
oidText <- runInputPost $ ireq textField "option" | ||
oid <- | ||
case fromSinglePiece oidText of | ||
Nothing -> invalidArgs ["Invalid selection"] | ||
Just x -> return x | ||
o <- runDB $ get404 oid | ||
unless (pollOptionPoll o == pollid) $ invalidArgs ["Poll mismatch"] | ||
res <- runDB $ insertBy $ PollAnswer pollid oid uid (userReal u) | ||
setMessage $ either (const "You already voted") (const "Vote cast") res | ||
redirect RedirectTemporary $ PollR pollid |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<h1>#{pollQuestion poll} | ||
$maybe _ <- muid | ||
$maybe answer <- manswer | ||
<p>You answered: #{answer} | ||
$nothing | ||
<form method=post> | ||
$forall option <- options | ||
$with oid <- fst option, o <- snd option | ||
<div> | ||
<input type=radio name=option id=#{toSinglePiece oid} value=#{toSinglePiece oid}> | ||
\ # | ||
<label for=#{toSinglePiece oid}>#{pollOptionAnswer o} | ||
<input type=submit value=Vote> | ||
$nothing | ||
<p>You must be logged in to submit an answer. | ||
<h2>Results | ||
<ul> | ||
$forall oi <- ois | ||
<li> | ||
<span .answer>#{oiAnswer oi} | ||
\ # | ||
<span .all> | ||
#{show $ oiCount oi} votes # | ||
$maybe p <- oiPercent False oi ois | ||
(#{show p}%) | ||
\, # | ||
<span .real> | ||
#{show $ oiRealCount oi} verified votes # | ||
$maybe p <- oiPercent True oi ois | ||
(#{show p}%) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<h1>_{MsgPolls} | ||
$if null polls | ||
<p>_{MsgNoPolls} | ||
<ul> | ||
$forall p <- polls | ||
$with pollid <- fst p, poll <- snd p | ||
<li> | ||
<a href=@{PollR pollid}>#{pollQuestion poll} | ||
\ # | ||
<span .asked>_{MsgPollAsked $ pollCreated poll} | ||
$if isAdmin | ||
<form method=post> | ||
<p>Create a new poll. Put the question on the first line, and each answer on succeeding lines. | ||
<textarea name=poll> | ||
<input type=submit value="Add poll"> | ||
$else | ||
<p> | ||
Want to create a new poll? Just # | ||
<a href="mailto:michael@snoyman.com?subject=New%20Haskellers.com%20poll">email Michael and ask | ||
. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
.all, .real { | ||
font-size: 0.8em; | ||
font-style: italic; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -85,3 +85,6 @@ | |
/bling BlingR GET | ||
|
||
/lang LangR POST | ||
|
||
/poll PollsR GET POST | ||
/poll/#PollId PollR GET POST |