chrono/chrono/apps/ants_hub/views.py

242 lines
7.8 KiB
Python

# chrono - agendas system
# Copyright (C) 2023 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from django import forms
from django.contrib import messages
from django.core.cache import cache
from django.shortcuts import get_object_or_404, redirect
from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView, DeleteView, ListView, TemplateView, UpdateView
from . import hub, models
class Homepage(ListView):
template_name = 'chrono/manager_ants_hub.html'
model = models.City
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
ok = cache.get('ants-hub-ok')
if not ok:
try:
hub.ping()
except hub.AntsHubException as e:
messages.warning(self.request, _('ANTS Hub is down: "%s".') % e)
else:
messages.info(self.request, _('ANTS Hub is responding.'))
cache.set('ants-hub-ok', True, 600)
return ctx
class CityAddView(CreateView):
template_name = 'chrono/manager_ants_hub_add_form.html'
model = models.City
name = _('New city')
fields = '__all__'
class CityMixin:
def dispatch(self, request, pk):
self.city = get_object_or_404(models.City, pk=pk)
return super().dispatch(request, pk=pk)
class CityView(CityMixin, ListView):
template_name = 'chrono/manager_ants_hub_city.html'
model = models.Place
def get_queryset(self):
return super().get_queryset().filter(city=self.city)
class CityEditView(UpdateView):
template_name = 'chrono/manager_ants_hub_add_form.html'
model = models.City
fields = '__all__'
class CityDeleteView(DeleteView):
template_name = 'chrono/manager_confirm_delete.html'
model = models.City
success_url = '../../../'
class PlaceForm(forms.ModelForm):
class Meta:
model = models.Place
exclude = ['city']
class PlaceAddView(CityMixin, CreateView):
template_name = 'chrono/manager_ants_hub_add_form.html'
model = models.Place
form_class = PlaceForm
@property
def name(self):
return _('New place in %s') % self.city
def dispatch(self, request, pk):
self.city = get_object_or_404(models.City, pk=pk)
return super().dispatch(request, pk)
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['instance'] = models.Place(city=self.city)
return kwargs
class PlaceMixin:
def dispatch(self, request, city_pk, pk):
self.place = get_object_or_404(models.Place, pk=pk, city_id=city_pk)
self.city = self.place.city
return super().dispatch(request, pk=pk)
class PlaceView(PlaceMixin, ListView):
template_name = 'chrono/manager_ants_hub_place.html'
model = models.PlaceAgenda
def get_queryset(self):
return super().get_queryset().filter(place=self.place)
class PlaceEditForm(PlaceForm):
class Meta:
model = models.Place
fields = ['name', 'address', 'zipcode', 'city_name', 'longitude', 'latitude']
class PlaceEditView(UpdateView):
template_name = 'chrono/manager_ants_hub_place_edit_form.html'
model = models.Place
fields = ['zipcode', 'city_name', 'address', 'longitude', 'latitude']
class PlaceDeleteView(DeleteView):
template_name = 'chrono/manager_confirm_delete.html'
model = models.Place
success_url = '../../../../../'
class PlaceUrlEditView(UpdateView):
template_name = 'chrono/manager_ants_hub_add_form.html'
model = models.Place
fields = ['url', 'logo_url', 'meeting_url', 'management_url', 'cancel_url']
class PlaceAgendaAddForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# hide agendas already linked to the place
self.fields['agenda'].queryset = self.fields['agenda'].queryset.exclude(
ants_place__place=self.instance.place
)
class Meta:
model = models.PlaceAgenda
exclude = ['place', 'setting']
class PlaceAgendaAddView(PlaceMixin, CreateView):
template_name = 'chrono/manager_ants_hub_add_form.html'
model = models.PlaceAgenda
form_class = PlaceAgendaAddForm
@property
def name(self):
return _('New agenda for %s') % self.place
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['instance'] = models.PlaceAgenda(place=self.place)
return kwargs
def get_success_url(self):
return f'../../#open-place-agenda-{self.object.pk}'
class PlaceAgendaEditForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.meeting_types = self.instance.agenda.meetingtype_set.order_by('label')
for meeting_type in self.instance.agenda.iter_meetingtypes():
field_meeting_type = forms.TypedMultipleChoiceField(
label=_('%s') % meeting_type.label,
choices=models.ANTSMeetingType.choices,
widget=forms.CheckboxSelectMultiple(attrs={'class': 'inline'}),
required=False,
initial=self.instance.get_meeting_type_setting(meeting_type, 'ants_meeting_type'),
)
field_meeting_type.meeting_type = meeting_type
field_meeting_type.key = 'ants_meeting_type'
field_persons_number = forms.TypedMultipleChoiceField(
label=_('%s') % meeting_type.label,
choices=models.ANTSPersonsNumber.choices,
widget=forms.CheckboxSelectMultiple(attrs={'class': 'inline'}),
required=False,
initial=self.instance.get_meeting_type_setting(meeting_type, 'ants_persons_number'),
)
field_persons_number.meeting_type = meeting_type
field_persons_number.key = 'ants_persons_number'
self.fields[f'mt_{meeting_type.slug}_1'] = field_meeting_type
self.fields[f'mt_{meeting_type.slug}_2'] = field_persons_number
def field_by_labels(self):
d = {}
for bound_field in self:
d.setdefault(bound_field.label, []).append(bound_field)
return list(d.items())
def clean(self):
for key, field in self.fields.items():
value = self.cleaned_data.get(key, [])
self.instance.set_meeting_type_setting(field.meeting_type, field.key, value)
return self.cleaned_data
class Meta:
model = models.PlaceAgenda
fields = []
class PlaceAgendaEditView(UpdateView):
template_name = 'chrono/manager_ants_hub_agenda_edit_form.html'
model = models.PlaceAgenda
form_class = PlaceAgendaEditForm
success_url = '../../../'
class PlaceAgendaDeleteView(DeleteView):
template_name = 'chrono/manager_confirm_delete.html'
model = models.PlaceAgenda
success_url = '../../../'
class Synchronize(TemplateView):
template_name = 'chrono/manager_ants_hub_synchronize.html'
def post(self, request):
self.synchronize()
messages.info(request, _('Synchronization has been launched.'))
return redirect('chrono-manager-ants-hub')
@classmethod
def synchronize(cls):
from chrono.utils.spooler import ants_hub_city_push
ants_hub_city_push.spool()