Merge branch 'webapp-model-permissions' into develop

This commit is contained in:
Jan Tuomi
2017-09-29 00:05:29 +03:00
24 changed files with 750 additions and 300 deletions
+6 -4
View File
@@ -1,11 +1,13 @@
"""File containing Infoscreen tests."""
from django.test import TestCase
from django.test import TestCase, Client
from infoscreen.models import Rotation
from infoscreen.models import SossoInfoItem
from django.http import HttpRequest
import infoscreen.views
import logging
class InfoscreenTestCase(TestCase):
"""Test cases for testing infoscreen methods."""
@@ -14,6 +16,7 @@ class InfoscreenTestCase(TestCase):
"""Create some dummy models."""
Rotation.objects.create(name="test_rot")
SossoInfoItem.objects.create()
self.c = Client()
def test_rotation_created(self):
"""Check if the dummy model actually exists."""
@@ -32,7 +35,6 @@ class InfoscreenTestCase(TestCase):
That would mean that something meaningful has been included
in the response.
"""
req = HttpRequest()
resp = infoscreen.views.info_items(req)
content = resp.content.decode('utf-8')
resp = self.c.get('/infoscreen/items')
content = resp.json()
self.assertTrue(len(content) > 0)
+2
View File
@@ -0,0 +1,2 @@
from infoscreen.views.admin_views import *
from infoscreen.views.public_views import *
@@ -5,7 +5,7 @@ from django.http import HttpResponse, HttpResponseBadRequest
from django.views.decorators.csrf import ensure_csrf_cookie
from django.views.decorators.http import require_http_methods
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.decorators import permission_required
from django.contrib.auth.decorators import permission_required, login_required
from infoscreen.models import UploadFileForm
import sikweb.settings as settings
@@ -23,53 +23,22 @@ from infoscreen.models import ImageUploadForm
from infoscreen.models import HSLDataModel
from infoscreen.models import ApyInfoItem
from infoscreen.models import VideoInfoItem
from infoscreen.hsl_fetcher import HSLFetcher
def index(request, idx, *args, **kwargs):
"""Render infoscreen index page."""
return render(request, 'infoscreen_index.html', {'rotation': idx})
@permission_required('infoscreen.change_infoinstance', login_url='/login')
@login_required(login_url='/login')
@permission_required('infoscreen.change_infoinstance', raise_exception=True)
def admin(request, *args, **kwargs):
"""Render infoscreen admin page."""
return render(request, 'infoscreen_admin.html', {})
def default(request, *args, **kwargs):
"""Try getting first rotation item."""
try:
first = Rotation.objects.all()[0].id
except:
first = 0
return index(request, first, *args, **kwargs)
def get_apy_json(request):
"""Render APY diilikone page."""
return HttpResponse(
requests.get("https://api-diilikone.apy.fi/deals/top-groups").text)
@require_http_methods(["GET"])
def rotation(request, idx, *args, **kwargs):
"""Get rotation."""
try:
rotation = Rotation.objects.get(pk=idx)
except Rotation.DoesNotExist:
resp = HttpResponse('{"error": "Rotation not found"}')
resp.status_code = 404
return resp
return HttpResponse(json.dumps(rotation.get_dict()))
def create_item_generator(model):
"""Create Infoscreen item generator."""
@ensure_csrf_cookie
@require_http_methods(["POST"])
@permission_required('infoscreen.change_infoinstance', login_url='/login')
@login_required(login_url='/login')
@permission_required('infoscreen.add_infoinstance', raise_exception=True)
def create_item(request, *args, **kwargs):
try:
data = json.loads(request.body.decode("utf-8"))
@@ -87,9 +56,11 @@ def create_item_generator(model):
def delete_item_generator(model):
"""Delete Infoscreen item generator."""
@ensure_csrf_cookie
@require_http_methods(["DELETE"])
@permission_required('infoscreen.change_infoinstance', login_url='/login')
@login_required(login_url='/login')
@permission_required('infoscreen.delete_infoinstance', raise_exception=True)
def delete_item(request, *args, **kwargs):
idx = kwargs.pop("idx", 0)
try:
@@ -110,7 +81,8 @@ def delete_item_generator(model):
# due to model structure this is little complicated
@ensure_csrf_cookie
@permission_required('infoscreen.change_infoinstance', login_url='/login')
@login_required(login_url='/login')
@permission_required('infoscreen.delete_infoinstance', raise_exception=True)
@require_http_methods(["DELETE"])
def delete_info_item(request, *args, **kwargs):
"""Delete info item."""
@@ -132,39 +104,10 @@ def delete_info_item(request, *args, **kwargs):
return resp
@require_http_methods(["GET"])
def rotations(request, *args, **kwargs):
"""Return rotation lists."""
rotations = list(map(lambda r: r.get_list(), Rotation.objects.all()))
return HttpResponse(json.dumps(rotations))
@require_http_methods(["GET"])
def info_types(request, *args, **kwargs):
"""Return info item types."""
types = []
classes = InfoItem.get_subclasses()
for c in classes:
types.append({
"name": c.display_name,
"create_template_url": c.get_create_template_url(),
})
return HttpResponse(json.dumps(types))
def info_items(request, *args, **kwargs):
"""Return Infoscreen items."""
items = []
classes = InfoItem.get_subclasses()
for c in classes:
for i in c.objects.all():
items.append(i.get_dict())
return HttpResponse(json.dumps(items))
@require_http_methods(["POST"])
@ensure_csrf_cookie
@permission_required('infoscreen.change_infoinstance', login_url='/login')
@login_required(login_url='/login')
@permission_required('infoscreen.add_infoinstance', raise_exception=True)
def create_image_item(request, *args, **kwargs):
"""Create image Infoscreen item."""
form = ImageUploadForm(request.POST, request.FILES)
@@ -180,7 +123,8 @@ def create_image_item(request, *args, **kwargs):
@require_http_methods(["POST"])
@ensure_csrf_cookie
@permission_required('infoscreen.change_infoinstance', login_url='/login')
@login_required(login_url='/login')
@permission_required('infoscreen.add_infoinstance', raise_exception=True)
def create_video_item(request, *args, **kwargs):
"""Create video Infoscreen item."""
form = UploadFileForm(request.POST, request.FILES)
@@ -196,7 +140,8 @@ def create_video_item(request, *args, **kwargs):
@require_http_methods(["POST"])
@ensure_csrf_cookie
@permission_required('infoscreen.add_rotation', login_url='/login')
@login_required(login_url='/login')
@permission_required('infoscreen.add_rotation', raise_exception=True)
def create_rotation(request, *args, **kwargs):
"""Create rotation."""
try:
@@ -217,7 +162,8 @@ def create_rotation(request, *args, **kwargs):
@require_http_methods(["DELETE"])
@ensure_csrf_cookie
@permission_required('infoscreen.delete_rotation', login_url='/login')
@login_required(login_url='/login')
@permission_required('infoscreen.delete_rotation', raise_exception=True)
def delete_rotation(request, *args, **kwargs):
"""Delete rotation."""
id = kwargs.pop("id", 0)
@@ -233,32 +179,6 @@ def delete_rotation(request, *args, **kwargs):
return resp
@require_http_methods(["GET"])
def hsl_timetable_settings(request, *args, **kwargs):
"""Set HSL timetable settings."""
d = {"departure_threshold": settings.HSL_DEPARTURE_THRESHOLD,
"hurry_threshold": settings.HSL_HURRY_THRESHOLD}
resp = json.dumps(d)
return HttpResponse(resp, status=200)
@require_http_methods(["GET"])
def CurrentHSLView(request, *args, **kwargs):
"""Get HSL data and return it."""
fetcher = HSLFetcher()
fetcherThread = threading.Thread(target=fetcher.fetch_if_needed, args=[])
fetcherThread.setDaemon(False)
fetcherThread.start()
data = HSLDataModel.objects.all()
if len(data) < 1:
return HttpResponse(
'{"error" : "Could not find timetables from database."}',
status=500)
return HttpResponse(data[len(data) - 1].data, status=200)
createInstance = create_item_generator(InfoInstance)
deleteInstance = delete_item_generator(InfoInstance)
createABBItem = create_item_generator(ABBInfoItem)
+103
View File
@@ -0,0 +1,103 @@
from django.shortcuts import render
from django.http import HttpResponse, JsonResponse, HttpResponseBadRequest
from django.views.decorators.http import require_http_methods
from infoscreen.models import Rotation, InfoItem, InfoInstance
from infoscreen.hsl_fetcher import HSLFetcher
import json
import logging
@require_http_methods(["GET"])
def index(request, idx, *args, **kwargs):
"""Render infoscreen index page."""
return render(request, 'infoscreen_index.html', {'rotation': idx})
@require_http_methods(["GET"])
def default(request, *args, **kwargs):
"""Try getting first rotation item."""
try:
first = Rotation.objects.all()[0].id
except:
first = 0
return index(request, first, *args, **kwargs)
@require_http_methods(["GET"])
def get_apy_json(request):
"""Render APY diilikone page."""
return HttpResponse(
requests.get("https://api-diilikone.apy.fi/deals/top-groups").text)
@require_http_methods(["GET"])
def rotation(request, idx, *args, **kwargs):
"""Get rotation."""
try:
rotation = Rotation.objects.get(pk=idx)
except Rotation.DoesNotExist:
resp = HttpResponse('{"error": "Rotation not found"}')
resp.status_code = 404
return resp
return HttpResponse(json.dumps(rotation.get_dict()))
@require_http_methods(["GET"])
def rotations(request, *args, **kwargs):
"""Return rotation lists."""
rotations = list(map(lambda r: r.get_list(), Rotation.objects.all()))
return HttpResponse(json.dumps(rotations))
@require_http_methods(["GET"])
def info_types(request, *args, **kwargs):
"""Return info item types."""
types = []
classes = InfoItem.get_subclasses()
for c in classes:
types.append({
"name": c.display_name,
"create_template_url": c.get_create_template_url(),
})
return HttpResponse(json.dumps(types))
@require_http_methods(["GET"])
def info_items(request, *args, **kwargs):
"""Return Infoscreen items."""
items = []
classes = InfoItem.get_subclasses()
for c in classes:
for i in c.objects.all():
items.append(i.get_dict())
return JsonResponse(items, safe=False)
@require_http_methods(["GET"])
def hsl_timetable_settings(request, *args, **kwargs):
"""Set HSL timetable settings."""
d = {"departure_threshold": settings.HSL_DEPARTURE_THRESHOLD,
"hurry_threshold": settings.HSL_HURRY_THRESHOLD}
resp = json.dumps(d)
return HttpResponse(resp, status=200)
@require_http_methods(["GET"])
def CurrentHSLView(request, *args, **kwargs):
"""Get HSL data and return it."""
fetcher = HSLFetcher()
fetcherThread = threading.Thread(target=fetcher.fetch_if_needed, args=[])
fetcherThread.setDaemon(False)
fetcherThread.start()
data = HSLDataModel.objects.all()
if len(data) < 1:
return HttpResponse(
'{"error" : "Could not find timetables from database."}',
status=500)
return HttpResponse(data[len(data) - 1].data, status=200)
Binary file not shown.
+137 -70
View File
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-09-27 19:01+0300\n"
"POT-Creation-Date: 2017-09-28 23:40+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -33,7 +33,7 @@ msgstr "External website"
msgid "Sössö articles"
msgstr "Sössö articles"
#: infoscreen/models.py:199
#: infoscreen/models.py:199 webapp/models.py:70
msgid "Events"
msgstr "Events"
@@ -81,10 +81,8 @@ msgid "Create new item"
msgstr "Create new item"
#: infoscreen/templates/infoscreen_admin.html:50
#, fuzzy
#| msgid "Create new item"
msgid "Create a new item by type"
msgstr "Create new item"
msgstr "Create a new item by type"
#: infoscreen/templates/infoscreen_admin.html:53
msgid "Item type"
@@ -169,8 +167,8 @@ msgstr "Select rotation to edit"
msgid "id"
msgstr "id"
#: infoscreen/templates/infoscreen_admin.html:141 webapp/models.py:60
#: webapp/models.py:94 webapp/models.py:107
#: infoscreen/templates/infoscreen_admin.html:141 webapp/models.py:91
#: webapp/models.py:125 webapp/models.py:138
msgid "Name"
msgstr "Name"
@@ -184,12 +182,12 @@ msgid "Language"
msgstr "Language"
#: infoscreen/templates/infoscreen_admin.html:161
#: members/templates/settings.html:20 sikweb/base.py:220
#: members/templates/settings.html:20 sikweb/base.py:221
msgid "Finnish"
msgstr "Finnish"
#: infoscreen/templates/infoscreen_admin.html:162
#: members/templates/settings.html:21 sikweb/base.py:221
#: members/templates/settings.html:21 sikweb/base.py:222
msgid "English"
msgstr "English"
@@ -212,7 +210,7 @@ msgstr "First name"
msgid "Last name"
msgstr "Last name"
#: members/models.py:16 webapp/models.py:95 webapp/models.py:108
#: members/models.py:16 webapp/models.py:126 webapp/models.py:139
msgid "Email"
msgstr "Email"
@@ -220,7 +218,7 @@ msgstr "Email"
msgid "Place of residence"
msgstr "Place of residence"
#: members/models.py:19 members/models.py:60
#: members/models.py:19 members/models.py:70
#: members/templates/member_add_many.html:35
msgid "AYY"
msgstr "AYY"
@@ -229,27 +227,27 @@ msgstr "AYY"
msgid "JAS"
msgstr "JAS"
#: members/models.py:46
#: members/models.py:51
msgid "Submitted"
msgstr "Submitted"
#: members/models.py:58
#: members/models.py:68
msgid "Date"
msgstr "Date"
#: members/models.py:59
#: members/models.py:69
msgid "Source"
msgstr "Source"
#: members/models.py:61
#: members/models.py:71
msgid "Cash"
msgstr "Cash"
#: members/models.py:62 members/templates/member_add_many.html:36
#: members/models.py:72 members/templates/member_add_many.html:36
msgid "Bank transfer"
msgstr "Bank transfer"
#: members/models.py:86
#: members/models.py:96
msgid "Created"
msgstr "Created"
@@ -453,130 +451,190 @@ msgstr "Payment events"
msgid "Payments in register:"
msgstr "Member register"
#: members/views/applications.py:49 members/views/applications.py:96
#: members/views/applications.py:124
#: members/views/applications.py:51 members/views/applications.py:100
#: members/views/applications.py:129
msgid "No application id specified"
msgstr "No application id specified"
#: members/views/applications.py:77
#: members/views/applications.py:80
msgid "Successfully accepted application"
msgstr "Successfully accepted application"
#: members/views/applications.py:84
#: members/views/applications.py:87
msgid "Could not accept application object"
msgstr "Could not accept application object"
#: members/views/applications.py:100
#: members/views/applications.py:104
msgid "Successfully deleted application"
msgstr "Successfully deleted application"
#: members/views/applications.py:112
#: members/views/applications.py:116
msgid "Could not delete application object"
msgstr "Could not delete application object"
#: members/views/members.py:71 members/views/members.py:164
#: members/views/members.py:190
#: members/views/members.py:74 members/views/members.py:172
#: members/views/members.py:199
msgid "No member id specified"
msgstr "No member id specified"
#: members/views/members.py:106
#: members/views/members.py:111
msgid "Failed to import members"
msgstr "Failed to import members"
#: members/views/members.py:119
#: members/views/members.py:125
msgid "Successfully added member"
msgstr "Successfully added member"
#: members/views/members.py:144
#: members/views/members.py:151
msgid "Successfully updated member"
msgstr "Successfully updated member"
#: members/views/members.py:152
#: members/views/members.py:159
msgid "Could not update member object"
msgstr "Could not update member object"
#: members/views/members.py:168
#: members/views/members.py:176
msgid "Successfully deleted member"
msgstr "Successfully deleted member"
#: members/views/members.py:179
#: members/views/members.py:187
msgid "Could not delete member object"
msgstr "Could not delete member object"
#: members/views/payments.py:67
#: members/views/payments.py:70
msgid "Successfully added payment for member"
msgstr "Successfully added payment for member"
#: members/views/payments.py:85 members/views/payments.py:103
#: members/views/payments.py:122
#: members/views/payments.py:89 members/views/payments.py:108
#: members/views/payments.py:128
msgid "No payment id specified"
msgstr "No payment id specified"
#: members/views/payments.py:127
#: members/views/payments.py:133
msgid "Successfully deleted payment"
msgstr "Successfully deleted payment"
#: members/views/payments.py:137
#: members/views/payments.py:143
msgid "Could not delete payment object"
msgstr "Could not delete payment object"
#: members/views/payments.py:156
#: members/views/payments.py:163
msgid "Successfully updated payment"
msgstr "Successfully updated payment"
#: members/views/payments.py:163
#: members/views/payments.py:170
msgid "Could not update payment object"
msgstr "Could not update payment object"
#: members/views/utils.py:113
#: members/views/utils.py:115
msgid "Missing \"textfield\" POST request field"
msgstr "Missing \"textfield\" POST request field"
#: templates/admin/base_site.html:43
msgid "Go"
msgstr ""
#: templates/footer.html:7
msgid "Copyright Aalto-yliopiston Sähköinsinöörikilta ry"
msgstr "Copyright Aalto-yliopiston Sähköinsinöörikilta ry"
#: webapp/models.py:61
#: webapp/models.py:15
msgid "Webapp"
msgstr ""
#: webapp/models.py:26
msgid "Tag"
msgstr ""
#: webapp/models.py:27
msgid "Tags"
msgstr ""
#: webapp/models.py:30
msgid "Tag: {}"
msgstr ""
#: webapp/models.py:50
msgid "Feed: {}"
msgstr ""
#: webapp/models.py:53
msgid "Feed"
msgstr ""
#: webapp/models.py:54
msgid "Feeds"
msgstr ""
#: webapp/models.py:66
#, fuzzy
#| msgid "Events"
msgid "Event: {}"
msgstr "Events"
#: webapp/models.py:69
#, fuzzy
#| msgid "Events"
msgid "Event"
msgstr "Events"
#: webapp/models.py:81
msgid "Registration: {}"
msgstr ""
#: webapp/models.py:84
#, fuzzy
#| msgid "Rotation"
msgid "Registration"
msgstr "Rotation"
#: webapp/models.py:85
#, fuzzy
#| msgid "Rotations"
msgid "Registrations"
msgstr "Rotations"
#: webapp/models.py:92
#, fuzzy
#| msgid "Add member"
msgid "Board member"
msgstr "Add member"
#: webapp/models.py:67
#: webapp/models.py:98
#, fuzzy
#| msgid "Duration"
msgid "Description"
msgstr "Duration"
#: webapp/models.py:68
#: webapp/models.py:99
msgid "Summary"
msgstr ""
#: webapp/models.py:96
#: webapp/models.py:127
msgid "Message"
msgstr ""
#: webapp/models.py:109
#: webapp/models.py:140
msgid "Year"
msgstr ""
#: webapp/models.py:123
#: webapp/models.py:154
msgid "Role"
msgstr ""
#: webapp/models.py:125
#: webapp/models.py:156
msgid "Start date"
msgstr ""
#: webapp/models.py:126
#: webapp/models.py:157
msgid "End date"
msgstr ""
#: webapp/models.py:136
#: webapp/models.py:167
msgid "Official"
msgstr ""
#: webapp/models.py:138
#: webapp/models.py:169
msgid "Phone number"
msgstr ""
@@ -588,6 +646,30 @@ msgstr "SIK Admin"
msgid "Aalto-yliopiston Sähköinsinöörikilta ry"
msgstr "Aalto-yliopiston Sähköinsinöörikilta ry"
#: webapp/templates/contact.html:7 webapp/templates/navigation.html:32
msgid "Contact"
msgstr "Contact"
#: webapp/templates/event_calendar.html:7 webapp/templates/navigation.html:29
msgid "Event calendar"
msgstr "Event calendar"
#: webapp/templates/freshmen.html:7 webapp/templates/navigation.html:16
msgid "Freshmen"
msgstr "Freshmen"
#: webapp/templates/guild.html:7
msgid "Kilta"
msgstr "Guild"
#: webapp/templates/international.html:7 webapp/templates/navigation.html:30
msgid "International"
msgstr "International"
#: webapp/templates/jobs.html:7 webapp/templates/navigation.html:20
msgid "Jobs"
msgstr "Jobs"
#: webapp/templates/login.html:25 webapp/templates/login.html:27
msgid "Username"
msgstr "Username"
@@ -612,34 +694,14 @@ msgstr "Admin tools"
msgid "Guild"
msgstr "Guild"
#: webapp/templates/navigation.html:16
msgid "Freshmen"
msgstr "Freshmen"
#: webapp/templates/navigation.html:18
msgid "Corporate"
msgstr "Corporate"
#: webapp/templates/navigation.html:20
msgid "Jobs"
msgstr "Jobs"
#: webapp/templates/navigation.html:29
msgid "Event calendar"
msgstr "Event calendar"
#: webapp/templates/navigation.html:30
msgid "International"
msgstr "International"
#: webapp/templates/navigation.html:31
#: webapp/templates/navigation.html:31 webapp/templates/sosso.html:7
msgid "Sössö"
msgstr "Sössö"
#: webapp/templates/navigation.html:32
msgid "Contact"
msgstr "Contact"
#: webapp/templates/ohlhafv.html:8
msgid "Ohlhafv"
msgstr "Ohlhafv"
@@ -656,6 +718,11 @@ msgstr "All challenges"
msgid "Total challenges:"
msgstr "Total challenges:"
#, fuzzy
#~| msgid "Language"
#~ msgid "language"
#~ msgstr "Language"
#~ msgid "Successfully imported multiple members"
#~ msgstr "Successfully imported multiple members"
Binary file not shown.
+126 -67
View File
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-09-27 19:01+0300\n"
"POT-Creation-Date: 2017-09-28 23:40+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -34,7 +34,7 @@ msgstr "Ulkoinen verkkosivu"
msgid "Sössö articles"
msgstr "Sössön artikkelit"
#: infoscreen/models.py:199
#: infoscreen/models.py:199 webapp/models.py:70
msgid "Events"
msgstr "Tapahtumat"
@@ -168,8 +168,8 @@ msgstr "Valitse muokattava rotaatio"
msgid "id"
msgstr "id"
#: infoscreen/templates/infoscreen_admin.html:141 webapp/models.py:60
#: webapp/models.py:94 webapp/models.py:107
#: infoscreen/templates/infoscreen_admin.html:141 webapp/models.py:91
#: webapp/models.py:125 webapp/models.py:138
msgid "Name"
msgstr "Nimi"
@@ -183,12 +183,12 @@ msgid "Language"
msgstr "Kieli"
#: infoscreen/templates/infoscreen_admin.html:161
#: members/templates/settings.html:20 sikweb/base.py:220
#: members/templates/settings.html:20 sikweb/base.py:221
msgid "Finnish"
msgstr "suomi"
#: infoscreen/templates/infoscreen_admin.html:162
#: members/templates/settings.html:21 sikweb/base.py:221
#: members/templates/settings.html:21 sikweb/base.py:222
msgid "English"
msgstr "englanti"
@@ -209,7 +209,7 @@ msgstr "Etunimi"
msgid "Last name"
msgstr "Sukunimi"
#: members/models.py:16 webapp/models.py:95 webapp/models.py:108
#: members/models.py:16 webapp/models.py:126 webapp/models.py:139
msgid "Email"
msgstr "Sähköposti"
@@ -217,7 +217,7 @@ msgstr "Sähköposti"
msgid "Place of residence"
msgstr "Asuinpaikka"
#: members/models.py:19 members/models.py:60
#: members/models.py:19 members/models.py:70
#: members/templates/member_add_many.html:35
msgid "AYY"
msgstr "AYY"
@@ -226,27 +226,27 @@ msgstr "AYY"
msgid "JAS"
msgstr "JAS"
#: members/models.py:46
#: members/models.py:51
msgid "Submitted"
msgstr "Lisätty"
#: members/models.py:58
#: members/models.py:68
msgid "Date"
msgstr "Päivämäärä"
#: members/models.py:59
#: members/models.py:69
msgid "Source"
msgstr "Lähde"
#: members/models.py:61
#: members/models.py:71
msgid "Cash"
msgstr "Käteinen"
#: members/models.py:62 members/templates/member_add_many.html:36
#: members/models.py:72 members/templates/member_add_many.html:36
msgid "Bank transfer"
msgstr "Tilisiirto"
#: members/models.py:86
#: members/models.py:96
msgid "Created"
msgstr "Lisätty"
@@ -443,126 +443,178 @@ msgstr "Maksutapahtumat"
msgid "Payments in register:"
msgstr "Maksutapahtumia:"
#: members/views/applications.py:49 members/views/applications.py:96
#: members/views/applications.py:124
#: members/views/applications.py:51 members/views/applications.py:100
#: members/views/applications.py:129
msgid "No application id specified"
msgstr "Hakemuksen ID ei määritelty"
#: members/views/applications.py:77
#: members/views/applications.py:80
msgid "Successfully accepted application"
msgstr "Onnistuneesti hyväksyttiin hakemus"
#: members/views/applications.py:84
#: members/views/applications.py:87
msgid "Could not accept application object"
msgstr "Hakemusobjektia ei voitu hyväksyä"
#: members/views/applications.py:100
#: members/views/applications.py:104
msgid "Successfully deleted application"
msgstr "Onnistuneesti poistettiin hakemus"
#: members/views/applications.py:112
#: members/views/applications.py:116
msgid "Could not delete application object"
msgstr "Hakemusobjektia ei voitu poistaa"
#: members/views/members.py:71 members/views/members.py:164
#: members/views/members.py:190
#: members/views/members.py:74 members/views/members.py:172
#: members/views/members.py:199
msgid "No member id specified"
msgstr "Jäsenen ID ei määritelty"
#: members/views/members.py:106
#: members/views/members.py:111
msgid "Failed to import members"
msgstr "Jäsenten tuonti epäonnistui"
#: members/views/members.py:119
#: members/views/members.py:125
msgid "Successfully added member"
msgstr "Onnistuneesti lisättiin jäsen"
#: members/views/members.py:144
#: members/views/members.py:151
msgid "Successfully updated member"
msgstr "Onnistuneesti päivitettiin jäsen"
#: members/views/members.py:152
#: members/views/members.py:159
msgid "Could not update member object"
msgstr "Jäsenobjektia ei voitu päivittää"
#: members/views/members.py:168
#: members/views/members.py:176
msgid "Successfully deleted member"
msgstr "Onnistuneesti poistettiin jäsen"
#: members/views/members.py:179
#: members/views/members.py:187
msgid "Could not delete member object"
msgstr "Jäsenobjektia ei voitu poistaa"
#: members/views/payments.py:67
#: members/views/payments.py:70
msgid "Successfully added payment for member"
msgstr "Onnistuneesti lisättiin maksutapahtuma jäsenelle"
#: members/views/payments.py:85 members/views/payments.py:103
#: members/views/payments.py:122
#: members/views/payments.py:89 members/views/payments.py:108
#: members/views/payments.py:128
msgid "No payment id specified"
msgstr "Maksutapahtuman ID ei määritelty"
#: members/views/payments.py:127
#: members/views/payments.py:133
msgid "Successfully deleted payment"
msgstr "Onnistuneesti poistettiin maksutapahtuma"
#: members/views/payments.py:137
#: members/views/payments.py:143
msgid "Could not delete payment object"
msgstr "Maksutapahtumaobjektia ei voitu poistaa"
#: members/views/payments.py:156
#: members/views/payments.py:163
msgid "Successfully updated payment"
msgstr "Onnistuneesti päivitettiin maksutapahtuma"
#: members/views/payments.py:163
#: members/views/payments.py:170
msgid "Could not update payment object"
msgstr "Maksutapahtumaobjektia ei voitu päivittää"
#: members/views/utils.py:113
#: members/views/utils.py:115
msgid "Missing \"textfield\" POST request field"
msgstr "Puuttuva \"textfield\" POST-kenttä"
#: templates/admin/base_site.html:43
msgid "Go"
msgstr "Vaihda"
#: templates/footer.html:7
msgid "Copyright Aalto-yliopiston Sähköinsinöörikilta ry"
msgstr "Copyright Aalto-yliopiston Sähköinsinöörikilta ry"
#: webapp/models.py:61
#: webapp/models.py:15
msgid "Webapp"
msgstr "Nettisivut"
#: webapp/models.py:26
msgid "Tag"
msgstr "Tunniste"
#: webapp/models.py:27
msgid "Tags"
msgstr "Tunnisteet"
#: webapp/models.py:30
msgid "Tag: {}"
msgstr "Tunniste: {}"
#: webapp/models.py:50
msgid "Feed: {}"
msgstr "Uutinen: {}"
#: webapp/models.py:53
msgid "Feed"
msgstr "Uutinen"
#: webapp/models.py:54
msgid "Feeds"
msgstr "Uutiset"
#: webapp/models.py:66
msgid "Event: {}"
msgstr "Tapahtuma: {}"
#: webapp/models.py:69
msgid "Event"
msgstr "Tapahtuma"
#: webapp/models.py:81
msgid "Registration: {}"
msgstr "Registration: {}"
#: webapp/models.py:84
msgid "Registration"
msgstr "Ilmoittautuminen"
#: webapp/models.py:85
msgid "Registrations"
msgstr "Ilmoittautumiset"
#: webapp/models.py:92
msgid "Board member"
msgstr "Hallituksen jäsen"
#: webapp/models.py:67
#: webapp/models.py:98
msgid "Description"
msgstr "Kuvaus"
#: webapp/models.py:68
#: webapp/models.py:99
msgid "Summary"
msgstr "Tiivistelmä"
#: webapp/models.py:96
#: webapp/models.py:127
msgid "Message"
msgstr "Viesti"
#: webapp/models.py:109
#: webapp/models.py:140
msgid "Year"
msgstr "Vuosi"
#: webapp/models.py:123
#: webapp/models.py:154
msgid "Role"
msgstr "Rooli"
#: webapp/models.py:125
#: webapp/models.py:156
msgid "Start date"
msgstr "Alkupäivämäärä"
#: webapp/models.py:126
#: webapp/models.py:157
msgid "End date"
msgstr "Loppupäivämäärä"
#: webapp/models.py:136
#: webapp/models.py:167
msgid "Official"
msgstr "Toimihenkilö"
#: webapp/models.py:138
#: webapp/models.py:169
msgid "Phone number"
msgstr "Puhelinnumero"
@@ -574,6 +626,30 @@ msgstr "SIK Hallintapaneeli"
msgid "Aalto-yliopiston Sähköinsinöörikilta ry"
msgstr "Aalto-yliopiston Sähköinsinöörikilta ry"
#: webapp/templates/contact.html:7 webapp/templates/navigation.html:32
msgid "Contact"
msgstr "Yhteystiedot"
#: webapp/templates/event_calendar.html:7 webapp/templates/navigation.html:29
msgid "Event calendar"
msgstr "Tapahtumakalenteri"
#: webapp/templates/freshmen.html:7 webapp/templates/navigation.html:16
msgid "Freshmen"
msgstr "Fuksit"
#: webapp/templates/guild.html:7
msgid "Kilta"
msgstr ""
#: webapp/templates/international.html:7 webapp/templates/navigation.html:30
msgid "International"
msgstr "International"
#: webapp/templates/jobs.html:7 webapp/templates/navigation.html:20
msgid "Jobs"
msgstr "Työpaikat"
#: webapp/templates/login.html:25 webapp/templates/login.html:27
msgid "Username"
msgstr "Käyttäjänimi"
@@ -598,34 +674,14 @@ msgstr "Hallintatyökalut"
msgid "Guild"
msgstr "Kilta"
#: webapp/templates/navigation.html:16
msgid "Freshmen"
msgstr "Fuksit"
#: webapp/templates/navigation.html:18
msgid "Corporate"
msgstr "Yritys"
#: webapp/templates/navigation.html:20
msgid "Jobs"
msgstr "Työpaikat"
#: webapp/templates/navigation.html:29
msgid "Event calendar"
msgstr "Tapahtumakalenteri"
#: webapp/templates/navigation.html:30
msgid "International"
msgstr "International"
#: webapp/templates/navigation.html:31
#: webapp/templates/navigation.html:31 webapp/templates/sosso.html:7
msgid "Sössö"
msgstr "Sössö"
#: webapp/templates/navigation.html:32
msgid "Contact"
msgstr "Yhteystiedot"
#: webapp/templates/ohlhafv.html:8
msgid "Ohlhafv"
msgstr "Øhlhäfv"
@@ -641,3 +697,6 @@ msgstr "Kaikki haasteet"
#: webapp/templates/ohlhafv_list.html:15
msgid "Total challenges:"
msgstr "Haasteita yhteensä:"
#~ msgid "language"
#~ msgstr "Kieli"
@@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2017-09-27 16:18
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('members', '0017_auto_20170926_1316'),
]
operations = [
migrations.AlterModelOptions(
name='member',
options={'permissions': (('check_by_email', 'Can check if user exists by email'), ('read_member', 'Can see member in list'))},
),
migrations.AlterModelOptions(
name='payment',
options={'permissions': (('read_payment', 'Can see payment in list'),)},
),
migrations.AlterModelOptions(
name='request',
options={'permissions': (('read_application', 'Can see member application in list'),)},
),
]
+11
View File
@@ -43,6 +43,11 @@ class BaseMember(models.Model):
class Request(BaseMember):
"""Member request model represents one member request."""
class Meta:
permissions = (
('read_application', 'Can see member application in list'),
)
submitted = models.DateTimeField(_('Submitted'), default=timezone.now)
def to_member(self):
@@ -55,6 +60,11 @@ class Request(BaseMember):
class Payment(models.Model):
"""Payment model representing one payment event."""
class Meta:
permissions = (
('read_payment', 'Can see payment in list'),
)
date = models.DateTimeField(_('Date'), default=timezone.now)
source = models.CharField(_('Source'), choices=[
('AYY', _('AYY')),
@@ -88,6 +98,7 @@ class Member(BaseMember):
class Meta:
permissions = (
('check_by_email', 'Can check if user exists by email'),
('read_member', 'Can see member in list'),
)
def last_paid(self):
+11 -6
View File
@@ -1,5 +1,5 @@
from django.shortcuts import render
from django.contrib.auth.decorators import permission_required
from django.contrib.auth.decorators import permission_required, login_required
from django.views.decorators.http import require_http_methods
from django.views.decorators.csrf import ensure_csrf_cookie
from django.http import HttpResponse, HttpResponseRedirect
@@ -18,7 +18,8 @@ from members.forms import ApplicationForm
@ensure_csrf_cookie
@require_http_methods(["GET"])
@permission_required('members.change_member', login_url='/login')
@login_required(login_url='/login')
@permission_required('members.read_application', raise_exception=True)
def application_list(request, *args, **kwargs):
"""List member applications not yet processed."""
applications = Request.objects.all()
@@ -40,7 +41,8 @@ def application_list(request, *args, **kwargs):
@ensure_csrf_cookie
@require_http_methods(["GET"])
@permission_required('members.change_member', login_url='/login')
@login_required(login_url='/login')
@permission_required('members.change_request', raise_exception=True)
def application_edit(request, *args, **kwargs):
"""Edit member request information."""
i = kwargs.pop('index', None)
@@ -58,7 +60,8 @@ def application_edit(request, *args, **kwargs):
@ensure_csrf_cookie
@require_http_methods(["POST"])
@permission_required('members.change_member', login_url='/login')
@login_required(login_url='/login')
@permission_required('members.add_member', raise_exception=True)
def application_accept(request, *args, **kwargs):
"""Accept application."""
form = ApplicationForm(request.POST)
@@ -86,7 +89,8 @@ def application_accept(request, *args, **kwargs):
@ensure_csrf_cookie
@require_http_methods(["POST"])
@permission_required('members.change_member', login_url='/login')
@login_required(login_url='/login')
@permission_required('members.delete_request', raise_exception=True)
def application_delete(request, *args, **kwargs):
"""Delete member application."""
try:
@@ -114,7 +118,8 @@ def application_delete(request, *args, **kwargs):
@ensure_csrf_cookie
@require_http_methods(["GET"])
@permission_required('members.change_member', login_url='/login')
@login_required(login_url='/login')
@permission_required('members.delete_request', raise_exception=True)
def application_delete_confirm(request, *args, **kwargs):
"""Confirm application deletion."""
i = kwargs.pop('index', None)
+19 -10
View File
@@ -1,5 +1,5 @@
from django.shortcuts import render
from django.contrib.auth.decorators import permission_required
from django.contrib.auth.decorators import permission_required, login_required
from django.utils.decorators import method_decorator
from django.views.decorators.http import require_http_methods
from django.views.decorators.csrf import ensure_csrf_cookie
@@ -27,7 +27,8 @@ from members.views.utils import *
@ensure_csrf_cookie
@require_http_methods(["GET"])
@permission_required('members.change_member', login_url='/login')
@login_required(login_url='/login')
@permission_required('members.read_member', raise_exception=True)
def member_list(request, *args, **kwargs):
"""Render members list."""
search = request.GET.get('q', None)
@@ -53,7 +54,8 @@ def member_list(request, *args, **kwargs):
@ensure_csrf_cookie
@require_http_methods(["GET"])
@permission_required('members.change_member', login_url='/login')
@login_required(login_url='/login')
@permission_required('members.add_member', raise_exception=True)
def member_add(request, *args, **kwargs):
"""Render add member page."""
form = MemberForm()
@@ -62,7 +64,8 @@ def member_add(request, *args, **kwargs):
@ensure_csrf_cookie
@require_http_methods(["GET"])
@permission_required('members.change_member', login_url='/login')
@login_required(login_url='/login')
@permission_required('members.delete_member', raise_exception=True)
def member_delete_confirm(request, *args, **kwargs):
"""Render member deletion confirmation page."""
i = kwargs.pop('index', None)
@@ -78,7 +81,8 @@ def member_delete_confirm(request, *args, **kwargs):
@ensure_csrf_cookie
@require_http_methods(["GET"])
@permission_required('members.change_member', login_url='/login')
@login_required(login_url='/login')
@permission_required('members.add_member', raise_exception=True)
def member_add_many(request, *args, **kwargs):
"""Render add multiple members page."""
return render(request, 'member_add_many.html', {})
@@ -86,7 +90,8 @@ def member_add_many(request, *args, **kwargs):
@ensure_csrf_cookie
@require_http_methods(["POST"])
@permission_required('members.change_member', login_url='/login')
@login_required(login_url='/login')
@permission_required('members.add_member', raise_exception=True)
def add_many_confirm(request, *args, **kwargs):
models = request.session['models']
@@ -108,7 +113,8 @@ def add_many_confirm(request, *args, **kwargs):
@ensure_csrf_cookie
@require_http_methods(["POST"])
@permission_required('members.change_member', login_url='/login')
@login_required(login_url='/login')
@permission_required('members.add_member', raise_exception=True)
def member_submit(request, *args, **kwargs):
"""Add member based on data gained from member form."""
form = MemberForm(request.POST)
@@ -128,7 +134,8 @@ def member_submit(request, *args, **kwargs):
@ensure_csrf_cookie
@require_http_methods(["POST"])
@permission_required('members.change_member', login_url='/login')
@login_required(login_url='/login')
@permission_required('members.change_member', raise_exception=True)
def member_update(request, *args, **kwargs):
"""Update member information."""
form = MemberForm(request.POST)
@@ -154,7 +161,8 @@ def member_update(request, *args, **kwargs):
@ensure_csrf_cookie
@require_http_methods(["POST"])
@permission_required('members.change_member', login_url='/login')
@login_required(login_url='/login')
@permission_required('members.delete_member', raise_exception=True)
def member_delete(request, *args, **kwargs):
"""Delete member."""
try:
@@ -181,7 +189,8 @@ def member_delete(request, *args, **kwargs):
@ensure_csrf_cookie
@require_http_methods(["GET"])
@permission_required('members.change_member', login_url='/login')
@login_required(login_url='/login')
@permission_required('members.change_member', raise_exception=True)
def member_edit(request, *args, **kwargs):
"""Edit member information."""
i = kwargs.pop('index', None)
+15 -8
View File
@@ -1,5 +1,5 @@
from django.shortcuts import render
from django.contrib.auth.decorators import permission_required
from django.contrib.auth.decorators import permission_required, login_required
from django.views.decorators.http import require_http_methods
from django.views.decorators.csrf import ensure_csrf_cookie
from django.http import HttpResponse, HttpResponseRedirect
@@ -18,7 +18,8 @@ from members.forms import PaymentForm
@ensure_csrf_cookie
@require_http_methods(["GET"])
@permission_required('members.change_member', login_url='/login')
@login_required(login_url='/login')
@permission_required('members.read_payment', raise_exception=True)
def payment_list(request, *args, **kwargs):
"""Render list of payments."""
search = request.GET.get('q', None)
@@ -45,7 +46,8 @@ def payment_list(request, *args, **kwargs):
@ensure_csrf_cookie
@require_http_methods(["GET"])
@permission_required('members.change_member', login_url='/login')
@login_required(login_url='/login')
@permission_required('members.add_payment', raise_exception=True)
def payment_add(request, *args, **kwargs):
"""Render add payment form."""
form = PaymentForm()
@@ -54,7 +56,8 @@ def payment_add(request, *args, **kwargs):
@ensure_csrf_cookie
@require_http_methods(["POST"])
@permission_required('members.change_member', login_url='/login')
@login_required(login_url='/login')
@permission_required('members.add_payment', raise_exception=True)
def payment_submit(request, *args, **kwargs):
"""Submit payment."""
form = PaymentForm(request.POST)
@@ -75,7 +78,8 @@ def payment_submit(request, *args, **kwargs):
@ensure_csrf_cookie
@require_http_methods(["GET"])
@permission_required('members.change_member', login_url='/login')
@login_required(login_url='/login')
@permission_required('members.change_payment', raise_exception=True)
def payment_edit(request, *args, **kwargs):
"""Edit payment."""
i = kwargs.pop('index', None)
@@ -93,7 +97,8 @@ def payment_edit(request, *args, **kwargs):
@ensure_csrf_cookie
@require_http_methods(["GET"])
@permission_required('members.change_member', login_url='/login')
@login_required(login_url='/login')
@permission_required('members.delete_payment', raise_exception=True)
def payment_delete_confirm(request, *args, **kwargs):
"""Render payment delete confirmation page."""
i = kwargs.pop('index', None)
@@ -111,7 +116,8 @@ def payment_delete_confirm(request, *args, **kwargs):
@ensure_csrf_cookie
@require_http_methods(["POST"])
@permission_required('members.change_member', login_url='/login')
@login_required(login_url='/login')
@permission_required('members.delete_payment', raise_exception=True)
def payment_delete(request, *args, **kwargs):
"""Delete payment."""
try:
@@ -139,7 +145,8 @@ def payment_delete(request, *args, **kwargs):
@ensure_csrf_cookie
@require_http_methods(["POST"])
@permission_required('members.change_member', login_url='/login')
@login_required(login_url='/login')
@permission_required('members.change_payment', raise_exception=True)
def payment_update(request, *args, **kwargs):
"""Update payment information."""
form = PaymentForm(request.POST)
+6 -4
View File
@@ -1,5 +1,5 @@
from django.shortcuts import render
from django.contrib.auth.decorators import permission_required
from django.contrib.auth.decorators import permission_required, login_required
from django.views.decorators.http import require_http_methods
from django.views.decorators.csrf import ensure_csrf_cookie
from django.http import HttpResponse, HttpResponseRedirect
@@ -93,7 +93,8 @@ def convert_table_to_html(table, request):
@ensure_csrf_cookie
@require_http_methods(["GET"])
@permission_required('members.change_member', login_url='/login')
@login_required(login_url='/login')
@permission_required('members.change_member', raise_exception=True)
def settings_page(request, *args, **kwargs):
"""Render member app settings page."""
return render(request, 'settings.html', {})
@@ -101,7 +102,8 @@ def settings_page(request, *args, **kwargs):
@ensure_csrf_cookie
@require_http_methods(["POST"])
@permission_required('members.change_member', login_url='/login')
@login_required(login_url='/login')
@permission_required(['members.change_member', 'members.change_payment'], raise_exception=True)
def import_csv(request, *args, **kwargs):
"""Get csv data imported to page and create members based on that."""
try:
@@ -145,7 +147,7 @@ def import_csv(request, *args, **kwargs):
@ensure_csrf_cookie
@require_http_methods(["GET"])
@permission_required('members.change_member', login_url='/login')
@permission_required('members.read_member', login_url='/login', raise_exception=True)
def export_csv(request, *args, **kwargs):
"""Export members as csv."""
response = HttpResponse()
+1
View File
@@ -28,3 +28,4 @@ django-phonenumber-field==1.3.0
paho-mqtt==1.3.0
django-autocomplete-light==3.2.10
six==1.10.0
django-suit==0.2.25
+33
View File
@@ -64,6 +64,7 @@ LOGGING = {
INSTALLED_APPS = [
'modeltranslation', # has to be before admin for translation admin to work
'suit',
'dal',
'dal_select2',
'django.contrib.admin',
@@ -249,3 +250,35 @@ STATICFILES_DIRS = (
)
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
LOGIN_URL = '/login/'
LOGIN_REDIRECT_URL = '/admin'
SUIT_CONFIG = {
# header
'ADMIN_NAME': 'SIK Admin',
# 'HEADER_DATE_FORMAT': 'l, j. F Y',
# 'HEADER_TIME_FORMAT': 'H:i',
# forms
# 'SHOW_REQUIRED_ASTERISK': True, # Default True
# 'CONFIRM_UNSAVED_CHANGES': True, # Default True
# menu
# 'SEARCH_URL': '/admin/auth/user/',
# 'MENU_ICONS': {
# 'sites': 'icon-leaf',
# 'auth': 'icon-lock',
# },
# 'MENU_OPEN_FIRST_CHILD': True, # Default True
# 'MENU_EXCLUDE': ('auth.group',),
# 'MENU': (
# 'sites',
# {'app': 'auth', 'icon':'icon-lock', 'models': ('user', 'group')},
# {'label': 'Settings', 'icon':'icon-cog', 'models': ('auth.user', 'auth.group')},
# {'label': 'Support', 'icon':'icon-question-sign', 'url': '/support/'},
# ),
# misc
# 'LIST_PER_PAGE': 15
}
+17
View File
@@ -0,0 +1,17 @@
body {
font-size: 14px;
}
.header {
background: #003366;
padding-top: 1rem;
padding-bottom: 1rem;
}
.header #branding {
border-right: 0px;
}
.header .header-content.header-content-first {
border-left: 0px;
}
+74
View File
@@ -0,0 +1,74 @@
{% extends "admin/base.html" %}
{% load admin_static %}
{% load i18n %}
{# Additional <head> content here, some extra meta tags or favicon #}
{#{% block extrahead %}#}
{#{% endblock %}#}
{# Additional CSS includes #}
{% block extrastyle %}
<link rel="stylesheet" type="text/css" href="{% static 'css/sikadmin.css' %}" media="all">
{% endblock %}
{# Additional JS files in footer, right before </body> #}
{#{% block extrajs %}#}
{# <script type="text/javascript" src="{% static 'js/my_project.js' %}"></script>#}
{#{% endblock %}#}
{# Footer links (left side) #}
{#{% block footer_links %}#}
{# <a href="/docs/" class="icon"><i class="icon-question-sign"></i>Documentation</a>#}
{#{% endblock %}#}
{# Additional header content like notifications or language switcher #}
{% block header_content %}
{{ block.super }}
<div class="header-content">
<form action="{% url 'set_language' %}" method="post">{% csrf_token %}
<input name="next" type="hidden" value="{{ redirect_to }}" />
<select name="language" style="width: auto;">
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<option value="{{ language.code }}"{% if language.code == LANGUAGE_CODE %} selected="selected"{% endif %}>
{{ language.name_local }} ({{ language.code }})
</option>
{% endfor %}
</select>
<input class="btn btn-high" type="submit" value="{% trans 'Go' %}" style="vertical-align: top;"/>
</form>
<!-- First icon column -->
<!--
<div class="header-column icon">
<i class="icon-home"></i><br>
<i class="icon-cog"></i>
</div>
<div class="header-column" style="margin-right: 20px">
<a href="/" class="grey">Front-end</a><br>
<a href="" class="grey">One more link</a>
</div>
Second icon column
<div class="header-column icon">
<i class="icon-comment"></i>
</div>
<div class="header-column">
<a href="" class="grey">5 new messages</a>
</div>
-->
</div>
{% endblock %}
{# Footer branding name (center) #}
{#{% block footer_branding %}#}
{#{% endblock %}#}
{# Footer copyright (right side) #}
{#{% block copyright %}#}
{# Copyright &copy; 2013 Client<br>Developed by <a href="http://yoursite.com" target="_blank">YourName</a> #}
{#{% endblock %}#}
+5 -2
View File
@@ -2,17 +2,20 @@
from django.contrib import admin
from webapp.models import Official, Role
from webapp.models import Feed, Tag, BaseFeed, Event
from webapp.models import Feed, Tag, BaseFeed, Event, Registration
from webapp.models import KaehmyForm, KaehmyMessage
from webapp.models import CustomKaehmyRole, PresetKaehmyRole
from modeltranslation.admin import TranslationAdmin
from django.contrib.auth.models import Permission
# this is needed so that the models get registered for translation
import webapp.translation
admin.site.register(Permission)
admin.site.register(Feed, TranslationAdmin)
admin.site.register(Tag, TranslationAdmin)
admin.site.register(Event, TranslationAdmin)
admin.site.register(Registration, TranslationAdmin)
admin.site.register(Official)
admin.site.register(Role)
admin.site.register(KaehmyForm)
+54 -26
View File
@@ -9,31 +9,59 @@ class Command(BaseCommand):
This command MUST do nothing if already run.
'''
def create_infoscreen_moderator(self):
self.stdout.write("Creating infoscreen moderator group")
infoscreen_group, created = Group.objects.get_or_create(name="infoscreen moderators")
if not created:
self.stdout.write('The group "infoscreen moderators" already existed '
'and was not therefore created')
cts = ContentType.objects.filter(app_label='infoscreen')
permissions = Permission.objects.filter(content_type__in=cts)
infoscreen_group.permissions.add(*permissions)
def create_member_register_viewer(self):
self.stdout.write("Creating member register viewer group")
viewers_group, created = Group.objects.get_or_create(name="member register viewers")
if not created:
self.stdout.write('The group "member register viewers" already existed '
'and was not therefore created')
cts = ContentType.objects.filter(app_label='members')
members_permissions = Permission.objects.filter(content_type__in=cts, codename__contains='read')
viewers_group.permissions.add(*members_permissions)
def create_member_register_administrator(self):
self.stdout.write("Creating member register administrator group")
admins_group, created = Group.objects.get_or_create(name="member register administrators")
if not created:
self.stdout.write('The group "member register administrators" already existed '
'and was not therefore created')
cts = ContentType.objects.filter(app_label='members')
permissions = Permission.objects.filter(content_type__in=cts)
admins_group.permissions.add(*permissions)
def create_official(self):
self.stdout.write("Creating official group")
officials_group, created = Group.objects.get_or_create(name="officials")
if not created:
self.stdout.write('The group "officials" already existed '
'and was not therefore created')
cts = ContentType.objects.filter(app_label='webapp')
feed_permissions = Permission.objects.filter(content_type__in=cts, codename__contains='feed')
event_permissions = Permission.objects.filter(content_type__in=cts, codename__contains='event')
registration_permissions = Permission.objects.filter(content_type__in=cts, codename__contains='registration')
officials_group.permissions.add(*feed_permissions)
officials_group.permissions.add(*event_permissions)
officials_group.permissions.add(*registration_permissions)
def handle(self, *args, **options):
self.stdout.write("Creating sikadmin group")
sikadmin_group, created = Group.objects.get_or_create(name="sikadmin")
if not created:
self.stdout.write('The group "sikadmin" already existed'
'and was not therefore created')
self.stdout.write("Creating sikadmin permission")
# TODO Use some sikadmin native model when such exists
group_ctype = ContentType.objects.get_for_model(Group)
sikadmin_permission, created = Permission.objects.get_or_create(
codename='sikadmin',
content_type=group_ctype,
name='SIK Admin')
if not created:
self.stdout.write('The permission "sikadmin" already existed'
'and was not therefore created')
self.stdout.write("Giving sikadmin group permission to sikadmin")
if sikadmin_group.permissions.filter(id=sikadmin_permission.id).exists():
self.stdout.write("Permission already existed. skipping...")
else:
sikadmin_group.permissions.add(sikadmin_permission)
self.create_infoscreen_moderator()
self.create_member_register_viewer()
self.create_member_register_administrator()
self.create_official()
self.stdout.write("Initialization successful")
@@ -0,0 +1,41 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2017-09-28 20:31
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('webapp', '0014_auto_20170920_1807'),
]
operations = [
migrations.AlterModelOptions(
name='event',
options={'verbose_name': 'Event', 'verbose_name_plural': 'Events'},
),
migrations.AlterModelOptions(
name='feed',
options={'verbose_name': 'Feed', 'verbose_name_plural': 'Feeds'},
),
migrations.AlterModelOptions(
name='registration',
options={'verbose_name': 'Registration', 'verbose_name_plural': 'Registrations'},
),
migrations.AlterModelOptions(
name='tag',
options={'verbose_name': 'Tag', 'verbose_name_plural': 'Tags'},
),
migrations.AddField(
model_name='registration',
name='name_en',
field=models.CharField(max_length=255, null=True),
),
migrations.AddField(
model_name='registration',
name='name_fi',
field=models.CharField(max_length=255, null=True),
),
]
+31
View File
@@ -12,6 +12,9 @@ from phonenumber_field.modelfields import PhoneNumberField
from django.contrib.postgres.fields import JSONField
VERBOSE_NAME = _('Webapp')
class Tag(models.Model):
"""Model for tag."""
@@ -19,6 +22,13 @@ class Tag(models.Model):
name = models.CharField(max_length=127)
icon = models.ImageField()
class Meta:
verbose_name = _('Tag')
verbose_name_plural = _('Tags')
def __str__(self):
return _('Tag: {}').format(self.slug)
class BaseFeed(models.Model):
"""Model containing something showing on some info feed."""
@@ -36,6 +46,13 @@ class Feed(BaseFeed):
publish_time = models.DateTimeField(default=timezone.now)
autohide = models.DateTimeField(default=month_from_now)
def __str__(self):
return _('Feed: {}').format(self.title)
class Meta:
verbose_name = _('Feed')
verbose_name_plural = _('Feeds')
class Event(BaseFeed):
"""Model for event."""
@@ -45,6 +62,13 @@ class Event(BaseFeed):
registration = models.ForeignKey(
'Registration', on_delete=models.CASCADE, null=True)
def __str__(self):
return _('Event: {}').format(self.title)
class Meta:
verbose_name = _('Event')
verbose_name_plural = _('Events')
class Registration(models.Model):
"""Model for event registration."""
@@ -53,6 +77,13 @@ class Registration(models.Model):
email = models.EmailField()
options = JSONField()
def __str__(self):
return _('Registration: {}').format(self.name)
class Meta:
verbose_name = _('Registration')
verbose_name_plural = _('Registrations')
class BaseRole(models.Model):
"""Base model for occupations/roles."""
+8 -1
View File
@@ -1,7 +1,7 @@
"""Translation classes."""
from modeltranslation.translator import register, TranslationOptions
from webapp.models import BaseFeed, Feed, Tag, Event
from webapp.models import BaseFeed, Feed, Tag, Event, Registration
@register(BaseFeed)
@@ -30,3 +30,10 @@ class TagTranslationOptions(TranslationOptions):
"""Class for tag translation options."""
fields = ('name',)
@register(Registration)
class RegistrationTranslationOptions(TranslationOptions):
"""Class for registration translation options."""
fields = ('name',)
+4 -3
View File
@@ -5,7 +5,7 @@ from django.contrib.auth import login, logout, authenticate
from django.views.decorators.http import require_http_methods
from django.views.decorators.csrf import ensure_csrf_cookie
from django.http import HttpResponse, HttpResponseRedirect
from django.contrib.auth.decorators import permission_required
from django.contrib.auth.decorators import permission_required, login_required
from django.conf import settings
import logging
from webapp.models import OhlhafvChallenge
@@ -21,7 +21,8 @@ def main_index(request, *args, **kwargs):
@require_http_methods(["GET", "POST"])
@ensure_csrf_cookie
@permission_required('members.change_member', login_url='/login')
@login_required(login_url='/login')
@permission_required('members.change_member')
def admin_index(request, *args, **kwargs):
"""Render admin main page."""
return render(request, "admin_index.html", {})
@@ -50,7 +51,7 @@ def login_view(request, *args, **kwargs):
return render(request, "login.html", {})
@require_http_methods(["POST"])
@require_http_methods(["GET", "POST"])
def logout_view(request, *args, **kwargs):
"""Logout user and return to main page."""
logout(request)