Cleanup Theme declaration
This commit is contained in:
parent
d2242f21ff
commit
28c7afe69c
1
.gitignore
vendored
1
.gitignore
vendored
@ -29,3 +29,4 @@ uniworx.nix
|
|||||||
src/Handler/Assist.bak
|
src/Handler/Assist.bak
|
||||||
src/Handler/Course.SnapCustom.hs
|
src/Handler/Course.SnapCustom.hs
|
||||||
*.orig
|
*.orig
|
||||||
|
.stack-work-*
|
||||||
|
|||||||
13
ghci.sh
13
ghci.sh
@ -5,4 +5,15 @@ export DETAILED_LOGGING=true
|
|||||||
export LOG_ALL=true
|
export LOG_ALL=true
|
||||||
export DUMMY_LOGIN=true
|
export DUMMY_LOGIN=true
|
||||||
|
|
||||||
exec -- stack ghci --flag uniworx:dev --flag uniworx:library-only
|
move-back() {
|
||||||
|
mv -v .stack-work .stack-work-ghci
|
||||||
|
[[ -d .stack-work-run ]] && mv -v .stack-work-run .stack-work
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ -d .stack-work-ghci ]]; then
|
||||||
|
[[ -d .stack-work ]] && mv -v .stack-work .stack-work-run
|
||||||
|
mv -v .stack-work-ghci .stack-work
|
||||||
|
trap move-back EXIT
|
||||||
|
fi
|
||||||
|
|
||||||
|
stack ghci --flag uniworx:dev --flag uniworx:library-only
|
||||||
|
|||||||
@ -88,6 +88,8 @@ dependencies:
|
|||||||
- Glob
|
- Glob
|
||||||
- ldap-client
|
- ldap-client
|
||||||
- connection
|
- connection
|
||||||
|
- universe
|
||||||
|
- universe-base
|
||||||
|
|
||||||
# The library contains all of our application code. The executable
|
# The library contains all of our application code. The executable
|
||||||
# defined below is just a thin wrapper.
|
# defined below is just a thin wrapper.
|
||||||
|
|||||||
@ -515,6 +515,7 @@ instance Yesod UniWorX where
|
|||||||
|
|
||||||
defaultLayout widget = do
|
defaultLayout widget = do
|
||||||
master <- getYesod
|
master <- getYesod
|
||||||
|
let AppSettings { appUserDefaults = UserDefaultConf{..}, .. } = appSettings master
|
||||||
mmsgs <- getMessages
|
mmsgs <- getMessages
|
||||||
|
|
||||||
mcurrentRoute <- getCurrentRoute
|
mcurrentRoute <- getCurrentRoute
|
||||||
@ -534,10 +535,10 @@ instance Yesod UniWorX where
|
|||||||
isAuth <- isJust <$> maybeAuthId
|
isAuth <- isJust <$> maybeAuthId
|
||||||
|
|
||||||
-- Lookup Favourites & Theme if possible -- TODO: cache this info in a cookie?!
|
-- Lookup Favourites & Theme if possible -- TODO: cache this info in a cookie?!
|
||||||
(favourites',show -> currentTheme) <- do
|
(favourites', currentTheme) <- do
|
||||||
muid <- maybeAuthPair
|
muid <- maybeAuthPair
|
||||||
case muid of
|
case muid of
|
||||||
Nothing -> return ([],Default)
|
Nothing -> return ([],userDefaultTheme)
|
||||||
(Just (uid,user)) -> do
|
(Just (uid,user)) -> do
|
||||||
favs <- runDB $ E.select . E.from $ \(course `E.InnerJoin` courseFavourite) -> do
|
favs <- runDB $ E.select . E.from $ \(course `E.InnerJoin` courseFavourite) -> do
|
||||||
E.on (course E.^. CourseId E.==. courseFavourite E.^. CourseFavouriteCourse)
|
E.on (course E.^. CourseId E.==. courseFavourite E.^. CourseFavouriteCourse)
|
||||||
|
|||||||
@ -30,12 +30,12 @@ data SettingsForm = SettingsForm
|
|||||||
|
|
||||||
makeSettingForm :: Maybe SettingsForm -> Form SettingsForm
|
makeSettingForm :: Maybe SettingsForm -> Form SettingsForm
|
||||||
makeSettingForm template = identForm FIDsettings $ \html -> do
|
makeSettingForm template = identForm FIDsettings $ \html -> do
|
||||||
let themeList = [(display t,t) | t <- allThemes]
|
let themeList = [Option (display t) t (toPathPiece t) | t <- universeF]
|
||||||
(result, widget) <- flip (renderAForm FormStandard) html $ SettingsForm
|
(result, widget) <- flip (renderAForm FormStandard) html $ SettingsForm
|
||||||
<$> areq (natFieldI $ MsgNatField "Favoriten") -- TODO: natFieldI not working here
|
<$> areq (natFieldI $ MsgNatField "Favoriten") -- TODO: natFieldI not working here
|
||||||
(fslpI MsgFavoriten "Anzahl Favoriten") (stgMaxFavourties <$> template)
|
(fslpI MsgFavoriten "Anzahl Favoriten") (stgMaxFavourties <$> template)
|
||||||
<*> areq (selectFieldList themeList)
|
<*> areq (selectField . return $ mkOptionList themeList)
|
||||||
(fslpI MsgTheme "theme-select" ) (stgTheme <$> template) -- TODO: pass theme-select as id-attribute or similar.
|
(fslI MsgTheme) { fsId = Just "theme-select" } (stgTheme <$> template)
|
||||||
<*> areq (selectField $ dateTimeFormatOptions SelFormatDateTime) (fslI MsgDateTimeFormat) (stgDateTime <$> template)
|
<*> areq (selectField $ dateTimeFormatOptions SelFormatDateTime) (fslI MsgDateTimeFormat) (stgDateTime <$> template)
|
||||||
<*> areq (selectField $ dateTimeFormatOptions SelFormatDate) (fslI MsgDateFormat) (stgDate <$> template)
|
<*> areq (selectField $ dateTimeFormatOptions SelFormatDate) (fslI MsgDateFormat) (stgDate <$> template)
|
||||||
<*> areq (selectField $ dateTimeFormatOptions SelFormatTime) (fslI MsgTimeFormat) (stgTime <$> template)
|
<*> areq (selectField $ dateTimeFormatOptions SelFormatTime) (fslI MsgTimeFormat) (stgTime <$> template)
|
||||||
|
|||||||
@ -21,3 +21,5 @@ import Data.UUID as Import (UUID)
|
|||||||
import Text.Lucius as Import
|
import Text.Lucius as Import
|
||||||
|
|
||||||
import Text.Shakespeare.Text as Import hiding (text, stext)
|
import Text.Shakespeare.Text as Import hiding (text, stext)
|
||||||
|
|
||||||
|
import Data.Universe as Import
|
||||||
|
|||||||
@ -16,12 +16,15 @@ import ClassyPrelude
|
|||||||
import Utils
|
import Utils
|
||||||
import Control.Lens
|
import Control.Lens
|
||||||
|
|
||||||
import Data.Map (Map)
|
|
||||||
import qualified Data.Map as Map
|
|
||||||
import Data.Set (Set)
|
import Data.Set (Set)
|
||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
import Data.Fixed
|
import Data.Fixed
|
||||||
import Data.Monoid (Sum(..))
|
import Data.Monoid (Sum(..))
|
||||||
|
import Data.Maybe (fromJust)
|
||||||
|
import Data.Universe
|
||||||
|
import Data.Universe.Helpers
|
||||||
|
|
||||||
|
import Text.Read (readMaybe)
|
||||||
|
|
||||||
import Database.Persist.TH
|
import Database.Persist.TH
|
||||||
import Database.Persist.Class
|
import Database.Persist.Class
|
||||||
@ -32,15 +35,14 @@ import Web.HttpApiData
|
|||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import qualified Data.Text as Text
|
import qualified Data.Text as Text
|
||||||
import qualified Data.Text.Encoding as Text
|
import qualified Data.Text.Encoding as Text
|
||||||
|
import qualified Data.Text.Lens as Text
|
||||||
import Text.Read (readMaybe,readsPrec)
|
|
||||||
|
|
||||||
import Data.CaseInsensitive (CI)
|
import Data.CaseInsensitive (CI)
|
||||||
import qualified Data.CaseInsensitive as CI
|
import qualified Data.CaseInsensitive as CI
|
||||||
|
|
||||||
import Yesod.Core.Dispatch (PathPiece(..))
|
import Yesod.Core.Dispatch (PathPiece(..))
|
||||||
import Data.Aeson (FromJSON(..), ToJSON(..), withText, Value(..))
|
import Data.Aeson (FromJSON(..), ToJSON(..), withText, Value(..))
|
||||||
import Data.Aeson.TH (deriveJSON, defaultOptions)
|
import Data.Aeson.TH (deriveJSON, defaultOptions, Options(..))
|
||||||
|
|
||||||
import GHC.Generics (Generic)
|
import GHC.Generics (Generic)
|
||||||
import Generics.Deriving.Monoid (gmemptydefault, gmappenddefault)
|
import Generics.Deriving.Monoid (gmemptydefault, gmappenddefault)
|
||||||
@ -107,19 +109,19 @@ data SheetGroup
|
|||||||
deriveJSON defaultOptions ''SheetGroup
|
deriveJSON defaultOptions ''SheetGroup
|
||||||
derivePersistFieldJSON "SheetGroup"
|
derivePersistFieldJSON "SheetGroup"
|
||||||
|
|
||||||
enumFromPathPiece :: (PathPiece a, Enum a, Bounded a) => Text -> Maybe a
|
|
||||||
enumFromPathPiece t = lookup (CI.mk t) [(CI.mk $ toPathPiece ty,ty) | ty <- [minBound..maxBound]]
|
|
||||||
|
|
||||||
data SheetFileType = SheetExercise | SheetHint | SheetSolution | SheetMarking
|
data SheetFileType = SheetExercise | SheetHint | SheetSolution | SheetMarking
|
||||||
deriving (Show, Read, Eq, Ord, Enum, Bounded)
|
deriving (Show, Read, Eq, Ord, Enum, Bounded)
|
||||||
derivePersistField "SheetFileType"
|
derivePersistField "SheetFileType"
|
||||||
|
|
||||||
|
instance Universe SheetFileType where universe = universeDef
|
||||||
|
instance Finite SheetFileType
|
||||||
|
|
||||||
instance PathPiece SheetFileType where
|
instance PathPiece SheetFileType where
|
||||||
toPathPiece SheetExercise = "file"
|
toPathPiece SheetExercise = "file"
|
||||||
toPathPiece SheetHint = "hint"
|
toPathPiece SheetHint = "hint"
|
||||||
toPathPiece SheetSolution = "solution"
|
toPathPiece SheetSolution = "solution"
|
||||||
toPathPiece SheetMarking = "marking"
|
toPathPiece SheetMarking = "marking"
|
||||||
fromPathPiece = enumFromPathPiece
|
fromPathPiece = finiteFromPathPiece
|
||||||
|
|
||||||
-- $(deriveSimpleWith ''DisplayAble 'display (drop 17) ''SheetFileType)
|
-- $(deriveSimpleWith ''DisplayAble 'display (drop 17) ''SheetFileType)
|
||||||
instance DisplayAble SheetFileType where -- deprecated, see RenderMessage instance in Foundation
|
instance DisplayAble SheetFileType where -- deprecated, see RenderMessage instance in Foundation
|
||||||
@ -148,6 +150,9 @@ partitionFileType fts =
|
|||||||
data SubmissionFileType = SubmissionOriginal | SubmissionCorrected
|
data SubmissionFileType = SubmissionOriginal | SubmissionCorrected
|
||||||
deriving (Show, Read, Eq, Ord, Enum, Bounded)
|
deriving (Show, Read, Eq, Ord, Enum, Bounded)
|
||||||
|
|
||||||
|
instance Universe SubmissionFileType where universe = universeDef
|
||||||
|
instance Finite SubmissionFileType
|
||||||
|
|
||||||
submissionFileTypeIsUpdate :: SubmissionFileType -> Bool
|
submissionFileTypeIsUpdate :: SubmissionFileType -> Bool
|
||||||
submissionFileTypeIsUpdate SubmissionOriginal = False
|
submissionFileTypeIsUpdate SubmissionOriginal = False
|
||||||
submissionFileTypeIsUpdate SubmissionCorrected = True
|
submissionFileTypeIsUpdate SubmissionCorrected = True
|
||||||
@ -159,7 +164,7 @@ isUpdateSubmissionFileType True = SubmissionCorrected
|
|||||||
instance PathPiece SubmissionFileType where
|
instance PathPiece SubmissionFileType where
|
||||||
toPathPiece SubmissionOriginal = "original"
|
toPathPiece SubmissionOriginal = "original"
|
||||||
toPathPiece SubmissionCorrected = "corrected"
|
toPathPiece SubmissionCorrected = "corrected"
|
||||||
fromPathPiece = enumFromPathPiece
|
fromPathPiece = finiteFromPathPiece
|
||||||
|
|
||||||
instance DisplayAble SubmissionFileType where
|
instance DisplayAble SubmissionFileType where
|
||||||
display SubmissionOriginal = "Abgabe"
|
display SubmissionOriginal = "Abgabe"
|
||||||
@ -319,38 +324,43 @@ data StudyFieldType = FieldPrimary | FieldSecondary
|
|||||||
deriving (Eq, Ord, Enum, Show, Read, Bounded)
|
deriving (Eq, Ord, Enum, Show, Read, Bounded)
|
||||||
derivePersistField "StudyFieldType"
|
derivePersistField "StudyFieldType"
|
||||||
|
|
||||||
|
data Theme
|
||||||
|
= ThemeDefault
|
||||||
|
| ThemeLavender
|
||||||
|
| ThemeNeutralBlue
|
||||||
|
| ThemeAberdeenReds
|
||||||
|
| ThemeMossGreen
|
||||||
|
| ThemeSkyLove
|
||||||
|
deriving (Eq, Ord, Bounded, Enum, Show, Read)
|
||||||
|
|
||||||
-- Skins / Themes
|
deriveJSON defaultOptions
|
||||||
data Theme --Simply add Themes to this type only. CamelCase will be converted to "-lower"
|
{ constructorTagModifier = fromJust . stripPrefix "Theme"
|
||||||
= Default
|
} ''Theme
|
||||||
| Lavender
|
|
||||||
| NeutralBlue
|
|
||||||
| AberdeenReds -- e.g. turned into "theme--aberdeen-reds"
|
|
||||||
| MossGreen
|
|
||||||
| SkyLove
|
|
||||||
deriving (Eq,Ord,Bounded,Enum)
|
|
||||||
|
|
||||||
$(deriveJSON defaultOptions ''Theme)
|
instance Universe Theme where universe = universeDef
|
||||||
$(deriveShowWith uncamel ''Theme) -- show for internal use in css/js
|
instance Finite Theme
|
||||||
$(deriveSimpleWith ''DisplayAble 'display camelSpace ''Theme) -- display to display at user
|
|
||||||
|
|
||||||
allThemes :: [Theme]
|
instance PathPiece Theme where
|
||||||
allThemes = [minBound..maxBound]
|
toPathPiece = $(nullaryToPathPiece ''Theme [Text.intercalate "-" . map Text.toLower . unsafeTail . splitCamel])
|
||||||
|
fromPathPiece = finiteFromPathPiece
|
||||||
|
|
||||||
readTheme :: Map String Theme
|
$(deriveSimpleWith ''DisplayAble 'display (over Text.packed $ Text.intercalate " " . unsafeTail . splitCamel) ''Theme) -- describe theme to user
|
||||||
readTheme = Map.fromList [ (show t,t) | t <- allThemes ]
|
|
||||||
|
-- derivePersistFieldJSON "Theme" -- Preferred Version
|
||||||
|
-- Backwards-compatibility until database versioning is implemented (#120):
|
||||||
|
instance PersistField Theme where
|
||||||
|
toPersistValue = PersistText . ("theme--" <>) . toPathPiece
|
||||||
|
fromPersistValue (PersistText t) = do
|
||||||
|
pp <- case Text.stripPrefix "theme--" t of
|
||||||
|
Just pp -> return pp
|
||||||
|
Nothing -> Left "Expected 'theme--'-Prefix"
|
||||||
|
case fromPathPiece pp of
|
||||||
|
Just th -> return th
|
||||||
|
Nothing -> Left "Could not parse PathPiece"
|
||||||
|
fromPersistValue x = Left $ "Expected PersistText, received: " <> tshow x
|
||||||
|
|
||||||
instance Read Theme where -- generic Read-Instance for Show/Bounded
|
instance PersistFieldSql Theme where
|
||||||
readsPrec _ s
|
sqlType _ = SqlString
|
||||||
| (Just t) <- (Map.lookup s readTheme) = [(t,"")]
|
|
||||||
| otherwise = [(Default,"")] -- read shall always succeed
|
|
||||||
|
|
||||||
{-
|
|
||||||
instance Default Theme where
|
|
||||||
def = Default
|
|
||||||
-}
|
|
||||||
|
|
||||||
derivePersistField "Theme"
|
|
||||||
|
|
||||||
|
|
||||||
newtype ZIPArchiveName obj = ZIPArchiveName { unZIPArchiveName :: obj }
|
newtype ZIPArchiveName obj = ZIPArchiveName { unZIPArchiveName :: obj }
|
||||||
@ -380,6 +390,9 @@ instance PersistField (CI String) where
|
|||||||
instance PersistFieldSql (CI Text) where
|
instance PersistFieldSql (CI Text) where
|
||||||
sqlType _ = SqlOther "citext"
|
sqlType _ = SqlOther "citext"
|
||||||
|
|
||||||
|
instance PersistFieldSql (CI String) where
|
||||||
|
sqlType _ = SqlOther "citext"
|
||||||
|
|
||||||
instance ToJSON a => ToJSON (CI a) where
|
instance ToJSON a => ToJSON (CI a) where
|
||||||
toJSON = toJSON . CI.original
|
toJSON = toJSON . CI.original
|
||||||
|
|
||||||
|
|||||||
19
src/Utils.hs
19
src/Utils.hs
@ -25,6 +25,7 @@ import qualified Data.CaseInsensitive as CI
|
|||||||
import Utils.DB as Utils
|
import Utils.DB as Utils
|
||||||
import Utils.Common as Utils
|
import Utils.Common as Utils
|
||||||
import Utils.DateTime as Utils
|
import Utils.DateTime as Utils
|
||||||
|
import Utils.PathPiece as Utils
|
||||||
|
|
||||||
import Text.Blaze (Markup, ToMarkup)
|
import Text.Blaze (Markup, ToMarkup)
|
||||||
|
|
||||||
@ -109,24 +110,6 @@ withFragment :: ( Monad m
|
|||||||
withFragment form html = (flip fmap) form $ \(x, widget) -> (x, toWidget html >> widget)
|
withFragment form html = (flip fmap) form $ \(x, widget) -> (x, toWidget html >> widget)
|
||||||
|
|
||||||
|
|
||||||
uncamel :: String -> String -- "Model.Theme.CamelCaseThing" -> "camel-case-thing"
|
|
||||||
uncamel = ("theme-" ++) . reverse . foldl helper []
|
|
||||||
where
|
|
||||||
helper _ '.' = []
|
|
||||||
helper acc c
|
|
||||||
| Char.isSpace c = acc
|
|
||||||
| Char.isUpper c = Char.toLower c : '-' : acc
|
|
||||||
| otherwise = c : acc
|
|
||||||
|
|
||||||
camelSpace :: String -> String -- "Model.Theme.CamelCaseThing" -> "Camel Case Thing"
|
|
||||||
camelSpace = reverse . foldl helper []
|
|
||||||
where
|
|
||||||
helper _ '.' = []
|
|
||||||
helper acc c
|
|
||||||
| Char.isSpace c = acc
|
|
||||||
| Char.isUpper c = c : ' ' : acc
|
|
||||||
| otherwise = c : acc
|
|
||||||
|
|
||||||
-- Convert anything to Text, and I don't care how
|
-- Convert anything to Text, and I don't care how
|
||||||
class DisplayAble a where
|
class DisplayAble a where
|
||||||
display :: a -> Text
|
display :: a -> Text
|
||||||
|
|||||||
@ -73,7 +73,7 @@ deriveSimpleWith cls fun strOp ty = do
|
|||||||
genClause :: Con -> Q Clause
|
genClause :: Con -> Q Clause
|
||||||
genClause (NormalC name []) =
|
genClause (NormalC name []) =
|
||||||
let pats = [ConP name []]
|
let pats = [ConP name []]
|
||||||
body = NormalB $ LitE $ StringL $ strOp $ show $ name
|
body = NormalB $ LitE $ StringL $ strOp $ nameBase name
|
||||||
in return $ Clause pats body []
|
in return $ Clause pats body []
|
||||||
genClause _ = fail "deriveShowTheme: constructors not allowed to have arguments"
|
genClause _ = fail "deriveShowTheme: constructors not allowed to have arguments"
|
||||||
|
|
||||||
|
|||||||
51
src/Utils/PathPiece.hs
Normal file
51
src/Utils/PathPiece.hs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
{-# LANGUAGE NoImplicitPrelude
|
||||||
|
#-}
|
||||||
|
|
||||||
|
module Utils.PathPiece
|
||||||
|
( finiteFromPathPiece
|
||||||
|
, nullaryToPathPiece
|
||||||
|
, splitCamel
|
||||||
|
) where
|
||||||
|
|
||||||
|
import ClassyPrelude.Yesod
|
||||||
|
|
||||||
|
import Language.Haskell.TH
|
||||||
|
import qualified Language.Haskell.TH.Syntax as TH (Lift(..))
|
||||||
|
import Data.Universe
|
||||||
|
|
||||||
|
import qualified Data.Text as Text
|
||||||
|
import qualified Data.Char as Char
|
||||||
|
|
||||||
|
import Data.Monoid (Endo(..))
|
||||||
|
|
||||||
|
finiteFromPathPiece :: (PathPiece a, Finite a) => Text -> Maybe a
|
||||||
|
finiteFromPathPiece text = case filter (\c -> toPathPiece c == text) universeF of
|
||||||
|
[x] -> Just x
|
||||||
|
_xs -> Nothing
|
||||||
|
|
||||||
|
nullaryToPathPiece :: Name -> [Text -> Text] -> ExpQ
|
||||||
|
nullaryToPathPiece nullaryType manglers = do
|
||||||
|
TyConI (DataD _ _ _ _ constructors _) <- reify nullaryType
|
||||||
|
helperName <- newName "helper"
|
||||||
|
let
|
||||||
|
toClause (NormalC cName []) = clause [conP cName []] (normalB . TH.lift . mangle $ nameBase cName) []
|
||||||
|
toClause con = fail $ "Unsupported constructor: " ++ show con
|
||||||
|
helperDec = funD helperName $ map toClause constructors
|
||||||
|
letE [helperDec] $ varE helperName
|
||||||
|
where
|
||||||
|
mangle = appEndo (foldMap Endo manglers) . Text.pack
|
||||||
|
|
||||||
|
splitCamel :: Text -> [Text]
|
||||||
|
splitCamel = map Text.pack . reverse . helper (error "hasChange undefined at start of string") [] "" . Text.unpack
|
||||||
|
where
|
||||||
|
helper hadChange words thisWord [] = reverse thisWord : words
|
||||||
|
helper hadChange words [] (c:cs) = helper True words [c] cs
|
||||||
|
helper hadChange words ws@(w:ws') (c:cs)
|
||||||
|
| sameCategory w c
|
||||||
|
, null ws' = helper False words (c:ws) cs
|
||||||
|
| sameCategory w c = helper hadChange words (c:ws) cs
|
||||||
|
| null ws' = helper True words (c:ws) cs
|
||||||
|
| not hadChange = helper True (reverse ws':words) [c,w] cs
|
||||||
|
| otherwise = helper True (reverse ws:words) [c] cs
|
||||||
|
|
||||||
|
sameCategory = (==) `on` Char.generalCategory
|
||||||
13
start.sh
13
start.sh
@ -7,4 +7,15 @@ export DUMMY_LOGIN=true
|
|||||||
export ALLOW_DEPRECATED=true
|
export ALLOW_DEPRECATED=true
|
||||||
export PWFILE=users.yml
|
export PWFILE=users.yml
|
||||||
|
|
||||||
exec -- stack exec -- yesod devel
|
move-back() {
|
||||||
|
mv -v .stack-work .stack-work-run
|
||||||
|
[[ -d .stack-work-ghci ]] && mv -v .stack-work-ghci .stack-work
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ -d .stack-work-run ]]; then
|
||||||
|
[[ -d .stack-work ]] && mv -v .stack-work .stack-work-ghci
|
||||||
|
mv -v .stack-work-run .stack-work
|
||||||
|
trap move-back EXIT
|
||||||
|
fi
|
||||||
|
|
||||||
|
stack exec -- yesod devel
|
||||||
|
|||||||
@ -39,7 +39,7 @@ $newline never
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
<body .no-js .#{currentTheme} :isAuth:.logged-in>
|
<body .no-js .theme--#{toPathPiece currentTheme} :isAuth:.logged-in>
|
||||||
<!-- removes no-js class from body if client supports javascript -->
|
<!-- removes no-js class from body if client supports javascript -->
|
||||||
<script>
|
<script>
|
||||||
document.body.classList.remove('no-js');
|
document.body.classList.remove('no-js');
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
document.addEventListener('DOMContentLoaded', function () {
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
|
||||||
var themeSelector = document.querySelector('[placeholder="theme-select"]');
|
var themeSelector = document.querySelector('#theme-select');
|
||||||
themeSelector.addEventListener('change', function() {
|
themeSelector.addEventListener('change', function() {
|
||||||
// get rid of old themes on body
|
// get rid of old themes on body
|
||||||
var options = Array.from(themeSelector.options)
|
var options = Array.from(themeSelector.options)
|
||||||
@ -8,10 +8,10 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
document.body.classList.remove(optionToTheme(option));
|
document.body.classList.remove(optionToTheme(option));
|
||||||
});
|
});
|
||||||
// add newly selected theme
|
// add newly selected theme
|
||||||
document.body.classList.add(optionToTheme(themeSelector.options[themeSelector.value - 1]));
|
document.body.classList.add(optionToTheme(themeSelector.selectedOptions[0]));
|
||||||
});
|
});
|
||||||
|
|
||||||
function optionToTheme(option) {
|
function optionToTheme(option) {
|
||||||
return optionValue = 'theme--' + option.innerText.toLowerCase().trim().replace(/\s/g, '-');
|
return optionValue = 'theme--' + option.value;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user