mirror of
https://github.com/Southampton-RSG/breccia-mapper.git
synced 2026-03-03 11:27:09 +00:00
Compare commits
50 Commits
v2.0.0-alp
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
| f83805af4f | |||
| 170db50a1c | |||
| 2ebe7777c3 | |||
| 2f9f35c396 | |||
| aecd0ff314 | |||
| e0e9a05747 | |||
| cce0543408 | |||
| a6e36b9854 | |||
| 995a4f6cb2 | |||
| d24756ca38 | |||
| f69b7aa1f0 | |||
| 74b6b3b27d | |||
| e51c2dc76b | |||
| b0fcda5901 | |||
| 253846f877 | |||
| 4b61b26661 | |||
| 66567e5a55 | |||
| b8059175c6 | |||
| a85a07ea82 | |||
| 21088a1412 | |||
| e37d5fcb61 | |||
| f6bfcceb6c | |||
| 79bb6cc415 | |||
| 99161b269e | |||
| 365c3f04c9 | |||
| 65023cf4f9 | |||
| 85bb6ae5ba | |||
| 6eeb74fdd7 | |||
| f015929a0c | |||
| c05ef1ed10 | |||
| f8593776c0 | |||
| 284132f4cc | |||
| 858933c6bb | |||
| 0a3c85bb42 | |||
| 266bdfe628 | |||
| d19554de24 | |||
| 4e4503e097 | |||
| d65ccc807f | |||
| b94c459e56 | |||
| b6a6be99da | |||
| 83765c99ad | |||
| 11a6f8d8f1 | |||
| bcb2b1bc20 | |||
| 843bdebabf | |||
| 86e18c399d | |||
| 05ca7433f1 | |||
| 3beeeab4ae | |||
| ccea25133c | |||
| ced86f308b | |||
| 6d1e5effda |
@@ -17,5 +17,5 @@ mail.log/
|
|||||||
*.log*
|
*.log*
|
||||||
deployment*
|
deployment*
|
||||||
|
|
||||||
docs/
|
/docs/
|
||||||
.readthedocs.yaml
|
.readthedocs.yaml
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# BRECcIA Mapper
|
# BRECcIA Mapper
|
||||||
|
|
||||||
[](https://breccia.readthedocs.io/en/latest/?badge=latest)
|
[](https://docs.gcrf-breccia.com/en/latest/?badge=latest)
|
||||||
|
|
||||||
BRECcIA Mapper is a web app to collect and explore data about the relationships between researchers and their stakeholders on large-scale, multi-site research projects.
|
BRECcIA Mapper is a web app to collect and explore data about the relationships between researchers and their stakeholders on large-scale, multi-site research projects.
|
||||||
This allows researchers to visually represent the relationships between project staff and stakeholders involved in the their project at different points in time.
|
This allows researchers to visually represent the relationships between project staff and stakeholders involved in the their project at different points in time.
|
||||||
@@ -11,7 +11,7 @@ This work was funded through the "Building REsearch Capacity for sustainable wat
|
|||||||
## Deployment
|
## Deployment
|
||||||
|
|
||||||
This project is written in Python using the popular [Django](https://www.djangoproject.com/) framework.
|
This project is written in Python using the popular [Django](https://www.djangoproject.com/) framework.
|
||||||
Deployment is managed using [Ansible](https://www.ansible.com/) and Docker (https://www.docker.com/), see the `deploy/README.md` for details.
|
Deployment relies on [Docker Compose](https://docs.docker.com/compose) but is possible with various methods. See [the documentation](https://docs.gcrf-breccia.com/en/latest/1-deployment.html) for details.
|
||||||
|
|
||||||
## Contributors
|
## Contributors
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ class ActivityAttendanceView(permissions.UserIsLinkedPersonMixin, SingleObjectMi
|
|||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
self.object = self.get_object()
|
self.object = self.get_object()
|
||||||
|
|
||||||
if request.is_ajax():
|
if request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest':
|
||||||
self.object.attendance_list.add(self.get_test_person())
|
self.object.attendance_list.add(self.get_test_person())
|
||||||
|
|
||||||
return HttpResponse(status=204)
|
return HttpResponse(status=204)
|
||||||
@@ -89,7 +89,7 @@ class ActivityAttendanceView(permissions.UserIsLinkedPersonMixin, SingleObjectMi
|
|||||||
def delete(self, request, *args, **kwargs):
|
def delete(self, request, *args, **kwargs):
|
||||||
self.object = self.get_object()
|
self.object = self.get_object()
|
||||||
|
|
||||||
if request.is_ajax():
|
if request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest':
|
||||||
self.object.attendance_list.remove(self.get_test_person())
|
self.object.attendance_list.remove(self.get_test_person())
|
||||||
|
|
||||||
return HttpResponse(status=204)
|
return HttpResponse(status=204)
|
||||||
|
|||||||
16
breccia_mapper/account_adapter.py
Normal file
16
breccia_mapper/account_adapter.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
from allauth.account.adapter import DefaultAccountAdapter
|
||||||
|
from constance import config
|
||||||
|
|
||||||
|
|
||||||
|
class ControlSignupsAccountAdapter(DefaultAccountAdapter):
|
||||||
|
|
||||||
|
def is_open_for_signup(self, request):
|
||||||
|
"""
|
||||||
|
Checks whether or not the site is open for signups.
|
||||||
|
|
||||||
|
Next to simply returning True/False you can also intervene the
|
||||||
|
regular flow by raising an ImmediateHttpResponse
|
||||||
|
|
||||||
|
(Comment reproduced from the overridden method.)
|
||||||
|
"""
|
||||||
|
return config.ALLOW_SIGNUPS
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"model": "bootstrap_customizer.sitebootstraptheme",
|
||||||
|
"pk": 1,
|
||||||
|
"fields": { "site": 1, "bootstrap_theme": 1, "updated": "2023-02-23T14:41:48.620Z" }
|
||||||
|
}
|
||||||
|
]
|
||||||
1
breccia_mapper/fixtures/bootstrap_customizer_theme.json
Normal file
1
breccia_mapper/fixtures/bootstrap_customizer_theme.json
Normal file
File diff suppressed because one or more lines are too long
0
breccia_mapper/management/__init__.py
Normal file
0
breccia_mapper/management/__init__.py
Normal file
0
breccia_mapper/management/commands/__init__.py
Normal file
0
breccia_mapper/management/commands/__init__.py
Normal file
44
breccia_mapper/management/commands/selectiveloaddata.py
Normal file
44
breccia_mapper/management/commands/selectiveloaddata.py
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.management.commands import loaddata
|
||||||
|
|
||||||
|
from bootstrap_customizer.models import BootstrapTheme
|
||||||
|
|
||||||
|
|
||||||
|
def should_add_record(record):
|
||||||
|
if record['model'] != 'bootstrap_customizer.bootstraptheme':
|
||||||
|
return True
|
||||||
|
|
||||||
|
return not BootstrapTheme.objects.filter(
|
||||||
|
pk=record['pk'],
|
||||||
|
).exists()
|
||||||
|
|
||||||
|
|
||||||
|
class Command(loaddata.Command):
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
args = list(args)
|
||||||
|
|
||||||
|
# Read the original JSON file
|
||||||
|
file_name = args[0]
|
||||||
|
with open(file_name) as json_file:
|
||||||
|
json_list = json.load(json_file)
|
||||||
|
|
||||||
|
# Filter out records that already exists
|
||||||
|
json_list_filtered = list(filter(should_add_record, json_list))
|
||||||
|
if not json_list_filtered:
|
||||||
|
print("All data are already previously loaded")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Write the updated JSON file
|
||||||
|
file_dir_and_name, file_ext = os.path.splitext(file_name)
|
||||||
|
file_name_temp = f"{file_dir_and_name}_temp{file_ext}"
|
||||||
|
with open(file_name_temp, 'w') as json_file_temp:
|
||||||
|
json.dump(json_list_filtered, json_file_temp)
|
||||||
|
|
||||||
|
# Pass the request to the actual loaddata (parent functionality)
|
||||||
|
args[0] = file_name_temp
|
||||||
|
super().handle(*args, **options)
|
||||||
|
|
||||||
|
# You can choose to not delete the file so that you can see what was added to your records
|
||||||
|
os.remove(file_name_temp)
|
||||||
@@ -185,6 +185,7 @@ DJANGO_APPS = [
|
|||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
|
'django.contrib.sites',
|
||||||
]
|
]
|
||||||
|
|
||||||
THIRD_PARTY_APPS = [
|
THIRD_PARTY_APPS = [
|
||||||
@@ -199,9 +200,17 @@ THIRD_PARTY_APPS = [
|
|||||||
'bootstrap_datepicker_plus',
|
'bootstrap_datepicker_plus',
|
||||||
'hijack',
|
'hijack',
|
||||||
'pwa',
|
'pwa',
|
||||||
|
'allauth',
|
||||||
|
'allauth.account',
|
||||||
|
'allauth.socialaccount',
|
||||||
|
'allauth.socialaccount.providers.google',
|
||||||
|
'allauth.socialaccount.providers.microsoft',
|
||||||
|
'django_inlinecss',
|
||||||
|
'bootstrap_customizer',
|
||||||
]
|
]
|
||||||
|
|
||||||
FIRST_PARTY_APPS = [
|
FIRST_PARTY_APPS = [
|
||||||
|
'breccia_mapper',
|
||||||
'people',
|
'people',
|
||||||
'activities',
|
'activities',
|
||||||
'export',
|
'export',
|
||||||
@@ -218,6 +227,12 @@ MIDDLEWARE = [
|
|||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
'hijack.middleware.HijackUserMiddleware',
|
'hijack.middleware.HijackUserMiddleware',
|
||||||
|
'django.contrib.sites.middleware.CurrentSiteMiddleware',
|
||||||
|
'bootstrap_customizer.middleware.BootstrapThemeMiddleware',
|
||||||
|
]
|
||||||
|
|
||||||
|
FIXTURE_DIRS = [
|
||||||
|
BASE_DIR.joinpath('breccia_mapper', 'fixtures'),
|
||||||
]
|
]
|
||||||
|
|
||||||
ROOT_URLCONF = 'breccia_mapper.urls'
|
ROOT_URLCONF = 'breccia_mapper.urls'
|
||||||
@@ -242,11 +257,45 @@ TEMPLATES = [
|
|||||||
|
|
||||||
WSGI_APPLICATION = 'breccia_mapper.wsgi.application'
|
WSGI_APPLICATION = 'breccia_mapper.wsgi.application'
|
||||||
|
|
||||||
|
# allauth
|
||||||
|
AUTHENTICATION_BACKENDS = [
|
||||||
|
# Needed to login by username in Django admin, regardless of `allauth`
|
||||||
|
'django.contrib.auth.backends.ModelBackend',
|
||||||
|
# `allauth` specific authentication methods, such as login by email
|
||||||
|
'allauth.account.auth_backends.AuthenticationBackend',
|
||||||
|
]
|
||||||
|
SITE_ID = 1
|
||||||
|
ACCOUNT_DEFAULT_HTTP_PROTOCOL = SITE_PROTOCOL
|
||||||
|
ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS = 1
|
||||||
|
ACCOUNT_EMAIL_REQUIRED = True
|
||||||
|
ACCOUNT_EMAIL_VERIFICATION = "mandatory"
|
||||||
|
ACCOUNT_LOGIN_ATTEMPTS_LIMIT = 5
|
||||||
|
# 1 day
|
||||||
|
ACCOUNT_LOGIN_ATTEMPTS_TIMEOUT = 86400
|
||||||
|
# or any other page
|
||||||
|
ACCOUNT_LOGOUT_REDIRECT_URL = '/'
|
||||||
|
ACCOUNT_ADAPTER = 'breccia_mapper.account_adapter.ControlSignupsAccountAdapter'
|
||||||
|
|
||||||
|
|
||||||
|
PROJECT_LONG_NAME = config('PROJECT_LONG_NAME', 'Project Network Mapper')
|
||||||
|
PROJECT_SHORT_NAME = config('PROJECT_SHORT_NAME', 'Network Mapper')
|
||||||
|
PROJECT_DESCRIPTION = config('PROJECT_DESCRIPTION', 'Application to map network relationships in the organisation.')
|
||||||
|
THEME_COLOR = '#' + config('THEME_COLOR', '212121')
|
||||||
|
BACKGROUND_COLOR = '#' + config('BACKGROUND_COLOR', 'ffffff')
|
||||||
|
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
|
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
|
||||||
|
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': dj_database_url.parse('sqlite:///' + str(BASE_DIR.joinpath('db.sqlite3')))
|
'default' : {
|
||||||
|
'ENGINE': 'django.db.backends.postgresql',
|
||||||
|
'NAME': 'breccia-mapper',
|
||||||
|
'USER': 'breccia-mapper',
|
||||||
|
'PASSWORD': config('DB_PASSWORD'),
|
||||||
|
'HOST': 'db',
|
||||||
|
'PORT': '5432',
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Django DBBackup
|
# Django DBBackup
|
||||||
@@ -302,7 +351,7 @@ AUTH_USER_MODEL = 'people.User'
|
|||||||
|
|
||||||
# Login flow
|
# Login flow
|
||||||
|
|
||||||
LOGIN_URL = reverse_lazy('login')
|
LOGIN_URL = reverse_lazy('account_login')
|
||||||
|
|
||||||
LOGIN_REDIRECT_URL = reverse_lazy('people:person.profile')
|
LOGIN_REDIRECT_URL = reverse_lazy('people:person.profile')
|
||||||
|
|
||||||
@@ -407,6 +456,15 @@ CONSTANCE_CONFIG = {
|
|||||||
'PROJECT_TAGLINE': (
|
'PROJECT_TAGLINE': (
|
||||||
'Here is your project\'s tagline.',
|
'Here is your project\'s tagline.',
|
||||||
'Project tagline'),
|
'Project tagline'),
|
||||||
|
'ALLOW_SIGNUPS': (
|
||||||
|
False,
|
||||||
|
'Allow new users to sign up using the site\'s sign up form'),
|
||||||
|
'ENABLE_GOOGLE_LOGIN': (
|
||||||
|
False,
|
||||||
|
'Allow users to sign in using their Google accounts'),
|
||||||
|
'ENABLE_MICROSOFT_LOGIN': (
|
||||||
|
False,
|
||||||
|
'Allow users to sign in using their Microsoft accounts'),
|
||||||
'HOMEPAGE_HEADER_IMAGE': (
|
'HOMEPAGE_HEADER_IMAGE': (
|
||||||
'800x500.png',
|
'800x500.png',
|
||||||
'Homepage header image',
|
'Homepage header image',
|
||||||
@@ -436,7 +494,7 @@ CONSTANCE_CONFIG = {
|
|||||||
'Step 3',
|
'Step 3',
|
||||||
'Homepage card #3 title'),
|
'Homepage card #3 title'),
|
||||||
'HOMEPAGE_CARD_3_DESCRIPTION': (
|
'HOMEPAGE_CARD_3_DESCRIPTION': (
|
||||||
'Use the network view to build new relationships',
|
'Use the network view to analyse relationships',
|
||||||
'Homepage card #3 description'),
|
'Homepage card #3 description'),
|
||||||
'HOMEPAGE_CARD_3_ICON': (
|
'HOMEPAGE_CARD_3_ICON': (
|
||||||
'diagram-project',
|
'diagram-project',
|
||||||
@@ -458,6 +516,9 @@ CONSTANCE_CONFIG_FIELDSETS = {
|
|||||||
'PARENT_PROJECT_NAME',
|
'PARENT_PROJECT_NAME',
|
||||||
'PROJECT_LEAD',
|
'PROJECT_LEAD',
|
||||||
'PROJECT_TAGLINE',
|
'PROJECT_TAGLINE',
|
||||||
|
'ALLOW_SIGNUPS',
|
||||||
|
'ENABLE_GOOGLE_LOGIN',
|
||||||
|
'ENABLE_MICROSOFT_LOGIN',
|
||||||
),
|
),
|
||||||
'Homepage configuration': (
|
'Homepage configuration': (
|
||||||
'HOMEPAGE_HEADER_IMAGE_SHRINK',
|
'HOMEPAGE_HEADER_IMAGE_SHRINK',
|
||||||
@@ -491,12 +552,6 @@ CONSTANCE_CONFIG_FIELDSETS = {
|
|||||||
|
|
||||||
CONSTANCE_BACKEND = 'constance.backends.database.DatabaseBackend'
|
CONSTANCE_BACKEND = 'constance.backends.database.DatabaseBackend'
|
||||||
|
|
||||||
PROJECT_LONG_NAME = config('PROJECT_LONG_NAME', 'Project Network Mapper')
|
|
||||||
PROJECT_SHORT_NAME = config('PROJECT_SHORT_NAME', 'Network Mapper')
|
|
||||||
PROJECT_DESCRIPTION = config('PROJECT_DESCRIPTION', 'Application to map network relationships in the organisation.')
|
|
||||||
THEME_COLOR = '#' + config('THEME_COLOR', '212121')
|
|
||||||
BACKGROUND_COLOR = '#' + config('BACKGROUND_COLOR', 'ffffff')
|
|
||||||
|
|
||||||
# Django Hijack settings
|
# Django Hijack settings
|
||||||
# See https://django-hijack.readthedocs.io/en/stable/
|
# See https://django-hijack.readthedocs.io/en/stable/
|
||||||
|
|
||||||
@@ -515,7 +570,7 @@ BOOTSTRAP4 = {
|
|||||||
EMAIL_HOST = config('EMAIL_HOST', default=None)
|
EMAIL_HOST = config('EMAIL_HOST', default=None)
|
||||||
DEFAULT_FROM_EMAIL = config(
|
DEFAULT_FROM_EMAIL = config(
|
||||||
'DEFAULT_FROM_EMAIL',
|
'DEFAULT_FROM_EMAIL',
|
||||||
default=f'{PROJECT_SHORT_NAME}@localhost.localdomain')
|
default=f'{PROJECT_SHORT_NAME.replace(" ","")}@localhost.localdomain')
|
||||||
SERVER_EMAIL = DEFAULT_FROM_EMAIL
|
SERVER_EMAIL = DEFAULT_FROM_EMAIL
|
||||||
|
|
||||||
if EMAIL_HOST is None:
|
if EMAIL_HOST is None:
|
||||||
|
|||||||
303
breccia_mapper/static/css/emails.css
Normal file
303
breccia_mapper/static/css/emails.css
Normal file
@@ -0,0 +1,303 @@
|
|||||||
|
/* -------------------------------------
|
||||||
|
GLOBAL
|
||||||
|
A very basic CSS reset
|
||||||
|
------------------------------------- */
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-webkit-text-size-adjust: none;
|
||||||
|
width: 100% !important;
|
||||||
|
height: 100%;
|
||||||
|
line-height: 1.6em;
|
||||||
|
/* 1.6em * 14px = 22.4px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
|
||||||
|
/*line-height: 22px;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Let's make sure all tables have defaults */
|
||||||
|
table td {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------
|
||||||
|
BODY & CONTAINER
|
||||||
|
------------------------------------- */
|
||||||
|
body {
|
||||||
|
background-color: #f6f6f6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.body-wrap {
|
||||||
|
background-color: #f6f6f6;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: block !important;
|
||||||
|
max-width: 600px !important;
|
||||||
|
margin: 0 auto !important;
|
||||||
|
/* makes it centered */
|
||||||
|
clear: both !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
display: block;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------
|
||||||
|
HEADER, FOOTER, MAIN
|
||||||
|
------------------------------------- */
|
||||||
|
.main {
|
||||||
|
background-color: #fff;
|
||||||
|
border: 1px solid #e9e9e9;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-wrap {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-block {
|
||||||
|
padding: 0 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
width: 100%;
|
||||||
|
clear: both;
|
||||||
|
color: #999;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer p,
|
||||||
|
.footer a,
|
||||||
|
.footer td {
|
||||||
|
color: #999;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------
|
||||||
|
TYPOGRAPHY
|
||||||
|
------------------------------------- */
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3 {
|
||||||
|
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
|
||||||
|
color: #000;
|
||||||
|
margin: 40px 0 0;
|
||||||
|
line-height: 1.2em;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 32px;
|
||||||
|
font-weight: 500;
|
||||||
|
/* 1.2em * 32px = 38.4px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
|
||||||
|
/*line-height: 38px;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 24px;
|
||||||
|
/* 1.2em * 24px = 28.8px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
|
||||||
|
/*line-height: 29px;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 18px;
|
||||||
|
/* 1.2em * 18px = 21.6px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
|
||||||
|
/*line-height: 22px;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
p,
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
p li,
|
||||||
|
ul li,
|
||||||
|
ol li {
|
||||||
|
margin-left: 5px;
|
||||||
|
list-style-position: inside;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------
|
||||||
|
LINKS & BUTTONS
|
||||||
|
------------------------------------- */
|
||||||
|
a {
|
||||||
|
color: #348eda;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #FFF;
|
||||||
|
background-color: #348eda;
|
||||||
|
border: solid #348eda;
|
||||||
|
border-width: 10px 20px;
|
||||||
|
line-height: 2em;
|
||||||
|
/* 2em * 14px = 28px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
|
||||||
|
/*line-height: 28px;*/
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-block;
|
||||||
|
border-radius: 5px;
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------
|
||||||
|
OTHER STYLES THAT MIGHT BE USEFUL
|
||||||
|
------------------------------------- */
|
||||||
|
.last {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.first {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aligncenter {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alignright {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alignleft {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clear {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------
|
||||||
|
ALERTS
|
||||||
|
Change the class depending on warning email, good email or bad email
|
||||||
|
------------------------------------- */
|
||||||
|
.alert {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #fff;
|
||||||
|
font-weight: 500;
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 3px 3px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert a {
|
||||||
|
color: #fff;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert.alert-warning {
|
||||||
|
background-color: #FF9F00;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert.alert-bad {
|
||||||
|
background-color: #D0021B;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert.alert-good {
|
||||||
|
background-color: #68B90F;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------
|
||||||
|
INVOICE
|
||||||
|
Styles for the billing table
|
||||||
|
------------------------------------- */
|
||||||
|
.invoice {
|
||||||
|
margin: 40px auto;
|
||||||
|
text-align: left;
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.invoice td {
|
||||||
|
padding: 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.invoice .invoice-items {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.invoice .invoice-items td {
|
||||||
|
border-top: #eee 1px solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.invoice .invoice-items .total td {
|
||||||
|
border-top: 2px solid #333;
|
||||||
|
border-bottom: 2px solid #333;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------
|
||||||
|
RESPONSIVE AND MOBILE FRIENDLY STYLES
|
||||||
|
------------------------------------- */
|
||||||
|
@media only screen and (max-width: 640px) {
|
||||||
|
body {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4 {
|
||||||
|
font-weight: 800 !important;
|
||||||
|
margin: 20px 0 5px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 22px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 18px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 16px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
padding: 0 !important;
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-wrap {
|
||||||
|
padding: 10px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.invoice {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*# sourceMappingURL=styles.css.map */
|
||||||
@@ -12,6 +12,20 @@ body {
|
|||||||
flex: 1 0 auto;
|
flex: 1 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
padding-top: 12px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.social_providers_list > form {
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.footer {
|
.footer {
|
||||||
height: 60px;
|
height: 60px;
|
||||||
|
|||||||
@@ -34,6 +34,11 @@ header.masthead .textbox-container {
|
|||||||
background-color: rgba(30, 30, 30, 0.2);
|
background-color: rgba(30, 30, 30, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
header.masthead > .row {
|
||||||
|
max-width: 1140px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
header.masthead {
|
header.masthead {
|
||||||
padding-top: 1rem;
|
padding-top: 1rem;
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
var staticCacheName = "django-pwa-v" + new Date().getTime();
|
var staticCacheName = "django-pwa-v" + new Date().getTime();
|
||||||
var filesToCache = [
|
var filesToCache = [
|
||||||
"/offline",
|
"/offline/",
|
||||||
"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/fontawesome.min.css",
|
"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/fontawesome.min.css",
|
||||||
"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/solid.min.css",
|
"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/solid.min.css",
|
||||||
"/static/css/global.css",
|
"/static/css/global.css",
|
||||||
|
"/static/js/serviceworker.js",
|
||||||
"/static/hijack/hijack.min.css",
|
"/static/hijack/hijack.min.css",
|
||||||
"/media/icon-192x192.png",
|
"/media/icon-192x192.png",
|
||||||
];
|
];
|
||||||
@@ -41,7 +42,7 @@ self.addEventListener("fetch", event => {
|
|||||||
return response || fetch(event.request);
|
return response || fetch(event.request);
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
return caches.match('offline');
|
return caches.match('/offline/');
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
7
breccia_mapper/templates/404.html
Normal file
7
breccia_mapper/templates/404.html
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h2>Error 404: Page not Found</h2>
|
||||||
|
|
||||||
|
<p>Sorry, we can't find that page. Click <a href="{% url 'index' %}">here</a> to go home.</p>
|
||||||
|
{% endblock content %}
|
||||||
0
breccia_mapper/templates/account/Profile.html
Executable file
0
breccia_mapper/templates/account/Profile.html
Executable file
11
breccia_mapper/templates/account/account_inactive.html
Executable file
11
breccia_mapper/templates/account/account_inactive.html
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
{% extends "account/base.html" %}
|
||||||
|
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block head_title %}{% trans "Account Inactive" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>{% trans "Account Inactive" %}</h1>
|
||||||
|
|
||||||
|
<p>{% trans "This account is inactive." %}</p>
|
||||||
|
{% endblock %}
|
||||||
1
breccia_mapper/templates/account/base.html
Executable file
1
breccia_mapper/templates/account/base.html
Executable file
@@ -0,0 +1 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
93
breccia_mapper/templates/account/email.html
Executable file
93
breccia_mapper/templates/account/email.html
Executable file
@@ -0,0 +1,93 @@
|
|||||||
|
{% extends "account/base.html" %}
|
||||||
|
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block head_title %}{% trans "Account Details" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h1 class="h1" id="head_banner">Account Details</h1>
|
||||||
|
|
||||||
|
<h2 class="h2" id="head_banner">{% trans "Email Addresses" %}</h2>
|
||||||
|
|
||||||
|
{% if user.emailaddress_set.all %}
|
||||||
|
|
||||||
|
<p class="email_settings_info">{% trans 'The following email addresses are associated with your account:' %}</p>
|
||||||
|
|
||||||
|
<form action="{% url 'account_email' %}" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
{% for emailaddress in user.emailaddress_set.all %}
|
||||||
|
<div class="ctrlHolder">
|
||||||
|
|
||||||
|
<label for="email_radio_{{forloop.counter}}" class="{% if emailaddress.primary %}primary_email{%endif%}">
|
||||||
|
|
||||||
|
{{ emailaddress.email }}
|
||||||
|
|
||||||
|
{% if emailaddress.primary %}
|
||||||
|
<span class="primary">(primary email)</span>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if not emailaddress.verified %}
|
||||||
|
<span class="unverified">(not verified)</span>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<input id="email_radio_{{forloop.counter}}" type="radio" name="email" {% if emailaddress.primary or user.emailaddress_set.count == 1 %}checked="checked"{%endif %} value="{{emailaddress.email}}"/>
|
||||||
|
|
||||||
|
</label>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button class="btn btn-primary" type="submit" name="action_primary" >{% trans 'Make Primary' %}</button>
|
||||||
|
<button class="btn btn-info" type="submit" name="action_send" >{% trans 'Re-send Verification' %}</button>
|
||||||
|
<button class="btn btn-danger" type="submit" name="action_remove" >{% trans 'Remove' %}</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
<p class="email_settings_info"><strong>{% trans 'Warning:'%}</strong> {% trans "You do not have any email addresses set up. Please add an email address to receive notifications, reset your password, and perform other account-related actions." %}</p>
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
<h3 class="h3" id="head_banner">{% trans "Add Email Address" %}</h3>
|
||||||
|
|
||||||
|
<form method="post" id="email_form" action="{% url 'account_email' %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% load bootstrap4 %}
|
||||||
|
{% bootstrap_form form %}
|
||||||
|
<button class="btn btn-primary" name="action_add" type="submit">{% trans "Add Email" %}</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<h2 class="h2" id="head_banner">{% trans "Change Password" %}</h2>
|
||||||
|
|
||||||
|
<a class="btn btn-primary mb-4" href="{% url 'account_change_password' %}">{% trans "Change password" %}</a>
|
||||||
|
|
||||||
|
<h2 class="h2" id="head_banner">{% trans "Federated Login" %}</h2>
|
||||||
|
|
||||||
|
<p>You can connect third-party accounts to log into this site with them.</p>
|
||||||
|
|
||||||
|
<a class="btn btn-primary" href="{% url 'socialaccount_connections' %}">{% trans "Manage" %}</a>
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_body %}
|
||||||
|
<script type="text/javascript">
|
||||||
|
(function() {
|
||||||
|
var message = "{% trans 'Are you sure you want to remove the selected email address?' %}";
|
||||||
|
var actions = document.getElementsByName('action_remove');
|
||||||
|
if (actions.length) {
|
||||||
|
actions[0].addEventListener("click", function(e) {
|
||||||
|
if (! confirm(message)) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
{% load account %}
|
||||||
|
{% user_display user as user_display %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load inlinecss %}
|
||||||
|
{% inlinecss "css/emails.css" %}
|
||||||
|
|
||||||
|
<!DOCTYPE html
|
||||||
|
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta name="viewport" content="width=device-width" />
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
|
<title>Your New {{ settings.PROJECT_LONG_NAME }} Account</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body itemscope itemtype="http://schema.org/EmailMessage">
|
||||||
|
|
||||||
|
<table class="body-wrap">
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td class="container" width="600">
|
||||||
|
<div class="content">
|
||||||
|
<table class="main" width="100%" cellpadding="0" cellspacing="0" itemprop="action" itemscope
|
||||||
|
itemtype="http://schema.org/ConfirmAction">
|
||||||
|
<tr>
|
||||||
|
<td class="content-wrap">
|
||||||
|
<meta itemprop="name" content="Confirm Email" />
|
||||||
|
<table width="100%" cellpadding="0" cellspacing="0">
|
||||||
|
<tr>
|
||||||
|
<td class="content-block">
|
||||||
|
<h2>{{ settings.PROJECT_LONG_NAME }}</h2>
|
||||||
|
</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td class="content-block">
|
||||||
|
You have a new account on {{ settings.PROJECT_LONG_NAME }}. You can log in with the button below.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="content-block">
|
||||||
|
Your username is <i>{{ user.username }}</i>.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="content-block" itemprop="handler" itemscope
|
||||||
|
itemtype="http://schema.org/HttpActionHandler">
|
||||||
|
<a href="{{ settings.SITE_PROTOCOL }}://{{ settings.SITE_URL }}/accounts/login/" class="btn-primary" itemprop="url">Log in</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="content-block">
|
||||||
|
The {{ settings.PROJECT_SHORT_NAME }} team
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<div class="footer">
|
||||||
|
<table width="100%">
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|
||||||
|
{% endinlinecss %}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
Dear user,
|
||||||
|
|
||||||
|
You have a new account on {{ settings.PROJECT_LONG_NAME }}. You can log in at the link below.
|
||||||
|
|
||||||
|
Your username is {{ user.username }}.
|
||||||
|
|
||||||
|
Log in: {{ settings.SITE_PROTOCOL }}://{{ settings.SITE_URL }}/accounts/login/
|
||||||
|
|
||||||
|
Thanks,
|
||||||
|
The {{ settings.PROJECT_SHORT_NAME }} team
|
||||||
71
breccia_mapper/templates/account/email/email_confirmation_message.html
Executable file
71
breccia_mapper/templates/account/email/email_confirmation_message.html
Executable file
@@ -0,0 +1,71 @@
|
|||||||
|
{% load account %}
|
||||||
|
{% user_display user as user_display %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load inlinecss %}
|
||||||
|
{% inlinecss "css/emails.css" %}
|
||||||
|
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta name="viewport" content="width=device-width" />
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
|
<title>Registration confirmation email</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body itemscope itemtype="http://schema.org/EmailMessage">
|
||||||
|
|
||||||
|
<table class="body-wrap">
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td class="container" width="600">
|
||||||
|
<div class="content">
|
||||||
|
<table class="main" width="100%" cellpadding="0" cellspacing="0" itemprop="action" itemscope itemtype="http://schema.org/ConfirmAction">
|
||||||
|
<tr>
|
||||||
|
<td class="content-wrap">
|
||||||
|
<meta itemprop="name" content="Confirm Email"/>
|
||||||
|
<table width="100%" cellpadding="0" cellspacing="0">
|
||||||
|
<tr>
|
||||||
|
<td class="content-block">
|
||||||
|
<h2>{{ settings.PROJECT_LONG_NAME }}</h2>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="content-block">
|
||||||
|
Please confirm your email address by clicking the link below.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="content-block">
|
||||||
|
We may need to send you critical information about our service, so it is important that we have your correct email address.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="content-block" itemprop="handler" itemscope itemtype="http://schema.org/HttpActionHandler">
|
||||||
|
<a href="{{ activate_url }}" class="btn-primary" itemprop="url">Confirm email address</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="content-block">
|
||||||
|
The {{ settings.PROJECT_SHORT_NAME }} team
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<div class="footer">
|
||||||
|
<table width="100%">
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div></div>
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
{% endinlinecss %}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{% include "account/email/email_confirmation_message.html" %}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
{% autoescape off %}
|
||||||
|
{% blocktrans %}Confirm Your Registration - {{ settings.PROJECT_SHORT_NAME }}{% endblocktrans %}
|
||||||
|
{% endautoescape %}
|
||||||
1
breccia_mapper/templates/account/email/email_confirmation_subject.html
Executable file
1
breccia_mapper/templates/account/email/email_confirmation_subject.html
Executable file
@@ -0,0 +1 @@
|
|||||||
|
Confirm Your Email
|
||||||
69
breccia_mapper/templates/account/email/password_reset_key_message.html
Executable file
69
breccia_mapper/templates/account/email/password_reset_key_message.html
Executable file
@@ -0,0 +1,69 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
{% load inlinecss %}
|
||||||
|
{% inlinecss "css/emails.css" %}
|
||||||
|
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta name="viewport" content="width=device-width" />
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
|
<title>Reset your Password</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body itemscope itemtype="http://schema.org/EmailMessage">
|
||||||
|
|
||||||
|
<table class="body-wrap">
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td class="container" width="600">
|
||||||
|
<div class="content">
|
||||||
|
<table class="main" width="100%" cellpadding="0" cellspacing="0" itemprop="action" itemscope itemtype="http://schema.org/ConfirmAction">
|
||||||
|
<tr>
|
||||||
|
<td class="content-wrap">
|
||||||
|
<meta itemprop="name" content="Confirm Email"/>
|
||||||
|
<table width="100%" cellpadding="0" cellspacing="0">
|
||||||
|
<tr>
|
||||||
|
<td class="content-block">
|
||||||
|
<h2>{{ settings.PROJECT_LONG_NAME }}</h2>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="content-block">
|
||||||
|
Please reset your password by clicking the link below.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="content-block">
|
||||||
|
We may need to send you critical information about our service, so it is important that we have your correct email address.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="content-block" itemprop="handler" itemscope itemtype="http://schema.org/HttpActionHandler">
|
||||||
|
<a href="{{ password_reset_url }}" class="btn-primary" itemprop="url">Reset your password</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="content-block">
|
||||||
|
The {{ settings.PROJECT_SHORT_NAME }} team
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<div class="footer">
|
||||||
|
<table width="100%">
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div></div>
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
{% endinlinecss %}
|
||||||
4
breccia_mapper/templates/account/email/password_reset_key_subject.html
Executable file
4
breccia_mapper/templates/account/email/password_reset_key_subject.html
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
{% autoescape off %}
|
||||||
|
{% blocktrans %}Reset Password - {{ settings.PROJECT_SHORT_NAME }}{% endblocktrans %}
|
||||||
|
{% endautoescape %}
|
||||||
32
breccia_mapper/templates/account/email_confirm.html
Executable file
32
breccia_mapper/templates/account/email_confirm.html
Executable file
@@ -0,0 +1,32 @@
|
|||||||
|
{% extends "account/base.html" %}
|
||||||
|
|
||||||
|
{% load i18n %}
|
||||||
|
{% load account %}
|
||||||
|
{% block head_title %}{% trans "Confirm Email Address" %}{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h3 class="h3" id="head_banner">{% trans "Confirm Email Address" %}</h3>
|
||||||
|
|
||||||
|
{% if confirmation %}
|
||||||
|
|
||||||
|
<p class="verification_sent_info" >{% blocktrans with confirmation.email_address.email as email %} Please confirm ownership of <a href="mailto:{{ email }}">{{ email }}</a>.{% endblocktrans %}</p>
|
||||||
|
|
||||||
|
<form method="post"action="{% url 'account_confirm_email' confirmation.key %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
<button class="btn btn-success" type="submit">{% trans 'Confirm' %}</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
{% url 'account_email' as email_url %}
|
||||||
|
|
||||||
|
<p class="verification_sent_info" >{% blocktrans %}This email confirmation link expired or is invalid. Please <a href="{{ email_url }}">request a new email confirmation</a>. You will be redirected to the login page in 5 seconds.{% endblocktrans %}</p>
|
||||||
|
<script>
|
||||||
|
setTimeout("location.href = '{% url 'account_login' %}';",5000);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
62
breccia_mapper/templates/account/login.html
Executable file
62
breccia_mapper/templates/account/login.html
Executable file
@@ -0,0 +1,62 @@
|
|||||||
|
{% extends "account/base.html" %}
|
||||||
|
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block head_links %}
|
||||||
|
|
||||||
|
<title>Sign In</title>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block head_title %}{% trans "Sign In" %} {% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h3 class="h3" id="head_banner">{% trans "Sign In" %}</h3>
|
||||||
|
|
||||||
|
<form id="login_form" method="POST" action="{% url 'account_login' %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
{% load bootstrap4 %}
|
||||||
|
{% bootstrap_form form %}
|
||||||
|
|
||||||
|
{% if redirect_field_value %}
|
||||||
|
|
||||||
|
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<button class="btn btn-primary " type="submit">{% trans "Log in" %}</button>
|
||||||
|
{% if config.ALLOW_SIGNUPS %}
|
||||||
|
<a class="btn btn-secondary" href="{% url 'account_signup' %}">Sign up</a>
|
||||||
|
{% endif %}
|
||||||
|
<a class="btn btn-outline-dark" href="{% url 'account_reset_password' %}">{% trans "Forgot password?" %}</a>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% if config.ENABLE_GOOGLE_LOGIN or config.ENABLE_MICROSOFT_LOGIN %}
|
||||||
|
|
||||||
|
{% load account socialaccount %}
|
||||||
|
|
||||||
|
{% get_providers as socialaccount_providers %}
|
||||||
|
<h5>Federated Login</h5>
|
||||||
|
<div class="social_providers_list">
|
||||||
|
|
||||||
|
{% for provider in socialaccount_providers %}
|
||||||
|
{% if provider.name == "Google" and config.ENABLE_GOOGLE_LOGIN or provider.name == "Microsoft Graph" and config.ENABLE_MICROSOFT_LOGIN %}
|
||||||
|
<form action="{% provider_login_url provider.id process=process scope=scope auth_params=auth_params %}" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<button class="btn btn-outline-dark" type="submit">
|
||||||
|
{% if provider.name == "Microsoft Graph" %}
|
||||||
|
Microsoft
|
||||||
|
{% else %}
|
||||||
|
{{provider.name}}
|
||||||
|
{% endif %}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
26
breccia_mapper/templates/account/logout.html
Executable file
26
breccia_mapper/templates/account/logout.html
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
{% extends "account/base.html" %}
|
||||||
|
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block head_title %}{% trans "Sign Out" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h3 class="h3" id="head_banner">{% trans "Sign Out" %}</h3>
|
||||||
|
|
||||||
|
<p class="confirm_logout_info">{% trans 'Are you sure you want to sign out?' %}</p>
|
||||||
|
|
||||||
|
<form id="logout_form" method="post" action="{% url 'account_logout' %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
{% if redirect_field_value %}
|
||||||
|
|
||||||
|
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}"/>
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<button class="btn btn-success" type="submit">{% trans 'Sign Out' %}</button>
|
||||||
|
<a class="btn btn-danger" id="custom_logout_no" href="/accounts/profile/">{% trans 'No' %}</a>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
{% blocktrans %}You cannot remove your primary email address ({{email}}).{% endblocktrans %}
|
||||||
2
breccia_mapper/templates/account/messages/email_confirmation_sent.txt
Executable file
2
breccia_mapper/templates/account/messages/email_confirmation_sent.txt
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
{% blocktrans %}Confirmation email sent to {{email}}.{% endblocktrans %}
|
||||||
2
breccia_mapper/templates/account/messages/email_confirmed.txt
Executable file
2
breccia_mapper/templates/account/messages/email_confirmed.txt
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
{% blocktrans %}You have confirmed {{email}}.{% endblocktrans %}
|
||||||
2
breccia_mapper/templates/account/messages/email_deleted.txt
Executable file
2
breccia_mapper/templates/account/messages/email_deleted.txt
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
{% blocktrans %}Removed email address {{email}}.{% endblocktrans %}
|
||||||
4
breccia_mapper/templates/account/messages/logged_in.txt
Executable file
4
breccia_mapper/templates/account/messages/logged_in.txt
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
{% load account %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% user_display user as name %}
|
||||||
|
{% blocktrans %}Successfully logged in as {{name}}.{% endblocktrans %}
|
||||||
2
breccia_mapper/templates/account/messages/logged_out.txt
Executable file
2
breccia_mapper/templates/account/messages/logged_out.txt
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
{% blocktrans %}You have signed out.{% endblocktrans %}
|
||||||
2
breccia_mapper/templates/account/messages/password_changed.txt
Executable file
2
breccia_mapper/templates/account/messages/password_changed.txt
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
{% blocktrans %}Password successfully changed.{% endblocktrans %}
|
||||||
2
breccia_mapper/templates/account/messages/password_set.txt
Executable file
2
breccia_mapper/templates/account/messages/password_set.txt
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
{% blocktrans %}Password successfully set.{% endblocktrans %}
|
||||||
2
breccia_mapper/templates/account/messages/primary_email_set.txt
Executable file
2
breccia_mapper/templates/account/messages/primary_email_set.txt
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
{% blocktrans %}Primary email address set.{% endblocktrans %}
|
||||||
2
breccia_mapper/templates/account/messages/unverified_primary_email.txt
Executable file
2
breccia_mapper/templates/account/messages/unverified_primary_email.txt
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
{% blocktrans %}Your primary email address must be verified.{% endblocktrans %}
|
||||||
18
breccia_mapper/templates/account/password_change.html
Executable file
18
breccia_mapper/templates/account/password_change.html
Executable file
@@ -0,0 +1,18 @@
|
|||||||
|
{% extends "account/base.html" %}
|
||||||
|
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block head_title %}{% trans "Change Password" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h3 class="h3" id="head_banner">{% trans "Change Password" %}</h3>
|
||||||
|
|
||||||
|
<form method="POST" action="{% url 'account_change_password' %}" id="change_password_form">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
{% load bootstrap4 %}
|
||||||
|
{% bootstrap_form form %}
|
||||||
|
<button class="btn btn-info" type="submit" name="action">{% trans "Change Password" %}</button>
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
||||||
26
breccia_mapper/templates/account/password_reset.html
Executable file
26
breccia_mapper/templates/account/password_reset.html
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
{% extends "account/base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load account %}
|
||||||
|
|
||||||
|
{% block head_title %}{% trans "Password Reset" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
{% if user.is_authenticated %}
|
||||||
|
{% include "account/snippets/already_logged_in.html" %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<h3 class="h3" id="head_banner">{% trans "Password Reset" %}</h3>
|
||||||
|
<p class="forgot_password_info" >{% trans "Forgotten your password? Enter your email address below to reset it." %}</p>
|
||||||
|
|
||||||
|
<form method="POST" id="forgot_password_form" action="{% url 'account_reset_password' %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
{% load bootstrap4 %}
|
||||||
|
{% bootstrap_form form %}
|
||||||
|
<input class="btn btn-outline-primary " type="submit" value="{% trans 'Reset Password' %}" />
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<p class="forgot_password_info">{% blocktrans %}Please contact us if you are unable to reset your password.{% endblocktrans %}</p>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
20
breccia_mapper/templates/account/password_reset_done.html
Executable file
20
breccia_mapper/templates/account/password_reset_done.html
Executable file
@@ -0,0 +1,20 @@
|
|||||||
|
{% extends "account/base.html" %}
|
||||||
|
|
||||||
|
{% load i18n %}
|
||||||
|
{% load account %}
|
||||||
|
|
||||||
|
{% block head_title %}{% trans "Password Reset" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h3 class="h3" id="head_banner">{% trans "Password Reset Email Sent." %}</h3>
|
||||||
|
|
||||||
|
{% if user.is_authenticated %}
|
||||||
|
{% include "account/snippets/already_logged_in.html" %}
|
||||||
|
{% block content_extra %} {% endblock %}
|
||||||
|
{% else %}
|
||||||
|
<p class="forgot_password_info">A password reset link has been sent to your email address. Please contact us if you do not receive it within a few minutes. <br> You will be redirected to <a href="{% url 'account_login' %}">sign in</a> in 5 seconds.</p>
|
||||||
|
<script>
|
||||||
|
setTimeout("location.href = '{% url 'account_login' %}';",5000);
|
||||||
|
</script>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
24
breccia_mapper/templates/account/password_reset_from_key.html
Executable file
24
breccia_mapper/templates/account/password_reset_from_key.html
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
{% extends "account/base.html" %}
|
||||||
|
|
||||||
|
{% load i18n %}
|
||||||
|
{% block head_title %}{% trans "Change Password" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>{% if token_fail %}{% trans "Bad Token" %}{% else %}{% trans "Change Password" %}{% endif %}</h1>
|
||||||
|
|
||||||
|
{% if token_fail %}
|
||||||
|
{% url 'account_reset_password' as passwd_reset_url %}
|
||||||
|
<p>{% blocktrans %}The password reset link was invalid, possibly because it has already been used. Please request a <a href="{{ passwd_reset_url }}">new password reset</a>.{% endblocktrans %}</p>
|
||||||
|
{% else %}
|
||||||
|
{% if form %}
|
||||||
|
<form method="POST" action="{{ action_url }}">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% load bootstrap4 %}
|
||||||
|
{% bootstrap_form form %}
|
||||||
|
<input type="submit" name="action" value="{% trans 'change password' %}"/>
|
||||||
|
</form>
|
||||||
|
{% else %}
|
||||||
|
<p>{% trans 'Your password has been changed.' %}</p>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
9
breccia_mapper/templates/account/password_reset_from_key_done.html
Executable file
9
breccia_mapper/templates/account/password_reset_from_key_done.html
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
{% extends "account/base.html" %}
|
||||||
|
|
||||||
|
{% load i18n %}
|
||||||
|
{% block head_title %}{% trans "Change Password" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>{% trans "Change Password" %}</h1>
|
||||||
|
<p>{% trans 'Your password has been changed.' %}</p>
|
||||||
|
{% endblock %}
|
||||||
18
breccia_mapper/templates/account/password_set.html
Executable file
18
breccia_mapper/templates/account/password_set.html
Executable file
@@ -0,0 +1,18 @@
|
|||||||
|
{% extends "account/base.html" %}
|
||||||
|
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block head_title %}{% trans "Set Password" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h3 class="h3" id="head_banner">{% trans "Set Password" %}</h3>
|
||||||
|
|
||||||
|
<form method="POST" action="{% url 'account_set_password' %}" class="password_set">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
{% load bootstrap4 %}
|
||||||
|
{% bootstrap_form form %}
|
||||||
|
<input class="btn btn-outline-primary btn-lg" type="submit" name="action" value="{% trans 'Set Password' %}"/>
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
||||||
33
breccia_mapper/templates/account/signup.html
Executable file
33
breccia_mapper/templates/account/signup.html
Executable file
@@ -0,0 +1,33 @@
|
|||||||
|
{% extends "account/base.html" %}
|
||||||
|
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block head_title %}{% trans "Sign Up" %}{% endblock %}
|
||||||
|
{% block head_links %}
|
||||||
|
|
||||||
|
<title>Signup</title>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h3 class="h3" id="head_banner">{% trans "Sign Up" %}</h3>
|
||||||
|
|
||||||
|
<p class="exist_account_info">{% blocktrans %}Already have an account? Please <a href="{{ login_url }}">sign in</a>.{% endblocktrans %}</p>
|
||||||
|
|
||||||
|
<form id="signup_form" method="post" action="{% url 'account_signup' %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
{% load bootstrap4 %}
|
||||||
|
{% bootstrap_form form %}
|
||||||
|
|
||||||
|
{% if redirect_field_value %}
|
||||||
|
|
||||||
|
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<button class="btn btn-primary" type="submit">{% trans "Sign Up" %}</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
11
breccia_mapper/templates/account/signup_closed.html
Executable file
11
breccia_mapper/templates/account/signup_closed.html
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
{% extends "account/base.html" %}
|
||||||
|
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block head_title %}{% trans "Sign Up Closed" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>{% trans "Sign Up Closed" %}</h1>
|
||||||
|
|
||||||
|
<p>{% blocktrans with project_long_name=settings.PROJECT_LONG_NAME %}Signing up to {{ project_long_name }} is currently not permitted.{% endblocktrans %}</p>
|
||||||
|
{% endblock %}
|
||||||
11
breccia_mapper/templates/account/snippets/already_logged_in.html
Executable file
11
breccia_mapper/templates/account/snippets/already_logged_in.html
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
{% load account %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% user_display user as user_display %}
|
||||||
|
|
||||||
|
<h3 class="h3" id="head_banner">Already Logged In</h3>
|
||||||
|
<p class="forgot_password_info" >You are already logged in as {{ user_display }}.</p>
|
||||||
|
<a class="btn btn-primary mb-4" id="custom_logout_no" href="{% url 'account_email' %}">Account Details</a>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
12
breccia_mapper/templates/account/verification_sent.html
Executable file
12
breccia_mapper/templates/account/verification_sent.html
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
{% extends "account/base.html" %}
|
||||||
|
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block head_title %}{% trans "Verify Your Email Address" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h3 class="h3" id="head_banner">{% trans "Verify Your Email Address" %}</h3>
|
||||||
|
|
||||||
|
<p id="verification_sent_info">{% blocktrans %}A verification email has been sent to your email address. Follow the link provided to activate your account. Contact us if you do not receive it within a few minutes.{% endblocktrans %}</p>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
22
breccia_mapper/templates/account/verified_email_required.html
Executable file
22
breccia_mapper/templates/account/verified_email_required.html
Executable file
@@ -0,0 +1,22 @@
|
|||||||
|
{% extends "account/base.html" %}
|
||||||
|
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block head_title %}{% trans "Verify Your Email Address" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>{% trans "Verify Your Email Address" %}</h1>
|
||||||
|
|
||||||
|
{% url 'account_email' as email_url %}
|
||||||
|
|
||||||
|
<p>{% blocktrans %}This part of the site requires us to verify that
|
||||||
|
you are who you claim to be. We therefore require you to
|
||||||
|
verify ownership of your email address. {% endblocktrans %}</p>
|
||||||
|
|
||||||
|
<p>{% blocktrans %}A verification email has been sent to your email address. Follow the link provided to activate your account. Contact us
|
||||||
|
if you do not receive it within a few minutes.{% endblocktrans %}</p>
|
||||||
|
|
||||||
|
<p>{% blocktrans %}<strong>Note:</strong> you can still <a href="{{ email_url }}">change your email address</a>.{% endblocktrans %}</p>
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@@ -4,9 +4,11 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% get_current_language as LANGUAGE_CODE %}
|
{% get_current_language as LANGUAGE_CODE %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% load bootstrap_customizer %}
|
||||||
<html lang="{{ LANGUAGE_CODE|default:'en_us' }}">
|
<html lang="{{ LANGUAGE_CODE|default:'en_us' }}">
|
||||||
|
|
||||||
{% load pwa %}
|
{% load pwa %}
|
||||||
|
{% load socialaccount %}
|
||||||
|
|
||||||
<link rel="manifest" href="/manifest.json">
|
<link rel="manifest" href="/manifest.json">
|
||||||
|
|
||||||
@@ -18,6 +20,9 @@
|
|||||||
|
|
||||||
<!-- Bootstrap CSS -->
|
<!-- Bootstrap CSS -->
|
||||||
{% bootstrap_css %}
|
{% bootstrap_css %}
|
||||||
|
<style lang="css">
|
||||||
|
{% bootstrap_theme_css_above_the_fold %}
|
||||||
|
</style>
|
||||||
|
|
||||||
<link rel="stylesheet"
|
<link rel="stylesheet"
|
||||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/fontawesome.min.css"
|
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/fontawesome.min.css"
|
||||||
@@ -60,6 +65,7 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
<link rel="stylesheet" type="text/css" href="{% bootstrap_theme_css_below_the_fold_url %}" />
|
||||||
<div class="content" style="display: flex; flex-direction: column">
|
<div class="content" style="display: flex; flex-direction: column">
|
||||||
{% block navbar %}
|
{% block navbar %}
|
||||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||||
@@ -76,6 +82,12 @@
|
|||||||
|
|
||||||
<div class="navbar-collapse collapse" id="navbarCollapse">
|
<div class="navbar-collapse collapse" id="navbarCollapse">
|
||||||
<ul class="navbar-nav mt-2 mt-lg-0">
|
<ul class="navbar-nav mt-2 mt-lg-0">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="{% if request.user.person %}{% url 'people:person.profile' %}{% else %}{% url 'people:person.create' %}{% endif %}" class="nav-link">
|
||||||
|
Profile
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a href="{% url 'people:person.list' %}" class="nav-link">People</a>
|
<a href="{% url 'people:person.list' %}" class="nav-link">People</a>
|
||||||
</li>
|
</li>
|
||||||
@@ -92,15 +104,15 @@
|
|||||||
<a href="{% url 'activities:activity.list' %}" class="nav-link">Activities</a>
|
<a href="{% url 'activities:activity.list' %}" class="nav-link">Activities</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-item">
|
|
||||||
<a href="{% url 'people:map' %}" class="nav-link">Map</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="nav-item">
|
|
||||||
<a href="{% url 'people:network' %}" class="nav-link">Network</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
{% if request.user.is_superuser %}
|
{% if request.user.is_superuser %}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="{% url 'people:map' %}" class="nav-link">Map</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="{% url 'people:network' %}" class="nav-link">Network</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a href="{% url 'export:index' %}" class="nav-link">Export</a>
|
<a href="{% url 'export:index' %}" class="nav-link">Export</a>
|
||||||
</li>
|
</li>
|
||||||
@@ -114,23 +126,18 @@
|
|||||||
<ul class="navbar-nav mt-2 mt-lg-0 ml-auto">
|
<ul class="navbar-nav mt-2 mt-lg-0 ml-auto">
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.user.is_authenticated %}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
{% if request.user.person %}
|
<a href="{% url 'account_email' %}" class="nav-link">
|
||||||
<a href="{% url 'people:person.profile' %}" class="nav-link">
|
<i class="fa-solid fa-circle-user"></i>
|
||||||
<i class="fa-solid fa-circle-user"></i>
|
{% if request.user.first_name != "" %}
|
||||||
{{ request.user }}
|
{{ request.user.first_name }}
|
||||||
</a>
|
{% else %}
|
||||||
|
{{ request.user }}
|
||||||
{% else %}
|
{% endif %}
|
||||||
<a href="{% url 'people:person.create' %}?user" class="nav-link">
|
</a>
|
||||||
<i class="fa-solid fa-circle-user"></i>
|
|
||||||
{{ request.user }}
|
|
||||||
</a>
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a href="{% url 'logout' %}" class="nav-link">
|
<a href="{% url 'account_logout' %}" class="nav-link">
|
||||||
<i class="fa-solid fa-right-from-bracket"></i>
|
<i class="fa-solid fa-right-from-bracket"></i>
|
||||||
Log Out
|
Log Out
|
||||||
</a>
|
</a>
|
||||||
@@ -138,7 +145,7 @@
|
|||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a href="{% url 'login' %}" class="nav-link">
|
<a href="{% url 'account_login' %}" class="nav-link">
|
||||||
<i class="fa-solid fa-right-to-bracket"></i>
|
<i class="fa-solid fa-right-to-bracket"></i>
|
||||||
Log In
|
Log In
|
||||||
</a>
|
</a>
|
||||||
@@ -190,7 +197,7 @@
|
|||||||
Please fill in your details so you can be part of the network.
|
Please fill in your details so you can be part of the network.
|
||||||
|
|
||||||
<a class="btn btn-success"
|
<a class="btn btn-success"
|
||||||
href="{% url 'people:person.create' %}?user">Profile</a>
|
href="{% url 'people:person.create' %}">Profile</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -10,13 +10,13 @@
|
|||||||
{% block before_content %}
|
{% block before_content %}
|
||||||
|
|
||||||
{% get_media_prefix as MEDIA_URL %}
|
{% get_media_prefix as MEDIA_URL %}
|
||||||
<header class="container-fluid masthead text-white text-left {% if config.HOMEPAGE_HEADER_IMAGE_SHRINK %}masthead-shrink{% endif %}"
|
<header class="container-fluid masthead text-white text-left {% if config.HOMEPAGE_HEADER_IMAGE_SHRINK %}masthead-shrink{% endif %} py-2"
|
||||||
style="background-image: url('{{ MEDIA_URL }}{{ config.HOMEPAGE_HEADER_IMAGE }}')">
|
style="background-image: url('{{ MEDIA_URL }}{{ config.HOMEPAGE_HEADER_IMAGE }}')">
|
||||||
<div class="overlay"></div>
|
<div class="overlay"></div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="mx-5 px-4 my-3 pt-3 pb-2 textbox-container">
|
<div class="px-4 my-3 pt-3 pb-2 textbox-container">
|
||||||
<h1 class="display-1">{{ settings.PROJECT_LONG_NAME }}</h1>
|
<h1>{{ settings.PROJECT_LONG_NAME }}</h1>
|
||||||
<p class="lead">{{ config.PROJECT_LEAD }}</p>
|
<p class="lead">{{ config.PROJECT_LEAD }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
8
breccia_mapper/templates/offline.html
Normal file
8
breccia_mapper/templates/offline.html
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h2>Offline</h2>
|
||||||
|
|
||||||
|
<p>You are currently offline. Please connect to a network to use this platform.</p>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@@ -9,8 +9,8 @@
|
|||||||
{% bootstrap_form form %}
|
{% bootstrap_form form %}
|
||||||
{% buttons %}
|
{% buttons %}
|
||||||
<input type="hidden" name="next" value="{{ next }}">
|
<input type="hidden" name="next" value="{{ next }}">
|
||||||
<input type="submit" class="btn btn-info" value="Login">
|
<input type="submit" class="btn btn-primary" value="Login">
|
||||||
{% endbuttons %}
|
{% endbuttons %}
|
||||||
<p>Forgot your password? Reset it <a href="{% url 'password_reset' %}">here</a>.</p>
|
<p>Forgot your password? Reset it <a href="{% url 'account_reset_password' %}">here</a>.</p>
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -4,5 +4,5 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Password Reset Complete</h1>
|
<h1>Password Reset Complete</h1>
|
||||||
|
|
||||||
<p>Your password has been successfully reset. You can now <a href="{% url 'login' %}">log in using it</a>.</p> If you haven't yet completed your profile, please do this now.
|
<p>Your password has been successfully reset. You can now <a href="{% url 'account_login' %}">log in using it</a>.</p> If you haven't yet completed your profile, please do this now.
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
||||||
<p>That link isn't valid - has it already been used? You can request a new link <a href="{% url 'login' %}">here</a>.</p>
|
<p>That link isn't valid - has it already been used? You can request a new link <a href="{% url 'account_reset_password' %}">here</a>.</p>
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|||||||
11
breccia_mapper/templates/socialaccount/authentication_error.html
Executable file
11
breccia_mapper/templates/socialaccount/authentication_error.html
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
{% extends "socialaccount/base.html" %}
|
||||||
|
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block head_title %}{% trans "Federated Login Failure" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>{% trans "Federated Login Failure" %}</h1>
|
||||||
|
|
||||||
|
<p>{% trans "An error occurred while attempting to log in via your third party account." %}</p>
|
||||||
|
{% endblock %}
|
||||||
1
breccia_mapper/templates/socialaccount/base.html
Executable file
1
breccia_mapper/templates/socialaccount/base.html
Executable file
@@ -0,0 +1 @@
|
|||||||
|
{% extends "account/base.html" %}
|
||||||
70
breccia_mapper/templates/socialaccount/connections.html
Executable file
70
breccia_mapper/templates/socialaccount/connections.html
Executable file
@@ -0,0 +1,70 @@
|
|||||||
|
{% extends "socialaccount/base.html" %}
|
||||||
|
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block head_title %}{% trans "Account Connections" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
<a class="btn btn-primary mb-4" href="{% url 'account_email' %}">{% trans "Account Details" %}</a>
|
||||||
|
|
||||||
|
<h2 class="h2" id="head_banner">{% trans "Account Connections" %}</h2>
|
||||||
|
|
||||||
|
{% if form.accounts %}
|
||||||
|
<p>{% blocktrans %}You can sign in to your account using any of the following third party accounts:{% endblocktrans %}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<form method="post" action="{% url 'socialaccount_connections' %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
{% if form.non_field_errors %}
|
||||||
|
<div id="errorMsg">{{ form.non_field_errors }}</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% for base_account in form.accounts %}
|
||||||
|
{% with base_account.get_provider_account as account %}
|
||||||
|
<div>
|
||||||
|
<label for="id_account_{{ base_account.id }}">
|
||||||
|
<input id="id_account_{{ base_account.id }}" type="radio" name="account"
|
||||||
|
value="{{ base_account.id }}" />
|
||||||
|
<span class="socialaccount_provider {{ base_account.provider }} {{ account.get_brand.id }}">
|
||||||
|
{% if account.get_brand.name == "Microsoft Graph" %}
|
||||||
|
Microsoft
|
||||||
|
{% else %}
|
||||||
|
{{ account.get_brand.name }}
|
||||||
|
{% endif %}
|
||||||
|
-
|
||||||
|
</span>
|
||||||
|
{{ account }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
{% endwith %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button class="btn btn-danger" type="submit">{% trans 'Remove' %}</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
<p>{% trans 'You currently have no third party accounts connected to this account.' %}</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<h3 class="h3" id="head_banner">{% trans 'Add Federated Login Account' %}</h3>
|
||||||
|
|
||||||
|
<p>Adding a third party account allows you to log in to this site with it.</p>
|
||||||
|
|
||||||
|
<div class="social_providers_list">
|
||||||
|
{% include "socialaccount/snippets/provider_list.html" with process="connect" %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% include "socialaccount/snippets/login_extra.html" %}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
15
breccia_mapper/templates/socialaccount/login_cancelled.html
Executable file
15
breccia_mapper/templates/socialaccount/login_cancelled.html
Executable file
@@ -0,0 +1,15 @@
|
|||||||
|
{% extends "socialaccount/base.html" %}
|
||||||
|
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block head_title %}{% trans "Login Cancelled" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h1>{% trans "Login Cancelled" %}</h1>
|
||||||
|
|
||||||
|
{% url 'account_login' as login_url %}
|
||||||
|
|
||||||
|
<p>{% blocktrans %}Login was cancelled. If this was a mistake, please proceed to <a href="{{login_url}}">sign in</a>.{% endblocktrans %}</p>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
2
breccia_mapper/templates/socialaccount/messages/account_connected.txt
Executable file
2
breccia_mapper/templates/socialaccount/messages/account_connected.txt
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
{% blocktrans %}Your third party account has been connected.{% endblocktrans %}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
{% blocktrans %}Your third party account is already connected to a different account on this site.{% endblocktrans %}
|
||||||
2
breccia_mapper/templates/socialaccount/messages/account_disconnected.txt
Executable file
2
breccia_mapper/templates/socialaccount/messages/account_disconnected.txt
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
{% blocktrans %}Your third party account has been disconnected.{% endblocktrans %}
|
||||||
24
breccia_mapper/templates/socialaccount/signup.html
Executable file
24
breccia_mapper/templates/socialaccount/signup.html
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
{% extends "socialaccount/base.html" %}
|
||||||
|
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block head_title %}{% trans "Signup" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>{% trans "Sign Up" %}</h1>
|
||||||
|
|
||||||
|
<p>{% blocktrans with provider_name=account.get_provider.name site_name=site.name %}You are about to use your {% if provider_name == 'Microsoft Graph' %}Microsoft{% else %}{{provider_name}}{% endif %} account to sign up to
|
||||||
|
{{site_name}}.{% endblocktrans %}</p>
|
||||||
|
|
||||||
|
<form class="signup" id="signup_form" method="post" action="{% url 'socialaccount_signup' %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
{% load bootstrap4 %}
|
||||||
|
{% bootstrap_form form %}
|
||||||
|
{% if redirect_field_value %}
|
||||||
|
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
|
||||||
|
{% endif %}
|
||||||
|
<button type="submit">{% trans "Sign Up" %} »</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
3
breccia_mapper/templates/socialaccount/snippets/login_extra.html
Executable file
3
breccia_mapper/templates/socialaccount/snippets/login_extra.html
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
{% load socialaccount %}
|
||||||
|
|
||||||
|
{% providers_media_js %}
|
||||||
22
breccia_mapper/templates/socialaccount/snippets/provider_list.html
Executable file
22
breccia_mapper/templates/socialaccount/snippets/provider_list.html
Executable file
@@ -0,0 +1,22 @@
|
|||||||
|
{% load socialaccount %}
|
||||||
|
|
||||||
|
{% get_providers as socialaccount_providers %}
|
||||||
|
|
||||||
|
{% for provider in socialaccount_providers %}
|
||||||
|
{% if provider.id == "openid" %}
|
||||||
|
{% for brand in provider.get_brands %}
|
||||||
|
<form action="{% provider_login_url provider.id openid=brand.openid_url process=process %}" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<button class="btn btn-outline-dark" type="submit">
|
||||||
|
{{ brand.name }}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
<form action="{% provider_login_url provider.id process=process scope=scope auth_params=auth_params %}" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<button class="btn btn-outline-dark" type="submit">
|
||||||
|
{% if provider.name == 'Microsoft Graph' %}Microsoft{% else %}{{provider.name}}{% endif %}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{% endfor %}
|
||||||
@@ -17,6 +17,7 @@ from django.contrib import admin
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.urls import include, path
|
from django.urls import include, path
|
||||||
from django.conf.urls.static import static
|
from django.conf.urls.static import static
|
||||||
|
from bootstrap_customizer import urls as bootstrap_customizer_urls
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
@@ -33,9 +34,6 @@ urlpatterns = [
|
|||||||
path('hijack/',
|
path('hijack/',
|
||||||
include('hijack.urls', namespace='hijack')),
|
include('hijack.urls', namespace='hijack')),
|
||||||
|
|
||||||
path('',
|
|
||||||
include('django.contrib.auth.urls')),
|
|
||||||
|
|
||||||
path('',
|
path('',
|
||||||
views.IndexView.as_view(),
|
views.IndexView.as_view(),
|
||||||
name='index'),
|
name='index'),
|
||||||
@@ -55,4 +53,10 @@ urlpatterns = [
|
|||||||
|
|
||||||
path('',
|
path('',
|
||||||
include('pwa.urls')),
|
include('pwa.urls')),
|
||||||
|
|
||||||
|
path('accounts/',
|
||||||
|
include('allauth.urls')),
|
||||||
|
|
||||||
|
path('bootstrap_customizer',
|
||||||
|
include(bootstrap_customizer_urls)),
|
||||||
] # yapf: disable
|
] # yapf: disable
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ from django.contrib.auth.mixins import LoginRequiredMixin
|
|||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
from django.views.generic.edit import UpdateView
|
from django.views.generic.edit import UpdateView
|
||||||
|
from django.contrib.auth.mixins import UserPassesTestMixin
|
||||||
|
import typing
|
||||||
|
|
||||||
from . import forms
|
from . import forms
|
||||||
|
|
||||||
@@ -19,6 +21,10 @@ class IndexView(TemplateView):
|
|||||||
# Template set in Django settings file - may be customised by a customisation app
|
# Template set in Django settings file - may be customised by a customisation app
|
||||||
template_name = settings.TEMPLATE_NAME_INDEX
|
template_name = settings.TEMPLATE_NAME_INDEX
|
||||||
|
|
||||||
|
class UserIsStaffMixin(UserPassesTestMixin):
|
||||||
|
def test_func(self) -> typing.Optional[bool]:
|
||||||
|
return self.request.user.is_staff
|
||||||
|
|
||||||
|
|
||||||
class ConsentTextView(LoginRequiredMixin, UpdateView):
|
class ConsentTextView(LoginRequiredMixin, UpdateView):
|
||||||
"""View with consent text and form for users to indicate consent."""
|
"""View with consent text and form for users to indicate consent."""
|
||||||
|
|||||||
134
deploy/deploy-ansible/example.env
Normal file
134
deploy/deploy-ansible/example.env
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
# REQUIRED=Secret key
|
||||||
|
# Used to generate CSRF tokens - must never be made public
|
||||||
|
SECRET_KEY=changeme
|
||||||
|
|
||||||
|
# REQUIRED=Database password
|
||||||
|
# The password for the breccia-mapper user in the postgres database
|
||||||
|
DB_PASSWORD=changeme
|
||||||
|
|
||||||
|
# REQUIRED=Google Maps API key
|
||||||
|
# Google Maps API key to display maps of people's locations - required to enable map functionality
|
||||||
|
# Default: None
|
||||||
|
# GOOGLE_MAPS_API_KEY=None
|
||||||
|
|
||||||
|
# Debug
|
||||||
|
# Should the server run in debug mode? Provides information to users which is unsafe in production
|
||||||
|
# Default: False
|
||||||
|
DEBUG=False
|
||||||
|
|
||||||
|
# Project long name
|
||||||
|
# The project's full name.
|
||||||
|
# Default: Project Network Mapper
|
||||||
|
# PROJECT_LONG_NAME=Project Network Mapper
|
||||||
|
|
||||||
|
# Project short name
|
||||||
|
# The project's short/abbreviated name. This will also be used as the app's name when installed as PWA.
|
||||||
|
# Default: Network Mapper
|
||||||
|
# PROJECT_SHORT_NAME=Network Mapper
|
||||||
|
|
||||||
|
# Project description
|
||||||
|
# The project's description. Used when installed as a PWA.
|
||||||
|
# Default: Application to map network relationships in the organisation.
|
||||||
|
# PROJECT_DESCRIPTION=Application to map network relationships in the organisation.
|
||||||
|
|
||||||
|
# Theme color
|
||||||
|
# The project's theme color, in hex format (excluding the leading #).
|
||||||
|
# Default: 212121
|
||||||
|
# THEME_COLOR=212121
|
||||||
|
|
||||||
|
# Background color
|
||||||
|
# The project's background color, in hex format (excluding the leading #).
|
||||||
|
# Default: ffffff
|
||||||
|
# BACKGROUND_COLOR=ffffff
|
||||||
|
|
||||||
|
# Allowed hosts
|
||||||
|
# Accepted values for server header in request - protects against CSRF and CSS attacks
|
||||||
|
# Default: * if DEBUG else localhost
|
||||||
|
# ALLOWED_HOSTS=127.0.0.1,localhost,localhost.localdomain
|
||||||
|
|
||||||
|
# Site URL
|
||||||
|
# The URL the site will be deployed on. Do not include http://, https://, or a trailing slash.
|
||||||
|
# Default: localhost
|
||||||
|
# SITE_URL=localhost
|
||||||
|
|
||||||
|
# Site protocol
|
||||||
|
# The protocol the site uses. Valid options are http or https.
|
||||||
|
# Default: http
|
||||||
|
# SITE_PROTOCOL=http
|
||||||
|
|
||||||
|
# Trusted origins
|
||||||
|
# The trusted origin domains of requests - protects against CSRF and CSS attacks
|
||||||
|
# Default: '*' if DEBUG else 'http://127.0.0.1,http://localhost,http://localhost.localdomain'
|
||||||
|
# TRUSTED_ORIGINS=http://127.0.0.1,http://localhost,http://localhost.localdomain
|
||||||
|
|
||||||
|
# Database backup storage location
|
||||||
|
# Directory where database backups should be stored
|
||||||
|
# Default: .dbbackup
|
||||||
|
# DBBACKUP_STORAGE_LOCATION=.dbbackup
|
||||||
|
|
||||||
|
# Default language
|
||||||
|
# Default language - used for translation - has not been enabled
|
||||||
|
# Default: en-gb
|
||||||
|
# LANGUAGE_CODE=en-gb
|
||||||
|
|
||||||
|
# Timezone
|
||||||
|
# Default timezone
|
||||||
|
# Default: UTC
|
||||||
|
# TIME_ZONE=UTC
|
||||||
|
|
||||||
|
# Logging level
|
||||||
|
# Level of messages written to log file
|
||||||
|
# Default: INFO
|
||||||
|
# LOG_LEVEL=INFO
|
||||||
|
|
||||||
|
# Logging filename
|
||||||
|
# Path to logfile
|
||||||
|
# Default: debug.log
|
||||||
|
# LOG_FILENAME=debug.log
|
||||||
|
|
||||||
|
# Logging duration
|
||||||
|
# Number of days of logs to keep - logfile is rotated out at the end of each day
|
||||||
|
# Default: 14
|
||||||
|
# LOG_DAYS=14
|
||||||
|
|
||||||
|
# STMP host
|
||||||
|
# Hostname of SMTP server
|
||||||
|
# Default: None
|
||||||
|
# EMAIL_HOST=None
|
||||||
|
|
||||||
|
# Default from email address
|
||||||
|
# Email address from which messages are sent
|
||||||
|
# Default: None
|
||||||
|
# DEFAULT_FROM_EMAIL=None
|
||||||
|
|
||||||
|
# [DEBUG ONLY] Email file path
|
||||||
|
# Directory where emails will be stored if not using an SMTP server
|
||||||
|
# Default: mail.log
|
||||||
|
# EMAIL_FILE_PATH=mail.log
|
||||||
|
|
||||||
|
# SMTP username
|
||||||
|
# Username to authenticate with SMTP server
|
||||||
|
# Default: None
|
||||||
|
# EMAIL_HOST_USER=None
|
||||||
|
|
||||||
|
# SMTP password
|
||||||
|
# Password to authenticate with SMTP server
|
||||||
|
# Default: None
|
||||||
|
# EMAIL_HOST_PASSWORD=None
|
||||||
|
|
||||||
|
# SMTP port
|
||||||
|
# Port to access on SMTP server
|
||||||
|
# Default: 25
|
||||||
|
# EMAIL_PORT=25
|
||||||
|
|
||||||
|
# SMTP use TLS
|
||||||
|
# Use TLS to communicate with SMTP server? Usually on port 587
|
||||||
|
# Cannot be enabled at the same time as EMAIL_USE_SSL
|
||||||
|
# Default: True if EMAIL_PORT == 587 else False
|
||||||
|
# EMAIL_USE_TLS=True if EMAIL_PORT == 587 else False
|
||||||
|
|
||||||
|
# SMTP use SSL
|
||||||
|
# Use SSL to communicate with SMTP server? Usually on port 465
|
||||||
|
# Cannot be enabled at the same time as EMAIL_USE_TLS
|
||||||
|
# Default: True if EMAIL_PORT == 465 else False
|
||||||
|
# EMAIL_USE_SSL=True if EMAIL_PORT == 465 else False
|
||||||
4
deploy/deploy-ansible/inventory.example.yml
Normal file
4
deploy/deploy-ansible/inventory.example.yml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
all:
|
||||||
|
hosts:
|
||||||
|
example.com:
|
||||||
|
|
||||||
104
deploy/deploy-ansible/playbook.yml
Normal file
104
deploy/deploy-ansible/playbook.yml
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
---
|
||||||
|
- hosts: all
|
||||||
|
become_user: root
|
||||||
|
become_method: sudo
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
pre_tasks:
|
||||||
|
- name: Check if running under Vagrant
|
||||||
|
stat:
|
||||||
|
path: /vagrant
|
||||||
|
register: vagrant_dir
|
||||||
|
|
||||||
|
vars:
|
||||||
|
project_name: network-mapper
|
||||||
|
project_dir: /srv/{{ project_name }}
|
||||||
|
project_src_dir: "{{ project_dir }}/src"
|
||||||
|
provision_superuser: false
|
||||||
|
superuser_username: admin
|
||||||
|
superuser_password: admin
|
||||||
|
superuser_email: email@example.com
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Vagrant specific tasks
|
||||||
|
block:
|
||||||
|
- name: Add Docker repository
|
||||||
|
get_url:
|
||||||
|
url: https://download.docker.com/linux/centos/docker-ce.repo
|
||||||
|
dest: '/etc/yum.repos.d/docker-ce.repo'
|
||||||
|
when: deploy_environment is defined and deploy_environment == "vagrant"
|
||||||
|
|
||||||
|
- name: Install system dependencies
|
||||||
|
ansible.builtin.yum:
|
||||||
|
name:
|
||||||
|
- git
|
||||||
|
- docker-ce
|
||||||
|
- docker-ce-cli
|
||||||
|
- containerd.io
|
||||||
|
- docker-compose-plugin
|
||||||
|
state: present
|
||||||
|
|
||||||
|
# - name: Update system packages
|
||||||
|
# ansible.builtin.yum:
|
||||||
|
# name: '*'
|
||||||
|
# state: latest
|
||||||
|
|
||||||
|
- name: Clone / update from source repos
|
||||||
|
ansible.builtin.git:
|
||||||
|
repo: 'https://github.com/Southampton-RSG/breccia-mapper.git'
|
||||||
|
dest: '{{ project_src_dir }}'
|
||||||
|
version: dev # master
|
||||||
|
accept_hostkey: yes
|
||||||
|
|
||||||
|
- name: Copy template files
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: '{{ item }}.j2'
|
||||||
|
dest: '{{ project_dir }}/{{ item }}'
|
||||||
|
mode: 0600
|
||||||
|
loop:
|
||||||
|
- Caddyfile
|
||||||
|
- docker-compose.yml
|
||||||
|
|
||||||
|
- name: Copy settings file
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: '.env'
|
||||||
|
dest: '{{ project_dir }}/.env'
|
||||||
|
mode: 0600
|
||||||
|
|
||||||
|
- name: Copy site icon
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: 'icon-192x192.png'
|
||||||
|
dest: '{{ project_dir }}/icon-192x192.png'
|
||||||
|
mode: 0600
|
||||||
|
|
||||||
|
- name: Start Docker
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: docker
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
|
||||||
|
- name: Pull latest docker images
|
||||||
|
ansible.builtin.command:
|
||||||
|
chdir: "{{ project_dir }}"
|
||||||
|
cmd: docker compose pull {{ item }}
|
||||||
|
loop:
|
||||||
|
- caddy
|
||||||
|
- server
|
||||||
|
- db
|
||||||
|
|
||||||
|
- name: Start containers
|
||||||
|
ansible.builtin.command:
|
||||||
|
chdir: "{{ project_dir }}"
|
||||||
|
cmd: docker compose up -d
|
||||||
|
|
||||||
|
- name: Provision superuser
|
||||||
|
ansible.builtin.command:
|
||||||
|
chdir: "{{ project_dir }}"
|
||||||
|
cmd: sudo docker compose exec -it server /bin/bash -c "DJANGO_SUPERUSER_USERNAME='{{ superuser_username }}' DJANGO_SUPERUSER_PASSWORD='{{ superuser_password }}' DJANGO_SUPERUSER_EMAIL='{{ superuser_email }}' /app/manage.py createsuperuser --no-input"
|
||||||
|
when: provision_superuser
|
||||||
|
|
||||||
|
- name: Display warning about new superuser
|
||||||
|
debug:
|
||||||
|
msg:
|
||||||
|
- "[WARNING] A superuser has been provisioned with the username \"{{ superuser_username }}\" and the password that was provided. This user has unlimited access to the network mapper."
|
||||||
|
when: provision_superuser
|
||||||
16
deploy/deploy-ansible/templates/Caddyfile.j2
Executable file
16
deploy/deploy-ansible/templates/Caddyfile.j2
Executable file
@@ -0,0 +1,16 @@
|
|||||||
|
:80 :443 {
|
||||||
|
root * /srv
|
||||||
|
file_server
|
||||||
|
|
||||||
|
@proxy_paths {
|
||||||
|
not path /static/*
|
||||||
|
not path /media/*
|
||||||
|
}
|
||||||
|
|
||||||
|
reverse_proxy @proxy_paths http://server:8000
|
||||||
|
|
||||||
|
log {
|
||||||
|
output stderr
|
||||||
|
format console
|
||||||
|
}
|
||||||
|
}
|
||||||
57
deploy/deploy-ansible/templates/docker-compose.yml.j2
Executable file
57
deploy/deploy-ansible/templates/docker-compose.yml.j2
Executable file
@@ -0,0 +1,57 @@
|
|||||||
|
version: '3.1'
|
||||||
|
|
||||||
|
services:
|
||||||
|
server:
|
||||||
|
image: mgrove36/breccia-mapper:latest
|
||||||
|
build: {{ project_src_dir }}
|
||||||
|
ports:
|
||||||
|
- 8000:8000
|
||||||
|
environment:
|
||||||
|
DJANGO_DEBUG: ${DEBUG}
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
volumes:
|
||||||
|
- static_files:/app/static
|
||||||
|
- media_files:/app/media
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
|
||||||
|
caddy:
|
||||||
|
image: caddy:2
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- 80:80
|
||||||
|
- 443:443
|
||||||
|
volumes:
|
||||||
|
- ./Caddyfile:/etc/caddy/Caddyfile:z
|
||||||
|
# Caddy serves static files collected by Django
|
||||||
|
- static_files:/srv/static:ro
|
||||||
|
- media_files:/srv/media
|
||||||
|
- {{ project_dir }}/icon-192x192.png:/srv/media/icon-192x192.png:ro
|
||||||
|
- caddy_data:/data
|
||||||
|
- caddy_config:/config
|
||||||
|
depends_on:
|
||||||
|
- server
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: postgres:15.2-alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
POSTGRES_DB: 'breccia-mapper'
|
||||||
|
POSTGRES_USER: 'breccia-mapper'
|
||||||
|
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- postgres_data:/var/lib/postgresql/data/
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U breccia-mapper"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
caddy_data:
|
||||||
|
caddy_config:
|
||||||
|
static_files:
|
||||||
|
media_files:
|
||||||
|
postgres_data:
|
||||||
16
deploy/deploy-docker/Caddyfile
Normal file
16
deploy/deploy-docker/Caddyfile
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
:80 :443 {
|
||||||
|
root * /srv
|
||||||
|
file_server
|
||||||
|
|
||||||
|
@proxy_paths {
|
||||||
|
not path /static/*
|
||||||
|
not path /media/*
|
||||||
|
}
|
||||||
|
|
||||||
|
reverse_proxy @proxy_paths http://server:8000
|
||||||
|
|
||||||
|
log {
|
||||||
|
output stderr
|
||||||
|
format console
|
||||||
|
}
|
||||||
|
}
|
||||||
55
deploy/deploy-docker/docker-compose.yml
Normal file
55
deploy/deploy-docker/docker-compose.yml
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
version: '3.1'
|
||||||
|
|
||||||
|
services:
|
||||||
|
server:
|
||||||
|
image: mgrove36/breccia-mapper:latest
|
||||||
|
build: .
|
||||||
|
environment:
|
||||||
|
DJANGO_DEBUG: ${DEBUG}
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
volumes:
|
||||||
|
- static_files:/app/static
|
||||||
|
- media_files:/app/media
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
|
||||||
|
caddy:
|
||||||
|
image: caddy:2
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- 80:80
|
||||||
|
- 443:443
|
||||||
|
volumes:
|
||||||
|
- ./Caddyfile:/etc/caddy/Caddyfile:z
|
||||||
|
# Caddy serves static files collected by Django
|
||||||
|
- static_files:/srv/static:ro
|
||||||
|
- media_files:/srv/media
|
||||||
|
- ./icon-192x192.png:/srv/media/icon-192x192.png:ro
|
||||||
|
- caddy_data:/data
|
||||||
|
- caddy_config:/config
|
||||||
|
depends_on:
|
||||||
|
- server
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: postgres:15.2-alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
POSTGRES_DB: 'breccia-mapper'
|
||||||
|
POSTGRES_USER: 'breccia-mapper'
|
||||||
|
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- postgres_data:/var/lib/postgresql/data/
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U breccia-mapper"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
caddy_data:
|
||||||
|
caddy_config:
|
||||||
|
static_files:
|
||||||
|
media_files:
|
||||||
|
postgres_data:
|
||||||
134
deploy/deploy-docker/example.env
Normal file
134
deploy/deploy-docker/example.env
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
# REQUIRED=Secret key
|
||||||
|
# Used to generate CSRF tokens - must never be made public
|
||||||
|
SECRET_KEY=changeme
|
||||||
|
|
||||||
|
# REQUIRED=Database password
|
||||||
|
# The password for the breccia-mapper user in the postgres database
|
||||||
|
DB_PASSWORD=changeme
|
||||||
|
|
||||||
|
# REQUIRED=Google Maps API key
|
||||||
|
# Google Maps API key to display maps of people's locations - required to enable map functionality
|
||||||
|
# Default: None
|
||||||
|
# GOOGLE_MAPS_API_KEY=None
|
||||||
|
|
||||||
|
# Debug
|
||||||
|
# Should the server run in debug mode? Provides information to users which is unsafe in production
|
||||||
|
# Default: False
|
||||||
|
DEBUG=False
|
||||||
|
|
||||||
|
# Project long name
|
||||||
|
# The project's full name.
|
||||||
|
# Default: Project Network Mapper
|
||||||
|
# PROJECT_LONG_NAME=Project Network Mapper
|
||||||
|
|
||||||
|
# Project short name
|
||||||
|
# The project's short/abbreviated name. This will also be used as the app's name when installed as PWA.
|
||||||
|
# Default: Network Mapper
|
||||||
|
# PROJECT_SHORT_NAME=Network Mapper
|
||||||
|
|
||||||
|
# Project description
|
||||||
|
# The project's description. Used when installed as a PWA.
|
||||||
|
# Default: Application to map network relationships in the organisation.
|
||||||
|
# PROJECT_DESCRIPTION=Application to map network relationships in the organisation.
|
||||||
|
|
||||||
|
# Theme color
|
||||||
|
# The project's theme color, in hex format (excluding the leading #).
|
||||||
|
# Default: 212121
|
||||||
|
# THEME_COLOR=212121
|
||||||
|
|
||||||
|
# Background color
|
||||||
|
# The project's background color, in hex format (excluding the leading #).
|
||||||
|
# Default: ffffff
|
||||||
|
# BACKGROUND_COLOR=ffffff
|
||||||
|
|
||||||
|
# Allowed hosts
|
||||||
|
# Accepted values for server header in request - protects against CSRF and CSS attacks
|
||||||
|
# Default: * if DEBUG else localhost
|
||||||
|
# ALLOWED_HOSTS=127.0.0.1,localhost,localhost.localdomain
|
||||||
|
|
||||||
|
# Site URL
|
||||||
|
# The URL the site will be deployed on. Do not include http://, https://, or a trailing slash.
|
||||||
|
# Default: localhost
|
||||||
|
# SITE_URL=localhost
|
||||||
|
|
||||||
|
# Site protocol
|
||||||
|
# The protocol the site uses. Valid options are http or https.
|
||||||
|
# Default: http
|
||||||
|
# SITE_PROTOCOL=http
|
||||||
|
|
||||||
|
# Trusted origins
|
||||||
|
# The trusted origin domains of requests - protects against CSRF and CSS attacks
|
||||||
|
# Default: '*' if DEBUG else 'http://127.0.0.1,http://localhost,http://localhost.localdomain'
|
||||||
|
# TRUSTED_ORIGINS=http://127.0.0.1,http://localhost,http://localhost.localdomain
|
||||||
|
|
||||||
|
# Database backup storage location
|
||||||
|
# Directory where database backups should be stored
|
||||||
|
# Default: .dbbackup
|
||||||
|
# DBBACKUP_STORAGE_LOCATION=.dbbackup
|
||||||
|
|
||||||
|
# Default language
|
||||||
|
# Default language - used for translation - has not been enabled
|
||||||
|
# Default: en-gb
|
||||||
|
# LANGUAGE_CODE=en-gb
|
||||||
|
|
||||||
|
# Timezone
|
||||||
|
# Default timezone
|
||||||
|
# Default: UTC
|
||||||
|
# TIME_ZONE=UTC
|
||||||
|
|
||||||
|
# Logging level
|
||||||
|
# Level of messages written to log file
|
||||||
|
# Default: INFO
|
||||||
|
# LOG_LEVEL=INFO
|
||||||
|
|
||||||
|
# Logging filename
|
||||||
|
# Path to logfile
|
||||||
|
# Default: debug.log
|
||||||
|
# LOG_FILENAME=debug.log
|
||||||
|
|
||||||
|
# Logging duration
|
||||||
|
# Number of days of logs to keep - logfile is rotated out at the end of each day
|
||||||
|
# Default: 14
|
||||||
|
# LOG_DAYS=14
|
||||||
|
|
||||||
|
# STMP host
|
||||||
|
# Hostname of SMTP server
|
||||||
|
# Default: None
|
||||||
|
# EMAIL_HOST=None
|
||||||
|
|
||||||
|
# Default from email address
|
||||||
|
# Email address from which messages are sent
|
||||||
|
# Default: None
|
||||||
|
# DEFAULT_FROM_EMAIL=None
|
||||||
|
|
||||||
|
# [DEBUG ONLY] Email file path
|
||||||
|
# Directory where emails will be stored if not using an SMTP server
|
||||||
|
# Default: mail.log
|
||||||
|
# EMAIL_FILE_PATH=mail.log
|
||||||
|
|
||||||
|
# SMTP username
|
||||||
|
# Username to authenticate with SMTP server
|
||||||
|
# Default: None
|
||||||
|
# EMAIL_HOST_USER=None
|
||||||
|
|
||||||
|
# SMTP password
|
||||||
|
# Password to authenticate with SMTP server
|
||||||
|
# Default: None
|
||||||
|
# EMAIL_HOST_PASSWORD=None
|
||||||
|
|
||||||
|
# SMTP port
|
||||||
|
# Port to access on SMTP server
|
||||||
|
# Default: 25
|
||||||
|
# EMAIL_PORT=25
|
||||||
|
|
||||||
|
# SMTP use TLS
|
||||||
|
# Use TLS to communicate with SMTP server? Usually on port 587
|
||||||
|
# Cannot be enabled at the same time as EMAIL_USE_SSL
|
||||||
|
# Default: True if EMAIL_PORT == 587 else False
|
||||||
|
# EMAIL_USE_TLS=True if EMAIL_PORT == 587 else False
|
||||||
|
|
||||||
|
# SMTP use SSL
|
||||||
|
# Use SSL to communicate with SMTP server? Usually on port 465
|
||||||
|
# Cannot be enabled at the same time as EMAIL_USE_TLS
|
||||||
|
# Default: True if EMAIL_PORT == 465 else False
|
||||||
|
# EMAIL_USE_SSL=True if EMAIL_PORT == 465 else False
|
||||||
28
deploy/deploy-vagrant/Vagrantfile
vendored
Normal file
28
deploy/deploy-vagrant/Vagrantfile
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# -*- mode: ruby -*-
|
||||||
|
# vi: set ft=ruby :
|
||||||
|
|
||||||
|
# All Vagrant configuration is done below. The "2" in Vagrant.configure
|
||||||
|
# configures the configuration version (we support older styles for
|
||||||
|
# backwards compatibility). Please don't change it unless you know what
|
||||||
|
# you're doing.
|
||||||
|
Vagrant.configure("2") do |config|
|
||||||
|
# Every Vagrant development environment requires a box. You can search for
|
||||||
|
# boxes at https://vagrantcloud.com/search.
|
||||||
|
config.vm.box = "generic/rocky8"
|
||||||
|
|
||||||
|
# Create a forwarded port mapping which allows access to a specific port
|
||||||
|
# within the machine from a port on the host machine and only allow access
|
||||||
|
# via 127.0.0.1 to disable public access
|
||||||
|
config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"
|
||||||
|
|
||||||
|
# Provision VM using Ansible playbook
|
||||||
|
config.vm.provision "ansible" do |ansible|
|
||||||
|
ansible.verbose = "v"
|
||||||
|
ansible.playbook = "playbook.yml"
|
||||||
|
ansible.host_vars = {
|
||||||
|
"default" => {
|
||||||
|
"deploy_environment" => "vagrant"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
134
deploy/deploy-vagrant/example.env
Normal file
134
deploy/deploy-vagrant/example.env
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
# REQUIRED=Secret key
|
||||||
|
# Used to generate CSRF tokens - must never be made public
|
||||||
|
SECRET_KEY=changeme
|
||||||
|
|
||||||
|
# REQUIRED=Database password
|
||||||
|
# The password for the breccia-mapper user in the postgres database
|
||||||
|
DB_PASSWORD=changeme
|
||||||
|
|
||||||
|
# REQUIRED=Google Maps API key
|
||||||
|
# Google Maps API key to display maps of people's locations - required to enable map functionality
|
||||||
|
# Default: None
|
||||||
|
# GOOGLE_MAPS_API_KEY=None
|
||||||
|
|
||||||
|
# Debug
|
||||||
|
# Should the server run in debug mode? Provides information to users which is unsafe in production
|
||||||
|
# Default: False
|
||||||
|
DEBUG=False
|
||||||
|
|
||||||
|
# Project long name
|
||||||
|
# The project's full name.
|
||||||
|
# Default: Project Network Mapper
|
||||||
|
# PROJECT_LONG_NAME=Project Network Mapper
|
||||||
|
|
||||||
|
# Project short name
|
||||||
|
# The project's short/abbreviated name. This will also be used as the app's name when installed as PWA.
|
||||||
|
# Default: Network Mapper
|
||||||
|
# PROJECT_SHORT_NAME=Network Mapper
|
||||||
|
|
||||||
|
# Project description
|
||||||
|
# The project's description. Used when installed as a PWA.
|
||||||
|
# Default: Application to map network relationships in the organisation.
|
||||||
|
# PROJECT_DESCRIPTION=Application to map network relationships in the organisation.
|
||||||
|
|
||||||
|
# Theme color
|
||||||
|
# The project's theme color, in hex format (excluding the leading #).
|
||||||
|
# Default: 212121
|
||||||
|
# THEME_COLOR=212121
|
||||||
|
|
||||||
|
# Background color
|
||||||
|
# The project's background color, in hex format (excluding the leading #).
|
||||||
|
# Default: ffffff
|
||||||
|
# BACKGROUND_COLOR=ffffff
|
||||||
|
|
||||||
|
# Allowed hosts
|
||||||
|
# Accepted values for server header in request - protects against CSRF and CSS attacks
|
||||||
|
# Default: * if DEBUG else localhost
|
||||||
|
# ALLOWED_HOSTS=127.0.0.1,localhost,localhost.localdomain
|
||||||
|
|
||||||
|
# Site URL
|
||||||
|
# The URL the site will be deployed on. Do not include http://, https://, or a trailing slash.
|
||||||
|
# Default: localhost
|
||||||
|
# SITE_URL=localhost
|
||||||
|
|
||||||
|
# Site protocol
|
||||||
|
# The protocol the site uses. Valid options are http or https.
|
||||||
|
# Default: http
|
||||||
|
# SITE_PROTOCOL=http
|
||||||
|
|
||||||
|
# Trusted origins
|
||||||
|
# The trusted origin domains of requests - protects against CSRF and CSS attacks
|
||||||
|
# Default: '*' if DEBUG else 'http://127.0.0.1,http://localhost,http://localhost.localdomain'
|
||||||
|
# TRUSTED_ORIGINS=http://127.0.0.1,http://localhost,http://localhost.localdomain
|
||||||
|
|
||||||
|
# Database backup storage location
|
||||||
|
# Directory where database backups should be stored
|
||||||
|
# Default: .dbbackup
|
||||||
|
# DBBACKUP_STORAGE_LOCATION=.dbbackup
|
||||||
|
|
||||||
|
# Default language
|
||||||
|
# Default language - used for translation - has not been enabled
|
||||||
|
# Default: en-gb
|
||||||
|
# LANGUAGE_CODE=en-gb
|
||||||
|
|
||||||
|
# Timezone
|
||||||
|
# Default timezone
|
||||||
|
# Default: UTC
|
||||||
|
# TIME_ZONE=UTC
|
||||||
|
|
||||||
|
# Logging level
|
||||||
|
# Level of messages written to log file
|
||||||
|
# Default: INFO
|
||||||
|
# LOG_LEVEL=INFO
|
||||||
|
|
||||||
|
# Logging filename
|
||||||
|
# Path to logfile
|
||||||
|
# Default: debug.log
|
||||||
|
# LOG_FILENAME=debug.log
|
||||||
|
|
||||||
|
# Logging duration
|
||||||
|
# Number of days of logs to keep - logfile is rotated out at the end of each day
|
||||||
|
# Default: 14
|
||||||
|
# LOG_DAYS=14
|
||||||
|
|
||||||
|
# STMP host
|
||||||
|
# Hostname of SMTP server
|
||||||
|
# Default: None
|
||||||
|
# EMAIL_HOST=None
|
||||||
|
|
||||||
|
# Default from email address
|
||||||
|
# Email address from which messages are sent
|
||||||
|
# Default: None
|
||||||
|
# DEFAULT_FROM_EMAIL=None
|
||||||
|
|
||||||
|
# [DEBUG ONLY] Email file path
|
||||||
|
# Directory where emails will be stored if not using an SMTP server
|
||||||
|
# Default: mail.log
|
||||||
|
# EMAIL_FILE_PATH=mail.log
|
||||||
|
|
||||||
|
# SMTP username
|
||||||
|
# Username to authenticate with SMTP server
|
||||||
|
# Default: None
|
||||||
|
# EMAIL_HOST_USER=None
|
||||||
|
|
||||||
|
# SMTP password
|
||||||
|
# Password to authenticate with SMTP server
|
||||||
|
# Default: None
|
||||||
|
# EMAIL_HOST_PASSWORD=None
|
||||||
|
|
||||||
|
# SMTP port
|
||||||
|
# Port to access on SMTP server
|
||||||
|
# Default: 25
|
||||||
|
# EMAIL_PORT=25
|
||||||
|
|
||||||
|
# SMTP use TLS
|
||||||
|
# Use TLS to communicate with SMTP server? Usually on port 587
|
||||||
|
# Cannot be enabled at the same time as EMAIL_USE_SSL
|
||||||
|
# Default: True if EMAIL_PORT == 587 else False
|
||||||
|
# EMAIL_USE_TLS=True if EMAIL_PORT == 587 else False
|
||||||
|
|
||||||
|
# SMTP use SSL
|
||||||
|
# Use SSL to communicate with SMTP server? Usually on port 465
|
||||||
|
# Cannot be enabled at the same time as EMAIL_USE_TLS
|
||||||
|
# Default: True if EMAIL_PORT == 465 else False
|
||||||
|
# EMAIL_USE_SSL=True if EMAIL_PORT == 465 else False
|
||||||
104
deploy/deploy-vagrant/playbook.yml
Normal file
104
deploy/deploy-vagrant/playbook.yml
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
---
|
||||||
|
- hosts: all
|
||||||
|
become_user: root
|
||||||
|
become_method: sudo
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
pre_tasks:
|
||||||
|
- name: Check if running under Vagrant
|
||||||
|
stat:
|
||||||
|
path: /vagrant
|
||||||
|
register: vagrant_dir
|
||||||
|
|
||||||
|
vars:
|
||||||
|
project_name: network-mapper
|
||||||
|
project_dir: /srv/{{ project_name }}
|
||||||
|
project_src_dir: "{{ project_dir }}/src"
|
||||||
|
provision_superuser: false
|
||||||
|
superuser_username: admin
|
||||||
|
superuser_password: admin
|
||||||
|
superuser_email: email@example.com
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Vagrant specific tasks
|
||||||
|
block:
|
||||||
|
- name: Add Docker repository
|
||||||
|
get_url:
|
||||||
|
url: https://download.docker.com/linux/centos/docker-ce.repo
|
||||||
|
dest: '/etc/yum.repos.d/docker-ce.repo'
|
||||||
|
when: deploy_environment is defined and deploy_environment == "vagrant"
|
||||||
|
|
||||||
|
- name: Install system dependencies
|
||||||
|
ansible.builtin.yum:
|
||||||
|
name:
|
||||||
|
- git
|
||||||
|
- docker-ce
|
||||||
|
- docker-ce-cli
|
||||||
|
- containerd.io
|
||||||
|
- docker-compose-plugin
|
||||||
|
state: present
|
||||||
|
|
||||||
|
# - name: Update system packages
|
||||||
|
# ansible.builtin.yum:
|
||||||
|
# name: '*'
|
||||||
|
# state: latest
|
||||||
|
|
||||||
|
- name: Clone / update from source repos
|
||||||
|
ansible.builtin.git:
|
||||||
|
repo: 'https://github.com/Southampton-RSG/breccia-mapper.git'
|
||||||
|
dest: '{{ project_src_dir }}'
|
||||||
|
version: dev # master
|
||||||
|
accept_hostkey: yes
|
||||||
|
|
||||||
|
- name: Copy template files
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: '{{ item }}.j2'
|
||||||
|
dest: '{{ project_dir }}/{{ item }}'
|
||||||
|
mode: 0600
|
||||||
|
loop:
|
||||||
|
- Caddyfile
|
||||||
|
- docker-compose.yml
|
||||||
|
|
||||||
|
- name: Copy settings file
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: '.env'
|
||||||
|
dest: '{{ project_dir }}/.env'
|
||||||
|
mode: 0600
|
||||||
|
|
||||||
|
- name: Copy site icon
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: 'icon-192x192.png'
|
||||||
|
dest: '{{ project_dir }}/icon-192x192.png'
|
||||||
|
mode: 0600
|
||||||
|
|
||||||
|
- name: Start Docker
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: docker
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
|
||||||
|
- name: Pull latest docker images
|
||||||
|
ansible.builtin.command:
|
||||||
|
chdir: "{{ project_dir }}"
|
||||||
|
cmd: docker compose pull {{ item }}
|
||||||
|
loop:
|
||||||
|
- caddy
|
||||||
|
- server
|
||||||
|
- db
|
||||||
|
|
||||||
|
- name: Start containers
|
||||||
|
ansible.builtin.command:
|
||||||
|
chdir: "{{ project_dir }}"
|
||||||
|
cmd: docker compose up -d
|
||||||
|
|
||||||
|
- name: Provision superuser
|
||||||
|
ansible.builtin.command:
|
||||||
|
chdir: "{{ project_dir }}"
|
||||||
|
cmd: sudo docker compose exec -it server /bin/bash -c "DJANGO_SUPERUSER_USERNAME='{{ superuser_username }}' DJANGO_SUPERUSER_PASSWORD='{{ superuser_password }}' DJANGO_SUPERUSER_EMAIL='{{ superuser_email }}' /app/manage.py createsuperuser --no-input"
|
||||||
|
when: provision_superuser
|
||||||
|
|
||||||
|
- name: Display warning about new superuser
|
||||||
|
debug:
|
||||||
|
msg:
|
||||||
|
- "[WARNING] A superuser has been provisioned with the username \"{{ superuser_username }}\" and the password that was provided. This user has unlimited access to the network mapper."
|
||||||
|
when: provision_superuser
|
||||||
16
deploy/deploy-vagrant/templates/Caddyfile.j2
Executable file
16
deploy/deploy-vagrant/templates/Caddyfile.j2
Executable file
@@ -0,0 +1,16 @@
|
|||||||
|
:80 :443 {
|
||||||
|
root * /srv
|
||||||
|
file_server
|
||||||
|
|
||||||
|
@proxy_paths {
|
||||||
|
not path /static/*
|
||||||
|
not path /media/*
|
||||||
|
}
|
||||||
|
|
||||||
|
reverse_proxy @proxy_paths http://server:8000
|
||||||
|
|
||||||
|
log {
|
||||||
|
output stderr
|
||||||
|
format console
|
||||||
|
}
|
||||||
|
}
|
||||||
57
deploy/deploy-vagrant/templates/docker-compose.yml.j2
Executable file
57
deploy/deploy-vagrant/templates/docker-compose.yml.j2
Executable file
@@ -0,0 +1,57 @@
|
|||||||
|
version: '3.1'
|
||||||
|
|
||||||
|
services:
|
||||||
|
server:
|
||||||
|
image: mgrove36/breccia-mapper:latest
|
||||||
|
build: {{ project_src_dir }}
|
||||||
|
ports:
|
||||||
|
- 8000:8000
|
||||||
|
environment:
|
||||||
|
DJANGO_DEBUG: ${DEBUG}
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
volumes:
|
||||||
|
- static_files:/app/static
|
||||||
|
- media_files:/app/media
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
|
||||||
|
caddy:
|
||||||
|
image: caddy:2
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- 80:80
|
||||||
|
- 443:443
|
||||||
|
volumes:
|
||||||
|
- ./Caddyfile:/etc/caddy/Caddyfile:z
|
||||||
|
# Caddy serves static files collected by Django
|
||||||
|
- static_files:/srv/static:ro
|
||||||
|
- media_files:/srv/media
|
||||||
|
- {{ project_dir }}/icon-192x192.png:/srv/media/icon-192x192.png:ro
|
||||||
|
- caddy_data:/data
|
||||||
|
- caddy_config:/config
|
||||||
|
depends_on:
|
||||||
|
- server
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: postgres:15.2-alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
POSTGRES_DB: 'breccia-mapper'
|
||||||
|
POSTGRES_USER: 'breccia-mapper'
|
||||||
|
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- postgres_data:/var/lib/postgresql/data/
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U breccia-mapper"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
caddy_data:
|
||||||
|
caddy_config:
|
||||||
|
static_files:
|
||||||
|
media_files:
|
||||||
|
postgres_data:
|
||||||
@@ -2,6 +2,15 @@
|
|||||||
# Used to generate CSRF tokens - must never be made public
|
# Used to generate CSRF tokens - must never be made public
|
||||||
SECRET_KEY=changeme
|
SECRET_KEY=changeme
|
||||||
|
|
||||||
|
# REQUIRED=Database password
|
||||||
|
# The password for the breccia-mapper user in the postgres database
|
||||||
|
DB_PASSWORD=changeme
|
||||||
|
|
||||||
|
# REQUIRED=Google Maps API key
|
||||||
|
# Google Maps API key to display maps of people's locations - required to enable map functionality
|
||||||
|
# Default: None
|
||||||
|
# GOOGLE_MAPS_API_KEY=None
|
||||||
|
|
||||||
# Debug
|
# Debug
|
||||||
# Should the server run in debug mode? Provides information to users which is unsafe in production
|
# Should the server run in debug mode? Provides information to users which is unsafe in production
|
||||||
# Default: False
|
# Default: False
|
||||||
@@ -123,8 +132,3 @@ DEBUG=False
|
|||||||
# Cannot be enabled at the same time as EMAIL_USE_TLS
|
# Cannot be enabled at the same time as EMAIL_USE_TLS
|
||||||
# Default: True if EMAIL_PORT == 465 else False
|
# Default: True if EMAIL_PORT == 465 else False
|
||||||
# EMAIL_USE_SSL=True if EMAIL_PORT == 465 else False
|
# EMAIL_USE_SSL=True if EMAIL_PORT == 465 else False
|
||||||
|
|
||||||
# Google Maps API key
|
|
||||||
# Google Maps API key to display maps of people's locations
|
|
||||||
# Default: None
|
|
||||||
# GOOGLE_MAPS_API_KEY=None
|
|
||||||
@@ -71,11 +71,6 @@
|
|||||||
dest: '{{ project_dir }}/icon-192x192.png'
|
dest: '{{ project_dir }}/icon-192x192.png'
|
||||||
mode: 0600
|
mode: 0600
|
||||||
|
|
||||||
- name: Create database file
|
|
||||||
ansible.builtin.file:
|
|
||||||
path: "{{ project_dir }}/db.sqlite3"
|
|
||||||
state: touch
|
|
||||||
|
|
||||||
- name: Start Docker
|
- name: Start Docker
|
||||||
ansible.builtin.systemd:
|
ansible.builtin.systemd:
|
||||||
name: docker
|
name: docker
|
||||||
@@ -89,6 +84,7 @@
|
|||||||
loop:
|
loop:
|
||||||
- caddy
|
- caddy
|
||||||
- server
|
- server
|
||||||
|
- db
|
||||||
|
|
||||||
- name: Start containers
|
- name: Start containers
|
||||||
ansible.builtin.command:
|
ansible.builtin.command:
|
||||||
|
|||||||
@@ -4,16 +4,16 @@ services:
|
|||||||
server:
|
server:
|
||||||
image: mgrove36/breccia-mapper:latest
|
image: mgrove36/breccia-mapper:latest
|
||||||
build: {{ project_src_dir }}
|
build: {{ project_src_dir }}
|
||||||
ports:
|
|
||||||
- 8000:8000
|
|
||||||
environment:
|
environment:
|
||||||
DJANGO_DEBUG: ${DEBUG}
|
DJANGO_DEBUG: ${DEBUG}
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
volumes:
|
volumes:
|
||||||
- {{ project_dir }}/db.sqlite3:/app/db.sqlite3:z
|
|
||||||
- static_files:/app/static
|
- static_files:/app/static
|
||||||
- media_files:/app/media
|
- media_files:/app/media
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
|
||||||
caddy:
|
caddy:
|
||||||
image: caddy:2
|
image: caddy:2
|
||||||
@@ -25,15 +25,31 @@ services:
|
|||||||
- ./Caddyfile:/etc/caddy/Caddyfile:z
|
- ./Caddyfile:/etc/caddy/Caddyfile:z
|
||||||
# Caddy serves static files collected by Django
|
# Caddy serves static files collected by Django
|
||||||
- static_files:/srv/static:ro
|
- static_files:/srv/static:ro
|
||||||
- media_files:/srv/media:ro
|
- media_files:/srv/media
|
||||||
- {{ project_dir }}/icon-192x192.png:/srv/media/icon-192x192.png:ro
|
- {{ project_dir }}/icon-192x192.png:/srv/media/icon-192x192.png:ro
|
||||||
- caddy_data:/data
|
- caddy_data:/data
|
||||||
- caddy_config:/config
|
- caddy_config:/config
|
||||||
depends_on:
|
depends_on:
|
||||||
- server
|
- server
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: postgres:15.2-alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
POSTGRES_DB: 'breccia-mapper'
|
||||||
|
POSTGRES_USER: 'breccia-mapper'
|
||||||
|
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- postgres_data:/var/lib/postgresql/data/
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U breccia-mapper"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
caddy_data:
|
caddy_data:
|
||||||
caddy_config:
|
caddy_config:
|
||||||
static_files:
|
static_files:
|
||||||
media_files:
|
media_files:
|
||||||
|
postgres_data:
|
||||||
|
|||||||
@@ -4,16 +4,16 @@ services:
|
|||||||
server:
|
server:
|
||||||
image: mgrove36/breccia-mapper:latest
|
image: mgrove36/breccia-mapper:latest
|
||||||
build: .
|
build: .
|
||||||
ports:
|
|
||||||
- 8000:8000
|
|
||||||
environment:
|
environment:
|
||||||
DJANGO_DEBUG: ${DEBUG}
|
DJANGO_DEBUG: ${DEBUG}
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
volumes:
|
volumes:
|
||||||
- ./db.sqlite3:/app/db.sqlite3:z
|
|
||||||
- static_files:/app/static
|
- static_files:/app/static
|
||||||
- media_files:/app/media
|
- media_files:/app/media
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
|
||||||
caddy:
|
caddy:
|
||||||
image: caddy:2
|
image: caddy:2
|
||||||
@@ -25,15 +25,31 @@ services:
|
|||||||
- ./Caddyfile:/etc/caddy/Caddyfile:z
|
- ./Caddyfile:/etc/caddy/Caddyfile:z
|
||||||
# Caddy serves static files collected by Django
|
# Caddy serves static files collected by Django
|
||||||
- static_files:/srv/static:ro
|
- static_files:/srv/static:ro
|
||||||
- media_files:/srv/media:ro
|
- media_files:/srv/media
|
||||||
- ./icon-192x192.png:/srv/media/icon-192x192.png:ro
|
- ./icon-192x192.png:/srv/media/icon-192x192.png:ro
|
||||||
- caddy_data:/data
|
- caddy_data:/data
|
||||||
- caddy_config:/config
|
- caddy_config:/config
|
||||||
depends_on:
|
depends_on:
|
||||||
- server
|
- server
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: postgres:15.2-alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
POSTGRES_DB: 'breccia-mapper'
|
||||||
|
POSTGRES_USER: 'breccia-mapper'
|
||||||
|
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- postgres_data:/var/lib/postgresql/data/
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U breccia-mapper"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
caddy_data:
|
caddy_data:
|
||||||
caddy_config:
|
caddy_config:
|
||||||
static_files:
|
static_files:
|
||||||
media_files:
|
media_files:
|
||||||
|
postgres_data:
|
||||||
|
|||||||
199
docs/source/1-deployment.md
Normal file
199
docs/source/1-deployment.md
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
# Deployment
|
||||||
|
|
||||||
|
The [BRECcIA Network Mapper](https://github.com/Southampton-RSG/breccia-mapper) can be deployed in a variety of ways, most of which utilise Docker.
|
||||||
|
Ansible deployment has been tested on RHEL7 and RHEL8.
|
||||||
|
|
||||||
|
## Choosing How to Deploy
|
||||||
|
|
||||||
|
If you are an organisation deploying the app on a server, [Ansible](#ansible) is recommended. If Ansible is not used on your server, [Docker Compose](#docker-compose) or [Vagrant](#vagrant) are recommended.
|
||||||
|
|
||||||
|
If you are an individual deploying the app on your local machine, [Docker (for individuals)](#docker-for-individuals) is recommended. However, if you are planning on making the app accessible to other people (outside your computer), we advise deploying the app on a server.
|
||||||
|
|
||||||
|
## Ansible
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
|
||||||
|
- [Ansible](https://www.ansible.com/)
|
||||||
|
|
||||||
|
:::{note}
|
||||||
|
Deployment with Ansible has been tested on RHEL7 and RHEL8, but is compatible with other Linux distributions with minor changes to the playbook (`playbook.yml`)
|
||||||
|
:::
|
||||||
|
|
||||||
|
To deploy the BRECcIA Network Mapper with Ansible:
|
||||||
|
|
||||||
|
1. Download and extract the deployment files from [the latest release](https://github.com/Southampton-RSG/breccia-mapper/releases/latest):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl https://github.com/Southampton-RSG/breccia-mapper/releases/latest/download/deploy-ansible.tar.gz | tar xzv && cd network-mapper
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Copy your logo (192x192 pixels) to `icon-192x192.png` in the `network-mapper` folder.
|
||||||
|
|
||||||
|
3. Copy `example.env` to `.env`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp example.env .env
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Edit this file as desired. Note that some variables are required, and that `True` and `False` values must have correct capitalisation.
|
||||||
|
5. Copy `inventory.example.yml` to `inventory.yml`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp inventory.example.yml inventory.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
6. Edit this file to reflect your Ansible setup:
|
||||||
|
- Use your server's hostname instead of `example.com`
|
||||||
|
7. If you would like a new superuser to be provisioned (e.g. during initial install), edit the `provision_superuser` variable in `playbook.yml` to `true`.
|
||||||
|
- Then change the `superuser_*` options below it as desired.
|
||||||
|
8. Run the Ansible playbook `playbook.yml` with this inventory file using:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible-playbook playbook.yml -i inventory.yml -K -k -u <SSH username>
|
||||||
|
```
|
||||||
|
|
||||||
|
This will ask for your SSH and sudo passwords for the server before deploying.
|
||||||
|
To redeploy updates, the same command can be run again - it's safe to redeploy on top of an existing deployment.
|
||||||
|
|
||||||
|
:::{warning}
|
||||||
|
If you changed the `provision_superuser` variable in `playbook.yml` to `true`, remember to change it back to `false`.
|
||||||
|
:::
|
||||||
|
|
||||||
|
|
||||||
|
## Docker Compose
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
|
||||||
|
- [Docker Compose](https://docs.docker.com/compose) (installed by default with most [Docker](https://docker.com/) installs)
|
||||||
|
|
||||||
|
:::{note}
|
||||||
|
Deployment with Docker has been tested on RHEL7, RHEL8, and Ubuntu 22.04 LTS
|
||||||
|
:::
|
||||||
|
|
||||||
|
To deploy the BRECcIA Network Mapper with Docker:
|
||||||
|
|
||||||
|
1. Download and extract the deployment files from [the latest release](https://github.com/Southampton-RSG/breccia-mapper/releases/latest):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl https://github.com/Southampton-RSG/releases/latest/download/deploy-docker.tar.gz | tar xzv && cd network-mapper
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Copy your logo (192x192 pixels) to `icon-192x192.png` in the `network-mapper` folder.
|
||||||
|
3. Copy `example.env` to `.env`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp example.env .env
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Edit this file as desired. Note that some variables are required, and that `True` and `False` values must have correct capitalisation.
|
||||||
|
5. Start the containers with the following command (you may need to use `sudo`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
6. If desired (e.g. on initial deployment), create a superuser by running the following, and enter their details when prompted:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose exec -it server /bin/bash -c "/app/manage.py createsuperuser"
|
||||||
|
```
|
||||||
|
|
||||||
|
:::{important}
|
||||||
|
If you don't create a superuser when you first deploy the app, you will be unable to log in.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Vagrant
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
|
||||||
|
- [Vagrant](https://www.vagrantup.com/)
|
||||||
|
- [Ansible](https://www.ansible.com/)
|
||||||
|
|
||||||
|
To deploy the BRECcIA Network Mapper with Vagrant:
|
||||||
|
|
||||||
|
1. Download and extract the deployment files from [the latest release](https://github.com/Southampton-RSG/breccia-mapper/releases/latest):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl https://github.com/Southampton-RSG/releases/latest/download/deploy-vagrant.tar.gz | tar xzv && cd network-mapper
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Copy your logo (192x192 pixels) to `icon-192x192.png` in the `network-mapper` folder.
|
||||||
|
3. Copy `example.env` to `.env`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp example.env .env
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Edit this file as desired. Note that some variables are required, and that `True` and `False` values must have correct capitalisation.
|
||||||
|
5. If you would like a new superuser to be provisioned (e.g. during initial install), edit the `provision_superuser` variable in `playbook.yml` to `true`.
|
||||||
|
- Then change the `superuser_*` options below it as desired.
|
||||||
|
6. To change where the app is accessible from, edit the `config.vm.network` line in `Vagrantfile`.
|
||||||
|
- By default, the app is accessible only from `http://localhost:8080`.
|
||||||
|
- To make it available from any IP address, replace `host: 8080, host_ip: "127.0.0.1"` with `host: 8080`.
|
||||||
|
- To change the port the app is available on, edit `host: 8080`.
|
||||||
|
- More details are available in the [Vagrant docs](https://developer.hashicorp.com/vagrant/docs/networking).
|
||||||
|
6. Start the virtual machine:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vagrant up
|
||||||
|
```
|
||||||
|
|
||||||
|
7. Deploy the Network Mapper on the virtual machine:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vagrant provision
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
:::{note}
|
||||||
|
To stop the virtual machine, run `vagrant halt` in this directory. More commands are explained in the [Vagrant docs](https://developer.hashicorp.com/vagrant/docs/cli).
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Docker (for individuals)
|
||||||
|
|
||||||
|
This is the recommended deployment method for individuals who are not planning on making the network mapper accessible to other users.
|
||||||
|
|
||||||
|
:::{warning}
|
||||||
|
The network mapper will not run with Docker on Arm-based devices. This includes devices with Apple silicon - e.g. M1 and M2 Macs.
|
||||||
|
|
||||||
|
To run it on these devices you will need to build it yourself, which requires additional knowledge of Docker.
|
||||||
|
:::
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
|
||||||
|
- [Docker Compose](https://docs.docker.com/compose) is installed and running. If you are not familiar with Docker, we recommend using [Docker Desktop](https://docs.docker.com/desktop/). Simply install and run it.
|
||||||
|
|
||||||
|
To deploy the BRECcIA Network Mapper with Docker:
|
||||||
|
|
||||||
|
1. Download `deploy-docker.zip` [from the latest release](https://github.com/Southampton-RSG/breccia-mapper/releases/latest).
|
||||||
|
2. Extract the zip file into an appropriate folder.
|
||||||
|
3. Copy your logo (192x192 pixels) to `icon-192x192.png` in the `network-mapper` folder.
|
||||||
|
4. Copy `example.env` to `.env` in this folder.
|
||||||
|
5. Edit this file as desired. Note that some variables are required, and that `True` and `False` values must have correct capitalisation.
|
||||||
|
|
||||||
|
- Variables are set with the following syntax, in this case setting the `DEBUG` variable to `False`:
|
||||||
|
|
||||||
|
```Dotenv
|
||||||
|
DEBUG=False
|
||||||
|
```
|
||||||
|
|
||||||
|
6. Open a terminal window in this folder. On Windows, do this by holding `Shift` and right clicking inside the folder; then selecting either `Open in Terminal` or `Open PowerShell window here`.
|
||||||
|
6. Start the network mapper with the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
7. If desired (e.g. on initial deployment), create a superuser by running the following, and enter their details when prompted:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose exec -it server /bin/bash -c "/app/manage.py createsuperuser"
|
||||||
|
```
|
||||||
|
|
||||||
|
Once the network mapper has been started for the first time with the above steps, it will appear in Docker Desktop (if installed). It can then be stopped/started again from here.
|
||||||
|
|
||||||
|
To stop it from the terminal, run
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose down
|
||||||
|
```
|
||||||
193
docs/source/2-configuration.md
Normal file
193
docs/source/2-configuration.md
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
# Configuration
|
||||||
|
|
||||||
|
After installing the [BRECcIA Network Mapper](https://github.com/Southampton-RSG/breccia-mapper), some configuration must be done in the web interface. You will need to log in with an admin account.
|
||||||
|
|
||||||
|
:::{note}
|
||||||
|
Admin dashboard: this is the admin section of the site, accessed by clicking `Admin` in the navigation bar at the top of the screen.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
### Activity Mediums
|
||||||
|
|
||||||
|
Each activity medium is a property of an activity - intended for storing, for example, whether the activity was face-to-face or virtual. Add an activity medium for each medium you wish to be available.
|
||||||
|
|
||||||
|
- In the admin dashboard, click `Add` next to `Activity mediums` and provide the name of the medium.
|
||||||
|
|
||||||
|
### Activity Types
|
||||||
|
|
||||||
|
Activities are categorised into types. Add an activity type for each type you wish to be available. For example: meetings, seminars, and training courses.
|
||||||
|
|
||||||
|
- In the admin dashboard, click `Add` next to `Activity types` and provide the name of the activity type.
|
||||||
|
|
||||||
|
### Activity Series
|
||||||
|
|
||||||
|
Activities in a series (e.g. a set of connected meetings or courses) can be linked together with an activity series. Activity series are created in the admin dashboard, and activities are linked to series when creating or updating the activities.
|
||||||
|
|
||||||
|
When new activity series next to be created, create them in the admin dashboard.
|
||||||
|
|
||||||
|
- In the admin dashboard, click `Add` next to `Activity series` and provide the name of the series, along with the type and medium of the activities in this series.
|
||||||
|
|
||||||
|
### Site Theme
|
||||||
|
|
||||||
|
If desired, you can adjust the site's theming through the admin dashboard. All of the below steps are optional.
|
||||||
|
|
||||||
|
- In the admin dashboard, click `Bootstrap themes` under `BOOTSTRAP_CUSTOMIZER`, then select `Default Theme`.
|
||||||
|
- Toggle rounded corners (e.g. for buttons), shadows, and gradients with the checkboxes.
|
||||||
|
- Click each colour to change it - a pop-up will appear allowing you to choose the new colour.
|
||||||
|
- Change the site's fonts by replacing the content of the `Font family base` field.
|
||||||
|
- Change the font size with the `Font size base` field.
|
||||||
|
- Change the line height with the `Line height base` field.
|
||||||
|
- Change the main background and text colours with the `Body background` and `Body color` fields respectively.
|
||||||
|
|
||||||
|
- Change the heading font by expanding the `Headings` section and replacing the content of the `Headings font family` field.
|
||||||
|
- Change the heading font weight (i.e. thickness) by expanding the `Headings` section and replacing the content of the `Headings font weight` field.
|
||||||
|
- Change the heading line height by expanding the `Headings` section and replacing the content of the `Headings line height` field.
|
||||||
|
|
||||||
|
Then click `Save`.
|
||||||
|
|
||||||
|
### Main Configuration Options
|
||||||
|
|
||||||
|
There are several general settings which must be configured. Open the admin dashboard and click `Config` under `CONSTANCE`, then configure the available settings, as explained below.
|
||||||
|
|
||||||
|
- `CONSENT_TEXT`: The text shown to users when requesting consent to use their data. This text accompanies a checkbox captioned `I have read and understood this information and consent to my data being used in this way`.
|
||||||
|
- `PERSON_LIST_HELP`: Help text to display at the top of the people list.
|
||||||
|
- `ORGANISATION_LIST_HELP`: Help text to display at the top of the organisaton list.
|
||||||
|
- `RELATIONSHIP_FORM_HELP`: Help text to display at the top of relationship forms.
|
||||||
|
- `HOMEPAGE_HEADER_IMAGE_SHRINK`: Whether the homepage header image should be shrunk to display the whole image at all times.
|
||||||
|
- `HOMEPAGE_HEADER_IMAGE`: The header image for the homepage.
|
||||||
|
- `HOMEPAGE_CARD_1_TITLE`: The title for the first card displayed on the homepage.
|
||||||
|
- `HOMEPAGE_CARD_1_DESCRIPTION`: The description for the first card displayed on the homepage.
|
||||||
|
- `HOMEPAGE_CARD_1_ICON`: The icon for the first card displayed on the homepage. Icons are FontAwesome 6 icons, which are listed [here](https://fontawesome.com/v6/search?m=free).
|
||||||
|
- `HOMEPAGE_CARD_2_TITLE`: The title for the second card displayed on the homepage.
|
||||||
|
- `HOMEPAGE_CARD_2_DESCRIPTION`: The description for the second card displayed on the homepage.
|
||||||
|
- `HOMEPAGE_CARD_2_ICON`: The icon for the second card displayed on the homepage. Icons are FontAwesome 6 icons, which are listed [here](https://fontawesome.com/v6/search?m=free).
|
||||||
|
- `HOMEPAGE_CARD_3_TITLE`: The title for the third card displayed on the homepage.
|
||||||
|
- `HOMEPAGE_CARD_3_DESCRIPTION`: The description for the third card displayed on the homepage.
|
||||||
|
- `HOMEPAGE_CARD_3_ICON`: The icon for the third card displayed on the homepage. Icons are FontAwesome 6 icons, which are listed [here](https://fontawesome.com/v6/search?m=free).
|
||||||
|
- `HOMEPAGE_ABOUT_TITLE`: The title for the about section on the homepage.
|
||||||
|
- `HOMEPAGE_ABOUT_CONTENT`: The content for the about section on the homepage. HTML is accepted.
|
||||||
|
- `HOMEPAGE_ABOUT_IMAGE`: The image for the about section on the homepage.
|
||||||
|
- `NOTICE_TEXT`: Text to be displayed in a notice banner at the top of every page.
|
||||||
|
- `NOTICE_CLASS`: CSS class to use for the background of the notice banner.
|
||||||
|
- `PARENT_PROJECT_NAME`: The name of the project's parent project, if one exists.
|
||||||
|
- `PROJECT_LEAD`: The project's lead person, organisation, or similar.
|
||||||
|
- `PROJECT_TAGLINE`: The project's tagline.
|
||||||
|
- `ALLOW_SIGNUPS`: Whether new users should be able to sign themselves up through the site. This is useful for minimising the number of users that must be manually created, and it is recommended that this feature is disabled once all users have created their accounts.
|
||||||
|
- `ENABLE_GOOGLE_LOGIN`: Whether login through Google should be enabled. Only enable this if Google login has been configured. See [Google login](#google).
|
||||||
|
- `ENABLE_MICROSOFT_LOGIN`: Whether login through Microsoft should be enabled. Only enable this if Microsoft login has been configured. See [Microsoft login](#microsoft).
|
||||||
|
|
||||||
|
Then click `Save`.
|
||||||
|
|
||||||
|
### Questions
|
||||||
|
|
||||||
|
There are several types of questions, but they all have the same set of information stored in them:
|
||||||
|
|
||||||
|
- `Version`: The version of the question - this should be incremented when the question is altered.
|
||||||
|
- `Text`: The main text of the question.
|
||||||
|
- `Filter text`: Each question appears as a filter on the `Network` page. This is alternative text to replace the full question as the filter title. If left blank, the main text of the question will be used.
|
||||||
|
- `Help text`: Help text shown below the question when people enter their answer.
|
||||||
|
- `Answer is public`: Whether answers to this question should be considered public.
|
||||||
|
- `Is multiple choice`: Whether users should only be allowed to select multiple options, instead of just one.
|
||||||
|
- `Hardcoded field`: The name of the hardcoded field that the question relates to. This is not applicable for non-preset questions (i.e. ones that you create).
|
||||||
|
- `Allow free text`: Whether users should be allowed to enter their own text in addition to choosing an available option. When a user enters free text, a new option will be created with their input.
|
||||||
|
- `Order`: The priority order for the question to be displayed in. Lower priority questions will be displayed earlier in the list of questions.
|
||||||
|
- Question choices
|
||||||
|
- `Text`: The main text of the option.
|
||||||
|
- `Order`: The priority order for the option to be displayed in. Lower priority options will be displayed earlier in the list of options.
|
||||||
|
- `Is negative response`: Only applicable for relationship questions. Whether the option indicates the relationship is of the lowest level of closeness. This allows automatic population of questions if the relationship being reported is not at all close. All options marked as negative responses will be selected when this button is pressed.
|
||||||
|
- `Delete?`: Whether the option should be deleted when the question is saved.
|
||||||
|
|
||||||
|
There are various types of questions, which can be added by clicking `Add` next to the appropriate section in the admin dashboard:
|
||||||
|
|
||||||
|
- Organisation questions: Questions that are shown when creating an organisation or updating its details.
|
||||||
|
- Organisation relationship questions: Questions that are shown when reporting a relationship with an organisation.
|
||||||
|
- Person questions: Questions that are shown when creating a person or updating their details.
|
||||||
|
- Relationship questions: Questions that are shown when reporting a relationship with a person.
|
||||||
|
|
||||||
|
### Existing Questions
|
||||||
|
|
||||||
|
Some "person questions" (i.e. questions about people) are preset, but require answers to be provided.
|
||||||
|
|
||||||
|
1. In the admin dashboard, click `Person questions` under `PEOPLE`, then select each of the following questions in turn:
|
||||||
|
|
||||||
|
- Disciplines
|
||||||
|
- Research theme affiliation
|
||||||
|
- Role
|
||||||
|
|
||||||
|
2. For each question, provide a set of possible answers as per the instructions [above](#questions).
|
||||||
|
|
||||||
|
:::{note}
|
||||||
|
At least one organisation must also exist for people to be able to create their profiles (unless the organisation question is removed). To create an organisation follow the instructions [below](#organisations).
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Organisations
|
||||||
|
|
||||||
|
Organisations are created through the main site (not the admin dashboard).
|
||||||
|
|
||||||
|
1. Click `Organisations` in the navigation bar at the top of the screen.
|
||||||
|
2. Click `New Organisation` at the top of the page.
|
||||||
|
2. Answer the questions shown.
|
||||||
|
4. Finally click `Submit`.
|
||||||
|
|
||||||
|
### People
|
||||||
|
|
||||||
|
:::{note}
|
||||||
|
When a `Person` is created for a user who does not have an account, an anonymous account is created for them - with login disabled and a random username (starting `autogen_`). This allows administrators to edit their details on their behalf. You should not delete these users unless you wish to delete all data relating to that person.
|
||||||
|
:::
|
||||||
|
|
||||||
|
People are created through the main site (not the admin dashboard). People should only be created when it is known that the person will not have a login of their own to the site - e.g. for researchers logging data for multiple individuals.
|
||||||
|
|
||||||
|
1. Click `People` in the navigation bar at the top of the screen.
|
||||||
|
2. Click `New Person` at the top of the page.
|
||||||
|
2. Answer the questions shown.
|
||||||
|
4. Finally click `Submit`.
|
||||||
|
|
||||||
|
## Federated Login
|
||||||
|
|
||||||
|
Federated login is supported for Google an Microsoft accounts, and can be set up through the `SOCIAL ACCOUNTS` section of the admin dashboard.
|
||||||
|
|
||||||
|
### Google
|
||||||
|
|
||||||
|
You will first need to create an OAuth application in Google Cloud Platform. You can do this by following [Google's guide](https://support.google.com/cloud/answer/6158849). The redirect URL is `[your-site-url]/accounts/google/login/callback/`.
|
||||||
|
|
||||||
|
Then:
|
||||||
|
|
||||||
|
- In the admin dashboard, click `Add` next to `Social applications`.
|
||||||
|
- Select `Google` as the provider.
|
||||||
|
- Enter `Google` as the name.
|
||||||
|
- Enter the client ID from Google in the `Client id` field.
|
||||||
|
- Enter the client secret from Google in the `Secret key` field.
|
||||||
|
- Leave the `Key` field blank.
|
||||||
|
- Click `Choose all` under the `Available sites` box, to enable Google login on this site.
|
||||||
|
- Click `Save`.
|
||||||
|
|
||||||
|
Then enable Google login with the `ENABLE_GOOGLE_LOGIN` option in the `Config` section of the admin dashboard, as per [these instructions](#main-configuration-options).
|
||||||
|
|
||||||
|
### Microsoft
|
||||||
|
|
||||||
|
You will first need to create an OAuth application in Azure Active Directory. You can do this by following [Microsoft's guide](https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app). The redirect URL is `[your-site-url]/accounts/microsoft/login/callback/`. You will also need to add a client secret.
|
||||||
|
|
||||||
|
Then:
|
||||||
|
|
||||||
|
- In the admin dashboard, click `Add` next to `Social applications`.
|
||||||
|
- Select `Microsoft Graph` as the provider.
|
||||||
|
- Enter `Microsoft` as the name.
|
||||||
|
- Enter the `Application (client) ID` from Azure in the `Client id` field. This is obtained from the `Overview` page and is different to the `Secret ID`.
|
||||||
|
- Enter the client secret value from Google in the `Secret key` field.
|
||||||
|
- Leave the `Key` field blank.
|
||||||
|
- Click `Choose all` under the `Available sites` box, to enable Google login on this site.
|
||||||
|
- Click `Save`.
|
||||||
|
|
||||||
|
Then enable Microsoft login with the `ENABLE_MICROSOFT_LOGIN` option in the `Config` section of the admin dashboard, as per [these instructions](#main-configuration-options).
|
||||||
|
|
||||||
|
(inviting_users)=
|
||||||
|
## Inviting Users
|
||||||
|
|
||||||
|
In the admin dashboard, click `Add` next to `Users`. Choose a username for them, enter their email address, and enter a temporary password. It does not matter what this password is, and you do not need to remember or store it, as the new user is automatically sent an email welcoming them to the platform and providing instructions for how to reset their password.
|
||||||
|
|
||||||
|
If the user you wish to invite has already had a `Person` created for them, they will already have an account with login disabled and a random username (starting `autogen_`). To find this account, go to `People` (in the `PEOPLE` section) in the admin dashboard and select the appropriate person. Then click the blue eye icon next to the `User` field.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
This will take you to the user, and you can then change their username and add a first name, last name, and email address. Note that a welcome email will not be sent to the user in this case, so you will have to let them know that their account is active and what their username is. They can use the *forgot password* option when logging in to set their password.
|
||||||
74
docs/source/3-admin-usage.md
Normal file
74
docs/source/3-admin-usage.md
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
# Admin Usage
|
||||||
|
|
||||||
|
You will need to log in with an administrator account to perform these actions.
|
||||||
|
|
||||||
|
:::{note}
|
||||||
|
Admin dashboard: this is the admin section of the site, accessed by clicking `Admin` in the navigation bar at the top of the screen.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Inviting Users
|
||||||
|
|
||||||
|
Please see [Configuration](inviting_users).
|
||||||
|
|
||||||
|
## Deleting Users
|
||||||
|
|
||||||
|
If you wish to permanently delete a user and their data:
|
||||||
|
|
||||||
|
1. Open the admin dashboard and click `Users`, in the `PEOPLE` section.
|
||||||
|
2. Locate and click the user you wish to delete.
|
||||||
|
3. Scroll to the bottom of the page and click `Delete`.
|
||||||
|
|
||||||
|
## Disable Login for a User
|
||||||
|
|
||||||
|
If you wish to disable login for a user but retain their data (relationships and personal details):
|
||||||
|
|
||||||
|
1. Open the admin dashboard and click `Users`, in the `PEOPLE` section.
|
||||||
|
2. Locate and click the user you wish to delete.
|
||||||
|
3. Under `Permissions`, disable `Active`.
|
||||||
|
4. Scroll to the bottom and click `Save`.
|
||||||
|
|
||||||
|
To allow the user to log in again, perform the same actions but enable the `Active` option.
|
||||||
|
|
||||||
|
## Promoting a User to Administrator
|
||||||
|
|
||||||
|
The user you wish to make an administrator must already exist. Then:
|
||||||
|
|
||||||
|
1. Open the admin dashboard and click `Users`, in the `PEOPLE` section.
|
||||||
|
2. Locate and click the user you wish to delete.
|
||||||
|
3. Under `Permissions`, enable `Staff status` and `Superuser status`.
|
||||||
|
4. Scroll to the bottom and click `Save`.
|
||||||
|
|
||||||
|
## Edit an Activity
|
||||||
|
|
||||||
|
1. Open the admin dashboard and click `Activities`, in the `ACTIVITIES` section.
|
||||||
|
2. Locate and click the activity you wish to update.
|
||||||
|
3. Update the fields appropriately.
|
||||||
|
4. Finally click `Save`.
|
||||||
|
|
||||||
|
## View a Map of People and Organisations
|
||||||
|
|
||||||
|
:::{note}
|
||||||
|
This page is only available to administrators.
|
||||||
|
:::
|
||||||
|
|
||||||
|
To view an interactive map showing people and organisations that have reported their locations, click `Map` in the navigation bar at the top of the screen. You can toggle the visibility of people and organisations with the buttons at the top of the page.
|
||||||
|
|
||||||
|
`Person` nodes on the map have the same colour as the buttons at the top of the page. Nodes can be clicked to show the name of the person or organisation they represent, and these in turn can be clicked to view the person's or organisation's profile.
|
||||||
|
|
||||||
|
## View a Graph of the Network
|
||||||
|
|
||||||
|
:::{note}
|
||||||
|
This page is only available to administrators.
|
||||||
|
:::
|
||||||
|
|
||||||
|
The network mapper provides an interface to view the network as a graph. To access it, click `Network` in the navigation bar at the top of the screen. This graph can be customised with various filters as shown on the page. Setting the date will show the state of the network as it was on the given date. People and organisations can be anonymised, organisations can be hidden, and the graph can be downloaded as an image. These options are all available as buttons on the page.
|
||||||
|
|
||||||
|
The graph can also be manipulated with the mouse.
|
||||||
|
|
||||||
|
## Export Data
|
||||||
|
|
||||||
|
:::{note}
|
||||||
|
This page is only available to administrators.
|
||||||
|
:::
|
||||||
|
|
||||||
|
All data relating to the network can be exported as CSV files. To do this, click `Export` in the navigation bar at the top of the screen, then click `Export` next to the data you wish to export. This can then be manipulated as a spreadsheet or with a tool like R to perform more complex data analysis than is available natively in the network mapper.
|
||||||
92
docs/source/4-general-usage.md
Normal file
92
docs/source/4-general-usage.md
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
# General Usage
|
||||||
|
|
||||||
|
## Create Your Profile
|
||||||
|
|
||||||
|
Until you have created your profile, you will be prompted to do so. You cannot add relationships until this has been done. To create your profile:
|
||||||
|
|
||||||
|
1. Click `Profile` in the banner at the top of the screen.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
2. Fill in your name and continue to the next step.
|
||||||
|
3. Provide consent for your data to be stored and continue to the next step.
|
||||||
|
4. Fill in the questions shown, and find your location on the map at the bottom of the page (if available). Click your location to select it.
|
||||||
|
5. Click `Save`.
|
||||||
|
|
||||||
|
## Update Your Profile
|
||||||
|
|
||||||
|
Click `Profile` in the navigation bar at the top of the screen. If you have not yet provided consent for your data to be stored, you will first be asked for this. You will then be presented with your profile.
|
||||||
|
|
||||||
|
1. Click `Update`
|
||||||
|
2. Update your answers to the questions, and optionally update your location on the map at the bottom of the page (if available). Click your location to select it.
|
||||||
|
3. Click `Save`.
|
||||||
|
|
||||||
|
## Add a Relationship
|
||||||
|
|
||||||
|
1. Click `People` in the navigation bar at the top of the screen.
|
||||||
|
2. Locate the person you wish to record a relationship with and click `Add Relationship` next to their name.
|
||||||
|
3. If you have an existing but very limited relationship with this person, you can click the `Autofill` button at the top of the page to automatically fill in appropriate responses. This will default your relationship to the lowest level of closeness. Otherwise, fill in the listed questions.
|
||||||
|
4. Click `Submit`.
|
||||||
|
|
||||||
|
|
||||||
|
## Update a Relationship
|
||||||
|
|
||||||
|
1. Click `People` in the navigation bar at the top of the screen.
|
||||||
|
2. Locate the person you wish to update your relationship with and click `Update Relationship` next to their name.
|
||||||
|
3. If you have an existing but very limited relationship with this person, you can click the `Autofill` button at the top of the page to automatically fill in appropriate responses. This will default your relationship to the lowest level of closeness. Otherwise, fill in the listed questions.
|
||||||
|
4. Click `Submit`.
|
||||||
|
|
||||||
|
## End a Relationship
|
||||||
|
|
||||||
|
1. Click `People` in the navigation bar at the top of the screen.
|
||||||
|
2. Locate the person you wish to record a relationship with and click `Profile` next to their name.
|
||||||
|
4. Click `End Relationship` at the top of the page.
|
||||||
|
|
||||||
|
## Create an Activity
|
||||||
|
|
||||||
|
1. Click `Activities` in the navigation bar at the top of the screen.
|
||||||
|
2. Click `New Activity` at the top of the page.
|
||||||
|
2. Answer the questions shown.
|
||||||
|
4. Click `Submit`.
|
||||||
|
|
||||||
|
:::{note}
|
||||||
|
Once an ativity has been created, it can only be edited by administrators.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Record Activity Attendance
|
||||||
|
|
||||||
|
Once an activity has been created, users should record their attendance.
|
||||||
|
|
||||||
|
1. Click `Activities` in the navigation bar at the top of the screen.
|
||||||
|
2. Locate the activity you wish to record attendance for and click `Details` next to its name.
|
||||||
|
3. At the top of the page, click `Attend`.
|
||||||
|
|
||||||
|
## Cancel Activity Attendance
|
||||||
|
|
||||||
|
Once an activity has been created, users should record their attendance. They can also remove their attendance after previously registering it.
|
||||||
|
|
||||||
|
1. Click `Activities` in the navigation bar at the top of the screen.
|
||||||
|
2. Locate the activity you wish to record attendance for and click `Details` next to its name.
|
||||||
|
3. At the top of the page, click `Cancel Attendance`.
|
||||||
|
|
||||||
|
## Manage Your Account Details
|
||||||
|
|
||||||
|
To manage your account details, click your username in the top right corner of the screen, next to the `Log Out` button.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Alternatively, you can manage your account by going to your profile (click `Profile` in the navigation bar at the top of the screen), then clicking `Account Details`.
|
||||||
|
|
||||||
|
## Enable Login With Google or Microsoft
|
||||||
|
|
||||||
|
1. Open your account details by following [the steps above](#manage-your-account-details).
|
||||||
|
2. Under `Federated Login`, click `Manage`.
|
||||||
|
3. Click `Google` or `Microsoft` to link your account.
|
||||||
|
|
||||||
|
|
||||||
|
## Remove a Linked Google or Microsoft Account
|
||||||
|
|
||||||
|
1. Open your account details by following [the steps above](#manage-your-account-details).
|
||||||
|
2. Under `Federated Login`, click `Manage`.
|
||||||
|
3. Under `Account Connections`, click the radius button next to the account you wish to remove.
|
||||||
|
4. Click `Remove`.
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
project = 'BRECcIA Network Mapper'
|
project = 'BRECcIA Network Mapper'
|
||||||
copyright = 'Matthew Grove, University of Southampton'
|
copyright = 'Matthew Grove, University of Southampton'
|
||||||
author = 'Matthew Grove'
|
author = 'Matthew Grove'
|
||||||
release = '1.1'
|
release = '2.0.0'
|
||||||
|
|
||||||
# -- General configuration ---------------------------------------------------
|
# -- General configuration ---------------------------------------------------
|
||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
||||||
|
|||||||
@@ -1,186 +0,0 @@
|
|||||||
|
|
||||||
The BRECcIA Network Mapper can be deployed in a variety of ways, most of which utilise Docker.
|
|
||||||
Ansible deployment has been tested on RHEL7 and RHEL8.
|
|
||||||
|
|
||||||
|
|
||||||
# Ansible
|
|
||||||
|
|
||||||
Prerequisites:
|
|
||||||
|
|
||||||
- [Ansible](https://www.ansible.com/)
|
|
||||||
|
|
||||||
:::{note}
|
|
||||||
Deployment with Ansible has been tested on RHEL7 and RHEL8, but is compatible with other Linux distributions with minor changes to the playbook (`deploy/playbook.yml`)
|
|
||||||
:::
|
|
||||||
|
|
||||||
To deploy the BRECcIA Network Mapper with Ansible:
|
|
||||||
|
|
||||||
<!-- -------------------------------------------------------
|
|
||||||
NOTES
|
|
||||||
pull deploy folder only
|
|
||||||
navigate to folder
|
|
||||||
copy icon to icon-192x192.png in folder
|
|
||||||
copy example.env to .env and edit
|
|
||||||
copy inventory.example.yml to inventory.yml and edit
|
|
||||||
edit playbook if superuser desired
|
|
||||||
run playbook
|
|
||||||
set provision_superuser to false if was changed
|
|
||||||
------------------------------------------------------- -->
|
|
||||||
|
|
||||||
1. Download and extract the deployment files from [the latest release](https://github.com/Southampton-RSG/breccia-mapper/releases/latest):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl https://github.com/Southampton-RSG/breccia-mapper/releases/latest/download/deploy-ansible.tar | tar xzv && cd deploy-ansible
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Copy your logo (192x192 pixels) to `icon-192x192.png` in this folder.
|
|
||||||
|
|
||||||
3. Copy `example.env` to `.env`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cp example.env .env
|
|
||||||
```
|
|
||||||
|
|
||||||
4. Edit this file as desired. Note that some variables are required.
|
|
||||||
5. Copy `inventory.example.yml` to `inventory.yml`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cp inventory.example.yml inventory.yml
|
|
||||||
```
|
|
||||||
|
|
||||||
6. Edit this file to reflect your Ansible setup:
|
|
||||||
- Use your server's hostname instead of `example.com`
|
|
||||||
7. If you would like a new superuser to be provisioned (e.g. during initial install), edit the `provision_superuser` variable in `playbook.yml` to `true`.
|
|
||||||
- Then change the `superuser_*` options below it as desired.
|
|
||||||
8. Run the Ansible playbook `playbook.yml` with this inventory file using:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ansible-playbook playbook.yml -i inventory.yml -K -k -u <SSH username>
|
|
||||||
```
|
|
||||||
|
|
||||||
This will ask for your SSH and sudo passwords for the server before deploying.
|
|
||||||
To redeploy updates, the same command can be run again - it's safe to redeploy on top of an existing deployment.
|
|
||||||
|
|
||||||
:::{warning}
|
|
||||||
If you changed the `provision_superuser` variable in `playbook.yml` to `true`, remember to change it back to `false`.
|
|
||||||
:::
|
|
||||||
|
|
||||||
|
|
||||||
# Docker Compose
|
|
||||||
|
|
||||||
Prerequisites:
|
|
||||||
|
|
||||||
- [Docker Compose](https://docs.docker.com/compose) (installed by default with most [Docker](https://docker.com/) installs)
|
|
||||||
|
|
||||||
:::{note}
|
|
||||||
Deployment with Docker has been tested on RHEL7, RHEL8, and Ubuntu 22.04 LTS
|
|
||||||
:::
|
|
||||||
|
|
||||||
<!-- -------------------------------------------------------
|
|
||||||
NOTES
|
|
||||||
create folder
|
|
||||||
pull docker compose file and example.env only
|
|
||||||
copy icon to icon-192x192.png in folder
|
|
||||||
copy example.env to .env and edit
|
|
||||||
touch db file? (is this needed?)
|
|
||||||
run docker compose up -d
|
|
||||||
create superuser if desired
|
|
||||||
------------------------------------------------------- -->
|
|
||||||
|
|
||||||
To deploy the BRECcIA Network Mapper with Docker:
|
|
||||||
|
|
||||||
1. Download and extract the deployment files from [the latest release](https://github.com/Southampton-RSG/breccia-mapper/releases/latest):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl https://github.com/mgrove36/Southampton-RSG/releases/latest/download/deploy-docker.tar | tar xzv && cd deploy-docker
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Copy your logo (192x192 pixels) to `icon-192x192.png` in this folder.
|
|
||||||
3. Copy `example.env` to `.env`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cp example.env .env
|
|
||||||
```
|
|
||||||
|
|
||||||
4. Edit this file as desired. Note that some variables are required.
|
|
||||||
3. Create the database using:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
touch db.sqlite3
|
|
||||||
```
|
|
||||||
|
|
||||||
5. Start the containers with the following command (you may need to use `sudo`):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
6. If desired (e.g. on initial deployment), create a superuser by running the following, and enter their details when prompted:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker compose exec -it server /bin/bash -c "/app/manage.py createsuperuser"
|
|
||||||
```
|
|
||||||
|
|
||||||
:::{important}
|
|
||||||
If you don't create a superuser when you first deploy the app, you will be unable to log in.
|
|
||||||
:::
|
|
||||||
|
|
||||||
# Vagrant
|
|
||||||
|
|
||||||
Prerequisites:
|
|
||||||
|
|
||||||
- [Vagrant](https://www.vagrantup.com/)
|
|
||||||
- [Ansible](https://www.ansible.com/)
|
|
||||||
|
|
||||||
<!-- -------------------------------------------------------
|
|
||||||
NOTES
|
|
||||||
pull deploy folder only
|
|
||||||
navigate to folder
|
|
||||||
copy icon to icon-192x192.png in folder
|
|
||||||
copy example.env to .env and edit
|
|
||||||
edit playbook if superuser desired
|
|
||||||
run vagrant up and/or vagrant provision
|
|
||||||
set provision_superuser to false if was changed
|
|
||||||
------------------------------------------------------- -->
|
|
||||||
|
|
||||||
To deploy the BRECcIA Network Mapper with Vagrant:
|
|
||||||
|
|
||||||
1. Download and extract the deployment files from [the latest release](https://github.com/Southampton-RSG/breccia-mapper/releases/latest):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl https://github.com/mgrove36/Southampton-RSG/releases/latest/download/deploy-vagrant.tar | tar xzv && cd deploy-vagrant
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Copy your logo (192x192 pixels) to `icon-192x192.png` in this folder.
|
|
||||||
3. Copy `example.env` to `.env`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cp example.env .env
|
|
||||||
```
|
|
||||||
|
|
||||||
4. Edit this file as desired. Note that some variables are required.
|
|
||||||
5. If you would like a new superuser to be provisioned (e.g. during initial install), edit the `provision_superuser` variable in `playbook.yml` to `true`.
|
|
||||||
- Then change the `superuser_*` options below it as desired.
|
|
||||||
6. To change where the app is accessible from, edit the `config.vm.network` line in `Vagrantfile`.
|
|
||||||
- By default, the app is accessible only from `http://localhost:8080`.
|
|
||||||
- To make it available from any IP address, replace `host: 8080, host_ip: "127.0.0.1"` with `host: 8080`.
|
|
||||||
- To change the port the app is available on, edit `host: 8080`.
|
|
||||||
- More details are available in the [Vagrant docs](https://developer.hashicorp.com/vagrant/docs/networking).
|
|
||||||
6. Start the virtual machine:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
vagrant up
|
|
||||||
```
|
|
||||||
|
|
||||||
7. Deploy the Network Mapper on the virtual machine:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
vagrant provision
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
:::{note}
|
|
||||||
To stop the virtual machine, run `vagrant halt` in this directory. More commands are explained in the [Vagrant docs](https://www.vagrantup.com/docs/cli).
|
|
||||||
:::
|
|
||||||
|
|
||||||
<!-- # Build From Source -->
|
|
||||||
BIN
docs/source/images/2-person-user.png
Normal file
BIN
docs/source/images/2-person-user.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.7 KiB |
BIN
docs/source/images/4-open-account-details.png
Normal file
BIN
docs/source/images/4-open-account-details.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
BIN
docs/source/images/4-profile-banner.png
Normal file
BIN
docs/source/images/4-profile-banner.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.5 KiB |
@@ -1,13 +1,13 @@
|
|||||||
# BRECcIA Network Mapper documentation
|
# BRECcIA Network Mapper documentation
|
||||||
|
|
||||||
The BRECcIA Network Mapper is a web app designed to track and quantify personnel networks & relationships - primarily developed for use in research projects. It is designed for global use across many different organisations involved in a single project, and has been utilised as part of [BRECcIA](https://gcrf-breccia.com) itself.
|
[](https://github.com/Southampton-RSG/breccia-mapper/releases/latest)
|
||||||
|
|
||||||
|
The BRECcIA Network Mapper [(view on GitHub)](https://github.com/Southampton-RSG/breccia-mapper) is a web app designed to track and quantify personnel networks & relationships - primarily developed for use in research projects. It is designed for global use across many different organisations involved in a single project, and has been utilised as part of [BRECcIA](https://gcrf-breccia.com) itself.
|
||||||
|
|
||||||
|
It can be deployed by individuals or organisations, and supports login with username/password, Google, and Microsoft.
|
||||||
|
|
||||||
This work was funded through the "Building REsearch Capacity for sustainable water and food security In drylands of sub-saharan Africa" (BRECcIA) project which is supported by UK Research and Innovation as part of the Global Challenges Research Fund, grant number NE/P021093/1.
|
This work was funded through the "Building REsearch Capacity for sustainable water and food security In drylands of sub-saharan Africa" (BRECcIA) project which is supported by UK Research and Innovation as part of the Global Challenges Research Fund, grant number NE/P021093/1.
|
||||||
|
|
||||||
:::{note}
|
|
||||||
This project is still under development until April 2023.
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Contents
|
## Contents
|
||||||
|
|
||||||
```{toctree}
|
```{toctree}
|
||||||
|
|||||||
@@ -3,6 +3,9 @@
|
|||||||
set -eo pipefail
|
set -eo pipefail
|
||||||
|
|
||||||
python manage.py migrate
|
python manage.py migrate
|
||||||
|
echo "[{\"model\": \"sites.site\",\"pk\": 1,\"fields\": { \"domain\": \"${SITE_URL}\", \"name\": \"${PROJECT_SHORT_NAME}\" }}]" | python manage.py loaddata --format=json -
|
||||||
|
python manage.py selectiveloaddata breccia_mapper/fixtures/bootstrap_customizer_theme.json
|
||||||
|
python manage.py loaddata --format=json bootstrap_customizer_sitetheme
|
||||||
python manage.py collectstatic --no-input
|
python manage.py collectstatic --no-input
|
||||||
|
|
||||||
exec "$@"
|
exec "$@"
|
||||||
|
|||||||
@@ -1,21 +1,16 @@
|
|||||||
import csv
|
import csv
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from django.contrib.auth.mixins import UserPassesTestMixin
|
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
from django.views.generic.list import BaseListView
|
from django.views.generic.list import BaseListView
|
||||||
|
from breccia_mapper.views import UserIsStaffMixin
|
||||||
|
|
||||||
|
|
||||||
class QuotedCsv(csv.excel):
|
class QuotedCsv(csv.excel):
|
||||||
quoting = csv.QUOTE_NONNUMERIC
|
quoting = csv.QUOTE_NONNUMERIC
|
||||||
|
|
||||||
|
|
||||||
class UserIsStaffMixin(UserPassesTestMixin):
|
|
||||||
def test_func(self) -> typing.Optional[bool]:
|
|
||||||
return self.request.user.is_staff
|
|
||||||
|
|
||||||
|
|
||||||
class CsvExportView(UserIsStaffMixin, BaseListView):
|
class CsvExportView(UserIsStaffMixin, BaseListView):
|
||||||
model = None
|
model = None
|
||||||
serializer_class = None
|
serializer_class = None
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
"created": "2020-04-27T12:13:30.448Z",
|
"created": "2020-04-27T12:13:30.448Z",
|
||||||
"last_updated": "2020-04-27T14:45:27.152Z",
|
"last_updated": "2020-04-27T14:45:27.152Z",
|
||||||
"subject": "Welcome to {{settings.PROJECT_LONG_NAME}}",
|
"subject": "Welcome to {{settings.PROJECT_LONG_NAME}}",
|
||||||
"content": "Dear user,\r\n\r\nWelcome to {{ settings.PROJECT_LONG_NAME }}. You can set your password at {{ settings.SITE_PROTOCOL }}://{{ settings.SITE_URL }}/password_reset/.\r\n\r\nYour username is {{ user.username }}.\r\nThanks,\r\n\r\nThe {{ settings.PROJECT_SHORT_NAME }} team",
|
"content": "{% include 'account/email/email_account_creation_message.txt' %}",
|
||||||
"html_content": "<h1>{{ settings.PROJECT_LONG_NAME }}</h1><br/><p>Dear user,</p><br/><p>Welcome to {{ settings.PROJECT_LONG_NAME }}. You can set your password <a href='{{ settings.SITE_PROTOCOL }}://{{ settings.SITE_URL }}/password_reset/'>here</a>.</p><p>Your username is {{ user.username }}.</p><br/><p>Thanks,</p><p>The {{ settings.PROJECT_SHORT_NAME }} team</p>",
|
"html_content": "{% include 'account/email/email_account_creation_message.html' %}",
|
||||||
"language": "",
|
"language": "",
|
||||||
"default_template": null
|
"default_template": null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ class PersonAnswerSetForm(forms.ModelForm, DynamicAnswerSetBase):
|
|||||||
'project_started_date':
|
'project_started_date':
|
||||||
f'Date started on the {config.PARENT_PROJECT_NAME} project',
|
f'Date started on the {config.PARENT_PROJECT_NAME} project',
|
||||||
'external_organisations':
|
'external_organisations':
|
||||||
'Please list the main organisations external to BRECcIA work that you have been working with since 1st January 2019 that are involved in food/water security in African dryland regions'
|
'Which external organisations do you work with that are involved in a related field/industry?'
|
||||||
}
|
}
|
||||||
help_texts = {
|
help_texts = {
|
||||||
'organisation_started_date':
|
'organisation_started_date':
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user