Initial commit
This commit is contained in:
commit
2bfa91eca1
16
.gitignore
vendored
Normal file
16
.gitignore
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
.attr-cache
|
||||||
|
.cabal-sandbox
|
||||||
|
*.hi
|
||||||
|
*.o
|
||||||
|
cabal.project.local
|
||||||
|
cabal.sandbox.config
|
||||||
|
ctags
|
||||||
|
dist-newstyle/
|
||||||
|
dist/
|
||||||
|
ghcid-output.txt
|
||||||
|
profile/
|
||||||
|
result
|
||||||
|
result-*
|
||||||
|
tags
|
||||||
|
TAGS
|
||||||
|
static.out
|
2
.obelisk/impl/default.nix
Normal file
2
.obelisk/impl/default.nix
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# DO NOT HAND-EDIT THIS FILE
|
||||||
|
import (import ./thunk.nix)
|
8
.obelisk/impl/github.json
Normal file
8
.obelisk/impl/github.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"owner": "obsidiansystems",
|
||||||
|
"repo": "obelisk",
|
||||||
|
"branch": "cg/user-nixpkgs-overlays",
|
||||||
|
"private": false,
|
||||||
|
"rev": "c1c1e7e0aedefdf39497f4dda91cda76df1a05a9",
|
||||||
|
"sha256": "1xsp20j12sg6mg9wl640b709ksl3zs3bbkylm559gyvfbvll74p6"
|
||||||
|
}
|
12
.obelisk/impl/thunk.nix
Normal file
12
.obelisk/impl/thunk.nix
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# DO NOT HAND-EDIT THIS FILE
|
||||||
|
let fetch = { private ? false, fetchSubmodules ? false, owner, repo, rev, sha256, ... }:
|
||||||
|
if !fetchSubmodules && !private then builtins.fetchTarball {
|
||||||
|
url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz"; inherit sha256;
|
||||||
|
} else (import (builtins.fetchTarball {
|
||||||
|
url = "https://github.com/NixOS/nixpkgs/archive/3aad50c30c826430b0270fcf8264c8c41b005403.tar.gz";
|
||||||
|
sha256 = "0xwqsf08sywd23x0xvw4c4ghq0l28w2ki22h0bdn766i16z9q2gr";
|
||||||
|
}) {}).fetchFromGitHub {
|
||||||
|
inherit owner repo rev sha256 fetchSubmodules private;
|
||||||
|
};
|
||||||
|
json = builtins.fromJSON (builtins.readFile ./github.json);
|
||||||
|
in fetch json
|
6
README.md
Normal file
6
README.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# This repo
|
||||||
|
|
||||||
|
This is an example showing how to override a nixpkgs package, as well as include a Haskell package dependency not on Hackage.
|
||||||
|
|
||||||
|
See primarily the overrides in default.nix.
|
||||||
|
|
29
backend/backend.cabal
Normal file
29
backend/backend.cabal
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
name: backend
|
||||||
|
version: 0.1
|
||||||
|
cabal-version: >= 1.8
|
||||||
|
build-type: Simple
|
||||||
|
|
||||||
|
library
|
||||||
|
hs-source-dirs: src
|
||||||
|
if impl(ghcjs)
|
||||||
|
buildable: False
|
||||||
|
build-depends: base
|
||||||
|
, common
|
||||||
|
, frontend
|
||||||
|
, obelisk-backend
|
||||||
|
, obelisk-route
|
||||||
|
exposed-modules:
|
||||||
|
Backend
|
||||||
|
ghc-options: -Wall -Wredundant-constraints -Wincomplete-uni-patterns -Wincomplete-record-updates -O -fno-show-valid-hole-fits
|
||||||
|
|
||||||
|
executable backend
|
||||||
|
main-is: main.hs
|
||||||
|
hs-source-dirs: src-bin
|
||||||
|
ghc-options: -Wall -Wredundant-constraints -Wincomplete-uni-patterns -Wincomplete-record-updates -O -threaded -fno-show-valid-hole-fits
|
||||||
|
if impl(ghcjs)
|
||||||
|
buildable: False
|
||||||
|
build-depends: base
|
||||||
|
, backend
|
||||||
|
, common
|
||||||
|
, frontend
|
||||||
|
, obelisk-backend
|
1
backend/frontend.jsexe
Symbolic link
1
backend/frontend.jsexe
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../frontend-js/bin/frontend.jsexe
|
1
backend/frontendJs/frontend.jsexe
Symbolic link
1
backend/frontendJs/frontend.jsexe
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../frontend-js/bin/frontend.jsexe
|
6
backend/src-bin/main.hs
Normal file
6
backend/src-bin/main.hs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import Backend
|
||||||
|
import Frontend
|
||||||
|
import Obelisk.Backend
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = runBackend backend frontend
|
10
backend/src/Backend.hs
Normal file
10
backend/src/Backend.hs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
module Backend where
|
||||||
|
|
||||||
|
import Common.Route
|
||||||
|
import Obelisk.Backend
|
||||||
|
|
||||||
|
backend :: Backend BackendRoute FrontendRoute
|
||||||
|
backend = Backend
|
||||||
|
{ _backend_run = \serve -> serve $ const $ return ()
|
||||||
|
, _backend_routeEncoder = fullRouteEncoder
|
||||||
|
}
|
1
backend/static
Symbolic link
1
backend/static
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../static
|
3
cabal.project
Normal file
3
cabal.project
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
optional-packages:
|
||||||
|
*
|
||||||
|
write-ghc-environment-files: never
|
15
common/common.cabal
Normal file
15
common/common.cabal
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
name: common
|
||||||
|
version: 0.1
|
||||||
|
cabal-version: >= 1.2
|
||||||
|
build-type: Simple
|
||||||
|
|
||||||
|
library
|
||||||
|
hs-source-dirs: src
|
||||||
|
build-depends: base
|
||||||
|
, obelisk-route
|
||||||
|
, mtl
|
||||||
|
, text
|
||||||
|
exposed-modules:
|
||||||
|
Common.Api
|
||||||
|
Common.Route
|
||||||
|
ghc-options: -Wall -Wredundant-constraints -Wincomplete-uni-patterns -Wincomplete-record-updates -O -fno-show-valid-hole-fits
|
4
common/src/Common/Api.hs
Normal file
4
common/src/Common/Api.hs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
module Common.Api where
|
||||||
|
|
||||||
|
commonStuff :: String
|
||||||
|
commonStuff = "Here is a string defined in Common.Api"
|
48
common/src/Common/Route.hs
Normal file
48
common/src/Common/Route.hs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
{-# LANGUAGE ConstraintKinds #-}
|
||||||
|
{-# LANGUAGE EmptyCase #-}
|
||||||
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
|
{-# LANGUAGE GADTs #-}
|
||||||
|
{-# LANGUAGE KindSignatures #-}
|
||||||
|
{-# LANGUAGE LambdaCase #-}
|
||||||
|
{-# LANGUAGE MultiParamTypeClasses #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE RankNTypes #-}
|
||||||
|
{-# LANGUAGE TemplateHaskell #-}
|
||||||
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
|
module Common.Route where
|
||||||
|
|
||||||
|
{- -- You will probably want these imports for composing Encoders.
|
||||||
|
import Prelude hiding (id, (.))
|
||||||
|
import Control.Category
|
||||||
|
-}
|
||||||
|
|
||||||
|
import Data.Text (Text)
|
||||||
|
import Data.Functor.Identity
|
||||||
|
|
||||||
|
import Obelisk.Route
|
||||||
|
import Obelisk.Route.TH
|
||||||
|
|
||||||
|
data BackendRoute :: * -> * where
|
||||||
|
-- | Used to handle unparseable routes.
|
||||||
|
BackendRoute_Missing :: BackendRoute ()
|
||||||
|
-- You can define any routes that will be handled specially by the backend here.
|
||||||
|
-- i.e. These do not serve the frontend, but do something different, such as serving static files.
|
||||||
|
|
||||||
|
data FrontendRoute :: * -> * where
|
||||||
|
FrontendRoute_Main :: FrontendRoute ()
|
||||||
|
-- This type is used to define frontend routes, i.e. ones for which the backend will serve the frontend.
|
||||||
|
|
||||||
|
fullRouteEncoder
|
||||||
|
:: Encoder (Either Text) Identity (R (FullRoute BackendRoute FrontendRoute)) PageName
|
||||||
|
fullRouteEncoder = mkFullRouteEncoder
|
||||||
|
(FullRoute_Backend BackendRoute_Missing :/ ())
|
||||||
|
(\case
|
||||||
|
BackendRoute_Missing -> PathSegment "missing" $ unitEncoder mempty)
|
||||||
|
(\case
|
||||||
|
FrontendRoute_Main -> PathEnd $ unitEncoder mempty)
|
||||||
|
|
||||||
|
concat <$> mapM deriveRouteComponent
|
||||||
|
[ ''BackendRoute
|
||||||
|
, ''FrontendRoute
|
||||||
|
]
|
1
config/common/example
Normal file
1
config/common/example
Normal file
@ -0,0 +1 @@
|
|||||||
|
This string comes from config/common/example
|
1
config/common/route
Normal file
1
config/common/route
Normal file
@ -0,0 +1 @@
|
|||||||
|
http://localhost:8000
|
9
config/readme.md
Normal file
9
config/readme.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
### Config
|
||||||
|
|
||||||
|
Obelisk projects should contain a config folder with the following subfolders: common, frontend, and backend.
|
||||||
|
|
||||||
|
Things that should never be transmitted to the frontend belong in backend/ (e.g., email credentials)
|
||||||
|
|
||||||
|
Frontend-only configuration belongs in frontend/.
|
||||||
|
|
||||||
|
Shared configuration files (e.g., the route config) belong in common/
|
70
default.nix
Normal file
70
default.nix
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
{ system ? builtins.currentSystem
|
||||||
|
, nix-thunk ? import ./dep/nix-thunk {}
|
||||||
|
, obelisk ? import ./.obelisk/impl {
|
||||||
|
inherit system;
|
||||||
|
iosSdkVersion = "13.2";
|
||||||
|
# This argument (which is new, but was easy to add to Obelisk, thankfully), allows one to specify nixpkgs overlays.
|
||||||
|
# We'll use it to ensure we have the appropriate version of botan.
|
||||||
|
nixpkgsOverlays =
|
||||||
|
[
|
||||||
|
(self: super: rec {
|
||||||
|
botan2 =
|
||||||
|
(super.botan2.overrideAttrs (old: {
|
||||||
|
# Get rid of some patches that nixpkgs was applying to botan2 and which didn't apply to the branch.
|
||||||
|
patches = [];
|
||||||
|
# The --with-openssl flag didn't work for some reason, might need further figuring out.
|
||||||
|
configurePhase = builtins.replaceStrings [ "--with-openssl" ] [ " " ] old.configurePhase;
|
||||||
|
# Here, we use nix-thunk to get the source of the correct branch of the botan repo via a thunk.
|
||||||
|
# Nix thunks are essentially references to git repositories that can be unpacked to their
|
||||||
|
# source in-place when working on the project, or packed up into a few small files.
|
||||||
|
# After installing the nix-thunk command from https://github.com/obsidiansystems/nix-thunk
|
||||||
|
# you can run:
|
||||||
|
# nix-thunk unpack dep/botan
|
||||||
|
# from the top level of this repo to clone a copy of the botan git repo at the appropriate
|
||||||
|
# commit, and work on it from there. Similarly,
|
||||||
|
# nix-thunk pack dep/botan
|
||||||
|
# will pack it back up again, provided that the changes have been pushed somewhere.
|
||||||
|
# Note: there's a bug in the current version of Obelisk which occasionally gives it some trouble
|
||||||
|
# if certain repos are unpacked. If you have any trouble running an ob command
|
||||||
|
# (ob run, ob repl, etc.) with a thunk unpacked, try adding the flag --no-interpret dep
|
||||||
|
# and hopefully that will sort it out.
|
||||||
|
src = nix-thunk.thunkSource ./dep/botan;
|
||||||
|
})).override (old: {
|
||||||
|
# Also, turn on debugging.
|
||||||
|
extraConfigureFlags = "--debug-mode";
|
||||||
|
});
|
||||||
|
# For whatever reason, it seems callCabal2nix below wants to use the botan package rather than botan2.
|
||||||
|
# We could override the pkgconfigDepends of the resulting package, but this is easier.
|
||||||
|
botan = self.botan2;
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
# You must accept the Android Software Development Kit License Agreement at
|
||||||
|
# https://developer.android.com/studio/terms in order to build Android apps.
|
||||||
|
# Uncomment and set this to `true` to indicate your acceptance:
|
||||||
|
# config.android_sdk.accept_license = false;
|
||||||
|
|
||||||
|
# In order to use Let's Encrypt for HTTPS deployments you must accept
|
||||||
|
# their terms of service at https://letsencrypt.org/repository/.
|
||||||
|
# Uncomment and set this to `true` to indicate your acceptance:
|
||||||
|
# terms.security.acme.acceptTerms = false;
|
||||||
|
}
|
||||||
|
}:
|
||||||
|
with obelisk;
|
||||||
|
project ./. ({ pkgs, hackGet, ... }: {
|
||||||
|
android.applicationId = "systems.obsidian.obelisk.examples.minimal";
|
||||||
|
android.displayName = "Obelisk Minimal Example";
|
||||||
|
ios.bundleIdentifier = "systems.obsidian.obelisk.examples.minimal";
|
||||||
|
ios.bundleName = "Obelisk Minimal Example";
|
||||||
|
overrides = self: super:
|
||||||
|
with pkgs.haskell.lib; {
|
||||||
|
# Here, we get the tahoe-chk package from the chk.hs thunk, and use callCabal2nix to get a nix derivation to build it.
|
||||||
|
tahoe-chk = self.callCabal2nix "tahoe-chk" (nix-thunk.thunkSource ./dep/chkhs) {};
|
||||||
|
# We also ended up needing an override of the base32 library, which we obtain from Hackage.
|
||||||
|
base32 = self.callHackageDirect {
|
||||||
|
pkg = "base32";
|
||||||
|
ver = "0.2.2.0";
|
||||||
|
sha256 = "1qx7n2jyb9h1082434r90hfrjw5fab2j1yg0qzxh856fpksbh811";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
})
|
2
dep/botan/default.nix
Normal file
2
dep/botan/default.nix
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# DO NOT HAND-EDIT THIS FILE
|
||||||
|
import (import ./thunk.nix)
|
8
dep/botan/github.json
Normal file
8
dep/botan/github.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"owner": "PrivateStorageio",
|
||||||
|
"repo": "botan",
|
||||||
|
"branch": "3190.ffi-zfec",
|
||||||
|
"private": false,
|
||||||
|
"rev": "f9e20aae412f5b482334181885489a15bb8a4fd8",
|
||||||
|
"sha256": "0qcz9cxh0lymj09166wf9mxv9q2bhr3sllh71380dhq90ikaib7j"
|
||||||
|
}
|
12
dep/botan/thunk.nix
Normal file
12
dep/botan/thunk.nix
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# DO NOT HAND-EDIT THIS FILE
|
||||||
|
let fetch = { private ? false, fetchSubmodules ? false, owner, repo, rev, sha256, ... }:
|
||||||
|
if !fetchSubmodules && !private then builtins.fetchTarball {
|
||||||
|
url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz"; inherit sha256;
|
||||||
|
} else (import (builtins.fetchTarball {
|
||||||
|
url = "https://github.com/NixOS/nixpkgs/archive/3aad50c30c826430b0270fcf8264c8c41b005403.tar.gz";
|
||||||
|
sha256 = "0xwqsf08sywd23x0xvw4c4ghq0l28w2ki22h0bdn766i16z9q2gr";
|
||||||
|
}) {}).fetchFromGitHub {
|
||||||
|
inherit owner repo rev sha256 fetchSubmodules private;
|
||||||
|
};
|
||||||
|
json = builtins.fromJSON (builtins.readFile ./github.json);
|
||||||
|
in fetch json
|
2
dep/chkhs/default.nix
Normal file
2
dep/chkhs/default.nix
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# DO NOT HAND-EDIT THIS FILE
|
||||||
|
import (import ./thunk.nix)
|
8
dep/chkhs/git.json
Normal file
8
dep/chkhs/git.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"url": "https://gitlab.com/exarkun/chk.hs.git",
|
||||||
|
"rev": "46bdc9a1c235a26ab1cabdad7eceee36dccf4cdd",
|
||||||
|
"sha256": "0yykb9vyv0wci65nzq0aw0slw5njrzrbkrchpypd9vskvh7p8im0",
|
||||||
|
"private": false,
|
||||||
|
"fetchSubmodules": false,
|
||||||
|
"branch": "master"
|
||||||
|
}
|
17
dep/chkhs/thunk.nix
Normal file
17
dep/chkhs/thunk.nix
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# DO NOT HAND-EDIT THIS FILE
|
||||||
|
let fetch = {url, rev, branch ? null, sha256 ? null, fetchSubmodules ? false, private ? false, ...}:
|
||||||
|
let realUrl = let firstChar = builtins.substring 0 1 url; in
|
||||||
|
if firstChar == "/" then /. + url
|
||||||
|
else if firstChar == "." then ./. + url
|
||||||
|
else url;
|
||||||
|
in if !fetchSubmodules && private then builtins.fetchGit {
|
||||||
|
url = realUrl; inherit rev;
|
||||||
|
${if branch == null then null else "ref"} = branch;
|
||||||
|
} else (import (builtins.fetchTarball {
|
||||||
|
url = "https://github.com/NixOS/nixpkgs/archive/3aad50c30c826430b0270fcf8264c8c41b005403.tar.gz";
|
||||||
|
sha256 = "0xwqsf08sywd23x0xvw4c4ghq0l28w2ki22h0bdn766i16z9q2gr";
|
||||||
|
}) {}).fetchgit {
|
||||||
|
url = realUrl; inherit rev sha256;
|
||||||
|
};
|
||||||
|
json = builtins.fromJSON (builtins.readFile ./git.json);
|
||||||
|
in fetch json
|
2
dep/nix-thunk/default.nix
Normal file
2
dep/nix-thunk/default.nix
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# DO NOT HAND-EDIT THIS FILE
|
||||||
|
import (import ./thunk.nix)
|
7
dep/nix-thunk/github.json
Normal file
7
dep/nix-thunk/github.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"owner": "obsidiansystems",
|
||||||
|
"repo": "nix-thunk",
|
||||||
|
"private": false,
|
||||||
|
"rev": "0982911d78fbd9932c3ed8104a930f313f49b69b",
|
||||||
|
"sha256": "130n8mzywbvyqd6aap6yk98zynq3r3kpj2hfzdym26plwz0rr3bj"
|
||||||
|
}
|
12
dep/nix-thunk/thunk.nix
Normal file
12
dep/nix-thunk/thunk.nix
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# DO NOT HAND-EDIT THIS FILE
|
||||||
|
let fetch = { private ? false, fetchSubmodules ? false, owner, repo, rev, sha256, ... }:
|
||||||
|
if !fetchSubmodules && !private then builtins.fetchTarball {
|
||||||
|
url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz"; inherit sha256;
|
||||||
|
} else (import (builtins.fetchTarball {
|
||||||
|
url = "https://github.com/NixOS/nixpkgs/archive/3aad50c30c826430b0270fcf8264c8c41b005403.tar.gz";
|
||||||
|
sha256 = "0xwqsf08sywd23x0xvw4c4ghq0l28w2ki22h0bdn766i16z9q2gr";
|
||||||
|
}) {}).fetchFromGitHub {
|
||||||
|
inherit owner repo rev sha256 fetchSubmodules private;
|
||||||
|
};
|
||||||
|
json = builtins.fromJSON (builtins.readFile ./github.json);
|
||||||
|
in fetch json
|
36
frontend/frontend.cabal
Normal file
36
frontend/frontend.cabal
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
name: frontend
|
||||||
|
version: 0.1
|
||||||
|
cabal-version: >= 1.8
|
||||||
|
build-type: Simple
|
||||||
|
|
||||||
|
library
|
||||||
|
hs-source-dirs: src
|
||||||
|
build-depends: base
|
||||||
|
, common
|
||||||
|
, obelisk-frontend
|
||||||
|
, obelisk-route
|
||||||
|
, jsaddle
|
||||||
|
, reflex-dom-core
|
||||||
|
, obelisk-executable-config-lookup
|
||||||
|
, obelisk-generated-static
|
||||||
|
, text
|
||||||
|
exposed-modules:
|
||||||
|
Frontend
|
||||||
|
ghc-options: -Wall -Wredundant-constraints -Wincomplete-uni-patterns -Wincomplete-record-updates -O -fno-show-valid-hole-fits
|
||||||
|
|
||||||
|
executable frontend
|
||||||
|
main-is: main.hs
|
||||||
|
hs-source-dirs: src-bin
|
||||||
|
build-depends: base
|
||||||
|
, common
|
||||||
|
, obelisk-frontend
|
||||||
|
, obelisk-route
|
||||||
|
, reflex-dom
|
||||||
|
, obelisk-generated-static
|
||||||
|
, frontend
|
||||||
|
ghc-options: -threaded -O -Wall -Wredundant-constraints -Wincomplete-uni-patterns -Wincomplete-record-updates -fno-show-valid-hole-fits
|
||||||
|
if impl(ghcjs)
|
||||||
|
ghc-options: -dedupe
|
||||||
|
cpp-options: -DGHCJS_BROWSER
|
||||||
|
if os(darwin)
|
||||||
|
ghc-options: -dynamic
|
10
frontend/src-bin/main.hs
Normal file
10
frontend/src-bin/main.hs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import Frontend
|
||||||
|
import Common.Route
|
||||||
|
import Obelisk.Frontend
|
||||||
|
import Obelisk.Route.Frontend
|
||||||
|
import Reflex.Dom
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
let Right validFullEncoder = checkEncoder fullRouteEncoder
|
||||||
|
run $ runFrontend validFullEncoder frontend
|
47
frontend/src/Frontend.hs
Normal file
47
frontend/src/Frontend.hs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE TemplateHaskell #-}
|
||||||
|
|
||||||
|
module Frontend where
|
||||||
|
|
||||||
|
import Control.Monad
|
||||||
|
import qualified Data.Text as T
|
||||||
|
import qualified Data.Text.Encoding as T
|
||||||
|
import Language.Javascript.JSaddle (eval, liftJSM)
|
||||||
|
|
||||||
|
import Obelisk.Frontend
|
||||||
|
import Obelisk.Configs
|
||||||
|
import Obelisk.Route
|
||||||
|
import Obelisk.Generated.Static
|
||||||
|
|
||||||
|
import Reflex.Dom.Core
|
||||||
|
|
||||||
|
import Common.Api
|
||||||
|
import Common.Route
|
||||||
|
|
||||||
|
|
||||||
|
-- This runs in a monad that can be run on the client or the server.
|
||||||
|
-- To run code in a pure client or pure server context, use one of the
|
||||||
|
-- `prerender` functions.
|
||||||
|
frontend :: Frontend (R FrontendRoute)
|
||||||
|
frontend = Frontend
|
||||||
|
{ _frontend_head = do
|
||||||
|
el "title" $ text "Obelisk Minimal Example"
|
||||||
|
elAttr "link" ("href" =: $(static "main.css") <> "type" =: "text/css" <> "rel" =: "stylesheet") blank
|
||||||
|
, _frontend_body = do
|
||||||
|
el "h1" $ text "Welcome to Obelisk!"
|
||||||
|
el "p" $ text $ T.pack commonStuff
|
||||||
|
|
||||||
|
-- `prerender` and `prerender_` let you choose a widget to run on the server
|
||||||
|
-- during prerendering and a different widget to run on the client with
|
||||||
|
-- JavaScript. The following will generate a `blank` widget on the server and
|
||||||
|
-- print "Hello, World!" on the client.
|
||||||
|
prerender_ blank $ liftJSM $ void $ eval ("console.log('Hello, World!')" :: T.Text)
|
||||||
|
|
||||||
|
elAttr "img" ("src" =: $(static "obelisk.jpg")) blank
|
||||||
|
el "div" $ do
|
||||||
|
exampleConfig <- getConfig "common/example"
|
||||||
|
case exampleConfig of
|
||||||
|
Nothing -> text "No config file found in config/common/example"
|
||||||
|
Just s -> text $ T.decodeUtf8 s
|
||||||
|
return ()
|
||||||
|
}
|
3
static/main.css
Normal file
3
static/main.css
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
p {
|
||||||
|
color: red;
|
||||||
|
}
|
BIN
static/obelisk.jpg
Normal file
BIN
static/obelisk.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
Loading…
Reference in New Issue
Block a user