lambdacms-core 0.0.7.3 → 0.0.8.0
raw patch · 13 files changed
+166/−174 lines, 13 filesnew-uploader
Files
- CHANGES.md +3/−0
- LambdaCms/Core.hs +2/−1
- LambdaCms/Core/Foundation.hs +36/−52
- LambdaCms/Core/Handler/ActionLog.hs +20/−16
- LambdaCms/Core/Handler/User.hs +14/−18
- LambdaCms/Core/Message.hs +1/−0
- README.md +77/−77
- config/models +0/−1
- lambdacms-core.cabal +3/−3
- templates/admin-layout.julius +6/−2
- templates/admin-welcome.hamlet +2/−2
- templates/user/edit.hamlet +1/−1
- templates/user/index.hamlet +1/−1
CHANGES.md view
@@ -4,6 +4,9 @@ #### dev * ... +#### 0.0.8.0+* Fixed action logging to also work outside of LambdaCms.Core+ #### 0.0.7.2 * Fixed broken package
LambdaCms/Core.hs view
@@ -3,12 +3,13 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_GHC -fno-warn-orphans #-} module LambdaCms.Core ( module Export ) where -import Database.Persist.Sql (SqlBackend)+import Database.Persist.Sql () import LambdaCms.Core.Classes as Export import LambdaCms.Core.Foundation as Export
LambdaCms/Core/Foundation.hs view
@@ -3,29 +3,27 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_GHC -fno-warn-orphans #-} module LambdaCms.Core.Foundation where -import Control.Applicative ((<$>)) import Control.Arrow ((&&&))-import Control.Monad (filterM) import Data.ByteString (ByteString) import qualified Data.ByteString.Lazy.Char8 as LB (concat, toStrict)-import Data.Int import Data.List (find, sortBy) import Data.Maybe (catMaybes, isJust) import Data.Monoid ((<>)) import Data.Ord (comparing)-import Data.Set (Set, empty, fromList, intersection)-import qualified Data.Set as S (null)+import Data.Set (Set)+import qualified Data.Set as S (empty, intersection, null) import Data.Text (Text, concat, intercalate, pack, unpack)-import qualified Data.Text as T import Data.Text.Encoding (decodeUtf8)-import Data.Time (getCurrentTime, utc)+import Data.Time (getCurrentTime) import Data.Time.Format.Human import Data.Traversable (forM) import Database.Persist.Sql (SqlBackend)@@ -40,8 +38,6 @@ import Network.Mail.Mime import Network.Wai (requestMethod) import Text.Hamlet (hamletFile)-import Text.Julius (juliusFile)-import Text.Lucius (luciusFile) import Yesod import Yesod.Auth @@ -112,7 +108,7 @@ -- | Gives the default roles a user should have on create defaultRoles :: HandlerT master IO (Set (Roles master))- defaultRoles = return empty+ defaultRoles = return S.empty -- | See if a user is authorized to perform an action. isAuthorizedTo :: master -- Needed to make function injective.@@ -124,7 +120,7 @@ isAuthorizedTo _ (Just _) Authenticated = Authorized isAuthorizedTo _ Nothing _ = AuthenticationRequired isAuthorizedTo _ (Just urs) (Roles rrs) = do- case (not . S.null $ urs `intersection` rrs) of+ case (not . S.null $ urs `S.intersection` rrs) of True -> Authorized -- non-empty intersection means authorized False -> Unauthorized "Access denied." @@ -152,7 +148,7 @@ welcomeWidget :: Maybe (WidgetT master IO ()) welcomeWidget = Just $ do Entity _ user <- handlerToWidget requireAuth- renderMessage <- getMessageRender+ messageRenderer <- getMessageRender $(widgetFile "admin-welcome") -- | Applies some form of layout to the contents of an admin section page.@@ -348,51 +344,39 @@ (cparts, _) = renderRoute cr rrs = map ((fst . renderRoute) &&& id) rs orrs = reverse $ sortBy (comparing (length . fst)) rrs- cmp (route, _) = route == (take (length route) cparts)+ cmp (route', _) = route' == (take (length route') cparts) routeBestMatch _ _ = Nothing -class LambdaCmsLoggable entity where- logMessage :: LambdaCmsAdmin master => master -> ByteString -> entity -> Maybe (SomeMessage master)- logRoute :: LambdaCmsAdmin master => master -> Key entity -> Maybe (Route master)--instance LambdaCmsLoggable User where- logMessage _ "POST" = jsm Msg.LogCreatedUser- logMessage _ "PATCH" = jsm Msg.LogUpdatedUser- logMessage _ "DELETE" = jsm Msg.LogDeletedUser- logMessage _ "CHPASS" = jsm Msg.LogChangedPasswordUser- logMessage _ "RQPASS" = jsm Msg.LogRequestedPasswordUser- logMessage _ "DEACTIVATE" = jsm Msg.LogDeactivatedUser- logMessage _ "ACTIVATE" = jsm Msg.LogActivatedUser- logMessage _ _ = const Nothing+class LambdaCmsLoggable master entity where+ logMessage :: master -> ByteString -> entity -> [(Text, Text)] - logRoute _ userId = Just . coreR . UserAdminR $ UserAdminEditR userId+instance LambdaCmsAdmin master => LambdaCmsLoggable master User where+ logMessage y "POST" = translateUserLogs y Msg.LogCreatedUser+ logMessage y "PATCH" = translateUserLogs y Msg.LogUpdatedUser+ logMessage y "DELETE" = translateUserLogs y Msg.LogDeletedUser+ logMessage y "CHPASS" = translateUserLogs y Msg.LogChangedPasswordUser+ logMessage y "RQPASS" = translateUserLogs y Msg.LogRequestedPasswordUser+ logMessage y "DEACTIVATE" = translateUserLogs y Msg.LogDeactivatedUser+ logMessage y "ACTIVATE" = translateUserLogs y Msg.LogActivatedUser+ logMessage _ _ = const [] -jsm msg = Just . SomeMessage . msg . userName+translateUserLogs :: forall b master.+ ( LambdaCmsAdmin master+ , RenderMessage master b+ ) => master -> (Text -> b) -> User -> [(Text, Text)]+translateUserLogs y msg u = map (id &&& messageFor) $ renderLanguages y+ where messageFor lang = renderMessage y [lang] . msg $ userName u -logAction :: (LambdaCmsAdmin master, LambdaCmsLoggable entity) => Entity entity -> HandlerT master IO ()-logAction (Entity objectId object) = do- wai <- waiRequest+logUser :: LambdaCmsAdmin master => User -> HandlerT master IO [(Text, Text)]+logUser user = do y <- getYesod- authId <- requireAuthId- timeNow <- liftIO getCurrentTime- ident <- liftIO generateUUID+ method <- waiRequest >>= return . requestMethod+ return $ logMessage y method user - let method = requestMethod wai- langs = renderLanguages y- mRoute = logRoute y objectId- mPath = T.intercalate "/" . fst . renderRoute <$> mRoute+logAction :: LambdaCmsAdmin master => [(Text, Text)] -> HandlerT master IO ()+logAction messages = do+ actionLogUserId <- requireAuthId+ actionLogCreatedAt <- liftIO getCurrentTime+ actionLogIdent <- liftIO generateUUID - mapM_ (saveLog y ident method timeNow object mPath authId) langs- where- saveLog y ident method time entity mPath userId lang = case logMessage y method entity of- Just message' -> do- let message = renderMessage y [lang] message'- runDB . insert_ $ ActionLog- { actionLogIdent = ident- , actionLogUserId = userId- , actionLogMessage = message- , actionLogLang = lang- , actionLogPath = mPath- , actionLogCreatedAt = time- }- Nothing -> return ()+ mapM_ (\(actionLogLang, actionLogMessage) -> runDB . insert_ $ ActionLog {..}) messages
LambdaCms/Core/Handler/ActionLog.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE KindSignatures #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE RankNTypes #-}@@ -9,14 +10,12 @@ , getActionLogAdminUserR ) where -import Control.Applicative ((<$>)) import Data.Int (Int64) import Data.List (intersect) import Data.Lists (firstOr)-import Data.Maybe (fromJust, maybe)+import Data.String import Data.Text import Data.Time.Clock-import Data.Time.Clock import Data.Time.Format.Human import Database.Esqueleto ((^.)) import qualified Database.Esqueleto as E@@ -24,7 +23,6 @@ import qualified LambdaCms.Core.Message as Msg import Network.Wai import Text.Read (readEither)-import Yesod.Auth (requireAuthId) import Yesod.Core import Yesod.Core.Types @@ -36,10 +34,10 @@ } instance ToJSON JsonLog where- toJSON (JsonLog message username userUrl timeAgo) = object [ "message" .= message- , "username" .= username- , "userUrl" .= userUrl- , "timeAgo" .= timeAgo+ toJSON (JsonLog msg username' userUrl' timeAgo') = object [ "message" .= msg+ , "username" .= username'+ , "userUrl" .= userUrl'+ , "timeAgo" .= timeAgo' ] resolveApproot :: Yesod master => master -> Request -> ResolvedApproot@@ -50,13 +48,19 @@ ApprootMaster f -> f master ApprootRequest f -> f master req -logToJsonLog can renderUrl toAgo (Entity _ log, Entity userId user) = do+logToJsonLog :: (LambdaCmsAdmin master, IsString method, Monad m) =>+ (Route master -> method -> Maybe r)+ -> (r -> Text)+ -> (UTCTime -> String)+ -> (Entity ActionLog, Entity User)+ -> m JsonLog+logToJsonLog can renderUrl toAgo (Entity _ log', Entity userId user) = do let mUserUrl = renderUrl <$> (can (coreR $ UserAdminR $ UserAdminEditR userId) "GET") return $ JsonLog- { message = actionLogMessage log+ { message = actionLogMessage log' , username = userName user , userUrl = mUserUrl- , timeAgo = toAgo $ actionLogCreatedAt log+ , timeAgo = toAgo $ actionLogCreatedAt log' } getCurrentLang :: CoreHandler Text@@ -69,15 +73,15 @@ getActionLogs mUserId limit offset lang = do logs <- lift $ runDB $ E.select- $ E.from $ \(log `E.InnerJoin` user) -> do- E.on $ log ^. ActionLogUserId E.==. user ^. UserId- E.where_ $ log ^. ActionLogLang E.==. E.val lang+ $ E.from $ \(log' `E.InnerJoin` user) -> do+ E.on $ log' ^. ActionLogUserId E.==. user ^. UserId+ E.where_ $ log' ^. ActionLogLang E.==. E.val lang maybe (return ()) (E.where_ . (E.==.) (user ^. UserId) . E.val) mUserId E.limit limit E.offset offset- E.orderBy [E.desc (log ^. ActionLogCreatedAt)]+ E.orderBy [E.desc (log' ^. ActionLogCreatedAt)] - return (log, user)+ return (log', user) return logs getActionLogAdminJson :: Maybe UserId -> CoreHandler TypedContent
LambdaCms/Core/Handler/User.hs view
@@ -22,27 +22,23 @@ import LambdaCms.Core.Import import LambdaCms.Core.Message (CoreMessage) import qualified LambdaCms.Core.Message as Msg-import LambdaCms.I18n import Yesod (Route)-import Yesod.Auth (Creds (..), requireAuthId, setCreds)--import qualified Data.Text as T (breakOn, concat, length,- pack, takeWhile)-import qualified Data.Text.Lazy as LT (Text)-import Data.Time.Format+import Yesod.Auth (Creds (..), requireAuthId,+ setCreds) import Control.Arrow ((&&&))-import Data.Maybe (fromJust, fromMaybe, isJust)+import Data.Maybe (fromJust, isJust, fromMaybe) import qualified Data.Set as S+import qualified Data.Text as T (breakOn, length, pack,+ takeWhile) import Data.Time.Clock import Data.Time.Format.Human import Network.Mail.Mime-import System.Locale import Text.Blaze.Html.Renderer.Text (renderHtml) -- data type for a form to change a user's password data ComparePassword = ComparePassword { originalPassword :: Text- , confirmPassword :: Text+ , _confirmPassword :: Text } deriving (Show, Eq) accountSettingsForm :: LambdaCmsAdmin master@@ -198,8 +194,8 @@ FormSuccess (user, roles) -> do userId <- lift $ runDB $ insert user lift $ setUserRoles userId (S.fromList roles)- _ <- sendAccountActivationToken (Entity userId user)- _ <- lift . logAction $ Entity userId user+ sendAccountActivationToken (Entity userId user)+ lift $ logUser user >>= logAction lift $ setMessageI Msg.SuccessCreate redirectUltDest $ UserAdminR UserAdminIndexR _ -> lift $ do@@ -237,7 +233,7 @@ FormSuccess (updatedUser, updatedRoles) -> do _ <- lift $ runDB $ update userId [UserName =. userName updatedUser, UserEmail =. userEmail updatedUser] lift $ setUserRoles userId (S.fromList updatedRoles)- _ <- lift . logAction $ Entity userId updatedUser+ lift $ logUser user >>= logAction lift $ setMessageI Msg.SuccessReplace redirect $ UserAdminR $ UserAdminEditR userId _ -> lift $ do@@ -263,7 +259,7 @@ case formResult of FormSuccess f -> do _ <- lift . runDB $ update userId [UserPassword =. Just (originalPassword f)]- _ <- lift . logAction $ Entity userId user+ lift $ logUser user >>= logAction lift $ setMessageI Msg.SuccessChgPwd redirect $ UserAdminR $ UserAdminEditR userId _ -> lift $ do@@ -284,7 +280,7 @@ } _ <- lift . runDB $ replace userId user _ <- sendAccountResetToken (Entity userId user)- _ <- lift . logAction $ Entity userId user+ lift $ logUser user >>= logAction lift $ setMessageI Msg.PasswordResetTokenSend redirectUltDest . UserAdminR $ UserAdminEditR userId @@ -296,7 +292,7 @@ let user = user' { userActive = False } _ <- lift . runDB $ replace userId user- _ <- lift . logAction $ Entity userId user+ lift $ logUser user >>= logAction lift $ setMessageI Msg.UserDeactivated _ -> lift $ setMessageI Msg.UserStillPending redirectUltDest . UserAdminR $ UserAdminEditR userId@@ -309,7 +305,7 @@ let user = user' { userActive = True } _ <- lift . runDB $ replace userId user- _ <- lift . logAction $ Entity userId user+ lift $ logUser user >>= logAction lift $ setMessageI Msg.UserActivated _ -> lift $ setMessageI Msg.UserStillPending redirectUltDest . UserAdminR $ UserAdminEditR userId@@ -331,7 +327,7 @@ } _ <- runDB $ replace userId user- _ <- logAction $ Entity userId user+ logAction =<< logUser user setMessageI Msg.SuccessDelete redirectUltDest $ UserAdminR UserAdminIndexR
LambdaCms/Core/Message.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_GHC -fno-warn-name-shadowing #-} module LambdaCms.Core.Message ( CoreMessage (..)
README.md view
@@ -1,6 +1,5 @@ - ``` , _ / _, _ / _/ _, / ) _ _,@@ -44,7 +43,7 @@ # Getting started -Using this guide you will create a CMS website named `YourApp`.+Using this guide you will create a CMS website named `mysite`. For a real project you want to substitute this name, but for trying out LambdaCms it is recommended to keep it for the convenience of copy-pasting the instructions that follow.@@ -93,31 +92,33 @@ against non-Haskell libraries. One of the following libraries needs to be available: -* `libpq-dev` (Ubuntu) or `postgress` (Homebrew on OSX) for Postgres-* `libmysqlclient-dev` (Ubuntu) or `mysql` (Homebrew on OSX) for MySQL-* `libsqlite3-dev` (Ubuntu) or `sqlite` (Homebrew on OSX) for Sqlite+* For Postgres:+ * Ubuntu: `libpq-dev`+ * Homebrew on OSX: `postgres`+* For Mysql:+ * Ubuntu: `libmysqlclient-dev`+ * Homebrew on OSX: `mysql`+* For Sqlite+ * Ubuntu: `libsqlite3-dev`+ * Homebrew on OSX: `sqlite` On other platforms these packages might have different names, but are most likely available. -If you are going to use a database other then Sqlite, you also need+If you are going to use a database other than Sqlite, you also need to install that. - ### Create the base application With the following command you create a "scaffolded" Yesod application. The command is interactive; you need to supply some configuration values.-Pick the database of your choice, and name it `YourApp` (if you want follow this-guide closely).+Pick the database of your choice, and choose a project name yesod init -After scaffolding move into the project folder.-- cd YourApp+After scaffolding `cd` into the project folder. -If you have chosen a database other then Sqlite, you need to create a+If you have chosen a database other than Sqlite, you need to create a database and a sufficiently priviledged user, and supply the credentials to the `config/setting.yml` file. @@ -133,7 +134,7 @@ thereby automatically using the most recent minor release in that series. -Run the following commands from within `YourApp`'s project folder,+Run the following commands from within your project's root folder, to install the most recent LTS Haskell package set in the `1.x` series. wget http://www.stackage.org/lts/1/cabal.config@@ -163,23 +164,32 @@ ### Add LambdaCms -At some point the `lambdacms-core` package will be distributed from Hackage,-until then we install it from Github.-- cd ..- git clone git@github.com:lambdacms/lambdacms-core.git- cd lambdacms-core- cabal install- cd ../YourApp+LambdaCms is on Hackage! Install with: `cabal install lambdacms-core` In the following sub-sections we explain how to install `lambdacms-core` into the base application. Much of what we show here can be accomplished in many different ways, in this guide we merely provide a way to get you started. +#### Patching a new Yesod application -#### Modify the `YourApp.cabal` file+To setup a new LambdaCms website the easy way we created patch files to convert+a new Yesod application to a LambdaCms website. Those patches can be found in+[lambdamcs-patches](https://github.com/lambdacms/lambdacms-patches). Either clone+the repository or copy only the required patches to your local environment and+run the following command (replace `/path/to` with the actual path to the patch+file): -First add `lambdacms-core` to the dependencies list of the `YourApp.cabal`+ patch -p1 < /path/to/lambdacms.patch++This patches all files at the same time. Documentation about how to patch files+individually can be found in the `lambdacms-patches`+[README](https://github.com/lambdacms/lambdacms-patches/blob/master/README.md).++To manually add LambdaCms to a Yesod application follow the steps below.++#### Modify the `.cabal` file++First add `lambdacms-core` to the dependencies list of the `.cabal` file (name of the file depends on the name of your project). Add the follwing to the end of the `build-depends` section:@@ -197,44 +207,47 @@ #### Modify the `config/routes` file -Add the following routes to the `config/routes` file of your application:+Replace **all** of the file's content with: ```-/admin/auth AuthR Auth getAuth-/admin/core CoreAdminR CoreAdmin getLambdaCms-/admin AdminHomeRedirectR GET-```+/static StaticR Static appStatic -And remove `/auth AuthR Auth getAuth`.+/favicon.ico FaviconR GET+/robots.txt RobotsR GET -#### Modify the `config/settings.yml` file+/ HomeR GET -Add the following line, which sets the email address for an admin user account-that is created (and activated) in case no user exists:+/admin/auth AuthR Auth getAuth+/admin/core CoreAdminR CoreAdmin getLambdaCms+/admin AdminHomeRedirectR GET+``` +#### Modify Settings++There are two files to modify here. One is `config/settings.yml` and the the other is `Settings.hs`.++In `config/settings.yml`, add the following line to the bottom of the file ``` admin: "_env:LAMBDACMS_ADMIN:<your email address>" ``` -#### Modify the `Settings.hs` file--Append the following record to the `AppSettings` data type:+Then, in `Settings.hs`, append the following record to the `AppSettings` data type: ```haskell , appAdmin :: Text ``` -Add this line to `instance FromJSON AppSettings` (ensure following-the same order as the properties appear in `settings.yml`):+In `instance FromJSON AppSettings`, find this line: +Add the following line just before the line containing `return AppSettings {..}`:+ ```haskell appAdmin <- o .: "admin" ``` #### Modify the `config/models` file -Replace **all** of the file's content with the following `UserRole`-definition:+Replace **all** of the file's content with the following `UserRole` definition: ``` UserRole@@ -260,10 +273,10 @@ ```haskell import LambdaCms.Core import LambdaCms.Core.Settings (generateUUID)-import qualified Network.Wai.Middleware.MethodOverridePost as MiddlewareMOP+import Network.Wai.Middleware.MethodOverridePost ``` -And add the following function:+Add the following function: ```haskell getAdminHomeRedirectR :: Handler Html@@ -271,47 +284,33 @@ redirect $ CoreAdminR AdminHomeR ``` -Replace the `makeFoundation` function with the following code, so it will-create the `admin` user as provided in `settings.yml` and run all needed migrations.-This example assumes Postgres is used:+In the `makeFoundation` function, add this line to beginning: ```haskell-makeFoundation :: AppSettings -> IO App-makeFoundation appSettings' = do- -- Some basic initializations: HTTP connection manager, logger, and static- -- subsite.- appHttpManager' <- newManager- appLogger' <- newStdoutLoggerSet defaultBufSize >>= makeYesodLogger- appStatic' <-- (if appMutableStatic appSettings' then staticDevel else static)- (appStaticDir appSettings')+let getLambdaCms = CoreAdmin+``` - -- We need a log function to create a connection pool. We need a connection- -- pool to create our foundation. And we need our foundation to get a- -- logging function. To get out of this loop, we initially create a- -- temporary foundation without a real connection pool, get a log function- -- from there, and then create the real foundation.- let mkFoundation appConnPool' = App { appSettings = appSettings'- , appStatic = appStatic'- , appHttpManager = appHttpManager'- , appLogger = appLogger'- , appConnPool = appConnPool'- , getLambdaCms = CoreAdmin- }- tempFoundation = mkFoundation $ error "connPool forced in tempFoundation"- logFunc = messageLoggerSource tempFoundation appLogger'+Then, find this code: - -- Create the database connection pool- pool <- flip runLoggingT logFunc $ createPostgresqlPool- (pgConnStr $ appDatabaseConf appSettings')- (pgPoolSize $ appDatabaseConf appSettings')+```haskell+ -- Perform database migration using our application's logging settings.+ runLoggingT (runSqlPool (runMigration migrateAll) pool) logFunc + -- Return the foundation+ return $ mkFoundation pool+```++And replace it with:++```haskell+ -- Perform database migration using our application's logging settings. let theFoundation = mkFoundation pool runLoggingT (runSqlPool (mapM_ runMigration [migrateAll, migrateLambdaCmsCore]) pool)- (messageLoggerSource theFoundation appLogger')+ (messageLoggerSource theFoundation appLogger) - let admin = appAdmin appSettings'+ -- Create a user if no user exists yet+ let admin = appAdmin appSettings madmin <- runSqlPool (getBy (UniqueEmail admin)) pool case madmin of Nothing -> do@@ -332,10 +331,11 @@ mapM_ (insert_ . UserRole uid) [minBound .. maxBound] _ -> return () + -- Return the foundation return theFoundation- ``` + In the function `makeApplication` replace this line: ```haskell@@ -346,7 +346,7 @@ forms work on older browsers): ```haskell- return $ logWare $ MiddlewareMOP.methodOverridePost appPlain+ return $ logWare $ methodOverridePost appPlain ``` ## Create the `Roles.hs` file@@ -476,7 +476,7 @@ ### Give it a try -LambdaCms should now be installed into `YourApp`. You can give it a try.+LambdaCms should now be installed. You can give it a try. yesod devel
config/models view
@@ -24,7 +24,6 @@ userId UserId message Text lang Text- path Text Maybe createdAt UTCTime UniqueLog ident lang deriving Typeable Show
lambdacms-core.cabal view
@@ -1,5 +1,5 @@ name: lambdacms-core-version: 0.0.7.3+version: 0.0.8.0 license: MIT license-file: LICENSE author: Cies Breijs, Mats Rietdijk, Rutger van Aalst@@ -15,9 +15,9 @@ build-type: Simple tested-with: GHC >= 7.6 cabal-version: >= 1.18-extra-source-files: README.md+extra-doc-files: README.md , CHANGES.md- , templates/*.hamlet+extra-source-files: templates/*.hamlet , templates/*.julius , templates/*.cassius , templates/mail/*.hamlet
templates/admin-layout.julius view
@@ -4,9 +4,13 @@ var formToggles; formToggles = $('.form-toggle'); formToggles.each(function(index) {- var glyph;+ var btn, glyph; glyph = $('<span />').addClass('glyphicon');- $(this).prepend(glyph);+ btn = $(this);+ if (btn.parent('.form-toggle-wrapper').find('.has-error').length) {+ btn.data('expanded', true);+ }+ btn.prepend(glyph); toggleForm(this); }); formToggles.on('click', function() {
templates/admin-welcome.hamlet view
@@ -2,6 +2,6 @@ <div .col-xs-12> <div .jumbotron> <h2>_{Msg.WelcomeTitle $ userName user}- <p>_{Msg.WelcomeIntro $ renderMessage adminTitle}+ <p>_{Msg.WelcomeIntro $ messageRenderer adminTitle} <p>_{Msg.WelcomeMenu}- <p>#{preEscapedToMarkup $ renderMessage $ SomeMessage Msg.WelcomeInfo}+ <p>#{preEscapedToMarkup $ messageRenderer $ SomeMessage Msg.WelcomeInfo}
templates/user/edit.hamlet view
@@ -58,7 +58,7 @@ - <tr> <td>_{Msg.AccountStatus}- $maybe ut <- userToken user+ $maybe _ <- userToken user <td .text-right .text-warning>_{Msg.AccountPending} $nothing $if userActive user
templates/user/index.hamlet view
@@ -38,7 +38,7 @@ $forall role <- roles <span .label .label-primary>#{show role} <td>#{userEmail user}- $maybe ut <- userToken user+ $maybe _ <- userToken user <td .text-right .text-warning>_{Msg.AccountPending} $nothing $if userActive user