refactor(icons): only allow semantics icons from now on

This commit is contained in:
Steffen Jost 2019-07-24 15:03:35 +02:00
parent f2963cff07
commit 495fdd18dd
8 changed files with 105 additions and 231 deletions

View File

@ -122,8 +122,7 @@ isNewCell = cell . toWidget . isNew
-- | Maybe display comment icon linking a given URL or show nothing at all -- | Maybe display comment icon linking a given URL or show nothing at all
commentCell :: IsDBTable m a => Maybe (Route UniWorX) -> DBCell m a commentCell :: IsDBTable m a => Maybe (Route UniWorX) -> DBCell m a
commentCell Nothing = mempty commentCell Nothing = mempty
commentCell (Just link) = anchorCell link icon commentCell (Just link) = anchorCell link $ hasComment True
where icon = hasComment True
-- | whether something is visible or hidden -- | whether something is visible or hidden
isVisibleCell :: (IsDBTable m a) => Bool -> DBCell m a isVisibleCell :: (IsDBTable m a) => Bool -> DBCell m a
@ -134,11 +133,15 @@ isVisibleCell False = (cell . toWidget $ isVisible False) & addUrgencyClass
-- | for simple file downloads -- | for simple file downloads
fileCell :: IsDBTable m a => Route UniWorX -> DBCell m a fileCell :: IsDBTable m a => Route UniWorX -> DBCell m a
fileCell route = anchorCell route fileDownload fileCell route = anchorCell route iconFileDownload
-- | for zip-archive downloads -- | for zip-archive downloads
zipCell :: IsDBTable m a => Route UniWorX -> DBCell m a zipCell :: IsDBTable m a => Route UniWorX -> DBCell m a
zipCell route = anchorCell route zipDownload zipCell route = anchorCell route iconFileZip
-- | for csv downloads
csvCell :: IsDBTable m a => Route UniWorX -> DBCell m a
csvCell route = anchorCell route iconFileCSV
-- | Display an icon that opens a modal upon clicking -- | Display an icon that opens a modal upon clicking
modalCell :: (IsDBTable m a, ToWidget UniWorX w) => w -> DBCell m a modalCell :: (IsDBTable m a, ToWidget UniWorX w) => w -> DBCell m a

View File

@ -285,7 +285,7 @@ instance Button UniWorX ButtonCsvMode where
btnLabel BtnCsvExport btnLabel BtnCsvExport
= [whamlet| = [whamlet|
$newline never $newline never
#{iconCSV} #{iconFileCSV}
\ _{BtnCsvExport} \ _{BtnCsvExport}
|] |]
btnLabel BtnCsvImport btnLabel BtnCsvImport

View File

@ -7,8 +7,18 @@ module Language.Haskell.TH.Instances
import Language.Haskell.TH import Language.Haskell.TH
import Language.Haskell.TH.Lift (deriveLift) import Language.Haskell.TH.Lift (deriveLift)
import Data.Binary (Binary) import Data.Binary (Binary)
import Data.Semigroup
import Data.Monoid ()
import Control.Applicative
instance Binary Loc instance Binary Loc
deriveLift ''Loc deriveLift ''Loc
instance Semigroup (Q [Dec]) where
(<>) = liftA2 (<>)
instance Monoid (Q [Dec]) where
mempty = pure mempty
mappend = (<>)

View File

@ -171,10 +171,10 @@ instance PathPiece SheetFileType where
fromPathPiece = finiteFromPathPiece fromPathPiece = finiteFromPathPiece
sheetFile2markup :: SheetFileType -> Markup sheetFile2markup :: SheetFileType -> Markup
sheetFile2markup SheetExercise = iconQuestion sheetFile2markup SheetExercise = iconSFTQuestion
sheetFile2markup SheetHint = iconHint sheetFile2markup SheetHint = iconSFTHint
sheetFile2markup SheetSolution = iconSolution sheetFile2markup SheetSolution = iconSFTSolution
sheetFile2markup SheetMarking = iconMarking sheetFile2markup SheetMarking = iconSFTMarking
-- partitionFileType' :: Ord a => [(SheetFileType,a)] -> Map SheetFileType (Set a) -- partitionFileType' :: Ord a => [(SheetFileType,a)] -> Map SheetFileType (Set a)
-- partitionFileType' = groupMap -- partitionFileType' = groupMap

View File

@ -23,6 +23,7 @@ import Utils.TH as Utils
import Utils.DateTime as Utils import Utils.DateTime as Utils
import Utils.PathPiece as Utils import Utils.PathPiece as Utils
import Utils.Route as Utils import Utils.Route as Utils
import Utils.Icon as Utils
import Utils.Message as Utils import Utils.Message as Utils
import Utils.Lang as Utils import Utils.Lang as Utils
import Utils.Parameters as Utils import Utils.Parameters as Utils
@ -79,9 +80,10 @@ import Algebra.Lattice (top, bottom, (/\), (\/), BoundedJoinSemiLattice, Bounded
import Data.Constraint (Dict(..)) import Data.Constraint (Dict(..))
{-# ANN choice ("HLint: ignore Use asum" :: String) #-} {- # ANN choice ("HLint: ignore Use asum" :: String) # -}
$(iconShortcuts) -- declares constants for all known icons
----------- -----------
-- Yesod -- -- Yesod --
@ -114,122 +116,6 @@ unsupportedAuthPredicate = do
-- | A @Widget@ for any site; no language interpolation, etc.
type WidgetSiteless = forall site. forall m. (MonadIO m, MonadThrow m, MonadBaseControl IO m)
=> WidgetT site m ()
-----------
-- Icons --
-----------
-- Create an icon from font-awesome without additional space
fontAwesomeIcon :: Text -> Markup
fontAwesomeIcon iconName =
[shamlet|$newline never
<i .fas .fa-#{iconName}>|]
-- We collect all used icons here for an overview.
-- For consistency, some conditional icons are also provided, e.g. `isIvisble`
iconQuestion :: Markup
iconQuestion = fontAwesomeIcon "question-circle"
iconNew :: Markup
iconNew = fontAwesomeIcon "seedling"
iconOK :: Markup
iconOK = fontAwesomeIcon "check"
iconNotOK :: Markup
iconNotOK = fontAwesomeIcon "times"
iconWarning :: Markup
iconWarning = fontAwesomeIcon "exclamation"
iconProblem :: Markup
iconProblem = fontAwesomeIcon "bolt"
iconHint :: Markup
iconHint = fontAwesomeIcon "life-ring"
-- Icons for Course
iconCourse :: Markup
iconCourse = fontAwesomeIcon "graduation-cap"
iconExam :: Markup
iconExam = fontAwesomeIcon "file-invoice"
iconEnrol :: Bool -> Markup
iconEnrol True = fontAwesomeIcon "user-plus"
iconEnrol False = fontAwesomeIcon "user-slash"
iconExamRegister :: Bool -> Markup
iconExamRegister True = fontAwesomeIcon "calendar-check"
iconExamRegister False = fontAwesomeIcon "calendar-times"
-- Icons for SheetFileType
iconSolution :: Markup
iconSolution =fontAwesomeIcon "exclamation-circle"
iconMarking :: Markup
iconMarking = fontAwesomeIcon "check-circle"
fileDownload :: Markup
fileDownload = fontAwesomeIcon "file-download"
zipDownload :: Markup
zipDownload = fontAwesomeIcon "file-archive"
iconCSV :: Markup
iconCSV = fontAwesomeIcon "file-csv"
-- Generic Conditional icons
isVisible :: Bool -> Markup
-- ^ Display an icon that denotes that something™ is visible or invisible
isVisible True = fontAwesomeIcon "eye"
isVisible False = fontAwesomeIcon "eye-slash"
--
-- For documentation on how to avoid these unneccessary functions
-- we implement them here just once for the first icon:
--
isVisibleWidget :: Bool -> WidgetSiteless
-- ^ Widget having an icon that denotes that something™ is visible or invisible
isVisibleWidget = toWidget . isVisible
maybeIsVisibleWidget :: Maybe Bool -> WidgetSiteless
-- ^ Maybe a widget with an icon that denotes that something™ is visible or invisible
maybeIsVisibleWidget = toWidget . foldMap isVisible
-- Other _frequently_ used icons:
hasComment :: Bool -> Markup
-- ^ Display an icon that denotes that something™ has a comment or not
hasComment True = fontAwesomeIcon "comment-alt"
hasComment False = fontAwesomeIcon "comment-slash" -- comment-alt-slash is not available for free
hasTickmark :: Bool -> Markup
-- ^ Display an icon that denotes that something™ is okay
hasTickmark True = iconOK
hasTickmark False = mempty
isBad :: Bool -> Markup
-- ^ Display an icon that denotes that something™ is bad
isBad True = iconProblem
isBad False = mempty
isNew :: Bool -> Markup
isNew True = iconNew
isNew False = mempty
boolSymbol :: Bool -> Markup
boolSymbol True = iconOK
boolSymbol False = iconNotOK
--------------------- ---------------------
-- Text and String -- -- Text and String --
--------------------- ---------------------

View File

@ -1,13 +1,22 @@
module Utils.Icon where module Utils.Icon where
import ClassyPrelude.Yesod hiding (foldlM, Proxy)
import Data.Universe
import Data.Char
import Utils.PathPiece
-- import Text.Hamlet
import Text.Blaze (Markup)
import Control.Lens
import Language.Haskell.TH
import Language.Haskell.TH.Instances ()
import Language.Haskell.TH.Lift (deriveLift)
import Instances.TH.Lift ()
-- | A @Widget@ for any site; no language interpolation, etc. -- | A @Widget@ for any site; no language interpolation, etc.
type WidgetSiteless = forall site. forall m. (MonadIO m, MonadThrow m, MonadBaseControl IO m) type WidgetSiteless = forall site. forall m. (MonadIO m, MonadThrow m, MonadBaseControl IO m)
=> WidgetT site m () => WidgetT site m ()
import Data.Universe
import Utils.PathPiece
import Text.Hamlet
----------- -----------
-- Icons -- -- Icons --
@ -23,7 +32,7 @@ data Icon
| IconWarning | IconWarning
| IconProblem | IconProblem
| IconVisible | IconVisible
| IconNotVisible | IconInvisible
| IconCourse | IconCourse
| IconEnrolTrue | IconEnrolTrue
| IconEnrolFalse | IconEnrolFalse
@ -49,7 +58,7 @@ iconText = \case
IconWarning -> "exclamation" IconWarning -> "exclamation"
IconProblem -> "bolt" IconProblem -> "bolt"
IconVisible -> "eye" IconVisible -> "eye"
IconNotVisible -> "eye-slash" IconInvisible -> "eye-slash"
IconCourse -> "graduation-cap" IconCourse -> "graduation-cap"
IconEnrolTrue -> "user-plus" IconEnrolTrue -> "user-plus"
IconEnrolFalse -> "user-slash" IconEnrolFalse -> "user-slash"
@ -57,7 +66,7 @@ iconText = \case
IconExamRegisterTrue -> "calendar-check" IconExamRegisterTrue -> "calendar-check"
IconExamRegisterFalse -> "calendar-times" IconExamRegisterFalse -> "calendar-times"
IconCommentTrue -> "comment-alt" IconCommentTrue -> "comment-alt"
IconCommentFalse -> "comment-slash" IconCommentFalse -> "comment-slash" -- comment-alt-slash is not available for free
IconFileDownload -> "file-download" IconFileDownload -> "file-download"
IconFileZip -> "file-archive" IconFileZip -> "file-archive"
IconFileCSV -> "file-csv" IconFileCSV -> "file-csv"
@ -67,85 +76,74 @@ iconText = \case
IconSFTMarking -> "check-circle" -- for SheetFileType only IconSFTMarking -> "check-circle" -- for SheetFileType only
instance Universe Icon instance Universe Icon
instance Finte Icon instance Finite Icon
nullaryPathPiece ''Icon $ camelToPathPiece' 1 nullaryPathPiece ''Icon $ camelToPathPiece' 1
deriveLift ''Icon
-- Create an icon from font-awesome without additional space -- Create an icon from font-awesome without additional space
icon :: Icon -> Markup icon :: Icon -> Markup
icon iconName = icon ic = let ict = iconText ic in
[shamlet|$newline never [shamlet|$newline never
<i .fas .fa-#{iconText iconName}>|] <i .fas .fa-#{ict}>|]
-- declare constats for all icons for compatibility and convenience
-- for compatibility and convenience -- "IconCourse" generates "iconCourse = icon IconCourse"
iconShortcuts :: Q [Dec] iconShortcuts :: Q [Dec]
iconShortcuts = forM universeF iconShortcuts = foldMap mkIcon (universeF :: [Icon])
(\ic -> where
iname <- newName $ 'i' : (drop 1 $ show ic) mkIcon :: Icon -> Q [Dec]
valD (varP iname) (normalB [|icon iname|]) mkIcon ic = do
) do
iname <- newName $ over (ix 0) Data.Char.toLower $ show ic
iconQuestion :: Markup isig <- sigD iname [t|Markup|]
iconQuestion = icon IconQuestion idef <- valD (varP iname) (normalB [|icon ic|]) []
return $ [isig, idef]
iconNew :: Markup
iconNew = icon IconNew
iconOK :: Markup
iconOK = icon IconOK
iconNotOK :: Markup
iconNotOK = icon IconNotOK
iconWarning :: Markup
iconWarning = icon IconWarning
iconProblem :: Markup
iconProblem = icon IconProblem
iconHint :: Markup
iconHint = icon
-- Icons for Course
iconCourse :: Markup
iconCourse = fontAwesomeIcon "graduation-cap"
iconExam :: Markup
iconExam = fontAwesomeIcon "file-invoice"
iconEnrol :: Bool -> Markup
iconEnrol True = fontAwesomeIcon "user-plus"
iconEnrol False = fontAwesomeIcon "user-slash"
iconExamRegister :: Bool -> Markup
iconExamRegister True = fontAwesomeIcon "calendar-check"
iconExamRegister False = fontAwesomeIcon "calendar-times"
-- Icons for SheetFileType ----------------------
iconSolution :: Markup -- Conditional icons
iconSolution =fontAwesomeIcon "exclamation-circle" --
-- Some case are special, hence no Template Haskell here
iconMarking :: Markup
iconMarking = fontAwesomeIcon "check-circle"
fileDownload :: Markup
fileDownload = fontAwesomeIcon "file-download"
zipDownload :: Markup
zipDownload = fontAwesomeIcon "file-archive"
iconCSV :: Markup
iconCSV = fontAwesomeIcon "file-csv"
-- Generic Conditional icons
isVisible :: Bool -> Markup isVisible :: Bool -> Markup
-- ^ Display an icon that denotes that something™ is visible or invisible -- ^ Display an icon that denotes that something™ is visible or invisible
isVisible True = fontAwesomeIcon "eye" isVisible True = icon IconVisible
isVisible False = fontAwesomeIcon "eye-slash" isVisible False = icon IconInvisible
--
hasComment :: Bool -> Markup
-- ^ Display an icon that denotes that something™ has a comment or not
hasComment True = icon IconCommentTrue
hasComment False = icon IconCommentFalse
hasTickmark :: Bool -> Markup
-- ^ Maybe display an icon that denotes that something™ is okay
hasTickmark True = icon IconOK
hasTickmark False = mempty
isBad :: Bool -> Markup
-- ^ Maybe display an icon that denotes that something™ is bad
isBad True = icon IconProblem
isBad False = mempty
-- ^ Maybe display an icon that denotes that something™ is bad
isNew :: Bool -> Markup
isNew True = icon IconNew
isNew False = mempty
boolSymbol :: Bool -> Markup
boolSymbol True = icon IconOK
boolSymbol False = icon IconNotOK
iconEnrol :: Bool -> Markup
iconEnrol True = icon IconEnrolTrue
iconEnrol False = icon IconEnrolFalse
iconExamRegister :: Bool -> Markup
iconExamRegister True = icon IconExamRegisterTrue
iconExamRegister False = icon IconExamRegisterTrue
----------------
-- For documentation on how to avoid these unneccessary functions -- For documentation on how to avoid these unneccessary functions
-- we implement them here just once for the first icon: -- we implement them here just once for the first icon:
-- --
@ -156,27 +154,3 @@ isVisibleWidget = toWidget . isVisible
maybeIsVisibleWidget :: Maybe Bool -> WidgetSiteless maybeIsVisibleWidget :: Maybe Bool -> WidgetSiteless
-- ^ Maybe a widget with an icon that denotes that something™ is visible or invisible -- ^ Maybe a widget with an icon that denotes that something™ is visible or invisible
maybeIsVisibleWidget = toWidget . foldMap isVisible maybeIsVisibleWidget = toWidget . foldMap isVisible
-- Other _frequently_ used icons:
hasComment :: Bool -> Markup
-- ^ Display an icon that denotes that something™ has a comment or not
hasComment True = fontAwesomeIcon "comment-alt"
hasComment False = fontAwesomeIcon "comment-slash" -- comment-alt-slash is not available for free
hasTickmark :: Bool -> Markup
-- ^ Display an icon that denotes that something™ is okay
hasTickmark True = iconOK
hasTickmark False = mempty
isBad :: Bool -> Markup
-- ^ Display an icon that denotes that something™ is bad
isBad True = iconProblem
isBad False = mempty
isNew :: Bool -> Markup
isNew True = iconNew
isNew False = mempty
boolSymbol :: Bool -> Markup
boolSymbol True = iconOK
boolSymbol False = iconNotOK

View File

@ -47,6 +47,7 @@ instance Exception UnknownMessageStatus
data Message = Message data Message = Message
{ messageStatus :: MessageStatus { messageStatus :: MessageStatus
, messageContent :: Html , messageContent :: Html
-- , messageIcon :: Maybe Icon
} }
instance Eq Message where instance Eq Message where

View File

@ -121,7 +121,7 @@ $if not (null occurrences)
$if occurrenceAssignmentsShown $if occurrenceAssignmentsShown
<td .table__td> <td .table__td>
$if registered $if registered
#{fontAwesomeIcon "check"} #{iconOK}
$if gradingShown && not (null parts) $if gradingShown && not (null parts)
<section> <section>
@ -148,7 +148,7 @@ $if gradingShown && not (null parts)
$of Just (ExamAttended (Just ps)) $of Just (ExamAttended (Just ps))
#{showFixed True ps} #{showFixed True ps}
$of Just (ExamAttended Nothing) $of Just (ExamAttended Nothing)
#{fontAwesomeIcon "check"} #{iconOK}
$of Just ExamNoShow $of Just ExamNoShow
_{MsgExamNoShow} _{MsgExamNoShow}
$of Just ExamVoided $of Just ExamVoided