Merge branch 'master' into initial_thoughts_on_frontend
This commit is contained in:
commit
20b6828c96
21
README.md
21
README.md
@ -67,3 +67,24 @@ Assuming Ubuntu or similar
|
|||||||
stack:<br> https://docs.haskellstack.org/en/stable/README/#how-to-install
|
stack:<br> https://docs.haskellstack.org/en/stable/README/#how-to-install
|
||||||
|
|
||||||
ldap:<br>https://wiki.ubuntuusers.de/OpenLDAP_ab_Precise/
|
ldap:<br>https://wiki.ubuntuusers.de/OpenLDAP_ab_Precise/
|
||||||
|
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
# PostgreSQL
|
||||||
|
|
||||||
|
Starten als Root:
|
||||||
|
|
||||||
|
# systemctl start postgresql
|
||||||
|
# find / -name postgresql.conf
|
||||||
|
# cd /var/lib/pgsql/data/
|
||||||
|
# su - postgres
|
||||||
|
|
||||||
|
|
||||||
|
psql -U uniworx -d uniworx -h 127.0.0.1 -w
|
||||||
|
|
||||||
|
--Zeige Tabellen
|
||||||
|
\dt
|
||||||
|
|
||||||
|
--Lösche Tabelle "course" und alle davon abhängigen:
|
||||||
|
DROP TABLE "course" CASCADE;
|
||||||
|
|||||||
@ -221,7 +221,7 @@ courseEditHandler course = do
|
|||||||
let formActions = defaultFormActions
|
let formActions = defaultFormActions
|
||||||
defaultLayout $ do
|
defaultLayout $ do
|
||||||
setTitle [shamlet| #{formTitle} |]
|
setTitle [shamlet| #{formTitle} |]
|
||||||
$(widgetFile "generic_form")
|
$(widgetFile "formPage")
|
||||||
|
|
||||||
|
|
||||||
data CourseForm = CourseForm
|
data CourseForm = CourseForm
|
||||||
|
|||||||
@ -89,42 +89,21 @@ getTermEditExistR tid = do
|
|||||||
termEditHandler :: Maybe Term -> Handler Html
|
termEditHandler :: Maybe Term -> Handler Html
|
||||||
termEditHandler term = do
|
termEditHandler term = do
|
||||||
((result, formWidget), formEnctype) <- runFormPost $ newTermForm term
|
((result, formWidget), formEnctype) <- runFormPost $ newTermForm term
|
||||||
action <- lookupPostParam "formaction"
|
case result of
|
||||||
case (result,action) of
|
(FormSuccess res) -> do
|
||||||
(FormSuccess res, fAct)
|
|
||||||
| fAct == formActionDelete -> do
|
|
||||||
runDB $ delete (TermKey $ termName res)
|
|
||||||
let tid = termToText $ termName res
|
|
||||||
let msg = "Semester " `T.append` tid `T.append` " erfolgreich gelöscht."
|
|
||||||
addMessage "warning" [shamlet| #{msg} |]
|
|
||||||
redirect TermShowR
|
|
||||||
| fAct == formActionSave -> do
|
|
||||||
-- term <- runDB $ get $ TermKey termName
|
-- term <- runDB $ get $ TermKey termName
|
||||||
runDB $ repsert (TermKey $ termName res) res
|
runDB $ repsert (TermKey $ termName res) res
|
||||||
let tid = termToText $ termName res
|
let tid = termToText $ termName res
|
||||||
let msg = "Semester " `T.append` tid `T.append` " erfolgreich editiert."
|
let msg = "Semester " `T.append` tid `T.append` " erfolgreich editiert."
|
||||||
addMessage "success" [shamlet| #{msg} |]
|
addMessage "success" [shamlet| #{msg} |]
|
||||||
redirect TermShowR
|
redirect TermShowR
|
||||||
| otherwise -> redirect TermShowR
|
(FormMissing ) -> return ()
|
||||||
(FormMissing,_) -> return ()
|
(FormFailure _) -> addMessage "warning" "Bitte Eingabe korrigieren."
|
||||||
(FormFailure _,_) -> addMessage "warning" "Bitte Eingabe korrigieren."
|
|
||||||
let formTitle = "Semester editieren/anlegen" :: Text
|
let formTitle = "Semester editieren/anlegen" :: Text
|
||||||
let actionUrl = TermEditR
|
let actionUrl = TermEditR
|
||||||
let formActions = defaultFormActions
|
|
||||||
defaultLayout $ do
|
defaultLayout $ do
|
||||||
setTitle [shamlet| #{formTitle} |]
|
setTitle [shamlet| #{formTitle} |]
|
||||||
$(widgetFile "generic_form")
|
$(widgetFile "formPage")
|
||||||
|
|
||||||
{-
|
|
||||||
wdgtTermForm :: (ToWidget UniWorX a) => a -> Enctype -> Handler Html
|
|
||||||
wdgtTermForm formWidget formEnctype = do
|
|
||||||
let formTitle = "Semester editieren/anlegen" :: Text
|
|
||||||
let actionUrl = TermEditR
|
|
||||||
let formActions = defaultFormActions
|
|
||||||
defaultLayout $ do
|
|
||||||
setTitle [shamlet| #{formTitle} |]
|
|
||||||
$(widgetFile "generic_form")
|
|
||||||
-}
|
|
||||||
|
|
||||||
newTermForm :: Maybe Term -> Form Term
|
newTermForm :: Maybe Term -> Form Term
|
||||||
newTermForm template html = do
|
newTermForm template html = do
|
||||||
@ -136,7 +115,7 @@ newTermForm template html = do
|
|||||||
<*> areq dayField (bfs ("Beginn Vorlesungen" :: Text)) (termLectureStart <$> template)
|
<*> areq dayField (bfs ("Beginn Vorlesungen" :: Text)) (termLectureStart <$> template)
|
||||||
<*> areq dayField (bfs ("Ende Vorlesungen" :: Text)) (termLectureEnd <$> template)
|
<*> areq dayField (bfs ("Ende Vorlesungen" :: Text)) (termLectureEnd <$> template)
|
||||||
<*> areq checkBoxField (bfs ("Aktiv" :: Text)) (termActive <$> template)
|
<*> areq checkBoxField (bfs ("Aktiv" :: Text)) (termActive <$> template)
|
||||||
-- <* bootstrapSubmit (bsSubmit "Semester bearbeiten")
|
<* submitButton
|
||||||
return $ case result of
|
return $ case result of
|
||||||
FormSuccess termResult
|
FormSuccess termResult
|
||||||
| errorMsgs <- validateTerm termResult
|
| errorMsgs <- validateTerm termResult
|
||||||
|
|||||||
@ -69,7 +69,8 @@ class (Enum a, Bounded a, Ord a, PathPiece a) => Button a where
|
|||||||
cssClass _ = BCDefault
|
cssClass _ = BCDefault
|
||||||
|
|
||||||
|
|
||||||
--Some standard Buttons useful throughout
|
|
||||||
|
{- Abort is not useful (press Back instead); Delete should be different:
|
||||||
data StandardButton = BtnDelete | BtnAbort | BtnSave
|
data StandardButton = BtnDelete | BtnAbort | BtnSave
|
||||||
deriving (Enum, Eq, Ord, Bounded, Read, Show)
|
deriving (Enum, Eq, Ord, Bounded, Read, Show)
|
||||||
|
|
||||||
@ -85,6 +86,7 @@ instance Button StandardButton where
|
|||||||
cssClass BtnDelete = BCWarning
|
cssClass BtnDelete = BCWarning
|
||||||
cssClass BtnAbort = BCDefault
|
cssClass BtnAbort = BCDefault
|
||||||
cssClass BtnSave = BCPrimary
|
cssClass BtnSave = BCPrimary
|
||||||
|
-}
|
||||||
|
|
||||||
data SubmitButton = BtnSubmit
|
data SubmitButton = BtnSubmit
|
||||||
deriving (Enum, Eq, Ord, Bounded, Read, Show)
|
deriving (Enum, Eq, Ord, Bounded, Read, Show)
|
||||||
@ -132,13 +134,13 @@ buttonField btn = Field {fieldParse, fieldView, fieldEnctype}
|
|||||||
fieldParse _ _ = return $ Left "Multiple button values"
|
fieldParse _ _ = return $ Left "Multiple button values"
|
||||||
|
|
||||||
|
|
||||||
combinedButtonField1 :: Button a => [a] -> AForm Handler [Maybe a]
|
combinedButtonField :: Button a => [a] -> AForm Handler [Maybe a]
|
||||||
combinedButtonField1 btns = traverse b2f btns
|
combinedButtonField btns = traverse b2f btns
|
||||||
where
|
where
|
||||||
b2f b = aopt (buttonField b) "" Nothing
|
b2f b = aopt (buttonField b) "" Nothing
|
||||||
|
|
||||||
submitButton :: AForm Handler ()
|
submitButton :: AForm Handler ()
|
||||||
submitButton = void $ combinedButtonField1 [BtnSubmit]
|
submitButton = void $ combinedButtonField [BtnSubmit]
|
||||||
|
|
||||||
{-
|
{-
|
||||||
combinedButtonField :: Button a => [a] -> Form m -> Form (a,m)
|
combinedButtonField :: Button a => [a] -> Form m -> Form (a,m)
|
||||||
|
|||||||
@ -11,6 +11,3 @@
|
|||||||
<div .bs-callout bs-callout-info well>
|
<div .bs-callout bs-callout-info well>
|
||||||
<form .form-horizontal method=post action=@{actionUrl}#forms enctype=#{formEnctype}>
|
<form .form-horizontal method=post action=@{actionUrl}#forms enctype=#{formEnctype}>
|
||||||
^{formWidget}
|
^{formWidget}
|
||||||
<div .btn-group>
|
|
||||||
$forall (fAct,bLbl,bCl) <- formActions
|
|
||||||
<button .btn .#{bCl} type=submit name=formaction value=#{fAct}>#{bLbl}
|
|
||||||
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
<li .list-group-item>
|
<li .list-group-item>
|
||||||
<a href=@{TermShowR}>Semester Verwaltung
|
<a href=@{TermShowR}>Semester Verwaltung
|
||||||
|
<a href=@{TermEditR}>Neues Semester anlegen
|
||||||
|
|
||||||
<li .list-group-item>
|
<li .list-group-item>
|
||||||
<a href=@{CourseEditR}>Kurse anlegen, editieren und anzeigen
|
<a href=@{CourseEditR}>Kurse anlegen, editieren und anzeigen
|
||||||
|
|||||||
@ -1,139 +0,0 @@
|
|||||||
<div .masthead>
|
|
||||||
<div .container>
|
|
||||||
<div .row>
|
|
||||||
<h1 .header>
|
|
||||||
Yesod—a modern framework for blazing fast websites
|
|
||||||
<h2>
|
|
||||||
Fast, stable & spiced with great community
|
|
||||||
<a href="http://www.yesodweb.com/book/" .btn.btn-info.btn-lg>
|
|
||||||
Read the Book
|
|
||||||
|
|
||||||
<div .container>
|
|
||||||
<!-- Starting
|
|
||||||
================================================== -->
|
|
||||||
<div .bs-docs-section>
|
|
||||||
<div .row>
|
|
||||||
<div .col-lg-12>
|
|
||||||
<div .page-header>
|
|
||||||
<h1 #start>Starting
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Now that you have a working project you should use the
|
|
||||||
<a href=http://www.yesodweb.com/book/>Yesod book</a> to learn more.
|
|
||||||
<p>
|
|
||||||
You can also use this scaffolded site to explore some concepts, and best practices.
|
|
||||||
|
|
||||||
<ul .list-group>
|
|
||||||
|
|
||||||
<li .list-group-item>
|
|
||||||
This page was generated by the <tt>#{handlerName}</tt> handler in
|
|
||||||
<tt>Handler/Home.hs</tt>.
|
|
||||||
|
|
||||||
<li .list-group-item>
|
|
||||||
The <tt>#{handlerName}</tt> handler is set to generate your
|
|
||||||
site's home screen in Routes file
|
|
||||||
<tt>config/routes
|
|
||||||
|
|
||||||
<li .list-group-item>
|
|
||||||
We can link to other handlers, like the <a href="@{ProfileR}">Profile</a>.
|
|
||||||
Try it out as an anonymous user and see the access denied.
|
|
||||||
Then, try to <a href="@{AuthR LoginR}">login</a> with the dummy authentication added
|
|
||||||
while in development.
|
|
||||||
|
|
||||||
<li .list-group-item>
|
|
||||||
The HTML you are seeing now is actually composed by a number of <em>widgets</em>, #
|
|
||||||
most of them are brought together by the <tt>defaultLayout</tt> function which #
|
|
||||||
is defined in the <tt>Foundation.hs</tt> module, and used by <tt>#{handlerName}</tt>. #
|
|
||||||
All the files for templates and wigdets are in <tt>templates</tt>.
|
|
||||||
|
|
||||||
<li .list-group-item>
|
|
||||||
A Widget's Html, Css and Javascript are separated in three files with the
|
|
||||||
<tt>.hamlet</tt>, <tt>.lucius</tt> and <tt>.julius</tt> extensions.
|
|
||||||
|
|
||||||
<li .list-group-item ##{aDomId}>
|
|
||||||
If you had javascript enabled then you wouldn't be seeing this.
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<!-- Forms
|
|
||||||
================================================== -->
|
|
||||||
<div .bs-docs-section>
|
|
||||||
<div .row>
|
|
||||||
<div .col-lg-12>
|
|
||||||
<div .page-header>
|
|
||||||
<h1 #forms>Forms
|
|
||||||
|
|
||||||
<p>
|
|
||||||
This is an example of a form. Read the
|
|
||||||
<a href="http://www.yesodweb.com/book/forms">Forms chapter</a> #
|
|
||||||
on the yesod book to learn more about them.
|
|
||||||
|
|
||||||
<div .row>
|
|
||||||
<div .col-lg-6>
|
|
||||||
<div .bs-callout bs-callout-info well>
|
|
||||||
<form .form-horizontal method=post action=@{HomeR}#forms enctype=#{formEnctype}>
|
|
||||||
^{formWidget}
|
|
||||||
|
|
||||||
<button .btn.btn-primary type="submit">
|
|
||||||
Upload it!
|
|
||||||
|
|
||||||
|
|
||||||
<div .col-lg-4.col-lg-offset-1>
|
|
||||||
<div .bs-callout.bs-callout-info.upload-response>
|
|
||||||
|
|
||||||
$maybe (FileForm info con) <- submission
|
|
||||||
Your file type is <em>#{fileContentType info}</em>. You say it has: <em>#{con}</em>
|
|
||||||
|
|
||||||
$nothing
|
|
||||||
File upload result will be here...
|
|
||||||
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<!-- JSON
|
|
||||||
================================================== -->
|
|
||||||
<div .bs-docs-section>
|
|
||||||
<div .row>
|
|
||||||
<div .col-lg-12>
|
|
||||||
<div .page-header>
|
|
||||||
<h1 #json>JSON
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Yesod has JSON support baked-in.
|
|
||||||
The form below makes an AJAX request with Javascript,
|
|
||||||
then updates the page with your submission.
|
|
||||||
(see <tt>Handler/Comment.hs</tt>, <tt>templates/homepage.julius</tt>,
|
|
||||||
and <tt>Handler/Home.hs</tt> for the implementation).
|
|
||||||
|
|
||||||
<div .row>
|
|
||||||
<div .col-lg-6>
|
|
||||||
<div .bs-callout.bs-callout-info.well>
|
|
||||||
<form .form-horizontal ##{commentFormId}>
|
|
||||||
<div .field>
|
|
||||||
<textarea rows="2" ##{commentTextareaId} placeholder="Your comment here..." required></textarea>
|
|
||||||
|
|
||||||
<button .btn.btn-primary type=submit>
|
|
||||||
Create comment
|
|
||||||
|
|
||||||
<div .col-lg-4.col-lg-offset-1>
|
|
||||||
<div .bs-callout.bs-callout-info>
|
|
||||||
<small>
|
|
||||||
Your comments will appear here. You can also open the
|
|
||||||
console log to see the raw response from the server.
|
|
||||||
<ul ##{commentListId}>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<!-- Testing
|
|
||||||
================================================== -->
|
|
||||||
<div .bs-docs-section>
|
|
||||||
<div .row>
|
|
||||||
<div .col-lg-12>
|
|
||||||
<div .page-header>
|
|
||||||
<h1 #test>Testing
|
|
||||||
|
|
||||||
<p>
|
|
||||||
And last but not least, Testing. In <tt>test/Spec.hs</tt> you will find a #
|
|
||||||
test suite that performs tests on this page.
|
|
||||||
<p>
|
|
||||||
You can run your tests by doing: <code>stack test</code>
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
document.getElementById(#{toJSON aDomId}).innerHTML = "This text was added by the Javascript part of the homepage widget.";
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
$("##{rawJS commentFormId}").submit(function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
var message = $("##{rawJS commentTextareaId}").val();
|
|
||||||
// (Browsers that enforce the "required" attribute on the textarea won't see this alert)
|
|
||||||
if (!message) {
|
|
||||||
alert("Please fill out the comment form first.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make an AJAX request to the server to create a new comment
|
|
||||||
$.ajax({
|
|
||||||
url: 'null.invalid',
|
|
||||||
type: 'POST',
|
|
||||||
contentType: "application/json",
|
|
||||||
data: JSON.stringify({
|
|
||||||
message: message,
|
|
||||||
}),
|
|
||||||
success: function (data) {
|
|
||||||
var newNode = $("<li></li>");
|
|
||||||
newNode.text(data.message);
|
|
||||||
console.log(data);
|
|
||||||
$("##{rawJS commentListId}").append(newNode);
|
|
||||||
},
|
|
||||||
error: function (data) {
|
|
||||||
console.log("Error creating comment: " + data);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
h2##{aDomId} {
|
|
||||||
color: #990
|
|
||||||
}
|
|
||||||
|
|
||||||
li {
|
|
||||||
line-height: 2em;
|
|
||||||
font-size: 16px
|
|
||||||
}
|
|
||||||
|
|
||||||
##{commentTextareaId} {
|
|
||||||
width: 400px;
|
|
||||||
height: 100px;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user