Compare commits

..

15 Commits

Author SHA1 Message Date
Lauréline Guérin 625f558376
export_import: missing component in bundle (#88068)
gitea/chrono/pipeline/head This commit looks good Details
2024-03-21 10:20:42 +01:00
Lauréline Guérin 82ca10e0ac
export_import: unknown component_type in urls (#88068) 2024-03-21 10:20:40 +01:00
Lauréline Guérin 6b9e4dcb98
export_import: invalid bundle (#88068) 2024-03-21 10:16:47 +01:00
Lauréline Guérin e29172ec74
manager: get snapshots to compare from application version (#87653)
gitea/chrono/pipeline/head This commit looks good Details
2024-03-21 10:16:23 +01:00
Lauréline Guérin 6e6082daba
export_import: redirect to compare view if compare in GET params (#87653) 2024-03-21 10:16:23 +01:00
Lauréline Guérin 527301d318
export_import: bundle-check endpoint (#87653) 2024-03-21 10:16:23 +01:00
Lauréline Guérin df0e356e75
export_import: snapshots on application import (#87653) 2024-03-21 10:10:48 +01:00
Frédéric Péters 07512150e8 api: limit export/import APIs to admin users (#88439)
gitea/chrono/pipeline/head This commit looks good Details
2024-03-21 09:50:18 +01:00
Lauréline Guérin 2576350aae
translation update
gitea/chrono/pipeline/head This commit looks good Details
2024-03-21 08:36:35 +01:00
Lauréline Guérin 2187bf3dde export_import: unknown component in urls (#88085)
gitea/chrono/pipeline/head This commit looks good Details
2024-03-21 08:31:19 +01:00
Lauréline Guérin 4add868dd9 agendas: fix import of incorrect ics file (#88090)
gitea/chrono/pipeline/head This commit looks good Details
2024-03-21 08:30:58 +01:00
Valentin Deniaud 9c19321fb9 tests: fix typo in partial bookings feature flag (#88098)
gitea/chrono/pipeline/head This commit looks good Details
2024-03-18 16:25:34 +01:00
Lauréline Guérin a88db00e04
misc: add pyquery in dependencies (#88222)
gitea/chrono/pipeline/head This commit looks good Details
2024-03-15 12:11:59 +01:00
Lauréline Guérin eecbb80809
translation update
gitea/chrono/pipeline/head This commit looks good Details
2024-03-15 10:40:59 +01:00
Lauréline Guérin e0f1d9541d
manager: prefill presence check form with unexpected presence (#88039)
gitea/chrono/pipeline/head This commit looks good Details
2024-03-15 08:38:14 +01:00
14 changed files with 361 additions and 128 deletions

View File

@ -3975,15 +3975,18 @@ class TimePeriodExceptionSource(WithInspectMixin, models.Model):
data = clean_import_data(cls, data)
if data.get('ics_file'):
data['ics_file'] = ContentFile(base64.b64decode(data['ics_file']), name=data['ics_filename'])
try:
data['ics_file'] = ContentFile(base64.b64decode(data['ics_file']), name=data['ics_filename'])
except base64.binascii.Error:
raise AgendaImportError(_('Bad ics file'))
desk = data.pop('desk')
settings_slug = data.pop('settings_slug')
ics_url = data.pop('ics_url', None)
ics_filename = data.pop('ics_filename', None)
source, _ = cls.objects.update_or_create(
source = cls.objects.update_or_create(
desk=desk, settings_slug=settings_slug, ics_filename=ics_filename, ics_url=ics_url, defaults=data
)
)[0]
if settings_slug:
if source.enabled:
source.enable()

View File

@ -60,7 +60,7 @@ def get_klass_from_component_type(component_type):
class Index(GenericAPIView):
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
permission_classes = (permissions.IsAdminUser,)
def get(self, request, *args, **kwargs):
data = []
@ -154,7 +154,7 @@ def get_component_bundle_entry(request, component):
class ListComponents(GenericAPIView):
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
permission_classes = (permissions.IsAdminUser,)
def get(self, request, *args, **kwargs):
klass = get_klass_from_component_type(kwargs['component_type'])
@ -169,11 +169,11 @@ list_components = ListComponents.as_view()
class ExportComponent(GenericAPIView):
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
permission_classes = (permissions.IsAdminUser,)
def get(self, request, slug, *args, **kwargs):
klass = get_klass_from_component_type(kwargs['component_type'])
serialisation = klass.objects.get(slug=slug).export_json()
serialisation = get_object_or_404(klass, slug=slug).export_json()
return Response({'data': serialisation})
@ -181,11 +181,11 @@ export_component = ExportComponent.as_view()
class ComponentDependencies(GenericAPIView):
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
permission_classes = (permissions.IsAdminUser,)
def get(self, request, slug, *args, **kwargs):
klass = get_klass_from_component_type(kwargs['component_type'])
component = klass.objects.get(slug=slug)
component = get_object_or_404(klass, slug=slug)
def dependency_dict(element):
return get_component_bundle_entry(request, element)
@ -236,7 +236,7 @@ def component_redirect(request, component_type, slug):
class BundleCheck(GenericAPIView):
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
permission_classes = (permissions.IsAdminUser,)
def put(self, request, *args, **kwargs):
tar_io = io.BytesIO(request.read())
@ -352,7 +352,7 @@ bundle_check = BundleCheck.as_view()
class BundleImport(GenericAPIView):
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
permission_classes = (permissions.IsAdminUser,)
install = True
def put(self, request, *args, **kwargs):
@ -448,7 +448,7 @@ bundle_declare = BundleDeclare.as_view()
class BundleUnlink(GenericAPIView):
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
permission_classes = (permissions.IsAdminUser,)
def post(self, request, *args, **kwargs):
if request.POST.get('application'):

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: chrono 0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-02-27 16:39+0100\n"
"POT-Creation-Date: 2024-03-21 08:36+0100\n"
"PO-Revision-Date: 2024-02-01 09:50+0100\n"
"Last-Translator: Frederic Peters <fpeters@entrouvert.com>\n"
"Language: French\n"
@ -41,6 +41,7 @@ msgid "in %s days"
msgstr "dans %s jours"
#: agendas/models.py
#: manager/templates/chrono/manager_agenda_inspect_fragment.html
#: manager/templates/chrono/manager_events_agenda_day_view.html
#: manager/templates/chrono/manager_events_agenda_month_view.html
#: manager/templates/chrono/manager_events_agenda_settings.html
@ -142,6 +143,7 @@ msgid "Label"
msgstr "Libellé"
#: agendas/models.py
#: manager/templates/chrono/includes/snapshot_history_fragment.html
msgid "Identifier"
msgstr "Identifiant"
@ -192,6 +194,10 @@ msgstr "Vue par défaut"
msgid "Booking form URL"
msgstr "Adresse de la démarche de réservation"
#: agendas/models.py
msgid "Global desk management"
msgstr "Gestion globale des guichets"
#: agendas/models.py
msgid "Automatically mark event as checked when all bookings have been checked"
msgstr ""
@ -380,6 +386,7 @@ msgid "Repeat"
msgstr "Répéter"
#: agendas/models.py manager/forms.py
#: manager/templates/chrono/includes/snapshot_history_fragment.html
msgid "Date"
msgstr "Date"
@ -461,6 +468,7 @@ msgid "Optional label to identify this date."
msgstr "Libellé optionnel pour identifier la date."
#: agendas/models.py
#: manager/templates/chrono/includes/snapshot_history_fragment.html
msgid "Description"
msgstr "Description"
@ -567,6 +575,7 @@ msgid "Resource"
msgstr "Ressource"
#: agendas/models.py manager/forms.py
#: manager/templates/chrono/manager_agenda_inspect_fragment.html
#: manager/templates/chrono/manager_home.html
#: manager/templates/chrono/manager_meetings_agenda_settings.html
#: manager/templates/chrono/manager_resource_list.html
@ -612,11 +621,16 @@ msgstr "Lévènement « %s » na pas de date de début."
msgid "Exception"
msgstr "Exception"
#: agendas/models.py
msgid "Bad ics file"
msgstr "Mauvais format de fichier ICS"
#: agendas/models.py
msgid "Unavailability calendar"
msgstr "Calendrier dindisponibilités"
#: agendas/models.py manager/forms.py
#: manager/templates/chrono/manager_agenda_inspect_fragment.html
#: manager/templates/chrono/manager_home.html
msgid "Unavailability calendars"
msgstr "Calendrier dindisponibilités"
@ -1938,6 +1952,15 @@ msgstr "Rôle"
msgid "deletion"
msgstr "suppression"
#: apps/snapshot/views.py
#, python-format
msgid "Version %s"
msgstr "Version %s"
#: apps/snapshot/views.py
msgid "Snapshot"
msgstr "Sauvegarde"
#: manager/forms.py
msgid "Desk 1"
msgstr "Guichet 1"
@ -2011,14 +2034,17 @@ msgid "Field type"
msgstr "Type du champ"
#: manager/forms.py
#: manager/templates/chrono/manager_events_type_inspect_fragment.html
msgid "Text"
msgstr "Texte"
#: manager/forms.py
#: manager/templates/chrono/manager_events_type_inspect_fragment.html
msgid "Textarea"
msgstr "Zone de texte"
#: manager/forms.py
#: manager/templates/chrono/manager_events_type_inspect_fragment.html
msgid "Boolean"
msgstr "Booléen"
@ -2441,12 +2467,49 @@ msgstr "Couleurs des rendez-vous:"
msgid "Applications"
msgstr "Applications"
#: manager/templates/chrono/includes/snapshot_history_fragment.html
msgid "Show differences"
msgstr "Afficher les différences"
#: manager/templates/chrono/includes/snapshot_history_fragment.html
msgid "Compare"
msgstr "Comparer"
#: manager/templates/chrono/includes/snapshot_history_fragment.html
msgid "User"
msgstr "Usager"
#: manager/templates/chrono/includes/snapshot_history_fragment.html
#: manager/templates/chrono/manager_agenda_settings.html
#: manager/templates/chrono/manager_category_list.html
#: manager/templates/chrono/manager_events_type_list.html
#: manager/templates/chrono/manager_home.html
#: manager/templates/chrono/manager_resource_detail.html
#: manager/templates/chrono/manager_resource_list.html
#: manager/templates/chrono/manager_unavailability_calendar_list.html
#: manager/templates/chrono/manager_unavailability_calendar_settings.html
msgid "Actions"
msgstr "Actions"
#: manager/templates/chrono/includes/snapshot_history_fragment.html
#, python-format
msgid "1 other this day"
msgid_plural "%(counter)s others"
msgstr[0] "1 autre ce jour"
msgstr[1] "%(counter)s autres ce jour"
#: manager/templates/chrono/includes/snapshot_history_fragment.html
#, python-format
msgid "Version %(version)s"
msgstr "Version %(version)s"
#: manager/templates/chrono/manager_agenda_add_form.html
msgid "New Agenda"
msgstr "Nouvel agenda"
#: manager/templates/chrono/manager_agenda_date_view.html
#: manager/templates/chrono/manager_agenda_form.html
#: manager/templates/chrono/manager_agenda_inspect_fragment.html
#: manager/templates/chrono/manager_agenda_notifications_form.html
#: manager/templates/chrono/manager_agenda_settings.html
#: manager/templates/chrono/manager_agenda_view.html
@ -2578,6 +2641,169 @@ msgstr "hors de la période dinscription"
msgid "Booking form"
msgstr "Démarche de réservation"
#: manager/templates/chrono/manager_agenda_history.html
msgid "Agenda history"
msgstr "Historique de lagenda"
#: manager/templates/chrono/manager_agenda_history.html
#: manager/templates/chrono/manager_agenda_settings.html
#: manager/templates/chrono/manager_category_form.html
#: manager/templates/chrono/manager_category_history.html
#: manager/templates/chrono/manager_events_type_form.html
#: manager/templates/chrono/manager_events_type_history.html
#: manager/templates/chrono/manager_resource_detail.html
#: manager/templates/chrono/manager_resource_history.html
#: manager/templates/chrono/manager_unavailability_calendar_history.html
#: manager/templates/chrono/manager_unavailability_calendar_settings.html
msgid "History"
msgstr "Historique"
#: manager/templates/chrono/manager_agenda_history_compare.html
#: manager/templates/chrono/manager_category_history_compare.html
#: manager/templates/chrono/manager_events_type_history_compare.html
#: manager/templates/chrono/manager_resource_history_compare.html
#: manager/templates/chrono/manager_unavailability_calendar_history_compare.html
msgid "Compare snapshots"
msgstr "Comparaison des sauvergardes"
#: manager/templates/chrono/manager_agenda_history_compare.html
#: manager/templates/chrono/manager_category_history_compare.html
#: manager/templates/chrono/manager_events_type_history_compare.html
#: manager/templates/chrono/manager_resource_history_compare.html
#: manager/templates/chrono/manager_unavailability_calendar_history_compare.html
msgid "JSON"
msgstr "JSON"
#: manager/templates/chrono/manager_agenda_history_compare.html
#: manager/templates/chrono/manager_agenda_inspect.html
#: manager/templates/chrono/manager_agenda_settings.html
#: manager/templates/chrono/manager_category_form.html
#: manager/templates/chrono/manager_category_history_compare.html
#: manager/templates/chrono/manager_category_inspect.html
#: manager/templates/chrono/manager_events_type_form.html
#: manager/templates/chrono/manager_events_type_history_compare.html
#: manager/templates/chrono/manager_events_type_inspect.html
#: manager/templates/chrono/manager_resource_detail.html
#: manager/templates/chrono/manager_resource_history_compare.html
#: manager/templates/chrono/manager_resource_inspect.html
#: manager/templates/chrono/manager_unavailability_calendar_history_compare.html
#: manager/templates/chrono/manager_unavailability_calendar_inspect.html
#: manager/templates/chrono/manager_unavailability_calendar_settings.html
msgid "Inspect"
msgstr "Inspecteur"
#: manager/templates/chrono/manager_agenda_history_compare.html
#: manager/templates/chrono/manager_category_history_compare.html
#: manager/templates/chrono/manager_events_type_history_compare.html
#: manager/templates/chrono/manager_resource_history_compare.html
#: manager/templates/chrono/manager_unavailability_calendar_history_compare.html
msgid "Compare inspect"
msgstr "Comparaison des inspecteurs"
#: manager/templates/chrono/manager_agenda_history_compare.html
#: manager/templates/chrono/manager_category_history_compare.html
#: manager/templates/chrono/manager_events_type_history_compare.html
#: manager/templates/chrono/manager_resource_history_compare.html
#: manager/templates/chrono/manager_unavailability_calendar_history_compare.html
msgid "Compare JSON"
msgstr "Comparaison JSON"
#: manager/templates/chrono/manager_agenda_inspect_fragment.html
#: manager/templates/chrono/manager_category_inspect_fragment.html
#: manager/templates/chrono/manager_events_type_inspect_fragment.html
#: manager/templates/chrono/manager_resource_inspect_fragment.html
#: manager/templates/chrono/manager_unavailability_calendar_inspect_fragment.html
msgid "Information"
msgstr "Informations"
#: manager/templates/chrono/manager_agenda_inspect_fragment.html
#: manager/templates/chrono/manager_agenda_settings.html
#: manager/templates/chrono/manager_unavailability_calendar_inspect_fragment.html
msgid "Permissions"
msgstr "Permissions"
#: manager/templates/chrono/manager_agenda_inspect_fragment.html
#: manager/templates/chrono/manager_events_agenda_settings.html
msgid "Recurrence exceptions"
msgstr "Exceptions aux récurrences"
#: manager/templates/chrono/manager_agenda_inspect_fragment.html
#: manager/templates/chrono/manager_meetings_agenda_settings.html
#: manager/templates/chrono/manager_virtual_agenda_settings.html
msgid "Meeting Types"
msgstr "Types de rendez-vous"
#: manager/templates/chrono/manager_agenda_inspect_fragment.html
#: manager/templates/chrono/manager_meetings_agenda_settings.html
msgid "Desks"
msgstr "Guichets"
#: manager/templates/chrono/manager_agenda_inspect_fragment.html
#: manager/templates/chrono/manager_virtual_agenda_settings.html
msgid "Included Agendas"
msgstr "Agendas inclus"
#: manager/templates/chrono/manager_agenda_inspect_fragment.html
#: manager/templates/chrono/manager_virtual_agenda_settings.html
msgid "Excluded Periods"
msgstr "Périodes exclues"
#: manager/templates/chrono/manager_agenda_inspect_fragment.html
#: manager/templates/chrono/manager_category_inspect_fragment.html
#: manager/templates/chrono/manager_events_type_inspect_fragment.html
#: manager/templates/chrono/manager_resource_inspect_fragment.html
#: manager/templates/chrono/manager_unavailability_calendar_inspect_fragment.html
#, python-format
msgid "%(label)s:"
msgstr "%(label)s :"
#: manager/templates/chrono/manager_agenda_inspect_fragment.html
#: manager/templates/chrono/manager_events_agenda_settings.html
#: manager/templates/chrono/manager_meetings_agenda_settings.html
msgid "Display options"
msgstr "Paramètres daffichage"
#: manager/templates/chrono/manager_agenda_inspect_fragment.html
#: manager/templates/chrono/manager_events_agenda_settings.html
msgid "Booking check options"
msgstr "Paramètres du pointage"
#: manager/templates/chrono/manager_agenda_inspect_fragment.html
#: manager/templates/chrono/manager_events_agenda_settings.html
msgid "Invoicing options"
msgstr "Paramètres de facturation"
#: manager/templates/chrono/manager_agenda_inspect_fragment.html
#: manager/templates/chrono/manager_events_agenda_settings.html
msgid "Management notifications"
msgstr "Notifications dadministration"
#: manager/templates/chrono/manager_agenda_inspect_fragment.html
#: manager/templates/chrono/manager_agenda_settings.html
msgid "Booking reminders"
msgstr "Rappels de réservation"
#: manager/templates/chrono/manager_agenda_inspect_fragment.html
#: manager/templates/chrono/manager_agenda_settings.html
msgid "Booking Delays"
msgstr "Délais de réservation"
#: manager/templates/chrono/manager_agenda_inspect_fragment.html
msgid "Exception sources"
msgstr "Sources dexceptions"
#: manager/templates/chrono/manager_agenda_inspect_fragment.html
#: manager/templates/chrono/manager_meetings_agenda_settings.html
#: manager/templates/chrono/manager_time_period_exception_list.html
#: manager/templates/chrono/manager_unavailability_calendar_inspect_fragment.html
msgid "Exceptions"
msgstr "Exceptions"
#: manager/templates/chrono/manager_agenda_inspect_fragment.html
#: manager/templates/chrono/manager_meetings_agenda_settings.html
msgid "Opening hours"
msgstr "Plages horaires"
#: manager/templates/chrono/manager_agenda_month_view.html
#: manager/templates/chrono/manager_resource_month_view.html
msgid "Previous month"
@ -2662,18 +2888,6 @@ msgstr "Exporter les évènements (CSV)"
msgid "Delete"
msgstr "Supprimer"
#: manager/templates/chrono/manager_agenda_settings.html
msgid "Booking reminders"
msgstr "Rappels de réservation"
#: manager/templates/chrono/manager_agenda_settings.html
msgid "Booking Delays"
msgstr "Délais de réservation"
#: manager/templates/chrono/manager_agenda_settings.html
msgid "Permissions"
msgstr "Permissions"
#: manager/templates/chrono/manager_agenda_settings.html
msgid "Reminders are disabled for this agenda."
msgstr "Les rappels sont désactivés pour cet agenda."
@ -2735,23 +2949,19 @@ msgstr "Rôle dédition :"
msgid "View Role:"
msgstr "Rôle de visualisation :"
#: manager/templates/chrono/manager_agenda_settings.html
#: manager/templates/chrono/manager_category_list.html
#: manager/templates/chrono/manager_events_type_list.html
#: manager/templates/chrono/manager_home.html
#: manager/templates/chrono/manager_resource_detail.html
#: manager/templates/chrono/manager_resource_list.html
#: manager/templates/chrono/manager_unavailability_calendar_list.html
#: manager/templates/chrono/manager_unavailability_calendar_settings.html
msgid "Actions"
msgstr "Actions"
#: manager/templates/chrono/manager_agenda_settings.html
#: manager/templates/chrono/manager_event_detail.html
#: manager/templates/chrono/manager_unavailability_calendar_settings.html
msgid "Options"
msgstr "Options"
#: manager/templates/chrono/manager_agenda_settings.html
#: manager/templates/chrono/manager_home.html
#: manager/templates/chrono/manager_resource_detail.html
#: manager/templates/chrono/manager_unavailability_calendar_settings.html
msgid "Navigation"
msgstr "Navigation"
#: manager/templates/chrono/manager_agenda_unavailability_calendar_form.html
msgid "Add unavailability calendar"
msgstr "Ajouter un calendrier dindisponibilités"
@ -2795,6 +3005,10 @@ msgstr "Nouvelle catégorie"
msgid "Edit Category"
msgstr "Modification de la catégorie"
#: manager/templates/chrono/manager_category_history.html
msgid "Category history"
msgstr "Historique de la catégorie"
#: manager/templates/chrono/manager_category_list.html
msgid "Categories outside applications"
msgstr "Catégories hors applications"
@ -3116,37 +3330,11 @@ msgstr "Ce mois na pas dévènements configurés."
msgid "Import Events"
msgstr "Importer des évènements"
#: manager/templates/chrono/manager_events_agenda_settings.html
#: manager/templates/chrono/manager_home.html
msgid "Navigation"
msgstr "Navigation"
#: manager/templates/chrono/manager_events_agenda_settings.html
msgctxt "pricing"
msgid "Pricing"
msgstr "Tarification"
#: manager/templates/chrono/manager_events_agenda_settings.html
msgid "Recurrence exceptions"
msgstr "Exceptions aux récurrences"
#: manager/templates/chrono/manager_events_agenda_settings.html
#: manager/templates/chrono/manager_meetings_agenda_settings.html
msgid "Display options"
msgstr "Paramètres daffichage"
#: manager/templates/chrono/manager_events_agenda_settings.html
msgid "Booking check options"
msgstr "Paramètres du pointage"
#: manager/templates/chrono/manager_events_agenda_settings.html
msgid "Invoicing options"
msgstr "Paramètres de facturation"
#: manager/templates/chrono/manager_events_agenda_settings.html
msgid "Management notifications"
msgstr "Notifications dadministration"
#: manager/templates/chrono/manager_events_agenda_settings.html
msgid ""
"This agenda doesn't have any event yet. Click on the \"New Event\" button in "
@ -3329,6 +3517,7 @@ msgid "Edit events type"
msgstr "Modification du type dévènement"
#: manager/templates/chrono/manager_events_type_form.html
#: manager/templates/chrono/manager_events_type_inspect_fragment.html
msgid "Custom fields"
msgstr "Champs personnalisés"
@ -3336,6 +3525,22 @@ msgstr "Champs personnalisés"
msgid "Add another custom field"
msgstr "Ajouter un autre champ"
#: manager/templates/chrono/manager_events_type_history.html
msgid "Events type history"
msgstr "Historique du type dévènement"
#: manager/templates/chrono/manager_events_type_inspect_fragment.html
msgid "Field slug:"
msgstr "Identifiant du champ :"
#: manager/templates/chrono/manager_events_type_inspect_fragment.html
msgid "Field label:"
msgstr "Libellé du champ :"
#: manager/templates/chrono/manager_events_type_inspect_fragment.html
msgid "Field type:"
msgstr "Type du champ :"
#: manager/templates/chrono/manager_events_type_list.html
msgid "Events types outside applications"
msgstr "Types dévènements hors applications"
@ -3430,19 +3635,6 @@ msgstr "Basculer en gestion unitaire des guichets"
msgid "Switch to global desk management"
msgstr "Basculer en gestion globale des guichets"
#: manager/templates/chrono/manager_meetings_agenda_settings.html
#: manager/templates/chrono/manager_virtual_agenda_settings.html
msgid "Meeting Types"
msgstr "Types de rendez-vous"
#: manager/templates/chrono/manager_meetings_agenda_settings.html
msgid "Desks"
msgstr "Guichets"
#: manager/templates/chrono/manager_meetings_agenda_settings.html
msgid "Opening hours"
msgstr "Plages horaires"
#: manager/templates/chrono/manager_meetings_agenda_settings.html
#: manager/templates/chrono/manager_virtual_agenda_settings.html
msgid "minutes"
@ -3468,11 +3660,6 @@ msgstr "Ajouter une plage horaire régulière"
msgid "Add a unique period"
msgstr "Ajouter une plage horaire unique"
#: manager/templates/chrono/manager_meetings_agenda_settings.html
#: manager/templates/chrono/manager_time_period_exception_list.html
msgid "Exceptions"
msgstr "Exceptions"
#: manager/templates/chrono/manager_meetings_agenda_settings.html
msgid "manage exceptions"
msgstr "gérer les exceptions"
@ -3602,6 +3789,10 @@ msgstr "Nouvelle ressource"
msgid "Edit Resource"
msgstr "Modification de la ressource"
#: manager/templates/chrono/manager_resource_history.html
msgid "Resource history"
msgstr "Historique de la ressource"
#: manager/templates/chrono/manager_resource_list.html
msgid "Resources outside applications"
msgstr "Ressources hors applications"
@ -3786,6 +3977,10 @@ msgstr "Modification du calendrier dindisponibilités"
msgid "New Unavailability Calendar"
msgstr "Nouveau calendrier dindisponibilités"
#: manager/templates/chrono/manager_unavailability_calendar_history.html
msgid "UnavailabilityCalendarSnapshot calendar history"
msgstr "Historique du calendrier dindisponibilités"
#: manager/templates/chrono/manager_unavailability_calendar_list.html
msgid "Unavailability Calendars"
msgstr "Calendriers dindisponibilités"
@ -3837,14 +4032,6 @@ msgstr "Ajouter une période dexclusion"
msgid "Include Agenda"
msgstr "Inclure un agenda"
#: manager/templates/chrono/manager_virtual_agenda_settings.html
msgid "Included Agendas"
msgstr "Agendas inclus"
#: manager/templates/chrono/manager_virtual_agenda_settings.html
msgid "Excluded Periods"
msgstr "Périodes exclues"
#: manager/templates/chrono/manager_virtual_agenda_settings.html
msgid ""
"This virtual agenda doesn't include any agenda yet. Click on the \"Include "

View File

@ -589,12 +589,17 @@ class BookingCheckPresenceForm(forms.Form):
def __init__(self, *args, **kwargs):
agenda = kwargs.pop('agenda')
subscription = kwargs.pop('subscription', False)
super().__init__(*args, **kwargs)
check_types = get_agenda_check_types(agenda)
self.presence_check_types = [ct for ct in check_types if ct.kind == 'presence']
self.fields['check_type'].choices = [('', '---------')] + [
(ct.slug, ct.label) for ct in self.presence_check_types
]
if not self.initial and subscription:
unexpected_presences = [ct for ct in check_types if ct.unexpected_presence]
if unexpected_presences:
self.initial['check_type'] = unexpected_presences[0].slug
class PartialBookingCheckForm(forms.ModelForm):

View File

@ -13,7 +13,7 @@
<button aria-controls="panel-resources" aria-selected="false" id="tab-resources" role="tab" tabindex="-1">{% trans "Resources" %}</button>
{% elif object.kind == 'virtual' %}
<button aria-controls="panel-agendas" aria-selected="false" id="tab-agendas" role="tab" tabindex="-1">{% trans "Included Agendas" %}</button>
<button aria-controls="panel-time-periods" aria-selected="false" id="tab-time-periods" role="tab" tabindex="-1">{% trans "Exception Periods" %}</button>
<button aria-controls="panel-time-periods" aria-selected="false" id="tab-time-periods" role="tab" tabindex="-1">{% trans "Excluded Periods" %}</button>
{% endif %}
</div>
<div class="pk-tabs--container">

View File

@ -1759,6 +1759,7 @@ class EventChecksMixin:
)
subscription.presence_form = BookingCheckPresenceForm(
agenda=self.agenda,
subscription=True,
)
# sort results
if (

View File

@ -62,6 +62,7 @@ class CheckType:
slug: str
label: str
kind: str
unexpected_presence: bool = False
def get_agenda_check_types(agenda):
@ -73,5 +74,12 @@ def get_agenda_check_types(agenda):
check_types = []
for ct in result['data']:
check_types.append(CheckType(slug=ct['id'], label=ct['text'], kind=ct['kind']))
check_types.append(
CheckType(
slug=ct['id'],
label=ct['text'],
kind=ct['kind'],
unexpected_presence=ct.get('unexpected_presence') or False,
)
)
return check_types

1
debian/control vendored
View File

@ -16,6 +16,7 @@ Depends: python3-django (>= 2:3.2),
python3-gadjo,
python3-lxml,
python3-publik-django-templatetags,
python3-pyquery,
python3-requests,
python3-uwsgidecorators,
${misc:Depends},

View File

@ -165,6 +165,7 @@ setup(
'django-filter<23.2',
'vobject',
'python-dateutil',
'pyquery',
'requests',
'workalendar',
'weasyprint',

View File

@ -14,8 +14,11 @@ from chrono.apps.snapshot.models import AgendaSnapshot
pytestmark = pytest.mark.django_db
def test_object_types(app, user):
def test_object_types(app, user, admin_user):
app.authorization = ('Basic', ('john.doe', 'password'))
app.get('/api/export-import/', status=403)
app.authorization = ('Basic', ('admin', 'admin'))
resp = app.get('/api/export-import/')
assert resp.json == {
'data': [
@ -64,8 +67,8 @@ def test_object_types(app, user):
}
def test_list(app, user):
app.authorization = ('Basic', ('john.doe', 'password'))
def test_list(app, admin_user):
app.authorization = ('Basic', ('admin', 'admin'))
Agenda.objects.create(label='Rdv', slug='rdv', kind='meetings')
Agenda.objects.create(label='Event', slug='event', kind='events')
Category.objects.create(slug='cat', label='Category')
@ -167,8 +170,8 @@ def test_list(app, user):
app.get('/api/export-import/unknown/', status=404)
def test_export_agenda(app, user):
app.authorization = ('Basic', ('john.doe', 'password'))
def test_export_agenda(app, admin_user):
app.authorization = ('Basic', ('admin', 'admin'))
group1 = Group.objects.create(name='group1')
group2 = Group.objects.create(name='group2')
Agenda.objects.create(label='Rdv', slug='rdv', kind='meetings', edit_role=group1, view_role=group2)
@ -177,8 +180,8 @@ def test_export_agenda(app, user):
assert resp.json['data']['permissions'] == {'view': 'group2', 'edit': 'group1'}
def test_export_minor_components(app, user):
app.authorization = ('Basic', ('john.doe', 'password'))
def test_export_minor_components(app, admin_user):
app.authorization = ('Basic', ('admin', 'admin'))
Category.objects.create(slug='cat', label='Category')
Resource.objects.create(slug='foo', label='Foo')
EventsType.objects.create(slug='foo', label='Foo')
@ -193,12 +196,15 @@ def test_export_minor_components(app, user):
resp = app.get('/api/export-import/unavailability_calendars/foo/')
assert resp.json['data']['label'] == 'Foo'
# unknown component
app.get('/api/export-import/agendas/foo/', status=404)
# unknown component type
app.get('/api/export-import/unknown/foo/', status=404)
def test_agenda_dependencies_category(app, user):
app.authorization = ('Basic', ('john.doe', 'password'))
def test_agenda_dependencies_category(app, admin_user):
app.authorization = ('Basic', ('admin', 'admin'))
category = Category.objects.create(slug='cat', label='Category')
Agenda.objects.create(label='Rdv', slug='rdv', kind='meetings', category=category)
resp = app.get('/api/export-import/agendas/rdv/dependencies/')
@ -219,8 +225,8 @@ def test_agenda_dependencies_category(app, user):
}
def test_agenda_dependencies_resources(app, user):
app.authorization = ('Basic', ('john.doe', 'password'))
def test_agenda_dependencies_resources(app, admin_user):
app.authorization = ('Basic', ('admin', 'admin'))
meetings_agenda = Agenda.objects.create(label='Rdv', slug='rdv', kind='meetings')
meetings_agenda.resources.add(Resource.objects.create(slug='foo', label='Foo'))
resp = app.get('/api/export-import/agendas/rdv/dependencies/')
@ -241,8 +247,8 @@ def test_agenda_dependencies_resources(app, user):
}
def test_agenda_dependencies_unavailability_calendars(app, user):
app.authorization = ('Basic', ('john.doe', 'password'))
def test_agenda_dependencies_unavailability_calendars(app, admin_user):
app.authorization = ('Basic', ('admin', 'admin'))
meetings_agenda = Agenda.objects.create(label='Rdv', slug='rdv', kind='meetings')
desk = Desk.objects.create(slug='foo', label='Foo', agenda=meetings_agenda)
unavailability_calendar = UnavailabilityCalendar.objects.create(slug='foo', label='Foo')
@ -284,8 +290,8 @@ def test_agenda_dependencies_unavailability_calendars(app, user):
}
def test_agenda_dependencies_groups(app, user):
app.authorization = ('Basic', ('john.doe', 'password'))
def test_agenda_dependencies_groups(app, admin_user):
app.authorization = ('Basic', ('admin', 'admin'))
group1 = Group.objects.create(name='group1')
group2 = Group.objects.create(name='group2')
Agenda.objects.create(label='Rdv', slug='rdv', kind='meetings', edit_role=group1, view_role=group2)
@ -301,8 +307,8 @@ def test_agenda_dependencies_groups(app, user):
}
def test_agenda_dependencies_virtual_agendas(app, user):
app.authorization = ('Basic', ('john.doe', 'password'))
def test_agenda_dependencies_virtual_agendas(app, admin_user):
app.authorization = ('Basic', ('admin', 'admin'))
rdv1 = Agenda.objects.create(label='Rdv1', slug='rdv1', kind='meetings')
rdv2 = Agenda.objects.create(label='Rdv2', slug='rdv2', kind='meetings')
virt = Agenda.objects.create(label='Virt', slug='virt', kind='virtual')
@ -336,8 +342,8 @@ def test_agenda_dependencies_virtual_agendas(app, user):
}
def test_agenda_dependencies_events_type(app, user):
app.authorization = ('Basic', ('john.doe', 'password'))
def test_agenda_dependencies_events_type(app, admin_user):
app.authorization = ('Basic', ('admin', 'admin'))
events_type = EventsType.objects.create(slug='foo', label='Foo')
events_agenda = Agenda.objects.create(label='Evt', slug='evt', kind='events', events_type=events_type)
Desk.objects.create(agenda=events_agenda, slug='_exceptions_holder')
@ -359,13 +365,18 @@ def test_agenda_dependencies_events_type(app, user):
}
def test_unknown_compoment_type_dependencies(app, user):
app.authorization = ('Basic', ('john.doe', 'password'))
def test_unknown_compoment_dependencies(app, admin_user):
app.authorization = ('Basic', ('admin', 'admin'))
app.get('/api/export-import/agendas/foo/dependencies/', status=404)
def test_unknown_compoment_type_dependencies(app, admin_user):
app.authorization = ('Basic', ('admin', 'admin'))
app.get('/api/export-import/unknown/foo/dependencies/', status=404)
def test_redirect(app, user):
app.authorization = ('Basic', ('john.doe', 'password'))
app.authorization = ('Basic', ('john', 'doe'))
agenda = Agenda.objects.create(label='Rdv', slug='rdv', kind='meetings')
category = Category.objects.create(slug='cat', label='Category')
resource = Resource.objects.create(slug='foo', label='Foo')
@ -431,8 +442,8 @@ def test_redirect(app, user):
app.get('/api/export-import/unknown/foo/redirect/', status=404)
def create_bundle(app, user, visible=True, version_number='42.0'):
app.authorization = ('Basic', ('john.doe', 'password'))
def create_bundle(app, admin_user, visible=True, version_number='42.0'):
app.authorization = ('Basic', ('admin', 'admin'))
group, _ = Group.objects.get_or_create(name='plop')
category, _ = Category.objects.get_or_create(slug='foo', label='Foo')
@ -517,12 +528,12 @@ def bundle(app, user):
return create_bundle(app, user)
def test_bundle_import(app, user):
app.authorization = ('Basic', ('john.doe', 'password'))
def test_bundle_import(app, admin_user):
app.authorization = ('Basic', ('admin', 'admin'))
bundles = []
for version_number in ['42.0', '42.1']:
bundles.append(create_bundle(app, user, version_number=version_number))
bundles.append(create_bundle(app, admin_user, version_number=version_number))
Agenda.objects.all().delete()
Category.objects.all().delete()
@ -620,10 +631,10 @@ def test_bundle_import(app, user):
assert resp.json['err_desc'] == 'Invalid tar file, missing component agendas/foo'
def test_bundle_declare(app, user):
app.authorization = ('Basic', ('john.doe', 'password'))
def test_bundle_declare(app, admin_user):
app.authorization = ('Basic', ('admin', 'admin'))
bundle = create_bundle(app, user, visible=False)
bundle = create_bundle(app, admin_user, visible=False)
resp = app.put('/api/export-import/bundle-declare/', bundle)
assert Agenda.objects.all().count() == 4
assert resp.json['err'] == 0
@ -640,7 +651,7 @@ def test_bundle_declare(app, user):
assert application.visible is False
assert ApplicationElement.objects.count() == 8
bundle = create_bundle(app, user, visible=True)
bundle = create_bundle(app, admin_user, visible=True)
# create link to element not present in manifest: it should be unlinked
last_page = Agenda.objects.latest('pk')
ApplicationElement.objects.create(
@ -690,8 +701,8 @@ def test_bundle_declare(app, user):
assert resp.json['err_desc'] == 'Invalid tar file, missing component agendas/foo'
def test_bundle_unlink(app, user, bundle):
app.authorization = ('Basic', ('john.doe', 'password'))
def test_bundle_unlink(app, admin_user, bundle):
app.authorization = ('Basic', ('admin', 'admin'))
application = Application.objects.create(
name='Test',
@ -745,12 +756,12 @@ def test_bundle_unlink(app, user, bundle):
assert ApplicationElement.objects.count() == 2
def test_bundle_check(app, user):
app.authorization = ('Basic', ('john.doe', 'password'))
def test_bundle_check(app, admin_user):
app.authorization = ('Basic', ('admin', 'admin'))
bundles = []
for version_number in ['42.0', '42.1']:
bundles.append(create_bundle(app, user, version_number=version_number))
bundles.append(create_bundle(app, admin_user, version_number=version_number))
Agenda.objects.all().delete()
Category.objects.all().delete()
Resource.objects.all().delete()

View File

@ -489,7 +489,7 @@ def test_add_agenda_and_set_role(app, admin_user, manager_user):
def test_agenda_set_role_with_partial_booking(settings, app, admin_user):
settings.PARTIAL_BOOKING_ENABLED = True
settings.PARTIAL_BOOKINGS_ENABLED = True
group = Group.objects.create(name='testgroup')
agenda = Agenda.objects.create(label='Foobar')

View File

@ -2482,11 +2482,12 @@ def test_event_check_booking(check_types, app, admin_user):
check_types.return_value = [
CheckType(slug='foo-reason', label='Foo reason', kind='absence'),
CheckType(slug='bar-reason', label='Bar reason', kind='presence'),
CheckType(slug='bar-reason', label='Bar reason', kind='presence', unexpected_presence=True),
]
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
assert len(resp.pyquery.find('td.booking-actions form.absence select')) == 1
assert len(resp.pyquery.find('td.booking-actions form.presence select')) == 1
assert resp.pyquery.find('td.booking-actions form.presence option:selected').text() == '---------'
# reset
_test_reset()
@ -2833,6 +2834,14 @@ def test_event_check_subscription(check_types, app, admin_user):
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
assert '/manage/agendas/%s/subscriptions/%s/presence/%s' % (agenda.pk, subscription.pk, event.pk) in resp
assert '/manage/agendas/%s/subscriptions/%s/absence/%s' % (agenda.pk, subscription.pk, event.pk) in resp
assert resp.pyquery.find('td.booking-actions form.presence option:selected').text() == '---------'
check_types.return_value = [
CheckType(slug='foo-reason', label='Foo reason', kind='absence'),
CheckType(slug='bar-reason', label='Bar reason', kind='presence'),
CheckType(slug='baz-reason', label='Baz reason', kind='presence', unexpected_presence=True),
]
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
assert resp.pyquery.find('td.booking-actions form.presence option:selected').text() == 'Baz reason'
app.post(
'/manage/agendas/%s/subscriptions/%s/presence/%s' % (agenda.pk, subscription.pk, event.pk),
params={'csrfmiddlewaretoken': token, 'check_type': 'bar-reason'},

View File

@ -899,6 +899,11 @@ def test_import_export_time_period_exception_source_ics_file(mocked_get):
assert TimePeriodExceptionSource.objects.count() == 1
assert TimePeriodException.objects.count() == 2
payload['agendas'][0]['desks'][0]['exception_sources'][0]['ics_file'] = 'garbage'
with pytest.raises(AgendaImportError) as excinfo:
import_site(payload)
assert '%s' % excinfo.value == 'Bad ics file'
@override_settings(
EXCEPTIONS_SOURCES={

View File

@ -36,6 +36,7 @@ def test_get_weekday_index():
CHECK_TYPES_DATA = [
{'id': 'bar-reason', 'kind': 'presence', 'text': 'Bar reason'},
{'id': 'baz-reason', 'kind': 'presence', 'text': 'Baz reason', 'unexpected_presence': True},
{'id': 'foo-reason', 'kind': 'absence', 'text': 'Foo reason'},
]
@ -92,6 +93,7 @@ def test_get_agenda_check_types():
requests_get.return_value = MockedRequestResponse(content=json.dumps(data))
assert get_agenda_check_types(agenda) == [
CheckType(slug='bar-reason', label='Bar reason', kind='presence'),
CheckType(slug='baz-reason', label='Baz reason', kind='presence', unexpected_presence=True),
CheckType(slug='foo-reason', label='Foo reason', kind='absence'),
]