login bereich

standalone
Simon Caminada 8 years ago
parent a74f6d0ee4
commit 5e1b34bfef

@ -1,6 +1,6 @@
/*!
* modernizr v3.5.0
* Build https://modernizr.com/download?-touchevents-setclasses-dontmin
* modernizr v3.6.0
* Build https://modernizr.com/download?-cssanimations-touchevents-setclasses-dontmin
*
* Copyright (c)
* Faruk Ates
@ -39,7 +39,7 @@
var ModernizrProto = {
// The current version, dummy
_version: '3.5.0',
_version: '3.6.0',
// Any settings that don't work as separate modules
// can go in here as configuration.
@ -510,6 +510,464 @@ This test will also return `true` for Firefox 4 Multitouch support.
});
/**
* If the browsers follow the spec, then they would expose vendor-specific styles as:
* elem.style.WebkitBorderRadius
* instead of something like the following (which is technically incorrect):
* elem.style.webkitBorderRadius
* WebKit ghosts their properties in lowercase but Opera & Moz do not.
* Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+
* erik.eae.net/archives/2008/03/10/21.48.10/
* More here: github.com/Modernizr/Modernizr/issues/issue/21
*
* @access private
* @returns {string} The string representing the vendor-specific style properties
*/
var omPrefixes = 'Moz O ms Webkit';
var cssomPrefixes = (ModernizrProto._config.usePrefixes ? omPrefixes.split(' ') : []);
ModernizrProto._cssomPrefixes = cssomPrefixes;
/**
* List of JavaScript DOM values used for tests
*
* @memberof Modernizr
* @name Modernizr._domPrefixes
* @optionName Modernizr._domPrefixes
* @optionProp domPrefixes
* @access public
* @example
*
* Modernizr._domPrefixes is exactly the same as [_prefixes](#modernizr-_prefixes), but rather
* than kebab-case properties, all properties are their Capitalized variant
*
* ```js
* Modernizr._domPrefixes === [ "Moz", "O", "ms", "Webkit" ];
* ```
*/
var domPrefixes = (ModernizrProto._config.usePrefixes ? omPrefixes.toLowerCase().split(' ') : []);
ModernizrProto._domPrefixes = domPrefixes;
/**
* contains checks to see if a string contains another string
*
* @access private
* @function contains
* @param {string} str - The string we want to check for substrings
* @param {string} substr - The substring we want to search the first string for
* @returns {boolean}
*/
function contains(str, substr) {
return !!~('' + str).indexOf(substr);
}
;
/**
* fnBind is a super small [bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) polyfill.
*
* @access private
* @function fnBind
* @param {function} fn - a function you want to change `this` reference to
* @param {object} that - the `this` you want to call the function with
* @returns {function} The wrapped version of the supplied function
*/
function fnBind(fn, that) {
return function() {
return fn.apply(that, arguments);
};
}
;
/**
* testDOMProps is a generic DOM property test; if a browser supports
* a certain property, it won't return undefined for it.
*
* @access private
* @function testDOMProps
* @param {array.<string>} props - An array of properties to test for
* @param {object} obj - An object or Element you want to use to test the parameters again
* @param {boolean|object} elem - An Element to bind the property lookup again. Use `false` to prevent the check
* @returns {false|*} returns false if the prop is unsupported, otherwise the value that is supported
*/
function testDOMProps(props, obj, elem) {
var item;
for (var i in props) {
if (props[i] in obj) {
// return the property name as a string
if (elem === false) {
return props[i];
}
item = obj[props[i]];
// let's bind a function
if (is(item, 'function')) {
// bind to obj unless overriden
return fnBind(item, elem || obj);
}
// return the unbound function or obj or value
return item;
}
}
return false;
}
;
/**
* cssToDOM takes a kebab-case string and converts it to camelCase
* e.g. box-sizing -> boxSizing
*
* @access private
* @function cssToDOM
* @param {string} name - String name of kebab-case prop we want to convert
* @returns {string} The camelCase version of the supplied name
*/
function cssToDOM(name) {
return name.replace(/([a-z])-([a-z])/g, function(str, m1, m2) {
return m1 + m2.toUpperCase();
}).replace(/^-/, '');
}
;
/**
* Create our "modernizr" element that we do most feature tests on.
*
* @access private
*/
var modElem = {
elem: createElement('modernizr')
};
// Clean up this element
Modernizr._q.push(function() {
delete modElem.elem;
});
var mStyle = {
style: modElem.elem.style
};
// kill ref for gc, must happen before mod.elem is removed, so we unshift on to
// the front of the queue.
Modernizr._q.unshift(function() {
delete mStyle.style;
});
/**
* domToCSS takes a camelCase string and converts it to kebab-case
* e.g. boxSizing -> box-sizing
*
* @access private
* @function domToCSS
* @param {string} name - String name of camelCase prop we want to convert
* @returns {string} The kebab-case version of the supplied name
*/
function domToCSS(name) {
return name.replace(/([A-Z])/g, function(str, m1) {
return '-' + m1.toLowerCase();
}).replace(/^ms-/, '-ms-');
}
;
/**
* wrapper around getComputedStyle, to fix issues with Firefox returning null when
* called inside of a hidden iframe
*
* @access private
* @function computedStyle
* @param {HTMLElement|SVGElement} - The element we want to find the computed styles of
* @param {string|null} [pseudoSelector]- An optional pseudo element selector (e.g. :before), of null if none
* @returns {CSSStyleDeclaration}
*/
function computedStyle(elem, pseudo, prop) {
var result;
if ('getComputedStyle' in window) {
result = getComputedStyle.call(window, elem, pseudo);
var console = window.console;
if (result !== null) {
if (prop) {
result = result.getPropertyValue(prop);
}
} else {
if (console) {
var method = console.error ? 'error' : 'log';
console[method].call(console, 'getComputedStyle returning null, its possible modernizr test results are inaccurate');
}
}
} else {
result = !pseudo && elem.currentStyle && elem.currentStyle[prop];
}
return result;
}
;
/**
* nativeTestProps allows for us to use native feature detection functionality if available.
* some prefixed form, or false, in the case of an unsupported rule
*
* @access private
* @function nativeTestProps
* @param {array} props - An array of property names
* @param {string} value - A string representing the value we want to check via @supports
* @returns {boolean|undefined} A boolean when @supports exists, undefined otherwise
*/
// Accepts a list of property names and a single value
// Returns `undefined` if native detection not available
function nativeTestProps(props, value) {
var i = props.length;
// Start with the JS API: http://www.w3.org/TR/css3-conditional/#the-css-interface
if ('CSS' in window && 'supports' in window.CSS) {
// Try every prefixed variant of the property
while (i--) {
if (window.CSS.supports(domToCSS(props[i]), value)) {
return true;
}
}
return false;
}
// Otherwise fall back to at-rule (for Opera 12.x)
else if ('CSSSupportsRule' in window) {
// Build a condition string for every prefixed variant
var conditionText = [];
while (i--) {
conditionText.push('(' + domToCSS(props[i]) + ':' + value + ')');
}
conditionText = conditionText.join(' or ');
return injectElementWithStyles('@supports (' + conditionText + ') { #modernizr { position: absolute; } }', function(node) {
return computedStyle(node, null, 'position') == 'absolute';
});
}
return undefined;
}
;
// testProps is a generic CSS / DOM property test.
// In testing support for a given CSS property, it's legit to test:
// `elem.style[styleName] !== undefined`
// If the property is supported it will return an empty string,
// if unsupported it will return undefined.
// We'll take advantage of this quick test and skip setting a style
// on our modernizr element, but instead just testing undefined vs
// empty string.
// Property names can be provided in either camelCase or kebab-case.
function testProps(props, prefixed, value, skipValueTest) {
skipValueTest = is(skipValueTest, 'undefined') ? false : skipValueTest;
// Try native detect first
if (!is(value, 'undefined')) {
var result = nativeTestProps(props, value);
if (!is(result, 'undefined')) {
return result;
}
}
// Otherwise do it properly
var afterInit, i, propsLength, prop, before;
// If we don't have a style element, that means we're running async or after
// the core tests, so we'll need to create our own elements to use
// inside of an SVG element, in certain browsers, the `style` element is only
// defined for valid tags. Therefore, if `modernizr` does not have one, we
// fall back to a less used element and hope for the best.
// for strict XHTML browsers the hardly used samp element is used
var elems = ['modernizr', 'tspan', 'samp'];
while (!mStyle.style && elems.length) {
afterInit = true;
mStyle.modElem = createElement(elems.shift());
mStyle.style = mStyle.modElem.style;
}
// Delete the objects if we created them.
function cleanElems() {
if (afterInit) {
delete mStyle.style;
delete mStyle.modElem;
}
}
propsLength = props.length;
for (i = 0; i < propsLength; i++) {
prop = props[i];
before = mStyle.style[prop];
if (contains(prop, '-')) {
prop = cssToDOM(prop);
}
if (mStyle.style[prop] !== undefined) {
// If value to test has been passed in, do a set-and-check test.
// 0 (integer) is a valid property value, so check that `value` isn't
// undefined, rather than just checking it's truthy.
if (!skipValueTest && !is(value, 'undefined')) {
// Needs a try catch block because of old IE. This is slow, but will
// be avoided in most cases because `skipValueTest` will be used.
try {
mStyle.style[prop] = value;
} catch (e) {}
// If the property value has changed, we assume the value used is
// supported. If `value` is empty string, it'll fail here (because
// it hasn't changed), which matches how browsers have implemented
// CSS.supports()
if (mStyle.style[prop] != before) {
cleanElems();
return prefixed == 'pfx' ? prop : true;
}
}
// Otherwise just return true, or the property name if this is a
// `prefixed()` call
else {
cleanElems();
return prefixed == 'pfx' ? prop : true;
}
}
}
cleanElems();
return false;
}
;
/**
* testPropsAll tests a list of DOM properties we want to check against.
* We specify literally ALL possible (known and/or likely) properties on
* the element including the non-vendor prefixed one, for forward-
* compatibility.
*
* @access private
* @function testPropsAll
* @param {string} prop - A string of the property to test for
* @param {string|object} [prefixed] - An object to check the prefixed properties on. Use a string to skip
* @param {HTMLElement|SVGElement} [elem] - An element used to test the property and value against
* @param {string} [value] - A string of a css value
* @param {boolean} [skipValueTest] - An boolean representing if you want to test if value sticks when set
* @returns {false|string} returns the string version of the property, or false if it is unsupported
*/
function testPropsAll(prop, prefixed, elem, value, skipValueTest) {
var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1),
props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' ');
// did they call .prefixed('boxSizing') or are we just testing a prop?
if (is(prefixed, 'string') || is(prefixed, 'undefined')) {
return testProps(props, prefixed, value, skipValueTest);
// otherwise, they called .prefixed('requestAnimationFrame', window[, elem])
} else {
props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');
return testDOMProps(props, prefixed, elem);
}
}
// Modernizr.testAllProps() investigates whether a given style property,
// or any of its vendor-prefixed variants, is recognized
//
// Note that the property names must be provided in the camelCase variant.
// Modernizr.testAllProps('boxSizing')
ModernizrProto.testAllProps = testPropsAll;
/**
* testAllProps determines whether a given CSS property is supported in the browser
*
* @memberof Modernizr
* @name Modernizr.testAllProps
* @optionName Modernizr.testAllProps()
* @optionProp testAllProps
* @access public
* @function testAllProps
* @param {string} prop - String naming the property to test (either camelCase or kebab-case)
* @param {string} [value] - String of the value to test
* @param {boolean} [skipValueTest=false] - Whether to skip testing that the value is supported when using non-native detection
* @example
*
* testAllProps determines whether a given CSS property, in some prefixed form,
* is supported by the browser.
*
* ```js
* testAllProps('boxSizing') // true
* ```
*
* It can optionally be given a CSS value in string form to test if a property
* value is valid
*
* ```js
* testAllProps('display', 'block') // true
* testAllProps('display', 'penguin') // false
* ```
*
* A boolean can be passed as a third parameter to skip the value check when
* native detection (@supports) isn't available.
*
* ```js
* testAllProps('shapeOutside', 'content-box', true);
* ```
*/
function testAllProps(prop, value, skipValueTest) {
return testPropsAll(prop, undefined, undefined, value, skipValueTest);
}
ModernizrProto.testAllProps = testAllProps;
/*!
{
"name": "CSS Animations",
"property": "cssanimations",
"caniuse": "css-animation",
"polyfills": ["transformie", "csssandpaper"],
"tags": ["css"],
"warnings": ["Android < 4 will pass this test, but can only animate a single property at a time"],
"notes": [{
"name" : "Article: 'Dispelling the Android CSS animation myths'",
"href": "https://goo.gl/OGw5Gm"
}]
}
!*/
/* DOC
Detects whether or not elements can be animated using CSS
*/
Modernizr.addTest('cssanimations', testAllProps('animationName', 'a', true));
// Run each test
testRunner();

@ -1,5 +1,13 @@
window.transitionend = 'webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend';
window.on_transitionend = function($element, do_function) {
if (Modernizr.csstransitions) {
$element.on(window.transitionend, do_function);
} else {
do_function(false)
}
};
$(function() {
var $body = $('body');

@ -29,7 +29,7 @@ $(function() {
create_reveal_elements($('html'));
function remove_reveal_animation(event) {
if (event.target === this) {
if (!event || event.target === this) {
$(this).removeClass('reveal_animation');
$(this).off(window.transitionend, remove_reveal_animation);
}
@ -43,7 +43,7 @@ $(function() {
function reveal_element(element) {
window.requestAnimationFrame(function() {
$(element).on(window.transitionend, remove_reveal_animation);
window.on_transitionend($(element), remove_reveal_animation);
$(element).removeClass('reveal');
});
}

@ -55,17 +55,13 @@ $(function() {
$body.on('submit', '.control__item form', function(event) {
event.preventDefault();
var $form = $(this);
$form.addClass('loading');
$.ajax({
type: $form.attr('method'),
url: $form.attr('action'),
data: $form.serialize(),
success: function(data) {
if ($(data).hasClass('control__item__success')) {
var $control_item = $form.parents('.control__item');
$control_item.find('.control__item__close').trigger('click');
} else {
$form.replaceWith(data);
}
$form.replaceWith(data);
}
});
});
@ -76,7 +72,7 @@ $(function() {
window.location = '#form';
}
$task_form.formset();
// $task_form.formset();
$task_form.on('formAdded', function(event) {
var $title = $(event.target).find('h3');
var id = parseInt($title.attr('data-id').match(/\d+/)[0]);
@ -86,4 +82,49 @@ $(function() {
$task_form.on('formDeleted', function(event) {
$(event.target).hide();
});
/* DOWNLOADS */
var download_texts = [];
$('.download__item__title').each(function() {
var text = $(this).text().toLowerCase();
text = text + ' ' + $(this).next().text().toLowerCase();
text = text + ' ' + $(this).next().next().text().toLowerCase();
download_texts.push({
$element: $(this).parents('li'),
text: text
});
});
$body.on('input', '#downloads_search', function(event) {
var query = $(this).val().toLowerCase();
var query_list = $.trim(query).split(' ');
var matches = [];
for (var i = 0; i < download_texts.length; i++) {
var download_text_item = download_texts[i];
var matched = false;
if (!matched) {
for (var ii = 0; ii < query_list.length; ii++) {
var query_item = query_list[ii];
if (download_text_item.text.indexOf(query_item) >= 0) {
matched = true;
matches.push(download_text_item.$element);
}
}
}
}
$('#downloads li').each(function() {
$(this).parents('.downloads__section').css('display', 'none');
$(this).css('display', 'none');
});
for (i = 0; i < matches.length; i++) {
matches[i].removeAttr('style');
matches[i].parents('.downloads__section').removeAttr('style');
}
});
$('#downloads_search').trigger('input');
});

@ -1,47 +0,0 @@
$(function() {
'use strict';
var $body = $('body');
var download_texts = [];
$('.downloads__item__text').each(function() {
var text = $(this).text().toLowerCase();
text = text + '' + $(this).next().text().toLowerCase();
download_texts.push({
$element: $(this).parents('.downloads__item__frame'),
text: text
});
});
$body.on('input', '#downloads_search', function(event) {
var query = $(this).val().toLowerCase();
var query_list = $.trim(query).split(' ');
var matches = [];
for (var i = 0; i < download_texts.length; i++) {
var download_text_item = download_texts[i];
var matched = false;
if (!matched) {
for (var ii = 0; ii < query_list.length; ii++) {
var query_item = query_list[ii];
if (download_text_item.text.indexOf(query_item) >= 0) {
matched = true;
matches.push(download_text_item.$element);
}
}
}
}
$('.downloads__item__frame').each(function() {
$(this).parents('.downloads__section').css('display', 'none');
$(this).css('display', 'none');
});
for (i = 0; i < matches.length; i++) {
matches[i].removeAttr('style');
matches[i].parents('.downloads__section').removeAttr('style');
}
});
$('#downloads_search').trigger('input');
});

@ -0,0 +1,53 @@
var search = window.location.search;
if (search.indexOf('?page=1') === -1 && (search.indexOf('?page=') >= 0 || search.indexOf('&page=') >= 0)) {
document.getElementsByTagName("body")[0].classList.add('hidden');
window.location = window.location.pathname;
}
$(function() {
'use strict';
var $body = $('body');
$body.on('click', '.list__button', function(event) {
event.preventDefault();
var $button = $(this);
var $load_frame = $button.parents('.load__frame');
$button.width($button.width());
window.requestAnimationFrame(function() {
$load_frame.addClass('loading');
$load_frame.height($load_frame.outerHeight());
var load_frame_id = $load_frame.attr('id');
var $load_replace = $button.parents('.load__replace');
$.get($button.attr('href'), function(data) {
var loaded_data = $(data).find('#' + load_frame_id + ' .load__main').html();
$load_frame.addClass('loaded');
window.setTimeout(function() {
$load_replace.replaceWith(loaded_data);
window.on_transitionend($load_frame, function(event) {
if (!event || event.target === this) {
$load_frame.removeAttr('style');
$load_frame.removeClass('loading loaded');
$load_frame.off(window.transitionend)
}
});
$load_frame.height($load_frame.find('.load__main').height());
window.create_reveal_elements($load_frame);
init_auto_load();
}, 200);
});
});
});
function init_auto_load() {
$('.load__replace--auto').each(function() {
var that = this;
var elementWatcher = scrollMonitor.create(that);
elementWatcher.enterViewport(function() {
$(that).find('a').trigger('click');
});
});
}
init_auto_load();
});

@ -13,7 +13,8 @@ $(function() {
var href = $(this).attr('href');
var target = $(this).attr('target');
var is_event = $(this).hasClass('event');
if (href.indexOf('/') === 0 && !target && !is_event && !event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey && !$('html').hasClass('cms-ready')) {
var is_load = $(this).hasClass('button--load');
if (href.indexOf('/') === 0 && !is_load && !target && !is_event && !event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey && !$('html').hasClass('cms-ready')) {
event.preventDefault();
$body.addClass('unload loading');
window.setTimeout(function() {
@ -86,7 +87,7 @@ $(function() {
window.navigation_is_open = true;
$body.removeClass('notification_open');
$navigation.one(window.transitionend, function() {
window.on_transitionend($navigation, function() {
window.requestAnimationFrame(function() {
$navigation.css('position', 'relative');
$navigation.off(window.transitionend);

@ -4,6 +4,7 @@ $light_gray: #F4F4F4;
$medium_light_gray: #E6E6E6;
$gray: #ADADAD;
$dark_gray: #8f8f8f;
$black_gray: #737373;
$near_black: #444444;
$black: #000000;

@ -39,4 +39,12 @@ h2, .h2 {
@media screen and (max-width: $medium_breakpoint) {
font-size: em(30px);
}
}
h3, .h3 {
font-size: em(18px);
color: $dark_gray;
font-weight: 700;
line-height: 1.45;
letter-spacing: 0.01em;
}

@ -13,7 +13,6 @@
@import "modules/_contact.scss";
@import "modules/_content.scss";
@import "modules/_admin_editor.scss";
@import "modules/_downloads.scss";
@import "modules/_control-panel.scss";
@import "modules/plugins/_quote.scss";
@import "modules/plugins/_slider.scss";

@ -7,6 +7,27 @@ $max-width: 100%;
padding-top: em(50px);
}
.content__frame--dialog {
display: table;
width: 100%;
height: 100%;
.content__container {
display: table-cell;
width: 100%;
height: 100%;
vertical-align: middle;
text-align: center;
}
}
.content__dialog {
display: inline-block;
width: 100%;
max-width: em(600px);
padding: em(100px) em(30px);
text-align: left;
}
.content__intro {
width: 100%;
height: 70vh;
@ -17,14 +38,6 @@ $max-width: 100%;
padding: em(50px) 10% 0;
background: $light_gray;
transition: background 0.5s $easeOutQuart;
h1 {
width: 100%;
z-index: 3;
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%) translateY(em(40px));
}
&.reveal {
transform: none;
}
@ -48,8 +61,34 @@ $max-width: 100%;
}
@media screen and (max-width: $medium_breakpoint) {
height: 50vh;
h1 {
transform: translateY(-50%) translateY(em(25px));
}
}
.content__intro__content {
width: 100%;
z-index: 3;
position: absolute;
left: 0;
top: 50%;
text-align: center;
color: $white;
padding: 0 em(30px);
p {
line-height: 1.3;
font-size: em(18px);
margin: em(20px) 0 0;
}
a {
margin: em(40px) em(10px) 0;
}
transform: translateY(-50%) translateY(em(40px));
&.reveal {
transform: translateX(100px) translateY(-50%) translateY(em(40px));
}
@media screen and (max-width: $medium_breakpoint) {
transform: translateY(-50%) translateY(em(25px));
&.reveal {
transform: translateX(100px) translateY(-50%) translateY(em(25px));
}
}
}

@ -1,17 +1,12 @@
.control_panel {
width: 100%;
padding: em(100px) 0;
padding: em(100px) 0 0;
will-change: transform, height;
&.reveal_animation {
transition: background $reveal_duration $reveal_timing_function;
&.reveal {
background: transparent;
}
}
.load__replace {
margin-top: em(40px);
text-align: left;
}
text-align: left;
}
.task__form {
margin-top: em(50px);
}
.control__list {
@ -21,26 +16,27 @@
}
.control_panel__content {
max-width: em(1440px);
margin: 0 auto;
padding: 0 em(80px);
font-size: 0;
@media screen and (max-width: $large_breakpoint) {
padding: 0 em(60px);
}
@media screen and (max-width: $medium_breakpoint) {
max-width: em(600px);
padding: 0 em(30px);
}
}
.control__item {
display: block;
background: $white_gray;
color: $black_gray;
text-decoration: none;
width: 100%;
margin-bottom: em(15px);
position: relative;
line-height: 1.3;
border-bottom: 3px solid $white_gray;
&.loading {
&:before {
top: 50%;
width: em(30px);
height: em(30px);
margin-top: em(-15px);
}
}
}
.control__item__open {
@ -76,10 +72,8 @@
.control__item__title {
display: block;
width: 100%;
padding: em(22px) em(30px);
padding: em(23px) em(30px) em(20px);
position: relative;
font-size: em(18px);
color: $dark_gray;
.control__item--button & {
padding-right: em(240px);
.button {
@ -100,10 +94,10 @@
}
}
.control__item--status & {
padding-left: em(85px);
padding-left: em(80px);
}
.control__item--arrow & {
padding-right: em(85px);
padding-right: em(80px);
&:hover {
.control__item__arrow {
transform: translateX(em(5px));
@ -123,8 +117,10 @@
}
.control__item__content__main {
border-top: 1px solid $gray;
border: 3px solid $white_gray;
border-bottom: 0;
padding: em(30px);
background: $white;
}
.control__item__fields {
@ -135,23 +131,24 @@
display: inline-block;
position: absolute;
top: 50%;
left: em(20px);
margin-top: em(-20px);
border-radius: 50%;
left: em(22px);
width: em(34px);
height: em(34px);
margin-top: em(-16px);
border: 2px solid $gray;
svg {
display: block;
width: em(36px);
height: em(36px);
display: none;
width: 60%;
height: 60%;
margin: 20%;
fill: $white;
}
.control__item--status--active & {
background: $green;
border-color: $green;
}
.control__item--status--expired & {
background: $red;
border-color: $red;
svg {
display: block;
}
}
}
@ -160,36 +157,95 @@
position: absolute;
top: 50%;
right: em(20px);
margin-top: em(-20px);
margin-top: em(-13px);
transform: none;
transition: transform 0.3s $easeOutQuart;
svg {
display: block;
width: em(40px);
height: em(40px);
transform: rotate(-90deg);
}
.fill {
width: em(26px);
height: em(26px);
fill: $green;
}
}
.todo {
.control_panel__content__item {
display: inline-block;
vertical-align: top;
width: 48%;
margin-right: 4%;
font-size: em(18px);
position: relative;
&:first-child {
margin-right: 4%;
}
@media screen and (max-width: $large_breakpoint) {
display: block;
width: 100%;
margin: 0 0 em(40px) 0;
margin: 0 0 em(50px) 0;
}
}
.settings {
display: inline-block;
vertical-align: top;
width: 48%;
.downloads__frame {
width: 100%;
padding: em(150px) 0;
position: relative;
will-change: transform;
.downloads {
li {
width: 33.3333%;
@media screen and (max-width: $large_breakpoint) {
width: 50%;
}
@media screen and (max-width: $medium_breakpoint) {
width: 100%;
}
}
}
@media screen and (max-width: $large_breakpoint) {
width: 100%;
padding-top: 0;
}
}
.downloads__section {
margin-top: em(80px);
.downloads--flat & {
margin-top: 0;
}
}
}
.downloads__section__title {
width: 100%;
overflow: hidden;
h3 {
display: inline-block;
position: relative;
&:after {
content: '';
display: block;
position: absolute;
background: $medium_light_gray;
width: 100vw;
height: em(3px);
top: em(15px);
left: 100%;
margin-left: em(20px);
}
}
}
.downloads__section__title--flat {
h3 {
&:after {
display: none;
}
}
}
.downloads__list {
display: block;
margin: 0 em(-10px);
font-size: 0;
}
.downloads__item__tags {
display: none;
}

@ -1,66 +0,0 @@
.downloads__frame {
width: 100%;
padding: em(80px) 0 em(150px);
position: relative;
will-change: transform;
.downloads {
li {
width: 33.3333%;
}
}
}
.downloads__content {
max-width: em(1440px);
margin: 0 auto;
padding: 0 em(80px);
@media screen and (max-width: $large_breakpoint) {
padding: 0 em(60px);
}
@media screen and (max-width: $medium_breakpoint) {
max-width: em(600px);
padding: 0 em(30px);
}
}
.downloads__section {
margin-top: em(80px);
.downloads--flat & {
margin-top: 0;
}
}
.downloads__section__title {
width: 100%;
overflow: hidden;
h3 {
display: inline-block;
position: relative;
&:after {
content: '';
display: block;
position: absolute;
background: $white;
width: 100vw;
height: em(3px);
opacity: 0.15;
top: em(10.5px);
left: 100%;
margin-left: em(20px);
}
}
}
.downloads__section__title--flat {
h3 {
&:after {
display: none;
}
}
}
.downloads__list {
display: block;
margin: 0 em(-10px);
font-size: 0;
}

@ -57,8 +57,8 @@
@media screen and (min-width: $medium_breakpoint + 1) {
padding: 0 em(30px) !important;
.header__button__icon {
width: em(16px);
height: em(16px);
width: em(12px);
height: em(12px);
top: em(-1px);
margin-right: em(10px);
}

@ -68,7 +68,8 @@
color: $white;
font-weight: 500;
padding: 0 em(5px);
text-shadow: 0 1px 0 $green, 1px 0 0 $green, 0 -1px 0 $green, -1px 0 0 $green;
text-shadow: 1px 0 0 $green, 0 1px 0 $green, -1px 0 0 $green, 0 -1px 0 $green,
2px 0 0 $green, 0 2px 0 $green, -2px 0 0 $green, 0 -2px 0 $green;
&:before, &:after {
display: block;
content: '';

@ -44,6 +44,10 @@
.form__submit {
text-align: right;
.button {
vertical-align: top;
margin-left: em(10px);
}
}
.button {
@ -76,6 +80,31 @@
}
}
.button--small {
height: em(35px);
line-height: em(35px);
font-size: em(14px);
}
.button--ghost {
background: none;
color: $green;
svg {
fill: $green !important;
}
&:after {
content: '';
position: absolute;
z-index: -1;
display: block;
top: 0;
right: 0;
left: 0;
bottom: 0;
border: 2px solid $green;
}
}
.button__icon {
display: block;
position: absolute;
@ -90,6 +119,9 @@
width: em(36px);
fill: $white;
margin: em(12px) 0;
.button--small & {
margin: em(7px) 0;
}
}
}
@ -104,6 +136,78 @@
width: 100%;
display: block;
margin-bottom: em(15px);
position: relative;
}
.form__field--label {
padding-left: 30%;
label {
display: block;
position: absolute;
top: 0;
left: 0;
width: 30%;
line-height: em(40px);
font-weight: 400;
padding-right: em(20px);
font-size: em(12px);
letter-spacing: 0.03em;
text-transform: uppercase;
span {
line-height: 1.3;
display: inline-block;
vertical-align: middle;
}
}
@media screen and (max-width: $small_breakpoint) {
padding: 0;
label {
position: relative;
width: 100%;
padding: 0;
margin-bottom: em(2px);
}
}
}
.form__field--icon {
input {
height: em(70px);
padding: 0 em(90px) 0 em(15px);
}
button, a {
display: block;
-webkit-appearance: none;
position: absolute;
top: 0;
right: 0;
width: em(70px);
height: em(70px);
line-height: em(65px);
border: none;
font-size: 0;
text-align: center;
padding: em(3px);
border-top-right-radius: em(5px);
border-bottom-right-radius: em(5px);
background: transparent;
color: inherit;
cursor: pointer;
svg {
vertical-align: middle;
width: em(36px);
height: em(36px);
display: inline-block;
transform: none;
fill: $green;
transition: transform 0.3s $easeOutQuart;
}
&:hover {
svg {
transform: scale(1.1);
}
}
}
}
input, textarea {
@ -161,7 +265,7 @@ textarea {
.form__success, .form__errors, .form__field__errors {
display: block;
width: 100%;
font-size: em(16px);
font-size: em(14px);
font-weight: 700;
line-height: 1.5;
}

@ -233,6 +233,7 @@
font-weight: 700;
margin-bottom: em(5px);
line-height: 1.3;
color: $white;
}
.slider__text__item__subline {

@ -10,7 +10,6 @@ https://control.divio.com/api/v1/apps/serve/djangocms-picture/2.0.6/005e8663-d1c
https://control.divio.com/api/v1/apps/serve/djangocms-text-ckeditor/3.5.3/a7b5179f-cea5-4af8-b235-6b7f709c4e6a/djangocms-text-ckeditor-3.5.3.tar.gz#egg=djangocms-text-ckeditor==3.5.3
https://control.divio.com/api/v1/apps/serve/django-filer/1.3.0.1/bcb7d25b-6922-48a9-a252-9bc165f6403e/django-filer-1.3.0.1.tar.gz#egg=django-filer==1.3.0.1
# </INSTALLED_ADDONS>
lxml
Whoosh==2.7.4
aldryn-search==0.5.0
django-fontawesome==0.3.1

@ -33,6 +33,9 @@ INSTALLED_APPS.extend([
'image_cropping',
])
LOGIN_REDIRECT_URL = 'memberzone:overview'
MIDDLEWARE_CLASSES.extend([
# add your own middlewares here
])

@ -1,19 +1,11 @@
import xlwt
import json
from aldryn_forms.utils import get_user_model
from django.conf.urls import url
from django.contrib.admin.utils import unquote
from django.http import HttpResponse
from django.utils.text import slugify
from django.contrib import admin
from django.utils.translation import ugettext_lazy as _
from memberzone.models import MemberTask, MemberTaskFormField, MemberTaskRegistration, MemberDownloadFile, \
MemberDownloadTag, Profile, MemberDownloadSection
from parler.admin import TranslatableAdmin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from memberzone.models import Profile, MemberTask, MemberDownloadSection, MemberDownloadTag, MemberDownloadFile
User = get_user_model()
@ -34,86 +26,33 @@ admin.site.unregister(User)
admin.site.register(User, UserAdmin)
class MemberTaskFormFieldInlineAdmin(admin.TabularInline):
model = MemberTaskFormField
extra = 0
prepopulated_fields = {
'name': ('label',)
}
@admin.register(MemberTask)
class MemberTaskAdmin(admin.ModelAdmin):
list_display = ('title', 'publish_date', 'deadline')
class MemberTaskAdmin(TranslatableAdmin):
list_display = ('title', 'published', 'publish_date')
list_filter = ('groups',)
filter_horizontal = ('groups',)
prepopulated_fields = {
'slug': ('title',)
}
inlines = [MemberTaskFormFieldInlineAdmin, ]
def get_urls(self):
info = self.model._meta.app_label, self.model._meta.model_name
return [
url(
r'^(.+)/export/$',
self.admin_site.admin_view(self.participants_export_view),
name='%s_%s_participants_export' % info,
),
] + super(MemberTaskAdmin, self).get_urls()
def participants_export_view(self, request, object_id, *args, **kwargs):
obj = self.get_object(request, unquote(object_id))
wb = xlwt.Workbook()
ws = wb.add_sheet('Teilnehmerliste')
r = 0
c = 0
fields = []
for field in obj.fields.all():
ws.write(r, c, field.label)
fields.append(field.name.replace('-', '_'))
c += 1
for participant in obj.registrations.all():
for data_set in json.loads(participant.form_data):
r += 1
c = 0
for field in fields:
value = data_set.get(field, '')
if isinstance(value, list):
value = ', '.join(value)
ws.write(r, c, value)
c += 1
response = HttpResponse(content_type="application/ms-excel")
response['Content-Disposition'] = 'attachment; filename=%s-teilnehmer.xls' % slugify(obj.title)
wb.save(response)
return response
@admin.register(MemberTaskRegistration)
class MemberTaskRegistrationAdmin(admin.ModelAdmin):
readonly_fields = ['task', 'user', 'form_data', 'cdate']
def has_delete_permission(self, request, obj=None):
return False
def has_add_permission(self, request):
return False
readonly_fields = ('informed_users',)
fieldsets = (
(None, {'fields': ('title', 'published', 'image', 'cropping')}),
(_('Permissions'), {'fields': ('groups',)}),
(_('Veröffentlichung'), {'fields': ('publish_date',)}),
(_('Information'), {'fields': ('informed_users',)}),
)
@admin.register(MemberDownloadSection)
class MemberDownloadSectionAdmin(admin.ModelAdmin):
class MemberDownloadSectionAdmin(TranslatableAdmin):
list_display = ('title', 'ordering')
list_editable = ['ordering']
@admin.register(MemberDownloadTag)
class MemberDownloadTagAdmin(admin.ModelAdmin):
class MemberDownloadTagAdmin(TranslatableAdmin):
pass
@admin.register(MemberDownloadFile)
class MemberDownloadFileAdmin(admin.ModelAdmin):
class MemberDownloadFileAdmin(TranslatableAdmin):
list_display = ('label', 'ordering')
list_editable = ['ordering']
list_filter = ('section', 'groups')

@ -1,8 +1,21 @@
from django import forms
from django.contrib.auth.forms import AuthenticationForm
from memberzone.models import Profile
class LoginForm(AuthenticationForm):
def __init__(self, *args, **kwargs):
super(LoginForm, self).__init__(*args, **kwargs)
for _, value in self.fields.items():
value.widget.attrs['placeholder'] = value.label
class ProfileEditForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['first_name', 'last_name', 'street', 'zip', 'place', 'email']
def __init__(self, *args, **kwargs):
super(ProfileEditForm, self).__init__(*args, **kwargs)
self.fields['zip'].widget = forms.TextInput()

@ -0,0 +1,240 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.11 on 2018-03-22 10:52
from __future__ import unicode_literals
import cms.models.fields
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import image_cropping.fields
import project.utils
class Migration(migrations.Migration):
dependencies = [
('cms', '0018_pagenode'),
('memberzone', '0002_auto_20180321_1256'),
]
operations = [
migrations.CreateModel(
name='MemberDownloadFileTranslation',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('language_code', models.CharField(db_index=True, max_length=15, verbose_name='Language')),
('name', models.CharField(blank=True, max_length=512, null=True, verbose_name='Name')),
('description', models.TextField(blank=True, null=True, verbose_name='Beschreibung')),
('file', models.FileField(max_length=512, upload_to='protected_files')),
],
options={
'db_table': 'memberzone_memberdownloadfile_translation',
'default_permissions': (),
'managed': True,
'db_tablespace': '',
'verbose_name': 'Mitglieder Download Translation',
},
),
migrations.CreateModel(
name='MemberDownloadSectionTranslation',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('language_code', models.CharField(db_index=True, max_length=15, verbose_name='Language')),
('title', models.CharField(max_length=100, verbose_name='Title')),
],
options={
'db_table': 'memberzone_memberdownloadsection_translation',
'default_permissions': (),
'managed': True,
'db_tablespace': '',
'verbose_name': 'Mitglieder Download Section Translation',
},
),
migrations.CreateModel(
name='MemberDownloadTagTranslation',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('language_code', models.CharField(db_index=True, max_length=15, verbose_name='Language')),
('name', models.CharField(max_length=100, verbose_name='Name')),
],
options={
'db_table': 'memberzone_memberdownloadtag_translation',
'default_permissions': (),
'managed': True,
'db_tablespace': '',
'verbose_name': 'Mitglieder Download Tag Translation',
},
),
migrations.CreateModel(
name='MemberTaskTranslation',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('language_code', models.CharField(db_index=True, max_length=15, verbose_name='Language')),
('title', models.CharField(max_length=100, verbose_name='Title')),
],
options={
'db_table': 'memberzone_membertask_translation',
'default_permissions': (),
'managed': True,
'db_tablespace': '',
'verbose_name': 'Mitglieder Aufgabe Translation',
},
),
migrations.AlterUniqueTogether(
name='membertaskformfield',
unique_together=set([]),
),
migrations.RemoveField(
model_name='membertaskformfield',
name='task',
),
migrations.AlterUniqueTogether(
name='membertaskregistration',
unique_together=set([]),
),
migrations.RemoveField(
model_name='membertaskregistration',
name='task',
),
migrations.RemoveField(
model_name='membertaskregistration',
name='user',
),
migrations.AlterModelOptions(
name='memberdownloadfile',
options={'ordering': ['ordering'], 'verbose_name': 'Mitglieder Download', 'verbose_name_plural': 'Mitglieder Downloads'},
),
migrations.RemoveField(
model_name='memberdownloadfile',
name='description',
),
migrations.RemoveField(
model_name='memberdownloadfile',
name='file',
),
migrations.RemoveField(
model_name='memberdownloadfile',
name='name',
),
migrations.RemoveField(
model_name='memberdownloadsection',
name='title',
),
migrations.RemoveField(
model_name='memberdownloadtag',
name='name',
),
migrations.RemoveField(
model_name='membertask',
name='bodytext',
),
migrations.RemoveField(
model_name='membertask',
name='deadline',
),
migrations.RemoveField(
model_name='membertask',
name='folder',
),
migrations.RemoveField(
model_name='membertask',
name='form_bodytext',
),
migrations.RemoveField(
model_name='membertask',
name='max_num',
),
migrations.RemoveField(
model_name='membertask',
name='slug',
),
migrations.RemoveField(
model_name='membertask',
name='sub_title',
),
migrations.RemoveField(
model_name='membertask',
name='submit_text',
),
migrations.RemoveField(
model_name='membertask',
name='success_bodytext',
),
migrations.RemoveField(
model_name='membertask',
name='success_title',
),
migrations.RemoveField(
model_name='membertask',
name='title',
),
migrations.AddField(
model_name='membertask',
name='cropping',
field=image_cropping.fields.ImageRatioField('image', '1200x800', adapt_rotation=False, allow_fullsize=False, free_crop=True, help_text=None, hide_image_field=False, size_warning=False, verbose_name='cropping'),
),
migrations.AddField(
model_name='membertask',
name='placeholder',
field=cms.models.fields.PlaceholderField(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, slotname='task_placeholder', to='cms.Placeholder'),
),
migrations.AlterField(
model_name='membertask',
name='image',
field=project.utils.CroppableFilerImageField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.FILER_IMAGE_MODEL, verbose_name='Bild'),
),
migrations.AlterField(
model_name='profile',
name='first_name',
field=models.CharField(default='', max_length=255, verbose_name='Vorname'),
preserve_default=False,
),
migrations.AlterField(
model_name='profile',
name='last_name',
field=models.CharField(default='', max_length=255, verbose_name='Nachname'),
preserve_default=False,
),
migrations.DeleteModel(
name='MemberTaskFormField',
),
migrations.DeleteModel(
name='MemberTaskRegistration',
),
migrations.AddField(
model_name='membertasktranslation',
name='master',
field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='memberzone.MemberTask'),
),
migrations.AddField(
model_name='memberdownloadtagtranslation',
name='master',
field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='memberzone.MemberDownloadTag'),
),
migrations.AddField(
model_name='memberdownloadsectiontranslation',
name='master',
field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='memberzone.MemberDownloadSection'),
),
migrations.AddField(
model_name='memberdownloadfiletranslation',
name='master',
field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='memberzone.MemberDownloadFile'),
),
migrations.AlterUniqueTogether(
name='membertasktranslation',
unique_together=set([('language_code', 'master')]),
),
migrations.AlterUniqueTogether(
name='memberdownloadtagtranslation',
unique_together=set([('language_code', 'master')]),
),
migrations.AlterUniqueTogether(
name='memberdownloadsectiontranslation',
unique_together=set([('language_code', 'master')]),
),
migrations.AlterUniqueTogether(
name='memberdownloadfiletranslation',
unique_together=set([('language_code', 'master')]),
),
]

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.11 on 2018-03-22 11:21
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('memberzone', '0003_auto_20180322_1052'),
]
operations = [
migrations.AddField(
model_name='membertask',
name='published',
field=models.BooleanField(default=False, verbose_name='Veröffentlichen'),
),
]

@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.11 on 2018-03-22 12:05
from __future__ import unicode_literals
import cms.models.fields
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('memberzone', '0004_membertask_published'),
]
operations = [
migrations.AddField(
model_name='membertask',
name='informed_users',
field=models.ManyToManyField(blank=True, null=True, to=settings.AUTH_USER_MODEL, verbose_name='Als gelesen markiert von:'),
),
migrations.AlterField(
model_name='membertask',
name='placeholder',
field=cms.models.fields.PlaceholderField(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, slotname='content', to='cms.Placeholder'),
),
]

@ -1,18 +1,18 @@
from cms.models.fields import PlaceholderField
import os
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group
from django.core.files.storage import default_storage
from djangocms_text_ckeditor.fields import HTMLField
from django import forms
from django.conf import settings
from django.db import models
from django.urls import reverse_lazy
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from filer.fields.folder import FilerFolderField
from filer.fields.image import FilerImageField
from filer.models import Image as ImageModel
from image_cropping import ImageRatioField
from parler.models import TranslatableModel, TranslatedFields
from memberzone.storage import PrivateS3MediaStorage
from project.utils import CroppableFilerImageField
class Profile(models.Model):
@ -25,149 +25,69 @@ class Profile(models.Model):
email = models.EmailField(verbose_name=_('E-Mail'), null=True, blank=True)
class Meta:
verbose_name = _('User Profil')
verbose_name_plural = _('User Profile')
verbose_name = 'User Profil'
verbose_name_plural = 'User Profile'
def __str__(self):
return self.full_name
@property
def full_name(self):
return '{} {}'.format(self.first_name, self.last_name)
class MemberTask(models.Model):
groups = models.ManyToManyField(Group, verbose_name=_('Mitglieder Gruppe'), related_name='tasks')
title = models.CharField(max_length=100, verbose_name=_('Title'))
slug = models.SlugField(verbose_name=_('slug'), unique=True)
sub_title = models.CharField(max_length=100, verbose_name=_('Untertitle'), blank=True)
bodytext = HTMLField(verbose_name=_('Inhalt'), configuration='simple_ckeditor')
image = FilerImageField(verbose_name=_('Bild'), blank=True, null=True)
folder = FilerFolderField(verbose_name=_('Bilder'), blank=True, null=True)
publish_date = models.DateTimeField(verbose_name=_('Veröffentlichungsdatum'), default=timezone.now)
deadline = models.DateTimeField(verbose_name=_('Anmeldeschluss'), blank=True, null=True)
class MemberTask(TranslatableModel):
groups = models.ManyToManyField(Group, verbose_name='Mitglieder Gruppe', related_name='tasks')
image = CroppableFilerImageField(verbose_name='Bild', blank=True, null=True)
cropping = ImageRatioField('image', '1200x800', free_crop=True)
placeholder = PlaceholderField('content')
published = models.BooleanField(verbose_name='Veröffentlicht', default=False)
publish_date = models.DateTimeField(verbose_name='Veröffentlichungsdatum', default=timezone.now)
max_num = models.IntegerField(verbose_name=_('max. Formulare'), default=1)
submit_text = models.CharField(max_length=100, verbose_name=_('Formular Button Text'),
default=_('Als gelesen markieren'))
form_bodytext = HTMLField(verbose_name=_('Formular Beschreibung'), configuration='simple_ckeditor', blank=True,
default='<h2 class="reveal reveal_animation">Jetzt anmelden</h2>')
informed_users = models.ManyToManyField(get_user_model(), verbose_name='Als gelesen markiert von:',
null=True, blank=True)
success_title = models.CharField(verbose_name=_('Bestätigungstitel'), max_length=200,
default=_('Ihre Anmeldung wurde erfasst'))
success_bodytext = HTMLField(verbose_name=_('Bestätigungstext'), configuration='simple_ckeditor')
translations = TranslatedFields(
title=models.CharField(max_length=100, verbose_name=_('Title')),
)
class Meta:
verbose_name = _('Mitglieder Aufgabe')
verbose_name_plural = _('Mitglieder Aufgaben')
verbose_name = 'Mitglieder Aufgabe'
verbose_name_plural = 'Mitglieder Aufgaben'
ordering = ['-publish_date']
def __str__(self):
return self.title
@property
def images(self):
return [x for x in self.folder.files if isinstance(x, ImageModel)]
def get_absolute_url(self):
return reverse_lazy('memberzone:task', args=[self.slug])
@property
def is_expired(self):
return self.deadline and self.deadline <= timezone.now()
@property
def form_class(self):
fields = self.fields.all()
class MyDynamicForm(forms.Form):
def __init__(self, *args, **kwargs):
super(MyDynamicForm, self).__init__(*args, **kwargs)
for f in fields:
self.fields[f.name.replace('-', '_')] = f.form_field
return MyDynamicForm
class MemberTaskFormField(models.Model):
FIELD_TYPES = [
('text', _('Text Feld (einzeilig)')),
('textarea', _('Text Feld (mehrzeilig)')),
('email', _('E-Mail Feld')),
('radio', _('Auswahlfeld (eine auswahl)')),
('checkbox', _('Auswahlfeld (mehrere auswahlen)')),
]
task = models.ForeignKey(MemberTask, related_name='fields', verbose_name=_('Mitglieder Aufgabe'))
type = models.CharField(max_length=30, choices=FIELD_TYPES)
label = models.CharField(max_length=100, verbose_name=_('Label'))
name = models.SlugField(verbose_name=_('Name'))
choices = models.TextField(verbose_name=_('Auswahlwerte'),
help_text=_(
'Werte die bei einem Auswahlfeld zur verfügung stehen sollen. Ein wert pro Zeile'),
blank=True)
required = models.BooleanField(default=False, verbose_name=_('Pflichtfeld'))
ordering = models.IntegerField(default=50, verbose_name=_('Sortierung'))
class Meta:
verbose_name = _('Formularfeld')
verbose_name_plural = _('Formularfelder')
ordering = ['ordering']
unique_together = ['task', 'name']
def __str__(self):
return self.label
@property
def form_choices(self):
return [(x, x) for x in self.choices.splitlines()]
@property
def form_field(self):
if self.type == 'email':
return forms.EmailField(label=self.label, required=self.required)
elif self.type == 'textarea':
return forms.CharField(label=self.label, required=self.required, widget=forms.Textarea())
elif self.type == 'radio':
return forms.ChoiceField(label=self.label, required=self.required, choices=self.form_choices,
widget=forms.RadioSelect)
elif self.type == 'checkbox':
return forms.MultipleChoiceField(label=self.label, required=self.required, choices=self.form_choices,
widget=forms.CheckboxSelectMultiple)
else:
return forms.CharField(label=self.label, required=self.required)
return reverse_lazy('memberzone:task', args=[self.pk])
class MemberTaskRegistration(models.Model):
task = models.ForeignKey(MemberTask, related_name='registrations', verbose_name=_('Mitglieder Aufgabe'))
user = models.ForeignKey(get_user_model(), related_name='registrations')
form_data = models.TextField(verbose_name=_('Form Content'))
cdate = models.DateTimeField(auto_now_add=True)
class MemberDownloadSection(TranslatableModel):
translations = TranslatedFields(
title=models.CharField(max_length=100, verbose_name='Title')
)
ordering = models.IntegerField(default=50, verbose_name='Sortierung')
class Meta:
verbose_name = _('Mitglieder Aufgabe Registierung')
verbose_name_plural = _('Mitglieder Aufgaben Registierungen')
unique_together = ['user', 'task']
def __str__(self):
return '{} {}'.format(self.user, self.task)
class MemberDownloadSection(models.Model):
title = models.CharField(max_length=100, verbose_name=_('Title'))
ordering = models.IntegerField(default=50, verbose_name=_('Sortierung'))
class Meta:
verbose_name = _('Mitglieder Download Section')
verbose_name_plural = _('Mitglieder Download Sections')
verbose_name = 'Mitglieder Download Section'
verbose_name_plural = 'Mitglieder Download Sections'
ordering = ['ordering']
def __str__(self):
return self.title
class MemberDownloadTag(models.Model):
name = models.CharField(max_length=100, verbose_name=_('Name'))
class MemberDownloadTag(TranslatableModel):
translations = TranslatedFields(
name=models.CharField(max_length=100, verbose_name='Name')
)
class Meta:
verbose_name = _('Mitglieder Download Tag')
verbose_name_plural = _('Mitglieder Download Tags')
verbose_name = 'Mitglieder Download Tag'
verbose_name_plural = 'Mitglieder Download Tags'
def __str__(self):
return self.name
@ -179,22 +99,24 @@ else:
protected_file_storage = default_storage
class MemberDownloadFile(models.Model):
section = models.ForeignKey(MemberDownloadSection, verbose_name=_('Download Section'), related_name='files')
groups = models.ManyToManyField(Group, verbose_name=_('Mitgliedergruppen'), related_name='files')
tags = models.ManyToManyField(MemberDownloadTag, verbose_name=_('Suchbegriffe'), related_name='files', blank=True,
null=True)
class MemberDownloadFile(TranslatableModel):
section = models.ForeignKey(MemberDownloadSection, verbose_name='Download Section', related_name='files')
groups = models.ManyToManyField(Group, verbose_name='Mitgliedergruppen', related_name='files')
tags = models.ManyToManyField(MemberDownloadTag, verbose_name='Suchbegriffe', related_name='files',
blank=True, null=True)
name = models.CharField(max_length=512, verbose_name=_('Name'), blank=True, null=True)
description = models.TextField(verbose_name=_('Beschreibung'), blank=True, null=True)
file = models.FileField(upload_to='protected_files', max_length=512, storage=protected_file_storage)
translations = TranslatedFields(
name=models.CharField(max_length=512, verbose_name='Name', blank=True, null=True),
description=models.TextField(verbose_name='Beschreibung', blank=True, null=True),
file=models.FileField(upload_to='protected_files', max_length=512, storage=protected_file_storage)
)
ordering = models.IntegerField(default=50, verbose_name=_('Sortierung'))
ordering = models.IntegerField(default=50, verbose_name='Sortierung')
class Meta:
verbose_name = _('Mitglieder Download')
verbose_name_plural = _('Mitglieder Downloads')
ordering = ['ordering', 'name']
verbose_name = 'Mitglieder Download'
verbose_name_plural = 'Mitglieder Downloads'
ordering = ['ordering']
def __str__(self):
return self.label
@ -212,8 +134,8 @@ class MemberDownloadFile(models.Model):
if self.name:
return self.name
else:
return self.file.name
return os.path.basename(self.file.name)
@property
def tag_list(self):
return ', '.join(list(self.tags.values_list('name', flat=True)))
return ', '.join(list(self.tags.values_list('translations__name', flat=True)))

@ -0,0 +1,13 @@
{% load i18n %}
<form action="{{ request.path }}" method="post">
{% csrf_token %}
<div class="control__item__fields">
{% for field in form %}
{% include 'project/includes/field.html' with field=field label=True %}
{% endfor %}
</div>
<button class="button button--small">
<span class="button__icon">{% include 'project/assets/tick.svg' %}</span>
<span class="button__text">{% trans 'Speichern' %}</span>
</button>
</form>

@ -1,16 +0,0 @@
{% load i18n %}
<form action="{% url 'memberzone:change_password' %}" method="post">
{% csrf_token %}
<div class="control__item__fields">
{% include 'project/content/includes/_field.html' with field=form.old_password label=True small=True %}
{% include 'project/content/includes/_field.html' with field=form.new_password1 label=True small=True %}
{% include 'project/content/includes/_field.html' with field=form.new_password2 label=True small=True %}
</div>
<button class="button button--small">
<span class="button__wrapper">
{% include 'project/assets/tick.svg' %}
<b>{% trans 'ändern' %}</b>
</span>
{% include 'project/assets/tick.svg' %}
</button>
</form>

@ -1,11 +0,0 @@
{% load i18n %}
<div class="control__item__success">
<span class="tag tag--black">{% trans 'Ihr Passwort wurden erfolgreich geändert' %}</span>
<a href="#" class="button button--small control__item__close">
<span class="button__wrapper">
{% include 'project/assets/close.svg' %}
<b>{% trans 'Schliessen' %}</b>
</span>
{% include 'project/assets/close.svg' %}
</a>
</div>

@ -0,0 +1,8 @@
{% load i18n %}
<div class="control__item__success">
<p>{% trans 'Ihre Informationen wurden erfolgreich angepasst.' %}</p>
<a href="#" class="button button--small control__item__close">
<span class="button__icon">{% include 'project/assets/close.svg' %}</span>
<span class="button__text">{% trans 'Schliessen' %}</span>
</a>
</div>

@ -1,14 +0,0 @@
<html>
<head>{{ subject }}</head>
<body>
<h1>{{ subject }}</h1>
<hr>
{% for data_set in data %}
<ul>
{% for label, value in data_set %}
<li><strong>{{ label }}:</strong> {{ value }}</li>
{% endfor %}
</ul>
{% endfor %}
</body>
</html>

@ -1,57 +0,0 @@
{% load i18n static util_tags thumbnail %}
<div id="downloads" class="downloads__frame reveal_self reveal reveal_animation">
<div class="downloads__content">
{% if title != False %}
<h2 class="{% if not light %}white{% endif %} reveal_self reveal reveal_animation">{% trans title %}</h2>
{% endif %}
{% if search %}
<form class="downloads__filter reveal_self reveal reveal_animation" action="{{ request.path }}#downloads" method="get">
<div class="input__frame input__frame--blue input__frame--icon">
<input name="q" {% if request.GET.q %}value="{{ request.GET.q }}"{% endif %} id="downloads_search"
type="text" placeholder="{% trans 'Suchbegriff eingeben' %}">
<button>{% trans 'Suchen' %}{% include 'project/assets/search.svg' %}</button>
</div>
</form>
{% endif %}
{% for section in download_sections %}
<div class="downloads__section reveal_container">
<div class="downloads__section__title{% if flat %} downloads__section__title--flat{% endif %} reveal reveal_animation">
<h3 class="tag{% if flat %} tag--black{% endif %}{% if not light %} white{% endif %}">{{ section.title }}</h3>
</div>
{% include 'project/plugins/content/download_section.html' with instance=section %}
{# <div class="downloads__list reveal reveal_animation">#}
{# {% for file in files %}#}
{# <div class="downloads__item__frame">#}
{# <a target="_blank" href="{{ file.file.url }}" class="downloads__item">#}
{# <div class="downloads__item__main">#}
{# <div class="downloads__item__content reveal reveal_animation">#}
{# <span class="downloads__item__icon tag">#}
{# {% include 'project/assets/download.svg' %}#}
{# {{ file.file.name|split:'.'|last }}#}
{# </span>#}
{# {% if file.thumbnail %}#}
{# <img class="downloads__item__thumbnail"#}
{# src="{{ file.thumbnail.url }}">#}
{# {% elif file.file.name|split:'.'|last == 'pdf' %}#}
{# <img class="downloads__item__thumbnail"#}
{# src="{% download_thumbnail file %}">#}
{# {% else %}#}
{# {% thumbnail file.file 118x167 crop=True as thumb %}#}
{# {% static 'img/pdf_default.jpg' as static %}#}
{# <img class="downloads__item__thumbnail"#}
{# src="{{ thumb.url|default:static }}">#}
{# {% endif %}#}
{# </div>#}
{# </div>#}
{# <span class="p downloads__item__text">{{ file }}</span>#}
{# <span class="downloads__item__tags">{{ file.tag_list }}</span>#}
{# </a>#}
{# </div>#}
{# {% endfor %}#}
{# </div>#}
</div>
{% endfor %}
</div>
</div>

@ -1,8 +0,0 @@
<div class="input__frame{% if blue %} input__frame--blue{% endif %}{% if label %} input__frame--label{% else %} input__frame--no-label{% endif %}{% if small %} input__frame--small{% endif %}"
{% if hidden %}style="display: none"{% endif %}>
<label for="id_{{ field.name }}" class="p"><span>{{ field.label }}:</span></label>
{{ field }}
{% if field.errors %}
<span class="tag tag--light input__errors">{{ field.errors.0 }}</span>
{% endif %}
</div>

@ -1,160 +1,82 @@
{% extends 'main.html' %}
{% load i18n cms_tags thumbnail %}
{% load i18n static task_tags %}
{% load i18n static %}
{% block title %}{% trans 'Mitgliederbereich' %}{% endblock %}
{% block content %}
<div class="content__frame">
{% include 'project/includes/content_intro.html' %}
<div class="content__intro reveal_container reveal_self reveal reveal_animation image">
<div class="content__intro__content reveal reveal_animation">
<h1>{% trans 'Grüezi, ' %}{{ request.user.profile.full_name }}</h1>
<p>{% trans 'Willkommen in Ihrem persönlichen Portal der Tagesschule Elementa' %}</p>
<a href="{% url 'memberzone:logout' %}" class="button">
<span class="button__icon">{% include 'project/assets/arrow-left-long.svg' %}</span>
<span class="button__text">{% trans 'Logout' %}</span>
</a>
</div>
<div class="content__intro__image scroll reveal reveal_animation" data-ease-multiplier="-2"
style="background-image: url({% static 'img/memberzone_background.jpg' %})"></div>
</div>
<div class="content__container">
<div class="content__main">
<div class="control_panel reveal_self reveal reveal_animation">
<div class="control_panel__content">
<div class="todo">
<div class="control_panel__content__item">
<h2 class="reveal_self reveal reveal_animation">{% trans 'Aktuell' %}</h2>
<div id="todo" class="load__frame">
<div class="load__main">
<ul class="control__list reveal_container">
{% if open_tasks %}
{% for object in open_tasks %}
<li class="data_id_{{ forloop.counter0 }} reveal reveal_animation">
<a href="{{ object.get_absolute_url }}"
class="p control__item control__item--arrow control__item--status {{ object|task_status:request.user }}">
<span class="control__item__title">
<span class="control__item__status">
{% if object.is_expired %}
{% include 'project/assets/close.svg' %}
{% else %}
{% include 'project/assets/tick.svg' %}
{% endif %}
</span>
{{ object.title }}
<span class="control__item__arrow">
{% include 'project/assets/arrow-bottom.svg' %}
</span>
{% for object in object_list %}
<li class="data_id_{{ forloop.counter0 }} reveal reveal_animation">
<a href="{{ object.get_absolute_url }}"
class="p control__item control__item--arrow control__item--status {% if request.user in object.informed_users.all %}control__item--status--active{% endif %}">
<span class="control__item__title">
<span class="control__item__status">
{% if object.is_expired %}
{% include 'project/assets/close.svg' %}
{% else %}
{% include 'project/assets/tick.svg' %}
{% endif %}
</span>
</a>
</li>
{% endfor %}
{% else %}
{% for object in object_list %}
<li class="data_id_{{ forloop.counter0 }} reveal reveal_animation">
<a href="{{ object.get_absolute_url }}"
class="p control__item control__item--arrow control__item--status {{ object|task_status:request.user }}">
<span class="control__item__title">
<span class="control__item__status">
{% if object.is_expired %}
{% include 'project/assets/close.svg' %}
{% else %}
{% include 'project/assets/tick.svg' %}
{% endif %}
</span>
{{ object.title }}
<span class="control__item__arrow">
{% include 'project/assets/arrow-bottom.svg' %}
</span>
{{ object.title }}
<span class="control__item__arrow">
{% include 'project/assets/arrow-right.svg' %}
</span>
</a>
</li>
{% endfor %}
{% endif %}
</span>
</a>
</li>
{% endfor %}
</ul>
{% if page_obj.has_next or open_tasks and paginator.count > 0 %}
{% if page_obj.has_next or paginator.count > 0 and open_object_list %}
<div class="load__replace data_id_3 reveal_self reveal reveal_animation">
<a href="{% url 'memberzone:overview' %}?page=
{% if open_tasks %}{{ page_obj.start_index }}{% else %}{{ page_obj.next_page_number }}{% endif %}"
<a href="{% spaceless %}{% url 'memberzone:overview' %}?page=
{% if open_object_list %}{{ page_obj.start_index }}{% else %}{{ page_obj.next_page_number }}{% endif %}{% endspaceless %}"
class="button button--load list__button button--small">
<span class="button__wrapper">
{% include 'project/assets/dots.svg' %}
<b>{% trans 'Ältere laden' %}</b>
</span>
{% include 'project/assets/dots.svg' %}
<span class="button__icon">{% include 'project/assets/dots.svg' %}</span>
<span class="button__text">{% trans 'Ältere laden' %}</span>
</a>
</div>
{% endif %}
</div>
</div>
</div>
<div class="settings">
<div class="control_panel__content__item">
<h2 class="reveal_self reveal reveal_animation">{% trans 'Einstellungen' %}</h2>
<ul class="control__list reveal_container">
<li class="data_id_0 reveal reveal_animation">
<div class="p control__item control__item--button">
<span class="control__item__title">
{% trans 'Benutzerdaten' %}
<a href="#" data-href="{% url 'memberzone:profile_edit' %}"
class="button button--small button--load control__item__open">
<span class="button__wrapper">
{% include 'project/assets/dots.svg' %}
<b>{% trans 'Bearbeiten' %}</b>
</span>
{% include 'project/assets/dots.svg' %}
</a>
<a href="#" class="button button--small button--ghost control__item__close">
<span class="button__wrapper">
{% include 'project/assets/close.svg' %}
<b>{% trans 'Abbrechen' %}</b>
</span>
{% include 'project/assets/close.svg' %}
</a>
</span>
<div class="control__item__content">
<div class="control__item__content__main">
</div>
</div>
</div>
</li>
<li class="data_id_1 reveal reveal_animation">
<div class="p control__item control__item--button">
<span class="control__item__title">
{% trans 'Passwort' %}
<a href="#" data-href="{% url 'memberzone:change_password' %}"
class="button button--small button--load control__item__open">
<span class="button__wrapper">
{% include 'project/assets/dots.svg' %}
<b>{% trans 'Bearbeiten' %}</b>
</span>
{% include 'project/assets/dots.svg' %}
</a>
<a href="#" class="button button--small button--ghost control__item__close">
<span class="button__wrapper">
{% include 'project/assets/close.svg' %}
<b>{% trans 'Abbrechen' %}</b>
</span>
{% include 'project/assets/close.svg' %}
</a>
</span>
<div class="control__item__content">
<div class="control__item__content__main">
</div>
</div>
</div>
</li>
{% if request.user.company_responsible %}
<li class="data_id_2 reveal reveal_animation">
<div class="p control__item control__item--button">
{% for settings_title, settings_url in settings %}
<li class="reveal reveal_animation data_delay_{{ forloop.counter0 }}">
<div class="control__item control__item--button">
<span class="control__item__title">
{% trans 'Firmendaten' %}
<a href="#" data-href="{% url 'memberzone:company_edit' %}"
class="button button--small button--load control__item__open">
<span class="button__wrapper">
{% include 'project/assets/dots.svg' %}
<b>{% trans 'Bearbeiten' %}</b>
</span>
{% include 'project/assets/dots.svg' %}
{{ settings_title }}
<a href="#" data-href="{{ settings_url }}"
class="button button--small control__item__open">
<span class="button__icon">{% include 'project/assets/dots.svg' %}</span>
<span class="button__text">{% trans 'Ändern' %}</span>
</a>
<a href="#"
class="button button--small button--ghost control__item__close">
<span class="button__wrapper">
{% include 'project/assets/close.svg' %}
<b>{% trans 'Abbrechen' %}</b>
</span>
{% include 'project/assets/close.svg' %}
<span class="button__icon">{% include 'project/assets/close.svg' %}</span>
<span class="button__text">{% trans 'Abbrechen' %}</span>
</a>
</span>
<div class="control__item__content">
@ -163,14 +85,33 @@
</div>
</div>
</li>
{% endif %}
{% endfor %}
</ul>
</div>
</div>
</div>
{% include 'memberzone/includes/_downloads.html' with search=True title='Downloads' %}
<div id="downloads" class="downloads__frame reveal_self reveal reveal_animation">
<h2 class="reveal_self reveal reveal_animation">{% trans 'Downloads' %}</h2>
<form class="downloads__filter reveal_self reveal reveal_animation"
action="{{ request.path }}#downloads" method="get">
<div class="form__field form__field--icon">
<input name="q" {% if request.GET.q %}value="{{ request.GET.q }}"{% endif %}
id="downloads_search"
type="text" placeholder="{% trans 'Suchbegriff eingeben' %}">
<button>{% trans 'Suchen' %}{% include 'project/assets/search.svg' %}</button>
</div>
</form>
{% for section in download_sections %}
<div class="downloads__section reveal_container">
<div class="downloads__section__title{% if flat %} downloads__section__title--flat{% endif %} reveal reveal_animation">
<h3>{{ section.title }}</h3>
</div>
{% include 'project/plugins/content/download_section.html' with instance=section %}
</div>
{% endfor %}
</div>
</div>
</div>
</div>
{% endblock %}

@ -1,17 +0,0 @@
{% load i18n %}
<form action="{% url 'memberzone:profile_edit' %}" method="post">
{% csrf_token %}
<div class="control__item__fields">
{% include 'memberzone/includes/_field.html' with field=form.gender label=True small=True %}
{% include 'memberzone/includes/_field.html' with field=form.title label=True small=True %}
{% include 'memberzone/includes/_field.html' with field=form.first_name label=True small=True %}
{% include 'memberzone/includes/_field.html' with field=form.last_name label=True small=True %}
</div>
<button class="button button--small">
<span class="button__wrapper">
{% include 'project/assets/tick.svg' %}
<b>{% trans 'Speichern' %}</b>
</span>
{% include 'project/assets/tick.svg' %}
</button>
</form>

@ -1,11 +0,0 @@
{% load i18n %}
<div class="control__item__success">
<span class="tag tag--black">{% trans 'Ihre Benutzerdaten wurden erfolgreich geändert' %}</span>
<a href="#" class="button button--small control__item__close">
<span class="button__wrapper">
{% include 'project/assets/close.svg' %}
<b>{% trans 'Schliessen' %}</b>
</span>
{% include 'project/assets/close.svg' %}
</a>
</div>

@ -1,139 +1,44 @@
{% extends 'project/content.html' %}
{% load i18n static thumbnail task_tags %}
https://source.unsplash.com/random/1200x900
{% block body_class %}header-close{% endblock %}
{% block header_menu_url %}{% url 'memberzone:overview' %}{% endblock %}
{% block intro_class %}intro--image{% endblock %}
{% block intro_image %}{% if object.image %}
{% thumbnail object.image "1200x900" crop="center" subject_location=object.image.subject_location %}
{% endif %}{% endblock %}
{% block content_content %}
<div class="text text--full text--narrow reveal_container">
<div class="text__content">
<div class="text__content__frame">
<div class="text__content__main">{{ object.bodytext | add_animation_classes | safe }}</div>
</div>
{% load i18n thumbnail cms_tags %}
{% block title %}{{ object.title }}{% endblock %}
{% block content_intro %}
<div class="content__intro reveal_container reveal_self reveal reveal_animation{% if object.image %} image{% endif %}">
<div class="content__intro__content reveal reveal_animation">
<h1>{{ object.title }}</h1>
<a href="{% url 'memberzone:overview' %}" class="button">
<span class="button__icon">{% include 'project/assets/arrow-left-long.svg' %}</span>
<span class="button__text">{% trans 'Zurück zur Übersicht' %}</span>
</a>
</div>
{% if object.image %}
{% thumbnail object.image 1600x800 box=object.cropping crop detail as thumb %}
<div class="content__intro__image scroll reveal reveal_animation" data-ease-multiplier="-2"
style="background-image: url({{ thumb.url }})"></div>
{% endif %}
</div>
{% include 'project/content/includes/_grid.html' with grid=grid last=True %}
<div id="form"></div>
<div class="text text--full text--narrow reveal_container">
<div class="text__content">
<div class="text__content__frame">
<div class="text__content__main">
{% if formset and not object.is_expired %}
{{ object.form_bodytext | add_animation_classes | safe }}
{% if formset.errors %}
<span class="tag tag--light input__errors reveal reveal_animation">
{% trans 'Bitte korrigieren Sie die markierten Felder.' %}
</span>
{% endif %}
{% if formset.non_form_errors %}
<span class="tag tag--light input__errors reveal reveal_animation">
{{ formset.non_form_errors }}
</span>
{% endif %}
<form action="{% url 'memberzone:task' object.slug %}" method="post"
class="task__form text__content__form reveal reveal_animation {% if formset.errors %}errors{% endif %}"
data-formset-prefix="{{ formset.prefix }}">
{% csrf_token %}
{{ formset.management_form }}
<div data-formset-body>
{% for form in formset %}
<fieldset data-formset-form>
{% if object.max_num > 1 %}
<div class="fieldset__title">
<h3 class="tag" data-id="{{ forloop.counter }}">{{ forloop.counter }}.
Person</h3>
{% if forloop.counter0 > 0 %}
<a class="tag" data-formset-delete-button>
{% include 'project/assets/close.svg' %}
{% trans 'Entfernen' %}
</a>
{% endif %}
</div>
{% endif %}
{% if form.non_field_errors %}
<span class="tag tag--light input__errors">
{{ formset.non_field_errors }}
</span>
{% endif %}
{% for field in form %}
{% if field.name == 'DELETE' %}
{% include 'project/content/includes/_field.html' with field=field label=True hidden=True %}
{% else %}
{% include 'project/content/includes/_field.html' with field=field label=True %}
{% endif %}
{% endfor %}
</fieldset>
{% endfor %}
</div>
<script type="form-template" data-formset-empty-form>
<fieldset data-formset-form>
<div class="fieldset__title">
<h3 class="tag" data-id="{{ formset.empty_form.prefix }}">%(id). Person</h3>
<a class="tag" data-formset-delete-button>
{% include 'project/assets/close.svg' %}
{% trans 'Entfernen' %}
</a>
</div>
{% for field in formset.empty_form %}
{% if field.name == 'DELETE' %}
{% include 'project/content/includes/_field.html' with field=field label=True hidden=True %}
{% else %}
{% include 'project/content/includes/_field.html' with field=field label=True %}
{% endif %}
{% endfor %}
</fieldset>
</script>
<div class="form__controls">
<button class="button">
<span class="button__wrapper">
{% include 'project/assets/arrow-right-long.svg' %}
<b>{{ object.submit_text }}</b>
</span>
{% include 'project/assets/arrow-right-long.svg' %}
</button>
{% if object.max_num > 1 %}
<a class="button button--light" data-formset-add>
<span class="button__wrapper">
{% include 'project/assets/plus.svg' %}
<b>{% trans 'Weitere Person hinzufügen' %}</b>
</span>
</a>
{% endif %}
</div>
</form>
{% else %}
{% if object.is_expired %}
<h3 class="reveal reveal_animation">{% trans 'Die Anmeldungsfrist abgelaufen' %}</h3>
<p class="reveal reveal_animation">
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor
invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et
accusam et
</p>
{% else %}
<h3 class="reveal reveal_animation">{% trans "Bereits abgeschlossen" %}</h3>
<p class="reveal reveal_animation">
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor
invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et
accusam et
</p>
{% endif %}
{% endif %}
</div>
</div>
{% endblock %}
{% block navigation_title %}{{ object.title }}{% endblock %}
{% block content_main %}
{% render_placeholder object.placeholder language LANGUAGE_CODE %}
<form action="{{ request.path }}" method="post" class="task__form reveal_self reveal reveal_animation">
{% csrf_token %}
<div class="form__submit">
<a href="{% url 'memberzone:overview' %}" class="button button--ghost">
<span class="button__icon">{% include 'project/assets/arrow-left-long.svg' %}</span>
<span class="button__text">{% trans 'Zurück zur Übersicht' %}</span>
</a>
{% if not request.user in object.informed_users.all %}
<button class="button">
<span class="button__icon">{% include 'project/assets/tick.svg' %}</span>
<span class="button__text">{% trans 'Als gelesen markieren' %}</span>
</button>
{% endif %}
</div>
</div>
</form>
{% endblock %}

@ -1,20 +0,0 @@
{% extends 'project/dialog.html' %}
{% load i18n static %}
{% block extra_meta %}
<meta name="robots" content="noindex, nofollow">
{% endblock %}
{% block dialog_content %}
<div class="dialog__text reveal_self reveal reveal_animation">
{{ object.success_bodytext | safe }}
<a href="{% url 'memberzone:overview' %}" class="button">
<span class="button__wrapper">
{% include 'project/assets/arrow-right-long.svg' %}
<b>{% trans 'Zur Accountübersicht' %}</b>
</span>
{% include 'project/assets/arrow-right-long.svg' %}
</a>
</div>
{% endblock %}

@ -1,16 +1,36 @@
{% extends 'main.html' %}
{% extends 'project/dialog.html' %}
{% load i18n %}
{% block title %}{% trans 'Mitgliederbereich' %}{% endblock %}
{% block content %}
<div class="content__frame">
<div class="content__container">
<div class="content__main content__main--center">
<form action="" method="post">
{% csrf_token %}
{{ form }}
</form>
</div>
{% block extra_meta %}
<meta name="robots" content="noindex, nofollow"/>
{% endblock %}
{% block dialog %}
<h2 class="reveal_self reveal reveal_animation">{% trans 'Login' %}</h2>
<p class="reveal_self reveal reveal_animation section__text">
Lorem ipsum dolor sit amet, consetetur sadipscing elitr.
</p>
<form class="reveal_self reveal reveal_animation" method="post" action=".">
{% if form.non_field_errors %}
{% for error in form.non_field_errors %}
<p class="form__errors reveal_self reveal reveal_animation">{{ error }}</p>
{% endfor %}
{% endif %}
{% csrf_token %}
{% for field in form %}
{% include 'project/includes/field.html' with field=field %}
{% endfor %}
<div class="form__submit reveal_self reveal reveal_animation">
<button type="submit" class="button">
<span class="button__icon">{% include 'project/assets/arrow-right-long.svg' %}</span>
<span class="button__text">{% trans 'Login' %}</span>
</button>
</div>
</div>
</form>
{% endblock %}

@ -1,34 +0,0 @@
import lxml.html
from django import template
from django.template.defaultfilters import stringfilter
from memberzone.models import MemberTaskRegistration
register = template.Library()
@register.filter(name='task_status')
def task_user_status(task, user):
try:
MemberTaskRegistration.objects.get(task=task, user=user)
except MemberTaskRegistration.DoesNotExist:
if task.is_expired:
return 'control__item--status--expired'
else:
return ''
else:
return 'control__item--status--active'
@register.filter
@stringfilter
def add_animation_classes(input_html):
document = lxml.html.fromstring('<div>{}</div>'.format(input_html))
for el in document.xpath('//p|ul|ol|h2|h3'):
classes = el.attrib.get('class', '').split(' ')
if 'reveal' not in classes:
classes.append('reveal')
if 'reveal_animation' not in classes:
classes.append('reveal_animation')
el.attrib['class'] = ' '.join(classes)
return lxml.html.tostring(document)[5:-6]

@ -10,35 +10,29 @@ from memberzone.forms import LoginForm
from memberzone.views import OverviewView, MemberTaskDetailView, MemberTaskDetailSuccessView, ProfileEditView
urlpatterns = [
url(_(r'^login/$'), LoginView.as_view(
success_url=reverse_lazy('memberzone:overview'),
form_class=LoginForm
), name='login'),
url(_(r'^logout/$'), LogoutView.as_view(next_page='login'), name='logout'),
url(_(r'^login/$'), LoginView.as_view(form_class=LoginForm), name='login'),
url(_(r'^logout/$'), LogoutView.as_view(next_page=reverse_lazy('memberzone:overview')), name='logout'),
url(_(r'^account/change/password/$'), login_required(PasswordChangeView.as_view(
template_name='memberzone/change_password.html',
template_name='memberzone/change_form.html',
success_url=reverse_lazy('memberzone:change_password_done')
), login_url=reverse_lazy('memberzone:login')), name='change_password'),
url(_(r'^account/change/password/succeeded/$'), login_required(TemplateView.as_view(
template_name='memberzone/change_password_done.html'
url(_(r'^account/change/password/success/$'), login_required(TemplateView.as_view(
template_name='memberzone/change_success.html'
), login_url=reverse_lazy('memberzone:login')), name='change_password_done'),
url(_(r'^account/edit/$'), login_required(ProfileEditView.as_view(
url(_(r'^profile/edit/$'), login_required(ProfileEditView.as_view(
), login_url=reverse_lazy('memberzone:login')), name='profile_edit'),
url(_(r'^account/edit/succeeded/$'), login_required(TemplateView.as_view(
template_name='memberzone/profile_edit_done.html'
url(_(r'^profile/edit/success/$'), login_required(TemplateView.as_view(
template_name='memberzone/change_success.html'
), login_url=reverse_lazy('memberzone:login')), name='profile_edit_done'),
url(_(r'^task/(?P<slug>[\w-]+)/$'), login_required(MemberTaskDetailView.as_view(
url(_(r'^task/(?P<pk>\d+)/$'), login_required(MemberTaskDetailView.as_view(
), login_url=reverse_lazy('memberzone:login')), name='task'),
url(_(r'^task/(?P<slug>[\w-]+)/success/$'),
login_required(MemberTaskDetailSuccessView.as_view(), login_url=reverse_lazy('memberzone:login')),
name='task_success'),
url(_(r'^overview/$'), login_required(OverviewView.as_view(), login_url=reverse_lazy('memberzone:login')),
name='overview'),
]

@ -1,36 +1,26 @@
import json
from django.conf import settings
from django.contrib.auth.forms import SetPasswordForm
from django.contrib.auth.tokens import default_token_generator
from django.contrib.auth.views import LoginView as DjangoLoginView
from django.contrib.sites.shortcuts import get_current_site
from django.core.mail import EmailMessage
from django.db.models import Q
from django.forms import formset_factory
from django.http import HttpResponseRedirect
from django.shortcuts import resolve_url
from django.template.loader import render_to_string
from django.urls import reverse, reverse_lazy
from django.shortcuts import redirect
from django.urls import reverse_lazy
from django.utils import timezone
from django.utils.encoding import force_bytes, force_text
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.utils.translation import ugettext_lazy as _
from django.views.generic import UpdateView, ListView, DetailView, FormView
from django.views.generic import UpdateView, ListView, DetailView
from memberzone.models import MemberTask, MemberTaskRegistration, MemberDownloadFile, Profile
from memberzone.forms import ProfileEditForm
from memberzone.models import MemberTask, MemberDownloadFile
class MemeberTaskQuerysetMixin(object):
def get_queryset(self):
return MemberTask.objects.filter(groups__in=self.request.user.groups.all()).distinct()
queryset = MemberTask.objects.filter(groups__in=self.request.user.groups.all())
if not self.request.user.is_superuser:
queryset = queryset.filter(published=True)
return queryset
class OverviewView(MemeberTaskQuerysetMixin, ListView):
template_name = 'memberzone/overview.html'
open_tasks = None
paginate_by = 3
paginate_by = 5
def get_title(self):
return _('Grüezi, {first_name} {last_name}').format(
@ -50,106 +40,46 @@ class OverviewView(MemeberTaskQuerysetMixin, ListView):
sections[file.section_id]['items'].append(file)
sections_list = [{'title': x['section'].title, 'items': x['items'], 'ordering': x['section'].ordering} for x in
sections.values()]
sections.values()]
return sorted(sections_list, key=lambda x: x['ordering'])
def get_queryset(self):
queryset = super(OverviewView, self).get_queryset()
return queryset.exclude(pk__in=self.get_open_tasks().values_list('pk', flat=True))
return queryset.filter(informed_users__in=[self.request.user])
def get_open_tasks(self):
yesterday = timezone.now() - timezone.timedelta(days=1)
all_user_registrations = MemberTaskRegistration.objects.filter(user=self.request.user, cdate__lte=yesterday)
queryset = MemeberTaskQuerysetMixin.get_queryset(self)
queryset.exclude(registrations__in=all_user_registrations).order_by('-registrations__cdate')
queryset = MemeberTaskQuerysetMixin.get_queryset(self).exclude(informed_users__in=[self.request.user])
return queryset
def get_settings(self):
settings = (
(_('Benutzerdaten'), reverse_lazy('memberzone:profile_edit')),
(_('Passwort'), reverse_lazy('memberzone:change_password')),
)
return settings
def get_context_data(self, **kwargs):
context = super(OverviewView, self).get_context_data(**kwargs)
context.update({
'download_sections': self.get_download_sections(),
'open_tasks': None if self.request.GET.get(self.page_kwarg, None) else self.get_open_tasks(),
'settings': self.get_settings()
})
self.open_tasks = self.get_open_tasks()
if not self.request.GET.get(self.page_kwarg, None) and self.open_tasks.count() > 0:
context.update({
'object_list': self.open_tasks,
'open_object_list': True
})
return context
class MemberTaskDetailView(MemeberTaskQuerysetMixin, DetailView):
template_name = 'memberzone/task.html'
model = MemberTask
def get_title(self):
return self.object.title
def get_description(self):
return self.object.sub_title
def get_formset(self):
try:
MemberTaskRegistration.objects.get(task=self.object, user=self.request.user)
except MemberTaskRegistration.DoesNotExist:
MemeberTaskFormset = formset_factory(
self.object.form_class,
extra=0,
min_num=1,
max_num=self.object.max_num,
can_delete=True
)
formset_kwargs = {}
if self.request.method == 'POST':
formset_kwargs.update({
'data': self.request.POST
})
return MemeberTaskFormset(**formset_kwargs)
else:
return None
def formset_valid(self, formset):
registration = MemberTaskRegistration.objects.create(
task=self.object,
user=self.request.user,
form_data=json.dumps(formset.cleaned_data)
)
if registration.task.fields.count() > 0:
self.send_confirmation_email(registration=registration)
return HttpResponseRedirect(reverse('memberzone:task_success', args=[self.object.slug]))
def formset_invalid(self, formset):
return self.render_to_response(context=self.get_context_data(formset=formset, object=self.object))
def get(self, request, *args, **kwargs):
self.object = self.get_object()
formset = self.get_formset()
return self.render_to_response(context=self.get_context_data(formset=formset, object=self.object))
def send_confirmation_email(self, registration):
subject = _('Anmeldebestätigung: {}').format(registration.task.title)
confirmation_data = []
for data_set in json.loads(registration.form_data):
confirmation_data_set = []
for field in registration.task.fields.all():
value = data_set.get(field.name.replace('-', '_'), '')
if isinstance(value, list):
value = ','.join(value)
confirmation_data_set.append((field.label, value,))
confirmation_data.append(confirmation_data_set)
message = render_to_string('memberzone/email/member_registration_confirmation_email.html', {
'data': confirmation_data,
'subject': subject,
})
msg = EmailMessage(subject, message, settings.DEFAULT_FROM_EMAIL, to=[registration.user.email])
msg.content_subtype = "html"
# msg.send()
def post(self, request, *args, **kwargs):
self.object = self.get_object()
formset = self.get_formset()
if formset.is_valid():
return self.formset_valid(formset)
else:
return self.formset_invalid(formset)
self.get_object().informed_users.add(self.request.user)
return redirect('memberzone:overview')
class MemberTaskDetailSuccessView(MemeberTaskQuerysetMixin, DetailView):
@ -161,9 +91,8 @@ class MemberTaskDetailSuccessView(MemeberTaskQuerysetMixin, DetailView):
class ProfileEditView(UpdateView):
model = Profile
fields = ['first_name', 'last_name', 'street', 'zip', 'place', 'email']
template_name = 'memberzone/profile_edit.html'
form_class = ProfileEditForm
template_name = 'memberzone/change_form.html'
success_url = reverse_lazy('memberzone:profile_edit_done')
def get_object(self, queryset=None):

@ -79,36 +79,38 @@
{% endfor %}
</ul>
{% if notification %}
<a href="#" class="header__button header__button--notification data_id_1">
{% trans 'Aktuell' %}
<span class="header__button__icon">
{% include 'project/assets/bell.svg' %}
</span>
</a>
{% endif %}
<a href="#" class="header__button header__button--search data_id_2">
{% trans 'Suche' %}
<span class="header__button__icon">
{% include 'project/assets/search.svg' %}
</span>
</a>
{% block header_items %}
{% if notification %}
<a href="#" class="header__button header__button--notification data_id_1">
{% trans 'Aktuell' %}
<span class="header__button__icon">
{% include 'project/assets/bell.svg' %}
</span>
</a>
{% endif %}
{% url 'search' as search_url %}
{% with request.get_full_path as current_url %}
<a href="{% if search_url in current_url %}/{{ LANGUAGE_CODE }}/{% else %}{{ current_url }}{% endif %}"
class="event header__button header__button--navigation data_id_3">
{% trans 'Menü' %}
<a href="#" class="header__button header__button--search data_id_2">
{% trans 'Suche' %}
<span class="header__button__icon">
{% include 'project/assets/menu.svg' %}
{% include 'project/assets/search.svg' %}
</span>
</a>
{% endwith %}
<div class="header__navigation">
{% include 'project/includes/meta_navigation.html' %}
</div>
{% url 'search' as search_url %}
{% with request.get_full_path as current_url %}
<a href="{% if search_url in current_url %}/{{ LANGUAGE_CODE }}/{% else %}{{ current_url }}{% endif %}"
class="event header__button header__button--navigation data_id_3">
{% trans 'Menü' %}
<span class="header__button__icon">
{% include 'project/assets/menu.svg' %}
</span>
</a>
{% endwith %}
<div class="header__navigation">
{% include 'project/includes/meta_navigation.html' %}
</div>
{% endblock %}
</div>
<div id="canvas">

@ -1,4 +0,0 @@
<svg width="35px" height="35px" viewBox="0 0 35 35" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M31.4366634,9.44202305 C32.0209679,8.85475847 32.9707124,8.85235889 33.557977,9.43666344 C34.1452415,10.020968 34.1476411,10.9707124 33.5633366,11.557977 L18.6389421,26.557977 C18.0546323,27.1452468 17.1048775,27.1476404 16.517615,26.5633231 L1.44200954,11.5633232 C0.85475238,10.9790112 0.852364866,10.0292667 1.43667688,9.44200954 C2.02098889,8.85475238 2.97073336,8.85236487 3.55799051,9.43667688 L17.5702593,23.3786729 L31.4366634,9.44202305 Z"></path>
</svg>

Before

Width:  |  Height:  |  Size: 626 B

@ -0,0 +1,5 @@
<svg width="50px" height="35px" viewBox="0 0 50 35" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<polygon
points="7.0332611 16 48.75 16 48.75 19 6.95202028 19 20.3913601 32.4393398 18.2700398 34.5606602 1.25 17.5406204 18.3512806 0.439339828 20.4726009 2.56066017"></polygon>
</svg>

After

Width:  |  Height:  |  Size: 351 B

@ -1,4 +1,5 @@
<svg width="35px" height="35px" viewBox="0 0 35 35" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M26.557977,31.4366634 C27.1452415,32.0209679 27.1476411,32.9707124 26.5633366,33.557977 C25.979032,34.1452415 25.0292876,34.1476411 24.442023,33.5633366 L9.44202305,18.6389421 C8.85475319,18.0546323 8.85235962,17.1048775 9.43667688,16.517615 L24.4366768,1.44200954 C25.0209888,0.85475238 25.9707333,0.852364866 26.5579905,1.43667688 C27.1452476,2.02098889 27.1476351,2.97073336 26.5633231,3.55799051 L12.6213271,17.5702593 L26.557977,31.4366634 Z"></path>
<polygon
points="12.1313402 17.5406204 27.0300596 32.4393398 24.9087393 34.5606602 7.88869954 17.5406204 24.9899801 0.439339828 27.1113005 2.56066017"></polygon>
</svg>

Before

Width:  |  Height:  |  Size: 625 B

After

Width:  |  Height:  |  Size: 334 B

@ -1,6 +1,5 @@
<svg width="50px" height="35px" viewBox="0 0 50 35" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M32.442023,3.56333662 C31.8547585,2.97903206 31.8523589,2.02928763 32.4366634,1.44202305 C33.020968,0.854758464 33.9707124,0.852358886 34.557977,1.43666344 L49.557977,16.3610579 C50.1452468,16.9453677 50.1476404,17.8951225 49.5633231,18.482385 L34.5633232,33.5579905 C33.9790112,34.1452476 33.0292667,34.1476351 32.4420095,33.5633231 C31.8547524,32.9790111 31.8523649,32.0292666 32.4366769,31.4420095 L46.3786729,17.4297407 L32.442023,3.56333662 Z"
id="arrow" fill-rule="nonzero"></path>
<rect id="line" x="0" y="16" width="48" height="3" rx="1.5"></rect>
<polygon
points="42.9680397 16 29.5286999 2.56066017 31.6500202 0.439339828 48.7513008 17.5406204 31.731261 34.5606602 29.6099407 32.4393398 43.0492805 19 1.24869919 19 1.24869919 16"></polygon>
</svg>

Before

Width:  |  Height:  |  Size: 739 B

After

Width:  |  Height:  |  Size: 367 B

@ -1,4 +1,5 @@
<svg width="35px" height="35px" viewBox="0 0 35 35" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M9.44202305,3.56333662 C8.85475847,2.97903206 8.85235889,2.02928763 9.43666344,1.44202305 C10.020968,0.854758465 10.9707124,0.852358887 11.557977,1.43666344 L26.557977,16.3610579 C27.1452468,16.9453677 27.1476404,17.8951225 26.5633231,18.482385 L11.5633232,33.5579905 C10.9790112,34.1452476 10.0292667,34.1476351 9.44200954,33.5633231 C8.85475238,32.9790111 8.85236487,32.0292666 9.43667688,31.4420095 L23.3786729,17.4297407 L9.44202305,3.56333662 Z"></path>
<polygon
points="22.8686598 17.5406204 7.88869954 2.56066017 10.0100199 0.439339828 27.1113005 17.5406204 10.0912607 34.5606602 7.96994036 32.4393398"></polygon>
</svg>

Before

Width:  |  Height:  |  Size: 628 B

After

Width:  |  Height:  |  Size: 334 B

@ -1,7 +1,5 @@
<svg width="35px" height="35px" viewBox="0 0 35 35" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M8.80761184,6.1862915 L29.3137085,26.6923882 C29.8994949,27.2781746 29.8994949,28.2279221 29.3137085,28.8137085 C28.7279221,29.3994949 27.7781746,29.3994949 27.1923882,28.8137085 L6.6862915,8.30761184 C6.10050506,7.72182541 6.10050506,6.77207794 6.6862915,6.1862915 C7.27207794,5.60050506 8.22182541,5.60050506 8.80761184,6.1862915 Z"
class="line-left"></path>
<path d="M6.6862915,26.6923882 L27.1923882,6.1862915 C27.7781746,5.60050506 28.7279221,5.60050506 29.3137085,6.1862915 C29.8994949,6.77207794 29.8994949,7.72182541 29.3137085,8.30761184 L8.80761184,28.8137085 C8.22182541,29.3994949 7.27207794,29.3994949 6.6862915,28.8137085 C6.10050506,28.2279221 6.10050506,27.2781746 6.6862915,26.6923882 Z"
class="line-right"></path>
<polygon
points="17.5 15.3786797 27.6621477 5.21653197 29.783468 7.33785231 19.6213203 17.5 29.783468 27.6621477 27.6621477 29.783468 17.5 19.6213203 7.33785231 29.783468 5.21653197 27.6621477 15.3786797 17.5 5.21653197 7.33785231 7.33785231 5.21653197"></polygon>
</svg>

Before

Width:  |  Height:  |  Size: 925 B

After

Width:  |  Height:  |  Size: 437 B

@ -1,6 +1,4 @@
<svg width="35px" height="35px" viewBox="0 0 35 35" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<circle class="left" cx="7.5" cy="17.5" r="2"></circle>
<circle class="middle" cx="17.5" cy="17.5" r="2"></circle>
<circle class="right" cx="27.5" cy="17.5" r="2"></circle>
<path d="M3.5,20.3 C1.9536027,20.3 0.7,19.0463973 0.7,17.5 C0.7,15.9536027 1.9536027,14.7 3.5,14.7 C5.0463973,14.7 6.3,15.9536027 6.3,17.5 C6.3,19.0463973 5.0463973,20.3 3.5,20.3 Z M17.5,20.3 C15.9536027,20.3 14.7,19.0463973 14.7,17.5 C14.7,15.9536027 15.9536027,14.7 17.5,14.7 C19.0463973,14.7 20.3,15.9536027 20.3,17.5 C20.3,19.0463973 19.0463973,20.3 17.5,20.3 Z M31.5,20.3 C29.9536027,20.3 28.7,19.0463973 28.7,17.5 C28.7,15.9536027 29.9536027,14.7 31.5,14.7 C33.0463973,14.7 34.3,15.9536027 34.3,17.5 C34.3,19.0463973 33.0463973,20.3 31.5,20.3 Z"></path>
</svg>

Before

Width:  |  Height:  |  Size: 341 B

After

Width:  |  Height:  |  Size: 720 B

@ -1,4 +1,4 @@
<svg width="35px" height="35px" viewBox="0 0 35 35" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M15.9996412,16.8783208 L15.9996412,7.5 C15.9996412,6.67157288 16.671214,6 17.4996412,6 C18.3280683,6 18.9996412,6.67157288 18.9996412,7.5 L18.9996412,16.8790385 L21.4393398,14.4393398 C22.0251263,13.8535534 22.9748737,13.8535534 23.5606602,14.4393398 C24.1464466,15.0251263 24.1464466,15.9748737 23.5606602,16.5606602 L18.5606602,21.5606602 C17.9748737,22.1464466 17.0251263,22.1464466 16.4393398,21.5606602 L11.4393398,16.5606602 C10.8535534,15.9748737 10.8535534,15.0251263 11.4393398,14.4393398 C12.0251263,13.8535534 12.9748737,13.8535534 13.5606602,14.4393398 L15.9996412,16.8783208 Z M10.5,28 C9.67157288,28 9,27.3284271 9,26.5 C9,25.6715729 9.67157288,25 10.5,25 L24.5,25 C25.3284271,25 26,25.6715729 26,26.5 C26,27.3284271 25.3284271,28 24.5,28 L10.5,28 Z"></path>
<path d="M23.9705882,15.6149321 L17.5001879,22.8529412 L11.0294118,15.614659 L12.6140297,14.13906 L16.4261014,18.4006328 L16.4261014,6.38235294 L18.5738986,6.38235294 L18.5738986,18.4284934 L22.3859703,14.1393332 L23.9705882,15.6149321 Z M7.5,28.6176471 L7.5,26.2647059 L27.5,26.2647059 L27.5,28.6176471 L7.5,28.6176471 Z"></path>
</svg>

Before

Width:  |  Height:  |  Size: 942 B

After

Width:  |  Height:  |  Size: 491 B

@ -1,4 +1,4 @@
<svg width="35px" height="35px" viewBox="0 0 35 35" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M6.12132034,9 L17.5,20.3786797 L28.8786797,9 L6.12132034,9 Z M31,11.1213203 L18.5606602,23.5606602 C17.9748737,24.1464466 17.0251263,24.1464466 16.4393398,23.5606602 L4,11.1213203 L4,26 L31,26 L31,11.1213203 Z M2.5,6 L32.5,6 C33.3284271,6 34,6.67157288 34,7.5 L34,27.5 C34,28.3284271 33.3284271,29 32.5,29 L2.5,29 C1.67157288,29 1,28.3284271 1,27.5 L1,7.5 C1,6.67157288 1.67157288,6 2.5,6 Z"></path>
<path d="M3.03045763,9 L3,9 L3,26 L32,26 L32,9 L31.9695424,9 L17.5,23.3241161 L3.03045763,9 Z M0,6 L35,6 L35,29 L0,29 L0,6 Z M27.7053105,9 L7.29468951,9 L17.5,19.102742 L27.7053105,9 Z"></path>
</svg>

Before

Width:  |  Height:  |  Size: 569 B

After

Width:  |  Height:  |  Size: 354 B

@ -1,6 +1,6 @@
<svg width="35px" height="35px" viewBox="0 0 35 35" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<rect class="line-top" x="3" y="6" width="29" height="3" rx="1.5"></rect>
<rect class="line-middle" x="3" y="16" width="29" height="3" rx="1.5"></rect>
<rect class="line-bottom" x="3" y="26" width="29" height="3" rx="1.5"></rect>
<rect class="line-top" x="3" y="6" width="29" height="3"></rect>
<rect class="line-middle" x="3" y="16" width="29" height="3"></rect>
<rect class="line-bottom" x="3" y="26" width="29" height="3"></rect>
</svg>

Before

Width:  |  Height:  |  Size: 398 B

After

Width:  |  Height:  |  Size: 371 B

@ -1,4 +1,4 @@
<svg width="35px" height="35px" viewBox="0 0 35 35" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M9,30.6571365 L31.5466546,17.5217649 L9,4.38624411 L9,30.6571365 Z M8.06559183,3.82372129 C8.11385613,3.86213396 8.16060259,3.89389381 8.20583948,3.91964378 L8.06559183,3.82372129 Z M8.4983486,31.0038586 C8.46934226,31.0038586 8.4665067,31.0040799 8.49521517,31.0097894 C8.51358323,31.0044274 8.51354824,31.0038586 8.4983486,31.0038586 Z M9.82181934,1.39303795 L33.7559217,15.3368759 L33.9349236,15.4593044 C34.5868249,15.9781407 35,16.6468541 35,17.5216878 C35,18.4257399 34.5132392,19.2516282 33.7559217,19.7064998 L9.82726706,33.6443539 C9.66667195,33.7505899 9.49940323,33.8345151 9.31683935,33.8949975 C9.0236245,33.992138 8.86416284,34.0038586 8.4983486,34.0038586 C8.24745197,34.0038586 8.14898904,33.9995939 7.95603549,33.9612019 C7.73137005,33.9165001 7.55145108,33.8463643 7.32902093,33.7352886 L7.18821849,33.6649755 L7.06507641,33.566969 C6.41317513,33.0481327 6,32.3794194 6,31.5045856 L6,3.53879008 C6,2.63473804 6.4867608,1.80884967 7.22662515,1.3643049 C7.99391167,0.903283625 9.03327302,0.844492269 9.82181934,1.39303795 Z"></path>
<path d="M5.21268739,34.0493335 L5.21268739,0.950666475 L35,17.5 L5.21268739,34.0493335 Z M28.8228577,17.5 L8.21268739,6.04933352 L8.21268739,28.9506665 L28.8228577,17.5 Z"></path>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 341 B

@ -3,5 +3,5 @@
<path d="M15,22 C18.8659932,22 22,18.8659932 22,15 C22,11.1340068 18.8659932,8 15,8 C11.1340068,8 8,11.1340068 8,15 C8,18.8659932 11.1340068,22 15,22 Z M15,25 C9.4771525,25 5,20.5228475 5,15 C5,9.4771525 9.4771525,5 15,5 C20.5228475,5 25,9.4771525 25,15 C25,20.5228475 20.5228475,25 15,25 Z"
class="circle" fill-rule="nonzero"></path>
<rect class="line" transform="translate(25.303301, 25.303301) rotate(45.000000) translate(-25.303301, -25.303301) "
x="19.3033009" y="23.8033009" width="12" height="3" rx="1.5"></rect>
x="19.3033009" y="23.8033009" width="12" height="3"></rect>
</svg>

Before

Width:  |  Height:  |  Size: 704 B

After

Width:  |  Height:  |  Size: 695 B

@ -1,4 +1,5 @@
<svg width="50px" height="50px" viewBox="0 0 50 50" version="1.1" xmlns="http://www.w3.org/2000/svg"
<svg width="35px" height="35px" viewBox="0 0 35 35" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M35.3991009,16.5843195 C35.9048173,16.1143809 36.6957419,16.1433845 37.1656805,16.6491009 C37.6356191,17.1548173 37.6066155,17.9457419 37.1008991,18.4156805 L20.9589061,33.4156805 C20.4523976,33.8863552 19.659996,33.8564187 19.1904442,33.348869 L12.8324372,26.4763471 C12.3636198,25.9695911 12.3943751,25.1787327 12.901131,24.7099153 C13.407887,24.2410979 14.1987454,24.2718532 14.6675628,24.7786091 L20.1748187,30.7315338 L35.3991009,16.5843195 Z"></path>
<polygon
points="10.6706826 25.357247 32.4535139 5.11547945 34.6318156 7.45962147 10.4996447 29.8845205 0.3681844 18.9331827 2.71714513 16.7600781"></polygon>
</svg>

Before

Width:  |  Height:  |  Size: 626 B

After

Width:  |  Height:  |  Size: 331 B

@ -4,14 +4,14 @@
{% block content %}
<div class="content__frame">
{% block content_intro %}
{% include 'project/includes/content_intro.html' %}
{% include 'project/includes/content_intro.html' with image=request.current_page.imageextension.image cropping=request.current_page.imageextension.cropping %}
{% endblock %}
<div class="content__container">
<div class="content__navigation reveal_self reveal reveal_animation data_delay_3">
<div class="content__navigation__frame">
<div class="content__navigation__main">
<span class="content__navigation__title">
{{ request.current_page }}
{% block navigation_title %}{{ request.current_page }}{% endblock %}
</span>
<div class="content__navigation__content">
<div class="content__navigation__progress">

@ -0,0 +1,14 @@
{% extends 'main.html' %}
{% load i18n %}
{% block content %}
<div class="content__frame content__frame--dialog">
<div class="content__container">
<div class="content__dialog">
{% block dialog %}
{% endblock %}
</div>
</div>
</div>
{% endblock %}

@ -1,15 +1,17 @@
{% load i18n cms_tags thumbnail %}
<div class="content__intro reveal_container reveal_self reveal reveal_animation{% if request.current_page.imageextension.image %} image{% endif %}">
<h1 class="reveal reveal_animation">
{% if content_title %}
{{ content_title }}
{% else %}
{% page_attribute page_title %}
{% endif %}
</h1>
{% if request.current_page.imageextension.image %}
{% thumbnail request.current_page.imageextension.image 1600x800 box=request.current_page.imageextension.cropping crop detail as thumb %}
<div class="content__intro reveal_container reveal_self reveal reveal_animation{% if image %} image{% endif %}">
<div class="content__intro__content reveal reveal_animation">
<h1>
{% if content_title %}
{{ content_title }}
{% else %}
{% page_attribute page_title %}
{% endif %}
</h1>
</div>
{% if image %}
{% thumbnail image 1600x800 box=cropping crop detail as thumb %}
<div class="content__intro__image scroll reveal reveal_animation" data-ease-multiplier="-2"
style="background-image: url({{ thumb.url }})"></div>
{% endif %}

@ -0,0 +1,18 @@
<div class="form__field{% if label %} form__field--label{% endif %}">
{% if label %}
<label for="{{ field.id_for_label }}"><span>{{ field.label }}</span></label>
{% endif %}
{{ field }}
{% if field.errors %}
<p class="form__field__errors">
{% for error in field.errors %}
{{ error }}{% if not forloop.last %}<br>{% endif %}
{% endfor %}
</p>
{% endif %}
{% if field.help_text %}
<p class="form__field__help_text">{{ field.help_text }}</p>
{% endif %}
</div>

@ -4,7 +4,7 @@
{% for n in 'nn' %}
<div class="{% cycle 'navigation__images' 'navigation__list' %}">
{% for child in children|slice:'3' %}
{% thumbnail child.id|page_image 800x1200 crop=True as thumb %}
{% thumbnail child.id|page_image 800x1200 box=child.id|page_image_cropping crop as thumb %}
<div class="navigation__item data_id_{{ forloop.counter0 }}" data-id="{{ forloop.counter0 }}">
{% if forloop.parentloop.first %}
<div class="navigation__item__background"

@ -17,8 +17,8 @@
<div class="search__results">
<p class="section__text search__results__amount">
{% if page_obj.object_list|length > 0 %}
{% blocktrans with amount=page_obj.object_list|length q=search_form.q.value %}
{% if search_results|length > 0 %}
{% blocktrans with amount=search_results|length q=search_form.q.value %}
{{ amount }} Resultate für «{{ q }}»:
{% endblocktrans %}
{% else %}
@ -33,11 +33,10 @@
{% endif %}
</p>
<ul>
{% for page in page_obj.object_list %}
{% for page in search_results %}
{% include "project/includes/page_item.html" with search=True image=page.object.page.imageextension.image cropping=page.object.page.imageextension.cropping %}
{% endfor %}
</ul>
{# {% include "project/includes/pagination.html" with obj_string=_('results') %}#}
</div>
</div>
</div>

@ -6,15 +6,11 @@
<span class="download__item__file__icon">{{ item.extension }}</span>
</span>
<span class="download__item__title">{{ item.label }}</span>
{% if item.description %}
<span class="download__item__description">{{ item.description }}</span>
{% endif %}
<span class="download__item__description">{{ item.description }}</span>
<span class="downloads__item__tags">{{ item.tag_list }}</span>
<span class="download__item__icon">
{% include 'project/assets/download.svg' %}
</span>
{% if item.tag_list %}
<span class="downloads__item__tags">{{ file.tag_list }}</span>
{% endif %}
</a>
</li>
{% endfor %}

@ -11,3 +11,11 @@ def page_image(id):
return Page.objects.get(pk=id).imageextension.image
except:
return None
@register.filter
def page_image_cropping(id):
try:
return Page.objects.get(pk=id).imageextension.cropping
except:
return None

@ -8,6 +8,7 @@ from project.forms import NewsletterSubscriptionForm
class SearchView(AldrynSearchView):
template_name = 'project/search.html'
context_object_name = 'search_results'
def get_context_data(self, **kwargs):
context = super(SearchView, self).get_context_data(**kwargs)

Loading…
Cancel
Save