Compare commits
52 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2963c0b3fb | ||
|
|
eac8a31856 | ||
|
|
0048f5ef99 | ||
|
|
a0bb334f05 | ||
|
|
1f3adfd482 | ||
|
|
71fa095663 | ||
|
|
b27e30700f | ||
|
|
d4b9ba68a5 | ||
|
|
6883bc9cb9 | ||
|
|
5a0457d4ff | ||
|
|
7f11089915 | ||
|
|
93de30564d | ||
|
|
061a99e77e | ||
|
|
888daefd17 | ||
|
|
80685dd71f | ||
|
|
e36afcb527 | ||
|
|
2d162d0102 | ||
|
|
d2270543b9 | ||
|
|
b456ff219c | ||
|
|
97d972fbe1 | ||
|
|
1918797b1a | ||
|
|
01eb2066b9 | ||
| ccd9828781 | |||
| 47a26a0656 | |||
| 8c5b291d24 | |||
| 9a2717d4c0 | |||
| 00cc0ac532 | |||
| c6610b8c5c | |||
| 322786cdba | |||
| 35cb78284e | |||
| c4a25cbe1c | |||
| 4627c2342f | |||
| c420c84d39 | |||
|
|
96b61a1add | ||
| 47669c4d04 | |||
|
|
49e1467147 | ||
|
|
f454305849 | ||
|
|
a018f86f42 | ||
|
|
a5290f84f3 | ||
|
|
b065becd9a | ||
|
|
51b089f9e8 | ||
|
|
f3cd332ec4 | ||
|
|
e15c162ec0 | ||
|
|
831b779e7a | ||
|
|
2ec3daeab7 | ||
|
|
c1cd63e6a6 | ||
|
|
2fbaa20b50 | ||
|
|
0cb9122f2d | ||
|
|
e710dab605 | ||
|
|
b8e84b204e | ||
|
|
e6d9a13f22 | ||
|
|
b90dd00590 |
@@ -1,6 +1,6 @@
|
||||
*.pyc
|
||||
*.pyo
|
||||
/.env
|
||||
/data
|
||||
/static_collected
|
||||
/docker
|
||||
/node_modules
|
||||
.git
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
DATABASE_URL=postgres://postgres@postgres:5432/db
|
||||
DEFAULT_HAYSTACK_URL=es+https://tcjf1ngoog:qj70l67kk2@tagesschule-elementa-8329801232.eu-west-1.bonsaisearch.net/test-*
|
||||
DATABASE_URL=postgres://django@MuzQzD6yLyaksfw9f6NUDLsK6Tp7gD7f8uX:5432/db
|
||||
DEFAULT_HAYSTACK_URL=es+https://tcjf1ngoog:qj70l67kk2@tagesschule-elementa-8329801232.eu-west-1.bonsaisearch.net/test-*
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
SECRET_KEY=TEST---asdg4hr63453452542h4sdf25g42s3df54hj38rd4sg3f2d54h3sd5f4g53
|
||||
DEBUG=False
|
||||
DEBUG=True
|
||||
SENTRY_DSN=https://460e310d034c49a794941e087c4fcc6e@sentry.io/1196285
|
||||
DEFAULT_HAYSTACK_URL=es+https://tcjf1ngoog:qj70l67kk2@tagesschule-elementa-8329801232.eu-west-1.bonsaisearch.net/index-*
|
||||
DATABASE_URL=postgres://django:MuzQzD6yLyaksfw9f6NUDLsK6Tp7gD7f8uX@postgres:5432/db
|
||||
DATABASE_URL=postgres://django:MuzQzD6yLyaksfw9f6NUDLsK6Tp7gD7f8uX@postgres:5432/db
|
||||
HTTP_PORT=8009
|
||||
POSTGRES_PASSWORD=MuzQzD6yLyaksfw9f6NUDLsK6Tp7gD7f8uX
|
||||
POSTGRES_USER=django
|
||||
POSTGRES_DB=db
|
||||
POSTGRES_DATA_DIR=./docker/pgdata
|
||||
MEDIA_DIR=./docker/data/media
|
||||
DATA_DIR=./docker/data
|
||||
STATIC_DIR=./docker/static_collected
|
||||
17
.gitignore
vendored
17
.gitignore
vendored
@@ -15,16 +15,23 @@ Thumbs.db
|
||||
|
||||
# Aldryn
|
||||
.aldryn
|
||||
/data
|
||||
/data.tar.gz
|
||||
/static_collected
|
||||
/docker/static_collected
|
||||
/node_modules
|
||||
# </DEFAULT>
|
||||
/static/css/
|
||||
/static/js/
|
||||
/static/fonts/
|
||||
/static/img/
|
||||
/static/animation/
|
||||
/.idea
|
||||
/requirements.txt
|
||||
/conf/certbot/
|
||||
/docker/conf/certbot/
|
||||
/docker/pgdata/**
|
||||
/docker/data
|
||||
.env-nginx
|
||||
.env-db
|
||||
.env
|
||||
docker/storage/**
|
||||
.bash_history
|
||||
.cache/
|
||||
.local/
|
||||
.ssh/
|
||||
69
.viminfo
Normal file
69
.viminfo
Normal 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
|
||||
@@ -54,8 +54,8 @@ RUN pip-reqs compile && \
|
||||
COPY . /app
|
||||
# </SOURCE>
|
||||
|
||||
RUN mkdir /app/static_collected
|
||||
RUN mkdir /app/data/media
|
||||
RUN mkdir -p /app/static_collected
|
||||
RUN mkdir -p /app/data/media
|
||||
|
||||
# <GULP>
|
||||
ENV GULP_MODE=production
|
||||
|
||||
45
README.md
Normal file
45
README.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# Tagesschule elementa
|
||||
|
||||
ssh tagesschule@docker.mprofiag.de
|
||||
sudo ./docker-update.sh
|
||||
|
||||
## Docker
|
||||
|
||||
1. Copy environment files `.env*.example` to `.env*` and make the configuration changes.
|
||||
Configure database user and ports for docker.
|
||||
- HTTP_PORT=8009 [.env] ...
|
||||
|
||||
|
||||
2. Main app has several mountpoints / volumes. Point them into the appropriate location on
|
||||
your filesystem
|
||||
- ./docker/static_collected
|
||||
- ./docker/data/media
|
||||
- ./docker/data
|
||||
|
||||
3. To start
|
||||
|
||||
docker-compose up
|
||||
|
||||
4. Restore DB
|
||||
|
||||
docker exec -i tagesschule_db_1 pg_restore -U django --no-owner -d db < 41ebf901-4607-4653-9b00-54a42d877b38.dump
|
||||
|
||||
3. Migrate
|
||||
|
||||
docker-compose exec web manage.py migrate
|
||||
|
||||
5. Add admin user
|
||||
|
||||
In docker container `docker-compose exec web bash` run
|
||||
|
||||
python manage.py shell
|
||||
|
||||
In that shell create admin user (https://stackoverflow.com/questions/18503770/how-to-create-user-from-django-shell)
|
||||
|
||||
user@host> manage.py shell
|
||||
>>> from django.contrib.auth.models import User
|
||||
>>> user=User.objects.create_user('foo', password='bar')
|
||||
>>> user.is_superuser=True
|
||||
>>> user.is_staff=True
|
||||
>>> user.save()
|
||||
|
||||
2
bin/gulp
2
bin/gulp
@@ -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
2
docker-build.sh
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
cd /var/www/tagesschule && git pull && docker-compose build web
|
||||
@@ -5,55 +5,36 @@ services:
|
||||
image: nginx:1.16-alpine
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./conf/nginx:/etc/nginx/conf.d
|
||||
- ./conf/certbot/conf:/etc/letsencrypt
|
||||
- ./conf/certbot/www:/var/www/certbot
|
||||
- ./static_collected:/app/static_collected
|
||||
- ./data/media:/app/data/media
|
||||
- ./docker/conf/nginx:/etc/nginx/conf.d
|
||||
- ./docker/static_collected:/app/static_collected
|
||||
- ${MEDIA_DIR}:/app/data/media
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
|
||||
- ${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
|
||||
|
||||
certbot:
|
||||
image: certbot/certbot
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./conf/certbot/conf:/etc/letsencrypt
|
||||
- ./conf/certbot/www:/var/www/certbot
|
||||
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
|
||||
|
||||
network_mode: bridge
|
||||
links:
|
||||
- web
|
||||
web:
|
||||
restart: unless-stopped
|
||||
build: "."
|
||||
links:
|
||||
- "db:postgres"
|
||||
volumes:
|
||||
- ".:/app:rw"
|
||||
- "./data:/data:rw"
|
||||
- ./static_collected:/app/static_collected
|
||||
- ./data/media:/app/data/media
|
||||
networks:
|
||||
- nginx_network
|
||||
- db_network
|
||||
- .:/app:rw
|
||||
- ${DATA_DIR}:/data:rw
|
||||
- ${STATIC_DIR}:/app/static_collected
|
||||
- ${MEDIA_DIR}:/app/data/media
|
||||
network_mode: bridge
|
||||
command: "/bin/sh -c '/app/wait-for-postgres.sh postgres /app/run.sh'"
|
||||
env_file:
|
||||
- ./.env
|
||||
db:
|
||||
restart: unless-stopped
|
||||
image: postgres:9.6-alpine
|
||||
env_file:
|
||||
- ./.env-db
|
||||
volumes:
|
||||
- ".:/app:rw"
|
||||
- "./pgdata:/var/lib/postgresql/data:rw"
|
||||
networks:
|
||||
- db_network
|
||||
|
||||
networks:
|
||||
nginx_network:
|
||||
driver: bridge
|
||||
db_network:
|
||||
driver: bridge
|
||||
- ${POSTGRES_DATA_DIR}:/var/lib/postgresql/data:rw
|
||||
network_mode: bridge
|
||||
|
||||
2
docker-logs.sh
Executable file
2
docker-logs.sh
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
cd /var/www/tagesschule && docker-compose logs --tail=100 -f
|
||||
2
docker-restart.sh
Executable file
2
docker-restart.sh
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
cd /var/www/tagesschule && git pull && docker-compose restart web
|
||||
2
docker-up.sh
Executable file
2
docker-up.sh
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
cd /var/www/tagesschule && docker-compose up
|
||||
2
docker-update.sh
Executable file
2
docker-update.sh
Executable 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
2
docker-web-cli.sh
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
cd /var/www/tagesschule && docker-compose exec web bash
|
||||
@@ -2,34 +2,16 @@ upstream gunicorn {
|
||||
server web:80;
|
||||
}
|
||||
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name tagesschule.mprofiag.ch;
|
||||
server_tokens off;
|
||||
|
||||
location /.well-known/acme-challenge/ {
|
||||
root /var/www/certbot;
|
||||
}
|
||||
|
||||
location / {
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name tagesschule.mprofiag.ch;
|
||||
server_tokens off;
|
||||
sendfile on;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/tagesschule.mprofiag.ch/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/tagesschule.mprofiag.ch/privkey.pem;
|
||||
include /etc/letsencrypt/options-ssl-nginx.conf;
|
||||
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
||||
|
||||
add_header X-Frame-Options "";
|
||||
|
||||
client_max_body_size 1000M;
|
||||
|
||||
gzip on;
|
||||
gzip_http_version 1.1;
|
||||
gzip_disable "MSIE [1-6]\.";
|
||||
0
docker/pgdata/.gitkeep
Normal file
0
docker/pgdata/.gitkeep
Normal 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'));
|
||||
|
||||
});
|
||||
@@ -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();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
|
||||
@@ -38,3 +38,4 @@
|
||||
@import "modules/plugins/_timetable.scss";
|
||||
@import "modules/plugins/_reference_list.scss";
|
||||
@import "modules/plugins/_form.scss";
|
||||
@import "modules/plugins/_iframe.scss";
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
3
private/scss/modules/plugins/_iframe.scss
Normal file
3
private/scss/modules/plugins/_iframe.scss
Normal file
@@ -0,0 +1,3 @@
|
||||
.iframe {
|
||||
margin: em(50px) 0;
|
||||
}
|
||||
@@ -6,4 +6,8 @@
|
||||
width: 100%;
|
||||
display: block;
|
||||
height: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.spacer ~ .spacer {
|
||||
height: em(50px);
|
||||
}
|
||||
|
||||
@@ -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%);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,20 +15,31 @@ 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
|
||||
aldryn-forms-recaptcha-plugin==1.0.0.2
|
||||
django-recaptcha2==1.4.1
|
||||
# compat versions
|
||||
django-storages<1.9
|
||||
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
|
||||
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
|
||||
dj-database-url==0.5.0
|
||||
django-js-asset==1.2.3
|
||||
idna==3.4
|
||||
cssselect==1.1.0
|
||||
lxml-html-clean==0.1.1
|
||||
|
||||
27
settings.py
27
settings.py
@@ -38,8 +38,7 @@ aldryn_addons.settings.load(locals())
|
||||
|
||||
INSTALLED_APPS.insert(0, 'admin_view_permission')
|
||||
INSTALLED_APPS.extend([
|
||||
'aldryn_forms_recaptcha_plugin',
|
||||
'snowpenguin.django.recaptcha3',
|
||||
'snowpenguin.django.recaptcha2',
|
||||
'portal',
|
||||
'project',
|
||||
'fontawesome',
|
||||
@@ -205,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
|
||||
|
||||
@@ -255,11 +255,18 @@ if not DEBUG:
|
||||
'tagesschule-elementa.ch',
|
||||
'www.tagesschule-elementa.ch',
|
||||
'tagesschule.mprofiag.ch',
|
||||
'docker.mprofiag.de'
|
||||
]
|
||||
|
||||
DATA_UPLOAD_MAX_MEMORY_SIZE = 1024 * 1024 * 1024
|
||||
|
||||
RECAPTCHA_PUBLIC_KEY = '6Lec78gZAAAAANc-oxXJPMi7BXmINlP-QkcS937g'
|
||||
RECAPTCHA_PRIVATE_KEY = '6Lec78gZAAAAADuIppqW7cSh6iPw3TZQ9r-ogHtz'
|
||||
RECAPTCHA_PUBLIC_KEY = '6LeILd0ZAAAAAB9xO_y8kS292wv2ikl0M8s7zFn9'
|
||||
RECAPTCHA_PRIVATE_KEY = '6LeILd0ZAAAAAOGF1AvxdiGcXWLjr2BzHaQ8Zush'
|
||||
|
||||
RECAPTCHA_SCORE_THRESHOLD = 0.5
|
||||
|
||||
ALDRYN_FORMS_ACTION_BACKENDS = {
|
||||
'default': 'project.action_backends.DefaultAction',
|
||||
'email_only': 'aldryn_forms.action_backends.EmailAction',
|
||||
'none': 'aldryn_forms.action_backends.NoAction',
|
||||
}
|
||||
|
||||
46
src/portal/migrations/0005_auto_20200325_1611.py
Normal file
46
src/portal/migrations/0005_auto_20200325_1611.py
Normal file
@@ -0,0 +1,46 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.21 on 2020-03-25 16:11
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
import django.db.models.deletion
|
||||
import parler.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('portal', '0004_auto_20180718_1754'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='announcement',
|
||||
options={'ordering': ['-updated'], 'verbose_name': 'Neuigkeit', 'verbose_name_plural': 'Aktuell'},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='announcementtranslation',
|
||||
name='master',
|
||||
field=parler.fields.TranslationsForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='portal.Announcement'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='downloadfiletranslation',
|
||||
name='master',
|
||||
field=parler.fields.TranslationsForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='portal.DownloadFile'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='downloadsectiontranslation',
|
||||
name='master',
|
||||
field=parler.fields.TranslationsForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='portal.DownloadSection'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='informationsectiontranslation',
|
||||
name='master',
|
||||
field=parler.fields.TranslationsForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='portal.InformationSection'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='informationtranslation',
|
||||
name='master',
|
||||
field=parler.fields.TranslationsForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='portal.Information'),
|
||||
),
|
||||
]
|
||||
13
src/project/action_backends.py
Normal file
13
src/project/action_backends.py
Normal file
@@ -0,0 +1,13 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from aldryn_forms.action_backends_base import BaseAction
|
||||
|
||||
class DefaultAction(BaseAction):
|
||||
verbose_name = 'Default'
|
||||
|
||||
def form_valid(self, cmsplugin, instance, request, form):
|
||||
email = form.cleaned_data.get('emailfield_1', None)
|
||||
if email and email in ['eric.jones.z.mail@gmail.com']:
|
||||
return
|
||||
recipients = cmsplugin.send_notifications(instance, form)
|
||||
form.instance.set_recipients(recipients)
|
||||
form.save()
|
||||
@@ -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')
|
||||
|
||||
|
||||
|
||||
@@ -8,11 +8,14 @@ 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, \
|
||||
TextSliderItem, HighlightListItem, ReferenceListItem, SocialMediaList, SocialMediaListItem, Timetable, \
|
||||
TimetableItem, Partner, HighlightList, Image, TitleListItem, TitleList, IntroImage, Gallery
|
||||
TimetableItem, Partner, HighlightList, Image, TitleListItem, TitleList, IntroImage, Gallery, Iframe
|
||||
|
||||
|
||||
@plugin_pool.register_plugin
|
||||
@@ -26,7 +29,7 @@ class SectionPlugin(CMSPluginBase):
|
||||
'SectionTextPlugin', 'VideoPlugin', 'DownloadSectionPlugin', 'TextSliderPlugin',
|
||||
'HighlightListPlugin', 'ReferenceListPlugin', 'FormPlugin', 'PicturePlugin', 'SubPageListPlugin',
|
||||
'PartnerPlugin', 'NewsletterSubscriptionPlugin', 'NewsletterArchivePlugin',
|
||||
'SocialMediaListPlugin', 'GalleryPlugin']
|
||||
'SocialMediaListPlugin', 'GalleryPlugin', 'IframePlugin']
|
||||
|
||||
|
||||
@plugin_pool.register_plugin
|
||||
@@ -206,6 +209,24 @@ class FormPlugin(_FormPlugin):
|
||||
'SubmitButton', 'ReCaptchaFieldPlugin']
|
||||
|
||||
|
||||
@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):
|
||||
model = SocialMediaListItem
|
||||
extra = 0
|
||||
@@ -327,3 +348,11 @@ class GalleryPlugin(CMSPluginBase):
|
||||
module = 'Content'
|
||||
name = 'Gallery'
|
||||
render_template = 'project/plugins/content/gallery.html'
|
||||
|
||||
|
||||
@plugin_pool.register_plugin
|
||||
class IframePlugin(CMSPluginBase):
|
||||
model = Iframe
|
||||
module = 'Content'
|
||||
name = 'Iframe'
|
||||
render_template = 'project/plugins/content/iframe.html'
|
||||
|
||||
27
src/project/migrations/0010_auto_20200325_1611.py
Normal file
27
src/project/migrations/0010_auto_20200325_1611.py
Normal file
@@ -0,0 +1,27 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.21 on 2020-03-25 16:11
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
import django.db.models.deletion
|
||||
import parler.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('project', '0009_auto_20190214_1250'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='notificationtranslation',
|
||||
name='master',
|
||||
field=parler.fields.TranslationsForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='project.Notification'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='slideritemqualificationtranslation',
|
||||
name='master',
|
||||
field=parler.fields.TranslationsForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='project.SliderItemQualification'),
|
||||
),
|
||||
]
|
||||
26
src/project/migrations/0011_auto_20211104_1608.py
Normal file
26
src/project/migrations/0011_auto_20211104_1608.py
Normal 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'),
|
||||
),
|
||||
]
|
||||
30
src/project/migrations/0012_iframe.py
Normal file
30
src/project/migrations/0012_iframe.py
Normal file
@@ -0,0 +1,30 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.21 on 2024-05-23 15:51
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cms', '0020_old_tree_cleanup'),
|
||||
('project', '0011_auto_20211104_1608'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Iframe',
|
||||
fields=[
|
||||
('cmsplugin_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='project_iframe', serialize=False, to='cms.CMSPlugin')),
|
||||
('html', models.TextField(verbose_name='HTML')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Iframe',
|
||||
'verbose_name_plural': 'Iframes',
|
||||
'abstract': False,
|
||||
},
|
||||
bases=('cms.cmsplugin',),
|
||||
),
|
||||
]
|
||||
@@ -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'
|
||||
@@ -347,3 +349,14 @@ class Gallery(CMSPlugin):
|
||||
@property
|
||||
def files(self):
|
||||
return self.folder.files.all().order_by('name')
|
||||
|
||||
|
||||
class Iframe(CMSPlugin):
|
||||
html = models.TextField('HTML')
|
||||
|
||||
class Meta(CMSPlugin.Meta):
|
||||
verbose_name = 'Iframe'
|
||||
verbose_name_plural = 'Iframes'
|
||||
|
||||
def __str__(self):
|
||||
return self.html
|
||||
|
||||
@@ -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 %}
|
||||
@@ -175,12 +177,14 @@
|
||||
<div id="privacy-message" style="display: none;">
|
||||
<div class="privacy-message__frame">
|
||||
<p>
|
||||
{% page_url 'imprint' as privacy_url %}
|
||||
{% blocktrans with privacy_url=privacy_url %}
|
||||
{% page_url 'privacy' as privacy_url %}
|
||||
{% if LANGUAGE_CODE == 'de' %}
|
||||
Um diese Webseite optimal gestalten und fortlaufend verbessern zu können, verwenden wir Cookies.
|
||||
Weitere Informationen finden Sie in unserer
|
||||
<a href="{{ privacy_url }}">Datenschutzerklärung im Impressum</a>.
|
||||
{% endblocktrans %}
|
||||
Weitere Informationen finden Sie in unserer <a href="{{ privacy_url }}">Datenschutzerklärung</a>.
|
||||
{% else %}
|
||||
In order to optimize this website and to continuously improve it, we use cookies.
|
||||
Further information can be found in our <a href="{{ privacy_url }}">data protection policy</a>.
|
||||
{% endif %}
|
||||
</p>
|
||||
<div class="privacy-message__actions">
|
||||
<a href="#" class="button button--small button--ghost privacy_action--decline">
|
||||
@@ -206,32 +210,24 @@
|
||||
|
||||
<script>
|
||||
$(function() {
|
||||
var init_google_analytics = function() {
|
||||
(function(i, s, o, g, r, a, m) {
|
||||
i['GoogleAnalyticsObject'] = r;
|
||||
i[r] = i[r] || function() {
|
||||
(i[r].q = i[r].q || []).push(arguments)
|
||||
}, i[r].l = 1 * new Date();
|
||||
a = s.createElement(o),
|
||||
m = s.getElementsByTagName(o)[0];
|
||||
a.async = 1;
|
||||
a.src = g;
|
||||
m.parentNode.insertBefore(a, m)
|
||||
})(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');
|
||||
|
||||
ga('create', 'UA-116863155-1', 'auto');
|
||||
ga('set', 'anonymizeIp', true);
|
||||
ga('send', 'pageview');
|
||||
var init_tag_manager = function() {
|
||||
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
|
||||
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
|
||||
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
|
||||
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
|
||||
})(window,document,'script','dataLayer','GTM-WVRJ872');
|
||||
};
|
||||
|
||||
if (window.privacy_accepted) {
|
||||
init_google_analytics();
|
||||
init_tag_manager();
|
||||
}
|
||||
|
||||
$('body').on('enable_tracking', function() {
|
||||
init_google_analytics();
|
||||
init_tag_manager();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
{% recaptcha_explicit_init LANGUAGE_CODE %}
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<div class="iframe reveal_container">
|
||||
<div class="reveal reveal_animation">
|
||||
<div style="display:inline-block;vertical-align:top;width:300px;margin:20px auto;color:#333;background:#fff;border:1px solid #ddd;line-height:1.2;text-decoration:none;padding:0"><a href="https://read.bookcreator.com/Y0SYhDEKm4Wfw50K2K1EsVR6BSO2/3EzILpspTZubAkL9btIklA" style="display:block;color:#333;line-height:1.2;text-decoration:none;padding:0;font-weight:normal" target="_blank" rel="noreferrer"><img src="https://assets.api.bookcreator.com/Y0SYhDEKm4Wfw50K2K1EsVR6BSO2/books/3EzILpspTZubAkL9btIklA/cover/share" style="max-height:300px;max-width:100%;display:block;margin:0 auto;padding:0;border:none" alt="Unsere Lieblingstiere"/></a><div style="display:block;padding:20px;overflow:hidden;overflow-x:hidden;border-top:1px solid #ddd"><div style="display:block;color:#333;line-height:1.2;text-decoration:none;padding:0;font-weight:normal;font-size:21px;margin:0 0 0.25em"><a href="https://read.bookcreator.com/Y0SYhDEKm4Wfw50K2K1EsVR6BSO2/3EzILpspTZubAkL9btIklA" style="display:block;color:#333;line-height:1.2;text-decoration:none;padding:0;font-weight:normal" target="_blank" rel="noreferrer">Unsere Lieblingstiere</a></div><div style="display:block;color:#333;line-height:1.2;text-decoration:none;padding:0;font-weight:normal;font-size:16px;margin:0 0 0.5em"><a href="https://read.bookcreator.com/Y0SYhDEKm4Wfw50K2K1EsVR6BSO2/3EzILpspTZubAkL9btIklA" style="display:block;color:#333;line-height:1.2;text-decoration:none;padding:0;font-weight:normal" target="_blank" rel="noreferrer">Click to read this book, made with Book Creator</a></div><div style="display:block;color:#455a64;line-height:1.2;text-decoration:none;padding:0;font-weight:bold;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:14px"><a href="https://read.bookcreator.com/Y0SYhDEKm4Wfw50K2K1EsVR6BSO2/3EzILpspTZubAkL9btIklA" style="display:block;color:#333;line-height:1.2;text-decoration:none;padding:0;font-weight:normal" target="_blank" rel="noreferrer">read.bookcreator.com</a></div></div></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -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' %}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -3,7 +3,7 @@ from django.conf.urls import url, include
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.views.generic.base import TemplateView
|
||||
|
||||
from project.views import SearchView, NewsletterSubscriptionView, LoginRedirectView, MediaRedirectView
|
||||
from project.views import SearchView, NewsletterSubscriptionView, LoginRedirectView, MediaRedirectView, ArchiveFilerPublic
|
||||
|
||||
urlpatterns = [
|
||||
url(_(r'^suche/'), SearchView.as_view(), kwargs={'search': True}, name='search'),
|
||||
@@ -13,4 +13,5 @@ urlpatterns = [
|
||||
name='newsletter_subscription_success'),
|
||||
url(r'^login/redirect/$', LoginRedirectView.as_view(), name='login_redirect'),
|
||||
url(r'^media/bridge/$', MediaRedirectView.as_view(), name='media_bridge'),
|
||||
url(r'^media/archive/$', ArchiveFilerPublic.as_view(), name='media_archive'),
|
||||
]
|
||||
|
||||
@@ -2,10 +2,16 @@
|
||||
from aldryn_search.views import AldrynSearchView
|
||||
from cms.models import Page
|
||||
from django.core.urlresolvers import reverse_lazy
|
||||
from django.views import View
|
||||
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
|
||||
import os
|
||||
import zipfile
|
||||
|
||||
|
||||
class SearchView(AldrynSearchView):
|
||||
@@ -45,3 +51,75 @@ 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
|
||||
|
||||
|
||||
class ArchiveFilerPublic(View):
|
||||
|
||||
def get(self, request):
|
||||
path = '/app/data/media/filer_public/'
|
||||
with zipfile.ZipFile('filer_public.zip', 'w', zipfile.ZIP_DEFLATED) as zipf:
|
||||
for root, dirs, files in os.walk(path):
|
||||
for file in files:
|
||||
filePath = os.path.join(root, file)
|
||||
try:
|
||||
with open(filePath) as tempFile:
|
||||
pass
|
||||
zipf.write(filePath, os.path.relpath(filePath, os.path.join(path, '..')))
|
||||
except IOError:
|
||||
print(filePath)
|
||||
return HttpResponse('success')
|
||||
|
||||
|
||||
1
static/css/main.css
Normal file
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
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
1
static/js/main.js
Normal file
File diff suppressed because one or more lines are too long
@@ -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 %}
|
||||
|
||||
@@ -7,10 +7,10 @@ host="$1"
|
||||
shift
|
||||
cmd="$@"
|
||||
|
||||
until PGPASSWORD=$POSTGRES_PASSWORD psql -h "$host" -U "postgres" -c '\q'; do
|
||||
until PGPASSWORD=$POSTGRES_PASSWORD psql -h "$host" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c '\q'; do
|
||||
>&2 echo "Postgres is unavailable - sleeping"
|
||||
sleep 1
|
||||
done
|
||||
|
||||
>&2 echo "Postgres is up - executing command"
|
||||
exec $cmd
|
||||
exec $cmd
|
||||
|
||||
Reference in New Issue
Block a user