32 Commits

Author SHA1 Message Date
Simon Caminada
919dd33373 fix: local docker-compose setup 2022-06-29 12:40:27 +02:00
Simon Caminada
061a99e77e fix: update docs 2022-06-29 12:40:03 +02:00
Simon Caminada
888daefd17 fix: updated smtp password 2022-05-17 15:14:14 +02:00
Simon Caminada
80685dd71f fix: spacer not working 2022-05-06 17:03:50 +02:00
Simon Caminada
e36afcb527 fix 2021-11-05 18:30:07 +01:00
Simon Caminada
2d162d0102 add static to git 2021-11-05 18:14:05 +01:00
Simon Caminada
d2270543b9 add static 2021-11-05 17:31:37 +01:00
Simon Caminada
b456ff219c update timetable button 2021-11-05 17:25:34 +01:00
Simon Caminada
97d972fbe1 add video to timetable 2021-11-04 22:38:06 +01:00
Simon Caminada
1918797b1a fix vimeo autoplay 2021-10-14 09:45:03 +02:00
Simon Caminada
01eb2066b9 add timeout to video play 2021-10-14 09:38:27 +02:00
ccd9828781 custom aldryn_forms export 2021-05-25 15:03:16 +02:00
47a26a0656 updated requirements 2021-05-06 13:12:55 +02:00
8c5b291d24 fix password 2021-02-23 14:16:53 +01:00
9a2717d4c0 fix mail password 2021-02-23 12:11:10 +01:00
00cc0ac532 try to add static to git 2020-10-30 16:09:17 +01:00
c6610b8c5c recaptcha form fix 2020-10-30 15:30:25 +01:00
322786cdba fix privacy 2020-10-05 13:51:56 +02:00
35cb78284e fix compat version 2020-10-05 13:47:07 +02:00
c4a25cbe1c clean up anymail 2020-10-05 12:37:38 +02:00
4627c2342f update mail settings 2020-10-05 12:27:17 +02:00
c420c84d39 fix email infos 2020-10-05 12:27:11 +02:00
root
96b61a1add Renamed and new scripts 2020-09-10 20:40:25 +02:00
47669c4d04 Merge branch 'standalone' into mprofiag
# Conflicts:
#	requirements.in
2020-09-09 16:03:55 +02:00
2dd84d27f0 add recaptcha plugin 2020-09-07 15:53:28 +02:00
root
49e1467147 Changes from server 2020-07-07 22:46:42 +02:00
Petr Šnobl
f454305849 link 2020-05-04 21:57:31 +02:00
Petr Šnobl
a018f86f42 bridge network mode 2020-05-04 21:52:57 +02:00
8eeb5f5947 fix 2020-05-03 13:31:32 +02:00
0dfeb359ac fix 2020-05-03 13:18:45 +02:00
Petr Šnobl
a5290f84f3 Merge branch 'standalone' into mprofiag
# Conflicts:
#	requirements.in
2020-04-29 18:12:10 +02:00
ee63555dd8 sentry integration 2020-04-29 12:20:22 +02:00
34 changed files with 423 additions and 72 deletions

7
.gitignore vendored
View File

@@ -19,8 +19,6 @@ Thumbs.db
/docker/static_collected
/node_modules
# </DEFAULT>
/static/css/
/static/js/
/static/fonts/
/static/img/
/static/animation/
@@ -32,3 +30,8 @@ Thumbs.db
.env-nginx
.env-db
.env
docker/storage/**
.bash_history
.cache/
.local/
.ssh/

69
.viminfo Normal file
View File

@@ -0,0 +1,69 @@
# This viminfo file was generated by Vim 8.0.
# You may edit it if you're careful!
# Viminfo version
|1,4
# Value of 'encoding' when this file was written
*encoding=utf-8
# hlsearch on (H) or off (h):
~h
# Command Line History (newest to oldest):
:q
|2,0,1599761890,,"q"
# Search String History (newest to oldest):
# Expression History (newest to oldest):
# Input Line History (newest to oldest):
# Debug Line History (newest to oldest):
# Registers:
# File marks:
'0 1 0 ~/restart.sh
|4,48,1,0,1599761890,"~/restart.sh"
'1 1 0 ~/restart.sh
|4,49,1,0,1599761817,"~/restart.sh"
'2 1 0 ~/restart.sh
|4,50,1,0,1599761501,"~/restart.sh"
'3 1 0 ~/restart.sh
|4,51,1,0,1599761501,"~/restart.sh"
'4 1 0 ~/restart.sh
|4,52,1,0,1599660361,"~/restart.sh"
'5 1 0 ~/restart.sh
|4,53,1,0,1599660361,"~/restart.sh"
'6 1 0 ~/restart.sh
|4,54,1,0,1599660361,"~/restart.sh"
'7 1 0 ~/restart.sh
|4,55,1,0,1599660361,"~/restart.sh"
'8 1 0 ~/restart.sh
|4,56,1,0,1599485736,"~/restart.sh"
'9 1 0 ~/restart.sh
|4,57,1,0,1599485736,"~/restart.sh"
# Jumplist (newest first):
-' 1 0 ~/restart.sh
|4,39,1,0,1599761890,"~/restart.sh"
-' 1 0 ~/restart.sh
|4,39,1,0,1599761817,"~/restart.sh"
-' 1 0 ~/restart.sh
|4,39,1,0,1599761501,"~/restart.sh"
-' 1 0 ~/restart.sh
|4,39,1,0,1599660361,"~/restart.sh"
-' 1 0 ~/restart.sh
|4,39,1,0,1599485736,"~/restart.sh"
-' 1 0 ~/restart.sh
|4,39,1,0,1599480996,"~/restart.sh"
-' 1 0 ~/restart.sh
|4,39,1,0,1599474185,"~/restart.sh"
# History of marks within files (newest to oldest):
> ~/restart.sh
* 1599761887 0
" 1 0

View File

@@ -54,7 +54,7 @@ RUN pip-reqs compile && \
COPY . /app
# </SOURCE>
RUN mkdir /app/static_collected
RUN mkdir -p /app/static_collected
RUN mkdir -p /app/data/media
# <GULP>

View File

@@ -1,5 +1,7 @@
# Tagesschule elementa
ssh tagesschule@docker.mprofiag.de
sudo ./docker-update.sh
## Docker

View File

@@ -1,2 +1,2 @@
#/bin/bash
exec docker-compose run --rm web gulp "$@" --debug
exec docker-compose run --rm web gulp "$@" --inspect

2
docker-build.sh Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/bash
cd /var/www/tagesschule && git pull && docker-compose build web

View File

@@ -1,49 +1,21 @@
version: '3'
services:
nginx:
image: nginx:1.16-alpine
restart: unless-stopped
volumes:
- ./docker/conf/nginx:/etc/nginx/conf.d
- ./docker/static_collected:/app/static_collected
- ${MEDIA_DIR}:/app/data/media
ports:
- ${HTTP_PORT}:80
#command: "/bin/sh -c 'while :; do sleep 1m & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
depends_on:
- web
networks:
- nginx_network
web:
restart: unless-stopped
build: "."
links:
- "db:postgres"
ports:
- "8007:80"
volumes:
- .:/app:rw
- ${DATA_DIR}:/data:rw
- ${STATIC_DIR}:/app/static_collected
- ${MEDIA_DIR}:/app/data/media
networks:
- db_network
- nginx_network
command: "/bin/sh -c '/app/wait-for-postgres.sh postgres /app/run.sh'"
- ".:/app:rw"
- "./data:/data:rw"
command: python manage.py runserver 0.0.0.0:80
env_file:
- ./.env
db:
restart: unless-stopped
image: postgres:9.6-alpine
env_file:
- ./.env-db
volumes:
- ${POSTGRES_DATA_DIR}:/var/lib/postgresql/data:rw
networks:
- db_network
networks:
nginx_network:
driver: bridge
db_network:
driver: bridge
- ".:/app:rw"

2
docker-logs.sh Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/bash
cd /var/www/tagesschule && docker-compose logs --tail=100 -f

2
docker-restart.sh Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/bash
cd /var/www/tagesschule && git pull && docker-compose restart web

2
docker-up.sh Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/bash
cd /var/www/tagesschule && docker-compose up

2
docker-update.sh Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/bash
cd /var/www/tagesschule && git pull && docker-compose build web && docker-compose up

2
docker-web-cli.sh Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/bash
cd /var/www/tagesschule && docker-compose exec web bash

View File

@@ -54,6 +54,7 @@ $(function() {
reveal_element($('.header__logo'));
reveal_elements($('.timetable__clock__frame'));
reveal_element($('.timetable__next'));
reveal_element($('.timetable__button'));
reveal_element($('.timetable__start__background'));
});

View File

@@ -13,11 +13,14 @@ $(function() {
url: $form.attr('action'),
data: $form.serialize(),
success: function(data) {
django_recaptcha_callbacks = [];
var $new = $(data).find('#' + id);
$new.find('.reveal').each(function() {
$(this).removeClass('reveal reveal_animation');
});
$new.removeClass('reveal reveal_animation');
$form.replaceWith($new);
djangoRecaptchaOnLoadCallback();
}
});
});

View File

@@ -1,4 +1,4 @@
$(function() {
$(function () {
var $body = $('body');
var $timetable = $('#timetable');
@@ -9,7 +9,7 @@ $(function() {
$(window).scrollTop(0);
window.timetable_can_scroll = false;
window.setTimeout(function() {
window.setTimeout(function () {
window.timetable_can_scroll = true;
}, 2500);
@@ -39,17 +39,17 @@ $(function() {
function init_timetable_items() {
$timetable.attr('data-active', 1);
$timetable.find('.timetable__item').each(function() {
$timetable.find('.timetable__item').each(function () {
$(this).addClass('reveal_container')
});
window.setTimeout(function() {
window.setTimeout(function () {
$timetable.addClass('active');
window.requestAnimationFrame(function() {
$timetable.find('.timetable__item').each(function() {
window.requestAnimationFrame(function () {
$timetable.find('.timetable__item').each(function () {
var index = parseInt($(this).attr('data-id'));
var elementWatcher = scrollMonitor.create(this);
elementWatcher.enterViewport(function() {
elementWatcher.enterViewport(function () {
set_timetable_item(index);
});
});
@@ -76,7 +76,7 @@ $(function() {
var $timetable_progress = $('#timetable__clock__progress');
var timetable_clock_progress_max = parseFloat($timetable_progress.attr('stroke-dasharray'));
$body.on('click', '.timetable__next', function(event) {
$body.on('click', '.timetable__next', function (event) {
event.preventDefault();
if (!activated) {
$(window).scrollTop($(window).height());
@@ -146,4 +146,45 @@ $(function() {
$timetable_progress.attr('stroke-dashoffset', timetable_clock_progress_max * Math.abs(total_progress - 1));
}
}
document.querySelector('.timetable__button a').addEventListener('click', function (event) {
event.preventDefault();
var player;
var vimeo_id = document.querySelector('.timetable__button').getAttribute('data-video-vimeo-id');
var pswpElement = document.querySelectorAll('.pswp')[0],
gallery,
options,
items;
options = {
showHideOpacity: true,
download: false,
fullscreenEl: false,
shareEl: false,
bgOpacity: 0.85,
mainClass: 'timetable__pswp',
};
items = [
{
html: '<div class="gallery__iframe"><div class="gallery__iframe__main"><iframe src="https://player.vimeo.com/video/' + vimeo_id + '" width="100%" height="100%" frameborder="0" allow="autoplay; fullscreen" allowfullscreen></iframe></div></div>',
},
];
var gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, items, options);
gallery.listen('close', function () {
document.querySelector('#timetable').style.height = '';
player.pause();
});
gallery.init();
document.querySelector('#timetable').style.height = '100%';
var iframe = document.querySelector('.pswp iframe');
player = new Vimeo.Player(iframe);
player.play();
});
});

View File

@@ -11,14 +11,14 @@ $(function() {
$body.on('click', '.privacy_action--accept', function(event) {
event.preventDefault();
setCookie(cookie_name, true, 360);
setCookie(cookie_name, 'true', 60);
$privacy_message.remove();
$body.trigger('enable_tracking');
});
$body.on('click', '.privacy_action--decline', function(event) {
event.preventDefault();
setCookie(cookie_name, false, 360);
setCookie(cookie_name, 'false', 60);
$privacy_message.remove();
});

View File

@@ -153,6 +153,29 @@
min-width: em(200px);
}
.button--icon {
white-space: nowrap;
transform: none;
transition: transform 0.4s $easeOutQuart;
.button__icon {
display: inline-block;
vertical-align: top;
position: relative;
transform: none !important;
width: auto;
padding-left: em(15px);
}
.button__text {
vertical-align: top;
transform: none !important;
padding-left: 0;
min-width: auto;
}
&:hover {
transform: scale(1.05);
}
}
.form__field {
width: 100%;
display: block;

View File

@@ -3,6 +3,25 @@
font-size: 0;
}
.gallery__iframe {
width: 100%;
max-width: 140vh;
margin: auto;
position: relative;
top: 50%;
transform: translateY(-50%);
}
.gallery__iframe__main {
width: 100%;
padding-bottom: 56.25%;
position: relative;
}
.gallery__iframe__main iframe {
position: absolute;
}
.gallery__item {
display: inline-block;
vertical-align: top;

View File

@@ -6,4 +6,8 @@
width: 100%;
display: block;
height: 1px;
}
}
.spacer ~ .spacer {
height: em(50px);
}

View File

@@ -11,9 +11,44 @@ $timetable_count: 15;
}
}
.timetable__button {
opacity: 0;
position: fixed;
bottom: 150px;
left: 50%;
transform: translateX(-50%);
z-index: 1000;
transition: opacity 0.5s $easeOutQuad, transform 0.5s $easeOutQuad;
#timetable[data-active="0"] & {
opacity: 1;
}
img {
position: absolute;
top: 50%;
left: 50%;
width: 40px;
height: 20px;
margin-left: -20px;
}
&.reveal {
transform: translateX(-50%) scale(1.2);
}
@media screen and (max-width: $huge_breakpoint) {
bottom: 130px;
}
@media screen and (max-width: $large_breakpoint) {
bottom: 120px;
}
}
.timetable__pswp .pswp__top-bar {
opacity: 1;
background: transparent;
}
.timetable__clock__frame {
position: fixed;
top: 50%;
top: 40%;
transform: translateY(-50%);
width: 30%;
left: 35%;
@@ -25,10 +60,10 @@ $timetable_count: 15;
left: 50%;
max-width: 40vh;
transform: translateX(-50%) translateY(14%);
#timetable[data-active="0"] & {
top: 50%;
transform: translateX(-50%) translateY(-50%);
}
// #timetable[data-active="0"] & {
// top: 50%;
// transform: translateX(-50%) translateY(-50%);
// }
}
}

View File

@@ -15,10 +15,26 @@ https://control.divio.com/api/v1/apps/serve/django-filer/1.4.1/e7e860ea-0af6-4fc
elasticsearch==6.4.0
django-spurl==0.6.5
aldryn-search==1.0.1
django-fontawesome==0.3.1
django-fontawesome==1.0
mailchimp3==2.1.0
django-image-cropping==1.2.0
django-anymail[mailgun]==1.4
django-admin-view-permission==1.9
gunicorn==19.9.0
sentry-sdk==0.14.3
django-recaptcha2==1.4.1
# compat versions
django-storages<1.9 # https://stackoverflow.com/questions/60297619/divio-importerror-cannot-import-name-s3boto
psycopg2<2.8
django-parler<=2.1
django-select2<=6.3.1
django-formtools==2.2
django-sekizai<=1.1.0
django-classy-tags<=1.0.0
djangocms-attributes-field<=1.2.0
django-haystack==2.8.1
django-simple-captcha==0.5.12
django-treebeard==4.3.1
django-meta==1.7.0
tablib==0.14.0
django-simple-sso==0.14.1
easy-thumbnails==2.7.1

View File

@@ -1,6 +1,17 @@
# -*- coding: utf-8 -*-
import copy
import os
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration
sentry_sdk.init(
dsn="https://460e310d034c49a794941e087c4fcc6e@o74423.ingest.sentry.io/1196285",
integrations=[DjangoIntegration()],
# If you wish to associate users to errors (assuming you are using
# django.contrib.auth) you may enable sending PII data.
send_default_pii=True
)
INSTALLED_ADDONS = [
# <INSTALLED_ADDONS> # Warning: text inside the INSTALLED_ADDONS tags is auto-generated. Manual changes will be overwritten.
@@ -27,6 +38,7 @@ aldryn_addons.settings.load(locals())
INSTALLED_APPS.insert(0, 'admin_view_permission')
INSTALLED_APPS.extend([
'snowpenguin.django.recaptcha2',
'portal',
'project',
'fontawesome',
@@ -192,12 +204,13 @@ CKEDITOR_SETTINGS_TIMETABLE_ITEM_TITLE['bodyClass'] = 'h2 timetable__item__title
CKEDITOR_SETTINGS_TIMETABLE_ITEM_TEXT = copy.deepcopy(CKEDITOR_SETTINGS_INPUT)
CKEDITOR_SETTINGS_TIMETABLE_ITEM_TEXT['bodyClass'] = 'section__text timetable__item__text'
ANYMAIL = {
'MAILGUN_API_KEY': 'key-f6625f8850326f8774b2f587c0c41cd2',
'MAILGUN_SENDER_DOMAIN': 'mg.tagesschule-elementa.ch',
}
EMAIL_BACKEND = 'anymail.backends.mailgun.EmailBackend'
DEFAULT_FROM_EMAIL = 'system@tagesschule-elementa.ch'
DEFAULT_FROM_EMAIL = 'web@tagesschule-elementa.ch'
EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.office365.com'
EMAIL_HOST_USER = DEFAULT_FROM_EMAIL
EMAIL_HOST_PASSWORD = 'TagesschuleElementa1234'
EMAIL_PORT = 587
FILER_ENABLE_PERMISSIONS = True
@@ -246,3 +259,8 @@ if not DEBUG:
]
DATA_UPLOAD_MAX_MEMORY_SIZE = 1024 * 1024 * 1024
RECAPTCHA_PUBLIC_KEY = '6LeILd0ZAAAAAB9xO_y8kS292wv2ikl0M8s7zFn9'
RECAPTCHA_PRIVATE_KEY = '6LeILd0ZAAAAAOGF1AvxdiGcXWLjr2BzHaQ8Zush'
RECAPTCHA_SCORE_THRESHOLD = 0.5

View File

@@ -2,8 +2,10 @@
from django.contrib import admin
from cms.extensions import PageExtensionAdmin
from parler.admin import TranslatableAdmin
from aldryn_forms.models import FormSubmission
from aldryn_forms.admin.base import BaseFormSubmissionAdmin
from project.models import ImageExtension, SliderItemQualification, Notification
from project.views import CustomFormExportWizardView
@admin.register(ImageExtension)
@@ -19,3 +21,15 @@ class SliderItemQualificationAdmin(TranslatableAdmin):
@admin.register(Notification)
class NotificationAdmin(TranslatableAdmin):
pass
admin.site.unregister(FormSubmission)
@admin.register(FormSubmission)
class FormSubmissionAdmin(BaseFormSubmissionAdmin):
def get_form_export_view(self):
return CustomFormExportWizardView.as_view(admin=self, file_type='xls')

View File

@@ -8,6 +8,9 @@ from djangocms_picture.cms_plugins import PicturePlugin as _PicturePlugin
from djangocms_text_ckeditor.cms_plugins import TextPlugin as _TextPlugin
from django.contrib import admin
from mailchimp3 import MailChimp
from aldryn_forms.cms_plugins import Field
from snowpenguin.django.recaptcha2.fields import ReCaptchaField
from snowpenguin.django.recaptcha2.widgets import ReCaptchaWidget
from project.forms import NewsletterSubscriptionForm
from project.models import Section, Quote, SliderItem, SectionText, Video, DownloadSection, DownloadSectionFolder, \
@@ -203,12 +206,25 @@ class FormPlugin(_FormPlugin):
module = 'Content'
name = 'Form'
child_classes = ['TextField', 'TextAreaField', 'EmailField', 'RadioSelectField', 'MultipleSelectField',
'SubmitButton']
'SubmitButton', 'ReCaptchaFieldPlugin']
def send_notifications(self, instance, form):
if dict(form.get_serialized_field_choices()).get('honeypot', ''):
return []
return super(FormPlugin, self).send_notifications(instance, form)
@plugin_pool.register_plugin
class ReCaptchaFieldPlugin(Field):
name = 'ReCaptcha Field'
render_template = True
allow_children = False
form_field = ReCaptchaField
form_field_widget = ReCaptchaWidget
form_field_enabled_options = [
'error_messages',
]
fieldset_general_fields = []
fieldset_advanced_fields = []
def get_form_field_widget_kwargs(self, instance):
return {'explicit': True}
class SocialMediaListItemInlineAdmin(admin.TabularInline):

View File

@@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.21 on 2021-11-04 16:08
from __future__ import unicode_literals
from django.db import migrations, models
import djangocms_text_ckeditor.fields
class Migration(migrations.Migration):
dependencies = [
('project', '0010_auto_20200325_1611'),
]
operations = [
migrations.AddField(
model_name='timetable',
name='video_cta',
field=djangocms_text_ckeditor.fields.HTMLField(blank=True, null=True, verbose_name='Video CTA'),
),
migrations.AddField(
model_name='timetable',
name='video_vimeo_id',
field=models.IntegerField(blank=True, help_text='e.g. https://vimeo.com/<b>131766159</b>', null=True, verbose_name='Video Vimeo ID'),
),
]

View File

@@ -265,6 +265,8 @@ class Timetable(CMSPlugin):
introduction = HTMLField(verbose_name='Intro', configuration='CKEDITOR_SETTINGS_INPUT')
outro = HTMLField(verbose_name='Outro', configuration='CKEDITOR_SETTINGS_INPUT', blank=True, null=True)
cta = HTMLField(verbose_name='CTA', configuration='CKEDITOR_SETTINGS_INPUT', blank=True, null=True)
video_vimeo_id = models.IntegerField(verbose_name='Video Vimeo ID', blank=True, null=True, help_text='e.g. https://vimeo.com/<b>131766159</b>')
video_cta = HTMLField(verbose_name='Video CTA', configuration='CKEDITOR_SETTINGS_INPUT', blank=True, null=True)
class Meta(CMSPlugin.Meta):
verbose_name = 'Timetable'

View File

@@ -1,4 +1,4 @@
{% load static i18n cms_tags sekizai_tags fontawesome menu_tags %}<!DOCTYPE html>
{% load static i18n cms_tags sekizai_tags fontawesome menu_tags recaptcha2 %}<!DOCTYPE html>
<html class="r" lang="{{ LANGUAGE_CODE }}">
<head>
<meta http-equiv="x-ua-compatible" content="ie=edge">
@@ -10,6 +10,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="google" content="notranslate">
{% recaptcha_explicit_support %}
<meta name="msvalidate.01" content="7E7A1E68251AEDF0AF320164C774E3E8"/>
{% block extra_meta %}
@@ -233,5 +235,7 @@
});
});
</script>
{% recaptcha_explicit_init LANGUAGE_CODE %}
</body>
</html>

View File

@@ -1,7 +1,7 @@
{% load i18n thumbnail util_tags %}
<div class="video reveal_container">
<iframe class="video__frame" src="https://player.vimeo.com/video/{{ instance.vimeo_id }}?dnt=1" width="640" height="360" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
<iframe class="video__frame" src="https://player.vimeo.com/video/{{ instance.vimeo_id }}?dnt=1" width="640" height="360" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen allow="autoplay"></iframe>
<a href="#" class="video__thumbnail reveal reveal_animation">
<span class="video__play">
{% include 'project/assets/play.svg' %}

View File

@@ -1,6 +1,15 @@
{% load i18n cms_tags thumbnail util_tags %}
<div id="timetable" data-active="0" data-last="{{ instance.child_plugin_instances|length }}">
{% if instance.video_vimeo_id and instance.video_cta %}
<div class="timetable__button reveal reveal_animation data_delay_8" data-video-vimeo-id="{{ instance.video_vimeo_id }}">
<a href="#video" class="button button--white button--small button--icon">
<span class="button__icon">{% include 'project/assets/play.svg' %}</span>
<span class="button__text">{{ instance.video_cta }}</span>
</a>
</div>
{% endif %}
<div class="timetable__clock__frame">
<div class="timetable__clock__main">
<div class="timetable__start reveal reveal_animation data_delay_8"></div>

View File

@@ -4,7 +4,10 @@ from cms.models import Page
from django.core.urlresolvers import reverse_lazy
from django.views.generic import RedirectView
from django.views.generic.edit import FormView
from aldryn_forms.admin.views import FormExportWizardView
from aldryn_forms.admin.exporter import Exporter
from tablib import Dataset
from django.http import HttpResponse
from project.forms import NewsletterSubscriptionForm
@@ -45,3 +48,57 @@ class MediaRedirectView(RedirectView):
def get_redirect_url(self, *args, **kwargs):
return self.request.GET.get('url', None)
class CustomExporter(Exporter):
custom_fields = ['sent_at']
def get_dataset(self, fields):
headers = [field.rpartition('-')[0] for field in fields]
for custom_field in self.custom_fields:
headers.append(custom_field)
dataset = Dataset(headers=headers)
for submission in self.queryset.only('data').iterator():
row_data = []
form_fields = [field for field in submission.get_form_data()
if field.field_id in fields]
for header in fields:
for field in form_fields:
if field.field_id == header:
row_data.append(field.value)
break
else:
row_data.append('')
if row_data:
for custom_field in self.custom_fields:
row_data.append(getattr(submission, custom_field).strftime('%d.%m.%Y %H:%M:%S'))
dataset.append(row_data)
return dataset
class CustomFormExportWizardView(FormExportWizardView):
def done(self, form_list, **kwargs):
"""
this step only runs if all forms are valid.
"""
form_iter = iter(form_list)
step_1_form = next(form_iter)
step_2_form = next(form_iter)
fields = step_2_form.get_fields()
queryset = step_1_form.get_queryset()
dataset = CustomExporter(queryset=queryset).get_dataset(fields=fields)
filename = step_1_form.get_filename(extension=self.file_type)
content_type = self.get_content_type()
response = HttpResponse(dataset.xls, content_type=content_type)
response['Content-Disposition'] = 'attachment; filename=%s' % filename
return response

1
static/css/main.css Normal file

File diff suppressed because one or more lines are too long

1
static/js/lib.js Normal file

File diff suppressed because one or more lines are too long

1
static/js/main.js Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +1,5 @@
{% for name, value in form_data %}
<p>{{ name }}: {{ value|default_if_none:"—" }}</p>
{% if name %}
<p>{{ name }}: {{ value|default_if_none:"—" }}</p>
{% endif %}
{% endfor %}