diff --git a/apps/participation/forms.py b/apps/participation/forms.py
index 45839d9..3d0d829 100644
--- a/apps/participation/forms.py
+++ b/apps/participation/forms.py
@@ -1,10 +1,11 @@
import re
+from bootstrap_datepicker_plus import DateTimePickerInput
from django import forms
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
-from .models import Participation, Team, Video
+from .models import Participation, Phase, Team, Video
class TeamForm(forms.ModelForm):
@@ -72,3 +73,13 @@ class UploadVideoForm(forms.ModelForm):
class Meta:
model = Video
fields = ('link',)
+
+
+class PhaseForm(forms.ModelForm):
+ class Meta:
+ model = Phase
+ fields = ('start', 'end',)
+ widgets = {
+ 'start': DateTimePickerInput(),
+ 'end': DateTimePickerInput(),
+ }
diff --git a/apps/participation/templates/participation/phase_form.html b/apps/participation/templates/participation/phase_form.html
new file mode 100644
index 0000000..a5bb901
--- /dev/null
+++ b/apps/participation/templates/participation/phase_form.html
@@ -0,0 +1,14 @@
+{% extends "base.html" %}
+
+{% load crispy_forms_filters i18n %}
+
+{% block content %}
+
+{% endblock content %}
+
diff --git a/apps/participation/urls.py b/apps/participation/urls.py
index 121dc75..54efc74 100644
--- a/apps/participation/urls.py
+++ b/apps/participation/urls.py
@@ -1,7 +1,7 @@
from django.urls import path
from .views import CalendarView, CreateTeamView, JoinTeamView, MyParticipationDetailView, MyTeamDetailView, \
- ParticipationDetailView,TeamAuthorizationsView, TeamDetailView, TeamUpdateView, UploadVideoView
+ ParticipationDetailView, PhaseUpdateView, TeamAuthorizationsView, TeamDetailView, TeamUpdateView, UploadVideoView
app_name = "participation"
@@ -17,4 +17,5 @@ urlpatterns = [
path("detail//", ParticipationDetailView.as_view(), name="participation_detail"),
path("detail/upload-video//", UploadVideoView.as_view(), name="upload_video"),
path("calendar/", CalendarView.as_view(), name="calendar"),
+ path("calendar//", PhaseUpdateView.as_view(), name="update_phase"),
]
diff --git a/apps/participation/views.py b/apps/participation/views.py
index d777916..97b18ef 100644
--- a/apps/participation/views.py
+++ b/apps/participation/views.py
@@ -3,6 +3,7 @@ import os
from zipfile import ZipFile
from corres2math.lists import get_sympa_client
+from corres2math.views import AdminMixin
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.exceptions import PermissionDenied
from django.core.mail import send_mail
@@ -17,7 +18,7 @@ from django_tables2 import SingleTableView
from magic import Magic
from registration.models import AdminRegistration
-from .forms import JoinTeamForm, ParticipationForm, RequestValidationForm, TeamForm, UploadVideoForm,\
+from .forms import JoinTeamForm, ParticipationForm, PhaseForm, RequestValidationForm, TeamForm, UploadVideoForm,\
ValidateParticipationForm
from .models import Participation, Phase, Team, Video
from .tables import CalendarTable
@@ -281,3 +282,8 @@ class UploadVideoView(LoginRequiredMixin, UpdateView):
class CalendarView(SingleTableView):
table_class = CalendarTable
model = Phase
+
+
+class PhaseUpdateView(AdminMixin, UpdateView):
+ model = Phase
+ form_class = PhaseForm
diff --git a/corres2math/inputs.py b/corres2math/inputs.py
deleted file mode 100644
index 67838fc..0000000
--- a/corres2math/inputs.py
+++ /dev/null
@@ -1,322 +0,0 @@
-from json import dumps as json_dumps
-
-from django.forms.widgets import DateTimeBaseInput, NumberInput, TextInput, Widget
-
-
-class AmountInput(NumberInput):
- """
- This input type lets the user type amounts in euros, but forms receive data in cents
- """
- template_name = "amount_input.html"
-
- def format_value(self, value):
- return None if value is None or value == "" else "{:.02f}".format(int(value) / 100, )
-
- def value_from_datadict(self, data, files, name):
- val = super().value_from_datadict(data, files, name)
- return str(int(100 * float(val))) if val else val
-
-
-class Autocomplete(TextInput):
- template_name = "autocomplete_model.html"
-
- def __init__(self, model, attrs=None):
- super().__init__(attrs)
-
- self.model = model
- self.model_pk = None
-
- class Media:
- """JS/CSS resources needed to render the date-picker calendar."""
-
- js = ('js/autocomplete_model.js', )
-
- def format_value(self, value):
- if value:
- self.attrs["model_pk"] = int(value)
- return str(self.model.objects.get(pk=int(value)))
- return ""
-
-
-class ColorWidget(Widget):
- """
- Pulled from django-colorfield.
- Select a color.
- """
- template_name = 'colorfield/color.html'
-
- class Media:
- js = [
- 'colorfield/jscolor/jscolor.min.js',
- 'colorfield/colorfield.js',
- ]
-
- def format_value(self, value):
- if value is None:
- value = 0xFFFFFF
- return "#{:06X}".format(value)
-
- def value_from_datadict(self, data, files, name):
- val = super().value_from_datadict(data, files, name)
- return int(val[1:], 16)
-
-
-"""
-The remaining of this file comes from the project `django-bootstrap-datepicker-plus` available on Github:
-https://github.com/monim67/django-bootstrap-datepicker-plus
-This is distributed under Apache License 2.0.
-
-This adds datetime pickers with bootstrap.
-"""
-
-"""Contains Base Date-Picker input class for widgets of this package."""
-
-
-class DatePickerDictionary:
- """Keeps track of all date-picker input classes."""
-
- _i = 0
- items = dict()
-
- @classmethod
- def generate_id(cls):
- """Return a unique ID for each date-picker input class."""
- cls._i += 1
- return 'dp_%s' % cls._i
-
-
-class BasePickerInput(DateTimeBaseInput):
- """Base Date-Picker input class for widgets of this package."""
-
- template_name = 'bootstrap_datepicker_plus/date_picker.html'
- picker_type = 'DATE'
- format = '%Y-%m-%d'
- config = {}
- _default_config = {
- 'id': None,
- 'picker_type': None,
- 'linked_to': None,
- 'options': {} # final merged options
- }
- options = {} # options extended by user
- options_param = {} # options passed as parameter
- _default_options = {
- 'showClose': True,
- 'showClear': True,
- 'showTodayButton': True,
- "locale": "fr",
- }
-
- # source: https://github.com/tutorcruncher/django-bootstrap3-datetimepicker
- # file: /blob/31fbb09/bootstrap3_datetime/widgets.py#L33
- format_map = (
- ('DDD', r'%j'),
- ('DD', r'%d'),
- ('MMMM', r'%B'),
- ('MMM', r'%b'),
- ('MM', r'%m'),
- ('YYYY', r'%Y'),
- ('YY', r'%y'),
- ('HH', r'%H'),
- ('hh', r'%I'),
- ('mm', r'%M'),
- ('ss', r'%S'),
- ('a', r'%p'),
- ('ZZ', r'%z'),
- )
-
- class Media:
- """JS/CSS resources needed to render the date-picker calendar."""
-
- js = (
- 'https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.9.0/'
- 'moment-with-locales.min.js',
- 'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/'
- '4.17.47/js/bootstrap-datetimepicker.min.js',
- 'bootstrap_datepicker_plus/js/datepicker-widget.js'
- )
- css = {'all': (
- 'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/'
- '4.17.47/css/bootstrap-datetimepicker.css',
- 'bootstrap_datepicker_plus/css/datepicker-widget.css'
- ), }
-
- @classmethod
- def format_py2js(cls, datetime_format):
- """Convert python datetime format to moment datetime format."""
- for js_format, py_format in cls.format_map:
- datetime_format = datetime_format.replace(py_format, js_format)
- return datetime_format
-
- @classmethod
- def format_js2py(cls, datetime_format):
- """Convert moment datetime format to python datetime format."""
- for js_format, py_format in cls.format_map:
- datetime_format = datetime_format.replace(js_format, py_format)
- return datetime_format
-
- def __init__(self, attrs=None, format=None, options=None):
- """Initialize the Date-picker widget."""
- self.format_param = format
- self.options_param = options if options else {}
- self.config = self._default_config.copy()
- self.config['id'] = DatePickerDictionary.generate_id()
- self.config['picker_type'] = self.picker_type
- self.config['options'] = self._calculate_options()
- attrs = attrs if attrs else {}
- if 'class' not in attrs:
- attrs['class'] = 'form-control'
- super().__init__(attrs, self._calculate_format())
-
- def _calculate_options(self):
- """Calculate and Return the options."""
- _options = self._default_options.copy()
- _options.update(self.options)
- if self.options_param:
- _options.update(self.options_param)
- return _options
-
- def _calculate_format(self):
- """Calculate and Return the datetime format."""
- _format = self.format_param if self.format_param else self.format
- if self.config['options'].get('format'):
- _format = self.format_js2py(self.config['options'].get('format'))
- else:
- self.config['options']['format'] = self.format_py2js(_format)
- return _format
-
- def get_context(self, name, value, attrs):
- """Return widget context dictionary."""
- context = super().get_context(
- name, value, attrs)
- context['widget']['attrs']['dp_config'] = json_dumps(self.config)
- return context
-
- def start_of(self, event_id):
- """
- Set Date-Picker as the start-date of a date-range.
-
- Args:
- - event_id (string): User-defined unique id for linking two fields
- """
- DatePickerDictionary.items[str(event_id)] = self
- return self
-
- def end_of(self, event_id, import_options=True):
- """
- Set Date-Picker as the end-date of a date-range.
-
- Args:
- - event_id (string): User-defined unique id for linking two fields
- - import_options (bool): inherit options from start-date input,
- default: TRUE
- """
- event_id = str(event_id)
- if event_id in DatePickerDictionary.items:
- linked_picker = DatePickerDictionary.items[event_id]
- self.config['linked_to'] = linked_picker.config['id']
- if import_options:
- backup_moment_format = self.config['options']['format']
- self.config['options'].update(linked_picker.config['options'])
- self.config['options'].update(self.options_param)
- if self.format_param or 'format' in self.options_param:
- self.config['options']['format'] = backup_moment_format
- else:
- self.format = linked_picker.format
- # Setting useCurrent is necessary, see following issue
- # https://github.com/Eonasdan/bootstrap-datetimepicker/issues/1075
- self.config['options']['useCurrent'] = False
- self._link_to(linked_picker)
- else:
- raise KeyError(
- 'start-date not specified for event_id "%s"' % event_id)
- return self
-
- def _link_to(self, linked_picker):
- """
- Executed when two date-inputs are linked together.
-
- This method for sub-classes to override to customize the linking.
- """
- pass
-
-
-class DatePickerInput(BasePickerInput):
- """
- Widget to display a Date-Picker Calendar on a DateField property.
-
- Args:
- - attrs (dict): HTML attributes of rendered HTML input
- - format (string): Python DateTime format eg. "%Y-%m-%d"
- - options (dict): Options to customize the widget, see README
- """
-
- picker_type = 'DATE'
- format = '%Y-%m-%d'
- format_key = 'DATE_INPUT_FORMATS'
-
-
-class TimePickerInput(BasePickerInput):
- """
- Widget to display a Time-Picker Calendar on a TimeField property.
-
- Args:
- - attrs (dict): HTML attributes of rendered HTML input
- - format (string): Python DateTime format eg. "%Y-%m-%d"
- - options (dict): Options to customize the widget, see README
- """
-
- picker_type = 'TIME'
- format = '%H:%M'
- format_key = 'TIME_INPUT_FORMATS'
- template_name = 'bootstrap_datepicker_plus/time_picker.html'
-
-
-class DateTimePickerInput(BasePickerInput):
- """
- Widget to display a DateTime-Picker Calendar on a DateTimeField property.
-
- Args:
- - attrs (dict): HTML attributes of rendered HTML input
- - format (string): Python DateTime format eg. "%Y-%m-%d"
- - options (dict): Options to customize the widget, see README
- """
-
- picker_type = 'DATETIME'
- format = '%Y-%m-%d %H:%M'
- format_key = 'DATETIME_INPUT_FORMATS'
-
-
-class MonthPickerInput(BasePickerInput):
- """
- Widget to display a Month-Picker Calendar on a DateField property.
-
- Args:
- - attrs (dict): HTML attributes of rendered HTML input
- - format (string): Python DateTime format eg. "%Y-%m-%d"
- - options (dict): Options to customize the widget, see README
- """
-
- picker_type = 'MONTH'
- format = '01/%m/%Y'
- format_key = 'DATE_INPUT_FORMATS'
-
-
-class YearPickerInput(BasePickerInput):
- """
- Widget to display a Year-Picker Calendar on a DateField property.
-
- Args:
- - attrs (dict): HTML attributes of rendered HTML input
- - format (string): Python DateTime format eg. "%Y-%m-%d"
- - options (dict): Options to customize the widget, see README
- """
-
- picker_type = 'YEAR'
- format = '01/01/%Y'
- format_key = 'DATE_INPUT_FORMATS'
-
- def _link_to(self, linked_picker):
- """Customize the options when linked with other date-time input"""
- yformat = self.config['options']['format'].replace('-01-01', '-12-31')
- self.config['options']['format'] = yformat
diff --git a/corres2math/views.py b/corres2math/views.py
index 7ee3d7c..c777822 100644
--- a/corres2math/views.py
+++ b/corres2math/views.py
@@ -1,13 +1,16 @@
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.exceptions import PermissionDenied
-from django.utils.translation import gettext_lazy as _
from haystack.generic_views import SearchView
-class AdminSearchView(LoginRequiredMixin, SearchView):
+class AdminMixin(LoginRequiredMixin):
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return self.handle_no_permission()
if not request.user.registration.is_admin:
- raise PermissionDenied(_("Only administrators are allowed to perform a full research."))
+ raise PermissionDenied
return super().dispatch(request, *args, **kwargs)
+
+
+class AdminSearchView(AdminMixin, SearchView):
+ pass