Aktualności PodlZBS
-
+
{% for post in posts %}
{{ post.title }}
{{ post.content | safe }}
{% if not forloop.last %}
-
+
{% endif %} {% empty %}
Więcej wpisów nie ma
{% endfor %}
diff --git a/core/templates/tournaments.html b/core/templates/tournaments.html
new file mode 100644
index 0000000..75fb4b4
--- /dev/null
+++ b/core/templates/tournaments.html
@@ -0,0 +1,36 @@
+{% extends 'base.html' %}
+
+{% block title %}Składki Członkowskie | pdlzbs{% endblock %}
+
+{% load static tailwind_tags %} {% block content %}
+
+{% if tournaments %}
+
+ {% for tournament in tournaments %}
+
+ {{ tournament.title }}
+
+
+ {{ tournament.content | safe }}
+
+
+
+ Wyniki
+
+
+
+ {% if not forloop.last %}
+
+ {% endif %} {% endfor %}
+
+{% else %}
+
Brak dokumentów
+{% endif %} {% endblock %}
diff --git a/core/urls.py b/core/urls.py
index e326455..b402184 100644
--- a/core/urls.py
+++ b/core/urls.py
@@ -15,6 +15,7 @@ urlpatterns = [
path('liga', LeagueView.as_view(), name='league'),
path('kalendarz', CalendarView.as_view(), name='calendar'),
path('grandprix', GrandPrixView.as_view(), name='gpx'),
- path('inneturnieje', HomeView.as_view(), name='others'),
+ path('inneturnieje', TournamentView.as_view(), name='tournaments'),
path('skladki', MembershipView.as_view(), name='membership'),
+ path('atu', AtuView.as_view(), name='atu'),
]
diff --git a/core/views.py b/core/views.py
index 1b7b7ad..bb14481 100644
--- a/core/views.py
+++ b/core/views.py
@@ -10,6 +10,7 @@ from db.calendar.models import *
from db.gpb.models import *
from db.tournaments.models import *
from db.membership.models import *
+from db.atu.models import *
# Create your views here.
@@ -18,40 +19,31 @@ class HomeView(TemplateView):
template_name = 'home.html'
def get_context_data(self, **kwargs):
- context = super().get_context_data(**kwargs)
-
- context['home'] = 'active'
- context['gpw'] = GrandPrixW.load()
- context['posts'] = Post.objects.all()
-
- return context
+ return {
+ **super().get_context_data(**kwargs),
+ 'home': 'active',
+ 'gpw': GrandPrixW.load(),
+ 'posts': Post.objects.all(),
+ }
class AdministrationView(TemplateView):
template_name = 'administration.html'
def get_context_data(self, **kwargs):
- context = super().get_context_data(**kwargs)
-
- context = {
- **context,
+ return {
+ **super().get_context_data(**kwargs),
'czlonkowie': Member.objects.all(),
'statut': Statute.objects.first(),
}
- return context
-
class AdministrationAnnouncementsView(TemplateView):
template_name = 'administration/announcements.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
-
- context = {
- **context,
- 'ogloszenia': Announcement.objects.all(),
- }
+ context['ogloszenia'] = Announcement.objects.all()
return context
@@ -61,11 +53,7 @@ class AdministrationProtocolsView(TemplateView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
-
- context = {
- **context,
- 'protokoly': Protocol.objects.all(),
- }
+ context['protokoly'] = Protocol.objects.all()
return context
@@ -75,11 +63,7 @@ class AdministrationRegulationsView(TemplateView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
-
- context = {
- **context,
- 'regulaminy': Regulation.objects.all(),
- }
+ context['regulaminy'] = Regulation.objects.all()
return context
@@ -89,11 +73,7 @@ class AdministrationRODOView(TemplateView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
-
- context = {
- **context,
- 'rodos': RODO.objects.all(),
- }
+ context['rodos'] = RODO.objects.all()
return context
@@ -123,7 +103,17 @@ class GrandPrixView(TemplateView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
- context['gp'] = GrandPrixB.objects.first()
+ context['gp'] = GrandPrixB.load()
+
+ return context
+
+
+class TournamentView(TemplateView):
+ template_name = "tournaments.html"
+
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ context['tournaments'] = Tournament.objects.all()
return context
@@ -136,3 +126,13 @@ class MembershipView(TemplateView):
context['memberships'] = Membership.objects.all()
return context
+
+
+class AtuView(TemplateView):
+ template_name = 'atu.html'
+
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ context['atu'] = Atu.load()
+
+ return context
diff --git a/db/administration/migrations/0010_alter_announcement_attachment_and_more.py b/db/administration/migrations/0010_alter_announcement_attachment_and_more.py
new file mode 100644
index 0000000..328ea28
--- /dev/null
+++ b/db/administration/migrations/0010_alter_announcement_attachment_and_more.py
@@ -0,0 +1,39 @@
+# Generated by Django 4.0.5 on 2022-07-25 00:35
+
+from django.db import migrations
+import filebrowser.fields
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('administration', '0009_protocol_extra'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='announcement',
+ name='attachment',
+ field=filebrowser.fields.FileBrowseField(max_length=200, verbose_name='Plik pdf'),
+ ),
+ migrations.AlterField(
+ model_name='protocol',
+ name='attachment',
+ field=filebrowser.fields.FileBrowseField(max_length=200, verbose_name='Plik pdf'),
+ ),
+ migrations.AlterField(
+ model_name='regulation',
+ name='attachment',
+ field=filebrowser.fields.FileBrowseField(max_length=200, verbose_name='Plik pdf'),
+ ),
+ migrations.AlterField(
+ model_name='rodo',
+ name='attachment',
+ field=filebrowser.fields.FileBrowseField(max_length=200, verbose_name='Plik pdf'),
+ ),
+ migrations.AlterField(
+ model_name='statute',
+ name='attachment',
+ field=filebrowser.fields.FileBrowseField(max_length=200, verbose_name='Plik pdf'),
+ ),
+ ]
diff --git a/db/administration/models.py b/db/administration/models.py
index e494e52..7b581ae 100644
--- a/db/administration/models.py
+++ b/db/administration/models.py
@@ -1,29 +1,34 @@
from django.db import models
from admin_ordering.models import OrderableModel
+from filebrowser.fields import FileBrowseField
from core.utils import SingletonModel
# Create your models here.
class AttachmentModel(OrderableModel):
- upload_to = 'zalaczniki'
title = models.CharField('Tytuł', max_length=250)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
- def _upload_to(self, filename):
- return f'zarzad_{self.upload_to}/{filename}'
+ def _upload_to():
+ return None
- attachment = models.FileField('Plik pdf', upload_to=_upload_to)
+ def upload_to():
+ return 'zalaczniki'
+
+ attachment = FileBrowseField(
+ 'Plik pdf', directory=upload_to, max_length=200, extensions=['.pdf', '.doc'])
class Meta(OrderableModel.Meta):
abstract = True
class Announcement(AttachmentModel):
- upload_to = 'ogloszenia'
+ def upload_to():
+ return 'zarzad_ogloszenia'
class Meta(OrderableModel.Meta):
verbose_name = 'Ogłoszenie'
@@ -44,7 +49,9 @@ class Member(OrderableModel):
class Protocol(AttachmentModel):
- upload_to = 'protokolyuchwaly'
+ def upload_to():
+ return 'zarzad_protokolyuchwaly'
+
extra = models.TextField('Dodatkowy opis', default='', blank=True)
year = models.IntegerField('Rok', blank=True, null=True)
@@ -55,7 +62,8 @@ class Protocol(AttachmentModel):
class Regulation(AttachmentModel):
- upload_to = 'regulaminy'
+ def upload_to():
+ return 'zarzad_regulaminy'
class Meta(OrderableModel.Meta):
verbose_name = 'Regulamin'
@@ -65,7 +73,8 @@ class Regulation(AttachmentModel):
class RODO(models.Model):
who = models.CharField(
'Przez kogo przetwarzane dane osobowe?', max_length=512)
- attachment = models.FileField('Plik pdf', upload_to='zarzad_rodo')
+ attachment = FileBrowseField(
+ 'Plik pdf', directory='zarzad_rodo', max_length=200, extensions=['.pdf', '.doc'])
def __str__(self):
return f'RODO - {self.who}'
@@ -77,7 +86,8 @@ class RODO(models.Model):
class Statute(SingletonModel):
title = models.CharField('Tytuł', max_length=250)
- attachment = models.FileField('Plik pdf', upload_to='zarzad_statuty')
+ attachment = FileBrowseField(
+ 'Plik pdf', directory='zarzad_statuty', max_length=200, extensions=['.pdf', '.doc'])
def __str__(self):
return self.title
diff --git a/db/atu/__init__.py b/db/atu/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/db/atu/apps.py b/db/atu/apps.py
new file mode 100644
index 0000000..a0d0d01
--- /dev/null
+++ b/db/atu/apps.py
@@ -0,0 +1,7 @@
+from django.apps import AppConfig
+
+
+class AtuConfig(AppConfig):
+ default_auto_field = 'django.db.models.BigAutoField'
+ name = 'db.atu'
+ verbose_name = 'Stowarzyszenie Brydżowe ATU'
diff --git a/db/atu/migrations/0001_initial.py b/db/atu/migrations/0001_initial.py
new file mode 100644
index 0000000..a49d27f
--- /dev/null
+++ b/db/atu/migrations/0001_initial.py
@@ -0,0 +1,26 @@
+# Generated by Django 4.0.5 on 2022-07-25 00:07
+
+from django.db import migrations, models
+import tinymce.models
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Atu',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('content', tinymce.models.HTMLField(verbose_name='Tekst')),
+ ],
+ options={
+ 'verbose_name': 'Stowarzyszenie Brydżowe ATU',
+ 'verbose_name_plural': 'Stowarzyszenie Brydżowe ATU',
+ },
+ ),
+ ]
diff --git a/db/atu/migrations/__init__.py b/db/atu/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/db/atu/models.py b/db/atu/models.py
new file mode 100644
index 0000000..2a1fa99
--- /dev/null
+++ b/db/atu/models.py
@@ -0,0 +1,16 @@
+from django.db import models
+from tinymce.models import HTMLField
+from core.utils import SingletonModel
+
+# Create your models here.
+
+
+class Atu(SingletonModel):
+ content = HTMLField('Tekst')
+
+ def __str__(self):
+ return 'Stowarzyszenie Brydżowe ATU'
+
+ class Meta:
+ verbose_name = 'Stowarzyszenie Brydżowe ATU'
+ verbose_name_plural = 'Stowarzyszenie Brydżowe ATU'
diff --git a/db/tournaments/admin.py b/db/tournaments/admin.py
new file mode 100644
index 0000000..ab5c413
--- /dev/null
+++ b/db/tournaments/admin.py
@@ -0,0 +1,13 @@
+from django.contrib import admin
+from admin_ordering.admin import OrderableAdmin
+from .models import *
+
+# Register your models here.
+
+
+@admin.register(Tournament)
+class TournamentModelAdmin(OrderableAdmin, admin.ModelAdmin):
+ list_display = ['title', 'ordering']
+ list_editable = ['ordering']
+ ordering_field_hide_input = True
+ exclude = ['ordering']
diff --git a/db/tournaments/migrations/0001_initial.py b/db/tournaments/migrations/0001_initial.py
new file mode 100644
index 0000000..82c34d8
--- /dev/null
+++ b/db/tournaments/migrations/0001_initial.py
@@ -0,0 +1,31 @@
+# Generated by Django 4.0.5 on 2022-07-24 23:13
+
+from django.db import migrations, models
+import tinymce.models
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Tournament',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('ordering', models.IntegerField(default=0, verbose_name='Kolejność')),
+ ('title', models.CharField(max_length=250, verbose_name='Tytuł')),
+ ('content', tinymce.models.HTMLField(verbose_name='Tekst')),
+ ('link', models.TextField(verbose_name='Link do wyników')),
+ ],
+ options={
+ 'verbose_name': 'Inny turniej',
+ 'verbose_name_plural': 'Inne turnieje',
+ 'ordering': ['ordering'],
+ 'abstract': False,
+ },
+ ),
+ ]
diff --git a/db/tournaments/migrations/0002_tournament_photo.py b/db/tournaments/migrations/0002_tournament_photo.py
new file mode 100644
index 0000000..a810f4b
--- /dev/null
+++ b/db/tournaments/migrations/0002_tournament_photo.py
@@ -0,0 +1,19 @@
+# Generated by Django 4.0.5 on 2022-07-24 23:23
+
+from django.db import migrations
+import filebrowser.fields
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('tournaments', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='tournament',
+ name='photo',
+ field=filebrowser.fields.FileBrowseField(blank=True, max_length=200, verbose_name='Zdjęcie'),
+ ),
+ ]
diff --git a/db/tournaments/models.py b/db/tournaments/models.py
index 71a8362..351deb1 100644
--- a/db/tournaments/models.py
+++ b/db/tournaments/models.py
@@ -1,3 +1,21 @@
from django.db import models
+from admin_ordering.models import OrderableModel
+from tinymce.models import HTMLField
+from filebrowser.fields import FileBrowseField
# Create your models here.
+
+
+class Tournament(OrderableModel):
+ photo = FileBrowseField(
+ 'Zdjęcie', directory='inneturnieje/', max_length=200, blank=True)
+ title = models.CharField('Tytuł', max_length=250)
+ content = HTMLField('Tekst')
+ link = models.TextField('Link do wyników')
+
+ def __str__(self):
+ return self.title
+
+ class Meta(OrderableModel.Meta):
+ verbose_name = 'Inny turniej'
+ verbose_name_plural = 'Inne turnieje'
diff --git a/filebrowser/fields.py b/filebrowser/fields.py
index 4441fad..8446414 100644
--- a/filebrowser/fields.py
+++ b/filebrowser/fields.py
@@ -44,17 +44,20 @@ class FileBrowseWidget(Input):
if value != "" and not isinstance(value, FileObject):
value = FileObject(value, site=self.site)
final_attrs = self.build_attrs(attrs, type=self.input_type, name=name)
- final_attrs['search_icon'] = static('filebrowser/img/filebrowser_icon_show.gif')
+ final_attrs['search_icon'] = static(
+ 'filebrowser/img/filebrowser_icon_show.gif')
final_attrs['url'] = url
final_attrs['directory'] = self.directory
final_attrs['extensions'] = self.extensions
final_attrs['format'] = self.format
final_attrs['ADMIN_THUMBNAIL'] = ADMIN_THUMBNAIL
- final_attrs['data_attrs'] = {k: v for k, v in final_attrs.items() if k.startswith('data-')}
+ final_attrs['data_attrs'] = {
+ k: v for k, v in final_attrs.items() if k.startswith('data-')}
filebrowser_site = self.site
if value != "":
try:
- final_attrs['directory'] = os.path.split(value.original.path_relative_directory)[0]
+ final_attrs['directory'] = os.path.split(
+ value.original.path_relative_directory)[0]
except:
pass
return render_to_string("filebrowser/custom_field.html", locals())
@@ -89,7 +92,8 @@ class FileBrowseFormField(forms.CharField):
return value
file_extension = os.path.splitext(value)[1].lower()
if self.extensions and file_extension not in self.extensions:
- raise forms.ValidationError(self.error_messages['extension'] % {'ext': file_extension, 'allowed': ", ".join(self.extensions)})
+ raise forms.ValidationError(self.error_messages['extension'] % {
+ 'ext': file_extension, 'allowed': ", ".join(self.extensions)})
return value
@@ -98,7 +102,8 @@ class FileBrowseField(CharField):
def __init__(self, *args, **kwargs):
self.site = kwargs.pop('filebrowser_site', site)
- self.directory = kwargs.pop('directory', '')
+ directory = kwargs.pop('directory', '')
+ self.directory = directory() if callable(directory) else directory
self.extensions = kwargs.pop('extensions', '')
self.format = kwargs.pop('format', '')
return super(FileBrowseField, self).__init__(*args, **kwargs)
@@ -139,6 +144,7 @@ class FileBrowseField(CharField):
}
return super(FileBrowseField, self).formfield(**defaults)
+
FORMFIELD_FOR_DBFIELD_DEFAULTS[FileBrowseField] = {'widget': FileBrowseWidget}
@@ -146,7 +152,8 @@ class FileBrowseUploadWidget(Input):
input_type = 'text'
class Media:
- js = ('filebrowser/js/AddFileBrowser.js', 'filebrowser/js/fileuploader.js',)
+ js = ('filebrowser/js/AddFileBrowser.js',
+ 'filebrowser/js/fileuploader.js',)
css = {
'all': (os.path.join('/static/filebrowser/css/uploadfield.css'),)
}
@@ -182,7 +189,8 @@ class FileBrowseUploadWidget(Input):
final_attrs['ADMIN_THUMBNAIL'] = ADMIN_THUMBNAIL
if value != "":
try:
- final_attrs['directory'] = os.path.split(value.original.path_relative_directory)[0]
+ final_attrs['directory'] = os.path.split(
+ value.original.path_relative_directory)[0]
except:
pass
return render_to_string("filebrowser/custom_upload_field.html", locals())
@@ -219,7 +227,8 @@ class FileBrowseUploadFormField(forms.CharField):
return value
file_extension = os.path.splitext(value)[1].lower()
if self.extensions and file_extension not in self.extensions:
- raise forms.ValidationError(self.error_messages['extension'] % {'ext': file_extension, 'allowed': ", ".join(self.extensions)})
+ raise forms.ValidationError(self.error_messages['extension'] % {
+ 'ext': file_extension, 'allowed': ", ".join(self.extensions)})
return value
@@ -284,6 +293,7 @@ class FileBrowseUploadField(CharField):
try:
from south.modelsinspector import add_introspection_rules
add_introspection_rules([], [r"^filebrowser\.fields\.FileBrowseField"])
- add_introspection_rules([], [r"^filebrowser\.fields\.FileBrowseUploadField"])
+ add_introspection_rules(
+ [], [r"^filebrowser\.fields\.FileBrowseUploadField"])
except:
pass
diff --git a/pdlzbs/settings.py b/pdlzbs/settings.py
index 10d2748..afb6ad1 100644
--- a/pdlzbs/settings.py
+++ b/pdlzbs/settings.py
@@ -50,6 +50,7 @@ INSTALLED_APPS = [
'db.gpb',
'db.tournaments',
'db.membership',
+ 'db.atu',
'theme',
'core'
] + [
diff --git a/theme/static/css/dist/styles.css b/theme/static/css/dist/styles.css
index bafd6b7..75a0c98 100644
--- a/theme/static/css/dist/styles.css
+++ b/theme/static/css/dist/styles.css
@@ -1255,6 +1255,10 @@ select {
margin-bottom: auto;
}
+.ml-auto {
+ margin-left: auto;
+}
+
.box-content {
box-sizing: content-box;
}
@@ -1311,6 +1315,18 @@ select {
max-height: 3rem;
}
+.max-h-64 {
+ max-height: 16rem;
+}
+
+.max-h-96 {
+ max-height: 24rem;
+}
+
+.max-h-72 {
+ max-height: 18rem;
+}
+
.min-h-\[125px\] {
min-height: 125px;
}
@@ -1327,6 +1343,10 @@ select {
width: 48px;
}
+.w-36 {
+ width: 9rem;
+}
+
.min-w-\[145px\] {
min-width: 145px;
}
@@ -1339,6 +1359,12 @@ select {
max-width: 100%;
}
+.max-w-fit {
+ max-width: -webkit-fit-content;
+ max-width: -moz-fit-content;
+ max-width: fit-content;
+}
+
.grow-0 {
flex-grow: 0;
}
@@ -1507,6 +1533,11 @@ select {
border-color: rgb(214 211 209 / var(--tw-border-opacity));
}
+.border-red-200 {
+ --tw-border-opacity: 1;
+ border-color: rgb(254 202 202 / var(--tw-border-opacity));
+}
+
.bg-white {
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
@@ -1552,6 +1583,11 @@ select {
background-color: rgb(239 246 255 / var(--tw-bg-opacity));
}
+.bg-red-100 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(254 226 226 / var(--tw-bg-opacity));
+}
+
.p-4 {
padding: 1rem;
}
@@ -1592,6 +1628,10 @@ select {
padding-bottom: 1.5rem;
}
+.pb-4 {
+ padding-bottom: 1rem;
+}
+
.text-left {
text-align: left;
}
@@ -1604,6 +1644,14 @@ select {
text-align: right;
}
+.align-baseline {
+ vertical-align: baseline;
+}
+
+.align-middle {
+ vertical-align: middle;
+}
+
.font-serif {
font-family: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
}
@@ -1686,6 +1734,14 @@ select {
line-height: 1.5;
}
+.leading-3 {
+ line-height: .75rem;
+}
+
+.leading-none {
+ line-height: 1;
+}
+
.tracking-normal {
letter-spacing: 0em;
}
@@ -1695,6 +1751,11 @@ select {
color: rgb(255 255 255 / var(--tw-text-opacity));
}
+.no-underline {
+ -webkit-text-decoration-line: none;
+ text-decoration-line: none;
+}
+
.antialiased {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
@@ -1770,6 +1831,11 @@ select {
border-color: rgb(165 180 252 / var(--tw-border-opacity));
}
+.hover\:border-red-300:hover {
+ --tw-border-opacity: 1;
+ border-color: rgb(252 165 165 / var(--tw-border-opacity));
+}
+
.hover\:bg-pink-200:hover {
--tw-bg-opacity: 1;
background-color: rgb(251 207 232 / var(--tw-bg-opacity));
@@ -1790,6 +1856,11 @@ select {
background-color: rgb(199 210 254 / var(--tw-bg-opacity));
}
+.hover\:bg-red-200:hover {
+ --tw-bg-opacity: 1;
+ background-color: rgb(254 202 202 / var(--tw-bg-opacity));
+}
+
.prose-h2\:text-center :is(:where(h2):not(:where([class~="not-prose"] *))) {
text-align: center;
}
@@ -1829,6 +1900,10 @@ select {
font-weight: 400;
}
+.prose-a\:text-center :is(:where(a):not(:where([class~="not-prose"] *))) {
+ text-align: center;
+}
+
@media (min-width: 1024px) {
.lg\:flex-row {
flex-direction: row;