diff --git a/Makefile b/Makefile index d42be96a..495e6bfc 100644 --- a/Makefile +++ b/Makefile @@ -85,6 +85,8 @@ push_test: ./manage.py migrate --noinput && \ (chown -Rf :mam . || true ) && \ (chmod -Rf g+w . || true ) && \ + echo 'Reloading apache ... (You may have to start it manually on error!)' && \ + ~/etc/apache2/apache2ctl -k reload && \ echo Done." @echo "Test pushed to ${TEST_SERVER}:${TEST_DIR} successfully." @@ -93,6 +95,8 @@ push_prod: git tag deploy-prod-`date +%Y-%m-%d-%H-%M`-${USER} git push --all ssh ${PROD_USER}@${PROD_SERVER} -n -x "\ + echo 'Stopping apache ... (You may have to start it manually on error!)' && \ + ~/etc/apache2/apache2ctl -k stop && \ cd ${PROD_DIR} && \ ./backup_prod_db.sh && \ git fetch --all && \ @@ -104,6 +108,8 @@ push_prod: ./manage.py migrate --noinput && \ (chown -Rf :mam . || true ) && \ (chmod -Rf g+w . || true ) && \ + echo 'Starting apache ... (You may have to start it manually on error!)' && \ + ~/etc/apache2/apache2ctl -k start && \ echo Done." @echo "Deployed to ${PROD_SERVER}:${PROD_DIR} successfully." diff --git a/mamweb/admin.py b/mamweb/admin.py new file mode 100644 index 00000000..402f34ca --- /dev/null +++ b/mamweb/admin.py @@ -0,0 +1,24 @@ +from django.contrib import admin +from django.contrib.flatpages.models import FlatPage + +# Note: we are renaming the original Admin and Form as we import them! +from django.contrib.flatpages.admin import FlatPageAdmin as FlatPageAdminOld +from django.contrib.flatpages.admin import FlatpageForm as FlatpageFormOld + +from django import forms +from ckeditor.widgets import CKEditorWidget + +class FlatpageForm(FlatpageFormOld): + content = forms.CharField(widget=CKEditorWidget()) + class Meta: + model = FlatPage # this is not automatically inherited from FlatpageFormOld + exclude = [] + + +class FlatPageAdmin(FlatPageAdminOld): + form = FlatpageForm + + +# We have to unregister the normal admin, and then reregister ours +admin.site.unregister(FlatPage) +admin.site.register(FlatPage, FlatPageAdmin) diff --git a/mamweb/settings_common.py b/mamweb/settings_common.py index 18949127..b63e27a1 100644 --- a/mamweb/settings_common.py +++ b/mamweb/settings_common.py @@ -64,6 +64,7 @@ MIDDLEWARE_CLASSES = ( 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware', ) TEMPLATE_CONTEXT_PROCESSORS = ( @@ -104,6 +105,8 @@ INSTALLED_APPS = ( 'threadedcomments', 'django_comments', + 'django.contrib.flatpages', + # MaMweb 'mamweb', 'seminar', @@ -117,7 +120,6 @@ INSTALLED_APPS = ( # 'admin_tools.menu', # 'admin_tools.dashboard', 'flat', - 'django.contrib.admin', ) diff --git a/mamweb/templates/base.html b/mamweb/templates/base.html index f9dcf422..ff931421 100644 --- a/mamweb/templates/base.html +++ b/mamweb/templates/base.html @@ -21,8 +21,12 @@
{% if view.object %} - Objekt {{ view.object }}: {{ view.object }} - {% if view.object.admin_url %}[admin]{% endif %} + Objekt {{ view.object }}: {{ view.object }} + {% if view.object.admin_url %}[admin]{% endif %} + {% endif %} + {% if flatpage %} + Stránka {{ flatpage.url }} ({{ flatpage.title }}) + [admin] {% endif %}
diff --git a/mamweb/templates/flatpages/default.html b/mamweb/templates/flatpages/default.html new file mode 100644 index 00000000..d4d45502 --- /dev/null +++ b/mamweb/templates/flatpages/default.html @@ -0,0 +1,11 @@ +{% extends "base.html" %} + +{% block title %}{{ flatpage.title }}{% endblock title %} + +{% block content %} +

{{ flatpage.title }}

+
+{{ flatpage.content }} +
+{% endblock content %} + diff --git a/mamweb/templates/home.html b/mamweb/templates/home.html index 90c697d4..2998b0f7 100644 --- a/mamweb/templates/home.html +++ b/mamweb/templates/home.html @@ -1,9 +1,13 @@ {% extends "base.html" %} +{% block title %}{{ flatpage.title }}{% endblock title %} + {% block content %} -
-

Vítejte na testwebu MaM!

+
Toto je stránka podle šablony "home.html"

Administrátorské rozhraní (admin/admin) +

{{ flatpage.title }}

+
+{{ flatpage.content }}
{% endblock content %} diff --git a/mamweb/urls.py b/mamweb/urls.py index 56b8ce6e..c51c72a4 100644 --- a/mamweb/urls.py +++ b/mamweb/urls.py @@ -19,9 +19,8 @@ urlpatterns = i18n_patterns('', url(r'^comments_dj/', include('django_comments.urls')), url(r'^comments_fl/', include('fluent_comments.urls')), - # Obsah - url(r'^$', TemplateView.as_view(template_name='home.html'), name='home'), - + # Obsah - flatpages + url(r'^', include('django.contrib.flatpages.urls')), # Pozor: musi byt posledni ) # This is only needed when using runserver. diff --git a/seminar/admin.py b/seminar/admin.py index d83fd92f..dcd2ca5e 100644 --- a/seminar/admin.py +++ b/seminar/admin.py @@ -17,6 +17,25 @@ import autocomplete_light admin.site.register(Nastaveni, SingletonModelAdmin) +### UTILS (pro verbose_name a help_text) + +def field_labels(model, fieldname): + f = [i for i in model._meta.fields if i.name == fieldname][0] + return {'label': f.verbose_name.capitalize(), 'help_text': f.help_text, } + +def create_modeladmin(modeladmin, model, name = None, verbose_name = None, verbose_name_plural = None): + + class Meta: + proxy = True + app_label = model._meta.app_label + Meta.verbose_name = verbose_name + Meta.verbose_name_plural = verbose_name_plural + + attrs = {'__module__': '', 'Meta': Meta} + newmodel = type(name, (model,), attrs) + admin.site.register(newmodel, modeladmin) + return modeladmin + ### INLINES class ResitelInline(admin.TabularInline): @@ -224,10 +243,12 @@ admin.site.register(Reseni, ReseniAdmin) from autocomplete_light.contrib.taggit_field import TaggitField, TaggitWidget #TODO: Autocomplete autor/opravovatel + class ProblemAdminForm(forms.ModelForm): - text_problemu = forms.CharField(widget=CKEditorWidget()) - text_problemu_org = forms.CharField(widget=CKEditorWidget()) - zamereni = TaggitField(widget=TaggitWidget('TagAutocomplete')) + text_zadani = forms.CharField(widget=CKEditorWidget(), required=False, **field_labels(Problem, 'text_zadani')) + text_reseni = forms.CharField(widget=CKEditorWidget(), required=False, **field_labels(Problem, 'text_reseni')) + text_org = forms.CharField(widget=CKEditorWidget(), required=False, **field_labels(Problem, 'text_org')) + zamereni = TaggitField(widget=TaggitWidget('TagAutocomplete'), required=False) class Meta: model = Problem exclude = [] @@ -236,32 +257,56 @@ class ProblemAdmin(reversion.VersionAdmin): form = ProblemAdminForm fieldsets = [ (None, {'fields': ['nazev', 'typ', 'stav', 'autor', 'zamereni', 'body', 'timestamp', 'import_dakos_id']}), - (u'Vydání', {'fields': ['cislo_zadani', 'kod', 'cislo_reseni', 'opravovatel', 'text_problemu']}), - (None, {'fields': ['text_problemu_org']}), + (u'Vydání', {'fields': ['cislo_zadani', 'kod', 'cislo_reseni', 'opravovatel',]}), + (None, {'fields': ['text_zadani', 'text_reseni', 'text_org',]}), ] readonly_fields = ['timestamp', 'import_dakos_id'] - list_display = ['nazev', 'typ', 'kod', 'stav', 'autor', 'opravovatel', 'verejne', 'cislo_zadani', 'pocet_reseni'] list_select_related = True - list_filter = ['typ', 'stav', 'timestamp'] - search_fields = ['nazev', 'kod', 'text_problemu_org', 'text_problemu'] - inlines = [ReseniKProblemuInline] + search_fields = ['nazev', 'text_zadani', 'text_reseni', 'text_org'] view_on_site = Problem.verejne_url def get_queryset(self, request): qs = super(ProblemAdmin, self).get_queryset(request) - return qs.select_related('autor', 'opravovatel', 'cislo_zadani', 'cislo_reseni').annotate(pocet_reseni=Count('reseni')) + return qs.select_related('autor', 'opravovatel', 'cislo_zadani', 'cislo_reseni') def pocet_reseni(self, obj): return obj.pocet_reseni -admin.site.register(Problem, ProblemAdmin) +class ProblemNavrhAdmin(ProblemAdmin): + list_display = ['nazev', 'typ', 'stav', 'autor', 'timestamp'] + list_filter = ['typ', 'stav', 'timestamp'] + + def get_queryset(self, request): + qs = super(ProblemNavrhAdmin, self).get_queryset(request) + return qs.filter(stav__in=[Problem.STAV_NAVRH, Problem.STAV_SMAZANY]) +create_modeladmin(ProblemNavrhAdmin, Problem, 'ProblemNavrh', verbose_name=u'Problém (návrh)', verbose_name_plural=u'Problémy (návrhy)') + +class ProblemZadanyAdmin(ProblemAdmin): + list_display = ['nazev', 'typ', 'autor', 'opravovatel', 'kod', 'cislo_zadani', 'pocet_reseni', 'verejne'] + list_filter = ['typ', 'cislo_zadani__rocnik'] + inlines = [ReseniKProblemuInline] + + def get_queryset(self, request): + qs = super(ProblemZadanyAdmin, self).get_queryset(request) + return qs.filter(stav=Problem.STAV_ZADANY).annotate(pocet_reseni=Count('reseni')) + +create_modeladmin(ProblemZadanyAdmin, Problem, 'ProblemZadany', verbose_name=u'Problém (zadaný)', verbose_name_plural=u'Problémy (zadané)') + +#admin.site.register(Problem, ProblemAdmin) ### Soustredeni +class SoustredeniAdminForm(forms.ModelForm): + text = forms.CharField(widget=CKEditorWidget(), required=False, **field_labels(Soustredeni, 'text')) + class Meta: + model = Soustredeni + exclude = [] + class SoustredeniAdmin(reversion.VersionAdmin): + form = SoustredeniAdminForm fieldsets = [ - (None, {'fields': ['rocnik', 'misto', 'verejne_db']}), + (None, {'fields': ['rocnik', 'misto', 'verejne_db', 'text']}), (u'Data', {'fields': ['datum_zacatku', 'datum_konce']}), ] list_display = ['rocnik', 'misto', 'datum_zacatku', 'verejne'] diff --git a/seminar/migrations/0015_soustredeni_text.py b/seminar/migrations/0015_soustredeni_text.py new file mode 100644 index 00000000..87298eba --- /dev/null +++ b/seminar/migrations/0015_soustredeni_text.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('seminar', '0014_uprava_poznamek'), + ] + + operations = [ + migrations.AddField( + model_name='soustredeni', + name='text', + field=models.TextField(default=b'', verbose_name='text k soust\u0159ed\u011bn\xed (HTML)', blank=True), + preserve_default=True, + ), + ] diff --git a/seminar/migrations/0016_texty_problemu.py b/seminar/migrations/0016_texty_problemu.py new file mode 100644 index 00000000..451c888e --- /dev/null +++ b/seminar/migrations/0016_texty_problemu.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('seminar', '0015_soustredeni_text'), + ] + + operations = [ + migrations.RenameField( + model_name='problem', + old_name='text_problemu_org', + new_name='text_org', + ), + migrations.RenameField( + model_name='problem', + old_name='text_problemu', + new_name='text_zadani', + ), + migrations.AddField( + model_name='problem', + name='text_reseni', + field=models.TextField(help_text='Ve\u0159ejn\xfd text \u0159e\u0161en\xed (HTML, u t\xe9mat i p\u0159\xedsp\u011bvky a koment\xe1\u0159e)', verbose_name='ve\u0159ejn\xe9 \u0159e\u0161en\xed (HTML)', blank=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='problem', + name='text_org', + field=models.TextField(help_text='Neve\u0159ejn\xfd n\xe1vrh \xfalohy, n\xe1vrh \u0159e\u0161en\xed, text zad\xe1n\xed, pozn\xe1mky ...', verbose_name='org pozn\xe1mky (HTML)', blank=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='problem', + name='text_zadani', + field=models.TextField(help_text='Ve\u0159ejn\xfd text zad\xe1n\xed (HTML)', verbose_name='ve\u0159ejn\xe9 zad\xe1n\xed (HTML)', blank=True), + preserve_default=True, + ), + ] diff --git a/seminar/migrations/0017_texty_problemu_minor.py b/seminar/migrations/0017_texty_problemu_minor.py new file mode 100644 index 00000000..f732c111 --- /dev/null +++ b/seminar/migrations/0017_texty_problemu_minor.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('seminar', '0016_texty_problemu'), + ] + + operations = [ + migrations.AlterField( + model_name='problem', + name='text_reseni', + field=models.TextField(help_text='Ve\u0159ejn\xfd text \u0159e\u0161en\xed (HTML, u t\xe9mat i p\u0159\xedsp\u011bvky a koment\xe1\u0159e)', verbose_name='ve\u0159ejn\xe9 \u0159e\u0161en\xed (HTML)', blank=True), + preserve_default=True, + ), + ] diff --git a/seminar/migrations/0018_problemnavrh_problemzadany.py b/seminar/migrations/0018_problemnavrh_problemzadany.py new file mode 100644 index 00000000..afdcfa8c --- /dev/null +++ b/seminar/migrations/0018_problemnavrh_problemzadany.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('seminar', '0017_texty_problemu_minor'), + ] + + operations = [ + migrations.CreateModel( + name='ProblemNavrh', + fields=[ + ], + options={ + 'verbose_name': 'Probl\xe9m (n\xe1vrh)', + 'proxy': True, + 'verbose_name_plural': 'Probl\xe9my (n\xe1vrhy)', + }, + bases=('seminar.problem',), + ), + migrations.CreateModel( + name='ProblemZadany', + fields=[ + ], + options={ + 'verbose_name': 'Probl\xe9m (zadan\xfd)', + 'proxy': True, + 'verbose_name_plural': 'Probl\xe9my (zadan\xe9)', + }, + bases=('seminar.problem',), + ), + ] diff --git a/seminar/models.py b/seminar/models.py index c5a7cf44..9be4a1b8 100644 --- a/seminar/models.py +++ b/seminar/models.py @@ -348,9 +348,14 @@ class Problem(SeminarModelBase): zamereni = TaggableManager(verbose_name=u'zaměření', help_text='Zaměření M/F/I/O problému, příp. další tagy', blank=True) - text_problemu_org = models.TextField(u'neveřejné zadání a organizátorské a poznámky', blank=True) + text_org = models.TextField(u'org poznámky (HTML)', blank=True, + help_text=u'Neveřejný návrh úlohy, návrh řešení, text zadání, poznámky ...') - text_problemu = models.TextField(u'veřejný text zadání a řešení', blank=True) + text_zadani = models.TextField(u'veřejné zadání (HTML)', blank=True, + help_text=u'Veřejný text zadání (HTML)') + + text_reseni = models.TextField(u'veřejné řešení (HTML)', blank=True, + help_text=u'Veřejný text řešení (HTML, u témat i příspěvky a komentáře)') autor = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=u'autor problému', related_name='autor_uloh', null=True, blank=True) @@ -391,6 +396,12 @@ class Problem(SeminarModelBase): def verejne_url(self): return reverse('seminar_problem', kwargs={'pk': self.id}) + def admin_url(self): + if self.stav == Problem.STAV_ZADANY: + return reverse('admin:seminar_problemzadany_change', args=(self.id, )) + else: + return reverse('admin:seminar_problemnavrh_change', args=(self.id, )) + @reversion.register(ignore_duplicate_revisions=True) @python_2_unicode_compatible @@ -498,6 +509,8 @@ class Soustredeni(SeminarModelBase): ucastnici = models.ManyToManyField(Resitel, verbose_name=u'účastníci soustředění', help_text=u'Seznam účastníků soustředění', through='Soustredeni_Ucastnici') + text = models.TextField(u'text k soustředění (HTML)', blank=True, default='') + def __str__(self): return force_unicode(u'%s (%s)' % (self.misto, self.datum_zacatku)) diff --git a/seminar/templates/seminar/problem.html b/seminar/templates/seminar/problem.html index f7778281..bcec4b93 100644 --- a/seminar/templates/seminar/problem.html +++ b/seminar/templates/seminar/problem.html @@ -5,7 +5,7 @@ {% block content %}
{% if problem.cislo_zadani %} -

Problém {{ problem.kod_v_rocniku }} {{ problem.nazev }}

+

Problém {{ problem.kod_v_rocniku }}: {{ problem.nazev }}

Zadáno v čísle {{ problem.cislo_zadani.kod }}. {% if problem.cislo_reseni %} @@ -16,14 +16,17 @@ {% endif %} -

Text

- {{ problem.text_problemu |safe }} +

Zadání

+ {{ problem.text_zadani |safe }} + +

Řešení

+ {{ problem.text_reseni |safe }} {% if True %}

Text - org

- {{ problem.text_problemu_org |safe }} + {{ problem.text_org |safe }}

Diskuse - org

{% render_comment_list for object %}