before flake update

This commit is contained in:
Dennis Frieberg 2024-10-08 14:17:49 +02:00
parent 53d405d386
commit 7ec9a8f10e
No known key found for this signature in database
GPG key ID: 7C58AFED036072C5
15 changed files with 336 additions and 38 deletions

3
.gitignore vendored
View file

@ -33,3 +33,6 @@ result-*
*.sqlite3-shm
*.sqlite3-wal
static/tmp/
# ---> Editor
tags

View file

@ -38,11 +38,13 @@ library
Foundation
Handler.Common
Handler.Home
Handler.Station
Import
Import.NoFoundation
Model
Settings
Settings.StaticFiles
Json
other-modules:
Paths_OwOpointTracker
hs-source-dirs:
@ -75,6 +77,7 @@ library
, template-haskell
, text >=0.11 && <2.1
, time
, tomland
, unordered-containers
, vector
, wai

View file

@ -1,18 +1,25 @@
-- By default this file is used by `persistFileWith` in Model.hs (which is imported by Foundation.hs)
-- Syntax for this file here: https://github.com/yesodweb/persistent/blob/master/docs/Persistent-entity-syntax.md
User
ident Text
password Text Maybe
UniqueUser ident
deriving Typeable
Email
email Text
userId UserId Maybe
verkey Text Maybe
UniqueEmail email
Comment json -- Adding "json" causes ToJSON and FromJSON instances to be derived.
message Text
userId UserId Maybe
deriving Eq
deriving Show
Round
stationId Text
tutorPoints Int
erstiePoints Int
number Int
UniqueRoundStation number stationId
--User
-- ident Text
-- password Text Maybe
-- UniqueUser ident
-- deriving Typeable
--Email
-- email Text
-- userId UserId Maybe
-- verkey Text Maybe
-- UniqueEmail email
--Comment json -- Adding "json" causes ToJSON and FromJSON instances to be derived.
-- message Text
-- userId UserId Maybe
-- deriving Eq
-- deriving Show

View file

@ -9,6 +9,13 @@
/ HomeR GET
-- stationName
/station/#Text StationR GET
-- stationName/roundNumber
/station/#Text/#Int StationRoundR GET POST
-- /comments CommentR POST
-- /profile ProfileR GET

View file

@ -37,4 +37,7 @@ database:
poolsize: "_env:YESOD_SQLITE_POOLSIZE:10"
copyright: Insert copyright statement here
#analytics: UA-YOURCODE
stations:
- station-id: "test"
station-name: "Test"

43
settings.yml Normal file
View file

@ -0,0 +1,43 @@
# Values formatted like "_env:YESOD_ENV_VAR_NAME:default_value" can be overridden by the specified environment variable.
# See https://github.com/yesodweb/yesod/wiki/Configuration#overriding-configuration-values-with-environment-variables
static-dir: "_env:YESOD_STATIC_DIR:static"
host: "_env:YESOD_HOST:*4" # any IPv4 host
port: "_env:YESOD_PORT:3000" # NB: The port `yesod devel` uses is distinct from this value. Set the `yesod devel` port from the command line.
# For `keter` user, enable the follwing line, and comment out previous one.
#port: "_env:PORT:3000" # `keter` uses `PORT` env var name
ip-from-header: "_env:YESOD_IP_FROM_HEADER:false"
# Default behavior: determine the application root from the request headers.
# Uncomment to set an explicit approot
#approot: "_env:YESOD_APPROOT:http://localhost:3000"
# By default, `yesod devel` runs in development, and built executables use
# production settings (see below). To override this, use the following:
#
# development: false
# Optional values with the following production defaults.
# In development, they default to the inverse.
#
# detailed-logging: false
# should-log-all: false
# reload-templates: false
# mutable-static: false
# skip-combining: false
# auth-dummy-login : false
# NB: If you need a numeric value (e.g. 123) to parse as a String, wrap it in single quotes (e.g. "_env:YESOD_PGPASS:'123'")
# See https://github.com/yesodweb/yesod/wiki/Configuration#parsing-numeric-values-as-strings
database:
# See config/test-settings.yml for an override during tests
database: "_env:YESOD_SQLITE_DATABASE:OwOpointTracker.sqlite3"
poolsize: "_env:YESOD_SQLITE_POOLSIZE:10"
copyright: Insert copyright statement here
stations:
- station-id: "testi"
station-name: "Test"

View file

@ -42,6 +42,7 @@ import System.Log.FastLogger (defaultBufSize, newStdoutLoggerSet,
-- Don't forget to add new modules to your cabal file!
import Handler.Common
import Handler.Home
import Handler.Station
-- This line actually creates our YesodDispatch instance. It is the second half
-- of the call to mkYesodData which occurs in Foundation.hs. Please see the

View file

@ -39,15 +39,15 @@ data App = App
, appLogger :: Logger
}
data MenuItem = MenuItem
{ menuItemLabel :: Text
, menuItemRoute :: Route App
, menuItemAccessCallback :: Bool
}
data MenuTypes
= NavbarLeft MenuItem
| NavbarRight MenuItem
--data MenuItem = MenuItem
-- { menuItemLabel :: Text
-- , menuItemRoute :: Route App
-- , menuItemAccessCallback :: Bool
-- }
--
--data MenuTypes
-- = NavbarLeft MenuItem
-- | NavbarRight MenuItem
-- This is where we define all of the routes in our application. For a full
-- explanation of the syntax, please see:

View file

@ -3,6 +3,7 @@
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeApplications #-}
module Handler.Home where
import Import
@ -28,13 +29,13 @@ getHomeR = do
-- let submission = Nothing :: Maybe FileForm
-- handlerName = "getHomeR" :: Text
-- allComments <- runDB $ getAllComments
rou <- runDB $ selectList [] []
let rounds = fmap entityVal rou
defaultLayout $ do
-- let (commentFormId, commentTextareaId, commentListId) = commentIds
aDomId <- newIdent
setTitle "OwO Geländespielpunkte"
let tutorPoints = 5 :: Int
let erstiePoints = 3 :: Int
let tutorP = sum (fmap roundTutorPoints rounds)
let erstieP = sum (fmap roundErstiePoints rounds)
$(widgetFile "homepage")
--postHomeR :: Handler Html

155
src/Handler/Station.hs Normal file
View file

@ -0,0 +1,155 @@
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
module Handler.Station where
import Import
import Json
import qualified Data.Map as M
--import Yesod.Form.Bootstrap3 (BootstrapFormLayout (..), renderBootstrap3)
--import Text.Julius (RawJS (..))
checkStation :: Text -> Handler Text
checkStation stationIdentifier = do
stationMap <- getsYesod (appStations . appSettings)
let stat = stationMap M.!? stationIdentifier :: Maybe Text
case stat of
Nothing -> notFound
Just m -> return m
repsertBy :: (MonadIO m, PersistUniqueRead backend, PersistRecordBackend record backend, AtLeastOneUniqueKey record, SafeToInsert record) => record -> ReaderT backend m ()
repsertBy val = do
valM <- getByValue val
case valM of
Nothing -> insert_ val
Just (Entity key _) -> replace key val
getStationR :: Text -> Handler Html
getStationR stationIdentifier = do
station <- checkStation stationIdentifier
rounds <- runDB $ do
rou <- selectList [RoundStationId ==. stationIdentifier] []
return (fmap entityVal rou :: [Round])
defaultLayout $ do
setTitle $ "OwO Station"
$(widgetFile "station")
-- postStationR :: Text -> Handler Html
-- postStationR stationIdentifier = do
-- station <- checkStation stationIdentifier
-- ((result,widget),enctype) <- runFormPost (roundForm Nothing Nothing Nothing)
-- case result of
-- FormSuccess roundFormD -> do
-- runDB $ upsertBy (UniqueRoundStation (roundNumberForm roundFormD) stationIdentifier) ( Round (stationIdentifier)(tutorPointsForm roundFormD)(erstiePointsForm roundFormD)(roundNumberForm roundFormD))
-- redirect $ StationRoundR stationIdentifier (roundNumberForm roundFormD)
-- FormFailure errors -> error "Form Failure"
-- FormMissing -> error "Form Missing"
data RoundForm = RoundForm
{ tutorPointsForm :: Int
, erstiePointsForm :: Int
}
deriving Show
roundForm :: Maybe Int -> Maybe Int -> Form RoundForm
roundForm v w = renderDivs $ RoundForm
<$> areq intField "Tutor Points" v
<*> areq intField "Erstie Points" w
getStationRoundR :: Text -> Int -> Handler Html
getStationRoundR stationIdentifier roundNumber = do
station <- checkStation stationIdentifier
mRoundEntity <- runDB $ getBy $ UniqueRoundStation roundNumber stationIdentifier
case mRoundEntity of
Nothing -> do
(roundFormWidget,roundFormEnctype) <- generateFormPost (roundForm Nothing Nothing)
defaultLayout $ do
setTitle $ "OwO Round"
$(widgetFile "round")
Just roundEntity -> do
let round = entityVal roundEntity
(roundFormWidget,roundFormEnctype) <- generateFormPost (roundForm (Just $ roundTutorPoints round) (Just $ roundErstiePoints round))
defaultLayout $ do
setTitle $ "OwO Round"
$(widgetFile "round")
postStationRoundR :: Text -> Int -> Handler Html
postStationRoundR stationIdentifier roundNumber = do
station <- checkStation stationIdentifier
((result,widget),enctype) <- runFormPost (roundForm Nothing Nothing)
case result of
FormSuccess roundFormD -> do
runDB $ repsertBy $ Round (stationIdentifier)(tutorPointsForm roundFormD)(erstiePointsForm roundFormD) roundNumber
redirect $ StationRoundR stationIdentifier (roundNumber + 1)
FormFailure errors -> error "Form Failure"
FormMissing -> error "Form Missing"
-- Define our data that will be used for creating the form.
--data FileForm = FileForm
-- { fileInfo :: FileInfo
-- , fileDescription :: Text
-- }
-- This is a handler function for the GET request method on the HomeR
-- resource pattern. All of your resource patterns are defined in
-- config/routes.yesodroutes
--
-- The majority of the code you will write in Yesod lives in these handler
-- functions. You can spread them across multiple files if you are so
-- inclined, or create a single monolithic file.
--getHomeR :: Handler Html
--getHomeR = do
-- (formWidget, formEnctype) <- generateFormPost sampleForm
-- let submission = Nothing :: Maybe FileForm
-- handlerName = "getHomeR" :: Text
-- allComments <- runDB $ getAllComments
-- defaultLayout $ do
-- let (commentFormId, commentTextareaId, commentListId) = commentIds
-- aDomId <- newIdent
-- setTitle "OwO Geländespielpunkte"
-- let tutorPoints = 5 :: Int
-- let erstiePoints = 3 :: Int
-- $(widgetFile "homepage")
--postHomeR :: Handler Html
--postHomeR = do
-- ((result, formWidget), formEnctype) <- runFormPost sampleForm
-- let handlerName = "postHomeR" :: Text
-- submission = case result of
-- FormSuccess res -> Just res
-- _ -> Nothing
-- allComments <- runDB $ getAllComments
--
-- defaultLayout $ do
-- let (commentFormId, commentTextareaId, commentListId) = commentIds
-- aDomId <- newIdent
-- setTitle "Welcome To Yesod!"
-- $(widgetFile "homepage")
--
--sampleForm :: Form FileForm
--sampleForm = renderBootstrap3 BootstrapBasicForm $ FileForm
-- <$> fileAFormReq "Choose a file"
-- <*> areq textField textSettings Nothing
-- -- Add attributes like the placeholder and CSS classes.
-- where textSettings = FieldSettings
-- { fsLabel = "What's on the file?"
-- , fsTooltip = Nothing
-- , fsId = Nothing
-- , fsName = Nothing
-- , fsAttrs =
-- [ ("class", "form-control")
-- , ("placeholder", "File description")
-- ]
-- }
--
--commentIds :: (Text, Text, Text)
--commentIds = ("js-commentForm", "js-createCommentTextarea", "js-commentList")
--
--getAllComments :: DB [Entity Comment]
--getAllComments = selectList [] [Asc CommentId]

38
src/Json.hs Normal file
View file

@ -0,0 +1,38 @@
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskell #-}
module Json where
import ClassyPrelude.Yesod
import Data.Aeson.TH
data ResRound = ResRound
{ resRoundNumber :: Int
, resRoundErstiePoints :: Int
, resRoundTutorPoints :: Int
}
deriving Show
$(deriveJSON defaultOptions{fieldLabelModifier = drop 3} ''ResRound)
data ResStation = ResStation
{ resStationName :: Text
}
deriving Show
$(deriveJSON defaultOptions{fieldLabelModifier = drop 3} ''ResStation)
data ResScore = ResScore
{ resScoreErsties :: Int
, resScoreTutors :: Int
}
deriving Show
$(deriveJSON defaultOptions{fieldLabelModifier = drop 3} ''ResScore)
data ReqRoundPoints = ReqRoundPoints
{ reqRoundPointsErsties :: Int
, reqRoundPointTutors :: Int
}
deriving Show
$(deriveJSON defaultOptions{fieldLabelModifier = drop 3} ''ReqRoundPoints)

View file

@ -16,6 +16,7 @@ import Data.Aeson (Result (..), fromJSON, withObject, (.!=),
(.:?))
import Data.FileEmbed (embedFile)
import Data.Yaml (decodeEither')
import qualified Data.Map as M
import Database.Persist.Sqlite (SqliteConf)
import Language.Haskell.TH.Syntax (Exp, Name, Q)
import Network.Wai.Handler.Warp (HostPreference)
@ -23,6 +24,18 @@ import Yesod.Default.Config2 (applyEnvValue, configSettingsYml)
import Yesod.Default.Util (WidgetFileSettings, widgetFileNoReload,
widgetFileReload)
data Station = Station
{ stationId :: Text
, stationName :: Text
}
instance FromJSON Station where
parseJSON = withObject "Station" $ \o -> do
stationId <- o .: "station-id"
stationName <- o .:? "station-name" .!= "Station"
return Station {..}
-- | Runtime settings to configure this application. These settings can be
-- loaded from various sources: defaults, environment variables, config files,
-- theoretically even a database.
@ -56,11 +69,8 @@ data AppSettings = AppSettings
-- Example app-specific configuration values.
, appCopyright :: Text
-- ^ Copyright text to appear in the footer of the page
, appAnalytics :: Maybe Text
-- ^ Google Analytics code
, appAuthDummyLogin :: Bool
-- ^ Indicate if auth dummy login should be enabled.
, appStations :: Map Text Text
}
instance FromJSON AppSettings where
@ -87,9 +97,7 @@ instance FromJSON AppSettings where
appSkipCombining <- o .:? "skip-combining" .!= dev
appCopyright <- o .: "copyright"
appAnalytics <- o .:? "analytics"
appAuthDummyLogin <- o .:? "auth-dummy-login" .!= dev
appStations <- M.fromList . map (\x -> (stationId x, stationName x)) <$> o .: "stations"
return AppSettings {..}

View file

@ -12,7 +12,7 @@
<div .col-lg-12>
<div .page-header>
<h1 #Tutors>Tutors
#{tutorPoints}
#{tutorP}
<hr>
@ -23,5 +23,5 @@
<div .col-lg-12>
<div .page-header>
<h1 #Ersties>Ersties
#{erstiePoints}
#{erstieP}

14
templates/round.hamlet Normal file
View file

@ -0,0 +1,14 @@
<div .masthead>
<div .container>
<div .row>
<h1 .header>
OwO Geländespiel Station #{station} Round #{roundNumber}
<div .container>
<div .bs-docs-section>
<div .row>
<div .col-lg-12>
<div .page-header>
<form method=post action=@{StationRoundR stationIdentifier roundNumber} enctype=#{roundFormEnctype}>
^{roundFormWidget}
<button> Submit

15
templates/station.hamlet Normal file
View file

@ -0,0 +1,15 @@
<div .masthead>
<div .container>
<div .row>
<h1 .header>
OwO Geländespiel Station #{station}
<div .container>
<div .bs-docs-section>
<div .row>
<div .col-lg-12>
<div .page-header>
<ul>
$forall round <- rounds
<li>
<a href=@{StationRoundR stationIdentifier (roundNumber round)}> #{roundNumber round}