Updated scaffolding
This commit is contained in:
parent
f9e3e961b2
commit
f82bd1885f
@ -1,5 +1,15 @@
|
|||||||
__1.4.0.9__ Allow devel.hs to be located in app/ or src/ subdirectories.
|
## 1.4.1
|
||||||
|
|
||||||
__1.4.0.8__ Updated postgres-fay scaffolding for yesod-fay 0.7.0
|
Significant update to the scaffolding.
|
||||||
|
|
||||||
__1.4.0.7__ Fix a bug in `yesod devel` when cabal config has `tests: True` #864
|
## 1.4.0.9
|
||||||
|
|
||||||
|
Allow devel.hs to be located in app/ or src/ subdirectories.
|
||||||
|
|
||||||
|
## 1.4.0.8
|
||||||
|
|
||||||
|
Updated postgres-fay scaffolding for yesod-fay 0.7.0
|
||||||
|
|
||||||
|
## 1.4.0.7
|
||||||
|
|
||||||
|
Fix a bug in `yesod devel` when cabal config has `tests: True` #864
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -28,27 +28,29 @@ cabal.sandbox.config
|
|||||||
{-# START_FILE Application.hs #-}
|
{-# START_FILE Application.hs #-}
|
||||||
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
||||||
module Application
|
module Application
|
||||||
( makeApplication
|
( getApplicationDev
|
||||||
, getApplicationDev
|
, appMain
|
||||||
|
, develMain
|
||||||
, makeFoundation
|
, makeFoundation
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
import Control.Monad.Logger (liftLoc)
|
||||||
import Import
|
import Import
|
||||||
import Yesod.Default.Config
|
import Language.Haskell.TH.Syntax (qLocation)
|
||||||
import Yesod.Default.Main
|
import Network.Wai.Handler.Warp (Settings, defaultSettings,
|
||||||
import Yesod.Default.Handlers
|
defaultShouldDisplayException,
|
||||||
import Network.Wai.Middleware.RequestLogger
|
runSettings, setHost,
|
||||||
( mkRequestLogger, outputFormat, OutputFormat (..), IPAddrSource (..), destination
|
setOnException, setPort)
|
||||||
)
|
import Network.Wai.Middleware.RequestLogger (Destination (Logger),
|
||||||
import qualified Network.Wai.Middleware.RequestLogger as RequestLogger
|
IPAddrSource (..),
|
||||||
import Network.HTTP.Client.Conduit (newManager)
|
OutputFormat (..), destination,
|
||||||
import System.Log.FastLogger (newStdoutLoggerSet, defaultBufSize)
|
mkRequestLogger, outputFormat)
|
||||||
import Network.Wai.Logger (clockDateCacher)
|
import System.Log.FastLogger (defaultBufSize, newStdoutLoggerSet,
|
||||||
import Data.Default (def)
|
toLogStr)
|
||||||
import Yesod.Core.Types (loggerSet, Logger (Logger))
|
|
||||||
|
|
||||||
-- Import all relevant handler modules here.
|
-- Import all relevant handler modules here.
|
||||||
-- Don't forget to add new modules to your cabal file!
|
-- Don't forget to add new modules to your cabal file!
|
||||||
|
import Handler.Common
|
||||||
import Handler.Home
|
import Handler.Home
|
||||||
|
|
||||||
-- This line actually creates our YesodDispatch instance. It is the second half
|
-- This line actually creates our YesodDispatch instance. It is the second half
|
||||||
@ -56,90 +58,114 @@ import Handler.Home
|
|||||||
-- comments there for more details.
|
-- comments there for more details.
|
||||||
mkYesodDispatch "App" resourcesApp
|
mkYesodDispatch "App" resourcesApp
|
||||||
|
|
||||||
-- This function allocates resources (such as a database connection pool),
|
-- | This function allocates resources (such as a database connection pool),
|
||||||
-- performs initialization and creates a WAI application. This is also the
|
-- performs initialization and return a foundation datatype value. This is also
|
||||||
-- place to put your migrate statements to have automatic database
|
-- the place to put your migrate statements to have automatic database
|
||||||
-- migrations handled by Yesod.
|
-- migrations handled by Yesod.
|
||||||
makeApplication :: AppConfig DefaultEnv Extra -> IO (Application, LogFunc)
|
makeFoundation :: AppSettings -> IO App
|
||||||
makeApplication conf = do
|
makeFoundation appSettings = do
|
||||||
foundation <- makeFoundation conf
|
-- 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)
|
||||||
|
|
||||||
-- Initialize the logging middleware
|
-- Return the foundation
|
||||||
|
return App {..}
|
||||||
|
|
||||||
|
-- | Convert our foundation to a WAI Application by calling @toWaiAppPlain@ and
|
||||||
|
-- applyng some additional middlewares.
|
||||||
|
makeApplication :: App -> IO Application
|
||||||
|
makeApplication foundation = do
|
||||||
logWare <- mkRequestLogger def
|
logWare <- mkRequestLogger def
|
||||||
{ outputFormat =
|
{ outputFormat =
|
||||||
if development
|
if appDetailedRequestLogging $ appSettings foundation
|
||||||
then Detailed True
|
then Detailed True
|
||||||
else Apache FromSocket
|
else Apache
|
||||||
, destination = RequestLogger.Logger $ loggerSet $ appLogger foundation
|
(if appIpFromHeader $ appSettings foundation
|
||||||
|
then FromFallback
|
||||||
|
else FromSocket)
|
||||||
|
, destination = Logger $ loggerSet $ appLogger foundation
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Create the WAI application and apply middlewares
|
-- Create the WAI application and apply middlewares
|
||||||
app <- toWaiAppPlain foundation
|
appPlain <- toWaiAppPlain foundation
|
||||||
let logFunc = messageLoggerSource foundation (appLogger foundation)
|
return $ logWare $ defaultMiddlewaresNoLogging appPlain
|
||||||
return (logWare $ defaultMiddlewaresNoLogging app, logFunc)
|
|
||||||
|
|
||||||
-- | Loads up any necessary settings, creates your foundation datatype, and
|
-- | Warp settings for the given foundation value.
|
||||||
-- performs some initialization.
|
warpSettings :: App -> Settings
|
||||||
makeFoundation :: AppConfig DefaultEnv Extra -> IO App
|
warpSettings foundation =
|
||||||
makeFoundation conf = do
|
setPort (appPort $ appSettings foundation)
|
||||||
manager <- newManager
|
$ setHost (appHost $ appSettings foundation)
|
||||||
s <- staticSite
|
$ setOnException (\_req e ->
|
||||||
|
when (defaultShouldDisplayException e) $ messageLoggerSource
|
||||||
|
foundation
|
||||||
|
(appLogger foundation)
|
||||||
|
$(qLocation >>= liftLoc)
|
||||||
|
"yesod"
|
||||||
|
LevelError
|
||||||
|
(toLogStr $ "Exception from Warp: " ++ show e))
|
||||||
|
defaultSettings
|
||||||
|
|
||||||
loggerSet' <- newStdoutLoggerSet defaultBufSize
|
-- | For yesod devel, return the Warp settings and WAI Application.
|
||||||
(getter, _) <- clockDateCacher
|
getApplicationDev :: IO (Settings, Application)
|
||||||
|
getApplicationDev = do
|
||||||
|
settings <- loadAppSettings [configSettingsYml] [] useEnv
|
||||||
|
foundation <- makeFoundation settings
|
||||||
|
app <- makeApplication foundation
|
||||||
|
wsettings <- getDevSettings $ warpSettings foundation
|
||||||
|
return (wsettings, app)
|
||||||
|
|
||||||
let logger = Yesod.Core.Types.Logger loggerSet' getter
|
-- | main function for use by yesod devel
|
||||||
foundation = App
|
develMain :: IO ()
|
||||||
{ settings = conf
|
develMain = develMainHelper getApplicationDev
|
||||||
, getStatic = s
|
|
||||||
, httpManager = manager
|
|
||||||
, appLogger = logger
|
|
||||||
}
|
|
||||||
|
|
||||||
return foundation
|
-- | The @main@ function for an executable running this site.
|
||||||
|
appMain :: IO ()
|
||||||
|
appMain = do
|
||||||
|
-- Get the settings from all relevant sources
|
||||||
|
settings <- loadAppSettingsArgs
|
||||||
|
-- fall back to compile-time values, set to [] to require values at runtime
|
||||||
|
[configSettingsYmlValue]
|
||||||
|
|
||||||
-- for yesod devel
|
-- allow environment variables to override
|
||||||
getApplicationDev :: IO (Int, Application)
|
useEnv
|
||||||
getApplicationDev =
|
|
||||||
defaultDevelApp loader (fmap fst . makeApplication)
|
-- Generate the foundation from the settings
|
||||||
where
|
foundation <- makeFoundation settings
|
||||||
loader = Yesod.Default.Config.loadConfig (configSettings Development)
|
|
||||||
{ csParseExtra = parseExtra
|
-- Generate a WAI Application from the foundation
|
||||||
}
|
app <- makeApplication foundation
|
||||||
|
|
||||||
|
-- Run the application with Warp
|
||||||
|
runSettings (warpSettings foundation) app
|
||||||
|
|
||||||
{-# START_FILE Foundation.hs #-}
|
{-# START_FILE Foundation.hs #-}
|
||||||
module Foundation where
|
module Foundation where
|
||||||
|
|
||||||
import Prelude
|
import ClassyPrelude.Yesod
|
||||||
import Yesod
|
import Settings
|
||||||
import Yesod.Static
|
|
||||||
import Yesod.Default.Config
|
|
||||||
import Yesod.Default.Util (addStaticContentExternal)
|
|
||||||
import Network.HTTP.Client.Conduit (Manager, HasHttpManager (getHttpManager))
|
|
||||||
import qualified Settings
|
|
||||||
import Settings.Development (development)
|
|
||||||
import Settings.StaticFiles
|
import Settings.StaticFiles
|
||||||
import Settings (widgetFile, Extra (..))
|
|
||||||
import Text.Jasmine (minifym)
|
|
||||||
import Text.Hamlet (hamletFile)
|
import Text.Hamlet (hamletFile)
|
||||||
|
import Text.Jasmine (minifym)
|
||||||
import Yesod.Core.Types (Logger)
|
import Yesod.Core.Types (Logger)
|
||||||
|
import Yesod.Default.Util (addStaticContentExternal)
|
||||||
|
|
||||||
-- | The site argument for your application. This can be a good place to
|
-- | The foundation datatype for your application. This can be a good place to
|
||||||
-- keep settings and values requiring initialization before your application
|
-- keep settings and values requiring initialization before your application
|
||||||
-- starts running, such as database connections. Every handler will have
|
-- starts running, such as database connections. Every handler will have
|
||||||
-- access to the data present here.
|
-- access to the data present here.
|
||||||
data App = App
|
data App = App
|
||||||
{ settings :: AppConfig DefaultEnv Extra
|
{ appSettings :: AppSettings
|
||||||
, getStatic :: Static -- ^ Settings for static file serving.
|
, appStatic :: Static -- ^ Settings for static file serving.
|
||||||
, httpManager :: Manager
|
, appHttpManager :: Manager
|
||||||
, appLogger :: Logger
|
, appLogger :: Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
instance HasHttpManager App where
|
instance HasHttpManager App where
|
||||||
getHttpManager = httpManager
|
getHttpManager = appHttpManager
|
||||||
|
|
||||||
-- Set up i18n messages. See the message folder.
|
|
||||||
mkMessage "App" "messages" "en"
|
|
||||||
|
|
||||||
-- This is where we define all of the routes in our application. For a full
|
-- This is where we define all of the routes in our application. For a full
|
||||||
-- explanation of the syntax, please see:
|
-- explanation of the syntax, please see:
|
||||||
@ -150,12 +176,15 @@ mkMessage "App" "messages" "en"
|
|||||||
-- explanation for this split.
|
-- explanation for this split.
|
||||||
mkYesodData "App" $(parseRoutesFile "config/routes")
|
mkYesodData "App" $(parseRoutesFile "config/routes")
|
||||||
|
|
||||||
|
-- | A convenient synonym for creating forms.
|
||||||
type Form x = Html -> MForm (HandlerT App IO) (FormResult x, Widget)
|
type Form x = Html -> MForm (HandlerT App IO) (FormResult x, Widget)
|
||||||
|
|
||||||
-- Please see the documentation for the Yesod typeclass. There are a number
|
-- Please see the documentation for the Yesod typeclass. There are a number
|
||||||
-- of settings which can be configured by overriding methods here.
|
-- of settings which can be configured by overriding methods here.
|
||||||
instance Yesod App where
|
instance Yesod App where
|
||||||
approot = ApprootMaster $ appRoot . settings
|
-- Controls the base of generated URLs. For more information on modifying,
|
||||||
|
-- see: https://github.com/yesodweb/yesod/wiki/Overriding-approot
|
||||||
|
approot = ApprootMaster $ appRoot . appSettings
|
||||||
|
|
||||||
-- Store session data on the client in encrypted cookies,
|
-- Store session data on the client in encrypted cookies,
|
||||||
-- default session idle timeout is 120 minutes
|
-- default session idle timeout is 120 minutes
|
||||||
@ -178,12 +207,6 @@ instance Yesod App where
|
|||||||
$(widgetFile "default-layout")
|
$(widgetFile "default-layout")
|
||||||
withUrlRenderer $(hamletFile "templates/default-layout-wrapper.hamlet")
|
withUrlRenderer $(hamletFile "templates/default-layout-wrapper.hamlet")
|
||||||
|
|
||||||
-- This is done to provide an optimization for serving static files from
|
|
||||||
-- a separate domain. Please see the staticRoot setting in Settings.hs
|
|
||||||
urlRenderOverride y (StaticR s) =
|
|
||||||
Just $ uncurry (joinPath y (Settings.staticRoot $ settings y)) $ renderRoute s
|
|
||||||
urlRenderOverride _ _ = Nothing
|
|
||||||
|
|
||||||
-- Routes not requiring authenitcation.
|
-- Routes not requiring authenitcation.
|
||||||
isAuthorized FaviconR _ = return Authorized
|
isAuthorized FaviconR _ = return Authorized
|
||||||
isAuthorized RobotsR _ = return Authorized
|
isAuthorized RobotsR _ = return Authorized
|
||||||
@ -194,21 +217,27 @@ instance Yesod App where
|
|||||||
-- and names them based on a hash of their content. This allows
|
-- and names them based on a hash of their content. This allows
|
||||||
-- expiration dates to be set far in the future without worry of
|
-- expiration dates to be set far in the future without worry of
|
||||||
-- users receiving stale content.
|
-- users receiving stale content.
|
||||||
addStaticContent =
|
addStaticContent ext mime content = do
|
||||||
addStaticContentExternal minifym genFileName Settings.staticDir (StaticR . flip StaticRoute [])
|
master <- getYesod
|
||||||
|
let staticDir = appStaticDir $ appSettings master
|
||||||
|
addStaticContentExternal
|
||||||
|
minifym
|
||||||
|
genFileName
|
||||||
|
staticDir
|
||||||
|
(StaticR . flip StaticRoute [])
|
||||||
|
ext
|
||||||
|
mime
|
||||||
|
content
|
||||||
where
|
where
|
||||||
-- Generate a unique filename based on the content itself
|
-- Generate a unique filename based on the content itself
|
||||||
genFileName lbs
|
genFileName lbs = "autogen-" ++ base64md5 lbs
|
||||||
| development = "autogen-" ++ base64md5 lbs
|
|
||||||
| otherwise = base64md5 lbs
|
|
||||||
|
|
||||||
-- Place Javascript at bottom of the body tag so the rest of the page loads first
|
|
||||||
jsLoader _ = BottomOfBody
|
|
||||||
|
|
||||||
-- What messages should be logged. The following includes all messages when
|
-- What messages should be logged. The following includes all messages when
|
||||||
-- in development, and warnings and errors in production.
|
-- in development, and warnings and errors in production.
|
||||||
shouldLog _ _source level =
|
shouldLog app _source level =
|
||||||
development || level == LevelWarn || level == LevelError
|
appShouldLogAll (appSettings app)
|
||||||
|
|| level == LevelWarn
|
||||||
|
|| level == LevelError
|
||||||
|
|
||||||
makeLogger = return . appLogger
|
makeLogger = return . appLogger
|
||||||
|
|
||||||
@ -217,23 +246,38 @@ instance Yesod App where
|
|||||||
instance RenderMessage App FormMessage where
|
instance RenderMessage App FormMessage where
|
||||||
renderMessage _ _ = defaultFormMessage
|
renderMessage _ _ = defaultFormMessage
|
||||||
|
|
||||||
-- | Get the 'Extra' value, used to hold data from the settings.yml file.
|
-- Note: Some functionality previously present in the scaffolding has been
|
||||||
getExtra :: Handler Extra
|
-- moved to documentation in the Wiki. Following are some hopefully helpful
|
||||||
getExtra = fmap (appExtra . settings) getYesod
|
-- links:
|
||||||
|
|
||||||
-- Note: previous versions of the scaffolding included a deliver function to
|
|
||||||
-- send emails. Unfortunately, there are too many different options for us to
|
|
||||||
-- give a reasonable default. Instead, the information is available on the
|
|
||||||
-- wiki:
|
|
||||||
--
|
--
|
||||||
-- https://github.com/yesodweb/yesod/wiki/Sending-email
|
-- https://github.com/yesodweb/yesod/wiki/Sending-email
|
||||||
|
-- https://github.com/yesodweb/yesod/wiki/Serve-static-files-from-a-separate-domain
|
||||||
|
-- https://github.com/yesodweb/yesod/wiki/i18n-messages-in-the-scaffolding
|
||||||
|
|
||||||
|
{-# START_FILE Handler/Common.hs #-}
|
||||||
|
-- | Common handler functions.
|
||||||
|
module Handler.Common where
|
||||||
|
|
||||||
|
import Data.FileEmbed (embedFile)
|
||||||
|
import Import
|
||||||
|
|
||||||
|
-- These handlers embed files in the executable at compile time to avoid a
|
||||||
|
-- runtime dependency, and for efficiency.
|
||||||
|
|
||||||
|
getFaviconR :: Handler TypedContent
|
||||||
|
getFaviconR = return $ TypedContent "image/x-icon"
|
||||||
|
$ toContent $(embedFile "config/favicon.ico")
|
||||||
|
|
||||||
|
getRobotsR :: Handler TypedContent
|
||||||
|
getRobotsR = return $ TypedContent typePlain
|
||||||
|
$ toContent $(embedFile "config/robots.txt")
|
||||||
|
|
||||||
{-# START_FILE Handler/Home.hs #-}
|
{-# START_FILE Handler/Home.hs #-}
|
||||||
module Handler.Home where
|
module Handler.Home where
|
||||||
|
|
||||||
import Import
|
import Import
|
||||||
import Yesod.Form.Bootstrap3
|
import Yesod.Form.Bootstrap3 (BootstrapFormLayout (..), renderBootstrap3,
|
||||||
( BootstrapFormLayout (..), renderBootstrap3, withSmallInput )
|
withSmallInput)
|
||||||
|
|
||||||
-- This is a handler function for the GET request method on the HomeR
|
-- This is a handler function for the GET request method on the HomeR
|
||||||
-- resource pattern. All of your resource patterns are defined in
|
-- resource pattern. All of your resource patterns are defined in
|
||||||
@ -275,30 +319,12 @@ module Import
|
|||||||
( module Import
|
( module Import
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Prelude as Import hiding (head, init, last,
|
import ClassyPrelude.Yesod as Import
|
||||||
readFile, tail, writeFile)
|
|
||||||
import Yesod as Import hiding (Route (..))
|
|
||||||
|
|
||||||
import Control.Applicative as Import (pure, (<$>), (<*>))
|
|
||||||
import Data.Text as Import (Text)
|
|
||||||
|
|
||||||
import Foundation as Import
|
import Foundation as Import
|
||||||
import Settings as Import
|
import Settings as Import
|
||||||
import Settings.Development as Import
|
|
||||||
import Settings.StaticFiles as Import
|
import Settings.StaticFiles as Import
|
||||||
|
import Yesod.Core.Types as Import (loggerSet)
|
||||||
#if __GLASGOW_HASKELL__ >= 704
|
import Yesod.Default.Config2 as Import
|
||||||
import Data.Monoid as Import
|
|
||||||
(Monoid (mappend, mempty, mconcat),
|
|
||||||
(<>))
|
|
||||||
#else
|
|
||||||
import Data.Monoid as Import
|
|
||||||
(Monoid (mappend, mempty, mconcat))
|
|
||||||
|
|
||||||
infixr 5 <>
|
|
||||||
(<>) :: Monoid m => m -> m -> m
|
|
||||||
(<>) = mappend
|
|
||||||
#endif
|
|
||||||
|
|
||||||
{-# START_FILE PROJECTNAME.cabal #-}
|
{-# START_FILE PROJECTNAME.cabal #-}
|
||||||
name: PROJECTNAME
|
name: PROJECTNAME
|
||||||
@ -320,7 +346,7 @@ library
|
|||||||
Import
|
Import
|
||||||
Settings
|
Settings
|
||||||
Settings.StaticFiles
|
Settings.StaticFiles
|
||||||
Settings.Development
|
Handler.Common
|
||||||
Handler.Home
|
Handler.Home
|
||||||
|
|
||||||
if flag(dev) || flag(library-only)
|
if flag(dev) || flag(library-only)
|
||||||
@ -344,13 +370,17 @@ library
|
|||||||
DeriveDataTypeable
|
DeriveDataTypeable
|
||||||
ViewPatterns
|
ViewPatterns
|
||||||
TupleSections
|
TupleSections
|
||||||
|
RecordWildCards
|
||||||
|
|
||||||
build-depends: base >= 4 && < 5
|
build-depends: base >= 4 && < 5
|
||||||
, yesod >= 1.4.0 && < 1.5
|
, yesod >= 1.4.1 && < 1.5
|
||||||
, yesod-core >= 1.4.0 && < 1.5
|
, yesod-core >= 1.4.0 && < 1.5
|
||||||
, yesod-auth >= 1.4.0 && < 1.5
|
, yesod-auth >= 1.4.0 && < 1.5
|
||||||
, yesod-static >= 1.4.0 && < 1.5
|
, yesod-static >= 1.4.0.3 && < 1.5
|
||||||
, yesod-form >= 1.4.0 && < 1.5
|
, yesod-form >= 1.4.0 && < 1.5
|
||||||
|
, classy-prelude >= 0.10.2
|
||||||
|
, classy-prelude-conduit >= 0.10.2
|
||||||
|
, classy-prelude-yesod >= 0.10.2
|
||||||
, bytestring >= 0.9 && < 0.11
|
, bytestring >= 0.9 && < 0.11
|
||||||
, text >= 0.11 && < 2.0
|
, text >= 0.11 && < 2.0
|
||||||
, template-haskell
|
, template-haskell
|
||||||
@ -368,10 +398,12 @@ library
|
|||||||
, monad-logger >= 0.3 && < 0.4
|
, monad-logger >= 0.3 && < 0.4
|
||||||
, fast-logger >= 2.2 && < 2.3
|
, fast-logger >= 2.2 && < 2.3
|
||||||
, wai-logger >= 2.2 && < 2.3
|
, wai-logger >= 2.2 && < 2.3
|
||||||
|
, file-embed
|
||||||
-- see https://github.com/yesodweb/yesod/issues/814
|
, safe
|
||||||
if !os(windows)
|
, unordered-containers
|
||||||
build-depends: unix
|
, containers
|
||||||
|
, vector
|
||||||
|
, time
|
||||||
|
|
||||||
executable PROJECTNAME
|
executable PROJECTNAME
|
||||||
if flag(library-only)
|
if flag(library-only)
|
||||||
@ -379,9 +411,7 @@ executable PROJECTNAME
|
|||||||
|
|
||||||
main-is: main.hs
|
main-is: main.hs
|
||||||
hs-source-dirs: app
|
hs-source-dirs: app
|
||||||
build-depends: base
|
build-depends: base, PROJECTNAME
|
||||||
, PROJECTNAME
|
|
||||||
, yesod
|
|
||||||
|
|
||||||
ghc-options: -threaded -O2 -rtsopts -with-rtsopts=-N
|
ghc-options: -threaded -O2 -rtsopts -with-rtsopts=-N
|
||||||
|
|
||||||
@ -409,10 +439,12 @@ test-suite test
|
|||||||
|
|
||||||
build-depends: base
|
build-depends: base
|
||||||
, PROJECTNAME
|
, PROJECTNAME
|
||||||
, yesod-test >= 1.4 && < 1.5
|
, yesod-test >= 1.4.2 && < 1.5
|
||||||
, yesod-core
|
, yesod-core
|
||||||
, yesod
|
, yesod
|
||||||
, hspec
|
, hspec
|
||||||
|
, classy-prelude
|
||||||
|
, classy-prelude-yesod
|
||||||
|
|
||||||
{-# START_FILE Settings.hs #-}
|
{-# START_FILE Settings.hs #-}
|
||||||
-- | Settings are centralized, as much as possible, into this file. This
|
-- | Settings are centralized, as much as possible, into this file. This
|
||||||
@ -422,40 +454,76 @@ test-suite test
|
|||||||
-- declared in the Foundation.hs file.
|
-- declared in the Foundation.hs file.
|
||||||
module Settings where
|
module Settings where
|
||||||
|
|
||||||
import Prelude
|
import ClassyPrelude.Yesod
|
||||||
import Text.Shakespeare.Text (st)
|
import Control.Exception (throw)
|
||||||
import Language.Haskell.TH.Syntax
|
import Data.Aeson (Result (..), fromJSON, withObject, (.!=),
|
||||||
import Yesod.Default.Config
|
(.:?))
|
||||||
import Yesod.Default.Util
|
import Data.FileEmbed (embedFile)
|
||||||
import Data.Text (Text)
|
import Data.Yaml (decodeEither')
|
||||||
import Data.Yaml
|
import Language.Haskell.TH.Syntax (Exp, Name, Q)
|
||||||
import Control.Applicative
|
import Network.Wai.Handler.Warp (HostPreference)
|
||||||
import Settings.Development
|
import Yesod.Default.Config2 (applyEnvValue, configSettingsYml)
|
||||||
import Data.Default (def)
|
import Yesod.Default.Util (WidgetFileSettings, widgetFileNoReload,
|
||||||
import Text.Hamlet
|
widgetFileReload)
|
||||||
|
|
||||||
-- Static setting below. Changing these requires a recompile
|
-- | Runtime settings to configure this application. These settings can be
|
||||||
|
-- loaded from various sources: defaults, environment variables, config files,
|
||||||
|
-- theoretically even a database.
|
||||||
|
data AppSettings = AppSettings
|
||||||
|
{ appStaticDir :: String
|
||||||
|
-- ^ Directory from which to serve static files.
|
||||||
|
, appRoot :: Text
|
||||||
|
-- ^ Base for all generated URLs.
|
||||||
|
, appHost :: HostPreference
|
||||||
|
-- ^ Host/interface the server should bind to.
|
||||||
|
, appPort :: Int
|
||||||
|
-- ^ Port to listen on
|
||||||
|
, appIpFromHeader :: Bool
|
||||||
|
-- ^ Get the IP address from the header when logging. Useful when sitting
|
||||||
|
-- behind a reverse proxy.
|
||||||
|
|
||||||
-- | The location of static files on your system. This is a file system
|
, appDetailedRequestLogging :: Bool
|
||||||
-- path. The default value works properly with your scaffolded site.
|
-- ^ Use detailed request logging system
|
||||||
staticDir :: FilePath
|
, appShouldLogAll :: Bool
|
||||||
staticDir = "static"
|
-- ^ Should all log messages be displayed?
|
||||||
|
, appReloadTemplates :: Bool
|
||||||
|
-- ^ Use the reload version of templates
|
||||||
|
, appMutableStatic :: Bool
|
||||||
|
-- ^ Assume that files in the static dir may change after compilation
|
||||||
|
, appSkipCombining :: Bool
|
||||||
|
-- ^ Perform no stylesheet/script combining
|
||||||
|
|
||||||
-- | The base URL for your static files. As you can see by the default
|
-- Example app-specific configuration values.
|
||||||
-- value, this can simply be "static" appended to your application root.
|
, appCopyright :: Text
|
||||||
-- A powerful optimization can be serving static files from a separate
|
-- ^ Copyright text to appear in the footer of the page
|
||||||
-- domain name. This allows you to use a web server optimized for static
|
, appAnalytics :: Maybe Text
|
||||||
-- files, more easily set expires and cache values, and avoid possibly
|
-- ^ Google Analytics code
|
||||||
-- costly transference of cookies on static files. For more information,
|
}
|
||||||
-- please see:
|
|
||||||
-- http://code.google.com/speed/page-speed/docs/request.html#ServeFromCookielessDomain
|
instance FromJSON AppSettings where
|
||||||
--
|
parseJSON = withObject "AppSettings" $ \o -> do
|
||||||
-- If you change the resource pattern for StaticR in Foundation.hs, you will
|
let defaultDev =
|
||||||
-- have to make a corresponding change here.
|
#if DEVELOPMENT
|
||||||
--
|
True
|
||||||
-- To see how this value is used, see urlRenderOverride in Foundation.hs
|
#else
|
||||||
staticRoot :: AppConfig DefaultEnv x -> Text
|
False
|
||||||
staticRoot conf = [st|#{appRoot conf}/static|]
|
#endif
|
||||||
|
appStaticDir <- o .: "static-dir"
|
||||||
|
appRoot <- o .: "approot"
|
||||||
|
appHost <- fromString <$> o .: "host"
|
||||||
|
appPort <- o .: "port"
|
||||||
|
appIpFromHeader <- o .: "ip-from-header"
|
||||||
|
|
||||||
|
appDetailedRequestLogging <- o .:? "detailed-logging" .!= defaultDev
|
||||||
|
appShouldLogAll <- o .:? "should-log-all" .!= defaultDev
|
||||||
|
appReloadTemplates <- o .:? "reload-templates" .!= defaultDev
|
||||||
|
appMutableStatic <- o .:? "mutable-static" .!= defaultDev
|
||||||
|
appSkipCombining <- o .:? "skip-combining" .!= defaultDev
|
||||||
|
|
||||||
|
appCopyright <- o .: "copyright"
|
||||||
|
appAnalytics <- o .:? "analytics"
|
||||||
|
|
||||||
|
return AppSettings {..}
|
||||||
|
|
||||||
-- | Settings for 'widgetFile', such as which template languages to support and
|
-- | Settings for 'widgetFile', such as which template languages to support and
|
||||||
-- default Hamlet settings.
|
-- default Hamlet settings.
|
||||||
@ -465,69 +533,34 @@ staticRoot conf = [st|#{appRoot conf}/static|]
|
|||||||
-- https://github.com/yesodweb/yesod/wiki/Overriding-widgetFile
|
-- https://github.com/yesodweb/yesod/wiki/Overriding-widgetFile
|
||||||
widgetFileSettings :: WidgetFileSettings
|
widgetFileSettings :: WidgetFileSettings
|
||||||
widgetFileSettings = def
|
widgetFileSettings = def
|
||||||
{ wfsHamletSettings = defaultHamletSettings
|
|
||||||
{ hamletNewlines = AlwaysNewlines
|
-- | How static files should be combined.
|
||||||
}
|
combineSettings :: CombineSettings
|
||||||
}
|
combineSettings = def
|
||||||
|
|
||||||
-- The rest of this file contains settings which rarely need changing by a
|
-- The rest of this file contains settings which rarely need changing by a
|
||||||
-- user.
|
-- user.
|
||||||
|
|
||||||
widgetFile :: String -> Q Exp
|
widgetFile :: String -> Q Exp
|
||||||
widgetFile = (if development then widgetFileReload
|
widgetFile = (if appReloadTemplates compileTimeAppSettings
|
||||||
|
then widgetFileReload
|
||||||
else widgetFileNoReload)
|
else widgetFileNoReload)
|
||||||
widgetFileSettings
|
widgetFileSettings
|
||||||
|
|
||||||
data Extra = Extra
|
-- | Raw bytes at compile time of @config/settings.yml@
|
||||||
{ extraCopyright :: Text
|
configSettingsYmlBS :: ByteString
|
||||||
, extraAnalytics :: Maybe Text -- ^ Google Analytics
|
configSettingsYmlBS = $(embedFile configSettingsYml)
|
||||||
} deriving Show
|
|
||||||
|
|
||||||
parseExtra :: DefaultEnv -> Object -> Parser Extra
|
-- | @config/settings.yml@, parsed to a @Value@.
|
||||||
parseExtra _ o = Extra
|
configSettingsYmlValue :: Value
|
||||||
<$> o .: "copyright"
|
configSettingsYmlValue = either throw id $ decodeEither' configSettingsYmlBS
|
||||||
<*> o .:? "analytics"
|
|
||||||
|
|
||||||
{-# START_FILE Settings/Development.hs #-}
|
-- | A version of @AppSettings@ parsed at compile time from @config/settings.yml@.
|
||||||
module Settings.Development where
|
compileTimeAppSettings :: AppSettings
|
||||||
|
compileTimeAppSettings =
|
||||||
import Prelude
|
case fromJSON $ applyEnvValue False mempty configSettingsYmlValue of
|
||||||
|
Error e -> error e
|
||||||
development :: Bool
|
Success settings -> settings
|
||||||
development =
|
|
||||||
#if DEVELOPMENT
|
|
||||||
True
|
|
||||||
#else
|
|
||||||
False
|
|
||||||
#endif
|
|
||||||
|
|
||||||
production :: Bool
|
|
||||||
production = not development
|
|
||||||
|
|
||||||
{-# START_FILE Settings/StaticFiles.hs #-}
|
|
||||||
module Settings.StaticFiles where
|
|
||||||
|
|
||||||
import Prelude (IO)
|
|
||||||
import Yesod.Static
|
|
||||||
import qualified Yesod.Static as Static
|
|
||||||
import Settings (staticDir)
|
|
||||||
import Settings.Development
|
|
||||||
import Language.Haskell.TH (Q, Exp, Name)
|
|
||||||
import Data.Default (def)
|
|
||||||
|
|
||||||
-- | use this to create your static file serving site
|
|
||||||
staticSite :: IO Static.Static
|
|
||||||
staticSite = if development then Static.staticDevel staticDir
|
|
||||||
else Static.static staticDir
|
|
||||||
|
|
||||||
-- | This generates easy references to files in the static directory at compile time,
|
|
||||||
-- giving you compile-time verification that referenced files exist.
|
|
||||||
-- Warning: any files added to your static directory during run-time can't be
|
|
||||||
-- accessed this way. You'll have to use their FilePath or URL to access them.
|
|
||||||
$(staticFiles Settings.staticDir)
|
|
||||||
|
|
||||||
combineSettings :: CombineSettings
|
|
||||||
combineSettings = def
|
|
||||||
|
|
||||||
-- The following two functions can be used to combine multiple CSS or JS files
|
-- The following two functions can be used to combine multiple CSS or JS files
|
||||||
-- at compile time to decrease the number of http requests.
|
-- at compile time to decrease the number of http requests.
|
||||||
@ -536,10 +569,26 @@ combineSettings = def
|
|||||||
-- > $(combineStylesheets 'StaticR [style1_css, style2_css])
|
-- > $(combineStylesheets 'StaticR [style1_css, style2_css])
|
||||||
|
|
||||||
combineStylesheets :: Name -> [Route Static] -> Q Exp
|
combineStylesheets :: Name -> [Route Static] -> Q Exp
|
||||||
combineStylesheets = combineStylesheets' development combineSettings
|
combineStylesheets = combineStylesheets'
|
||||||
|
(appSkipCombining compileTimeAppSettings)
|
||||||
|
combineSettings
|
||||||
|
|
||||||
combineScripts :: Name -> [Route Static] -> Q Exp
|
combineScripts :: Name -> [Route Static] -> Q Exp
|
||||||
combineScripts = combineScripts' development combineSettings
|
combineScripts = combineScripts'
|
||||||
|
(appSkipCombining compileTimeAppSettings)
|
||||||
|
combineSettings
|
||||||
|
|
||||||
|
{-# START_FILE Settings/StaticFiles.hs #-}
|
||||||
|
module Settings.StaticFiles where
|
||||||
|
|
||||||
|
import Settings (appStaticDir, compileTimeAppSettings)
|
||||||
|
import Yesod.Static (staticFiles)
|
||||||
|
|
||||||
|
-- | This generates easy references to files in the static directory at compile time,
|
||||||
|
-- giving you compile-time verification that referenced files exist.
|
||||||
|
-- Warning: any files added to your static directory during run-time can't be
|
||||||
|
-- accessed this way. You'll have to use their FilePath or URL to access them.
|
||||||
|
staticFiles (appStaticDir compileTimeAppSettings)
|
||||||
|
|
||||||
{-# START_FILE app/DevelMain.hs #-}
|
{-# START_FILE app/DevelMain.hs #-}
|
||||||
-- | Development version to be run inside GHCi.
|
-- | Development version to be run inside GHCi.
|
||||||
@ -606,19 +655,24 @@ update = do
|
|||||||
start :: MVar () -- ^ Written to when the thread is killed.
|
start :: MVar () -- ^ Written to when the thread is killed.
|
||||||
-> IO ThreadId
|
-> IO ThreadId
|
||||||
start done = do
|
start done = do
|
||||||
(port,app) <- getApplicationDev
|
(settings,app) <- getApplicationDev
|
||||||
forkIO (finally (runSettings (setPort port defaultSettings) app)
|
forkIO (finally (runSettings settings app)
|
||||||
(putMVar done ()))
|
(putMVar done ()))
|
||||||
|
|
||||||
|
{-# START_FILE app/devel.hs #-}
|
||||||
|
{-# LANGUAGE PackageImports #-}
|
||||||
|
import "PROJECTNAME" Application (develMain)
|
||||||
|
import Prelude (IO)
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = develMain
|
||||||
|
|
||||||
{-# START_FILE app/main.hs #-}
|
{-# START_FILE app/main.hs #-}
|
||||||
import Prelude (IO)
|
import Prelude (IO)
|
||||||
import Yesod.Default.Config (fromArgs)
|
import Application (appMain)
|
||||||
import Yesod.Default.Main (defaultMainLog)
|
|
||||||
import Settings (parseExtra)
|
|
||||||
import Application (makeApplication)
|
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = defaultMainLog (fromArgs parseExtra) makeApplication
|
main = appMain
|
||||||
|
|
||||||
{-# START_FILE BASE64 config/favicon.ico #-}
|
{-# START_FILE BASE64 config/favicon.ico #-}
|
||||||
AAABAAIAEBAAAAEAIABoBAAAJgAAABAQAgABAAEAsAAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAA
|
AAABAAIAEBAAAAEAIABoBAAAJgAAABAQAgABAAEAsAAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAA
|
||||||
@ -713,7 +767,7 @@ stanzas:
|
|||||||
User-agent: *
|
User-agent: *
|
||||||
|
|
||||||
{-# START_FILE config/routes #-}
|
{-# START_FILE config/routes #-}
|
||||||
/static StaticR Static getStatic
|
/static StaticR Static appStatic
|
||||||
|
|
||||||
/favicon.ico FaviconR GET
|
/favicon.ico FaviconR GET
|
||||||
/robots.txt RobotsR GET
|
/robots.txt RobotsR GET
|
||||||
@ -721,155 +775,28 @@ User-agent: *
|
|||||||
/ HomeR GET POST
|
/ HomeR GET POST
|
||||||
|
|
||||||
{-# START_FILE config/settings.yml #-}
|
{-# START_FILE config/settings.yml #-}
|
||||||
Default: &defaults
|
static-dir: "_env:STATIC_DIR:static"
|
||||||
host: "*4" # any IPv4 host
|
host: "_env:HOST:*4" # any IPv4 host
|
||||||
port: 3000
|
port: "_env:PORT:3000"
|
||||||
approot: "http://localhost:3000"
|
approot: "_env:APPROOT:http://localhost:3000"
|
||||||
copyright: Insert copyright statement here
|
ip-from-header: "_env:IP_FROM_HEADER:false"
|
||||||
#analytics: UA-YOURCODE
|
|
||||||
|
|
||||||
Development:
|
# Optional values with the following production defaults.
|
||||||
<<: *defaults
|
# In development, they default to the inverse.
|
||||||
|
#
|
||||||
|
# development: false
|
||||||
|
# detailed-logging: false
|
||||||
|
# should-log-all: false
|
||||||
|
# reload-templates: false
|
||||||
|
# mutable-static: false
|
||||||
|
# skip-combining: false
|
||||||
|
|
||||||
Testing:
|
copyright: Insert copyright statement here
|
||||||
<<: *defaults
|
#analytics: UA-YOURCODE
|
||||||
|
|
||||||
Staging:
|
{-# START_FILE config/test-settings.yml #-}
|
||||||
<<: *defaults
|
database:
|
||||||
|
database: PROJECTNAME_test
|
||||||
Production:
|
|
||||||
#approot: "http://www.example.com"
|
|
||||||
<<: *defaults
|
|
||||||
|
|
||||||
{-# START_FILE deploy/Procfile #-}
|
|
||||||
# Free deployment to Heroku.
|
|
||||||
#
|
|
||||||
# !! Warning: You must use a 64 bit machine to compile !!
|
|
||||||
#
|
|
||||||
# This could mean using a virtual machine. Give your VM as much memory as you can to speed up linking.
|
|
||||||
#
|
|
||||||
# Basic Yesod setup:
|
|
||||||
#
|
|
||||||
# * Move this file out of the deploy directory and into your root directory
|
|
||||||
#
|
|
||||||
# mv deploy/Procfile ./
|
|
||||||
#
|
|
||||||
# * Create an empty package.json
|
|
||||||
# echo '{ "name": "PROJECTNAME", "version": "0.0.1", "dependencies": {} }' >> package.json
|
|
||||||
#
|
|
||||||
# Postgresql Yesod setup:
|
|
||||||
#
|
|
||||||
# * add dependencies on the "heroku", "aeson" and "unordered-containers" packages in your cabal file
|
|
||||||
#
|
|
||||||
# * add code in Application.hs to use the heroku package and load the connection parameters.
|
|
||||||
# The below works for Postgresql.
|
|
||||||
#
|
|
||||||
# import Data.HashMap.Strict as H
|
|
||||||
# import Data.Aeson.Types as AT
|
|
||||||
# #ifndef DEVELOPMENT
|
|
||||||
# import qualified Web.Heroku
|
|
||||||
# #endif
|
|
||||||
#
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# makeFoundation :: AppConfig DefaultEnv Extra -> Logger -> IO App
|
|
||||||
# makeFoundation conf setLogger = do
|
|
||||||
# manager <- newManager def
|
|
||||||
# s <- staticSite
|
|
||||||
# hconfig <- loadHerokuConfig
|
|
||||||
# dbconf <- withYamlEnvironment "config/postgresql.yml" (appEnv conf)
|
|
||||||
# (Database.Persist.Store.loadConfig . combineMappings hconfig) >>=
|
|
||||||
# Database.Persist.Store.applyEnv
|
|
||||||
# p <- Database.Persist.Store.createPoolConfig (dbconf :: Settings.PersistConfig)
|
|
||||||
# Database.Persist.Store.runPool dbconf (runMigration migrateAll) p
|
|
||||||
# return $ App conf setLogger s p manager dbconf
|
|
||||||
#
|
|
||||||
# #ifndef DEVELOPMENT
|
|
||||||
# canonicalizeKey :: (Text, val) -> (Text, val)
|
|
||||||
# canonicalizeKey ("dbname", val) = ("database", val)
|
|
||||||
# canonicalizeKey pair = pair
|
|
||||||
#
|
|
||||||
# toMapping :: [(Text, Text)] -> AT.Value
|
|
||||||
# toMapping xs = AT.Object $ M.fromList $ map (\(key, val) -> (key, AT.String val)) xs
|
|
||||||
# #endif
|
|
||||||
#
|
|
||||||
# combineMappings :: AT.Value -> AT.Value -> AT.Value
|
|
||||||
# combineMappings (AT.Object m1) (AT.Object m2) = AT.Object $ m1 `M.union` m2
|
|
||||||
# combineMappings _ _ = error "Data.Object is not a Mapping."
|
|
||||||
#
|
|
||||||
# loadHerokuConfig :: IO AT.Value
|
|
||||||
# loadHerokuConfig = do
|
|
||||||
# #ifdef DEVELOPMENT
|
|
||||||
# return $ AT.Object M.empty
|
|
||||||
# #else
|
|
||||||
# Web.Heroku.dbConnParams >>= return . toMapping . map canonicalizeKey
|
|
||||||
# #endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Heroku setup:
|
|
||||||
# Find the Heroku guide. Roughly:
|
|
||||||
#
|
|
||||||
# * sign up for a heroku account and register your ssh key
|
|
||||||
# * create a new application on the *cedar* stack
|
|
||||||
#
|
|
||||||
# * make your Yesod project the git repository for that application
|
|
||||||
# * create a deploy branch
|
|
||||||
#
|
|
||||||
# git checkout -b deploy
|
|
||||||
#
|
|
||||||
# Repeat these steps to deploy:
|
|
||||||
# * add your web executable binary (referenced below) to the git repository
|
|
||||||
#
|
|
||||||
# git checkout deploy
|
|
||||||
# git add ./dist/build/PROJECTNAME/PROJECTNAME
|
|
||||||
# git commit -m deploy
|
|
||||||
#
|
|
||||||
# * push to Heroku
|
|
||||||
#
|
|
||||||
# git push heroku deploy:master
|
|
||||||
|
|
||||||
|
|
||||||
# Heroku configuration that runs your app
|
|
||||||
web: ./dist/build/PROJECTNAME/PROJECTNAME production -p $PORT
|
|
||||||
|
|
||||||
{-# START_FILE devel.hs #-}
|
|
||||||
{-# LANGUAGE CPP #-}
|
|
||||||
{-# LANGUAGE PackageImports #-}
|
|
||||||
import "PROJECTNAME" Application (getApplicationDev)
|
|
||||||
import Network.Wai.Handler.Warp
|
|
||||||
(runSettings, defaultSettings, setPort)
|
|
||||||
import Control.Concurrent (forkIO)
|
|
||||||
import System.Directory (doesFileExist, removeFile)
|
|
||||||
import System.Exit (exitSuccess)
|
|
||||||
import Control.Concurrent (threadDelay)
|
|
||||||
|
|
||||||
#ifndef mingw32_HOST_OS
|
|
||||||
import System.Posix.Signals (installHandler, sigINT, Handler(Catch))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
main :: IO ()
|
|
||||||
main = do
|
|
||||||
#ifndef mingw32_HOST_OS
|
|
||||||
_ <- installHandler sigINT (Catch $ return ()) Nothing
|
|
||||||
#endif
|
|
||||||
|
|
||||||
putStrLn "Starting devel application"
|
|
||||||
(port, app) <- getApplicationDev
|
|
||||||
forkIO $ runSettings (setPort port defaultSettings) app
|
|
||||||
loop
|
|
||||||
|
|
||||||
loop :: IO ()
|
|
||||||
loop = do
|
|
||||||
threadDelay 100000
|
|
||||||
e <- doesFileExist "yesod-devel/devel-terminate"
|
|
||||||
if e then terminateDevel else loop
|
|
||||||
|
|
||||||
terminateDevel :: IO ()
|
|
||||||
terminateDevel = exitSuccess
|
|
||||||
|
|
||||||
{-# START_FILE messages/en.msg #-}
|
|
||||||
Hello: Hello
|
|
||||||
|
|
||||||
{-# START_FILE static/css/bootstrap.css #-}
|
{-# START_FILE static/css/bootstrap.css #-}
|
||||||
/*!
|
/*!
|
||||||
@ -8835,9 +8762,9 @@ $newline never
|
|||||||
<div id="main" role="main">
|
<div id="main" role="main">
|
||||||
^{pageBody pc}
|
^{pageBody pc}
|
||||||
<footer>
|
<footer>
|
||||||
#{extraCopyright $ appExtra $ settings master}
|
#{appCopyright $ appSettings master}
|
||||||
|
|
||||||
$maybe analytics <- extraAnalytics $ appExtra $ settings master
|
$maybe analytics <- appAnalytics $ appSettings master
|
||||||
<script>
|
<script>
|
||||||
if(!window.location.href.match(/localhost/)){
|
if(!window.location.href.match(/localhost/)){
|
||||||
window._gaq = [['_setAccount','#{analytics}'],['_trackPageview'],['_trackPageLoadTime']];
|
window._gaq = [['_setAccount','#{analytics}'],['_trackPageview'],['_trackPageLoadTime']];
|
||||||
@ -8860,7 +8787,7 @@ $maybe msg <- mmsg
|
|||||||
^{widget}
|
^{widget}
|
||||||
|
|
||||||
{-# START_FILE templates/homepage.hamlet #-}
|
{-# START_FILE templates/homepage.hamlet #-}
|
||||||
<h1>_{MsgHello}
|
<h1>Welcome to Yesod!
|
||||||
|
|
||||||
<ol>
|
<ol>
|
||||||
<li>Now that you have a working project you should use the #
|
<li>Now that you have a working project you should use the #
|
||||||
@ -8911,21 +8838,36 @@ h2##{aDomId} {
|
|||||||
color: #990
|
color: #990
|
||||||
}
|
}
|
||||||
|
|
||||||
{-# START_FILE test/Handler/HomeSpec.hs #-}
|
{-# START_FILE test/Handler/CommonSpec.hs #-}
|
||||||
module Handler.HomeSpec
|
module Handler.CommonSpec (spec) where
|
||||||
( spec
|
|
||||||
) where
|
|
||||||
|
|
||||||
import TestImport
|
import TestImport
|
||||||
|
|
||||||
spec :: Spec
|
spec :: Spec
|
||||||
spec =
|
spec = withApp $ do
|
||||||
ydescribe "These are some example tests" $ do
|
describe "robots.txt" $ do
|
||||||
|
it "gives a 200" $ do
|
||||||
|
get RobotsR
|
||||||
|
statusIs 200
|
||||||
|
it "has correct User-agent" $ do
|
||||||
|
get RobotsR
|
||||||
|
bodyContains "User-agent: *"
|
||||||
|
describe "favicon.ico" $ do
|
||||||
|
it "gives a 200" $ do
|
||||||
|
get FaviconR
|
||||||
|
statusIs 200
|
||||||
|
|
||||||
yit "loads the index and checks it looks right" $ do
|
{-# START_FILE test/Handler/HomeSpec.hs #-}
|
||||||
|
module Handler.HomeSpec (spec) where
|
||||||
|
|
||||||
|
import TestImport
|
||||||
|
|
||||||
|
spec :: Spec
|
||||||
|
spec = withApp $ do
|
||||||
|
it "loads the index and checks it looks right" $ do
|
||||||
get HomeR
|
get HomeR
|
||||||
statusIs 200
|
statusIs 200
|
||||||
htmlAllContain "h1" "Hello"
|
htmlAllContain "h1" "Welcome to Yesod"
|
||||||
|
|
||||||
request $ do
|
request $ do
|
||||||
setMethod "POST"
|
setMethod "POST"
|
||||||
@ -8941,39 +8883,26 @@ spec =
|
|||||||
htmlAllContain ".message" "text/plain"
|
htmlAllContain ".message" "text/plain"
|
||||||
|
|
||||||
{-# START_FILE test/Spec.hs #-}
|
{-# START_FILE test/Spec.hs #-}
|
||||||
module Main where
|
{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
|
||||||
|
|
||||||
import Import
|
|
||||||
import Yesod.Default.Config
|
|
||||||
import Yesod.Test
|
|
||||||
import Test.Hspec (hspec)
|
|
||||||
import Application (makeFoundation)
|
|
||||||
|
|
||||||
import qualified Handler.HomeSpec
|
|
||||||
|
|
||||||
main :: IO ()
|
|
||||||
main = do
|
|
||||||
conf <- Yesod.Default.Config.loadConfig $ (configSettings Testing)
|
|
||||||
{ csParseExtra = parseExtra
|
|
||||||
}
|
|
||||||
foundation <- makeFoundation conf
|
|
||||||
hspec $ do
|
|
||||||
yesodSpec foundation $ do
|
|
||||||
Handler.HomeSpec.spec
|
|
||||||
|
|
||||||
{-# START_FILE test/TestImport.hs #-}
|
{-# START_FILE test/TestImport.hs #-}
|
||||||
module TestImport
|
module TestImport
|
||||||
( module Yesod.Test
|
( module TestImport
|
||||||
, module Foundation
|
, module X
|
||||||
, module Prelude
|
|
||||||
, Spec
|
|
||||||
, Example
|
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Yesod.Test
|
import Application (makeFoundation)
|
||||||
import Prelude
|
import ClassyPrelude as X
|
||||||
import Foundation
|
import Foundation as X
|
||||||
|
import Test.Hspec as X
|
||||||
|
import Yesod.Default.Config2 (ignoreEnv, loadAppSettings)
|
||||||
|
import Yesod.Test as X
|
||||||
|
|
||||||
type Spec = YesodSpec App
|
withApp :: SpecWith App -> Spec
|
||||||
type Example = YesodExample App
|
withApp = before $ do
|
||||||
|
settings <- loadAppSettings
|
||||||
|
["config/test-settings.yml", "config/settings.yml"]
|
||||||
|
[]
|
||||||
|
ignoreEnv
|
||||||
|
makeFoundation settings
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
|||||||
name: yesod-bin
|
name: yesod-bin
|
||||||
version: 1.4.0.9
|
version: 1.4.1
|
||||||
license: MIT
|
license: MIT
|
||||||
license-file: LICENSE
|
license-file: LICENSE
|
||||||
author: Michael Snoyman <michael@snoyman.com>
|
author: Michael Snoyman <michael@snoyman.com>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user