diff --git a/Dockerfile b/Dockerfile
old mode 100644
new mode 100755
index 14b3c68..4884e33
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.8-slim
+FROM python:3.9-slim
RUN groupadd -r mapper && useradd --no-log-init -r -g mapper mapper
diff --git a/activities/migrations/0007_alter_activity_id_alter_activitymedium_id_and_more.py b/activities/migrations/0007_alter_activity_id_alter_activitymedium_id_and_more.py
new file mode 100755
index 0000000..d4d7663
--- /dev/null
+++ b/activities/migrations/0007_alter_activity_id_alter_activitymedium_id_and_more.py
@@ -0,0 +1,33 @@
+# Generated by Django 4.1.4 on 2023-01-05 16:57
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('activities', '0006_activity_attendance_optional'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='activity',
+ name='id',
+ field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+ ),
+ migrations.AlterField(
+ model_name='activitymedium',
+ name='id',
+ field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+ ),
+ migrations.AlterField(
+ model_name='activityseries',
+ name='id',
+ field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+ ),
+ migrations.AlterField(
+ model_name='activitytype',
+ name='id',
+ field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+ ),
+ ]
diff --git a/breccia_mapper/settings.py b/breccia_mapper/settings.py
index 6627eac..8bab638 100644
--- a/breccia_mapper/settings.py
+++ b/breccia_mapper/settings.py
@@ -165,7 +165,6 @@ THIRD_PARTY_APPS = [
'post_office',
'bootstrap_datepicker_plus',
'hijack',
- 'compat',
]
FIRST_PARTY_APPS = [
@@ -184,6 +183,7 @@ MIDDLEWARE = [
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
+ 'hijack.middleware.HijackUserMiddleware',
]
ROOT_URLCONF = 'breccia_mapper.urls'
@@ -417,6 +417,18 @@ else:
default=(EMAIL_PORT == 465),
cast=bool)
+# Bootstrap Datepicker Plus Settings
+BOOTSTRAP_DATEPICKER_PLUS = {
+ "variant_options": {
+ "date": {
+ "format": "%Y-%m-%d",
+ },
+ }
+}
+
+# Database default automatic primary key
+DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
+
# Upstream API keys
GOOGLE_MAPS_API_KEY = config('GOOGLE_MAPS_API_KEY', default=None)
diff --git a/breccia_mapper/templates/base.html b/breccia_mapper/templates/base.html
old mode 100644
new mode 100755
index ef622cb..be095e9
--- a/breccia_mapper/templates/base.html
+++ b/breccia_mapper/templates/base.html
@@ -16,21 +16,23 @@
{% bootstrap_css %}
+ href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/fontawesome.min.css"
+ integrity="sha512-giQeaPns4lQTBMRpOOHsYnGw1tGVzbAIHUyHRgn7+6FmiEgGGjaG0T2LZJmAPMzRCl+Cug0ItQ2xDZpTmEc+CQ=="
+ crossorigin="anonymous"
+ referrerpolicy="no-referrer" />
+ href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/solid.min.css"
+ integrity="sha512-6mc0R607di/biCutMUtU9K7NtNewiGQzrvWX4bWTeqmljZdJrwYvKJtnhgR+Ryvj+NRJ8+NnnCM/biGqMe/iRA=="
+ crossorigin="anonymous"
+ referrerpolicy="no-referrer" />
- {% load staticfiles %}
+ {% load static %}
+ href="{% static 'hijack/hijack.min.css' %}" />
{% if 'javascript_in_head'|bootstrap_setting %}
{% if 'include_jquery'|bootstrap_setting %}
@@ -107,13 +109,13 @@
{% if request.user.person %}
-
+
{{ request.user }}
{% else %}
-
+
{{ request.user }}
@@ -122,7 +124,7 @@
-
+
Log Out
@@ -130,7 +132,7 @@
{% else %}
-
+
Log In
@@ -149,8 +151,30 @@
{% endif %}
- {% load hijack_tags %}
- {% hijack_notification %}
+ {% load hijack %}
+
+ {# Hijack notification if user is hijacked #}
+ {% if person.user == request.user and request.user.is_hijacked %}
+
+
+
+ {% blocktrans trimmed with user=request.user %}
+ You are currently working on behalf of {{ user }}.
+ {% endblocktrans %}
+
+
+
+
+ {% endif %}
{% if request.user.is_authenticated and not request.user.has_person %}
diff --git a/breccia_mapper/templates/index.html b/breccia_mapper/templates/index.html
index 2044dde..fd475de 100644
--- a/breccia_mapper/templates/index.html
+++ b/breccia_mapper/templates/index.html
@@ -1,7 +1,7 @@
{% extends 'base.html' %}
{% block extra_head %}
- {% load staticfiles %}
+ {% load static %}
{% endblock %}
@@ -33,7 +33,7 @@
Do Feature 1
-
+
@@ -43,7 +43,7 @@
Do Feature 2
-
+
@@ -53,7 +53,7 @@
Do Feature 3
-
+
diff --git a/people/forms.py b/people/forms.py
old mode 100644
new mode 100755
index 925ea56..18eb007
--- a/people/forms.py
+++ b/people/forms.py
@@ -5,7 +5,7 @@ import typing
from django import forms
from django.conf import settings
-from bootstrap_datepicker_plus import DatePickerInput
+from bootstrap_datepicker_plus.widgets import DatePickerInput
from django_select2.forms import ModelSelect2Widget, Select2Widget, Select2MultipleWidget
from . import models
@@ -185,8 +185,8 @@ class PersonAnswerSetForm(forms.ModelForm, DynamicAnswerSetBase):
widgets = {
'nationality': Select2MultipleWidget(),
'country_of_residence': Select2Widget(),
- 'organisation_started_date': DatePickerInput(format='%Y-%m-%d'),
- 'project_started_date': DatePickerInput(format='%Y-%m-%d'),
+ 'organisation_started_date': DatePickerInput(),
+ 'project_started_date': DatePickerInput(),
'latitude': forms.HiddenInput,
'longitude': forms.HiddenInput,
}
@@ -325,7 +325,7 @@ class OrganisationRelationshipAnswerSetForm(forms.ModelForm,
class DateForm(forms.Form):
date = forms.DateField(
required=False,
- widget=DatePickerInput(format='%Y-%m-%d'),
+ widget=DatePickerInput(),
help_text='Show relationships as they were on this date'
)
diff --git a/people/migrations/0002_add_relationship_models.py b/people/migrations/0002_add_relationship_models.py
old mode 100644
new mode 100755
index cc6c888..d448c52
--- a/people/migrations/0002_add_relationship_models.py
+++ b/people/migrations/0002_add_relationship_models.py
@@ -50,10 +50,10 @@ class Migration(migrations.Migration):
),
migrations.AddConstraint(
model_name='relationshipquestionchoice',
- constraint=models.UniqueConstraint(fields=('question', 'text'), name='unique_question_answer'),
+ constraint=models.UniqueConstraint(fields=('question', 'text'), name='unique_question_answer_relationshipquestionchoice'),
),
migrations.AddConstraint(
model_name='relationship',
- constraint=models.UniqueConstraint(fields=('source', 'target'), name='unique_relationship'),
+ constraint=models.UniqueConstraint(fields=('source', 'target'), name='unique_relationship_relationship'),
),
]
diff --git a/people/migrations/0022_refactor_person_questions.py b/people/migrations/0022_refactor_person_questions.py
old mode 100644
new mode 100755
index 2da386b..d2869d8
--- a/people/migrations/0022_refactor_person_questions.py
+++ b/people/migrations/0022_refactor_person_questions.py
@@ -50,6 +50,6 @@ class Migration(migrations.Migration):
),
migrations.AddConstraint(
model_name='personquestionchoice',
- constraint=models.UniqueConstraint(fields=('question', 'text'), name='unique_question_answer'),
+ constraint=models.UniqueConstraint(fields=('question', 'text'), name='unique_question_answer_personquestionchoice'),
),
]
diff --git a/people/migrations/0035_add_organisation_questions.py b/people/migrations/0035_add_organisation_questions.py
old mode 100644
new mode 100755
index 19fccaf..d3f0702
--- a/people/migrations/0035_add_organisation_questions.py
+++ b/people/migrations/0035_add_organisation_questions.py
@@ -56,6 +56,6 @@ class Migration(migrations.Migration):
),
migrations.AddConstraint(
model_name='organisationquestionchoice',
- constraint=models.UniqueConstraint(fields=('question', 'text'), name='unique_question_answer'),
+ constraint=models.UniqueConstraint(fields=('question', 'text'), name='unique_question_answer_organisationquestionchoice'),
),
]
diff --git a/people/migrations/0039_add_organisation_relationship.py b/people/migrations/0039_add_organisation_relationship.py
old mode 100644
new mode 100755
index 461d897..dfcd46c
--- a/people/migrations/0039_add_organisation_relationship.py
+++ b/people/migrations/0039_add_organisation_relationship.py
@@ -67,10 +67,10 @@ class Migration(migrations.Migration):
),
migrations.AddConstraint(
model_name='organisationrelationshipquestionchoice',
- constraint=models.UniqueConstraint(fields=('question', 'text'), name='unique_question_answer'),
+ constraint=models.UniqueConstraint(fields=('question', 'text'), name='unique_question_answer_organisationrelationshipquestionchoice'),
),
migrations.AddConstraint(
model_name='organisationrelationship',
- constraint=models.UniqueConstraint(fields=('source', 'target'), name='unique_relationship'),
+ constraint=models.UniqueConstraint(fields=('source', 'target'), name='unique_relationship_organisationrelationship'),
),
]
diff --git a/people/migrations/0055_remove_organisationrelationship_unique_relationship_organisationrelationship_and_more.py b/people/migrations/0055_remove_organisationrelationship_unique_relationship_organisationrelationship_and_more.py
new file mode 100755
index 0000000..ccdcce5
--- /dev/null
+++ b/people/migrations/0055_remove_organisationrelationship_unique_relationship_organisationrelationship_and_more.py
@@ -0,0 +1,119 @@
+# Generated by Django 4.1.4 on 2023-01-05 16:57
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('people', '0054_add_option_for_auto_negative_response'),
+ ]
+
+ operations = [
+ migrations.RemoveConstraint(
+ model_name='organisationrelationship',
+ name='unique_relationship_organisationrelationship',
+ ),
+ migrations.RemoveConstraint(
+ model_name='relationship',
+ name='unique_relationship_relationship',
+ ),
+ migrations.AlterField(
+ model_name='organisation',
+ name='id',
+ field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+ ),
+ migrations.AlterField(
+ model_name='organisationanswerset',
+ name='id',
+ field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+ ),
+ migrations.AlterField(
+ model_name='organisationquestion',
+ name='id',
+ field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+ ),
+ migrations.AlterField(
+ model_name='organisationquestionchoice',
+ name='id',
+ field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+ ),
+ migrations.AlterField(
+ model_name='organisationrelationship',
+ name='id',
+ field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+ ),
+ migrations.AlterField(
+ model_name='organisationrelationshipanswerset',
+ name='id',
+ field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+ ),
+ migrations.AlterField(
+ model_name='organisationrelationshipquestion',
+ name='id',
+ field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+ ),
+ migrations.AlterField(
+ model_name='organisationrelationshipquestionchoice',
+ name='id',
+ field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+ ),
+ migrations.AlterField(
+ model_name='person',
+ name='id',
+ field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+ ),
+ migrations.AlterField(
+ model_name='personanswerset',
+ name='id',
+ field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+ ),
+ migrations.AlterField(
+ model_name='personquestion',
+ name='id',
+ field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+ ),
+ migrations.AlterField(
+ model_name='personquestionchoice',
+ name='id',
+ field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+ ),
+ migrations.AlterField(
+ model_name='relationship',
+ name='id',
+ field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+ ),
+ migrations.AlterField(
+ model_name='relationshipanswerset',
+ name='id',
+ field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+ ),
+ migrations.AlterField(
+ model_name='relationshipquestion',
+ name='id',
+ field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+ ),
+ migrations.AlterField(
+ model_name='relationshipquestionchoice',
+ name='id',
+ field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+ ),
+ migrations.AlterField(
+ model_name='user',
+ name='first_name',
+ field=models.CharField(blank=True, max_length=150, verbose_name='first name'),
+ ),
+ migrations.AlterField(
+ model_name='user',
+ name='id',
+ field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+ ),
+ migrations.AddConstraint(
+ model_name='organisationrelationship',
+ constraint=models.UniqueConstraint(fields=('source', 'target'), name='unique_relationship_modelorganisationrelationship'),
+ ),
+ migrations.AddConstraint(
+ model_name='relationship',
+ constraint=models.UniqueConstraint(fields=('source', 'target'), name='unique_relationship_modelrelationship'),
+ ),
+ ]
diff --git a/people/models/organisation.py b/people/models/organisation.py
old mode 100644
new mode 100755
index 3156d7f..347999a
--- a/people/models/organisation.py
+++ b/people/models/organisation.py
@@ -35,6 +35,11 @@ class OrganisationQuestionChoice(QuestionChoice):
on_delete=models.CASCADE,
blank=False,
null=False)
+ class Meta(QuestionChoice.Meta):
+ constraints = [
+ models.UniqueConstraint(fields=['question', 'text'],
+ name='unique_question_answer_organisationquestionchoice')
+ ]
class Organisation(models.Model):
diff --git a/people/models/person.py b/people/models/person.py
old mode 100644
new mode 100755
index 618bbfb..4d572af
--- a/people/models/person.py
+++ b/people/models/person.py
@@ -77,6 +77,11 @@ class PersonQuestionChoice(QuestionChoice):
on_delete=models.CASCADE,
blank=False,
null=False)
+ class Meta(QuestionChoice.Meta):
+ constraints = [
+ models.UniqueConstraint(fields=['question', 'text'],
+ name='unique_question_answer_personquestionchoice')
+ ]
class Person(models.Model):
diff --git a/people/models/question.py b/people/models/question.py
old mode 100644
new mode 100755
index 5d455e1..93b8161
--- a/people/models/question.py
+++ b/people/models/question.py
@@ -92,7 +92,7 @@ class QuestionChoice(models.Model):
abstract = True
constraints = [
models.UniqueConstraint(fields=['question', 'text'],
- name='unique_question_answer')
+ name='unique_question_answer_modelquestionchoice')
]
ordering = [
'question__order',
diff --git a/people/models/relationship.py b/people/models/relationship.py
old mode 100644
new mode 100755
index 3fd703d..ecd2c98
--- a/people/models/relationship.py
+++ b/people/models/relationship.py
@@ -33,6 +33,11 @@ class RelationshipQuestionChoice(QuestionChoice):
on_delete=models.CASCADE,
blank=False,
null=False)
+ class Meta(QuestionChoice.Meta):
+ constraints = [
+ models.UniqueConstraint(fields=['question', 'text'],
+ name='unique_question_answer_relationshipquestionchoice')
+ ]
class Relationship(models.Model):
@@ -40,7 +45,7 @@ class Relationship(models.Model):
class Meta:
constraints = [
models.UniqueConstraint(fields=['source', 'target'],
- name='unique_relationship'),
+ name='unique_relationship_modelrelationship'),
]
#: Person reporting the relationship
@@ -122,6 +127,11 @@ class OrganisationRelationshipQuestionChoice(QuestionChoice):
on_delete=models.CASCADE,
blank=False,
null=False)
+ class Meta(QuestionChoice.Meta):
+ constraints = [
+ models.UniqueConstraint(fields=['question', 'text'],
+ name='unique_question_answer_organisationrelationshipquestionchoice')
+ ]
class OrganisationRelationship(models.Model):
@@ -129,7 +139,7 @@ class OrganisationRelationship(models.Model):
class Meta:
constraints = [
models.UniqueConstraint(fields=['source', 'target'],
- name='unique_relationship'),
+ name='unique_relationship_modelorganisationrelationship'),
]
#: Person reporting the relationship
diff --git a/people/templates/people/map.html b/people/templates/people/map.html
old mode 100644
new mode 100755
index 688d32e..8560ee0
--- a/people/templates/people/map.html
+++ b/people/templates/people/map.html
@@ -3,7 +3,7 @@
{% block extra_head %}
{{ map_markers|json_script:'map-markers' }}
- {% load staticfiles %}
+ {% load static %}
- {% load staticfiles %}
+ {% load static %}
{% endblock %}
\ No newline at end of file
diff --git a/people/templates/people/organisation/detail.html b/people/templates/people/organisation/detail.html
old mode 100644
new mode 100755
index 1bb6dd0..6b75af2
--- a/people/templates/people/organisation/detail.html
+++ b/people/templates/people/organisation/detail.html
@@ -3,7 +3,7 @@
{% block extra_head %}
{{ map_markers|json_script:'map-markers' }}
- {% load staticfiles %}
+ {% load static %}
diff --git a/people/templates/people/person/detail_full.html b/people/templates/people/person/detail_full.html
old mode 100644
new mode 100755
index d550fa1..c3b3651
--- a/people/templates/people/person/detail_full.html
+++ b/people/templates/people/person/detail_full.html
@@ -3,7 +3,7 @@
{% block extra_head %}
{{ map_markers|json_script:'map-markers' }}
- {% load staticfiles %}
+ {% load static %}
diff --git a/people/templates/people/relationship/update.html b/people/templates/people/relationship/update.html
old mode 100644
new mode 100755
index 11022e5..680fecc
--- a/people/templates/people/relationship/update.html
+++ b/people/templates/people/relationship/update.html
@@ -23,6 +23,6 @@
{% endblock %}
{% block extra_script %}
- {% load staticfiles %}
+ {% load static %}
{% endblock %}
diff --git a/requirements.txt b/requirements.txt
old mode 100644
new mode 100755
index 4791a26..8497233
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,46 +1,45 @@
-astroid==2.3.3
-beautifulsoup4==4.8.2
-dj-database-url==0.5.0
-Django==2.2.10
-django-appconf==1.0.3
-django-bootstrap4==1.1.1
-django-bootstrap-datepicker-plus==3.0.5
-django-compat==1.0.15
-django-constance==2.6.0
-django-countries==5.5
-django-dbbackup==3.2.0
-django-filter==2.2.0
-django-hijack==2.2.1
-django-picklefield==2.1.1
-django-post-office==3.4.0
-django-select2==7.2.0
+astroid==2.12.13
+beautifulsoup4==4.11.1
+dj-database-url==1.2.0
+Django==4.1.4
+django-appconf==1.0.5
+django-bootstrap4==22.3
+django-bootstrap-datepicker-plus==5.0.2
+django-constance==2.9.1
+django-countries==7.5
+django-dbbackup==4.0.2
+django-filter==22.1
+django-hijack==3.2.6
+django-picklefield==3.1
+django-post-office==3.6.3
+django-select2==8.0.0
django-settings-export==1.2.1
-djangorestframework==3.11.0
+djangorestframework==3.14.0
dodgy==0.2.1
-isort==4.3.21
+isort==5.11.4
jsonfield==3.1.0
-lazy-object-proxy==1.4.3
-mccabe==0.6.1
+lazy-object-proxy==1.8.0
+mccabe==0.7.0
# mysqlclient==1.4.6
-pep8-naming==0.4.1
-prospector==1.2.0
-pycodestyle==2.4.0
-pydocstyle==5.0.2
-pyflakes==2.1.1
-pylint==2.4.4
+pep8-naming==0.10.0
+prospector==1.8.3
+pycodestyle==2.10.0
+pydocstyle==6.1.1
+pyflakes==2.5.0
+pylint==2.15.9
pylint-celery==0.3
-pylint-django==2.0.12
+pylint-django==2.5.3
pylint-flask==0.6
-pylint-plugin-utils==0.6
-python-decouple==3.3
-pytz==2019.3
+pylint-plugin-utils==0.7
+python-decouple==3.6
+pytz==2022.7
pyuca==1.2
-PyYAML==5.3
-requirements-detector==0.6
-setoptconf==0.2.0
-six==1.14.0
-snowballstemmer==2.0.0
-soupsieve==1.9.5
-sqlparse==0.3.0
+PyYAML==6.0
+requirements-detector==1.0.3
+setoptconf==0.3.0
+six==1.16.0
+snowballstemmer==2.2.0
+soupsieve==2.3.2.post1
+sqlparse==0.4.3
typed-ast
-wrapt==1.11.2
+wrapt==1.14.1