Merge branch 'master' of https://git.fet.at/bofh/fet2020
This commit is contained in:
@@ -5,6 +5,7 @@ from django.contrib.auth.models import User
|
|||||||
|
|
||||||
from .authentications import authentication
|
from .authentications import authentication
|
||||||
from .decorators import unauthenticated_user, authenticated_user
|
from .decorators import unauthenticated_user, authenticated_user
|
||||||
|
from documents.etherpadlib import del_ep_cookie
|
||||||
|
|
||||||
|
|
||||||
@unauthenticated_user
|
@unauthenticated_user
|
||||||
@@ -33,4 +34,8 @@ def loginPage(request):
|
|||||||
@authenticated_user
|
@authenticated_user
|
||||||
def logoutUser(request):
|
def logoutUser(request):
|
||||||
logout(request)
|
logout(request)
|
||||||
return redirect('home')
|
|
||||||
|
response = redirect('home')
|
||||||
|
response = del_ep_cookie(request, response)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
# from etherpad_lite import EtherpadLiteClient
|
|
||||||
# from django.conf import settings
|
|
||||||
from datetime import datetime, timedelta
|
|
||||||
# from django.utils.text import slugify
|
|
||||||
import urllib.parse
|
|
||||||
from django.conf import settings
|
|
||||||
# import os
|
|
||||||
from .api import ep
|
|
||||||
# from .etherpadlib import get_ep_sessionid2, add_ep_cookie
|
|
||||||
SERVER_URL = settings.ETHERPAD_CLIENT["exturl"]
|
|
||||||
t = datetime.now() + timedelta(days=1)
|
|
||||||
|
|
||||||
|
|
||||||
def get_pad_link(padID):
|
|
||||||
if padID is None:
|
|
||||||
return "#"
|
|
||||||
if ep.get_epc():
|
|
||||||
return urllib.parse.urljoin(SERVER_URL, 'p/' + ep.group["groupID"] + '$' + str(padID))
|
|
||||||
return ""
|
|
||||||
|
|||||||
@@ -1,93 +1,93 @@
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
|
||||||
from datetime import datetime, timedelta
|
|
||||||
from etherpad_lite import EtherpadLiteClient, EtherpadException
|
from etherpad_lite import EtherpadLiteClient, EtherpadException
|
||||||
|
|
||||||
|
SERVER_URL = settings.ETHERPAD_CLIENT["exturl"]
|
||||||
|
|
||||||
class ep_api():
|
|
||||||
def __init__(self):
|
|
||||||
self.group = None
|
|
||||||
self.epc = None
|
|
||||||
return
|
|
||||||
|
|
||||||
def load(self):
|
def get_ep_client():
|
||||||
|
epc = None
|
||||||
|
group = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(os.path.abspath(settings.ETHERPAD_CLIENT["apikey"]), "r") as f:
|
with open(os.path.abspath(settings.ETHERPAD_CLIENT["apikey"]), "r") as f:
|
||||||
k = f.read()
|
apikey = f.read()
|
||||||
epc = EtherpadLiteClient(
|
epc = EtherpadLiteClient(
|
||||||
base_params={'apikey': k, },
|
base_params={'apikey': apikey, },
|
||||||
base_url=urllib.parse.urljoin(settings.ETHERPAD_CLIENT["url"], "api")
|
base_url=urllib.parse.urljoin(settings.ETHERPAD_CLIENT["url"], "api"),
|
||||||
|
api_version='1.2.14',
|
||||||
)
|
)
|
||||||
g = epc.createGroupIfNotExistsFor(groupMapper="fet")
|
group = epc.createGroupIfNotExistsFor(groupMapper="fet")
|
||||||
self.group = g
|
|
||||||
self.epc = epc
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise e
|
raise e
|
||||||
self.group = None
|
|
||||||
self.epc = None
|
|
||||||
|
|
||||||
def getPadHTML(self, padID):
|
return epc, group
|
||||||
self.get_epc()
|
|
||||||
text = self.epc.getHTML(padID=self.group["groupID"] + "$" + padID)["html"]
|
|
||||||
return text
|
|
||||||
|
|
||||||
def setPadHTML(self, padID, html):
|
|
||||||
self.get_epc()
|
|
||||||
self.epc.setHTML(padID=self.group["groupID"] + "$" + padID, html=html)
|
|
||||||
return html
|
|
||||||
|
|
||||||
def checkPadExists(self, padID=None):
|
def __checkPadExists(padID=None):
|
||||||
print(self.epc.listPads(groupID=self.group["groupID"]))
|
|
||||||
if not padID:
|
if not padID:
|
||||||
return False
|
return False
|
||||||
try:
|
|
||||||
self.epc.getRevisionsCount(padID=self.group["groupID"] + "$" + padID)
|
|
||||||
except EtherpadException as e:
|
|
||||||
print(e)
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def createPadifNotExists(self, padid):
|
epc, group = get_ep_client()
|
||||||
self.get_epc()
|
if not epc:
|
||||||
if not self.epc:
|
|
||||||
return None
|
return None
|
||||||
if not self.checkPadExists(padID=padid): # Pad doesn't exist
|
|
||||||
self.epc.createGroupPad(groupID=self.group["groupID"], padName=padid, text="helloworld")
|
|
||||||
return padid
|
|
||||||
|
|
||||||
def get_epc(self):
|
|
||||||
if self.epc:
|
|
||||||
return self.epc
|
|
||||||
self.load()
|
|
||||||
return self.epc
|
|
||||||
|
|
||||||
def get_ep_sessionid2(self, request):
|
|
||||||
if request.user is None:
|
|
||||||
return None, None
|
|
||||||
if not request.user.is_authenticated:
|
|
||||||
return None, None
|
|
||||||
# server = SERVER_URL
|
|
||||||
ep.get_epc()
|
|
||||||
author = self.epc.createAuthorIfNotExistsFor(
|
|
||||||
name=str(request.user),
|
|
||||||
authorMapper=str(request.user)
|
|
||||||
)['authorID']
|
|
||||||
expires = datetime.utcnow() + timedelta(
|
|
||||||
hours=3
|
|
||||||
)
|
|
||||||
try:
|
try:
|
||||||
result = self.epc.createSession(
|
lists = epc.listAllPads()
|
||||||
groupID=str(self.group['groupID']),
|
|
||||||
authorID=str(author),
|
|
||||||
validUntil=str(int(expires.timestamp()))
|
|
||||||
)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise e
|
raise e
|
||||||
return None, None
|
else:
|
||||||
|
string = group["groupID"] + "$" + str(padID)
|
||||||
|
if string in lists["padIDs"]:
|
||||||
|
return True
|
||||||
|
|
||||||
return result['sessionID'], expires
|
return False
|
||||||
|
|
||||||
|
|
||||||
ep = ep_api()
|
def createPadifNotExists(padID):
|
||||||
|
epc, group = get_ep_client()
|
||||||
|
if not epc:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Pad doesn't exist
|
||||||
|
if not __checkPadExists(padID=padID):
|
||||||
|
try:
|
||||||
|
epc.createGroupPad(groupID=group["groupID"], padName=padID, text="helloworld")
|
||||||
|
except EtherpadException as e:
|
||||||
|
# TODO: change it after Etherpad server is a better one than that because of http 500
|
||||||
|
print(e)
|
||||||
|
except Exception as e:
|
||||||
|
raise e
|
||||||
|
return padID
|
||||||
|
|
||||||
|
|
||||||
|
def getReadOnlyID(padID):
|
||||||
|
epc, group = get_ep_client()
|
||||||
|
url = epc.getReadOnlyID(padID=group["groupID"] + "$" + padID)['readOnlyID']
|
||||||
|
return url
|
||||||
|
|
||||||
|
|
||||||
|
def getPadHTML(padID):
|
||||||
|
epc, group = get_ep_client()
|
||||||
|
text = epc.getHTML(padID=group["groupID"] + "$" + padID)["html"]
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
def setPadHTML(padID, html):
|
||||||
|
epc, group = get_ep_client()
|
||||||
|
epc.setHTML(padID=group["groupID"] + "$" + padID, html=html)
|
||||||
|
return html
|
||||||
|
|
||||||
|
|
||||||
|
def get_pad_link(padID):
|
||||||
|
if padID is None:
|
||||||
|
return "#"
|
||||||
|
|
||||||
|
epc, group = get_ep_client()
|
||||||
|
|
||||||
|
if epc:
|
||||||
|
return urllib.parse.urljoin(SERVER_URL, 'p/' + group["groupID"] + '$' + str(padID))
|
||||||
|
return ""
|
||||||
|
|||||||
@@ -1,36 +1,58 @@
|
|||||||
# from etherpad_lite import EtherpadLiteClient
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
# from datetime import datetime, timedelta
|
from .api import get_ep_client
|
||||||
# from django.utils.text import slugify
|
from authentications.decorators import authenticated_user
|
||||||
# import urllib.parse
|
|
||||||
# from django.conf import settings
|
|
||||||
from .api import ep
|
@authenticated_user
|
||||||
|
def __get_ep_sessionid(request):
|
||||||
|
epc, group = get_ep_client()
|
||||||
|
|
||||||
|
author = epc.createAuthorIfNotExistsFor(
|
||||||
|
name=str(request.user),
|
||||||
|
authorMapper=str(request.user)
|
||||||
|
)['authorID']
|
||||||
|
|
||||||
|
expires = datetime.utcnow() + timedelta(hours=3)
|
||||||
|
try:
|
||||||
|
result = epc.createSession(
|
||||||
|
groupID=str(group['groupID']),
|
||||||
|
authorID=str(author),
|
||||||
|
validUntil=str(int(expires.timestamp()))
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
raise e
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
return result['sessionID'], expires
|
||||||
|
|
||||||
|
|
||||||
def add_ep_cookie(request, response):
|
def add_ep_cookie(request, response):
|
||||||
response.set_cookie("HILib", "TestWert", domain="https://andis.2020.fet.at")
|
ep_sessid, expires = __get_ep_sessionid(request)
|
||||||
ep_sessid, expires = ep.get_ep_sessionid2(request)
|
|
||||||
if ep_sessid is None:
|
if ep_sessid:
|
||||||
response.set_cookie(
|
|
||||||
"sessionID",
|
|
||||||
"NOTAUTHENTICATED",
|
|
||||||
expires=expires,
|
|
||||||
domain=".2020.fet.at",
|
|
||||||
path="/",
|
|
||||||
)
|
|
||||||
return response
|
|
||||||
#response.set_cookie(
|
|
||||||
# "sessionID",
|
|
||||||
# ep_sessid,
|
|
||||||
# expires=expires,
|
|
||||||
# domain=".2020.fet.at",
|
|
||||||
# path="/"
|
|
||||||
#)
|
|
||||||
response.set_cookie(
|
response.set_cookie(
|
||||||
"sessionID",
|
"sessionID",
|
||||||
ep_sessid,
|
ep_sessid,
|
||||||
expires=expires,
|
expires=expires,
|
||||||
domain=".2020.fet.at",
|
domain=".2020.fet.at",
|
||||||
path="/p"
|
path="/"
|
||||||
|
)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
def del_ep_cookie(request, response):
|
||||||
|
|
||||||
|
if 'sessionID' in request.COOKIES:
|
||||||
|
ep_sessionID = request.COOKIES['sessionID']
|
||||||
|
|
||||||
|
epc, group = get_ep_client()
|
||||||
|
epc.deleteSession(sessionID=ep_sessionID)
|
||||||
|
|
||||||
|
response.delete_cookie(
|
||||||
|
"sessionID",
|
||||||
|
domain=".2020.fet.at",
|
||||||
|
path="/"
|
||||||
)
|
)
|
||||||
return response
|
return response
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from django import forms
|
|||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from ckeditor_uploader.widgets import CKEditorUploadingWidget
|
from ckeditor_uploader.widgets import CKEditorUploadingWidget
|
||||||
|
from taggit.models import Tag
|
||||||
|
|
||||||
from .models import Post, Event, News, FetMeeting
|
from .models import Post, Event, News, FetMeeting
|
||||||
|
|
||||||
@@ -91,7 +92,6 @@ class MyFetMeetingForm(MyEventForm):
|
|||||||
# agenda_html = forms.CharField(widget = forms.TextInput())
|
# agenda_html = forms.CharField(widget = forms.TextInput())
|
||||||
class Meta:
|
class Meta:
|
||||||
model = FetMeeting
|
model = FetMeeting
|
||||||
|
|
||||||
fields = ['event_start', 'event_end', 'tags', 'has_agenda', 'has_protocol']
|
fields = ['event_start', 'event_end', 'tags', 'has_agenda', 'has_protocol']
|
||||||
labels = {
|
labels = {
|
||||||
'event_start': _('Start der Sitzung'),
|
'event_start': _('Start der Sitzung'),
|
||||||
@@ -112,3 +112,8 @@ class MyFetMeetingForm(MyEventForm):
|
|||||||
|
|
||||||
self.fields['has_agenda'].initial = True
|
self.fields['has_agenda'].initial = True
|
||||||
self.fields['has_protocol'].initial = True
|
self.fields['has_protocol'].initial = True
|
||||||
|
|
||||||
|
tags = []
|
||||||
|
tags.append(Tag())
|
||||||
|
tags[0].name = "fachschaft"
|
||||||
|
self.fields['tags'].initial = tags
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from django.utils import timezone
|
|||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from taggit.managers import TaggableManager
|
from taggit.managers import TaggableManager
|
||||||
from documents import ep
|
from documents.api import getPadHTML, setPadHTML, createPadifNotExists
|
||||||
|
|
||||||
from .managers import (
|
from .managers import (
|
||||||
PostManager, ArticleManager, NewsManager, AllEventManager, EventManager, FetMeetingManager
|
PostManager, ArticleManager, NewsManager, AllEventManager, EventManager, FetMeetingManager
|
||||||
@@ -102,13 +102,14 @@ class Post(models.Model):
|
|||||||
def agenda_html(self):
|
def agenda_html(self):
|
||||||
if not self.agenda_key:
|
if not self.agenda_key:
|
||||||
return None
|
return None
|
||||||
h = ep.getPadHTML(self.agenda_key)
|
|
||||||
return h
|
html = getPadHTML(self.agenda_key)
|
||||||
|
return html
|
||||||
|
|
||||||
@agenda_html.setter
|
@agenda_html.setter
|
||||||
def agenda_html(self, value):
|
def agenda_html(self, value):
|
||||||
request_logger.info("Accessing etherpad ...")
|
request_logger.info("Accessing etherpad ...")
|
||||||
ep.setPadHTML(self.agenda_key, value)
|
setPadHTML(self.agenda_key, value)
|
||||||
request_logger.info("set etherpad!")
|
request_logger.info("set etherpad!")
|
||||||
return value
|
return value
|
||||||
|
|
||||||
@@ -259,7 +260,7 @@ class FetMeeting(Event):
|
|||||||
|
|
||||||
def __get_agenda_key(self):
|
def __get_agenda_key(self):
|
||||||
try:
|
try:
|
||||||
self.agenda_key = ep.createPadifNotExists(self.slug + "-agenda")
|
self.agenda_key = createPadifNotExists(self.slug + "-agenda")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
_('Die Agenda konnte nicht erstellt werden. Error: %(error)s'),
|
_('Die Agenda konnte nicht erstellt werden. Error: %(error)s'),
|
||||||
@@ -268,7 +269,7 @@ class FetMeeting(Event):
|
|||||||
|
|
||||||
def __get_protocol_key(self):
|
def __get_protocol_key(self):
|
||||||
try:
|
try:
|
||||||
self.protocol_key = ep.createPadifNotExists(self.slug + "-protocol")
|
self.protocol_key = createPadifNotExists(self.slug + "-protocol")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
_('Das Protokoll konnte nicht erstellt werden. Error: %(error)s'),
|
_('Das Protokoll konnte nicht erstellt werden. Error: %(error)s'),
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.http import HttpResponse, JsonResponse, HttpResponseServerError
|
from django.http import HttpResponse, JsonResponse, HttpResponseServerError
|
||||||
from django_filters.rest_framework import DjangoFilterBackend
|
|
||||||
# from django.core.cache import cache
|
|
||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from taggit.models import Tag
|
from collections import deque
|
||||||
|
from django_filters.rest_framework import DjangoFilterBackend
|
||||||
from rest_framework import viewsets
|
from rest_framework import viewsets
|
||||||
# from rest_framework import permissions
|
from taggit.models import Tag
|
||||||
|
|
||||||
from .models import Post, PostSerializer, FetMeeting
|
from .models import Post, PostSerializer, FetMeeting
|
||||||
from members.models import Member, JobMember
|
from documents.api import get_pad_link
|
||||||
# from documents import add_ep_to_response, get_ep_sessionid2
|
|
||||||
from documents import get_pad_link
|
|
||||||
from documents.etherpadlib import add_ep_cookie
|
from documents.etherpadlib import add_ep_cookie
|
||||||
|
from members.models import Member, JobMember
|
||||||
|
|
||||||
from collections import deque
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
##################
|
##################
|
||||||
@@ -78,18 +78,34 @@ def show(request, id=None):
|
|||||||
if post_author:
|
if post_author:
|
||||||
author_image = post_author.image['avatar'].url
|
author_image = post_author.image['avatar'].url
|
||||||
|
|
||||||
|
ep_agenda_link = None
|
||||||
|
ep_protocol_link = None
|
||||||
|
|
||||||
|
if p.has_agenda and p.agenda_key:
|
||||||
|
ep_agenda_link = get_pad_link(p.agenda_key)
|
||||||
|
|
||||||
|
if p.has_protocol and p.protocol_key:
|
||||||
|
ep_protocol_link = get_pad_link(p.protocol_key)
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
"post": p,
|
"post": p,
|
||||||
"author_image": author_image,
|
"author_image": author_image,
|
||||||
"next": get_next_dict(p),
|
"next": get_next_dict(p),
|
||||||
"related_posts": p.tags.similar_objects(),
|
"related_posts": p.tags.similar_objects(),
|
||||||
"ep_agenda_link": get_pad_link(p.agenda_key),
|
"ep_agenda_link": ep_agenda_link,
|
||||||
"ep_protocol_link": get_pad_link(p.protocol_key),
|
"ep_protocol_link": ep_protocol_link,
|
||||||
}
|
}
|
||||||
|
|
||||||
response = render(request, 'posts/show.html', context)
|
response = render(request, 'posts/show.html', context)
|
||||||
|
|
||||||
return add_ep_cookie(request, response)
|
# check if etherpad server works
|
||||||
|
if ep_agenda_link or ep_protocol_link:
|
||||||
|
try:
|
||||||
|
response = add_ep_cookie(request, response)
|
||||||
|
except Exception as e:
|
||||||
|
logger.info("Etherpad Server doesn't work. Error: {}".format(e))
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
###########
|
###########
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
<div class="article-title">
|
<div class="article-title">
|
||||||
<h1>{{ post.title|safe }}</h1>
|
<h1>{{ post.title|safe }}</h1>
|
||||||
<p>{{post.subtitle | safe}}</p>
|
<p>{{ post.subtitle|default_if_none:" "|safe }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -27,7 +27,6 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="medium-4 responsive-side-box cell">
|
<div class="medium-4 responsive-side-box cell">
|
||||||
|
|
||||||
<a href="{% url 'posts.index' %}"><h1>Neuigkeiten</h1></a>
|
<a href="{% url 'posts.index' %}"><h1>Neuigkeiten</h1></a>
|
||||||
<div class="article-row-section">
|
<div class="article-row-section">
|
||||||
{% with post=featured_post %}
|
{% with post=featured_post %}
|
||||||
@@ -37,7 +36,6 @@
|
|||||||
{% include 'posts/partials/_meeting_row.html' %}
|
{% include 'posts/partials/_meeting_row.html' %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -46,7 +44,6 @@
|
|||||||
{{ tags_list|tags_to_url }}
|
{{ tags_list|tags_to_url }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="grid-x grid-x-padding">
|
<div class="grid-x grid-x-padding">
|
||||||
<div class="medium-8 small-12 small-order-2 medium-order-1"">
|
<div class="medium-8 small-12 small-order-2 medium-order-1"">
|
||||||
{% for post in posts %}
|
{% for post in posts %}
|
||||||
@@ -57,6 +54,7 @@
|
|||||||
{% for post in events %}
|
{% for post in events %}
|
||||||
{% include 'posts/partials/_date_box.html' %}
|
{% include 'posts/partials/_date_box.html' %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
<iframe src="https://discordapp.com/widget?id=691755025697079347&theme=dark" style="width: 100%;" height="500" allowtransparency="true" frameborder="0" sandbox="allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts"></iframe>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
<div class="news-hero padding-bottom-1" style="background-image:url('{{ post.imageurl }}')">
|
<div class="news-hero padding-bottom-1" style="background-image:url('{{ post.imageurl }}')">
|
||||||
<div class="news-hero-text">
|
<div class="news-hero-text">
|
||||||
<h1>{{ post.title }}</h1>
|
<h1>{{ post.title }}</h1>
|
||||||
<h2>{{post.subtitle}}</h2>{{post}}
|
<h2>{{ post.subtitle|default_if_none:" " }}</h2>
|
||||||
|
{{ post }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
{% extends "layout.html" %}
|
{% extends "layout.html" %}
|
||||||
{% load post_helpers %}
|
{% load post_helpers %}
|
||||||
{% load admin_urls %}
|
{% load admin_urls %}
|
||||||
@@ -16,7 +15,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="article-details">
|
<div class="article-details">
|
||||||
{{post.subtitle |tags_to_url}}
|
{{ post.subtitle|default_if_none:" "|tags_to_url }}
|
||||||
|
|
||||||
{% if post.author %}
|
{% if post.author %}
|
||||||
<div class="article-author"><a href="{% url 'member' post.author %}">
|
<div class="article-author"><a href="{% url 'member' post.author %}">
|
||||||
@@ -29,11 +28,7 @@
|
|||||||
{{ post.author }}</a>
|
{{ post.author }}</a>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
</div>
|
||||||
</div> <button class="">
|
|
||||||
|
|
||||||
<span class="nav fa fa-chevron-right fa-3x"></span>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -42,11 +37,11 @@
|
|||||||
<div class="grid-x">
|
<div class="grid-x">
|
||||||
<div class="cell medium-8">
|
<div class="cell medium-8">
|
||||||
<h1>{{ post.title|tags_to_url }}</h1>
|
<h1>{{ post.title|tags_to_url }}</h1>
|
||||||
<strong>{{post.subtitle | tags_to_url}}</strong><span class="nav fa fa-chevron-right fa-3x"></span>
|
<strong>{{ post.subtitle|default_if_none:" "|tags_to_url }}</strong>
|
||||||
|
<span class="nav fa fa-chevron-right fa-3x"></span>
|
||||||
<br>
|
<br>
|
||||||
<a href="{% url 'posts.show' next %}">Nächster Artikel</a><br>
|
<a href="{% url 'posts.show' next %}">Nächster Artikel</a><br>
|
||||||
|
|
||||||
|
|
||||||
<div class="cell medium-4">
|
<div class="cell medium-4">
|
||||||
{% include 'posts/partials/_date_box.html' %}
|
{% include 'posts/partials/_date_box.html' %}
|
||||||
</div>
|
</div>
|
||||||
@@ -81,8 +76,8 @@
|
|||||||
{{ post.body|safe|add_internal_links|tags_to_url }}
|
{{ post.body|safe|add_internal_links|tags_to_url }}
|
||||||
<hr>
|
<hr>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid-x grid-margin-x">
|
<div class="grid-x grid-margin-x">
|
||||||
{% for post in related_posts %}
|
{% for post in related_posts %}
|
||||||
<div class="medium-6 large-4 small-12 cell">
|
<div class="medium-6 large-4 small-12 cell">
|
||||||
|
|||||||
Reference in New Issue
Block a user