Compare commits
102 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1fa1d0c019 | |||
| 4419f1cf2c | |||
| 6e74548206 | |||
| 5b9b4021d3 | |||
| 05279ae900 | |||
| 9b450f94a5 | |||
| 7ffce4e929 | |||
| ca8937d9f6 | |||
| 92f744f39c | |||
| 7c9a627d41 | |||
| a35b86af43 | |||
| 9651725bb3 | |||
| ac017bfb82 | |||
| f923511a72 | |||
| 78092ce734 | |||
| ae136aebae | |||
| 1eb5e7e10c | |||
| 74d0765eb2 | |||
| 1cab37dbcf | |||
| cf673c32c5 | |||
| a2e6a4754e | |||
| 6ccb1d01cf | |||
| cd708a469d | |||
| 831f15d0ff | |||
| ca73eba609 | |||
| fe46d57108 | |||
| 70e1835a4f | |||
| b7f17671d9 | |||
| 34659403a8 | |||
| 4fbf5fe0a4 | |||
| c6be0e6562 | |||
| 3623c7e9f4 | |||
| 298db5b78e | |||
| 1ca6de3090 | |||
| 07d0f2aa47 | |||
| 93e122b8a8 | |||
| 9678b663a0 | |||
| 992a2ec8e0 | |||
| b41bd41a54 | |||
| 30f59c36fb | |||
| f51d71e045 | |||
| 9c66238b82 | |||
| 2f0143a9ae | |||
| 45ff2c3757 | |||
| 321d45b628 | |||
| 2628d753f5 | |||
| a603e2dff8 | |||
| 96e05d908d | |||
| a5bf5668eb | |||
| 1ec5082faf | |||
| 6da5b97e19 | |||
| 7fd30e3eba | |||
| 3e9084ca1d | |||
| a28f82d31e | |||
| 04ecb8fc7e | |||
| 3e707e58a5 | |||
| 70d7f55996 | |||
| e408809e58 | |||
| 33fd4012f1 | |||
| 228938b695 | |||
| 72e91e3d62 | |||
| 3f6a719e9d | |||
| 490b99a848 | |||
| 0a899f5600 | |||
| 7825cc7293 | |||
| 8bb6e9e9a7 | |||
| 53c3acd39f | |||
| dd0254a08e | |||
| 9b53fb4bc0 | |||
| e17c3ad92c | |||
| 362d981532 | |||
| e12be3c2f6 | |||
| 3edae7f967 | |||
| 4d159b2793 | |||
| cb3b831f7a | |||
| acba330694 | |||
| eb22368055 | |||
| fac2f9b367 | |||
| 7319c32d73 | |||
| b3a484ce55 | |||
| 337b774074 | |||
| e70e598c57 | |||
| 5eef2f685c | |||
| d1953ef24c | |||
| ec4317d9e7 | |||
| cff84816fc | |||
| 7881a24eb1 | |||
| a0765ca18b | |||
| 913eb1cedf | |||
| 7035ebccca | |||
| 2031146fc7 | |||
| 35f30300b3 | |||
| 342f2862a5 | |||
| 3536ca5922 | |||
| 50ab7bc1f9 | |||
| 102d8f82d6 | |||
| f302c0a17d | |||
| a2b7086e9a | |||
| 704652c643 | |||
| 8741f6b113 | |||
| 9ffb79aa52 | |||
| a2551cc110 |
@@ -0,0 +1,32 @@
|
||||
.DS_Store
|
||||
.dockerignore
|
||||
.git/
|
||||
.husky/
|
||||
.venv/
|
||||
.vscode/
|
||||
collected_static/
|
||||
logs/
|
||||
!logs/README
|
||||
media/
|
||||
!media/REMOVE_ME
|
||||
misc/
|
||||
node_modules/
|
||||
scripts/
|
||||
.coverage
|
||||
.coveragerc
|
||||
.env*
|
||||
.eslintignore
|
||||
.eslintrc.json
|
||||
.gitignore
|
||||
.gitlab-ci.yml
|
||||
.python-version
|
||||
docker-compose.yml
|
||||
!manage.py
|
||||
package*.json
|
||||
!poetry.lock
|
||||
!production_entrypoint.sh
|
||||
pycodestyle.cfg
|
||||
!pyproject.toml
|
||||
pyright.json
|
||||
README.md
|
||||
stack-compose*.yml
|
||||
@@ -9,3 +9,5 @@ DB_PASSWD=postgres
|
||||
DB_HOST=db
|
||||
DB_PORT=5432
|
||||
EMAIL_API_KEY=
|
||||
GROUP_KEY=
|
||||
GOOGLE_CREDS_JSON='{}'
|
||||
|
||||
+1
-1
@@ -11,4 +11,4 @@ node_modules/
|
||||
.idea/
|
||||
*.code-workspace
|
||||
venv/
|
||||
.venv/
|
||||
.venv/
|
||||
+3
-3
@@ -21,7 +21,7 @@ audit:
|
||||
stage: audit
|
||||
needs: []
|
||||
before_script:
|
||||
- pip install poetry==1.1.4
|
||||
- pip install poetry==1.1.13
|
||||
- poetry config virtualenvs.create false
|
||||
- poetry install --no-interaction --no-ansi
|
||||
script:
|
||||
@@ -40,7 +40,7 @@ test:
|
||||
DATABASE_URL: "postgresql://postgres:postgres@postgres:5432/$POSTGRES_DB"
|
||||
DB_HOST: postgres
|
||||
before_script:
|
||||
- pip install poetry==1.1.4
|
||||
- pip install poetry==1.1.13
|
||||
- poetry config virtualenvs.create false
|
||||
- poetry install --no-interaction --no-ansi
|
||||
script:
|
||||
@@ -53,7 +53,7 @@ lint:py:
|
||||
stage: lint
|
||||
needs: []
|
||||
script:
|
||||
- pip install black==21.12b0
|
||||
- pip install black==22.3.0
|
||||
- black --check .
|
||||
|
||||
lint:js:
|
||||
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
PURPLE='\033[0;35m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
source "${VIRTUAL_ENV}/bin/activate"
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
printf "${PURPLE}Failed to find virtualenv. Skipping pre-commit hook.\n${NC}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
npm run lint
|
||||
+3
-3
@@ -2,10 +2,10 @@ FROM python:3.9-slim-buster as builder
|
||||
ENV PYTHONUNBUFFERED 1
|
||||
COPY . ./
|
||||
|
||||
ENV POETRY_VERSION=1.1.4
|
||||
ENV POETRY_VERSION=1.1.13
|
||||
|
||||
RUN pip install "poetry==$POETRY_VERSION"
|
||||
RUN poetry export > requirements.txt
|
||||
RUN poetry export --without-hashes > requirements.txt
|
||||
|
||||
FROM python:3.9-slim-buster as server
|
||||
|
||||
@@ -22,7 +22,7 @@ ENV PYTHONUNBUFFERED=1 \
|
||||
PIP_DEFAULT_TIMEOUT=100
|
||||
|
||||
RUN apt-get update && apt-get install --no-install-recommends -y build-essential
|
||||
RUN pip install -r requirements.txt
|
||||
RUN pip install --no-deps -r requirements.txt
|
||||
|
||||
RUN python manage.py collectstatic --noinput
|
||||
CMD ["sh", "-c", "./production_entrypoint.sh"]
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# Generated by Django 3.2.14 on 2022-08-01 19:13
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("infoscreen", "0007_lunchitem"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="infoinstance",
|
||||
name="id",
|
||||
field=models.AutoField(primary_key=True, serialize=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="infoitem",
|
||||
name="id",
|
||||
field=models.AutoField(primary_key=True, serialize=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="rotation",
|
||||
name="id",
|
||||
field=models.AutoField(primary_key=True, serialize=False),
|
||||
),
|
||||
]
|
||||
@@ -16,6 +16,7 @@ class InfoItem(models.Model):
|
||||
class __meta__:
|
||||
abstract = True
|
||||
|
||||
id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(max_length=255)
|
||||
# expire_date = None means never expiring item
|
||||
expire_date = models.DateTimeField(blank=True, null=True)
|
||||
@@ -316,6 +317,7 @@ class ExternalImageInfoItem(InfoItem):
|
||||
class InfoInstance(models.Model):
|
||||
"""Class for Info instance in Infoscreen."""
|
||||
|
||||
id = models.AutoField(primary_key=True)
|
||||
rotation = models.ForeignKey(
|
||||
"Rotation", related_name="instances", on_delete=models.CASCADE
|
||||
)
|
||||
@@ -356,6 +358,7 @@ class InfoInstance(models.Model):
|
||||
class Rotation(models.Model):
|
||||
"""Class for rotation model."""
|
||||
|
||||
id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(max_length=255)
|
||||
|
||||
def get_dict(self):
|
||||
@@ -388,6 +391,7 @@ class Rotation(models.Model):
|
||||
class ImageUploadForm(forms.Form):
|
||||
"""Form used to handle imageuploads to infoscreen app."""
|
||||
|
||||
id = models.AutoField(primary_key=True)
|
||||
name = forms.CharField()
|
||||
image = forms.ImageField()
|
||||
|
||||
@@ -395,5 +399,6 @@ class ImageUploadForm(forms.Form):
|
||||
class UploadFileForm(forms.Form):
|
||||
"""Form used for uploading file."""
|
||||
|
||||
id = models.AutoField(primary_key=True)
|
||||
name = forms.CharField()
|
||||
video = forms.FileField()
|
||||
|
||||
@@ -3,7 +3,7 @@ body {
|
||||
}
|
||||
|
||||
#header:after {
|
||||
content: " ";
|
||||
content: " ";
|
||||
display: block;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ body {
|
||||
.event {
|
||||
font-size: 100px;
|
||||
font-weight: bold;
|
||||
margin-left: 20px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
.event-col{
|
||||
padding-top:1vh;
|
||||
@@ -21,7 +21,7 @@ body {
|
||||
|
||||
.header-row{
|
||||
margin: 30px;
|
||||
margin-left: 20px;
|
||||
margin-left: 20px;
|
||||
font-size: 130px;
|
||||
padding-bottom:20px;
|
||||
color:#24a05f;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#infocontent {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
z-index: -1; /* Ensure div tag stays behind content; -999 might work, too. */
|
||||
}
|
||||
|
||||
@@ -31,10 +31,10 @@
|
||||
max-height 200px;
|
||||
}
|
||||
|
||||
#sossoimage {
|
||||
#sossoimage {
|
||||
height:300px;
|
||||
position: relative;
|
||||
left: 0px;
|
||||
position: relative;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<link rel="stylesheet" href="/static/infoscreen/css/events.css">
|
||||
<link href="https://fonts.googleapis.com/css?family=Droid+Sans+Mono" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css?family=Droid+Sans+Mono" rel="stylesheet">
|
||||
<div class="container" ng-app="myApp" ng-controller="EventController">
|
||||
<div class="header-row row">
|
||||
<div class="col-sm-6">Tapahtuma</div>
|
||||
|
||||
@@ -36,7 +36,7 @@ from infoscreen.models import (
|
||||
@permission_required("infoscreen.change_infoinstance", raise_exception=True)
|
||||
def admin(request, *args, **kwargs):
|
||||
"""Render infoscreen admin page."""
|
||||
return render(request, "infoscreen:infoscreen_admin.html", {})
|
||||
return render(request, "infoscreen/infoscreen_admin.html", {})
|
||||
|
||||
|
||||
def create_item_generator(model):
|
||||
|
||||
@@ -15,7 +15,7 @@ import requests
|
||||
@require_http_methods(["GET"])
|
||||
def index(request, idx, *args, **kwargs):
|
||||
"""Render infoscreen index page."""
|
||||
return render(request, "infoscreen_index.html", {"rotation": idx})
|
||||
return render(request, "infoscreen/infoscreen_index.html", {"rotation": idx})
|
||||
|
||||
|
||||
@require_http_methods(["GET"])
|
||||
|
||||
+3
-3
@@ -2,11 +2,11 @@ from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
from kaehmy.models import PresetRole, CustomRole, Application, Comment, KaehmyBaseRole
|
||||
from kaehmy.models import PresetRole, CustomRole, Application, Comment, BaseRole
|
||||
|
||||
|
||||
class CheckboxSelectMultiple(forms.widgets.CheckboxSelectMultiple):
|
||||
option_template_name = "checkbox_option.html"
|
||||
option_template_name = "kaehmy/checkbox_option.html"
|
||||
|
||||
def create_option(
|
||||
self, name, value, label, selected, index, subindex=None, attrs=None
|
||||
@@ -57,7 +57,7 @@ class ApplicationForm(forms.ModelForm):
|
||||
self.fields["custom_roles"].label = _("Custom roles")
|
||||
self.fields["custom_roles"].queryset = CustomRole.objects.all()
|
||||
|
||||
for cat_id, category in KaehmyBaseRole.CATEGORIES:
|
||||
for cat_id, category in BaseRole.CATEGORIES:
|
||||
key = "preset_roles_{}".format(cat_id)
|
||||
qset = PresetRole.objects.filter(category=cat_id).order_by(
|
||||
"category", "-is_board"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.2.14 on 2022-08-01 19:13
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("kaehmy", "0006_delete_telegramchannel"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="commentparent",
|
||||
name="id",
|
||||
field=models.AutoField(primary_key=True, serialize=False),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,44 @@
|
||||
# Generated by Django 3.2.14 on 2022-08-03 20:14
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("kaehmy", "0007_alter_commentparent_id"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="BaseRole",
|
||||
fields=[
|
||||
("id", models.AutoField(primary_key=True, serialize=False)),
|
||||
("name", models.CharField(max_length=255, verbose_name="Name")),
|
||||
("is_board", models.BooleanField(verbose_name="Board member")),
|
||||
(
|
||||
"category",
|
||||
models.CharField(
|
||||
choices=[
|
||||
("corporate", "Corporate affairs"),
|
||||
("freshman", "Freshmen"),
|
||||
("international", "International"),
|
||||
("external", "External affairs"),
|
||||
("media", "Media"),
|
||||
("tech", "Technology"),
|
||||
("wellbeing", "Wellbeing"),
|
||||
("elepaja", "Elepaja"),
|
||||
("ceremonies", "Ceremonies"),
|
||||
("studies", "Studies"),
|
||||
("sosso", "Sössö magazine"),
|
||||
("alumni", "Alumni relations"),
|
||||
("others", "Others"),
|
||||
],
|
||||
default="others",
|
||||
max_length=255,
|
||||
verbose_name="Category",
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,29 @@
|
||||
# Generated by Django 2.2.28 on 2022-07-26 17:15
|
||||
|
||||
from unicodedata import category
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def copyBaseRolesToNewTable(apps, schema_editor):
|
||||
Old = apps.get_model("kaehmy", "KaehmyBaseRole")
|
||||
New = apps.get_model("kaehmy", "BaseRole")
|
||||
for bases in Old.objects.all():
|
||||
New.objects.create(
|
||||
id=bases.id,
|
||||
name=bases.name,
|
||||
is_board=bases.is_board,
|
||||
category=bases.category,
|
||||
)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("kaehmy", "0008_baserole"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
copyBaseRolesToNewTable, reverse_code=migrations.RunPython.noop
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,51 @@
|
||||
# Generated by Django 2.2.28 on 2022-07-26 17:33
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
from sikweb.custom_operations import AlterModelBases
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("kaehmy", "0009_auto_20220726_2015"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
AlterModelBases("customrole", (models.Model,)),
|
||||
AlterModelBases("presetrole", (models.Model,)),
|
||||
migrations.AlterField(
|
||||
model_name="customrole",
|
||||
name="kaehmybaserole_ptr",
|
||||
field=models.OneToOneField(
|
||||
auto_created=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
parent_link=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
to="BaseRole",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="presetrole",
|
||||
name="kaehmybaserole_ptr",
|
||||
field=models.OneToOneField(
|
||||
auto_created=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
parent_link=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
to="BaseRole",
|
||||
),
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name="customrole",
|
||||
old_name="kaehmybaserole_ptr",
|
||||
new_name="baserole_ptr",
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name="presetrole",
|
||||
old_name="kaehmybaserole_ptr",
|
||||
new_name="baserole_ptr",
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,16 @@
|
||||
# Generated by Django 3.2.14 on 2022-08-03 20:19
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("kaehmy", "0010_auto_20220726_2033"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.DeleteModel(
|
||||
name="KaehmyBaseRole",
|
||||
),
|
||||
]
|
||||
+13
-12
@@ -1,20 +1,16 @@
|
||||
from django.db import models
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from webapp.models import BaseRole
|
||||
|
||||
|
||||
# TODO: Move BaseRole to Kaehmt App; will fuck up the DB since table is removed, if no data migration is done before-hand.
|
||||
# Either reconstruct all kaehmy roles from scratch then, or do these migrations:
|
||||
# 1. Create table here
|
||||
# 2. Data migrate from webapp BaseRole to new kaehmy BaseRole
|
||||
# 3. Delete webapp BaseRole table
|
||||
|
||||
VERBOSE_NAME = _("Kaehmy")
|
||||
|
||||
|
||||
class KaehmyBaseRole(BaseRole):
|
||||
"""ABC"""
|
||||
class BaseRole(models.Model):
|
||||
"""Base model for occupations/roles."""
|
||||
|
||||
id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(_("Name"), max_length=255)
|
||||
is_board = models.BooleanField(_("Board member"))
|
||||
|
||||
CATEGORIES = (
|
||||
("corporate", _("Corporate affairs")),
|
||||
@@ -35,8 +31,12 @@ class KaehmyBaseRole(BaseRole):
|
||||
_("Category"), choices=CATEGORIES, default="others", max_length=255
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
n = self.name.capitalize()
|
||||
return "{} ({})".format(n, _("board member")) if self.is_board else n
|
||||
|
||||
class PresetRole(KaehmyBaseRole):
|
||||
|
||||
class PresetRole(BaseRole):
|
||||
"""Model for kaehmy role."""
|
||||
|
||||
description = models.TextField(_("Description"))
|
||||
@@ -46,7 +46,7 @@ class PresetRole(KaehmyBaseRole):
|
||||
verbose_name_plural = _("Preset kaehmy roles")
|
||||
|
||||
|
||||
class CustomRole(KaehmyBaseRole):
|
||||
class CustomRole(BaseRole):
|
||||
"""Model representing a user-specified custom occupation."""
|
||||
|
||||
class Meta:
|
||||
@@ -56,6 +56,7 @@ class CustomRole(KaehmyBaseRole):
|
||||
|
||||
class CommentParent(models.Model):
|
||||
|
||||
id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(_("Name"), max_length=255, default="")
|
||||
email = models.EmailField(_("Email"), default="")
|
||||
timestamp = models.DateTimeField(_("Timestamp"), default=timezone.now)
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
{% load staticfiles %}
|
||||
|
||||
<footer style="text-align: center">
|
||||
<div>
|
||||
<form class="lang-form form" action="{% url 'set_language' %}" method="post">{% csrf_token %}
|
||||
<span>
|
||||
<input name="next" type="hidden" value="{{ redirect_to }}" />
|
||||
<select onchange="this.form.submit()" class="lang-select form-control" name="language">
|
||||
{% 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>
|
||||
</span>
|
||||
</form>
|
||||
<span>{% trans "Copyright Aalto-yliopiston Sähköinsinöörikilta ry" %} {% now 'Y' %}</span>
|
||||
</div>
|
||||
</footer>
|
||||
+8
-12
@@ -1,15 +1,11 @@
|
||||
from django.db.models import Count
|
||||
from django.shortcuts import render, redirect
|
||||
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, login_required
|
||||
from django.conf import settings
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.contrib.auth.decorators import login_required
|
||||
|
||||
import logging
|
||||
import requests
|
||||
from dealer.git import git
|
||||
from sikweb.settings import URL
|
||||
|
||||
from members.views.utils import *
|
||||
@@ -56,7 +52,7 @@ def list_view(request, *args, **kwargs):
|
||||
"filter_options": filter_options,
|
||||
}
|
||||
|
||||
return render(request, "kaehmy:list.html", context)
|
||||
return render(request, "kaehmy/list.html", context)
|
||||
|
||||
|
||||
@ensure_csrf_cookie
|
||||
@@ -81,7 +77,7 @@ def comment(request, *args, **kwargs):
|
||||
return redirect("/kaehmy")
|
||||
else:
|
||||
context = {"error": form.errors}
|
||||
return render(request, "kaehmy:error.html", context)
|
||||
return render(request, "kaehmy/error.html", context)
|
||||
|
||||
|
||||
@require_http_methods(["GET"])
|
||||
@@ -106,14 +102,14 @@ def statistics_view(request, *args, **kwargs):
|
||||
"application_count": len(applications),
|
||||
"role_list": role_list,
|
||||
}
|
||||
return render(request, "kaehmy:statistics.html", context)
|
||||
return render(request, "kaehmy/statistics.html", context)
|
||||
|
||||
|
||||
@require_http_methods(["GET"])
|
||||
def view(request, *args, **kwargs):
|
||||
"""Render Kaehmy form page."""
|
||||
form = ApplicationForm()
|
||||
return render(request, "kaehmy:kaehmy.html", {"form": form})
|
||||
return render(request, "kaehmy/kaehmy.html", {"form": form})
|
||||
|
||||
|
||||
@ensure_csrf_cookie
|
||||
@@ -148,7 +144,7 @@ def submit(request, *args, **kwargs):
|
||||
processHooks(message=f"Uusi New kaehmy! {name} -> {url}", eventType="kaehmy")
|
||||
else:
|
||||
context = {"error": form.errors}
|
||||
return render(request, "kaehmy:error.html", context)
|
||||
return render(request, "kaehmy/error.html", context)
|
||||
return HttpResponseRedirect("/kaehmy")
|
||||
|
||||
|
||||
@@ -175,4 +171,4 @@ def export_view(request, *args, **kwargs):
|
||||
"non_board_table": make_table(non_board),
|
||||
"board_table": make_table(board),
|
||||
}
|
||||
return render(request, "kaehmy:export.html", context)
|
||||
return render(request, "kaehmy/export.html", context)
|
||||
|
||||
@@ -1059,9 +1059,9 @@ msgid "-sarjassa"
|
||||
msgstr "series"
|
||||
|
||||
#: ohlhafv/templates/email.html:8
|
||||
msgid "Muistattehan vahvistaa haasteen paikan päällä Smökissä torstaina 14.2"
|
||||
msgid "Muistattehan vahvistaa haasteen paikan päällä Smökissä torstaina 26.5."
|
||||
msgstr ""
|
||||
"Remeber to confirm the challenge at Smökki on Thursday 14.2. at the event"
|
||||
"Remeber to confirm the challenge at Smökki on Thursday 26.5. at the event"
|
||||
|
||||
#: ohlhafv/templates/email.html:10
|
||||
msgid "Käy kurkkaamassa muutkin haasteet osoitteessa"
|
||||
|
||||
@@ -1045,7 +1045,7 @@ msgid "-sarjassa"
|
||||
msgstr ""
|
||||
|
||||
#: ohlhafv/templates/email.html:8
|
||||
msgid "Muistattehan vahvistaa haasteen paikan päällä Smökissä torstaina 14.2"
|
||||
msgid "Muistattehan vahvistaa haasteen paikan päällä Smökissä torstaina 26.5."
|
||||
msgstr ""
|
||||
|
||||
#: ohlhafv/templates/email.html:10
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.2.14 on 2022-08-01 19:13
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("members", "0019_auto_20171029_1143"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="payment",
|
||||
name="id",
|
||||
field=models.AutoField(primary_key=True, serialize=False),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,23 @@
|
||||
# Generated by Django 3.2.14 on 2022-08-01 19:15
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("members", "0020_alter_payment_id"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="member",
|
||||
name="id",
|
||||
field=models.AutoField(primary_key=True, serialize=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="request",
|
||||
name="id",
|
||||
field=models.AutoField(primary_key=True, serialize=False),
|
||||
),
|
||||
]
|
||||
@@ -9,6 +9,7 @@ from django.db.models import Q, OuterRef, Subquery
|
||||
class BaseMember(models.Model):
|
||||
"""Abstract base model for member."""
|
||||
|
||||
id = models.AutoField(primary_key=True)
|
||||
first_name = models.CharField(_("First name"), max_length=127)
|
||||
last_name = models.CharField(_("Last name"), max_length=127)
|
||||
email = models.EmailField(_("Email"), unique=True)
|
||||
@@ -60,6 +61,7 @@ class Payment(models.Model):
|
||||
class Meta:
|
||||
permissions = (("read_payment", "Can see payment in list"),)
|
||||
|
||||
id = models.AutoField(primary_key=True)
|
||||
date = models.DateTimeField(_("Date"), default=timezone.now)
|
||||
source = models.CharField(
|
||||
_("Source"),
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
{% load i18n %}
|
||||
{% trans "Moi" %} {{ first_name }}!
|
||||
|
||||
{% trans "Onnittelut! Sinut on hyväksytty Sähköinsinöörikillan jäseneksi." %}
|
||||
|
||||
{% trans "Käy kurkkaamassa killan nettisivuilta" %} (https://sik.ayy.fi) {% trans "tulevia tapahtumia ja piipahda kiltahuoneella tutustumassa uusiin kiltatovereihisi!" %}
|
||||
|
||||
{% trans "Liity myös killan TG-kanaville" %}:
|
||||
{% trans "SIK" %}: https://t.me/joinchat/A6EViD5FCWLxPcXCggY7hw
|
||||
{% trans "SIK-fuksit 2019" %}: http://tinyurl.com/sikfuksit19-tg
|
||||
{% trans "SIK-fuksit 2019 -tiedotuskanava" %}: http://tinyurl.com/sikfuksit19-tiedotus
|
||||
+13
-5
@@ -5,6 +5,7 @@ from unittest import skip
|
||||
from django.contrib.auth.models import User
|
||||
from members.models import Member, Payment, Request
|
||||
from rest_framework.authtoken.models import Token
|
||||
from datetime import timezone
|
||||
|
||||
|
||||
import logging
|
||||
@@ -108,8 +109,11 @@ class MemberRegisterTestCase(TestCase):
|
||||
|
||||
content = resp.content
|
||||
arrays = pyexcel.get_array(file_content=content, file_type="xlsx")
|
||||
created = Payment.objects.get(member__email="tidus@tester.fi").date.strftime(
|
||||
"%Y-%m-%d %H:%M:%S"
|
||||
created = (
|
||||
Payment.objects.get(member__email="tidus@tester.fi")
|
||||
.date.replace(tzinfo=timezone.utc)
|
||||
.astimezone(tz=None)
|
||||
.strftime("%Y-%m-%d %H:%M:%S")
|
||||
)
|
||||
tidus_array = ["Tidus Tester", created, "AYY"]
|
||||
self.assertIn(tidus_array, arrays)
|
||||
@@ -122,9 +126,13 @@ class MemberRegisterTestCase(TestCase):
|
||||
|
||||
content = resp.content
|
||||
arrays = pyexcel.get_array(file_content=content, file_type="xlsx")
|
||||
submitted = Request.objects.get(
|
||||
email="liisa.mattila@pylly.com"
|
||||
).submitted.strftime("%Y-%m-%d %H:%M:%S")
|
||||
submitted = (
|
||||
Request.objects.get(email="liisa.mattila@pylly.com")
|
||||
.submitted.replace(tzinfo=timezone.utc)
|
||||
.astimezone(tz=None)
|
||||
.strftime("%Y-%m-%d %H:%M:%S")
|
||||
)
|
||||
|
||||
liisa_array = [
|
||||
"Liisa",
|
||||
"Mattila",
|
||||
|
||||
@@ -12,6 +12,7 @@ import logging
|
||||
import html
|
||||
|
||||
from webapp.utils import send_email
|
||||
from webapp.utils import add_to_mailinglist
|
||||
|
||||
from members.views.utils import *
|
||||
from members.tables import RequestTable
|
||||
@@ -41,7 +42,7 @@ def application_list(request, *args, **kwargs):
|
||||
"application_count": application_count,
|
||||
"notification": request.GET.get("notification", None),
|
||||
}
|
||||
return render(request, "application_list.html", context)
|
||||
return render(request, "members/application_list.html", context)
|
||||
|
||||
|
||||
@ensure_csrf_cookie
|
||||
@@ -57,7 +58,9 @@ def application_edit(request, *args, **kwargs):
|
||||
application = Request.objects.get(id=i)
|
||||
form = ApplicationForm(instance=application)
|
||||
return render(
|
||||
request, "application_edit.html", {"application_id": i, "form": form}
|
||||
request,
|
||||
"members/application_edit.html",
|
||||
{"application_id": i, "form": form},
|
||||
)
|
||||
|
||||
|
||||
@@ -86,6 +89,9 @@ def application_accept(request, *args, **kwargs):
|
||||
).format(application.email),
|
||||
)
|
||||
|
||||
if application.jas:
|
||||
add_to_mailinglist(application.email)
|
||||
|
||||
member = application.to_member()
|
||||
member.save()
|
||||
application.delete()
|
||||
@@ -101,10 +107,10 @@ def application_accept(request, *args, **kwargs):
|
||||
subject = _("Jäsenhakemuksesi Sähköinsinöörikiltaan on hyväksytty!")
|
||||
|
||||
message = render_to_string(
|
||||
"members:email_application_accept.html",
|
||||
"members/email_application_accept.html",
|
||||
{"first_name": application.first_name},
|
||||
)
|
||||
send_email(member.email, subject, message)
|
||||
send_email(member.email, subject, message, True)
|
||||
|
||||
return HttpResponseRedirect(
|
||||
"/members/list?notification={}".format(html.escape(notification))
|
||||
@@ -158,7 +164,7 @@ def application_delete_confirm(request, *args, **kwargs):
|
||||
form = ApplicationForm(instance=application)
|
||||
return render(
|
||||
request,
|
||||
"application_delete_confirm.html",
|
||||
"members/application_delete_confirm.html",
|
||||
{"application_id": i, "form": form},
|
||||
)
|
||||
|
||||
@@ -167,7 +173,7 @@ def application_delete_confirm(request, *args, **kwargs):
|
||||
def application_form(request, *args, **kwargs):
|
||||
"""Render member application form."""
|
||||
form = ApplicationForm()
|
||||
return render(request, "application_index.html", {"form": form})
|
||||
return render(request, "members/application_index.html", {"form": form})
|
||||
|
||||
|
||||
@ensure_csrf_cookie
|
||||
@@ -186,7 +192,7 @@ def application_submit(request, *args, **kwargs):
|
||||
)
|
||||
|
||||
message = render_to_string(
|
||||
"members:email_application_submit.html",
|
||||
"members/email_application_submit.html",
|
||||
{
|
||||
"application": application,
|
||||
"ayy": _("Kyllä") if application.AYY else _("Ei"),
|
||||
@@ -195,6 +201,6 @@ def application_submit(request, *args, **kwargs):
|
||||
)
|
||||
send_email(email, subject, message)
|
||||
finally:
|
||||
return render(request, "application_success.html", {})
|
||||
return render(request, "members/application_success.html", {})
|
||||
else:
|
||||
return error_view(request, form.errors)
|
||||
|
||||
@@ -70,7 +70,7 @@ def member_list(request, *args, **kwargs):
|
||||
"paid_count": len(queryset.filter(last_paid__gte=filter_date)),
|
||||
"notification": request.GET.get("notification", None),
|
||||
}
|
||||
return render(request, "member_list.html", context)
|
||||
return render(request, "members/member_list.html", context)
|
||||
|
||||
|
||||
@ensure_csrf_cookie
|
||||
@@ -80,7 +80,7 @@ def member_list(request, *args, **kwargs):
|
||||
def member_add(request, *args, **kwargs):
|
||||
"""Render add member page."""
|
||||
form = MemberForm()
|
||||
return render(request, "member_add.html", {"form": form})
|
||||
return render(request, "members/member_add.html", {"form": form})
|
||||
|
||||
|
||||
@ensure_csrf_cookie
|
||||
@@ -96,7 +96,9 @@ def member_delete_confirm(request, *args, **kwargs):
|
||||
member = Member.objects.get(id=i)
|
||||
form = MemberForm(instance=member)
|
||||
return render(
|
||||
request, "member_delete_confirm.html", {"member_id": i, "form": form}
|
||||
request,
|
||||
"members/member_delete_confirm.html",
|
||||
{"member_id": i, "form": form},
|
||||
)
|
||||
|
||||
|
||||
@@ -106,7 +108,7 @@ def member_delete_confirm(request, *args, **kwargs):
|
||||
@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", {})
|
||||
return render(request, "members/member_add_many.html", {})
|
||||
|
||||
|
||||
@ensure_csrf_cookie
|
||||
@@ -233,7 +235,9 @@ def member_edit(request, *args, **kwargs):
|
||||
else:
|
||||
member = Member.objects.get(id=i)
|
||||
form = MemberForm(instance=member)
|
||||
return render(request, "member_edit.html", {"member_id": i, "form": form})
|
||||
return render(
|
||||
request, "members/member_edit.html", {"member_id": i, "form": form}
|
||||
)
|
||||
|
||||
|
||||
@method_decorator(login_required(login_url="/admin/login"), name="dispatch")
|
||||
|
||||
@@ -43,7 +43,7 @@ def payment_list(request, *args, **kwargs):
|
||||
"payment_count": len(payments),
|
||||
"notification": request.GET.get("notification", None),
|
||||
}
|
||||
return render(request, "payment_list.html", context)
|
||||
return render(request, "members/payment_list.html", context)
|
||||
|
||||
|
||||
@ensure_csrf_cookie
|
||||
@@ -53,7 +53,7 @@ def payment_list(request, *args, **kwargs):
|
||||
def payment_add(request, *args, **kwargs):
|
||||
"""Render add payment form."""
|
||||
form = PaymentForm()
|
||||
return render(request, "payment_add.html", {"form": form})
|
||||
return render(request, "members/payment_add.html", {"form": form})
|
||||
|
||||
|
||||
@ensure_csrf_cookie
|
||||
@@ -92,7 +92,9 @@ def payment_edit(request, *args, **kwargs):
|
||||
else:
|
||||
payment = Payment.objects.get(id=i)
|
||||
form = PaymentForm(instance=payment)
|
||||
return render(request, "payment_edit.html", {"payment_id": i, "form": form})
|
||||
return render(
|
||||
request, "members/payment_edit.html", {"payment_id": i, "form": form}
|
||||
)
|
||||
|
||||
|
||||
@ensure_csrf_cookie
|
||||
@@ -108,7 +110,9 @@ def payment_delete_confirm(request, *args, **kwargs):
|
||||
payment = Payment.objects.get(id=i)
|
||||
form = PaymentForm(instance=payment)
|
||||
return render(
|
||||
request, "payment_delete_confirm.html", {"payment_id": i, "form": form}
|
||||
request,
|
||||
"members/payment_delete_confirm.html",
|
||||
{"payment_id": i, "form": form},
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ class MemberDetail(generics.RetrieveAPIView):
|
||||
|
||||
|
||||
def error_view(request, message, status=400):
|
||||
return render(request, "error.html", {"error": message}, status=400)
|
||||
return render(request, "members/error.html", {"error": message}, status=400)
|
||||
|
||||
|
||||
def validate_recaptcha(response):
|
||||
@@ -100,7 +100,7 @@ def convert_table_to_html(table, request):
|
||||
@permission_required("members.change_member", raise_exception=True)
|
||||
def settings_page(request, *args, **kwargs):
|
||||
"""Render member app settings page."""
|
||||
return render(request, "settings.html", {})
|
||||
return render(request, "members/settings.html", {})
|
||||
|
||||
|
||||
@ensure_csrf_cookie
|
||||
@@ -155,7 +155,7 @@ def import_csv(request, *args, **kwargs):
|
||||
request.session["models"] = result
|
||||
request.session["payment_source"] = payment_source
|
||||
context = {"members": member_table_html, "payments": payment_table_html}
|
||||
return render(request, "member_add_many_confirm.html", context)
|
||||
return render(request, "members/member_add_many_confirm.html", context)
|
||||
|
||||
|
||||
def make_excel_response(Resource):
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.2.14 on 2022-08-01 19:13
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("ohlhafv", "0002_remove_ohlhafvchallenge_challenger_email"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="ohlhafvchallenge",
|
||||
name="id",
|
||||
field=models.AutoField(primary_key=True, serialize=False),
|
||||
),
|
||||
]
|
||||
@@ -29,6 +29,7 @@ class OhlhafvChallenge(models.Model):
|
||||
("Team", _("Team Challenge (1 x 0.33 L, 2 x 0.5 L, 1 x 1.0 L)")),
|
||||
)
|
||||
|
||||
id = models.AutoField(primary_key=True)
|
||||
challenger = models.CharField(_("Challenger"), max_length=255)
|
||||
victim = models.CharField(_("Victim"), max_length=255)
|
||||
victim_email = models.EmailField(_("Victim email"))
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 234 KiB After Width: | Height: | Size: 56 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.8 MiB |
@@ -1,25 +0,0 @@
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
{% load staticfiles %}
|
||||
<link rel="stylesheet" href="{% static "ohlhafv/css/footer.css" %}">
|
||||
|
||||
<footer style="text-align: center">
|
||||
<div>
|
||||
<form class="lang-form form" action="{% url 'set_language' %}" method="post">{% csrf_token %}
|
||||
<span>
|
||||
<input name="next" type="hidden" value="{{ redirect_to }}" />
|
||||
<select onchange="this.form.submit()" class="lang-select form-control" name="language">
|
||||
{% 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>
|
||||
</span>
|
||||
</form>
|
||||
<span>{% trans "Copyright Aalto-yliopiston Sähköinsinöörikilta ry" %} {% now 'Y' %}</span>
|
||||
</div>
|
||||
</footer>
|
||||
+4
-4
@@ -18,7 +18,7 @@ from webapp.models import processHooks
|
||||
def ohlhafv_view(request, *args, **kwargs):
|
||||
"""Render Ohlhafv form page."""
|
||||
form = OhlhafvForm()
|
||||
return render(request, "ohlhafv:new.html", {"form": form})
|
||||
return render(request, "ohlhafv/new.html", {"form": form})
|
||||
|
||||
|
||||
@ensure_csrf_cookie
|
||||
@@ -32,7 +32,7 @@ def ohlhafv_submit(request, *args, **kwargs):
|
||||
url = f"https://{URL}/ohlhafv/list"
|
||||
|
||||
email_body = render_to_string(
|
||||
"ohlhafv:email.html",
|
||||
"ohlhafv/email.html",
|
||||
{
|
||||
"challenge": challenge,
|
||||
"url": url,
|
||||
@@ -46,7 +46,7 @@ def ohlhafv_submit(request, *args, **kwargs):
|
||||
|
||||
try:
|
||||
webhook_message = render_to_string(
|
||||
"ohlhafv:tgmsg.tpl", {"challenge": challenge, "url": url}
|
||||
"ohlhafv/tgmsg.tpl", {"challenge": challenge, "url": url}
|
||||
)
|
||||
processHooks(message=webhook_message, eventType="ohlhafv")
|
||||
except Exception:
|
||||
@@ -67,4 +67,4 @@ def ohlhafv_list(request, *args, **kwargs):
|
||||
"challenges": challenges,
|
||||
"challenge_count": len(challenges),
|
||||
}
|
||||
return render(request, "ohlhafv:list.html", context)
|
||||
return render(request, "ohlhafv/list.html", context)
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
"lint": "run-p lint:js lint:md lint:py",
|
||||
"lint:js": "eslint .",
|
||||
"lint:md": "remark .",
|
||||
"lint:py": "black --diff .",
|
||||
"lint:py": "black --diff --check .",
|
||||
"lint:py:fix": "black .",
|
||||
"lint:py-type": "pyright",
|
||||
"prepare": "husky install"
|
||||
|
||||
Generated
+483
-487
File diff suppressed because it is too large
Load Diff
@@ -10,6 +10,9 @@ fi
|
||||
if test -f "$DB_PASSWD_FILE"; then
|
||||
export DB_PASSWD=$(cat $DB_PASSWD_FILE)
|
||||
fi
|
||||
if test -f "$GOOGLE_CREDS_JSON"; then
|
||||
export GOOGLE_CREDS_JSON=$(cat $GOOGLE_CRED_JSON_FILE)
|
||||
fi
|
||||
|
||||
# Collect static files
|
||||
echo "Collect static files"
|
||||
|
||||
+21
-22
@@ -7,43 +7,42 @@ authors = ["Aarni Halinen aarni.halinen@sahkoinsinoorikilta.fi"]
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.9"
|
||||
decorator = "^4.0.9"
|
||||
Django = "^2.2.19"
|
||||
requests = "^2.11.1"
|
||||
django-cors-headers = "^3.7.0"
|
||||
Django = "^3.2.14"
|
||||
requests = "^2.28.1"
|
||||
django-cors-headers = "^3.13.0"
|
||||
djangorestframework = "^3.12.4"
|
||||
djangorestframework-jwt = "^1.11.0"
|
||||
django-nose = "^1.4.5"
|
||||
psycopg2-binary = "2.8.6"
|
||||
django-bootstrap3 = "^11.1.0"
|
||||
django-tables2 = "^1.6.1"
|
||||
dealer = "^2.0.5"
|
||||
django-modeltranslation = "^0.13b1"
|
||||
django-auditlog = "^0.4.5"
|
||||
django-phonenumber-field = {version = "^4.0.0", extras = ["phonenumbers"]}
|
||||
psycopg2-binary = "^2.9.3"
|
||||
django-bootstrap3 = "^21.2"
|
||||
django-tables2 = "^2.4.1"
|
||||
django-modeltranslation = "^0.18.4"
|
||||
django-auditlog = "^2.1.1"
|
||||
django-phonenumber-field = {version = "^6.3.0", extras = ["phonenumbers"]}
|
||||
django-autocomplete-light = "^3.4.1"
|
||||
six = "^1.12.0"
|
||||
django-suit = "^0.2.26"
|
||||
pyexcel = "^0.5.14"
|
||||
pyexcel-xlsx = "^0.5.8"
|
||||
django-import-export = "^0.7.0"
|
||||
django-import-export = "^2.8.0"
|
||||
openpyxl = "^2.6.4"
|
||||
django-app-namespace-template-loader = "^0.4.1"
|
||||
django-filter = "^2.0.0"
|
||||
whitenoise = "^4.1.4"
|
||||
jsonschema = "^3.2.0"
|
||||
django-filter = "^22.1"
|
||||
whitenoise = "^6.2.0"
|
||||
jsonschema = "^4.9.0"
|
||||
Markdown = "^3.2.2"
|
||||
uWSGI = "^2.0.18"
|
||||
gunicorn = "^20.1.0"
|
||||
Pillow = "^8.4.0"
|
||||
Pillow = "^9.1.1"
|
||||
sendgrid = "^6.7.0"
|
||||
sentry-sdk = "^1.4.3"
|
||||
django-polymorphic = "^3.1.0"
|
||||
python-dotenv = "^0.20.0"
|
||||
djangorestframework-simplejwt = "^5.2.0"
|
||||
google-auth = "^2.9.1"
|
||||
google-api-python-client = "^2.54.0"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
coverage = "^5.5"
|
||||
nose-exclude = "^0.5.0"
|
||||
safety = "^1.10.3"
|
||||
black = "^21.12b0"
|
||||
coverage = "^6.4.2"
|
||||
safety = "^2.1.1"
|
||||
black = "^22.6.0"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core>=1.0.0"]
|
||||
|
||||
+2
-2
@@ -3,8 +3,8 @@ CREATE USER sik WITH PASSWORD 'password123';
|
||||
ALTER ROLE sik SET client_encoding TO 'utf8';
|
||||
ALTER ROLE sik SET default_transaction_isolation TO 'read committed';
|
||||
ALTER ROLE sik SET timezone TO 'UTC';
|
||||
CREATE DATABASE sik
|
||||
ENCODING 'UTF8'
|
||||
CREATE DATABASE sik
|
||||
ENCODING 'UTF8'
|
||||
OWNER sik;
|
||||
GRANT ALL PRIVILEGES ON DATABASE sik TO sik;
|
||||
ALTER USER sik CREATEDB;
|
||||
|
||||
+23
-92
@@ -7,14 +7,26 @@ from django.utils.translation import ugettext_lazy as _
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/1.9/howto/static-files/
|
||||
STATIC_URL = "static/"
|
||||
STATIC_ROOT = os.path.join(BASE_DIR, "collected_static")
|
||||
STATICFILES_DIRS = [
|
||||
os.path.join(BASE_DIR, "static"),
|
||||
]
|
||||
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
|
||||
MEDIA_URL = "/media/"
|
||||
|
||||
# Login paths
|
||||
LOGIN_URL = "/login/"
|
||||
LOGIN_REDIRECT_URL = "/admin"
|
||||
|
||||
# Might need to be changed to JSON serializer
|
||||
# https://docs.djangoproject.com/en/4.0/topics/http/sessions/#django.contrib.sessions.serializers.JSONSerializer
|
||||
SESSION_SERIALIZER = "django.contrib.sessions.serializers.PickleSerializer"
|
||||
|
||||
# Logger level
|
||||
|
||||
# Logging
|
||||
LOGGERLEVEL = logging.DEBUG
|
||||
LOGPATH = os.path.join(BASE_DIR, "logs", "debug.log")
|
||||
|
||||
@@ -67,10 +79,15 @@ LOGGING = {
|
||||
|
||||
|
||||
# Application definition
|
||||
IMPORT_EXPORT_USE_TRANSACTIONS = True
|
||||
# Could be replaced with CORS_ALLOWED_ORIGINS list.
|
||||
# See (check correct package version in the link) https://github.com/adamchainz/django-cors-headers/tree/3.7.0#configuration
|
||||
CORS_ALLOW_ALL_ORIGINS = True
|
||||
ROOT_URLCONF = "sikweb.urls"
|
||||
WSGI_APPLICATION = "sikweb.wsgi.application"
|
||||
|
||||
INSTALLED_APPS = [
|
||||
"modeltranslation", # has to be before admin for translation admin to work
|
||||
"suit",
|
||||
"dal",
|
||||
"dal_select2",
|
||||
"django.contrib.admin",
|
||||
@@ -87,8 +104,7 @@ INSTALLED_APPS = [
|
||||
"kaehmy",
|
||||
"ohlhafv",
|
||||
"rest_framework",
|
||||
"rest_framework_jwt",
|
||||
"django_nose",
|
||||
"rest_framework_simplejwt",
|
||||
"bootstrap3",
|
||||
"django_tables2",
|
||||
"auditlog",
|
||||
@@ -97,18 +113,6 @@ INSTALLED_APPS = [
|
||||
"django_filters",
|
||||
]
|
||||
|
||||
IMPORT_EXPORT_USE_TRANSACTIONS = True
|
||||
|
||||
TEST_RUNNER = "django_nose.NoseTestSuiteRunner"
|
||||
|
||||
NOSE_ARGS = [
|
||||
"--with-coverage",
|
||||
"--cover-package=webapp,members,infoscreen",
|
||||
"--exclude-dir={}".format(os.path.join(BASE_DIR, "members", "migrations")),
|
||||
"--exclude-dir={}".format(os.path.join(BASE_DIR, "infoscreen", "migrations")),
|
||||
"--exclude-dir={}".format(os.path.join(BASE_DIR, "webapp", "migrations")),
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
"sikweb.middleware.ForceDefaultLanguageMiddleware",
|
||||
"django.middleware.security.SecurityMiddleware",
|
||||
@@ -124,17 +128,12 @@ MIDDLEWARE = [
|
||||
"auditlog.middleware.AuditlogMiddleware",
|
||||
]
|
||||
|
||||
CORS_ORIGIN_ALLOW_ALL = True
|
||||
|
||||
ROOT_URLCONF = "sikweb.urls"
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
||||
"DIRS": ["templates"],
|
||||
"OPTIONS": {
|
||||
"loaders": [
|
||||
"app_namespace.Loader",
|
||||
"django.template.loaders.filesystem.Loader",
|
||||
"django.template.loaders.app_directories.Loader",
|
||||
],
|
||||
@@ -145,17 +144,14 @@ TEMPLATES = [
|
||||
"django.contrib.auth.context_processors.auth",
|
||||
"django.contrib.messages.context_processors.messages",
|
||||
"django.template.context_processors.static",
|
||||
"dealer.contrib.django.context_processor",
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
WSGI_APPLICATION = "sikweb.wsgi.application"
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators
|
||||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
"NAME": "django.contrib.auth.password_validation."
|
||||
@@ -179,88 +175,23 @@ REST_FRAMEWORK = {
|
||||
"rest_framework.permissions.IsAdminUser",
|
||||
),
|
||||
"DEFAULT_AUTHENTICATION_CLASSES": (
|
||||
"rest_framework_jwt.authentication.JSONWebTokenAuthentication",
|
||||
"rest_framework_simplejwt.authentication.JWTAuthentication",
|
||||
),
|
||||
# 'DEFAULT_THROTTLE_CLASSES': (
|
||||
# 'members.throttles.BurstRateThrottle',
|
||||
# 'members.throttles.SustainedRateThrottle'
|
||||
# ),
|
||||
# 'DEFAULT_THROTTLE_RATES': {
|
||||
# 'burst': '60/min',
|
||||
# 'sustained': '1000/day'
|
||||
# },
|
||||
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.LimitOffsetPagination",
|
||||
"PAGE_SIZE": 1000,
|
||||
"DEFAULT_FILTER_BACKENDS": ("django_filters.rest_framework.DjangoFilterBackend",),
|
||||
}
|
||||
|
||||
# Email settings (tested working with gmail)
|
||||
# EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
|
||||
# EMAIL_USE_TLS = True
|
||||
# EMAIL_HOST = 'smtp.gmail.com'
|
||||
# EMAIL_PORT = 587
|
||||
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/1.9/topics/i18n/
|
||||
|
||||
LANGUAGES = (
|
||||
("fi", _("Finnish")),
|
||||
("en", _("English")),
|
||||
)
|
||||
|
||||
LANGUAGE_CODE = "fi"
|
||||
|
||||
LOCALE_PATHS = (os.path.join(BASE_DIR, "locale"),)
|
||||
|
||||
TIME_ZONE = "Europe/Helsinki"
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
USE_L10N = True
|
||||
|
||||
USE_TZ = True
|
||||
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/1.9/howto/static-files/
|
||||
STATICFILES_FINDERS = (
|
||||
"django.contrib.staticfiles.finders.AppDirectoriesFinder",
|
||||
"django.contrib.staticfiles.finders.FileSystemFinder",
|
||||
)
|
||||
STATIC_URL = "/static/"
|
||||
STATIC_ROOT = os.path.join(BASE_DIR, "collected_static")
|
||||
STATICFILES_DIRS = (os.path.join(BASE_DIR, "static"),)
|
||||
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
|
||||
}
|
||||
|
||||
JWT_AUTH = {"JWT_EXPIRATION_DELTA": datetime.timedelta(days=7)}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
# contents of yourapp/migrations/custom_operations.py
|
||||
|
||||
from django.db.migrations.operations.models import ModelOperation
|
||||
|
||||
|
||||
class AlterModelBases(ModelOperation):
|
||||
reduce_to_sql = False
|
||||
reversible = True
|
||||
|
||||
def __init__(self, name, bases):
|
||||
self.bases = bases
|
||||
super().__init__(name)
|
||||
|
||||
def state_forwards(self, app_label, state):
|
||||
"""
|
||||
Overwrite a models base classes with a custom list of
|
||||
bases instead, then force Django to reload the model
|
||||
with this (probably completely) different class hierarchy.
|
||||
"""
|
||||
state.models[app_label, self.name_lower].bases = self.bases
|
||||
state.reload_model(app_label, self.name_lower)
|
||||
|
||||
def database_forwards(self, app_label, schema_editor, from_state, to_state):
|
||||
pass
|
||||
|
||||
def database_backwards(self, app_label, schema_editor, from_state, to_state):
|
||||
pass
|
||||
|
||||
def describe(self):
|
||||
return "Update %s bases to %s" % (self.name, self.bases)
|
||||
+54
-17
@@ -10,23 +10,17 @@ For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/1.9/ref/settings/
|
||||
"""
|
||||
|
||||
from dotenv import load_dotenv
|
||||
import sentry_sdk
|
||||
from sentry_sdk.integrations.django import DjangoIntegration
|
||||
from sikweb.base import *
|
||||
from datetime import timedelta
|
||||
import json
|
||||
|
||||
load_dotenv() # loads the configs from .env
|
||||
|
||||
SENTRY_DSN = os.getenv("SENTRY_DSN", "")
|
||||
DEPLOY_ENV = os.getenv("DEPLOY_ENV", "production")
|
||||
|
||||
# Setup sentry
|
||||
sentry_sdk.init(
|
||||
dsn=SENTRY_DSN,
|
||||
environment=DEPLOY_ENV,
|
||||
integrations=[DjangoIntegration()],
|
||||
# If you wish to associate users to errors (assuming you are using
|
||||
# django.contrib.auth) you may enable sending PII data.
|
||||
send_default_pii=True,
|
||||
)
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = os.getenv("DEBUG", False) == "True"
|
||||
|
||||
@@ -44,6 +38,19 @@ SECRET_KEY = os.getenv(
|
||||
"SECRET_KEY", "7p$85^4ibb^p4-=vs44b7!y0e-zemugze18@a#30&71=a8)dp("
|
||||
)
|
||||
|
||||
|
||||
# Sentry
|
||||
SENTRY_DSN = os.getenv("SENTRY_DSN", "")
|
||||
sentry_sdk.init(
|
||||
dsn=SENTRY_DSN,
|
||||
environment=DEPLOY_ENV,
|
||||
integrations=[DjangoIntegration()],
|
||||
# If you wish to associate users to errors (assuming you are using
|
||||
# django.contrib.auth) you may enable sending PII data.
|
||||
send_default_pii=True,
|
||||
)
|
||||
|
||||
|
||||
# ReCaptcha
|
||||
# http://www.yaconiello.com/blog/integrating-google-recaptcha-to-django/
|
||||
GOOGLE_RECAPTCHA_SITE_KEY = os.getenv("GOOGLE_RECAPTCHA_SITE_KEY", "YOUR-PUBLIC-KEY")
|
||||
@@ -51,21 +58,19 @@ GOOGLE_RECAPTCHA_SECRET_KEY = os.getenv(
|
||||
"GOOGLE_RECAPTCHA_SECRET_KEY", "YOUR-PRIVATE-KEY"
|
||||
)
|
||||
|
||||
# Email settings (more settings in base.py)
|
||||
|
||||
# Email settings (Sendgrid)
|
||||
EMAIL_API_KEY = os.getenv("EMAIL_API_KEY", "")
|
||||
# EMAIL_API_SECRET = os.getenv('EMAIL_API_SECRET', '')
|
||||
DEFAULT_EMAIL_FROM = "SIK"
|
||||
DEFAULT_EMAIL_FROM_ADDR = "noreply@sahkoinsinoorikilta.fi"
|
||||
ENABLE_AUTOMATIC_EMAILS = True
|
||||
|
||||
# Database settings
|
||||
# Only uncomment if default settings in base.py are not ok
|
||||
|
||||
## Database connection
|
||||
DB_OPTIONS = {"sslmode": "require"} if os.getenv("DB_SSL", False) == "True" else {}
|
||||
|
||||
DATABASES = {
|
||||
"default": {
|
||||
"ENGINE": "django.db.backends.postgresql_psycopg2",
|
||||
"ENGINE": "django.db.backends.postgresql",
|
||||
"NAME": os.getenv("DB_NAME", "postgres"),
|
||||
"USER": os.getenv("DB_USER", "postgres"),
|
||||
"PASSWORD": os.getenv("DB_PASSWD", "postgres"),
|
||||
@@ -74,3 +79,35 @@ DATABASES = {
|
||||
"OPTIONS": DB_OPTIONS,
|
||||
}
|
||||
}
|
||||
|
||||
# Google api settings
|
||||
GROUP_KEY = os.getenv("GROUP_KEY", "")
|
||||
GOOGLE_SERVICE_ACCOUNT = json.loads(os.getenv("GOOGLE_CREDS_JSON", "{}"))
|
||||
|
||||
# JWT authentication
|
||||
SIMPLE_JWT = {
|
||||
"ACCESS_TOKEN_LIFETIME": timedelta(minutes=5),
|
||||
"REFRESH_TOKEN_LIFETIME": timedelta(days=1),
|
||||
"ROTATE_REFRESH_TOKENS": False,
|
||||
"BLACKLIST_AFTER_ROTATION": False,
|
||||
"UPDATE_LAST_LOGIN": False,
|
||||
"ALGORITHM": "HS256",
|
||||
"SIGNING_KEY": SECRET_KEY,
|
||||
"VERIFYING_KEY": None,
|
||||
"AUDIENCE": None,
|
||||
"ISSUER": None,
|
||||
"JWK_URL": None,
|
||||
"LEEWAY": 0,
|
||||
"AUTH_HEADER_TYPES": ("Bearer",),
|
||||
"AUTH_HEADER_NAME": "HTTP_AUTHORIZATION",
|
||||
"USER_ID_FIELD": "id",
|
||||
"USER_ID_CLAIM": "user_id",
|
||||
"USER_AUTHENTICATION_RULE": "rest_framework_simplejwt.authentication.default_user_authentication_rule",
|
||||
"AUTH_TOKEN_CLASSES": ("rest_framework_simplejwt.tokens.AccessToken",),
|
||||
"TOKEN_TYPE_CLAIM": "token_type",
|
||||
"TOKEN_USER_CLASS": "rest_framework_simplejwt.models.TokenUser",
|
||||
"JTI_CLAIM": "jti",
|
||||
"SLIDING_TOKEN_REFRESH_EXP_CLAIM": "refresh_exp",
|
||||
"SLIDING_TOKEN_LIFETIME": timedelta(minutes=5),
|
||||
"SLIDING_TOKEN_REFRESH_LIFETIME": timedelta(days=1),
|
||||
}
|
||||
|
||||
@@ -34,11 +34,13 @@ services:
|
||||
- SECRET_KEY_FILE=/run/secrets/BACKEND_SECRET_KEY
|
||||
- DB_PASSWD_FILE=/run/secrets/BACKEND_DB_PASSWD
|
||||
- EMAIL_API_KEY_FILE=/run/secrets/BACKEND_EMAIL_API_KEY
|
||||
- GOOGLE_CREDS_JSON=/run/secrets/GOOGLE_CREDS_JSON
|
||||
|
||||
secrets:
|
||||
- BACKEND_SECRET_KEY
|
||||
- BACKEND_DB_PASSWD
|
||||
- BACKEND_EMAIL_API_KEY
|
||||
- GOOGLE_CREDS_JSON
|
||||
secrets:
|
||||
BACKEND_SECRET_KEY:
|
||||
external: true
|
||||
@@ -46,3 +48,5 @@ secrets:
|
||||
external: true
|
||||
BACKEND_EMAIL_API_KEY:
|
||||
external: true
|
||||
GOOGLE_CREDS_JSON:
|
||||
EXTERNAL: true
|
||||
|
||||
@@ -3475,19 +3475,19 @@
|
||||
}
|
||||
while( (node = node.parentNode) && (node !== document.body) );
|
||||
},
|
||||
|
||||
|
||||
disableMouseover: false,
|
||||
|
||||
mouseover: function (evt){
|
||||
if (!flash.disableMouseover) {
|
||||
var target = api.event.fix(evt).target;
|
||||
|
||||
|
||||
if( /input/i.test(target.nodeName) && target.type == 'file' && !target.disabled ){
|
||||
var
|
||||
state = target.getAttribute(_attr)
|
||||
, wrapper = flash.getWrapper(target)
|
||||
;
|
||||
|
||||
|
||||
if( api.multiFlash ){
|
||||
// check state:
|
||||
// i — published
|
||||
@@ -3500,14 +3500,14 @@
|
||||
else if( state != 'p' ){
|
||||
// set "init" state
|
||||
target.setAttribute(_attr, 'i');
|
||||
|
||||
|
||||
var dummy = document.createElement('div');
|
||||
|
||||
|
||||
if( !wrapper ){
|
||||
api.log('[err] FlashAPI.mouseover: js-fileapi-wrapper not found');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
_css(dummy, {
|
||||
top: 0
|
||||
, left: 0
|
||||
@@ -3516,21 +3516,21 @@
|
||||
, zIndex: 1e6+'' // set max zIndex
|
||||
, position: 'absolute'
|
||||
});
|
||||
|
||||
|
||||
wrapper.appendChild(dummy);
|
||||
flash.publish(dummy, api.uid());
|
||||
|
||||
|
||||
// set "publish" state
|
||||
target.setAttribute(_attr, 'p');
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
else if( wrapper ){
|
||||
// Use one flash element
|
||||
var box = _getDimensions(wrapper);
|
||||
_css(flash.getEl(), box);
|
||||
|
||||
|
||||
// Set current input
|
||||
flash.curInp = target;
|
||||
}
|
||||
@@ -3543,7 +3543,7 @@
|
||||
|
||||
onEvent: function (evt){
|
||||
var type = evt.type;
|
||||
|
||||
|
||||
if( type == 'ready' ){
|
||||
try {
|
||||
// set "ready" state
|
||||
@@ -3632,9 +3632,9 @@
|
||||
_each(files, function (file){
|
||||
api.checkFileObj(file);
|
||||
});
|
||||
|
||||
|
||||
_files[uid] = files;
|
||||
|
||||
|
||||
if( document.createEvent ){
|
||||
event = document.createEvent('Event');
|
||||
event.files = files;
|
||||
@@ -3664,7 +3664,7 @@
|
||||
this.cmdFn(id, name, data, last);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
cmdFn: function(id, name, data, last) {
|
||||
try {
|
||||
api.log('(js -> flash).'+name+':', data);
|
||||
@@ -3727,7 +3727,7 @@
|
||||
callback(evt);
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
getFiles: function (input, filter, callback){
|
||||
if( callback ){
|
||||
api.filterFiles(api.getFiles(input), filter, callback);
|
||||
@@ -4039,7 +4039,7 @@
|
||||
}
|
||||
try { el.style[key] = val; } catch (e) {}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4161,7 +4161,7 @@
|
||||
, body = document.body
|
||||
, docEl = (el && el.ownerDocument).documentElement
|
||||
;
|
||||
|
||||
|
||||
function getOffset(obj) {
|
||||
var left, top;
|
||||
left = top = 0;
|
||||
@@ -4176,7 +4176,7 @@
|
||||
top : top
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
top: getOffset(el).top
|
||||
, left: getOffset(el).left
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
{% load static %}
|
||||
<html>
|
||||
<head>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="/static/img/favicon.png"/>
|
||||
<link rel="stylesheet" href="{% static "css/about.css" %}">
|
||||
</head>
|
||||
<body>
|
||||
<h1>SIKWEB 2.0</h1>
|
||||
<p>{{ commit }}</p>
|
||||
<p>{{ date }}</p>
|
||||
<p>{{ tag }}</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,75 +0,0 @@
|
||||
{% extends "admin/base.html" %}
|
||||
{% load admin_static %}
|
||||
|
||||
{% load i18n %}
|
||||
{# Additional <head> content here, some extra meta tags or favicon #}
|
||||
{% block extrahead %}
|
||||
<link rel="shortcut icon" type="image/x-icon" href="/static/img/favicon.png"/>
|
||||
{% 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 © 2013 Client<br>Developed by <a href="http://yoursite.com" target="_blank">YourName</a> #}
|
||||
{#{% endblock %}#}
|
||||
+19
-38
@@ -1,43 +1,24 @@
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
{% load staticfiles %}
|
||||
<link rel="stylesheet" href="{% static "css/footer.css" %}">
|
||||
|
||||
<footer class="footer">
|
||||
<div class="container">
|
||||
<div class="d-flex align-items-center justify-content-end">
|
||||
<div class="p-2">
|
||||
<span><i class="fa fa-copyright"></i>{% trans "Aalto-yliopiston Sähköinsinöörikilta ry" %} {% now 'Y' %}</span>
|
||||
</div>
|
||||
<div class="p-2">
|
||||
<form class="lang-form form" action="{% url 'set_language' %}" method="post">{% csrf_token %}
|
||||
<span class="form-group">
|
||||
<input name="next" type="hidden" value="{{ redirect_to }}" />
|
||||
<select onchange="this.form.submit()" class="lang-select form-control" name="language">
|
||||
{% 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>
|
||||
</span>
|
||||
</form>
|
||||
</div>
|
||||
<div class="ml-auto p-2">
|
||||
<span class="nav-item">
|
||||
<a href="/members"><i class="fa fa-group fa-2x"></i></a>
|
||||
</span>
|
||||
<span class="nav-item">
|
||||
<a href="/infoscreen"><i class="fa fa-info fa-2x"></i></a>
|
||||
</span>
|
||||
<span class="nav-item">
|
||||
<a href="/admin"><i class="fa fa-gears fa-2x"></i></a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer-padder"></div>
|
||||
<footer style="text-align: center">
|
||||
<div>
|
||||
<form class="lang-form form" action="{% url 'set_language' %}" method="post">{% csrf_token %}
|
||||
<span>
|
||||
<input name="next" type="hidden" value="{{ redirect_to }}" />
|
||||
<select onchange="this.form.submit()" class="lang-select form-control" name="language">
|
||||
{% 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>
|
||||
</span>
|
||||
</form>
|
||||
<span>{% trans "Copyright Aalto-yliopiston Sähköinsinöörikilta ry" %} {% now 'Y' %}</span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
{% load staticfiles %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
+6
-7
@@ -1,8 +1,7 @@
|
||||
{% extends "infoscreen:base.html" %}
|
||||
{% extends "infoscreen/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
{% load staticfiles %}
|
||||
|
||||
{% block appname %}infoAdmin{% endblock appname %}
|
||||
|
||||
@@ -33,13 +32,13 @@
|
||||
<h1>{% trans "Infoscreen Admin Pane" %}</h1>
|
||||
</div>
|
||||
</div>
|
||||
{% include "infoscreen:nav.html" %}
|
||||
{% include "infoscreen/nav.html" %}
|
||||
<div class="tab-content" id="tabContent">
|
||||
{% include "infoscreen:tabs/slides.html" %}
|
||||
{% include "infoscreen:tabs/rotations.html" %}
|
||||
{% include "infoscreen:tabs/add_remove.html" %}
|
||||
{% include "infoscreen/tabs/slides.html" %}
|
||||
{% include "infoscreen/tabs/rotations.html" %}
|
||||
{% include "infoscreen/tabs/add_remove.html" %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% include "webapp:footer.html" %}
|
||||
{% include "footer.html" %}
|
||||
{% endblock body %}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
{% extends "infoscreen:base.html" %}
|
||||
{% extends "infoscreen/base.html" %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<div class="col">
|
||||
<div class="rotation-title-row">
|
||||
<h2>{% trans "Rotation" %}: {$ selected_rot.name $}</h2>
|
||||
<a class="btn btn-primary" href="/infoscreen/{$ selected_rot.id $}">{% trans "Preview" %}</a>
|
||||
<a class="btn btn-primary" href="/infoscreen/{$ selected_rot.id $}">{% trans "Preview" %}</a>
|
||||
</div>
|
||||
<div>{% trans "Instances in currently selected rotation" %}:</div>
|
||||
<table class="table table-striped">
|
||||
@@ -14,12 +14,12 @@
|
||||
|
||||
{% block header %}
|
||||
<div class="kaehmy_header">
|
||||
{% include "kaehmy:header.html" %}
|
||||
{% include "kaehmy/header.html" %}
|
||||
</div>
|
||||
{% endblock header %}
|
||||
|
||||
{% block navigation %}
|
||||
{% include "kaehmy:navigation.html" %}
|
||||
{% include "kaehmy/navigation.html" %}
|
||||
{% endblock %}
|
||||
|
||||
<div class="kaehmy-content">
|
||||
@@ -28,7 +28,7 @@
|
||||
</div>
|
||||
<div class="footer">
|
||||
{% block footer %}
|
||||
{% include "kaehmy:footer.html" %}
|
||||
{% include "footer.html" %}
|
||||
{% endblock footer %}
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "kaehmy:base.html" %}
|
||||
{% extends "kaehmy/base.html" %}
|
||||
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
@@ -18,7 +18,7 @@
|
||||
<h4>{% trans "Non-board applications" %}</h4>
|
||||
{{ non_board_table|safe }}
|
||||
</div>
|
||||
|
||||
|
||||
<div>
|
||||
<a href="/kaehmy" class="btn btn-primary">{% trans "Front page" %}</a>
|
||||
</div>
|
||||
@@ -1,10 +1,10 @@
|
||||
{% extends "kaehmy:base.html" %}
|
||||
{% extends "kaehmy/base.html" %}
|
||||
|
||||
{% load bootstrap3 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block navigation %}
|
||||
{% include "kaehmy:navigation.html" %}
|
||||
{% include "kaehmy/navigation.html" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
@@ -1,21 +1,21 @@
|
||||
{% extends "kaehmy:base.html" %}
|
||||
{% extends "kaehmy/base.html" %}
|
||||
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block navigation %}
|
||||
{% include "kaehmy:navigation.html" %}
|
||||
{% include "kaehmy/navigation.html" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<script>
|
||||
function commentOn(id, op) {
|
||||
setTimeout(function() {
|
||||
document.getElementById("commentNameField").focus();
|
||||
document.getElementById("commentNameField").focus();
|
||||
}, 50);
|
||||
|
||||
document.getElementById("collapse_add_comment").scrollIntoView();
|
||||
document.getElementById("commentOP").innerHTML = op;
|
||||
document.getElementById("collapse_add_comment").scrollIntoView();
|
||||
document.getElementById("commentOP").innerHTML = op;
|
||||
document.getElementById("commentId").value = id;
|
||||
}
|
||||
</script>
|
||||
@@ -24,7 +24,7 @@
|
||||
<h2 style="padding-top: 1rem">{% trans "All kaehmys" %}</h2>
|
||||
</div>
|
||||
|
||||
<div class="collapse" id="collapse_add_comment">
|
||||
<div class="collapse" id="collapse_add_comment">
|
||||
<div class="card">
|
||||
<div class="card-block">
|
||||
<form method="POST" action="/kaehmy/add_comment" class="form">{% csrf_token %}
|
||||
@@ -69,18 +69,18 @@
|
||||
<div>
|
||||
<h6 style="padding-bottom: 1rem">{% trans "Total kaehmys:" %} {{ application_count }}</h6>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{% for application in applications %}
|
||||
<div class="card">
|
||||
<h4 class="card-header">{{ application.name }}</h4>
|
||||
<h4 class="card-header">{{ application.name }}</h4>
|
||||
<div class="card-block">
|
||||
{% if application.board_roles|length > 0 %}
|
||||
<h5 style="padding-bottom: 1rem" class="card-subtitle mb-2 text-muted">{{ application.board_roles }}</h5>
|
||||
<h5 style="padding-bottom: 1rem" class="card-subtitle mb-2 text-muted">{{ application.board_roles }}</h5>
|
||||
{% endif %}
|
||||
{% if application.official_roles|length > 0 %}
|
||||
<h5 style="padding-bottom: 1rem" class="card-subtitle mb-2 text-muted">{{ application.official_roles }}</h5>
|
||||
{% endif %}
|
||||
<h5 style="padding-bottom: 1rem" class="card-subtitle mb-2 text-muted">{{ application.official_roles }}</h5>
|
||||
{% endif %}
|
||||
<p class="card-text">{{ application.text|linebreaks|urlize }}</p>
|
||||
|
||||
{% if application.comment_count > 0 %}
|
||||
@@ -95,9 +95,9 @@
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="collapse" id="collapse_{{ application.id }}">
|
||||
<div class="collapse" id="collapse_{{ application.id }}">
|
||||
{% for message in application.messages.all %}
|
||||
{% include "kaehmy:message.html" with messages=message.messages.all %}
|
||||
{% include "kaehmy/message.html" with messages=message.messages.all %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
@@ -13,9 +13,9 @@
|
||||
</div>
|
||||
<div>
|
||||
{% for message in messages %}
|
||||
{% include "message.html" with messages=message.messages.all %}
|
||||
{% include "kaehmy/message.html" with messages=message.messages.all %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,21 +1,21 @@
|
||||
{% extends "kaehmy:base.html" %}
|
||||
{% extends "kaehmy/base.html" %}
|
||||
|
||||
{% load bootstrap3 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block navigation %}
|
||||
{% include "kaehmy:navigation.html" %}
|
||||
{% include "kaehmy/navigation.html" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div>
|
||||
<div>
|
||||
<h2 style="padding-top: 1rem">{% trans "Statistics" %}</h2>
|
||||
<h2 style="padding-top: 1rem">{% trans "Statistics" %}</h2>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 1rem" class="card">
|
||||
<div class="card-header">
|
||||
<h5>{% trans "Total kaehmys:" %} {{ application_count }}</h5>
|
||||
<h5>{% trans "Total kaehmys:" %} {{ application_count }}</h5>
|
||||
</div>
|
||||
<div class="card-block">
|
||||
{% for role in role_list %}
|
||||
@@ -25,6 +25,6 @@
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
{% endblock content %}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
{% extends "members:base.html" %}
|
||||
{% extends "members/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "members:base.html" %}
|
||||
{% extends "members/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
<div id="input_form">
|
||||
<form name="applicationForm" action="/members/accept_application" method="post" class="form">{% csrf_token %}
|
||||
<input type="hidden" name="id" value="{{ application_id }}">
|
||||
<input type="hidden" name="id" value="{{ application_id }}">
|
||||
{% bootstrap_form form %}
|
||||
{% buttons %}
|
||||
<button type="submit" class="btn btn-primary">
|
||||
+1
-1
@@ -35,6 +35,6 @@
|
||||
<body>
|
||||
{% block content %}
|
||||
{% endblock content %}
|
||||
{% include "webapp:footer.html" %}
|
||||
{% include "footer.html" %}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "application_form_base.html" %}
|
||||
{% extends "members/application_form_base.html" %}
|
||||
{% load static %}
|
||||
{% load bootstrap3 %}
|
||||
{% load i18n %}
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "members:base.html" %}
|
||||
{% extends "members/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
{{ table|safe }}
|
||||
|
||||
<div>
|
||||
<a href="/members/export_applications" class="btn btn-info">{% trans "Download Excel" %}</a>
|
||||
<a href="/members/export_applications" class="btn btn-info">{% trans "Download Excel" %}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
{% extends "application_form_base.html" %}
|
||||
{% extends "members/application_form_base.html" %}
|
||||
{% load static %}
|
||||
{% load bootstrap3 %}
|
||||
{% load i18n %}
|
||||
@@ -7,5 +7,5 @@
|
||||
<link rel="stylesheet" href="{% static "css/application.css" %}">
|
||||
<h3>{% trans "Hienoa! Jäsenhakemuksesi on nyt lähetetty." %}</h3>
|
||||
<p>{% trans "Vahvistusviesti on lähetetty sähköpostiisi. Ota yhteyttä admin@sahkoinsinoorikilta.fi jos viestiä ei näy." %}</p>
|
||||
<a href="/"><h4>{% trans "Takaisin Sähköinsinöörikillan web-sivuille" %}</h4></a>
|
||||
<a href="https://sahkoinsinoorikilta.fi/"><h4>{% trans "Takaisin Sähköinsinöörikillan web-sivuille" %}</h4></a>
|
||||
{% endblock content %}
|
||||
@@ -1,6 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
@@ -92,6 +91,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% include "webapp:footer.html" %}
|
||||
{% include "footer.html" %}
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,15 @@
|
||||
{% load i18n %}
|
||||
|
||||
<p>Moi {{first_name}}!</p>
|
||||
|
||||
<p>Onnittelut! Sinut on hyväksytty Sähköinsinöörikillan jäseneksi.</p>
|
||||
<p>
|
||||
Käy kurkkaamassa killan
|
||||
<a href="https://sahkoinsinoorikilta.fi">nettisivuilta</a>
|
||||
tulevia tapahtumia ja piipahda kiltahuoneella tutustumassa uusiin kiltatovereihisi!
|
||||
</p>
|
||||
|
||||
<p>Liity myös killan TG-kanaville:</p>
|
||||
<p><a href="https://t.me/+ubTeGSYKTvg3NmVk">Killan yleinen telegram</a></p>
|
||||
<p><a href="https://t.me/+1PqQHRVMjiAxMTU0">SIK-fuksit 2022</a></p>
|
||||
<p><a href="https://t.me/+Ln8TvQ-_id9kZTU0">SIK-fuksit 2022 -tiedotuskanava</a></p>
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "members:base.html" %}
|
||||
{% extends "members/base.html" %}
|
||||
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "members:base.html" %}
|
||||
{% extends "members/base.html" %}
|
||||
|
||||
{% load bootstrap3 %}
|
||||
{% load i18n %}
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "members:base.html" %}
|
||||
{% extends "members/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
@@ -11,7 +11,7 @@
|
||||
<div>
|
||||
<p>
|
||||
{% blocktrans %}
|
||||
Enter member information in CSV format, separate members on separate lines.
|
||||
Enter member information in CSV format, separate members on separate lines.
|
||||
If a new member already exists in the database, a new payment event will be created for that member instead.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
@@ -20,7 +20,7 @@
|
||||
<div>
|
||||
<label>{% trans "Format the member table like this:" %}</label>
|
||||
<div>
|
||||
<img src="{% static "members/img/excel_csv_save_example.png" %}">
|
||||
<img src="{% static "members/img/excel_csv_save_example.png" %}">
|
||||
</div>
|
||||
<p>{% blocktrans %}Columns: First name, last name, email address, place of origin, AYY member, JAS recipient{% endblocktrans %}</p>
|
||||
</div>
|
||||
@@ -28,10 +28,10 @@
|
||||
<label>{% trans "Save the file as CSV" %}</label>
|
||||
<div><img src="{% static "members/img/excel_csv_save_tutorial.png" %}"></div>
|
||||
</div>
|
||||
|
||||
|
||||
<form name="memberTextForm" action="/members/import_csv" enctype="multipart/form-data" method="POST">{% csrf_token %}
|
||||
<h3>{% trans "Upload file" %}</h3>
|
||||
<input class="form-control-file" type="file" accept=".csv" name="csvFile" />
|
||||
<input class="form-control-file" type="file" accept=".csv" name="csvFile" />
|
||||
|
||||
<div class="form-group">
|
||||
<label>{% trans "Payment source" %}</label>
|
||||
@@ -42,7 +42,7 @@
|
||||
</select>
|
||||
<small class="form-text text-muted">
|
||||
{% trans "This payment source will be used to create any payments for new members that already exist in the database." %}
|
||||
</small>
|
||||
</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{% trans "CSV delimiter" %}</label>
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
{% extends "members:base.html" %}
|
||||
{% extends "members/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
{% extends "members:base.html" %}
|
||||
{% extends "members/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "members:base.html" %}
|
||||
{% extends "members/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "members:base.html" %}
|
||||
{% extends "members/base.html" %}
|
||||
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
@@ -41,7 +41,7 @@
|
||||
{{ table|safe }}
|
||||
|
||||
<div>
|
||||
<a href="/members/export_members" class="btn btn-info">{% trans "Download Excel" %}</a>
|
||||
<a href="/members/export_members" class="btn btn-info">{% trans "Download Excel" %}</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "members:base.html" %}
|
||||
{% extends "members/base.html" %}
|
||||
|
||||
{% load bootstrap3 %}
|
||||
{% load i18n %}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
{% extends "members:base.html" %}
|
||||
{% extends "members/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "members:base.html" %}
|
||||
{% extends "members/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "members:base.html" %}
|
||||
{% extends "members/base.html" %}
|
||||
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
@@ -38,7 +38,7 @@
|
||||
{{ table|safe }}
|
||||
|
||||
<div>
|
||||
<a href="/members/export_payments" class="btn btn-info">{% trans "Download Excel" %}</a>
|
||||
<a href="/members/export_payments" class="btn btn-info">{% trans "Download Excel" %}</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "members:base.html" %}
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
@@ -1,10 +1,10 @@
|
||||
{% extends "members:base.html" %}
|
||||
{% extends "members/base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{{ title }}</h1>
|
||||
<h3>{{ header }}</h3>
|
||||
<form method="POST" action="/members/import_excel" enctype="multipart/form-data">{% csrf_token %}
|
||||
{{ form }}
|
||||
<input type="submit" class="btn btn-primary">
|
||||
<input type="submit" class="btn btn-primary">
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -7,22 +7,23 @@
|
||||
<link rel="stylesheet" href="{% static "ohlhafv/css/base.css" %}">
|
||||
<link rel="stylesheet" href="{% static "ohlhafv/css/header.css" %}">
|
||||
<link rel="stylesheet" href="{% static "ohlhafv/css/nav.css" %}">
|
||||
<link rel="stylesheet" href="{% static "ohlhafv/css/footer.css" %}">
|
||||
{% endblock styles %}
|
||||
|
||||
{% block body %}
|
||||
{% block header %}
|
||||
{% include "ohlhafv:header.html" %}
|
||||
{% include "ohlhafv/header.html" %}
|
||||
{% endblock header %}
|
||||
|
||||
{% block navigation %}
|
||||
{% include "ohlhafv:navigation.html" %}
|
||||
{% include "ohlhafv/navigation.html" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
|
||||
{% block footer %}
|
||||
{% include "ohlhafv:footer.html" %}
|
||||
{% include "footer.html" %}
|
||||
{% endblock footer %}
|
||||
|
||||
{% endblock body %}
|
||||
@@ -5,6 +5,6 @@
|
||||
|
||||
{{ challenge.message }}
|
||||
|
||||
{% trans "Muistattehan vahvistaa haasteen paikan päällä Smökissä torstaina 14.2" %}.
|
||||
{% trans "Muistattehan vahvistaa haasteen paikan päällä Smökissä torstaina 26.5" %}.
|
||||
|
||||
{% trans "Käy kurkkaamassa muutkin haasteet osoitteessa" %} {{ url }}
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "ohlhafv:base.html" %}
|
||||
{% extends "ohlhafv/base.html" %}
|
||||
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
{% for challenge in challenges %}
|
||||
<div class="card">
|
||||
<h4 class="card-header">{{ challenge.challenger }} vs. {{ challenge.victim }}</h4>
|
||||
<h4 class="card-header">{{ challenge.challenger }} vs. {{ challenge.victim }}</h4>
|
||||
<div class="card-block">
|
||||
<h5 class="card-subtitle mb-2">{{ challenge.get_series_display }}</h5>
|
||||
<p class="card-text">{{ challenge.message|linebreaks|urlize }}</p>
|
||||
@@ -1,10 +1,10 @@
|
||||
{% extends "ohlhafv:base.html" %}
|
||||
{% extends "ohlhafv/base.html" %}
|
||||
|
||||
{% load bootstrap3 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block navigation %}
|
||||
{% include "ohlhafv:navigation.html" %}
|
||||
{% include "ohlhafv/navigation.html" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user