diff --git a/.gitignore b/.gitignore
index affc851f..91e55e22 100644
--- a/.gitignore
+++ b/.gitignore
@@ -47,6 +47,7 @@ backups/
env/
venv/
db.sqlite3
+shell.nix
# ansibles customs host
ansible/host_vars/*.yaml
diff --git a/apps/activity/views.py b/apps/activity/views.py
index 366cadb3..1f966c65 100644
--- a/apps/activity/views.py
+++ b/apps/activity/views.py
@@ -168,6 +168,9 @@ class ActivityEntryView(LoginRequiredMixin, TemplateView):
Don't display the entry interface if the user has no right to see it (no right to add an entry for itself),
it is closed or doesn't manage entries.
"""
+ if not self.request.user.is_authenticated:
+ return self.handle_no_permission()
+
activity = Activity.objects.get(pk=self.kwargs["pk"])
sample_entry = Entry(activity=activity, note=self.request.user.note)
diff --git a/apps/member/migrations/0008_auto_20211005_1544.py b/apps/member/migrations/0008_auto_20211005_1544.py
new file mode 100644
index 00000000..a0572999
--- /dev/null
+++ b/apps/member/migrations/0008_auto_20211005_1544.py
@@ -0,0 +1,18 @@
+# Generated by Django 2.2.24 on 2021-10-05 13:44
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('member', '0007_auto_20210313_1235'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='profile',
+ name='department',
+ field=models.CharField(choices=[('A0', 'Informatics (A0)'), ('A1', 'Mathematics (A1)'), ('A2', 'Physics (A2)'), ("A'2", "Applied physics (A'2)"), ("A''2", "Chemistry (A''2)"), ('A3', 'Biology (A3)'), ('B1234', 'SAPHIRE (B1234)'), ('B1', 'Mechanics (B1)'), ('B2', 'Civil engineering (B2)'), ('B3', 'Mechanical engineering (B3)'), ('B4', 'EEA (B4)'), ('C', 'Design (C)'), ('D2', 'Economy-management (D2)'), ('D3', 'Social sciences (D3)'), ('E', 'English (E)'), ('EXT', 'External (EXT)')], max_length=8, verbose_name='department'),
+ ),
+ ]
diff --git a/apps/member/views.py b/apps/member/views.py
index 39edcc0b..6ce8d4c5 100644
--- a/apps/member/views.py
+++ b/apps/member/views.py
@@ -18,7 +18,7 @@ from django.views.generic import DetailView, UpdateView, TemplateView
from django.views.generic.edit import FormMixin
from django_tables2.views import SingleTableView
from rest_framework.authtoken.models import Token
-from note.models import Alias, NoteUser
+from note.models import Alias, NoteUser, NoteClub
from note.models.transactions import Transaction, SpecialTransaction
from note.tables import HistoryTable, AliasTable
from note_kfet.middlewares import _set_current_request
@@ -174,7 +174,7 @@ class UserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
modified_note = NoteUser.objects.get(pk=user.note.pk)
# Don't log these tests
modified_note._no_signal = True
- modified_note.is_active = True
+ modified_note.is_active = False
modified_note.inactivity_reason = 'manual'
context["can_lock_note"] = user.note.is_active and PermissionBackend\
.check_perm(self.request, "note.change_noteuser_is_active", modified_note)
@@ -183,14 +183,14 @@ class UserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
modified_note._force_save = True
modified_note.save()
context["can_force_lock"] = user.note.is_active and PermissionBackend\
- .check_perm(self.request, "note.change_note_is_active", modified_note)
+ .check_perm(self.request, "note.change_noteuser_is_active", modified_note)
old_note._force_save = True
old_note._no_signal = True
old_note.save()
modified_note.refresh_from_db()
modified_note.is_active = True
context["can_unlock_note"] = not user.note.is_active and PermissionBackend\
- .check_perm(self.request, "note.change_note_is_active", modified_note)
+ .check_perm(self.request, "note.change_noteuser_is_active", modified_note)
return context
@@ -256,7 +256,8 @@ class ProfileAliasView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
context = super().get_context_data(**kwargs)
note = context['object'].note
context["aliases"] = AliasTable(
- note.alias.filter(PermissionBackend.filter_queryset(self.request, Alias, "view")).distinct().all())
+ note.alias.filter(PermissionBackend.filter_queryset(self.request, Alias, "view")).distinct()
+ .order_by('normalized_name').all())
context["can_create"] = PermissionBackend.check_perm(self.request, "note.add_alias", Alias(
note=context["object"].note,
name="",
@@ -403,9 +404,12 @@ class ClubDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
"""
context = super().get_context_data(**kwargs)
- club = context["club"]
+ club = self.object
+ context["note"] = club.note
+
if PermissionBackend.check_perm(self.request, "member.change_club_membership_start", club):
club.update_membership_dates()
+
# managers list
managers = Membership.objects.filter(club=self.object, roles__name="Bureau de club",
date_start__lte=date.today(), date_end__gte=date.today())\
@@ -443,6 +447,29 @@ class ClubDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
context["can_add_members"] = PermissionBackend()\
.has_perm(self.request.user, "member.add_membership", empty_membership)
+ # Check permissions to see if the authenticated user can lock/unlock the note
+ with transaction.atomic():
+ modified_note = NoteClub.objects.get(pk=club.note.pk)
+ # Don't log these tests
+ modified_note._no_signal = True
+ modified_note.is_active = False
+ modified_note.inactivity_reason = 'manual'
+ context["can_lock_note"] = club.note.is_active and PermissionBackend \
+ .check_perm(self.request, "note.change_noteclub_is_active", modified_note)
+ old_note = NoteClub.objects.select_for_update().get(pk=club.note.pk)
+ modified_note.inactivity_reason = 'forced'
+ modified_note._force_save = True
+ modified_note.save()
+ context["can_force_lock"] = club.note.is_active and PermissionBackend \
+ .check_perm(self.request, "note.change_noteclub_is_active", modified_note)
+ old_note._force_save = True
+ old_note._no_signal = True
+ old_note.save()
+ modified_note.refresh_from_db()
+ modified_note.is_active = True
+ context["can_unlock_note"] = not club.note.is_active and PermissionBackend \
+ .check_perm(self.request, "note.change_noteclub_is_active", modified_note)
+
return context
diff --git a/apps/note/tables.py b/apps/note/tables.py
index 518173c6..2cfbcc76 100644
--- a/apps/note/tables.py
+++ b/apps/note/tables.py
@@ -4,7 +4,7 @@
import html
import django_tables2 as tables
-from django.utils.html import format_html
+from django.utils.html import format_html, mark_safe
from django_tables2.utils import A
from django.utils.translation import gettext_lazy as _
from note_kfet.middlewares import get_current_request
@@ -197,6 +197,17 @@ class ButtonTable(tables.Table):
verbose_name=_("Edit"),
)
+ hideshow = tables.Column(
+ verbose_name=_("Hide/Show"),
+ accessor="pk",
+ attrs={
+ 'td': {
+ 'class': 'col-sm-1',
+ 'id': lambda record: "hideshow_" + str(record.pk),
+ }
+ },
+ )
+
delete_col = tables.TemplateColumn(template_code=DELETE_TEMPLATE,
extra_context={"delete_trans": _('delete')},
attrs={'td': {'class': 'col-sm-1'}},
@@ -204,3 +215,16 @@ class ButtonTable(tables.Table):
def render_amount(self, value):
return pretty_money(value)
+
+ def order_category(self, queryset, is_descending):
+ return queryset.order_by(f"{'-' if is_descending else ''}category__name"), True
+
+ def render_hideshow(self, record):
+ val = ''
+ return mark_safe(val)
diff --git a/apps/note/templates/note/transactiontemplate_list.html b/apps/note/templates/note/transactiontemplate_list.html
index 2a19922e..3536f9f8 100644
--- a/apps/note/templates/note/transactiontemplate_list.html
+++ b/apps/note/templates/note/transactiontemplate_list.html
@@ -31,29 +31,29 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% block extrajavascript %}
{% endblock %}
diff --git a/apps/note/views.py b/apps/note/views.py
index 074da01d..1224f2f8 100644
--- a/apps/note/views.py
+++ b/apps/note/views.py
@@ -90,9 +90,9 @@ class TransactionTemplateListView(ProtectQuerysetMixin, LoginRequiredMixin, Sing
if "search" in self.request.GET:
pattern = self.request.GET["search"]
qs = qs.filter(
- Q(name__iregex="^" + pattern)
- | Q(destination__club__name__iregex="^" + pattern)
- | Q(category__name__iregex="^" + pattern)
+ Q(name__iregex=pattern)
+ | Q(destination__club__name__iregex=pattern)
+ | Q(category__name__iregex=pattern)
| Q(description__iregex=pattern)
)
diff --git a/apps/permission/fixtures/initial.json b/apps/permission/fixtures/initial.json
index fe4f90e8..a7ed75f4 100644
--- a/apps/permission/fixtures/initial.json
+++ b/apps/permission/fixtures/initial.json
@@ -977,7 +977,7 @@
],
"query": "[\"OR\", {\"source\": [\"club\", \"note\"]}, {\"destination\": [\"club\", \"note\"]}]",
"type": "view",
- "mask": 1,
+ "mask": 2,
"field": "",
"permanent": false,
"description": "Voir les transactions d'un club"
@@ -2511,7 +2511,7 @@
"note",
"noteuser"
],
- "query": "[\"AND\", {\"user\": [\"user\"]}, [\"OR\", {\"inactivity_reason\": \"manual\"}, {\"inactivity_reason\": null}]]",
+ "query": "[\"AND\", {\"user\": [\"user\"]}, [\"OR\", {\"inactivity_reason\": \"manual\"}, {\"is_active\": true}]]",
"type": "change",
"mask": 1,
"field": "is_active",
@@ -2527,7 +2527,7 @@
"note",
"noteuser"
],
- "query": "[\"AND\", {\"user\": [\"user\"]}, [\"OR\", {\"inactivity_reason\": \"manual\"}, {\"inactivity_reason\": null}]]",
+ "query": "[\"AND\", {\"user\": [\"user\"]}, [\"OR\", {\"inactivity_reason\": \"manual\"}, {\"is_active\": true}]]",
"type": "change",
"mask": 1,
"field": "inactivity_reason",
@@ -2871,6 +2871,38 @@
"description": "Changer l'image de n'importe quelle note"
}
},
+ {
+ "model": "permission.permission",
+ "pk": 184,
+ "fields": {
+ "model": [
+ "note",
+ "noteclub"
+ ],
+ "query": "[\"AND\", {\"club\": [\"club\"]}, [\"OR\", {\"inactivity_reason\": \"manual\"}, {\"is_active\": true}]]",
+ "type": "change",
+ "mask": 3,
+ "field": "is_active",
+ "permanent": true,
+ "description": "(Dé)bloquer la note de son club manuellement"
+ }
+ },
+ {
+ "model": "permission.permission",
+ "pk": 185,
+ "fields": {
+ "model": [
+ "note",
+ "noteclub"
+ ],
+ "query": "[\"AND\", {\"club\": [\"club\"]}, [\"OR\", {\"inactivity_reason\": \"manual\"}, {\"is_active\": true}]]",
+ "type": "change",
+ "mask": 3,
+ "field": "inactivity_reason",
+ "permanent": true,
+ "description": "(Dé)bloquer la note de son club et indiquer que cela a été fait manuellement"
+ }
+ },
{
"model": "permission.role",
"pk": 1,
@@ -3010,7 +3042,9 @@
166,
167,
168,
- 182
+ 182,
+ 184,
+ 185
]
}
},
@@ -3278,7 +3312,9 @@
180,
181,
182,
- 183
+ 183,
+ 184,
+ 185
]
}
},
@@ -3338,7 +3374,8 @@
45,
46,
148,
- 149
+ 149,
+ 182
]
}
},
diff --git a/apps/scripts b/apps/scripts
index 7a022b94..86bc2d26 160000
--- a/apps/scripts
+++ b/apps/scripts
@@ -1 +1 @@
-Subproject commit 7a022b9407bdcbe97a78bfc10b2812c9b0aaf314
+Subproject commit 86bc2d269853ad60391e242ff655f0dc83b5967d
diff --git a/apps/treasury/migrations/0004_auto_20211005_1544.py b/apps/treasury/migrations/0004_auto_20211005_1544.py
new file mode 100644
index 00000000..6016a47f
--- /dev/null
+++ b/apps/treasury/migrations/0004_auto_20211005_1544.py
@@ -0,0 +1,18 @@
+# Generated by Django 2.2.24 on 2021-10-05 13:44
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('treasury', '0003_auto_20210321_1034'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='sogecredit',
+ name='transactions',
+ field=models.ManyToManyField(blank=True, related_name='_sogecredit_transactions_+', to='note.MembershipTransaction', verbose_name='membership transactions'),
+ ),
+ ]
diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po
index d7f05ff3..4ee77566 100644
--- a/locale/fr/LC_MESSAGES/django.po
+++ b/locale/fr/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2021-09-28 17:02+0200\n"
+"POT-Creation-Date: 2021-10-07 22:55+0200\n"
"PO-Revision-Date: 2020-11-16 20:02+0000\n"
"Last-Translator: Yohann D'ANELLO \n"
"Language-Team: French \n"
@@ -279,7 +279,7 @@ msgstr "Prénom"
msgid "Note"
msgstr "Note"
-#: apps/activity/tables.py:90 apps/member/tables.py:49
+#: apps/activity/tables.py:90 apps/member/tables.py:50
msgid "Balance"
msgstr "Solde du compte"
@@ -320,13 +320,13 @@ msgstr "Entrées"
msgid "Return to activity page"
msgstr "Retour à la page de l'activité"
-#: apps/activity/templates/activity/activity_entry.html:89
-#: apps/activity/templates/activity/activity_entry.html:124
+#: apps/activity/templates/activity/activity_entry.html:94
+#: apps/activity/templates/activity/activity_entry.html:129
msgid "Entry done, but caution: the user is not a Kfet member."
msgstr ""
"Entrée effectuée, mais attention : la personne n'est pas un adhérent Kfet."
-#: apps/activity/templates/activity/activity_entry.html:127
+#: apps/activity/templates/activity/activity_entry.html:132
msgid "Entry done!"
msgstr "Entrée effectuée !"
@@ -404,33 +404,33 @@ msgstr "Créer une nouvelle activité"
msgid "Activities"
msgstr "Activités"
-#: apps/activity/views.py:95
+#: apps/activity/views.py:93
msgid "Activity detail"
msgstr "Détails de l'activité"
-#: apps/activity/views.py:115
+#: apps/activity/views.py:113
msgid "Update activity"
msgstr "Modifier l'activité"
-#: apps/activity/views.py:142
+#: apps/activity/views.py:140
msgid "Invite guest to the activity \"{}\""
msgstr "Invitation pour l'activité « {} »"
-#: apps/activity/views.py:177
+#: apps/activity/views.py:178
msgid "You are not allowed to display the entry interface for this activity."
msgstr ""
"Vous n'êtes pas autorisé à afficher l'interface des entrées pour cette "
"activité."
-#: apps/activity/views.py:180
+#: apps/activity/views.py:181
msgid "This activity does not support activity entries."
msgstr "Cette activité ne requiert pas d'entrées."
-#: apps/activity/views.py:183
+#: apps/activity/views.py:184
msgid "This activity is closed."
msgstr "Cette activité est fermée."
-#: apps/activity/views.py:279
+#: apps/activity/views.py:280
msgid "Entry for activity \"{}\""
msgstr "Entrées pour l'activité « {} »"
@@ -466,7 +466,7 @@ msgstr "nouvelles données"
msgid "create"
msgstr "créer"
-#: apps/logs/models.py:65 apps/note/tables.py:165 apps/note/tables.py:201
+#: apps/logs/models.py:65 apps/note/tables.py:165 apps/note/tables.py:211
#: apps/permission/models.py:127 apps/treasury/tables.py:38
#: apps/wei/tables.py:74
msgid "delete"
@@ -850,33 +850,33 @@ msgstr "l'adhésion commence le"
msgid "membership ends on"
msgstr "l'adhésion finit le"
-#: apps/member/models.py:422
+#: apps/member/models.py:428
#, python-brace-format
msgid "The role {role} does not apply to the club {club}."
msgstr "Le rôle {role} ne s'applique pas au club {club}."
-#: apps/member/models.py:431 apps/member/views.py:651
+#: apps/member/models.py:437 apps/member/views.py:651
msgid "User is already a member of the club"
msgstr "L'utilisateur est déjà membre du club"
-#: apps/member/models.py:443 apps/member/views.py:660
+#: apps/member/models.py:449 apps/member/views.py:660
msgid "User is not a member of the parent club"
msgstr "L'utilisateur n'est pas membre du club parent"
-#: apps/member/models.py:496
+#: apps/member/models.py:502
#, python-brace-format
msgid "Membership of {user} for the club {club}"
msgstr "Adhésion de {user} pour le club {club}"
-#: apps/member/models.py:499 apps/note/models/transactions.py:389
+#: apps/member/models.py:505 apps/note/models/transactions.py:389
msgid "membership"
msgstr "adhésion"
-#: apps/member/models.py:500
+#: apps/member/models.py:506
msgid "memberships"
msgstr "adhésions"
-#: apps/member/tables.py:137
+#: apps/member/tables.py:139
msgid "Renew"
msgstr "Renouveler"
@@ -1535,7 +1535,7 @@ msgstr "Cliquez pour valider"
msgid "No reason specified"
msgstr "Pas de motif spécifié"
-#: apps/note/tables.py:169 apps/note/tables.py:203 apps/treasury/tables.py:39
+#: apps/note/tables.py:169 apps/note/tables.py:213 apps/treasury/tables.py:39
#: apps/treasury/templates/treasury/invoice_confirm_delete.html:30
#: apps/treasury/templates/treasury/sogecredit_detail.html:65
#: apps/wei/tables.py:75 apps/wei/tables.py:118
@@ -1556,6 +1556,10 @@ msgstr "Supprimer"
msgid "Edit"
msgstr "Éditer"
+#: apps/note/tables.py:201 apps/note/tables.py:224
+msgid "Hide/Show"
+msgstr "Afficher/Masquer"
+
#: apps/note/templates/note/conso_form.html:22
#: apps/note/templates/note/transaction_form.html:48
msgid "Please select a note"
@@ -1685,6 +1689,18 @@ msgstr "le bouton a bien été supprimé "
msgid "Unable to delete button "
msgstr "Impossible de supprimer le bouton "
+#: apps/note/templates/note/transactiontemplate_list.html:95
+msgid "Button hidden"
+msgstr "Bouton masqué"
+
+#: apps/note/templates/note/transactiontemplate_list.html:96
+msgid "Button displayed"
+msgstr "Bouton affiché"
+
+#: apps/note/templates/note/transactiontemplate_list.html:100
+msgid "An error occured"
+msgstr "Une erreur s'est produite"
+
#: apps/note/views.py:36
msgid "Transfer money"
msgstr "Transférer de l'argent"
@@ -3501,8 +3517,3 @@ msgstr ""
"vous connecter. Vous devez vous rendre à la Kfet et payer les frais "
"d'adhésion. Vous devez également valider votre adresse email en suivant le "
"lien que vous avez reçu."
-
-#~ msgid "You are not a Kfet member, so you can't use your note account."
-#~ msgstr ""
-#~ "Vous n'êtes pas adhérent Kfet, vous ne pouvez par conséquent pas utiliser "
-#~ "votre compte note."
diff --git a/note_kfet/static/js/turbolinks.js b/note_kfet/static/js/turbolinks.js
new file mode 100644
index 00000000..644af9b1
--- /dev/null
+++ b/note_kfet/static/js/turbolinks.js
@@ -0,0 +1,6 @@
+/*
+Turbolinks 5.2.0
+Copyright © 2018 Basecamp, LLC
+ */
+(function(){var t=this;(function(){(function(){this.Turbolinks={supported:function(){return null!=window.history.pushState&&null!=window.requestAnimationFrame&&null!=window.addEventListener}(),visit:function(t,r){return e.controller.visit(t,r)},clearCache:function(){return e.controller.clearCache()},setProgressBarDelay:function(t){return e.controller.setProgressBarDelay(t)}}}).call(this)}).call(t);var e=t.Turbolinks;(function(){(function(){var t,r,n,o=[].slice;e.copyObject=function(t){var e,r,n;r={};for(e in t)n=t[e],r[e]=n;return r},e.closest=function(e,r){return t.call(e,r)},t=function(){var t,e;return t=document.documentElement,null!=(e=t.closest)?e:function(t){var e;for(e=this;e;){if(e.nodeType===Node.ELEMENT_NODE&&r.call(e,t))return e;e=e.parentNode}}}(),e.defer=function(t){return setTimeout(t,1)},e.throttle=function(t){var e;return e=null,function(){var r;return r=1<=arguments.length?o.call(arguments,0):[],null!=e?e:e=requestAnimationFrame(function(n){return function(){return e=null,t.apply(n,r)}}(this))}},e.dispatch=function(t,e){var r,o,i,s,a,u;return a=null!=e?e:{},u=a.target,r=a.cancelable,o=a.data,i=document.createEvent("Events"),i.initEvent(t,!0,r===!0),i.data=null!=o?o:{},i.cancelable&&!n&&(s=i.preventDefault,i.preventDefault=function(){return this.defaultPrevented||Object.defineProperty(this,"defaultPrevented",{get:function(){return!0}}),s.call(this)}),(null!=u?u:document).dispatchEvent(i),i},n=function(){var t;return t=document.createEvent("Events"),t.initEvent("test",!0,!0),t.preventDefault(),t.defaultPrevented}(),e.match=function(t,e){return r.call(t,e)},r=function(){var t,e,r,n;return t=document.documentElement,null!=(e=null!=(r=null!=(n=t.matchesSelector)?n:t.webkitMatchesSelector)?r:t.msMatchesSelector)?e:t.mozMatchesSelector}(),e.uuid=function(){var t,e,r;for(r="",t=e=1;36>=e;t=++e)r+=9===t||14===t||19===t||24===t?"-":15===t?"4":20===t?(Math.floor(4*Math.random())+8).toString(16):Math.floor(15*Math.random()).toString(16);return r}}).call(this),function(){e.Location=function(){function t(t){var e,r;null==t&&(t=""),r=document.createElement("a"),r.href=t.toString(),this.absoluteURL=r.href,e=r.hash.length,2>e?this.requestURL=this.absoluteURL:(this.requestURL=this.absoluteURL.slice(0,-e),this.anchor=r.hash.slice(1))}var e,r,n,o;return t.wrap=function(t){return t instanceof this?t:new this(t)},t.prototype.getOrigin=function(){return this.absoluteURL.split("/",3).join("/")},t.prototype.getPath=function(){var t,e;return null!=(t=null!=(e=this.requestURL.match(/\/\/[^\/]*(\/[^?;]*)/))?e[1]:void 0)?t:"/"},t.prototype.getPathComponents=function(){return this.getPath().split("/").slice(1)},t.prototype.getLastPathComponent=function(){return this.getPathComponents().slice(-1)[0]},t.prototype.getExtension=function(){var t,e;return null!=(t=null!=(e=this.getLastPathComponent().match(/\.[^.]*$/))?e[0]:void 0)?t:""},t.prototype.isHTML=function(){return this.getExtension().match(/^(?:|\.(?:htm|html|xhtml))$/)},t.prototype.isPrefixedBy=function(t){var e;return e=r(t),this.isEqualTo(t)||o(this.absoluteURL,e)},t.prototype.isEqualTo=function(t){return this.absoluteURL===(null!=t?t.absoluteURL:void 0)},t.prototype.toCacheKey=function(){return this.requestURL},t.prototype.toJSON=function(){return this.absoluteURL},t.prototype.toString=function(){return this.absoluteURL},t.prototype.valueOf=function(){return this.absoluteURL},r=function(t){return e(t.getOrigin()+t.getPath())},e=function(t){return n(t,"/")?t:t+"/"},o=function(t,e){return t.slice(0,e.length)===e},n=function(t,e){return t.slice(-e.length)===e},t}()}.call(this),function(){var t=function(t,e){return function(){return t.apply(e,arguments)}};e.HttpRequest=function(){function r(r,n,o){this.delegate=r,this.requestCanceled=t(this.requestCanceled,this),this.requestTimedOut=t(this.requestTimedOut,this),this.requestFailed=t(this.requestFailed,this),this.requestLoaded=t(this.requestLoaded,this),this.requestProgressed=t(this.requestProgressed,this),this.url=e.Location.wrap(n).requestURL,this.referrer=e.Location.wrap(o).absoluteURL,this.createXHR()}return r.NETWORK_FAILURE=0,r.TIMEOUT_FAILURE=-1,r.timeout=60,r.prototype.send=function(){var t;return this.xhr&&!this.sent?(this.notifyApplicationBeforeRequestStart(),this.setProgress(0),this.xhr.send(),this.sent=!0,"function"==typeof(t=this.delegate).requestStarted?t.requestStarted():void 0):void 0},r.prototype.cancel=function(){return this.xhr&&this.sent?this.xhr.abort():void 0},r.prototype.requestProgressed=function(t){return t.lengthComputable?this.setProgress(t.loaded/t.total):void 0},r.prototype.requestLoaded=function(){return this.endRequest(function(t){return function(){var e;return 200<=(e=t.xhr.status)&&300>e?t.delegate.requestCompletedWithResponse(t.xhr.responseText,t.xhr.getResponseHeader("Turbolinks-Location")):(t.failed=!0,t.delegate.requestFailedWithStatusCode(t.xhr.status,t.xhr.responseText))}}(this))},r.prototype.requestFailed=function(){return this.endRequest(function(t){return function(){return t.failed=!0,t.delegate.requestFailedWithStatusCode(t.constructor.NETWORK_FAILURE)}}(this))},r.prototype.requestTimedOut=function(){return this.endRequest(function(t){return function(){return t.failed=!0,t.delegate.requestFailedWithStatusCode(t.constructor.TIMEOUT_FAILURE)}}(this))},r.prototype.requestCanceled=function(){return this.endRequest()},r.prototype.notifyApplicationBeforeRequestStart=function(){return e.dispatch("turbolinks:request-start",{data:{url:this.url,xhr:this.xhr}})},r.prototype.notifyApplicationAfterRequestEnd=function(){return e.dispatch("turbolinks:request-end",{data:{url:this.url,xhr:this.xhr}})},r.prototype.createXHR=function(){return this.xhr=new XMLHttpRequest,this.xhr.open("GET",this.url,!0),this.xhr.timeout=1e3*this.constructor.timeout,this.xhr.setRequestHeader("Accept","text/html, application/xhtml+xml"),this.xhr.setRequestHeader("Turbolinks-Referrer",this.referrer),this.xhr.onprogress=this.requestProgressed,this.xhr.onload=this.requestLoaded,this.xhr.onerror=this.requestFailed,this.xhr.ontimeout=this.requestTimedOut,this.xhr.onabort=this.requestCanceled},r.prototype.endRequest=function(t){return this.xhr?(this.notifyApplicationAfterRequestEnd(),null!=t&&t.call(this),this.destroy()):void 0},r.prototype.setProgress=function(t){var e;return this.progress=t,"function"==typeof(e=this.delegate).requestProgressed?e.requestProgressed(this.progress):void 0},r.prototype.destroy=function(){var t;return this.setProgress(1),"function"==typeof(t=this.delegate).requestFinished&&t.requestFinished(),this.delegate=null,this.xhr=null},r}()}.call(this),function(){var t=function(t,e){return function(){return t.apply(e,arguments)}};e.ProgressBar=function(){function e(){this.trickle=t(this.trickle,this),this.stylesheetElement=this.createStylesheetElement(),this.progressElement=this.createProgressElement()}var r;return r=300,e.defaultCSS=".turbolinks-progress-bar {\n position: fixed;\n display: block;\n top: 0;\n left: 0;\n height: 3px;\n background: #0076ff;\n z-index: 9999;\n transition: width "+r+"ms ease-out, opacity "+r/2+"ms "+r/2+"ms ease-in;\n transform: translate3d(0, 0, 0);\n}",e.prototype.show=function(){return this.visible?void 0:(this.visible=!0,this.installStylesheetElement(),this.installProgressElement(),this.startTrickling())},e.prototype.hide=function(){return this.visible&&!this.hiding?(this.hiding=!0,this.fadeProgressElement(function(t){return function(){return t.uninstallProgressElement(),t.stopTrickling(),t.visible=!1,t.hiding=!1}}(this))):void 0},e.prototype.setValue=function(t){return this.value=t,this.refresh()},e.prototype.installStylesheetElement=function(){return document.head.insertBefore(this.stylesheetElement,document.head.firstChild)},e.prototype.installProgressElement=function(){return this.progressElement.style.width=0,this.progressElement.style.opacity=1,document.documentElement.insertBefore(this.progressElement,document.body),this.refresh()},e.prototype.fadeProgressElement=function(t){return this.progressElement.style.opacity=0,setTimeout(t,1.5*r)},e.prototype.uninstallProgressElement=function(){return this.progressElement.parentNode?document.documentElement.removeChild(this.progressElement):void 0},e.prototype.startTrickling=function(){return null!=this.trickleInterval?this.trickleInterval:this.trickleInterval=setInterval(this.trickle,r)},e.prototype.stopTrickling=function(){return clearInterval(this.trickleInterval),this.trickleInterval=null},e.prototype.trickle=function(){return this.setValue(this.value+Math.random()/100)},e.prototype.refresh=function(){return requestAnimationFrame(function(t){return function(){return t.progressElement.style.width=10+90*t.value+"%"}}(this))},e.prototype.createStylesheetElement=function(){var t;return t=document.createElement("style"),t.type="text/css",t.textContent=this.constructor.defaultCSS,t},e.prototype.createProgressElement=function(){var t;return t=document.createElement("div"),t.className="turbolinks-progress-bar",t},e}()}.call(this),function(){var t=function(t,e){return function(){return t.apply(e,arguments)}};e.BrowserAdapter=function(){function r(r){this.controller=r,this.showProgressBar=t(this.showProgressBar,this),this.progressBar=new e.ProgressBar}var n,o,i;return i=e.HttpRequest,n=i.NETWORK_FAILURE,o=i.TIMEOUT_FAILURE,r.prototype.visitProposedToLocationWithAction=function(t,e){return this.controller.startVisitToLocationWithAction(t,e)},r.prototype.visitStarted=function(t){return t.issueRequest(),t.changeHistory(),t.loadCachedSnapshot()},r.prototype.visitRequestStarted=function(t){return this.progressBar.setValue(0),t.hasCachedSnapshot()||"restore"!==t.action?this.showProgressBarAfterDelay():this.showProgressBar()},r.prototype.visitRequestProgressed=function(t){return this.progressBar.setValue(t.progress)},r.prototype.visitRequestCompleted=function(t){return t.loadResponse()},r.prototype.visitRequestFailedWithStatusCode=function(t,e){switch(e){case n:case o:return this.reload();default:return t.loadResponse()}},r.prototype.visitRequestFinished=function(t){return this.hideProgressBar()},r.prototype.visitCompleted=function(t){return t.followRedirect()},r.prototype.pageInvalidated=function(){return this.reload()},r.prototype.showProgressBarAfterDelay=function(){return this.progressBarTimeout=setTimeout(this.showProgressBar,this.controller.progressBarDelay)},r.prototype.showProgressBar=function(){return this.progressBar.show()},r.prototype.hideProgressBar=function(){return this.progressBar.hide(),clearTimeout(this.progressBarTimeout)},r.prototype.reload=function(){return window.location.reload()},r}()}.call(this),function(){var t=function(t,e){return function(){return t.apply(e,arguments)}};e.History=function(){function r(e){this.delegate=e,this.onPageLoad=t(this.onPageLoad,this),this.onPopState=t(this.onPopState,this)}return r.prototype.start=function(){return this.started?void 0:(addEventListener("popstate",this.onPopState,!1),addEventListener("load",this.onPageLoad,!1),this.started=!0)},r.prototype.stop=function(){return this.started?(removeEventListener("popstate",this.onPopState,!1),removeEventListener("load",this.onPageLoad,!1),this.started=!1):void 0},r.prototype.push=function(t,r){return t=e.Location.wrap(t),this.update("push",t,r)},r.prototype.replace=function(t,r){return t=e.Location.wrap(t),this.update("replace",t,r)},r.prototype.onPopState=function(t){var r,n,o,i;return this.shouldHandlePopState()&&(i=null!=(n=t.state)?n.turbolinks:void 0)?(r=e.Location.wrap(window.location),o=i.restorationIdentifier,this.delegate.historyPoppedToLocationWithRestorationIdentifier(r,o)):void 0},r.prototype.onPageLoad=function(t){return e.defer(function(t){return function(){return t.pageLoaded=!0}}(this))},r.prototype.shouldHandlePopState=function(){return this.pageIsLoaded()},r.prototype.pageIsLoaded=function(){return this.pageLoaded||"complete"===document.readyState},r.prototype.update=function(t,e,r){var n;return n={turbolinks:{restorationIdentifier:r}},history[t+"State"](n,null,e)},r}()}.call(this),function(){e.HeadDetails=function(){function t(t){var e,r,n,s,a,u;for(this.elements={},n=0,a=t.length;a>n;n++)u=t[n],u.nodeType===Node.ELEMENT_NODE&&(s=u.outerHTML,r=null!=(e=this.elements)[s]?e[s]:e[s]={type:i(u),tracked:o(u),elements:[]},r.elements.push(u))}var e,r,n,o,i;return t.fromHeadElement=function(t){var e;return new this(null!=(e=null!=t?t.childNodes:void 0)?e:[])},t.prototype.hasElementWithKey=function(t){return t in this.elements},t.prototype.getTrackedElementSignature=function(){var t,e;return function(){var r,n;r=this.elements,n=[];for(t in r)e=r[t].tracked,e&&n.push(t);return n}.call(this).join("")},t.prototype.getScriptElementsNotInDetails=function(t){return this.getElementsMatchingTypeNotInDetails("script",t)},t.prototype.getStylesheetElementsNotInDetails=function(t){return this.getElementsMatchingTypeNotInDetails("stylesheet",t)},t.prototype.getElementsMatchingTypeNotInDetails=function(t,e){var r,n,o,i,s,a;o=this.elements,s=[];for(n in o)i=o[n],a=i.type,r=i.elements,a!==t||e.hasElementWithKey(n)||s.push(r[0]);return s},t.prototype.getProvisionalElements=function(){var t,e,r,n,o,i,s;r=[],n=this.elements;for(e in n)o=n[e],s=o.type,i=o.tracked,t=o.elements,null!=s||i?t.length>1&&r.push.apply(r,t.slice(1)):r.push.apply(r,t);return r},t.prototype.getMetaValue=function(t){var e;return null!=(e=this.findMetaElementByName(t))?e.getAttribute("content"):void 0},t.prototype.findMetaElementByName=function(t){var r,n,o,i;r=void 0,i=this.elements;for(o in i)n=i[o].elements,e(n[0],t)&&(r=n[0]);return r},i=function(t){return r(t)?"script":n(t)?"stylesheet":void 0},o=function(t){return"reload"===t.getAttribute("data-turbolinks-track")},r=function(t){var e;return e=t.tagName.toLowerCase(),"script"===e},n=function(t){var e;return e=t.tagName.toLowerCase(),"style"===e||"link"===e&&"stylesheet"===t.getAttribute("rel")},e=function(t,e){var r;return r=t.tagName.toLowerCase(),"meta"===r&&t.getAttribute("name")===e},t}()}.call(this),function(){e.Snapshot=function(){function t(t,e){this.headDetails=t,this.bodyElement=e}return t.wrap=function(t){return t instanceof this?t:"string"==typeof t?this.fromHTMLString(t):this.fromHTMLElement(t)},t.fromHTMLString=function(t){var e;return e=document.createElement("html"),e.innerHTML=t,this.fromHTMLElement(e)},t.fromHTMLElement=function(t){var r,n,o,i;return o=t.querySelector("head"),r=null!=(i=t.querySelector("body"))?i:document.createElement("body"),n=e.HeadDetails.fromHeadElement(o),new this(n,r)},t.prototype.clone=function(){return new this.constructor(this.headDetails,this.bodyElement.cloneNode(!0))},t.prototype.getRootLocation=function(){var t,r;return r=null!=(t=this.getSetting("root"))?t:"/",new e.Location(r)},t.prototype.getCacheControlValue=function(){return this.getSetting("cache-control")},t.prototype.getElementForAnchor=function(t){try{return this.bodyElement.querySelector("[id='"+t+"'], a[name='"+t+"']")}catch(e){}},t.prototype.getPermanentElements=function(){return this.bodyElement.querySelectorAll("[id][data-turbolinks-permanent]")},t.prototype.getPermanentElementById=function(t){return this.bodyElement.querySelector("#"+t+"[data-turbolinks-permanent]")},t.prototype.getPermanentElementsPresentInSnapshot=function(t){var e,r,n,o,i;for(o=this.getPermanentElements(),i=[],r=0,n=o.length;n>r;r++)e=o[r],t.getPermanentElementById(e.id)&&i.push(e);return i},t.prototype.findFirstAutofocusableElement=function(){return this.bodyElement.querySelector("[autofocus]")},t.prototype.hasAnchor=function(t){return null!=this.getElementForAnchor(t)},t.prototype.isPreviewable=function(){return"no-preview"!==this.getCacheControlValue()},t.prototype.isCacheable=function(){return"no-cache"!==this.getCacheControlValue()},t.prototype.isVisitable=function(){return"reload"!==this.getSetting("visit-control")},t.prototype.getSetting=function(t){return this.headDetails.getMetaValue("turbolinks-"+t)},t}()}.call(this),function(){var t=[].slice;e.Renderer=function(){function e(){}var r;return e.render=function(){var e,r,n,o;return n=arguments[0],r=arguments[1],e=3<=arguments.length?t.call(arguments,2):[],o=function(t,e,r){r.prototype=t.prototype;var n=new r,o=t.apply(n,e);return Object(o)===o?o:n}(this,e,function(){}),o.delegate=n,o.render(r),o},e.prototype.renderView=function(t){return this.delegate.viewWillRender(this.newBody),t(),this.delegate.viewRendered(this.newBody)},e.prototype.invalidateView=function(){return this.delegate.viewInvalidated()},e.prototype.createScriptElement=function(t){var e;return"false"===t.getAttribute("data-turbolinks-eval")?t:(e=document.createElement("script"),e.textContent=t.textContent,e.async=!1,r(e,t),e)},r=function(t,e){var r,n,o,i,s,a,u;for(i=e.attributes,a=[],r=0,n=i.length;n>r;r++)s=i[r],o=s.name,u=s.value,a.push(t.setAttribute(o,u));return a},e}()}.call(this),function(){var t,r,n=function(t,e){function r(){this.constructor=t}for(var n in e)o.call(e,n)&&(t[n]=e[n]);return r.prototype=e.prototype,t.prototype=new r,t.__super__=e.prototype,t},o={}.hasOwnProperty;e.SnapshotRenderer=function(e){function o(t,e,r){this.currentSnapshot=t,this.newSnapshot=e,this.isPreview=r,this.currentHeadDetails=this.currentSnapshot.headDetails,this.newHeadDetails=this.newSnapshot.headDetails,this.currentBody=this.currentSnapshot.bodyElement,this.newBody=this.newSnapshot.bodyElement}return n(o,e),o.prototype.render=function(t){return this.shouldRender()?(this.mergeHead(),this.renderView(function(e){return function(){return e.replaceBody(),e.isPreview||e.focusFirstAutofocusableElement(),t()}}(this))):this.invalidateView()},o.prototype.mergeHead=function(){return this.copyNewHeadStylesheetElements(),this.copyNewHeadScriptElements(),this.removeCurrentHeadProvisionalElements(),this.copyNewHeadProvisionalElements()},o.prototype.replaceBody=function(){var t;return t=this.relocateCurrentBodyPermanentElements(),this.activateNewBodyScriptElements(),this.assignNewBody(),this.replacePlaceholderElementsWithClonedPermanentElements(t)},o.prototype.shouldRender=function(){return this.newSnapshot.isVisitable()&&this.trackedElementsAreIdentical()},o.prototype.trackedElementsAreIdentical=function(){return this.currentHeadDetails.getTrackedElementSignature()===this.newHeadDetails.getTrackedElementSignature()},o.prototype.copyNewHeadStylesheetElements=function(){var t,e,r,n,o;for(n=this.getNewHeadStylesheetElements(),o=[],e=0,r=n.length;r>e;e++)t=n[e],o.push(document.head.appendChild(t));return o},o.prototype.copyNewHeadScriptElements=function(){var t,e,r,n,o;for(n=this.getNewHeadScriptElements(),o=[],e=0,r=n.length;r>e;e++)t=n[e],o.push(document.head.appendChild(this.createScriptElement(t)));return o},o.prototype.removeCurrentHeadProvisionalElements=function(){var t,e,r,n,o;for(n=this.getCurrentHeadProvisionalElements(),o=[],e=0,r=n.length;r>e;e++)t=n[e],o.push(document.head.removeChild(t));return o},o.prototype.copyNewHeadProvisionalElements=function(){var t,e,r,n,o;for(n=this.getNewHeadProvisionalElements(),o=[],e=0,r=n.length;r>e;e++)t=n[e],o.push(document.head.appendChild(t));return o},o.prototype.relocateCurrentBodyPermanentElements=function(){var e,n,o,i,s,a,u;for(a=this.getCurrentBodyPermanentElements(),u=[],e=0,n=a.length;n>e;e++)i=a[e],s=t(i),o=this.newSnapshot.getPermanentElementById(i.id),r(i,s.element),r(o,i),u.push(s);return u},o.prototype.replacePlaceholderElementsWithClonedPermanentElements=function(t){var e,n,o,i,s,a,u;for(u=[],o=0,i=t.length;i>o;o++)a=t[o],n=a.element,s=a.permanentElement,e=s.cloneNode(!0),u.push(r(n,e));return u},o.prototype.activateNewBodyScriptElements=function(){var t,e,n,o,i,s;for(i=this.getNewBodyScriptElements(),s=[],e=0,o=i.length;o>e;e++)n=i[e],t=this.createScriptElement(n),s.push(r(n,t));return s},o.prototype.assignNewBody=function(){return document.body=this.newBody},o.prototype.focusFirstAutofocusableElement=function(){var t;return null!=(t=this.newSnapshot.findFirstAutofocusableElement())?t.focus():void 0},o.prototype.getNewHeadStylesheetElements=function(){return this.newHeadDetails.getStylesheetElementsNotInDetails(this.currentHeadDetails)},o.prototype.getNewHeadScriptElements=function(){return this.newHeadDetails.getScriptElementsNotInDetails(this.currentHeadDetails)},o.prototype.getCurrentHeadProvisionalElements=function(){return this.currentHeadDetails.getProvisionalElements()},o.prototype.getNewHeadProvisionalElements=function(){return this.newHeadDetails.getProvisionalElements()},o.prototype.getCurrentBodyPermanentElements=function(){return this.currentSnapshot.getPermanentElementsPresentInSnapshot(this.newSnapshot)},o.prototype.getNewBodyScriptElements=function(){return this.newBody.querySelectorAll("script")},o}(e.Renderer),t=function(t){var e;return e=document.createElement("meta"),e.setAttribute("name","turbolinks-permanent-placeholder"),e.setAttribute("content",t.id),{element:e,permanentElement:t}},r=function(t,e){var r;return(r=t.parentNode)?r.replaceChild(e,t):void 0}}.call(this),function(){var t=function(t,e){function n(){this.constructor=t}for(var o in e)r.call(e,o)&&(t[o]=e[o]);return n.prototype=e.prototype,t.prototype=new n,t.__super__=e.prototype,t},r={}.hasOwnProperty;e.ErrorRenderer=function(e){function r(t){var e;e=document.createElement("html"),e.innerHTML=t,this.newHead=e.querySelector("head"),this.newBody=e.querySelector("body")}return t(r,e),r.prototype.render=function(t){return this.renderView(function(e){return function(){return e.replaceHeadAndBody(),e.activateBodyScriptElements(),t()}}(this))},r.prototype.replaceHeadAndBody=function(){var t,e;return e=document.head,t=document.body,e.parentNode.replaceChild(this.newHead,e),t.parentNode.replaceChild(this.newBody,t)},r.prototype.activateBodyScriptElements=function(){var t,e,r,n,o,i;for(n=this.getScriptElements(),i=[],e=0,r=n.length;r>e;e++)o=n[e],t=this.createScriptElement(o),i.push(o.parentNode.replaceChild(t,o));return i},r.prototype.getScriptElements=function(){return document.documentElement.querySelectorAll("script")},r}(e.Renderer)}.call(this),function(){e.View=function(){function t(t){this.delegate=t,this.htmlElement=document.documentElement}return t.prototype.getRootLocation=function(){return this.getSnapshot().getRootLocation()},t.prototype.getElementForAnchor=function(t){return this.getSnapshot().getElementForAnchor(t)},t.prototype.getSnapshot=function(){return e.Snapshot.fromHTMLElement(this.htmlElement)},t.prototype.render=function(t,e){var r,n,o;return o=t.snapshot,r=t.error,n=t.isPreview,this.markAsPreview(n),null!=o?this.renderSnapshot(o,n,e):this.renderError(r,e)},t.prototype.markAsPreview=function(t){return t?this.htmlElement.setAttribute("data-turbolinks-preview",""):this.htmlElement.removeAttribute("data-turbolinks-preview")},t.prototype.renderSnapshot=function(t,r,n){return e.SnapshotRenderer.render(this.delegate,n,this.getSnapshot(),e.Snapshot.wrap(t),r)},t.prototype.renderError=function(t,r){return e.ErrorRenderer.render(this.delegate,r,t)},t}()}.call(this),function(){var t=function(t,e){return function(){return t.apply(e,arguments)}};e.ScrollManager=function(){function r(r){this.delegate=r,this.onScroll=t(this.onScroll,this),this.onScroll=e.throttle(this.onScroll)}return r.prototype.start=function(){return this.started?void 0:(addEventListener("scroll",this.onScroll,!1),this.onScroll(),this.started=!0)},r.prototype.stop=function(){return this.started?(removeEventListener("scroll",this.onScroll,!1),this.started=!1):void 0},r.prototype.scrollToElement=function(t){return t.scrollIntoView()},r.prototype.scrollToPosition=function(t){var e,r;return e=t.x,r=t.y,window.scrollTo(e,r)},r.prototype.onScroll=function(t){return this.updatePosition({x:window.pageXOffset,y:window.pageYOffset})},r.prototype.updatePosition=function(t){var e;return this.position=t,null!=(e=this.delegate)?e.scrollPositionChanged(this.position):void 0},r}()}.call(this),function(){e.SnapshotCache=function(){function t(t){this.size=t,this.keys=[],this.snapshots={}}var r;return t.prototype.has=function(t){var e;return e=r(t),e in this.snapshots},t.prototype.get=function(t){var e;if(this.has(t))return e=this.read(t),this.touch(t),e},t.prototype.put=function(t,e){return this.write(t,e),this.touch(t),e},t.prototype.read=function(t){var e;return e=r(t),this.snapshots[e]},t.prototype.write=function(t,e){var n;return n=r(t),this.snapshots[n]=e},t.prototype.touch=function(t){var e,n;return n=r(t),e=this.keys.indexOf(n),e>-1&&this.keys.splice(e,1),this.keys.unshift(n),this.trim()},t.prototype.trim=function(){var t,e,r,n,o;for(n=this.keys.splice(this.size),o=[],t=0,r=n.length;r>t;t++)e=n[t],o.push(delete this.snapshots[e]);return o},r=function(t){return e.Location.wrap(t).toCacheKey()},t}()}.call(this),function(){var t=function(t,e){return function(){return t.apply(e,arguments)}};e.Visit=function(){function r(r,n,o){this.controller=r,this.action=o,this.performScroll=t(this.performScroll,this),this.identifier=e.uuid(),this.location=e.Location.wrap(n),this.adapter=this.controller.adapter,this.state="initialized",this.timingMetrics={}}var n;return r.prototype.start=function(){return"initialized"===this.state?(this.recordTimingMetric("visitStart"),this.state="started",this.adapter.visitStarted(this)):void 0},r.prototype.cancel=function(){var t;return"started"===this.state?(null!=(t=this.request)&&t.cancel(),this.cancelRender(),this.state="canceled"):void 0},r.prototype.complete=function(){var t;return"started"===this.state?(this.recordTimingMetric("visitEnd"),this.state="completed","function"==typeof(t=this.adapter).visitCompleted&&t.visitCompleted(this),this.controller.visitCompleted(this)):void 0},r.prototype.fail=function(){var t;return"started"===this.state?(this.state="failed","function"==typeof(t=this.adapter).visitFailed?t.visitFailed(this):void 0):void 0},r.prototype.changeHistory=function(){var t,e;return this.historyChanged?void 0:(t=this.location.isEqualTo(this.referrer)?"replace":this.action,e=n(t),this.controller[e](this.location,this.restorationIdentifier),this.historyChanged=!0)},r.prototype.issueRequest=function(){return this.shouldIssueRequest()&&null==this.request?(this.progress=0,this.request=new e.HttpRequest(this,this.location,this.referrer),this.request.send()):void 0},r.prototype.getCachedSnapshot=function(){var t;return!(t=this.controller.getCachedSnapshotForLocation(this.location))||null!=this.location.anchor&&!t.hasAnchor(this.location.anchor)||"restore"!==this.action&&!t.isPreviewable()?void 0:t},r.prototype.hasCachedSnapshot=function(){return null!=this.getCachedSnapshot()},r.prototype.loadCachedSnapshot=function(){var t,e;return(e=this.getCachedSnapshot())?(t=this.shouldIssueRequest(),this.render(function(){var r;return this.cacheSnapshot(),this.controller.render({snapshot:e,isPreview:t},this.performScroll),"function"==typeof(r=this.adapter).visitRendered&&r.visitRendered(this),t?void 0:this.complete()})):void 0},r.prototype.loadResponse=function(){return null!=this.response?this.render(function(){var t,e;return this.cacheSnapshot(),this.request.failed?(this.controller.render({error:this.response},this.performScroll),"function"==typeof(t=this.adapter).visitRendered&&t.visitRendered(this),this.fail()):(this.controller.render({snapshot:this.response},this.performScroll),"function"==typeof(e=this.adapter).visitRendered&&e.visitRendered(this),this.complete())}):void 0},r.prototype.followRedirect=function(){return this.redirectedToLocation&&!this.followedRedirect?(this.location=this.redirectedToLocation,this.controller.replaceHistoryWithLocationAndRestorationIdentifier(this.redirectedToLocation,this.restorationIdentifier),this.followedRedirect=!0):void 0},r.prototype.requestStarted=function(){var t;return this.recordTimingMetric("requestStart"),"function"==typeof(t=this.adapter).visitRequestStarted?t.visitRequestStarted(this):void 0},r.prototype.requestProgressed=function(t){var e;return this.progress=t,"function"==typeof(e=this.adapter).visitRequestProgressed?e.visitRequestProgressed(this):void 0},r.prototype.requestCompletedWithResponse=function(t,r){return this.response=t,null!=r&&(this.redirectedToLocation=e.Location.wrap(r)),this.adapter.visitRequestCompleted(this)},r.prototype.requestFailedWithStatusCode=function(t,e){return this.response=e,this.adapter.visitRequestFailedWithStatusCode(this,t)},r.prototype.requestFinished=function(){var t;return this.recordTimingMetric("requestEnd"),"function"==typeof(t=this.adapter).visitRequestFinished?t.visitRequestFinished(this):void 0},r.prototype.performScroll=function(){return this.scrolled?void 0:("restore"===this.action?this.scrollToRestoredPosition()||this.scrollToTop():this.scrollToAnchor()||this.scrollToTop(),this.scrolled=!0)},r.prototype.scrollToRestoredPosition=function(){var t,e;return t=null!=(e=this.restorationData)?e.scrollPosition:void 0,null!=t?(this.controller.scrollToPosition(t),!0):void 0},r.prototype.scrollToAnchor=function(){return null!=this.location.anchor?(this.controller.scrollToAnchor(this.location.anchor),!0):void 0},r.prototype.scrollToTop=function(){return this.controller.scrollToPosition({x:0,y:0})},r.prototype.recordTimingMetric=function(t){var e;return null!=(e=this.timingMetrics)[t]?e[t]:e[t]=(new Date).getTime()},r.prototype.getTimingMetrics=function(){return e.copyObject(this.timingMetrics)},n=function(t){switch(t){case"replace":return"replaceHistoryWithLocationAndRestorationIdentifier";case"advance":case"restore":return"pushHistoryWithLocationAndRestorationIdentifier"}},r.prototype.shouldIssueRequest=function(){return"restore"===this.action?!this.hasCachedSnapshot():!0},r.prototype.cacheSnapshot=function(){return this.snapshotCached?void 0:(this.controller.cacheSnapshot(),this.snapshotCached=!0)},r.prototype.render=function(t){return this.cancelRender(),this.frame=requestAnimationFrame(function(e){return function(){return e.frame=null,t.call(e)}}(this))},r.prototype.cancelRender=function(){return this.frame?cancelAnimationFrame(this.frame):void 0},r}()}.call(this),function(){var t=function(t,e){return function(){return t.apply(e,arguments)}};e.Controller=function(){function r(){this.clickBubbled=t(this.clickBubbled,this),this.clickCaptured=t(this.clickCaptured,this),this.pageLoaded=t(this.pageLoaded,this),this.history=new e.History(this),this.view=new e.View(this),this.scrollManager=new e.ScrollManager(this),this.restorationData={},this.clearCache(),this.setProgressBarDelay(500)}return r.prototype.start=function(){return e.supported&&!this.started?(addEventListener("click",this.clickCaptured,!0),addEventListener("DOMContentLoaded",this.pageLoaded,!1),this.scrollManager.start(),this.startHistory(),this.started=!0,this.enabled=!0):void 0},r.prototype.disable=function(){return this.enabled=!1},r.prototype.stop=function(){return this.started?(removeEventListener("click",this.clickCaptured,!0),removeEventListener("DOMContentLoaded",this.pageLoaded,!1),this.scrollManager.stop(),this.stopHistory(),this.started=!1):void 0},r.prototype.clearCache=function(){return this.cache=new e.SnapshotCache(10)},r.prototype.visit=function(t,r){var n,o;return null==r&&(r={}),t=e.Location.wrap(t),this.applicationAllowsVisitingLocation(t)?this.locationIsVisitable(t)?(n=null!=(o=r.action)?o:"advance",this.adapter.visitProposedToLocationWithAction(t,n)):window.location=t:void 0},r.prototype.startVisitToLocationWithAction=function(t,r,n){var o;return e.supported?(o=this.getRestorationDataForIdentifier(n),this.startVisit(t,r,{restorationData:o})):window.location=t},r.prototype.setProgressBarDelay=function(t){return this.progressBarDelay=t},r.prototype.startHistory=function(){return this.location=e.Location.wrap(window.location),this.restorationIdentifier=e.uuid(),this.history.start(),this.history.replace(this.location,this.restorationIdentifier)},r.prototype.stopHistory=function(){return this.history.stop()},r.prototype.pushHistoryWithLocationAndRestorationIdentifier=function(t,r){return this.restorationIdentifier=r,this.location=e.Location.wrap(t),this.history.push(this.location,this.restorationIdentifier)},r.prototype.replaceHistoryWithLocationAndRestorationIdentifier=function(t,r){return this.restorationIdentifier=r,this.location=e.Location.wrap(t),this.history.replace(this.location,this.restorationIdentifier)},r.prototype.historyPoppedToLocationWithRestorationIdentifier=function(t,r){var n;return this.restorationIdentifier=r,this.enabled?(n=this.getRestorationDataForIdentifier(this.restorationIdentifier),this.startVisit(t,"restore",{restorationIdentifier:this.restorationIdentifier,restorationData:n,historyChanged:!0}),this.location=e.Location.wrap(t)):this.adapter.pageInvalidated()},r.prototype.getCachedSnapshotForLocation=function(t){var e;return null!=(e=this.cache.get(t))?e.clone():void 0},r.prototype.shouldCacheSnapshot=function(){return this.view.getSnapshot().isCacheable();
+},r.prototype.cacheSnapshot=function(){var t,r;return this.shouldCacheSnapshot()?(this.notifyApplicationBeforeCachingSnapshot(),r=this.view.getSnapshot(),t=this.lastRenderedLocation,e.defer(function(e){return function(){return e.cache.put(t,r.clone())}}(this))):void 0},r.prototype.scrollToAnchor=function(t){var e;return(e=this.view.getElementForAnchor(t))?this.scrollToElement(e):this.scrollToPosition({x:0,y:0})},r.prototype.scrollToElement=function(t){return this.scrollManager.scrollToElement(t)},r.prototype.scrollToPosition=function(t){return this.scrollManager.scrollToPosition(t)},r.prototype.scrollPositionChanged=function(t){var e;return e=this.getCurrentRestorationData(),e.scrollPosition=t},r.prototype.render=function(t,e){return this.view.render(t,e)},r.prototype.viewInvalidated=function(){return this.adapter.pageInvalidated()},r.prototype.viewWillRender=function(t){return this.notifyApplicationBeforeRender(t)},r.prototype.viewRendered=function(){return this.lastRenderedLocation=this.currentVisit.location,this.notifyApplicationAfterRender()},r.prototype.pageLoaded=function(){return this.lastRenderedLocation=this.location,this.notifyApplicationAfterPageLoad()},r.prototype.clickCaptured=function(){return removeEventListener("click",this.clickBubbled,!1),addEventListener("click",this.clickBubbled,!1)},r.prototype.clickBubbled=function(t){var e,r,n;return this.enabled&&this.clickEventIsSignificant(t)&&(r=this.getVisitableLinkForNode(t.target))&&(n=this.getVisitableLocationForLink(r))&&this.applicationAllowsFollowingLinkToLocation(r,n)?(t.preventDefault(),e=this.getActionForLink(r),this.visit(n,{action:e})):void 0},r.prototype.applicationAllowsFollowingLinkToLocation=function(t,e){var r;return r=this.notifyApplicationAfterClickingLinkToLocation(t,e),!r.defaultPrevented},r.prototype.applicationAllowsVisitingLocation=function(t){var e;return e=this.notifyApplicationBeforeVisitingLocation(t),!e.defaultPrevented},r.prototype.notifyApplicationAfterClickingLinkToLocation=function(t,r){return e.dispatch("turbolinks:click",{target:t,data:{url:r.absoluteURL},cancelable:!0})},r.prototype.notifyApplicationBeforeVisitingLocation=function(t){return e.dispatch("turbolinks:before-visit",{data:{url:t.absoluteURL},cancelable:!0})},r.prototype.notifyApplicationAfterVisitingLocation=function(t){return e.dispatch("turbolinks:visit",{data:{url:t.absoluteURL}})},r.prototype.notifyApplicationBeforeCachingSnapshot=function(){return e.dispatch("turbolinks:before-cache")},r.prototype.notifyApplicationBeforeRender=function(t){return e.dispatch("turbolinks:before-render",{data:{newBody:t}})},r.prototype.notifyApplicationAfterRender=function(){return e.dispatch("turbolinks:render")},r.prototype.notifyApplicationAfterPageLoad=function(t){return null==t&&(t={}),e.dispatch("turbolinks:load",{data:{url:this.location.absoluteURL,timing:t}})},r.prototype.startVisit=function(t,e,r){var n;return null!=(n=this.currentVisit)&&n.cancel(),this.currentVisit=this.createVisit(t,e,r),this.currentVisit.start(),this.notifyApplicationAfterVisitingLocation(t)},r.prototype.createVisit=function(t,r,n){var o,i,s,a,u;return i=null!=n?n:{},a=i.restorationIdentifier,s=i.restorationData,o=i.historyChanged,u=new e.Visit(this,t,r),u.restorationIdentifier=null!=a?a:e.uuid(),u.restorationData=e.copyObject(s),u.historyChanged=o,u.referrer=this.location,u},r.prototype.visitCompleted=function(t){return this.notifyApplicationAfterPageLoad(t.getTimingMetrics())},r.prototype.clickEventIsSignificant=function(t){return!(t.defaultPrevented||t.target.isContentEditable||t.which>1||t.altKey||t.ctrlKey||t.metaKey||t.shiftKey)},r.prototype.getVisitableLinkForNode=function(t){return this.nodeIsVisitable(t)?e.closest(t,"a[href]:not([target]):not([download])"):void 0},r.prototype.getVisitableLocationForLink=function(t){var r;return r=new e.Location(t.getAttribute("href")),this.locationIsVisitable(r)?r:void 0},r.prototype.getActionForLink=function(t){var e;return null!=(e=t.getAttribute("data-turbolinks-action"))?e:"advance"},r.prototype.nodeIsVisitable=function(t){var r;return(r=e.closest(t,"[data-turbolinks]"))?"false"!==r.getAttribute("data-turbolinks"):!0},r.prototype.locationIsVisitable=function(t){return t.isPrefixedBy(this.view.getRootLocation())&&t.isHTML()},r.prototype.getCurrentRestorationData=function(){return this.getRestorationDataForIdentifier(this.restorationIdentifier)},r.prototype.getRestorationDataForIdentifier=function(t){var e;return null!=(e=this.restorationData)[t]?e[t]:e[t]={}},r}()}.call(this),function(){!function(){var t,e;if((t=e=document.currentScript)&&!e.hasAttribute("data-turbolinks-suppress-warning"))for(;t=t.parentNode;)if(t===document.body)return console.warn("You are loading Turbolinks from a
-
+
diff --git a/requirements.txt b/requirements.txt
index 0071bc83..f4ece220 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -4,14 +4,14 @@ django-bootstrap-datepicker-plus~=3.0.5
django-cas-server~=1.2.0
django-colorfield~=0.3.2
django-crispy-forms~=1.7.2
-django-extensions~=2.1.4
-django-filter~=2.1.0
+django-extensions>=2.1.4
+django-filter~=2.1
django-htcpcp-tea~=0.3.1
django-mailer~=2.0.1
django-oauth-toolkit~=1.3.3
django-phonenumber-field~=5.0.0
-django-polymorphic~=2.0.3
-djangorestframework~=3.9.0
+django-polymorphic>=2.0.3,<3.0.0
+djangorestframework>=3.9.0,<3.13.0
django-rest-polymorphic~=0.1.9
django-tables2~=2.3.1
python-memcached~=1.59