Merge branch 'master' into feat/exercises
This commit is contained in:
commit
afc022eee7
@ -9,6 +9,7 @@
|
|||||||
{-# LANGUAGE RecordWildCards #-}
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
{-# LANGUAGE NamedFieldPuns #-}
|
{-# LANGUAGE NamedFieldPuns #-}
|
||||||
{-# LANGUAGE PatternGuards #-}
|
{-# LANGUAGE PatternGuards #-}
|
||||||
|
{-# LANGUAGE TupleSections #-}
|
||||||
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
|
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
|
||||||
|
|
||||||
module Foundation where
|
module Foundation where
|
||||||
@ -181,8 +182,69 @@ instance Yesod UniWorX where
|
|||||||
_other -> return ()
|
_other -> return ()
|
||||||
return res
|
return res
|
||||||
|
|
||||||
defaultLayout = defaultLinkLayout []
|
defaultLayout widget = do
|
||||||
|
master <- getYesod
|
||||||
|
mmsgs <- getMessages
|
||||||
|
|
||||||
|
mcurrentRoute <- getCurrentRoute
|
||||||
|
|
||||||
|
-- Get the breadcrumbs, as defined in the YesodBreadcrumbs instance.
|
||||||
|
(title, parents) <- breadcrumbs
|
||||||
|
|
||||||
|
let
|
||||||
|
menu = defaultLinks ++ maybe [] pageActions mcurrentRoute
|
||||||
|
|
||||||
|
menuTypes <- filterM (menuItemAccessCallback . menuItem) menu
|
||||||
|
|
||||||
|
-- Lookup Favourites if possible
|
||||||
|
favourites' <- do
|
||||||
|
muid <- maybeAuthId
|
||||||
|
case muid of
|
||||||
|
Nothing -> return []
|
||||||
|
(Just uid) -> runDB . E.select . E.from $ \(course `E.InnerJoin` courseFavourite) -> do
|
||||||
|
E.on (course E.^. CourseId E.==. courseFavourite E.^. CourseFavouriteCourse)
|
||||||
|
E.where_ (courseFavourite E.^. CourseFavouriteUser E.==. E.val uid)
|
||||||
|
E.orderBy [ E.asc $ course E.^. CourseShorthand ]
|
||||||
|
return course
|
||||||
|
|
||||||
|
favourites <- forM favourites' $ \(Entity _ c@Course{..})
|
||||||
|
-> let
|
||||||
|
courseRoute = CourseR courseTermId courseShorthand CourseShowR
|
||||||
|
in (c, courseRoute, ) <$> filterM (menuItemAccessCallback . menuItem) (pageActions courseRoute)
|
||||||
|
|
||||||
|
-- We break up the default layout into two components:
|
||||||
|
-- default-layout is the contents of the body tag, and
|
||||||
|
-- default-layout-wrapper is the entire page. Since the final
|
||||||
|
-- value passed to hamletToRepHtml cannot be a widget, this allows
|
||||||
|
-- you to use normal widget features in default-layout.
|
||||||
|
|
||||||
|
let
|
||||||
|
navbar :: Widget
|
||||||
|
navbar = $(widgetFile "widgets/navbar")
|
||||||
|
asidenav :: Widget
|
||||||
|
asidenav = $(widgetFile "widgets/asidenav")
|
||||||
|
breadcrumbs :: Widget
|
||||||
|
breadcrumbs = $(widgetFile "widgets/breadcrumbs")
|
||||||
|
pageactionprime :: Widget
|
||||||
|
pageactionprime = $(widgetFile "widgets/pageactionprime")
|
||||||
|
-- functions to determine if there are page-actions
|
||||||
|
isPageActionPrime :: MenuTypes -> Bool
|
||||||
|
isPageActionPrime (PageActionPrime _) = True
|
||||||
|
isPageActionPrime _ = False
|
||||||
|
hasPageActions :: Bool
|
||||||
|
hasPageActions = any isPageActionPrime menuTypes
|
||||||
|
|
||||||
|
pc <- widgetToPageContent $ do
|
||||||
|
addStylesheetRemote "https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,800,900"
|
||||||
|
addScript $ StaticR js_featureChecker_js
|
||||||
|
addStylesheet $ StaticR css_fonts_css
|
||||||
|
addStylesheet $ StaticR css_icons_css
|
||||||
|
$(widgetFile "default-layout")
|
||||||
|
$(widgetFile "standalone/modal")
|
||||||
|
$(widgetFile "standalone/showHide")
|
||||||
|
$(widgetFile "standalone/inputs")
|
||||||
|
withUrlRenderer $(hamletFile "templates/default-layout-wrapper.hamlet")
|
||||||
|
|
||||||
-- The page to be redirected to when authentication is required.
|
-- The page to be redirected to when authentication is required.
|
||||||
authRoute _ = Just $ AuthR LoginR
|
authRoute _ = Just $ AuthR LoginR
|
||||||
|
|
||||||
@ -356,6 +418,40 @@ instance YesodBreadcrumbs UniWorX where
|
|||||||
breadcrumb ProfileR = return ("Profile", Just HomeR)
|
breadcrumb ProfileR = return ("Profile", Just HomeR)
|
||||||
breadcrumb _ = return ("home", Nothing)
|
breadcrumb _ = return ("home", Nothing)
|
||||||
|
|
||||||
|
pageActions :: Route UniWorX -> [MenuTypes]
|
||||||
|
pageActions (CourseR tid csh CourseShowR) =
|
||||||
|
[ PageActionPrime $ MenuItem
|
||||||
|
{ menuItemLabel = "Übungsblätter"
|
||||||
|
, menuItemIcon = Nothing
|
||||||
|
, menuItemRoute = CSheetR tid csh SheetListR
|
||||||
|
, menuItemAccessCallback' = return True
|
||||||
|
}
|
||||||
|
]
|
||||||
|
pageActions (CourseR tid csh (SheetR SheetListR)) =
|
||||||
|
[ PageActionPrime $ MenuItem
|
||||||
|
{ menuItemLabel = "Neues Übungsblatt"
|
||||||
|
, menuItemIcon = Nothing
|
||||||
|
, menuItemRoute = CSheetR tid csh SheetNewR
|
||||||
|
, menuItemAccessCallback' = return True
|
||||||
|
}
|
||||||
|
]
|
||||||
|
pageActions TermShowR =
|
||||||
|
[ PageActionPrime $ MenuItem
|
||||||
|
{ menuItemLabel = "Neues Semester"
|
||||||
|
, menuItemIcon = Nothing
|
||||||
|
, menuItemRoute = TermEditR
|
||||||
|
, menuItemAccessCallback' = return True
|
||||||
|
}
|
||||||
|
]
|
||||||
|
pageActions (CourseListTermR _) =
|
||||||
|
[ PageActionPrime $ MenuItem
|
||||||
|
{ menuItemLabel = "Neuer Kurs"
|
||||||
|
, menuItemIcon = Just "book"
|
||||||
|
, menuItemRoute = CourseNewR
|
||||||
|
, menuItemAccessCallback' = return True
|
||||||
|
}
|
||||||
|
]
|
||||||
|
pageActions _ = []
|
||||||
|
|
||||||
defaultLinks :: [MenuTypes]
|
defaultLinks :: [MenuTypes]
|
||||||
defaultLinks = -- Define the menu items of the header.
|
defaultLinks = -- Define the menu items of the header.
|
||||||
@ -409,67 +505,6 @@ defaultLinks = -- Define the menu items of the header.
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
defaultLinkLayout :: [MenuTypes] -> Widget -> Handler Html
|
|
||||||
defaultLinkLayout = defaultMenuLayout . (defaultLinks ++)
|
|
||||||
|
|
||||||
defaultMenuLayout :: [MenuTypes] -> Widget -> Handler Html
|
|
||||||
defaultMenuLayout menu widget = do
|
|
||||||
master <- getYesod
|
|
||||||
mmsgs <- getMessages
|
|
||||||
|
|
||||||
mcurrentRoute <- getCurrentRoute
|
|
||||||
|
|
||||||
-- Get the breadcrumbs, as defined in the YesodBreadcrumbs instance.
|
|
||||||
(title, parents) <- breadcrumbs
|
|
||||||
|
|
||||||
menuTypes <- filterM (menuItemAccessCallback . menuItem) menu
|
|
||||||
|
|
||||||
-- Lookup Favourites if possible
|
|
||||||
favourites <- do
|
|
||||||
muid <- maybeAuthId
|
|
||||||
case muid of
|
|
||||||
Nothing -> return []
|
|
||||||
(Just uid) -> runDB . E.select . E.from $ \(course `E.InnerJoin` courseFavourite) -> do
|
|
||||||
E.on (course E.^. CourseId E.==. courseFavourite E.^. CourseFavouriteCourse)
|
|
||||||
E.where_ (courseFavourite E.^. CourseFavouriteUser E.==. E.val uid)
|
|
||||||
E.orderBy [ E.asc $ course E.^. CourseShorthand ]
|
|
||||||
return course
|
|
||||||
|
|
||||||
-- We break up the default layout into two components:
|
|
||||||
-- default-layout is the contents of the body tag, and
|
|
||||||
-- default-layout-wrapper is the entire page. Since the final
|
|
||||||
-- value passed to hamletToRepHtml cannot be a widget, this allows
|
|
||||||
-- you to use normal widget features in default-layout.
|
|
||||||
|
|
||||||
let
|
|
||||||
navbar :: Widget
|
|
||||||
navbar = $(widgetFile "widgets/navbar")
|
|
||||||
asidenav :: Widget
|
|
||||||
asidenav = $(widgetFile "widgets/asidenav")
|
|
||||||
breadcrumbs :: Widget
|
|
||||||
breadcrumbs = $(widgetFile "widgets/breadcrumbs")
|
|
||||||
pageactionprime :: Widget
|
|
||||||
pageactionprime = $(widgetFile "widgets/pageactionprime")
|
|
||||||
-- functions to determine if there are page-actions
|
|
||||||
isPageActionPrime :: MenuTypes -> Bool
|
|
||||||
isPageActionPrime (PageActionPrime _) = True
|
|
||||||
isPageActionPrime _ = False
|
|
||||||
hasPageActions :: Bool
|
|
||||||
hasPageActions = any isPageActionPrime menuTypes
|
|
||||||
|
|
||||||
pc <- widgetToPageContent $ do
|
|
||||||
addStylesheetRemote "https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,800,900"
|
|
||||||
addScript $ StaticR js_featureChecker_js
|
|
||||||
addScript $ StaticR js_fetchPolyfill_js
|
|
||||||
addScript $ StaticR js_urlPolyfill_js
|
|
||||||
addStylesheet $ StaticR css_fonts_css
|
|
||||||
addStylesheet $ StaticR css_icons_css
|
|
||||||
$(widgetFile "default-layout")
|
|
||||||
$(widgetFile "standalone/modal")
|
|
||||||
$(widgetFile "standalone/showHide")
|
|
||||||
$(widgetFile "standalone/inputs")
|
|
||||||
withUrlRenderer $(hamletFile "templates/default-layout-wrapper.hamlet")
|
|
||||||
|
|
||||||
-- How to run database actions.
|
-- How to run database actions.
|
||||||
instance YesodPersist UniWorX where
|
instance YesodPersist UniWorX where
|
||||||
type YesodPersistBackend UniWorX = SqlBackend
|
type YesodPersistBackend UniWorX = SqlBackend
|
||||||
|
|||||||
@ -63,16 +63,8 @@ getCourseListTermR tidini = do
|
|||||||
|]
|
|]
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
let pageLinks =
|
|
||||||
[ PageActionPrime $ MenuItem
|
|
||||||
{ menuItemLabel = "Neuer Kurs"
|
|
||||||
, menuItemIcon = Just "book"
|
|
||||||
, menuItemRoute = CourseNewR
|
|
||||||
, menuItemAccessCallback' = return True
|
|
||||||
}
|
|
||||||
]
|
|
||||||
let coursesTable = encodeWidgetTable tableSortable colonnadeTerms courses
|
let coursesTable = encodeWidgetTable tableSortable colonnadeTerms courses
|
||||||
defaultLinkLayout pageLinks $ do
|
defaultLayout $ do
|
||||||
setTitle "Semesterkurse"
|
setTitle "Semesterkurse"
|
||||||
$(widgetFile "courses")
|
$(widgetFile "courses")
|
||||||
|
|
||||||
@ -92,15 +84,7 @@ getCourseShowR tid csh = do
|
|||||||
return $ (courseEnt,dependent)
|
return $ (courseEnt,dependent)
|
||||||
let course = entityVal courseEnt
|
let course = entityVal courseEnt
|
||||||
(regWidget, regEnctype) <- generateFormPost $ identifyForm "registerBtn" $ registerButton $ mbRegistered
|
(regWidget, regEnctype) <- generateFormPost $ identifyForm "registerBtn" $ registerButton $ mbRegistered
|
||||||
let pageActions =
|
defaultLayout $ do
|
||||||
[ PageActionPrime $ MenuItem
|
|
||||||
{ menuItemLabel = "Übungsblätter"
|
|
||||||
, menuItemIcon = Nothing
|
|
||||||
, menuItemRoute = CSheetR tid csh SheetListR
|
|
||||||
, menuItemAccessCallback' = return True
|
|
||||||
}
|
|
||||||
]
|
|
||||||
defaultLinkLayout pageActions $ do
|
|
||||||
setTitle $ [shamlet| #{toPathPiece tid} - #{csh}|]
|
setTitle $ [shamlet| #{toPathPiece tid} - #{csh}|]
|
||||||
$(widgetFile "course")
|
$(widgetFile "course")
|
||||||
|
|
||||||
|
|||||||
@ -163,15 +163,7 @@ getSheetList courseEnt = do
|
|||||||
let colSheets = if showAdmin
|
let colSheets = if showAdmin
|
||||||
then colBase `mappend` colAdmin
|
then colBase `mappend` colAdmin
|
||||||
else colBase
|
else colBase
|
||||||
let pageActions =
|
defaultLayout $ do
|
||||||
[ PageActionPrime $ MenuItem
|
|
||||||
{ menuItemLabel = "Neues Übungsblatt"
|
|
||||||
, menuItemIcon = Nothing
|
|
||||||
, menuItemRoute = CSheetR tid csh SheetNewR
|
|
||||||
, menuItemAccessCallback' = return True
|
|
||||||
}
|
|
||||||
]
|
|
||||||
defaultLinkLayout pageActions $ do
|
|
||||||
setTitle $ toHtml $ T.append "Übungsblätter " csh
|
setTitle $ toHtml $ T.append "Übungsblätter " csh
|
||||||
if null sheets
|
if null sheets
|
||||||
then [whamlet|Es wurden noch keine Übungsblätter angelegt.|]
|
then [whamlet|Es wurden noch keine Übungsblätter angelegt.|]
|
||||||
|
|||||||
@ -89,15 +89,7 @@ getTermShowR = do
|
|||||||
, dbtAttrs = tableDefault
|
, dbtAttrs = tableDefault
|
||||||
, dbtIdent = "terms" :: Text
|
, dbtIdent = "terms" :: Text
|
||||||
}
|
}
|
||||||
let pageActions =
|
defaultLayout $ do
|
||||||
[ PageActionPrime $ MenuItem
|
|
||||||
{ menuItemLabel = "Neues Semester"
|
|
||||||
, menuItemIcon = Nothing
|
|
||||||
, menuItemRoute = TermEditR
|
|
||||||
, menuItemAccessCallback' = return True
|
|
||||||
}
|
|
||||||
]
|
|
||||||
defaultLinkLayout pageActions $ do
|
|
||||||
setTitle "Freigeschaltete Semester"
|
setTitle "Freigeschaltete Semester"
|
||||||
$(widgetFile "terms")
|
$(widgetFile "terms")
|
||||||
|
|
||||||
|
|||||||
42
static/css/tabber.css
Normal file
42
static/css/tabber.css
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
.tab-group {
|
||||||
|
box-shadow: 0 0 0 18px white, 0 0 0 20px #b3b7c1;
|
||||||
|
margin-top: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-group-openers {
|
||||||
|
display: flex;
|
||||||
|
justify-content: stretch;
|
||||||
|
line-height: 40px;
|
||||||
|
font-size: 14px;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-opener {
|
||||||
|
display: inline-block;
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
padding: 0 13px;
|
||||||
|
margin: 0 2px;
|
||||||
|
background-color: #b3b7c1;
|
||||||
|
color: white;
|
||||||
|
font-size: 16px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: all .2s ease;
|
||||||
|
box-shadow: inset 0 -4px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
border-top: 5px solid transparent;
|
||||||
|
}
|
||||||
|
.tab-opener:not(.tab-visible):hover {
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: transparent;
|
||||||
|
color: rgb(52, 48, 58);
|
||||||
|
box-shadow: none;
|
||||||
|
border-top-color: grey;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-opener.tab-visible {
|
||||||
|
background-color: transparent;
|
||||||
|
color: rgb(52, 48, 58);
|
||||||
|
border-top-color: #5F98C2;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
88
static/js/tabber.js
Normal file
88
static/js/tabber.js
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
(function($) {
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// define plugin
|
||||||
|
$.fn.tabgroup = function() {
|
||||||
|
|
||||||
|
var $this = $(this);
|
||||||
|
var $openers = $('<div class="tab-group-openers"></div>');
|
||||||
|
$this.prepend($openers);
|
||||||
|
|
||||||
|
var openedByDefault = $this.data('tab-open') || 0;
|
||||||
|
var tabs = [];
|
||||||
|
var currentTab = {};
|
||||||
|
|
||||||
|
$this.find('.tab').each(function(i, t) {
|
||||||
|
var tab = $(t);
|
||||||
|
tab.data('tab-index', i);
|
||||||
|
var tabName = tab.data('tab-name') || 'Tab '+i;
|
||||||
|
var tabFile = tab.data('tab-file') || false;
|
||||||
|
var $opener = makeOpener(tabName, i);
|
||||||
|
$openers.append($opener);
|
||||||
|
if (tab.find('.tab-title')) {
|
||||||
|
tab.find('.tab-title').remove();
|
||||||
|
}
|
||||||
|
tab.hide();
|
||||||
|
var loaded = false;
|
||||||
|
tabs.push({index: i, name: tabName, file: tabFile, dom: tab, opener: $opener, loaded: false});
|
||||||
|
});
|
||||||
|
|
||||||
|
$this.on('click', 'a[href^="#"]', function(event) {
|
||||||
|
var $target = $(event.currentTarget);
|
||||||
|
var tab = getTabByName($target.attr('href').replace('#', ''));
|
||||||
|
if ( tab ) {
|
||||||
|
showTab(tab.index);
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
|
function getTabByName(name) {
|
||||||
|
var it = -1;
|
||||||
|
$.each(tabs, function(i, t) {
|
||||||
|
if ( t.name.toLowerCase() === name.toLowerCase() ) {
|
||||||
|
it = i;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if ( it >= 0 ) {
|
||||||
|
return tabs[it];
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeOpener(tabName, i) {
|
||||||
|
return $('<span class="tab-opener">'+tabName+'</span>').
|
||||||
|
on('click', function() {
|
||||||
|
showTab(i);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function showTab(i) {
|
||||||
|
tabs.forEach(function(t) {
|
||||||
|
t.dom.hide();
|
||||||
|
t.opener.removeClass('tab-visible');
|
||||||
|
});
|
||||||
|
currentTab = tabs[i];
|
||||||
|
if ( !currentTab.loaded && currentTab.file ){
|
||||||
|
$.get(currentTab.file, function(res) {
|
||||||
|
currentTab.dom.html(res);
|
||||||
|
currentTab.loaded = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
currentTab.opener.addClass('tab-visible');
|
||||||
|
currentTab.dom.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
showTab(openedByDefault);
|
||||||
|
currentTab = tabs[openedByDefault];
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// apply plugin to all available tab-groups
|
||||||
|
$('.tab-group').each(function(i, t) {
|
||||||
|
$(t).tabgroup();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
})($);
|
||||||
1650
static/js/zepto.js
Normal file
1650
static/js/zepto.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,34 +1,102 @@
|
|||||||
<div .course-header>
|
<div .container>
|
||||||
<div .course-header__info>
|
<h2>#{courseName course}
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
|
||||||
<th>Teilnehmer
|
|
||||||
<td>
|
|
||||||
#{participants}
|
|
||||||
$maybe capacity <- courseCapacity course
|
|
||||||
\ von #{capacity}
|
|
||||||
<tr>
|
|
||||||
<th>Anmeldezeitraum
|
|
||||||
<td>
|
|
||||||
$maybe regFrom <- courseRegisterFrom course
|
|
||||||
#{formatTimeGerWD regFrom}
|
|
||||||
$maybe regTo <- courseRegisterTo course
|
|
||||||
\ bis #{formatTimeGerWD regTo}
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<form method=post action=@{CourseR tid csh CourseShowR} enctype=#{regEnctype}>
|
|
||||||
^{regWidget}
|
|
||||||
|
|
||||||
<div .course-header__title>
|
|
||||||
<h1>#{courseName course}
|
|
||||||
$maybe school <- schoolMB
|
$maybe school <- schoolMB
|
||||||
<h4>#{schoolName school}
|
<tr>
|
||||||
|
<th #school>Fakultät/Institut
|
||||||
|
<td>
|
||||||
|
#{schoolName school}
|
||||||
|
$maybe descr <- courseDescription course
|
||||||
|
<tr>
|
||||||
|
<th #description>Beschreibung
|
||||||
|
<td>
|
||||||
|
<p>#{descr}
|
||||||
|
$maybe link <- courseLinkExternal course
|
||||||
|
<tr>
|
||||||
|
<th #website>Website
|
||||||
|
<td>
|
||||||
|
<a href=#{link}>#{link}
|
||||||
|
<tr>
|
||||||
|
<th #participants>Teilnehmer
|
||||||
|
<td>
|
||||||
|
#{participants}
|
||||||
|
$maybe capacity <- courseCapacity course
|
||||||
|
\ von #{capacity}
|
||||||
|
<tr>
|
||||||
|
<th #registration>Anmeldezeitraum
|
||||||
|
<td>
|
||||||
|
$maybe regFrom <- courseRegisterFrom course
|
||||||
|
#{formatTimeGerWD regFrom}
|
||||||
|
$maybe regTo <- courseRegisterTo course
|
||||||
|
\ bis #{formatTimeGerWD regTo}
|
||||||
|
|
||||||
|
$# if allowed to register
|
||||||
|
<div .course__registration>
|
||||||
|
<a href="#">Anmelden
|
||||||
|
|
||||||
|
$# <form method=post action=@{CourseR tid csh CourseShowR} enctype=#{regEnctype}>
|
||||||
|
$# ^{regWidget}
|
||||||
|
|
||||||
<div .container>
|
<div .container>
|
||||||
$maybe descr <- courseDescription course
|
<div .tab-group>
|
||||||
<h2 #description>Beschreibung
|
<div .tab data-tab-name="Übungsblätter">
|
||||||
<p> #{descr}
|
^{modal "#modal-toggler__new-sheet" Nothing}
|
||||||
$maybe link <- courseLinkExternal course
|
<h3 .tab-title>Übungsblätter
|
||||||
<h4 #linl>Homepage
|
<table .table.table-striped.table-hover>
|
||||||
<a href=#{link}>#{link}
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Blatt
|
||||||
|
<th>Abgabe ab
|
||||||
|
<th>Abgabe bis
|
||||||
|
<th>Bewertung</th>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="http://localhost:3000/course/S2018/ffp/ex/Blatt%201/show" role="button">Blatt 1
|
||||||
|
<td>Do 08.04.18
|
||||||
|
<td>Do 11.04.18
|
||||||
|
<td>NotGraded
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="http://localhost:3000/course/S2018/ffp/ex/Blatt%201/show" role="button">Blatt 2
|
||||||
|
<td>Do 15.04.18
|
||||||
|
<td>Do 18.04.18
|
||||||
|
<td>NotGraded
|
||||||
|
<tr .no-hover.no-stripe>
|
||||||
|
<td>
|
||||||
|
<td>
|
||||||
|
<td>
|
||||||
|
<td>
|
||||||
|
<td>
|
||||||
|
<a href="/course/S2018/ffp/ex/new" #modal-toggler__new-sheet>Neues Übungsblatt anlegen
|
||||||
|
<div .tab data-tab-name="Übungsgruppen">
|
||||||
|
<h3 .tab-title>Übungsgruppen
|
||||||
|
<table .table.table-striped.table-hover>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name
|
||||||
|
<th>Termin
|
||||||
|
<th>Raum
|
||||||
|
<th>Studenten
|
||||||
|
<th>Tutor
|
||||||
|
<th>Anmeldung bis
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="#">Gruppe 1
|
||||||
|
<td>Montag 10:00 - 12:00
|
||||||
|
<td>N/A
|
||||||
|
<td>2/10
|
||||||
|
<td>Tutor1 Tutoren
|
||||||
|
<td>Do 21.02.2019, 19:00
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="#">Gruppe 2
|
||||||
|
<td>Montag 12:00 - 14:00
|
||||||
|
<td>N/A
|
||||||
|
<td>0/10
|
||||||
|
<td>Assistant1 Assistant
|
||||||
|
<td>Di 21.02.2017, 19:00
|
||||||
|
<div .tab data-tab-name="Klausuren">
|
||||||
|
<h3 .tab-title>Klausuren
|
||||||
|
<div>...
|
||||||
|
|||||||
@ -1,19 +0,0 @@
|
|||||||
.course-header {
|
|
||||||
/*display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-between;*/
|
|
||||||
}
|
|
||||||
|
|
||||||
.course-header__title {
|
|
||||||
align-self: baseline;
|
|
||||||
}
|
|
||||||
.course-header__info {
|
|
||||||
border: 1px solid var(--greybase);
|
|
||||||
padding: 13px;
|
|
||||||
align-self: center;
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.course-header__info table {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
@ -106,6 +106,24 @@ table {
|
|||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.table-striped {
|
||||||
|
|
||||||
|
tbody {
|
||||||
|
tr:not(.no-stripe):nth-child(even) {
|
||||||
|
background-color: #e8e8e8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-hover {
|
||||||
|
|
||||||
|
tbody {
|
||||||
|
tr:not(.no-hover):hover {
|
||||||
|
background-color: #d8d8d8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
th, td {
|
th, td {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
padding: 0 13px 0 7px;
|
padding: 0 13px 0 7px;
|
||||||
|
|||||||
@ -40,7 +40,7 @@
|
|||||||
^{modal ".toggler1" Nothing}
|
^{modal ".toggler1" Nothing}
|
||||||
<a href="/" .btn.toggler1>Klick mich für Ajax-Test
|
<a href="/" .btn.toggler1>Klick mich für Ajax-Test
|
||||||
<noscript>(Für Modals bitte JS aktivieren)</noscript>
|
<noscript>(Für Modals bitte JS aktivieren)</noscript>
|
||||||
^{modal ".toggler2" (Just "Test wegen Modal")}
|
^{modal ".toggler2" (Just "Test Inhalt für Modal")}
|
||||||
<div .btn.toggler2>Klick mich für Content-Test
|
<div .btn.toggler2>Klick mich für Content-Test
|
||||||
<noscript>(Für Modals bitte JS aktivieren)</noscript>
|
<noscript>(Für Modals bitte JS aktivieren)</noscript>
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,8 @@
|
|||||||
var origParent = modal.parentNode;
|
var origParent = modal.parentNode;
|
||||||
|
|
||||||
function open(event) {
|
function open(event) {
|
||||||
|
// disable modals for narrow screens
|
||||||
|
if (window.innerWidth < 768) return true;
|
||||||
if (event) {
|
if (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
@ -64,7 +66,9 @@
|
|||||||
replaceMe.classList.remove('replace-me');
|
replaceMe.classList.remove('replace-me');
|
||||||
replaceMe.innerText = '...loading';
|
replaceMe.innerText = '...loading';
|
||||||
if (replaceWith.length > 0) {
|
if (replaceWith.length > 0) {
|
||||||
fetch(replaceWith).then(function(response) {
|
fetch(replaceWith, {
|
||||||
|
credentials: 'same-origin'
|
||||||
|
}).then(function(response) {
|
||||||
return response.text();
|
return response.text();
|
||||||
}).then(function(body) {
|
}).then(function(body) {
|
||||||
var modalContent = document.createElement('div');
|
var modalContent = document.createElement('div');
|
||||||
|
|||||||
@ -17,23 +17,17 @@ $newline never
|
|||||||
<h3 .asidenav__box-title>
|
<h3 .asidenav__box-title>
|
||||||
WiSe 17/18
|
WiSe 17/18
|
||||||
<ul .asidenav__list>
|
<ul .asidenav__list>
|
||||||
$forall (Entity _ Course{..}) <- favourites
|
$forall (Course{..}, courseRoute, pageActions) <- favourites
|
||||||
$with route <- CourseR courseTerm courseShorthand CourseShowR
|
<li .asidenav__list-item>
|
||||||
<li .asidenav__list-item :Just route == mcurrentRoute:.asidenav__list-item--active>
|
<a .asidenav__link-wrapper href=@{courseRoute}>
|
||||||
<a .asidenav__link-wrapper href=@{route}>
|
<div .asidenav__link-shorthand>#{courseShorthand}
|
||||||
<div .asidenav__link-shorthand>#{courseShorthand}
|
<div .asidenav__link-label>#{courseName}
|
||||||
<div .asidenav__link-label>#{courseName}
|
<ul .asidenav__nested-list>
|
||||||
|
$forall action <- pageActions
|
||||||
<li .asidenav__list-item>
|
$case action
|
||||||
<a .asidenav__link-wrapper href="/course/S2018/ixd/show">
|
$of PageActionPrime (MenuItem{..})
|
||||||
<div .asidenav__link-shorthand>EXAMPLE
|
<li .asidenav__list-item>
|
||||||
<div .asidenav__link-label>Beispiel-Kurs
|
<a .asidenav__link-wrapper href=@{menuItemRoute}>#{menuItemLabel}
|
||||||
<ul .asidenav__nested-list>
|
$of _
|
||||||
<li .asidenav__list-item>
|
|
||||||
<a .asidenav__link-wrapper href="/course/S2018/ixd/ex">Übungsblätter
|
|
||||||
<li .asidenav__list-item>
|
|
||||||
<a .asidenav__link-wrapper href="/course/S2018/ixd/show">Klausuren
|
|
||||||
<li .asidenav__list-item>
|
|
||||||
<a .asidenav__link-wrapper href="/course/S2018/ixd/show">Übungsgruppen
|
|
||||||
|
|
||||||
<div .asidenav__toggler>
|
<div .asidenav__toggler>
|
||||||
|
|||||||
@ -1,18 +1,8 @@
|
|||||||
<div .modal.js-modal #modal-#{modalId} data-trigger=#{modalTrigger} data-closeable=true>
|
<div .modal.js-modal #modal-#{modalId} data-trigger=#{modalTrigger} data-closeable=true>
|
||||||
|
$# primitive way of checking if this is supposed to be add a placeholder for async data.
|
||||||
|
$# modalContent is 'placeholder' if there should be a placeholder only.
|
||||||
|
$# 'placeholder' has length 11.
|
||||||
$if 11 == length modalContent
|
$if 11 == length modalContent
|
||||||
<div .replace-me>
|
<div .replace-me>
|
||||||
$else
|
$else
|
||||||
<h2>Neue Veranstaltung
|
|
||||||
#{modalContent}
|
#{modalContent}
|
||||||
<form>
|
|
||||||
<div .form-group>
|
|
||||||
<label .reactive-label for="inp1">Name
|
|
||||||
<input type="text" id="inp1">
|
|
||||||
<div .form-group>
|
|
||||||
<label .reactive-label for="inp2">Kürzel
|
|
||||||
<input type="text" id="inp2">
|
|
||||||
<div .form-group>
|
|
||||||
<label .reactive-label for="inp3">Semester
|
|
||||||
<input type="text" id="inp3">
|
|
||||||
<div .form-group>
|
|
||||||
<input type="submit" value="Submit">
|
|
||||||
|
|||||||
Reference in New Issue
Block a user