does it work?

This commit is contained in:
Dennis Frieberg 2024-10-09 08:14:47 +02:00
parent 7ec9a8f10e
commit 9b949230dd
No known key found for this signature in database
GPG key ID: 7C58AFED036072C5
28 changed files with 188 additions and 114 deletions

View file

@ -39,6 +39,7 @@ library
Handler.Common Handler.Common
Handler.Home Handler.Home
Handler.Station Handler.Station
Handler.Ad
Import Import
Import.NoFoundation Import.NoFoundation
Model Model
@ -72,6 +73,7 @@ library
, persistent >=2.9 && <2.15 , persistent >=2.9 && <2.15
, persistent-sqlite >=2.9 && <2.14 , persistent-sqlite >=2.9 && <2.14
, persistent-template >=2.5 && <2.14 , persistent-template >=2.5 && <2.14
, random
, safe , safe
, shakespeare >=2.0 && <2.2 , shakespeare >=2.0 && <2.2
, template-haskell , template-haskell

BIN
ads/image0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 511 KiB

BIN
ads/image1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
ads/image2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

BIN
ads/image3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

BIN
ads/image4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 440 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -15,6 +15,8 @@
-- stationName/roundNumber -- stationName/roundNumber
/station/#Text/#Int StationRoundR GET POST /station/#Text/#Int StationRoundR GET POST
/ad/ AdR GET
-- /comments CommentR POST -- /comments CommentR POST

View file

@ -41,3 +41,5 @@ copyright: Insert copyright statement here
stations: stations:
- station-id: "test" - station-id: "test"
station-name: "Test" station-name: "Test"
ad-files: "ads/"

View file

@ -5,11 +5,11 @@
"nixpkgs-lib": "nixpkgs-lib" "nixpkgs-lib": "nixpkgs-lib"
}, },
"locked": { "locked": {
"lastModified": 1719994518, "lastModified": 1727826117,
"narHash": "sha256-pQMhCCHyQGRzdfAkdJ4cIWiw+JNuWsTX7f0ZYSyz0VY=", "narHash": "sha256-K5ZLCyfO/Zj9mPFldf3iwS6oZStJcU4tSpiXTMYaaL0=",
"owner": "hercules-ci", "owner": "hercules-ci",
"repo": "flake-parts", "repo": "flake-parts",
"rev": "9227223f6d922fee3c7b190b2cc238a99527bbb7", "rev": "3d04084d54bedc3d6b8b736c70ef449225c361b1",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -20,11 +20,11 @@
}, },
"haskell-flake": { "haskell-flake": {
"locked": { "locked": {
"lastModified": 1720977934, "lastModified": 1728227251,
"narHash": "sha256-k9kwz2lpUqafRUpuCMgkv4AWtHEoJPCds1ZPRkyW2XE=", "narHash": "sha256-JLDhMFyGyFe0QJAbCuSxB7/kjUCA7uUAMa6BFRORwXk=",
"owner": "srid", "owner": "srid",
"repo": "haskell-flake", "repo": "haskell-flake",
"rev": "cd449f1c04175efdf5b553302d22916640090066", "rev": "9cbfbfc38f1fbf9a0f471795c84780211875fd45",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -35,11 +35,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1721466660, "lastModified": 1728279793,
"narHash": "sha256-pFSxgSZqZ3h+5Du0KvEL1ccDZBwu4zvOil1zzrPNb3c=", "narHash": "sha256-W3D5YpNrUVTFPVU4jiEiboaaUDShaiH5fRl9aJLqUnU=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "6e14bbce7bea6c4efd7adfa88a40dac750d80100", "rev": "f85a2d005e83542784a755ca8da112f4f65c4aa4",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -51,14 +51,14 @@
}, },
"nixpkgs-lib": { "nixpkgs-lib": {
"locked": { "locked": {
"lastModified": 1719876945, "lastModified": 1727825735,
"narHash": "sha256-Fm2rDDs86sHy0/1jxTOKB1118Q0O3Uc7EC0iXvXKpbI=", "narHash": "sha256-0xHYkMkeLVQAMa7gvkddbPqpxph+hDzdu1XdGPJR+Os=",
"type": "tarball", "type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/5daf0514482af3f97abaefc78a6606365c9108e2.tar.gz" "url": "https://github.com/NixOS/nixpkgs/archive/fb192fec7cc7a4c26d51779e9bab07ce6fa5597a.tar.gz"
}, },
"original": { "original": {
"type": "tarball", "type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/5daf0514482af3f97abaefc78a6606365c9108e2.tar.gz" "url": "https://github.com/NixOS/nixpkgs/archive/fb192fec7cc7a4c26d51779e9bab07ce6fa5597a.tar.gz"
} }
}, },
"root": { "root": {

View file

@ -6,6 +6,9 @@
}; };
outputs = inputs@{ self, nixpkgs, flake-parts, ... }: outputs = inputs@{ self, nixpkgs, flake-parts, ... }:
flake-parts.lib.mkFlake { inherit inputs; } { flake-parts.lib.mkFlake { inherit inputs; } {
flake = {
nixosModules.OwOpointTracker = { import ./module.nix self
};
systems = nixpkgs.lib.systems.flakeExposed; systems = nixpkgs.lib.systems.flakeExposed;
imports = [ inputs.haskell-flake.flakeModule ]; imports = [ inputs.haskell-flake.flakeModule ];

89
module.nix Normal file
View file

@ -0,0 +1,89 @@
self: {config, pkgs, lib ...}:
with lib;
let
cfg = config.services.owOPointTracker;
format = pkgs.formats.yaml {};
configFile = format.generate "settings.yml" cfg.config
databaseOptionType = types.submodule {
options = {
database = mkOption {
default = "_env:YESOD_SQLITE_DATABASE:OwOpointTracker.sqlite3";
type = types.str;
};
poolsize = mkOption {
default = "_env:YESOD_SQLITE_POOLSIZE:10";
type = types.str;
};
};
};
stationType = types.submodule {
options = {
station-id = mkOption {
default = "Station";
type = types.str;
};
station-name = mkOption {
types = types.str;
};
};
};
{
imports = [];
options.services.owOPointTracker = {
enable = mkEnableOption "OwOPointTracker";
config = {
static-dir = mkOption {
type = types.path;
};
host = mkOption {
type = types.str;
default = "_env:YESOD_HOST:*4";
ad-files = mkOption {
type = types.path;
};
port = mkOption {
default = "_env:YESOD_PORT:3000";
type = types.str;
};
ip-from-header = mkOption {
default = "_env:YESOD_IP_FROM_HEADER:false";
type = types.str;
};
database = {
type = databaseOptionType;
};
copyright = mkOption {
default = "copyright for this mess?";
type = types.str;
};
station = mkOption {
type = types.listOf stationType;
};
};
};
config = mkIf cfg.enable {
users.users.owopoint = {
isSystemUser = true;
group = "owopoint";
createHome = true;
home = "/var/owopoint";
};
users.groups = {
owopoint = {};
};
systemd.services.owOPointTracker = {
wantedBy = ["multi-user.target"];
after = ["network.target"];
serviceConfig = {
ExecStart = "${self.packages.${pkgs.system}.default} ${configFile}";
Restart = always;
User = "owopoint";
Group = "owopoint";
};
};
};
}

View file

@ -43,6 +43,7 @@ import System.Log.FastLogger (defaultBufSize, newStdoutLoggerSet,
import Handler.Common import Handler.Common
import Handler.Home import Handler.Home
import Handler.Station import Handler.Station
import Handler.Ad
-- This line actually creates our YesodDispatch instance. It is the second half -- 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 -- of the call to mkYesodData which occurs in Foundation.hs. Please see the

View file

@ -146,8 +146,10 @@ instance Yesod App where
-- value passed to hamletToRepHtml cannot be a widget, this allows -- value passed to hamletToRepHtml cannot be a widget, this allows
-- you to use normal widget features in default-layout. -- you to use normal widget features in default-layout.
-- randomAddNumber <- liftIO $ getStdRandom (randomR (0,4))
pc <- widgetToPageContent $ do pc <- widgetToPageContent $ do
addStylesheet $ StaticR css_bootstrap_css -- addStylesheet $ StaticR css_bootstrap_css
-- ^ generated from @Settings/StaticFiles.hs@ -- ^ generated from @Settings/StaticFiles.hs@
$(widgetFile "default-layout") $(widgetFile "default-layout")
withUrlRenderer $(hamletFile "templates/default-layout-wrapper.hamlet") withUrlRenderer $(hamletFile "templates/default-layout-wrapper.hamlet")

15
src/Handler/Ad.hs Normal file
View file

@ -0,0 +1,15 @@
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeApplications #-}
module Handler.Ad where
import Import
getAdR :: Handler Html
getAdR = do
basePath <- getsYesod (appAdFilePath . appSettings)
number <- applyAtomicGen (randomR (0 :: Int ,4)) globalStdGen
sendFile typePng $ basePath <> "image" <> show number <> ".png"

View file

@ -19,7 +19,8 @@ checkStation stationIdentifier = do
Nothing -> notFound Nothing -> notFound
Just m -> return m Just m -> return m
repsertBy :: (MonadIO m, PersistUniqueRead backend, PersistRecordBackend record backend, AtLeastOneUniqueKey record, SafeToInsert record) => record -> ReaderT backend m () -- TODO works without the type annotation, but I don't know why this one is wrong. No time to find out now
-- repsertBy :: (MonadIO m, PersistUniqueRead backend, PersistRecordBackend record backend, AtLeastOneUniqueKey record, SafeToInsert record) => record -> ReaderT backend m ()
repsertBy val = do repsertBy val = do
valM <- getByValue val valM <- getByValue val
case valM of case valM of

View file

@ -10,3 +10,5 @@ import Settings.StaticFiles as Import
import Yesod.Auth as Import import Yesod.Auth as Import
import Yesod.Core.Types as Import (loggerSet) import Yesod.Core.Types as Import (loggerSet)
import Yesod.Default.Config2 as Import import Yesod.Default.Config2 as Import
import System.Random as Import
import System.Random.Stateful as Import

View file

@ -71,6 +71,7 @@ data AppSettings = AppSettings
-- ^ Copyright text to appear in the footer of the page -- ^ Copyright text to appear in the footer of the page
, appStations :: Map Text Text , appStations :: Map Text Text
, appAdFilePath :: String
} }
instance FromJSON AppSettings where instance FromJSON AppSettings where
@ -98,6 +99,7 @@ instance FromJSON AppSettings where
appCopyright <- o .: "copyright" appCopyright <- o .: "copyright"
appStations <- M.fromList . map (\x -> (stationId x, stationName x)) <$> o .: "stations" appStations <- M.fromList . map (\x -> (stationId x, stationName x)) <$> o .: "stations"
appAdFilePath <- o .: "ad-files"
return AppSettings {..} return AppSettings {..}

3
static/css/test.css Normal file
View file

@ -0,0 +1,3 @@
.blubb {
border-width: 300px
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

View file

@ -1,16 +1,6 @@
<!-- Page Contents --> <!-- Page Contents -->
<div .container>
$if (Just HomeR == mcurrentRoute) <div .ad>
^{widget} <img src=@{AdR}>
$else ^{widget}
<div .container>
<div .row>
<div .col-md-12>
^{widget}
<!-- Footer -->
<footer .footer>
<div .container>
<p .text-muted>
#{appCopyright $ appSettings master}

View file

@ -1,28 +1,11 @@
.masthead, body {
.navbar { font-family: Lato,'Helvetica Neue',Arial,Helvetica,sans-serif;
background-color: rgb(27, 28, 29);
} }
.navbar-default .navbar-nav > .active > a {
background-color: transparent;
border-bottom: 2px solid white;
}
.navbar-nav {
padding-bottom: 1em;
}
.masthead {
margin-top: -21px;
color: white;
text-align: center;
min-height: 500px;
}
.masthead .header { .masthead .header {
max-width: 700px; max-width: 700px;
margin: 0 auto; margin: 0 auto;
font-family: Lato,'Helvetica Neue',Arial,Helvetica,sans-serif;
} }
.masthead h1.header { .masthead h1.header {
@ -38,36 +21,15 @@
font-weight: normal; font-weight: normal;
} }
.masthead .btn { aside,
margin: 1em 0; .ad {
width: 25%;
padding-left: 15px;
margin-left: 15px;
float: right;
} }
img {
/* Common styles for all types */ max-width: 100%;
.bs-callout { max-height: 100%;
padding: 20px;
margin: 20px 0;
border: 1px solid #eee;
border-left-width: 5px;
border-radius: 3px;
}
.bs-callout p:last-child {
margin-bottom: 0;
}
.bs-callout-info {
border-left-color: #1b809e;
}
/* Space things out */
.bs-docs-section {
margin-bottom: 60px;
}
.bs-docs-section:last-child {
margin-bottom: 0;
}
#message {
margin-bottom: 40px;
} }

View file

@ -1,27 +1,10 @@
<div .masthead> <div .masthead>
<div .container> <h1 .header>
<div .row> OWO Geländespiel
<h1 .header>
OwO Geländespiel
<div .container> <div .points .tutor>
<!-- Starting <h1 #Tutors>Tutoren: #{tutorP}
================================================== -->
<div .bs-docs-section>
<div .row>
<div .col-lg-12>
<div .page-header>
<h1 #Tutors>Tutors
#{tutorP}
<hr> <div .points .erstie>
<h1 #Ersties>Ersties: #{erstieP}
<!-- Forms
================================================== -->
<div .bs-docs-section>
<div .row>
<div .col-lg-12>
<div .page-header>
<h1 #Ersties>Ersties
#{erstieP}

View file

@ -2,3 +2,19 @@ li {
line-height: 2em; line-height: 2em;
font-size: 16px font-size: 16px
} }
.points {
border-radius: 25px;
font-weight: bold;
margin: auto;
max-width: 50%;
display: flex;
justify-content: center;
align-items: center;
margin-top: 30px;
}
.tutor {
background-color: #f68afc;
}
.erstie {
background-color: #00FF00;
}

View file

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

5
templates/round.lucious Normal file
View file

@ -0,0 +1,5 @@
.form {
display: flex;
justify-content: center;
align-items: center;
}

View file

@ -1,14 +1,8 @@
<div .masthead> <div .masthead>
<div .container>
<div .row>
<h1 .header> <h1 .header>
OwO Geländespiel Station #{station} OwO Geländespiel Station #{station}
<div .container> <div .container .form>
<div .bs-docs-section>
<div .row>
<div .col-lg-12>
<div .page-header>
<ul> <ul>
$forall round <- rounds $forall round <- rounds
<li> <li>

View file

@ -0,0 +1,5 @@
.form {
display: flex;
justify-content: center;
align-items: center;
}