reupload commit

This commit is contained in:
Nico 2022-02-19 20:16:53 +01:00
commit f98e66f9fe
92 changed files with 9874 additions and 0 deletions

48
.gitignore vendored Normal file
View File

@ -0,0 +1,48 @@
db.sqlite3
.env
# vs code
.vscode
.tx
############################
# Node
############################
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Dependency directories
node_modules
# Optional npm cache directory
.npm
# Yarn Integrity file
.yarn-integrity
############################
# OS X
############################
.DS_Store
.AppleDouble
.LSOverride
Icon
.Spotlight-V100
.Trashes
._*
############################
# Windows
############################
Thumbs.db
ehthumbs.db
Desktop.ini
$RECYCLE.BIN/
*.cab
*.msi
*.msm
*.msp

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 Bastian Greshake Tzovaras
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

16
Pipfile Normal file
View File

@ -0,0 +1,16 @@
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
[packages]
django = "*"
django-open-humans = "*"
django-heroku = "*"
gunicorn = "*"
ipython = "*"
[requires]
python_version = "3.6"

274
Pipfile.lock generated Normal file
View File

@ -0,0 +1,274 @@
{
"_meta": {
"hash": {
"sha256": "73f95eab65c4ba41b6746ad892f9cd561ffd9d6c952979dc6daf342b697c1f4d"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.6"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"arrow": {
"hashes": [
"sha256:a24c1de90850f6fb2033fd6bf8a11f281e84cb54825e5eabdda219e673b52aac",
"sha256:eb5d339f00072cc297d7de252a2e75f272085d1231a3723f1026d1fa91367118"
],
"version": "==0.15.6"
},
"asgiref": {
"hashes": [
"sha256:8036f90603c54e93521e5777b2b9a39ba1bad05773fcf2d208f0299d1df58ce5",
"sha256:9ca8b952a0a9afa61d30aa6d3d9b570bb3fd6bafcf7ec9e6bed43b936133db1c"
],
"version": "==3.2.7"
},
"backcall": {
"hashes": [
"sha256:38ecd85be2c1e78f77fd91700c76e14667dc21e2713b63876c0eb901196e01e4",
"sha256:bbbf4b1e5cd2bdb08f915895b51081c041bac22394fdfcfdfbe9f14b77c08bf2"
],
"version": "==0.1.0"
},
"certifi": {
"hashes": [
"sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304",
"sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519"
],
"version": "==2020.4.5.1"
},
"chardet": {
"hashes": [
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
],
"version": "==3.0.4"
},
"click": {
"hashes": [
"sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a",
"sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"
],
"version": "==7.1.2"
},
"decorator": {
"hashes": [
"sha256:41fa54c2a0cc4ba648be4fd43cff00aedf5b9465c9bf18d64325bc225f08f760",
"sha256:e3a62f0520172440ca0dcc823749319382e377f37f140a0b99ef45fecb84bfe7"
],
"version": "==4.4.2"
},
"dj-database-url": {
"hashes": [
"sha256:4aeaeb1f573c74835b0686a2b46b85990571159ffc21aa57ecd4d1e1cb334163",
"sha256:851785365761ebe4994a921b433062309eb882fedd318e1b0fcecc607ed02da9"
],
"version": "==0.5.0"
},
"django": {
"hashes": [
"sha256:5052b34b34b3425233c682e0e11d658fd6efd587d11335a0203d827224ada8f2",
"sha256:e1630333248c9b3d4e38f02093a26f1e07b271ca896d73097457996e0fae12e8"
],
"index": "pypi",
"version": "==3.0.7"
},
"django-heroku": {
"hashes": [
"sha256:2bc690aab89eedbe01311752320a9a12e7548e3b0ed102681acc5736a41a4762",
"sha256:6af4bc3ae4a9b55eaad6dbe5164918982d2762661aebc9f83d9fa49f6009514e"
],
"index": "pypi",
"version": "==0.3.1"
},
"django-open-humans": {
"hashes": [
"sha256:8b0b0831c3729001b156f06fc801a20b5d6b8d6abf6f5f5e019d123ecc53ec3d"
],
"index": "pypi",
"version": "==0.1.5"
},
"gunicorn": {
"hashes": [
"sha256:1904bb2b8a43658807108d59c3f3d56c2b6121a701161de0ddf9ad140073c626",
"sha256:cd4a810dd51bf497552cf3f863b575dabd73d6ad6a91075b65936b151cbf4f9c"
],
"index": "pypi",
"version": "==20.0.4"
},
"humanfriendly": {
"hashes": [
"sha256:bf52ec91244819c780341a3438d5d7b09f431d3f113a475147ac9b7b167a3d12",
"sha256:e78960b31198511f45fd455534ae7645a6207d33e512d2e842c766d15d9c8080"
],
"version": "==8.2"
},
"idna": {
"hashes": [
"sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb",
"sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"
],
"version": "==2.9"
},
"ipython": {
"hashes": [
"sha256:5b241b84bbf0eb085d43ae9d46adf38a13b45929ca7774a740990c2c242534bb",
"sha256:f0126781d0f959da852fb3089e170ed807388e986a8dd4e6ac44855845b0fb1c"
],
"index": "pypi",
"version": "==7.14.0"
},
"ipython-genutils": {
"hashes": [
"sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8",
"sha256:eb2e116e75ecef9d4d228fdc66af54269afa26ab4463042e33785b887c628ba8"
],
"version": "==0.2.0"
},
"jedi": {
"hashes": [
"sha256:cd60c93b71944d628ccac47df9a60fec53150de53d42dc10a7fc4b5ba6aae798",
"sha256:df40c97641cb943661d2db4c33c2e1ff75d491189423249e989bcea4464f3030"
],
"version": "==0.17.0"
},
"open-humans-api": {
"hashes": [
"sha256:c3328e5ee6a596b9ff653525e65252bb499ccfcb9ed330c0f86742d4d7dd228e"
],
"version": "==0.2.9"
},
"parso": {
"hashes": [
"sha256:158c140fc04112dc45bca311633ae5033c2c2a7b732fa33d0955bad8152a8dd0",
"sha256:908e9fae2144a076d72ae4e25539143d40b8e3eafbaeae03c1bfe226f4cdf12c"
],
"version": "==0.7.0"
},
"pexpect": {
"hashes": [
"sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937",
"sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"
],
"markers": "sys_platform != 'win32'",
"version": "==4.8.0"
},
"pickleshare": {
"hashes": [
"sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca",
"sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"
],
"version": "==0.7.5"
},
"prompt-toolkit": {
"hashes": [
"sha256:563d1a4140b63ff9dd587bda9557cffb2fe73650205ab6f4383092fb882e7dc8",
"sha256:df7e9e63aea609b1da3a65641ceaf5bc7d05e0a04de5bd45d05dbeffbabf9e04"
],
"version": "==3.0.5"
},
"psycopg2": {
"hashes": [
"sha256:132efc7ee46a763e68a815f4d26223d9c679953cd190f1f218187cb60decf535",
"sha256:2327bf42c1744a434ed8ed0bbaa9168cac7ee5a22a9001f6fc85c33b8a4a14b7",
"sha256:27c633f2d5db0fc27b51f1b08f410715b59fa3802987aec91aeb8f562724e95c",
"sha256:2c0afb40cfb4d53487ee2ebe128649028c9a78d2476d14a67781e45dc287f080",
"sha256:2df2bf1b87305bd95eb3ac666ee1f00a9c83d10927b8144e8e39644218f4cf81",
"sha256:440a3ea2c955e89321a138eb7582aa1d22fe286c7d65e26a2c5411af0a88ae72",
"sha256:6a471d4d2a6f14c97a882e8d3124869bc623f3df6177eefe02994ea41fd45b52",
"sha256:6b306dae53ec7f4f67a10942cf8ac85de930ea90e9903e2df4001f69b7833f7e",
"sha256:a0984ff49e176062fcdc8a5a2a670c9bb1704a2f69548bce8f8a7bad41c661bf",
"sha256:ac5b23d0199c012ad91ed1bbb971b7666da651c6371529b1be8cbe2a7bf3c3a9",
"sha256:acf56d564e443e3dea152efe972b1434058244298a94348fc518d6dd6a9fb0bb",
"sha256:d3b29d717d39d3580efd760a9a46a7418408acebbb784717c90d708c9ed5f055",
"sha256:f7d46240f7a1ae1dd95aab38bd74f7428d46531f69219954266d669da60c0818"
],
"version": "==2.8.5"
},
"ptyprocess": {
"hashes": [
"sha256:923f299cc5ad920c68f2bc0bc98b75b9f838b93b599941a6b63ddbc2476394c0",
"sha256:d7cc528d76e76342423ca640335bd3633420dc1366f258cb31d05e865ef5ca1f"
],
"version": "==0.6.0"
},
"pygments": {
"hashes": [
"sha256:647344a061c249a3b74e230c739f434d7ea4d8b1d5f3721bc0f3558049b38f44",
"sha256:ff7a40b4860b727ab48fad6360eb351cc1b33cbf9b15a0f689ca5353e9463324"
],
"version": "==2.6.1"
},
"python-dateutil": {
"hashes": [
"sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c",
"sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"
],
"version": "==2.8.1"
},
"pytz": {
"hashes": [
"sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed",
"sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048"
],
"version": "==2020.1"
},
"requests": {
"hashes": [
"sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee",
"sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6"
],
"version": "==2.23.0"
},
"six": {
"hashes": [
"sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259",
"sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"
],
"version": "==1.15.0"
},
"sqlparse": {
"hashes": [
"sha256:022fb9c87b524d1f7862b3037e541f68597a730a8843245c349fc93e1643dc4e",
"sha256:e162203737712307dfe78860cc56c8da8a852ab2ee33750e33aeadf38d12c548"
],
"version": "==0.3.1"
},
"traitlets": {
"hashes": [
"sha256:70b4c6a1d9019d7b4f6846832288f86998aa3b9207c6821f3578a6a6a467fe44",
"sha256:d023ee369ddd2763310e4c3eae1ff649689440d4ae59d7485eb4cfbbe3e359f7"
],
"version": "==4.3.3"
},
"urllib3": {
"hashes": [
"sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527",
"sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115"
],
"version": "==1.25.9"
},
"wcwidth": {
"hashes": [
"sha256:980fbf4f3c196c0f329cdcd1e84c554d6a211f18e252e525a0cf4223154a41d6",
"sha256:edbc2b718b4db6cdf393eefe3a420183947d6aa312505ce6754516f458ff8830"
],
"version": "==0.2.3"
},
"whitenoise": {
"hashes": [
"sha256:60154b976a13901414a25b0273a841145f77eb34a141f9ae032a0ace3e4d5b27",
"sha256:6dd26bfda3af29177d8ab7333a0c7b7642eb615ce83764f4d15a9aecda3201c4"
],
"version": "==5.1.0"
}
},
"develop": {}
}

2
Procfile Normal file
View File

@ -0,0 +1,2 @@
release: python manage.py migrate
web: gunicorn open_survey.wsgi:application --log-file -

80
README.md Normal file
View File

@ -0,0 +1,80 @@
## Demo of how Open Humans to OpenClinica workflow can work
### Install
Assumes you have a basic understanding of how Django, `pipenv`, & `heroku` work:
- `pipenv install`
- `pipenv shell`
- `heroku local:run python manage.py migrate`
- `heroku local`
Web-server should be up on `127.0.0.1:5000`
### Setup
Copy the `env.sample` as `.env` and fill in the missing bits. Required:
- An Open Humans project
- Having a _Participate_ enabled Open Clinica survey and the corresponding token to add participants etc.
Demo deployment runs on https://opensurveytest.herokuapp.com/
Logging in with Open Humans will:
- Create Open Clinica participant
- Schedule first survey for them
- Get participant access survey_token
- Email this via Open Humans to just registered participant
### Design dev
Assumes you have a basic understanding of how node and yarn/npm work.
Node version used: 12.16.1
We use [PostCSS](https://github.com/postcss/postcss) to enhance browser compatibility, accessibility and preformances.
A `package.json` and a `postcss.config.js` config file exist at the document root. Add or remove plugin from there.
In order to edit the styles, you need to:
- run `yarn install` or `npm i`
- edit the styles in `src > css > parts`
- run `yarn watch` or `npm run watch` while in developement (watches the changes)
- run `yarn build` or `npm run dev` for production
The optimized and minified style file is under `static > css`
### Translations / i18n
#### Activate a new language
To activate a new language edit the **LANGUAGES** setting in **settings.py**
```
LANGUAGES = [
('en', _('English')),
('fr', _('French')),
('de', _('German')),
]
```
You need to do this first before translating because the language name itself needs to be translated.
#### Add a new language
To add a new language simply add a new directory in /locale with the language code as name, for example:
**/locale/fr** for french.
Then to generate the translation files run:
`python manage.py makemessages`
It will create **django.po** files inside each /\<lang\>/LC_MESSAGES directory.
You can edit these files directly with any text editor or specialized software / web application.
Once the translations are complete, to generate the binary files optimized for consumption by Django, run:
`python manage.py compilemessages`
It will create **django.mo** files inside each /\<lang\>/LC_MESSAGES directory.

BIN
_design/index.sketch Normal file

Binary file not shown.

BIN
dump.rdb Normal file

Binary file not shown.

26
env.sample Normal file
View File

@ -0,0 +1,26 @@
SECRET_KEY="SOME_KEY"
DEBUG="True"
# Setup for Open Humans backend
OPENHUMANS_APP_BASE_URL="http://127.0.0.1:5000/"
OPENHUMANS_CLIENT_ID="CLIENT_ID"
OPENHUMANS_CLIENT_SECRET="CLIENT_SECRET"
ON_HEROKU='True'
# Setup for Open Clinica
## Username for adding participants & scheduling data ('site investigator' role)
OPENCLINICA_USERNAME="Username"
OPENCLINICA_PASSWORD="Password"
## Username for exporting data ('data manager' role)
OPENCLINICA_DATA_USERNAME="AnotherUsername"
OPENCLINICA_DATA_PASSWORD="Password"
OPENCLINICA_STUDY="DEMO_NAME(TEST)"
OPENCLINICA_SITE="SITE_NAME(TEST)"
OPENCLINICA_PARTICIPATE_LINK="PARTICIPATE_LINK.mytrial.me"

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

1
main/__init__.py Normal file
View File

@ -0,0 +1 @@
default_app_config = 'main.apps.MainConfig'

3
main/admin.py Normal file
View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

8
main/apps.py Normal file
View File

@ -0,0 +1,8 @@
from django.apps import AppConfig
class MainConfig(AppConfig):
name = 'main'
def ready(self):
import main.signals

124
main/helpers.py Normal file
View File

@ -0,0 +1,124 @@
import datetime
import requests
import json
from urllib.parse import urljoin
from .models import ReportToken
from django.utils import translation
from django.conf import settings
from django.shortcuts import reverse
from django.utils.translation import gettext_lazy as _
def get_access_token(download=False):
url = 'https://opencovid.build.openclinica.io/user-service/api/oauth/token'
headers = {'Content-Type': "application/json"}
data = json.dumps(
{'username': settings.OPENCLINICA_SITE_USERNAME, 'password': settings.OPENCLINICA_SITE_PASSWORD}
)
if download:
data = json.dumps(
{'username': settings.OPENCLINICA_DATA_USERNAME, 'password': settings.OPENCLINICA_DATA_PASSWORD}
)
response = requests.post(url, headers=headers, data=data)
if response.status_code == 200:
return response.text
else:
raise ValueError("{} returned: {}".format(url, response.text))
def create_openclinica_user(survey_member):
headers = {
"Authorization": "bearer {}".format(get_access_token()),
"Content-Type": "application/json"
}
data = {
"identifier": survey_member.member.oh_id,
"subjectKey": survey_member.member.oh_id
}
url = "https://opencovid.openclinica.io/OpenClinica/pages/auth/api/clinicaldata/studies/{}/sites/{}/participants?register=y".format(
settings.OPENCLINICA_STUDY, settings.OPENCLINICA_SITE
)
response = requests.post(url, headers=headers, data=json.dumps(data))
if response.status_code == 200:
return response.text
else:
raise ValueError("{} returned: {}".format(url, response.text))
def create_openclinica_event(survey_member, event, date):
headers = {
"Authorization": "bearer {}".format(get_access_token()),
"Content-Type": "application/json"
}
data = {
"endDate": date,
"startDate": date,
"studyEventOID": event,
"subjectKey": survey_member.member.oh_id,
}
url = "https://opencovid.openclinica.io/OpenClinica/pages/auth/api/clinicaldata/studies/{}/sites/{}/events".format(
settings.OPENCLINICA_STUDY, settings.OPENCLINICA_SITE
)
response = requests.post(url, headers=headers, data=json.dumps(data))
if response.status_code == 200:
return response.text
else:
try:
# Does onboarding event already exists on OpenClinica ?
if response.json().get("message") == "errorCode.eventAlreadyExists":
return response.text
except:
raise ValueError("{} returned: {}".format(url, response.text))
def get_openclinica_token(survey_member):
headers = {
"Authorization": "bearer {}".format(get_access_token()),
"Content-Type": "application/json"
}
url = "https://opencovid.openclinica.io/OpenClinica/pages/auth/api/clinicaldata/studies/{}/sites/{}/participant?includeParticipateInfo=y&participantID={}".format(
settings.OPENCLINICA_STUDY, settings.OPENCLINICA_SITE, survey_member.member.oh_id
)
response = requests.get(url, headers=headers)
print(response.json())
if response.status_code == 200:
survey_member.survey_token = response.json()['accessCode']
survey_member.save()
return response.text
else:
raise ValueError("{} returned: {}".format(url, response.text))
def create_autologin_url(member, token):
url = urljoin(
settings.OPENHUMANS_APP_BASE_URL,
reverse("autologin", kwargs={"oh_id":member.oh_id}) + "?login_token={}".format(token.token)
)
return url
def create_survey_url(member, token):
url = create_autologin_url(member, token) + "&next=/survey"
return url
def send_user_survey_link(survey_member):
token = ReportToken(member=survey_member.member)
token.save()
url = create_survey_url(survey_member.member, token)
withdraw_url = create_autologin_url(survey_member.member, token)
saved_language = survey_member.member.surveyaccount.language
translation.activate(saved_language)
# make str out of subject as otherwise only last character is subject!
survey_member.member.message(
subject=str(_("Here's your survey link!")),
message="{}: {}\n\n\n{}: {}".format(
_("Please use this link to fill out the survey"),
url,
_("If you don't want to take part in the survey anymore, please use this link and click on \"WITHDRAW MY CONSENT\""),
withdraw_url
)
)
survey_member.last_email = datetime.date.today()
survey_member.save()

View File

View File

@ -0,0 +1,21 @@
from django.core.management.base import BaseCommand
import requests
from main.helpers import get_access_token
class Command(BaseCommand):
help = "Exports data for all members"
def handle(self, *args, **options):
headers = {
"Authorization": "bearer {}".format(get_access_token(download=True)),
"Accept": "application/json"
}
url = "https://opencovid.openclinica.io/OpenClinica/pages/auth/api/clinicaldata/S_DEMO_BGT(TEST)/91048557/*/*?includeAudits=n&includeDNs=n&includeMetadata=y&showArchived=n"
# download all data:
# url = "https://opencovid.openclinica.io/OpenClinica/pages/auth/api/clinicaldata/S_DEMO_BGT(TEST)/*/*/*?includeAudits=n&includeDNs=n&includeMetadata=y&showArchived=n"
response = requests.get(url, headers=headers)
print(response.json())
# TODO: so far it doesn't process the data, next step:
# - Save data to Open Humans for each member

View File

@ -0,0 +1,16 @@
from django.core.management.base import BaseCommand
from main.models import SurveyAccount
from main.helpers import get_openclinica_token
from main.helpers import send_user_survey_link
class Command(BaseCommand):
help = "Updates all data for all members"
def handle(self, *args, **options):
for survey_account in SurveyAccount.objects.filter(consent_given=True, daily_emails_activated=True):
# we no longer create events on sending out email, it's dynamically
# done when clicking the email link now
# create_openclinica_event(survey_account, "SE_DAILY", str(datetime.date.today()))
get_openclinica_token(survey_account)
send_user_survey_link(survey_account)

41
main/middleware.py Normal file
View File

@ -0,0 +1,41 @@
from django.conf import settings
from django.utils import translation
from openhumans.models import OpenHumansMember
import logging
logger = logging.getLogger(__name__)
class OpenHumansLoginUrlMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
request.openhumans_login_url = OpenHumansMember.get_auth_url()
response = self.get_response(request)
return response
class LoginLangMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
if request.user.is_authenticated:
current_language = translation.get_language()
saved_language = request.user.openhumansmember.surveyaccount.language
if saved_language != current_language and saved_language in [lang[0] for lang in settings.LANGUAGES]:
response.set_cookie(
settings.LANGUAGE_COOKIE_NAME, saved_language,
max_age=settings.LANGUAGE_COOKIE_AGE,
path=settings.LANGUAGE_COOKIE_PATH,
domain=settings.LANGUAGE_COOKIE_DOMAIN,
secure=settings.LANGUAGE_COOKIE_SECURE,
httponly=settings.LANGUAGE_COOKIE_HTTPONLY,
samesite=settings.LANGUAGE_COOKIE_SAMESITE,
)
return response

View File

@ -0,0 +1,24 @@
# Generated by Django 3.0.6 on 2020-05-18 10:37
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('openhumans', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='SurveyAccount',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('survey_token', models.BooleanField(blank=True)),
('member', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='openhumans.OpenHumansMember')),
],
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.0.6 on 2020-05-18 11:23
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('main', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='surveyaccount',
name='survey_token',
field=models.TextField(blank=True, null=True),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.0.6 on 2020-05-26 12:40
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('main', '0002_auto_20200518_1123'),
]
operations = [
migrations.AddField(
model_name='surveyaccount',
name='last_survey',
field=models.DateField(blank=True, null=True),
),
]

View File

@ -0,0 +1,26 @@
# Generated by Django 3.0.6 on 2020-05-26 13:14
from django.db import migrations, models
import django.db.models.deletion
import main.models
class Migration(migrations.Migration):
dependencies = [
('openhumans', '0001_initial'),
('main', '0003_surveyaccount_last_survey'),
]
operations = [
migrations.CreateModel(
name='ReportToken',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(auto_now_add=True)),
('token', models.TextField(default=main.models.create_token)),
('minutes_valid', models.IntegerField(default=1440)),
('member', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='openhumans.OpenHumansMember')),
],
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.0.6 on 2020-06-08 11:50
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('main', '0004_reporttoken'),
]
operations = [
migrations.AddField(
model_name='surveyaccount',
name='consent_given',
field=models.BooleanField(default=False),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.0.6 on 2020-06-23 09:10
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('main', '0005_surveyaccount_consent_given'),
]
operations = [
migrations.AddField(
model_name='surveyaccount',
name='language',
field=models.CharField(default='en', max_length=5),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.0.6 on 2020-06-25 12:40
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('main', '0006_surveyaccount_language'),
]
operations = [
migrations.AddField(
model_name='surveyaccount',
name='last_email',
field=models.DateField(blank=True, null=True),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.0.6 on 2020-06-30 09:35
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('main', '0007_surveyaccount_last_email'),
]
operations = [
migrations.AddField(
model_name='surveyaccount',
name='daily_emails_activated',
field=models.BooleanField(default=True),
),
]

View File

45
main/models.py Normal file
View File

@ -0,0 +1,45 @@
from django.db import models
from openhumans.models import OpenHumansMember
import secrets
import datetime
from django.utils.timezone import now
class SurveyAccount(models.Model):
"""
Store additional data for an Open humans member.
This is a one to one relationship with a OpenHumansMember object.
"""
member = models.OneToOneField(OpenHumansMember, on_delete=models.CASCADE)
survey_token = models.TextField(blank=True, null=True)
last_survey = models.DateField(blank=True, null=True)
last_email = models.DateField(blank=True, null=True)
consent_given = models.BooleanField(default=False)
daily_emails_activated = models.BooleanField(default=True)
language = models.CharField(max_length=5, default='en')
TOKEN_EXPIRATION_MINUTES = 1440 # default expiration is one day
def create_token():
return secrets.token_urlsafe(16)
class ReportToken(models.Model):
member = models.ForeignKey(OpenHumansMember, on_delete=models.CASCADE)
created = models.DateTimeField(auto_now_add=True)
token = models.TextField(default=create_token)
minutes_valid = models.IntegerField(default=TOKEN_EXPIRATION_MINUTES)
def is_valid(self):
expires = self.created + datetime.timedelta(minutes=self.minutes_valid)
if expires > now():
return True
return False
def valid_member(self):
if self.is_valid():
return self.member
return None

18
main/signals.py Normal file
View File

@ -0,0 +1,18 @@
from django.db.models.signals import post_save
from django.dispatch import receiver
from openhumans.models import OpenHumansMember
from .models import SurveyAccount
from .helpers import create_openclinica_user, create_openclinica_event
import datetime
@receiver(post_save, sender=OpenHumansMember)
def my_handler(sender, instance, created, **kwargs):
if created:
survey_account = SurveyAccount.objects.create(
member=instance
)
survey_account.save()
create_openclinica_user(survey_account)
create_openclinica_event(survey_account, "SE_FSFD", str(datetime.date.today()))

324
main/templates/base.html Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,106 @@
{% extends 'base.html' %}
{% load static %}
{% load i18n %}
{% block intro %}
<section class="intro">
<div class="intro-content">
<h1>{% trans "About" %}</h1>
<p>
{% blocktrans %}
The Covid Open survey was created by a team of scientists at the Center for Research and Interdisciplinarity (CRI)
in
Paris, with collaborating researchers from the USA, Australia, Canada, Costa Rica, India and more! We are
interested
in bringing together minds from all over the world, yours included, to come up with great ideas to research the COVID-19 virus.
{% endblocktrans %}
</p>
<p>
<a href="/team">{% blocktrans %}Meet the team!{% endblocktrans %}</a>
</p>
</div>
</section>
{% endblock intro %}
{% block main %}
<section>
<article>
<h2>{% trans "Citizen Science" %}</h2>
<h3>{% trans "Be part of the team." %}</h3>
<p>
{% blocktrans %}
When it comes to science, we believe in harnessing the ingenuity of all citizens. We want you to contribute your
own survey items according to your research questions and interests. This will not only help us develop the study
to cover the needs and interests of the cohort, but will also help us understand key questions and concerns that
citizens outside of academia have regarding the pandemic.
{% endblocktrans %}
</p>
<h3>{% trans "How it works." %}</h3>
<p>
{% blocktrans %}
You will need to access the Open Humans forum, where we have created a dedicated section for your suggestions. Your
participation in this forum cannot be linked to your answers in the Covid Open survey. You can also create and engage in topics of
discussion directly on the forum and also vote for suggestions others have made!
{% endblocktrans %}
</p>
<h3>{% trans "What to tell us:" %}</h3>
<p>
{% trans "We want to add questions to the survey with an end-goal in mind. We therefore ask you to suggest:" %}
<ul>
<li>{% trans "A research hypothesis that you would like to test" %}</li>
<li>{% trans "A quick description of why you think your idea is worth exploring" %}</li>
<li>{% trans "The questions you would like to incorporate in the survey to test your hypothesis" %}</li>
</ul>
</p>
<h3>{% trans "How we review it." %}</h3>
<p>
{% blocktrans %}
Every fortnight, our team will go through your suggestions, and decide on a few to incorporate into our
next iteration of the survey. We will then send the new set of questions to be reviewed by the Institutional Review
Board, to make sure it doesnt go against any legal or ethical regulations. Once we get the green light, we will code the new questions into the survey.
{% endblocktrans %}
</p>
</article>
<article>
<h2>{% trans "Our approach" %}</h2>
<h3>{% trans "What we do." %}</h3>
<p>
{% blocktrans %}
The Covid Open survey questionnaire has been created for people who want to help fight the COVID-19 virus from
the comfort of their home. It consists of a short questionnaire that takes about 20 minutes to complete the first time, followed by a much quicker daily check-in on how you are feeling. A
wide variety of questions are asked, some of which can be answered daily, others that appear on a rolling basis, in order to keep the survey fresh!
{% endblocktrans %}
</p>
<p>
{% blocktrans %}
Our goal? To better understand the virus transmission patterns and its effect on physical and mental health. We want
to understand <strong>how the virus spreads</strong>, <strong>who it affects most</strong>, and <strong>how it impacts our daily lives</strong>. We hope this may
guide decisions surrounding public health and medication repurposing in the future.
{% endblocktrans %}
</p>
<h3>{% trans "How we do it." %}</h3>
<p>
{% blocktrans %}
All data collected is anonymized and goes through the Open Humans platform. We also seek to promote citizen science
and provide an opportunity for you to contribute to this research
hypotheses that could be implemented in our fast-evolving survey.
{% endblocktrans %}
</p>
<p>
{% trans "Our inital research aims are as follows:" %}
<ul>
<li>
{% trans "To collect comprehensive symptom reports with a high temporal resolution to better understand COVID-19 disease progression." %}
</li>
<li>{% trans "To measure the impact of the COVID-19 pandemic on mental health." %}</li>
<li>{% trans "To identify effective agents to reduce COVID-19 disease severity" %}</li>
<li>{% trans "To characterize factors linked to increased susceptibility to COVID-19" %}</li>
<li>
{% trans "To understand how a more participatory approach to survey research - that makes participants esearch partners - changes survey success." %}
</li>
</ul>
<p>
</article>
</section>
{% endblock main %}

View File

@ -0,0 +1,40 @@
{% extends 'base.html' %}
{% load static %}
{% load i18n %}
{% block main %}
<h1 class="mt-3 text-center">{% trans "Be a Citizen Scientist" %}</h1>
<p>
{% blocktrans %}
When it comes to science, we believe in harnessing the ingenuity of all citizens. We want you to contribute your
own survey items according to your research questions and interests. This will not only help us develop the
study to cover the needs and interests of the cohort, but will also help us understand key questions and
concerns that citizens outside of academia have regarding the pandemic.
{% endblocktrans %}
</p>
<p>
{% blocktrans %}
How it works: You will need to access the Open Humans forum, where a dedicated section for suggestions has been
created. Your personal information will be anonymized for your suggestions. You can also create and engage in
topics of discussions directly on the forum, as well as vote for suggestions others have made!
{% endblocktrans %}
</p>
<p>{% trans "What to tell us: We want to add questions to the survey with an end-goal in mind. We therefore ask you to suggest:" %}</p>
<ul>
<li>{% trans "a research hypothesis that you would like to test" %}</li>
<li>{% trans "A quick description of why you think your idea is worth exploring" %}</li>
<li>{% trans "The questions you would like to incorporate in the survey to test your hypothesis" %}</li>
</ul>
<p>
{% blocktrans %}
How we review it: Every fortnight, our team will go through your suggestions, and decide on a few that we could
incorporate into our next survey iteration . We will then send the new set of questions to be reviewed by the
Institutional Review Board, to make sure it doesnt go against any legal or ethical regulations. Once we get the
green light, we will code it into the survey.
{% endblocktrans %}
</p>
{% endblock main %}

View File

@ -0,0 +1,31 @@
{% extends 'base.html' %}
{% load static %}
{% load i18n %}
{% block intro %}
<section class="intro">
<div class="intro-content">
<h1>{% trans "Access the Data" %}</h1>
<p>
{% blocktrans %}
Your data belongs to you! If you want to get a transcript with your past responses to the survey, <a
href="#">click here!</a> You will be redirected to our Open Humans server which stores your data securely.
{% endblocktrans %}
</p>
</div>
</section>
{% endblock intro %}
{% block main %}
<section>
<article>
<p>
{% blocktrans %}
As the survey just launched, we are waiting a few days to gain enough data points to show you the trends! Come
back later and see whats happening around you!
{% endblocktrans %}
</p>
</article>
</section>
{% endblock main %}

View File

@ -0,0 +1,219 @@
{% extends 'base.html' %}
{% load static %}
{% load i18n %}
{% block intro %}
<section class="intro">
<div class="intro-content">
<h1>{% trans "Frequently Asked Questions" %}</h1>
<p>
{% blocktrans %}
Find answers to the most frequently asked questions about the Covid Open survey and the data we collect.
{% endblocktrans %}
</p>
<p>
{% blocktrans %}
Feel free to email us with any other question you may have at: <a href="mailto:bastian.greshake-tzovaras@cri-paris.org">bastian.greshake-tzovaras@cri-paris.org</a>
{% endblocktrans %}
</p>
<p>
{% blocktrans %}
Thank you!
{% endblocktrans %}
</p>
</div>
</section>
{% endblock intro %}
{% block main %}
<section>
<article>
<h2>{% trans "The data" %}</h2>
<h3 data-collapse aria-expanded="false">{% trans "Who will be using my data?" %}
<svg xmlns="http://www.w3.org/2000/svg" height="12" width="20" viewbox="0 0 20 12" class="chevron">
<line x1="0" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
<line x1="20" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
</svg>
</h3>
<p class="collapse__item">
{% blocktrans %}
De-identified data will be made available to the scientific community, and will be distributed with any
publications
that arise from this study. If necessary to protect the privacy of participants, individual bits of data might be
removed or only shared in aggregate. These data cannot be used to identify participants. Additionally, each
participant will be given a copy of their own data as part of this study.
{% endblocktrans %}
</p>
<h3 data-collapse aria-expanded="false">{% trans "How will my data be protected?" %}
<svg xmlns="http://www.w3.org/2000/svg" height="12" width="20" viewbox="0 0 20 12" class="chevron">
<line x1="0" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
<line x1="20" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
</svg>
</h3>
<p class="collapse__item">
{% blocktrans %}
All data will be stored on a firewall and password-protected on secure project servers of Open Humans &
OpenClinica.
This study does not collect individual identifiers such as name or email addresses. Instead, Open Humans assigns
each participant a study ID on enrollment.
{% endblocktrans %}
</p>
<h3 data-collapse aria-expanded="false">{% trans "Will someone make money off my data?" %}
<svg xmlns="http://www.w3.org/2000/svg" height="12" width="20" viewbox="0 0 20 12" class="chevron">
<line x1="0" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
<line x1="20" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
</svg>
</h3>
<p class="collapse__item">
{% blocktrans %}
Participant data will not be sold and data sharing will be performed within strict protocol-driven procedural
guidelines.
{% endblocktrans %}
</p>
<h3 data-collapse aria-expanded="false">{% trans "How long will my data be used for?" %}
<svg xmlns="http://www.w3.org/2000/svg" height="12" width="20" viewbox="0 0 20 12" class="chevron">
<line x1="0" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
<line x1="20" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
</svg>
</h3>
<p class="collapse__item">
{% blocktrans %}
The collection period is aimed to end in May 2022. After this we will stop gathering new data but will need some
time to analyze everything collected.
{% endblocktrans %}
</p>
<h3 data-collapse aria-expanded="false">{% trans "Can I delete my data?" %}
<svg xmlns="http://www.w3.org/2000/svg" height="12" width="20" viewbox="0 0 20 12" class="chevron">
<line x1="0" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
<line x1="20" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
</svg>
</h3>
<div class="collapse__item">
<p>
{% blocktrans %}
Yes! Your data belongs to you. You can do so automatically from here, or manually through the Open Humans website.
{% endblocktrans %}
</p>
{% if not request.user.is_authenticated %}
<p><i>{% trans "Please login to view the automatic delete links" %}.</i></p>
{% else %}
<p class="collapse__item">{% trans "Follow these steps to delete your data automatically:" %}
<ul>
<li>{% blocktrans count counter=files|length %}You have 1 data file on Open Humans{% plural %}You have
{{ counter }} data files on Open Humans{% endblocktrans %}. {% if files|length != 0 %}<a
href="{% url "delete_all_openhuman_files" %}">{% trans "Click here to delete all your data files" %}</a>.{% else %}{% trans "You don't have anything to delete!" %}{% endif %}
</li>
<li>
{% trans "Additionally, if you want to revoke access from Covid Open Survey to your Open Humans account, follow theses steps:" %}
<ul>
<li>{% blocktrans %}Go to <a href="https://www.openhumans.org/activity/covid-open-survey/"
target="_blank">https://www.openhumans.org/activity/covid-open-survey/</a>{% endblocktrans %}</li>
<li>{% trans 'Click on "Leave project" in the bottom left corner' %}</li>
<li>{% trans 'Click on "Withdraw & revoke authorization"' %}</li>
</ul>
</li>
</ul>
</p>
{% endif %}
<p>
{% trans "Follow these steps to delete your data through the Open Humans website:" %}
<ul>
<li>
{% blocktrans %}Go to <a href="https://www.openhumans.org/activity/covid-open-survey/" target="_blank">https://www.openhumans.org/activity/covid-open-survey/</a>
{% endblocktrans %}
</li>
<li>{% trans 'Click on "Leave project" in the bottom left corner' %}</li>
<li>{% trans 'Check "Remove my data files for Covid Open Survey from Open Humans"' %}</li>
<li>{% trans 'Click on "Withdraw & revoke authorization"' %}</li>
</ul>
</p>
{% if request.user.is_authenticated %}
<p>
{% trans "You can also delete all your data files and your Covid Open Survey account:" %}
<br>
<a
href="{% url "delete_all" %}">{% trans "Click here to delete all your data files and your Covid Open Survey account" %}</a>.
</p>
{% endif %}
</div>
<h3 data-collapse aria-expanded="false">{% trans "Can others access my data?" %}
<svg xmlns="http://www.w3.org/2000/svg" height="12" width="20" viewbox="0 0 20 12" class="chevron">
<line x1="0" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
<line x1="20" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
</svg>
</h3>
<p class="collapse__item">
{% blocktrans %}
Other individual participants will not be able to access your data. However, the overall dataset will be made
available to the science community.
{% endblocktrans %}
</p>
</article>
<article>
<h2>{% trans "The survey" %}</h2>
<h3 data-collapse aria-expanded="false">{% trans "Why do I need to sign up with Open Humans?" %}
<svg xmlns="http://www.w3.org/2000/svg" height="12" width="20" viewbox="0 0 20 12" class="chevron">
<line x1="0" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
<line x1="20" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
</svg>
</h3>
<p class="collapse__item">
{% blocktrans %}
Open Humans hosts our secure servers, and is the place where all the data goes.
{% endblocktrans %}
</p>
<h3 data-collapse aria-expanded="false">{% trans "How do I end the survey?" %}
<svg xmlns="http://www.w3.org/2000/svg" height="12" width="20" viewbox="0 0 20 12" class="chevron">
<line x1="0" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
<line x1="20" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
</svg>
</h3>
<p class="collapse__item">
{% blocktrans %}
In your daily reminder to complete the survey, simply click on “I do not want to be part of this research
initiative
anymore” and we will stop sending you reminders.
{% endblocktrans %}
</p>
<h3 data-collapse aria-expanded="false">{% trans "Can someone under 18 enroll in the survey?" %}
<svg xmlns="http://www.w3.org/2000/svg" height="12" width="20" viewbox="0 0 20 12" class="chevron">
<line x1="0" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
<line x1="20" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
</svg>
</h3>
<p class="collapse__item">
{% blocktrans %}
No, this study is not open to participants under the age of 18
{% endblocktrans %}
</p>
<h3 data-collapse aria-expanded="false">{% trans "Whats the difference between Open Humans and OpenClinica?" %}
<svg xmlns="http://www.w3.org/2000/svg" height="12" width="20" viewbox="0 0 20 12" class="chevron">
<line x1="0" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
<line x1="20" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
</svg>
</h3>
<p class="collapse__item">
{% blocktrans %}
Open Humans encrypts and stores the data, OpenClinica is the survey platform: data is collected there and sent to
Open Humans.
{% endblocktrans %}
</p>
</article>
<article>
<h2>{% trans "The survey" %}</h2>
<h3 data-collapse aria-expanded="false">{% trans "I would like to help, what can I do?" %}
<svg xmlns="http://www.w3.org/2000/svg" height="12" width="20" viewbox="0 0 20 12" class="chevron">
<line x1="0" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
<line x1="20" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
</svg>
</h3>
<p class="collapse__item">
{% blocktrans %}
The easiest way to help is by <strong>sharing the survey.</strong> If you want to get involved, send us an email at: <a href="mailto:contact@opencovid.org">contact@opencovid.org</a>
{% endblocktrans %}
</p>
</article>
</section>
{% endblock main %}

View File

@ -0,0 +1,322 @@
{% extends 'base.html' %}
{% load static %}
{% load i18n %}
{% block intro %}
<section class="intro hp-intro">
<div class="intro-content intro-content--hp">
<h1>Covid-Open survey</h1>
{% if not request.user.is_authenticated %}
<p>
{% blocktrans %}
COVID-19 has turned our lives upside down. And while this virus continues to spread, millions around the world
are
taking positive action. From the comfort of your home, you too can join the global fight against this virus!
<strong>5 minutes a day.</strong> Thats all it takes to advance science.
{% endblocktrans %}
</p>
<p>
<strong>I want to help fight COVID-19!</strong>
</p>
<a class="button button--white" href="{{ request.openhumans_login_url }}">{% blocktrans %}Start the survey {% endblocktrans %}</a>
<a href="#content">{% blocktrans %}Or learn more before taking the survey.{% endblocktrans %}</a>
{% else %}
<p>
{% blocktrans %}
Thank you for taking part in this project! The team is grateful and eager for your participation.
{% endblocktrans %}
</p>
<p>
{% blocktrans %}
You can find your consent and email settings <a href="#settings">below.</a>
{% endblocktrans %}
</p>
{% endif %}
</div>
<div class="hp-intro__illustration">
<svg width="457" height="418" viewBox="0 0 457 418" xmlns="http://www.w3.org/2000/svg">
<title>Survey</title>
<desc>Ilustration of a survey sheet.</desc>
<defs>
<linearGradient x1="50%" y1="100%" x2="50%" y2="0%" id="a">
<stop stop-color="gray" stop-opacity=".25" offset="0%" />
<stop stop-color="gray" stop-opacity=".12" offset="54%" />
<stop stop-color="gray" stop-opacity=".1" offset="100%" />
</linearGradient>
<linearGradient x1="50%" y1="99.981618%" x2="50%" y2="0%" id="b">
<stop stop-color="gray" stop-opacity=".25" offset="0%" />
<stop stop-color="gray" stop-opacity=".12" offset="54%" />
<stop stop-color="gray" stop-opacity=".1" offset="100%" />
</linearGradient>
<linearGradient x1="50%" y1="100%" x2="50%" y2="-.024845%" id="c">
<stop stop-color="gray" stop-opacity=".25" offset="0%" />
<stop stop-color="gray" stop-opacity=".12" offset="54%" />
<stop stop-color="gray" stop-opacity=".1" offset="100%" />
</linearGradient>
</defs>
<g transform="translate(1)" fill="none" fill-rule="evenodd">
<path stroke="#163A40" fill="#FFF" fill-rule="nonzero" d="M128 31h202v280H128z" />
<path fill="url(#a)" fill-rule="nonzero" d="M180 24h100v25H180z" />
<path
d="M230 0c-7.732681 0-14 6.493015-14 14.5S222.267319 29 230 29s14-6.493015 14-14.5S237.732681 0 230 0zm0 22.864154c-3.363309.088915-6.444663-1.891606-7.793123-5.008981-1.34846-3.117376-.695229-6.750199 1.652101-9.187858 2.347331-2.437659 5.920852-3.194239 9.037876-1.913484 3.117024 1.280755 5.156214 4.343543 5.157363 7.746169.052778 4.556254-3.549254 8.296897-8.054217 8.364154z"
fill="url(#b)" fill-rule="nonzero" />
<path
d="M229.5 1c3.580423 0 7.0142 1.422317 9.545942 3.954058C241.577683 7.4858 243 10.919578 243 14.5c0 3.70519-1.492668 7.06175-3.909473 9.501148L279 24v23h-98V24l38.909473.001148C217.492668 21.56175 216 18.205191 216 14.5 216 7.044156 222.044156 1 229.5 1zm0 5.711538c-4.301449 0-7.788462 3.487014-7.788462 7.788462 0 4.301448 3.487013 7.788462 7.788462 7.788462s7.788462-3.487013 7.788462-7.788462c0-4.301448-3.487013-7.788462-7.788462-7.788462z"
stroke="#163A40" fill="#FFA318" fill-rule="nonzero" />
<path stroke="#163A40" fill="#35D78C" fill-rule="nonzero" d="M139 78h40v40h-40z" />
<path stroke="#163A40" fill="#FFA318" fill-rule="nonzero" d="M139 163h40v40h-40zM139 248h40v40h-40z" />
<path fill="#E0E0E0" fill-rule="nonzero"
d="M206 90h54v4h-54zM206 96h90v4h-90zM206 102h84v4h-84zM206 175h54v4h-54zM206 181h90v4h-90zM206 187h84v4h-84zM206 260h54v4h-54zM206 266h90v4h-90zM206 271h84v4h-84z" />
<path fill="url(#c)" fill-rule="nonzero"
d="M150.125 95.394783L157.625 102l10.625-15 3.75 3-14.375 18L147 96.6z" />
<path fill="#FFF" fill-rule="nonzero"
d="M151.625 96.2l6.3 5.657143L166.85 89l3.15 2.571429L157.925 107 149 97.228571zM151.625 181.2l6.3 5.657143L166.85 174l3.15 2.571429L157.925 192 149 182.228571zM151.625 266.2l6.3 5.657143L166.85 259l3.15 2.571429L157.925 277 149 267.228571z" />
<g stroke="#163A40" stroke-dasharray="11" stroke-width="5">
<path d="M424.5 171.5v-63M339.5 174.5h88" />
</g>
<path d="M119 96H49v67M160 322v38h105" stroke="#163A40" stroke-width="5" stroke-dasharray="12" />
<path stroke="#163A40" fill="#FFF" fill-rule="nonzero"
d="M455 100h-77V56.871972L416.238095 24 455 56.871972z" />
<path fill="#E0E0E0" fill-rule="nonzero" d="M379 57l37.741497 22L455 57" />
<path stroke="#979797" fill="#FAFAFA" fill-rule="nonzero" d="M416.764706 79.333333L394 94V39h45v27.971429z" />
<path fill="#F5F5F5" fill-rule="nonzero" d="M379 99h76l-76-42z" />
<path fill="#E0E0E0" fill-rule="nonzero" d="M400 46h32v2h-32zM400 50h32v2h-32z" />
<path fill="#F9A826" fill-rule="nonzero" d="M400 54h32v2h-32z" />
<path fill="#E0E0E0" fill-rule="nonzero" d="M400 59h32v2h-32z" />
<path fill="#F9A826" fill-rule="nonzero" d="M400 63h32v2h-32z" />
<path stroke="#163A40" d="M273 329h88v88h-88z" />
<path fill="#FFF" fill-rule="nonzero" d="M278 331h77v68h-77z" />
<path
d="M355 377.176471c-21.280479 0-38.5-5.447647-38.5-12.176471-21.280479 0-38.5 4.738235-38.5 10.588235V401h77v-23.823529z"
fill="#E0E0E0" fill-rule="nonzero" />
<circle fill="#FFA318" fill-rule="nonzero" cx="342" cy="346" r="8" />
<path stroke="#163A40" fill="#FFF" fill-rule="nonzero" d="M0 170h101v72H0z" />
<path
d="M53.5 189a19.652713 19.652713 0 00-2.52973.168649L53.5 208.5l-19.452568-1.296486C34.021082 207.630405 34 208.062568 34 208.5c0 10.769553 8.730447 19.5 19.5 19.5S73 219.269553 73 208.5 64.269553 189 53.5 189z"
fill="#E0E0E0" fill-rule="nonzero" />
<path d="M46.529125 186C37.524358 187.187466 30.605365 194.607353 30 203.725736L49 205l-2.470875-19z"
fill="#FFA318" fill-rule="nonzero" />
<path fill="#FFF" d="M454 57l-39 22 39 20z" />
</g>
</svg>
</div>
</section>
{% endblock intro %}
{% block main %}
<div class="u-hidden" aria-hidden="true">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol viewBox="0 0 89 93" id="brain">
<title>Mental wellbeing</title>
<desc>A brain seen from above</desc>
<g fill="none" fill-rule="evenodd">
<path
d="M44.085106 4.331128c-.099239-.00055-.194073-.03983-.263127-.108982-.967876-.947996-4.79014-3.70241-15.12441-1.195819C16.309061 6.03155 1 20.266416 1 52.292255c0 32.025838 25.389438 38.815579 33.852584 38.815579 6.204255 0 8.275418-1.607861 8.937082-2.463297.068274-.092663.178044-.148132.29544-.14929"
fill="#35D78C" fill-rule="nonzero" />
<path
d="M11.771277 44.703189c0-19.930047 5.898043-32.98472 13.33484-40.744775C13.540843 8.673724 1 23.123532 1 52.187809c0 32.112014 25.389438 38.920025 33.852584 38.920025 6.204255 0 8.275418-1.612187 8.937082-2.469925.068274-.092912.178044-.14853.29544-.149692v-4.93985c-9.623366-.748462-32.31383-8.487559-32.31383-38.845178z"
fill="#163A40" fill-rule="nonzero" opacity=".16" />
<path
d="M59.472644 3.026366c-10.33427-2.50659-14.156535.247823-15.12441 1.194325-.068796.069703-.163663.109533-.263128.110475V88.50122c.117396.001159.227167.056628.295441.149291.661664.849464 2.732827 2.457324 8.937082 2.457324 8.463146 0 33.852584-6.789738 33.852584-38.815562 0-32.025825-15.309062-46.260686-27.697569-49.265906z"
fill="#35D78C" fill-rule="nonzero" />
<path
d="M45.32192 4.220691c-.067352.069703-.160229.109533-.257607.110475V88.50122c.114933.001159.222402.056628.289243.149291.647783.849464 2.675495 2.457324 8.74959 2.457324 11.78068-.617525 22.417247-7.183249 28.171032-17.389372-23.049026 16.9415-26.664559-16.947472-26.664559-34.862346 0-15.26198 1.098218-33.760582 8.873122-34.29355-1.400003-.644803-2.857523-1.159087-4.353705-1.5362C50.011568.519776 46.26949 3.27419 45.32192 4.220691z"
fill="#163A40" fill-rule="nonzero" opacity=".16" />
<path
d="M26.228418 3.958414c3.341717.510248 5.878359 3.200936 6.11543 6.48681M12.19962 14.9117c10.758572 2.541425 7.930185 11.983553 7.930185 11.983553m-4.60339 5.882347s.285896-7.444125 9.173145-5.9553M1.979207 47.378506c5.82189-8.137918 18.13378-6.465967 21.191496 3.955808m-7.644288 5.264485c3.057715-5.9553 10.702003-7.444125 15.288576-1.488825M24.699561 38.7329c4.988662 0 10.702003 2.97765 10.702003 10.421775m9.173146-11.9106c-4.586573-1.488825-10.468088-.461535-12.524402 4.019828m.29354-23.374553c4.586574 1.488825 6.115431 8.93295 3.057716 13.399425m9.173146-5.9553c-2.398234-1.054234-5.131875-1.121336-7.581605-.186103M7.59623 74.4647c6.16894-.334986 11.24322-5.57416 11.24322-10.018303m-7.899608-.403472c7.644288-1.488825 11.399162 1.122574 12.23086 5.9553M38.732946 68.2295c-10.702004-1.488825-18.0818 12.56866-8.237485 21.899127m1.848389-30.552178c6.11543 1.488825 9.173146 10.421775 3.057715 16.377075m-8.67321-61.914276c.83072-1.87231 2.587594-3.200392 4.656199-3.51978s4.161169.414348 5.545869 1.944603m25.99058-8.505657c-3.341718.510248-5.87836 3.200936-6.115431 6.48681M76.949799 14.9117c-10.75857 2.541425-7.930184 11.983553-7.930184 11.983553m4.60339 5.882347s-.285896-7.444125-9.173146-5.9553m22.720354 20.556207c-5.82189-8.137918-18.13378-6.465967-21.191496 3.955808m7.644288 5.264485c-3.057715-5.9553-10.702003-7.444125-15.288576-1.488825m6.11543-16.377075c-4.988662 0-10.702003 2.97765-10.702003 10.421775m-9.173146-11.9106c4.586573-1.488825 10.468088-.461535 12.524402 4.019828m-.293541-23.374553c-4.586573 1.488825-6.11543 8.93295-3.057715 13.399425m-9.173146-5.9553c2.398234-1.054234 5.131874-1.121336 7.581605-.186103M81.554719 74.4647c-6.168941-.334986-11.24322-5.57416-11.24322-10.018303m7.89808-.403472c-7.64429-1.488825-11.399164 1.122574-12.230862 5.9553M50.416475 68.2295c10.702003-1.488825 18.0818 12.56866 8.237485 21.899127M56.80557 59.576449c-6.11543 1.488825-9.173146 10.421775-3.057715 16.377075m8.67321-61.914276c-.83072-1.87231-2.587594-3.200392-4.6562-3.51978-2.068605-.319388-4.161168.414348-5.545868 1.944603"
stroke="#163A40" stroke-linecap="round" stroke-linejoin="round" />
<path
d="M44.085106 4.331166c-.099239-.00055-.194073-.039829-.263127-.108982-.967876-.947995-4.79014-3.702407-15.12441-1.195818C16.309061 6.031586 1 20.266447 1 52.292272c0 32.025824 25.389438 38.815562 33.852584 38.815562 6.204255 0 8.275418-1.60786 8.937082-2.463296.068274-.092663.178044-.148132.29544-.14929M59.472644 3.026366c-10.33427-2.50659-14.156535.247823-15.12441 1.194325-.068796.069703-.163663.109533-.263128.110475V88.50122c.117396.001159.227167.056628.295441.149291.661664.849464 2.732827 2.457324 8.937082 2.457324 8.463146 0 33.852584-6.789738 33.852584-38.815562 0-32.025825-15.309062-46.260686-27.697569-49.265906z"
stroke="#163A40" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
</g>
</symbol>
<symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 88 88" id="bandaid">
<title>Bandaid</title>
<desc>A bandaid seen from above</desc>
<g transform="translate(-2 -2)" fill="none" fill-rule="evenodd">
<path
d="M6.272848 64.783183L64.7913 6.26473c3.204838-3.204838 8.400906-3.204838 11.605744 0l9.331064 9.331064c3.204837 3.204838 3.204837 8.400906 0 11.605744L27.209656 85.71999c-3.204838 3.204838-8.400906 3.204838-11.605744 0l-9.331064-9.331064c-3.204837-3.204837-3.204837-8.400906 0-11.605743z"
fill="#35D78C" fill-rule="nonzero" />
<path
d="M33.106067 42.225736l14.538199-14.538198c.585786-.585787 1.535534-.585787 2.12132 0l14.538199 14.538198c.585786.585787.585786 1.535534 0 2.12132l-14.538199 14.5382c-.585786.585786-1.535534.585786-2.12132 0l-14.538199-14.5382c-.585786-.585786-.585786-1.535533 0-2.12132z"
fill="#FFF" fill-rule="nonzero" opacity=".25" />
<path
d="M6.272848 64.783183L64.7913 6.26473c3.204838-3.204838 8.400906-3.204838 11.605744 0l9.331064 9.331064c3.204837 3.204838 3.204837 8.400906 0 11.605744L27.209656 85.71999c-3.204838 3.204838-8.400906 3.204838-11.605744 0l-9.331064-9.331064c-3.204837-3.204837-3.204837-8.400906 0-11.605743z"
stroke="#163A40" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
<path
d="M46 66.961848l14.142983 14.142983c5.798155 5.764987 15.163693 5.764987 20.961848 0 5.764987-5.798155 5.764987-15.163693 0-20.961848L66.961848 46 46 66.961848z"
fill="#35D78C" fill-rule="nonzero" />
<path
d="M46 66.961848l14.142983 14.142983c5.798155 5.764987 15.163693 5.764987 20.961848 0 5.764987-5.798155 5.764987-15.163693 0-20.961848L66.961848 46 46 66.961848z"
fill="#163A40" fill-rule="nonzero" opacity=".2" />
<path
d="M25.038152 46L10.895169 31.857886c-5.764987-5.798354-5.764987-15.164214 0-20.962568 5.798155-5.765186 15.163693-5.765186 20.961848 0L46 25.038786 25.038152 46z"
fill="#35D78C" fill-rule="nonzero" />
<path fill="#163A40" fill-rule="nonzero" opacity=".2"
d="M20.653061 41.324675l20.671614-20.671614L46 25.328386 25.328386 46z" />
<path
d="M66.961848 45.999323l14.142983 14.143225c5.764987 5.798255 5.764987 15.163954 0 20.962208-5.798155 5.765087-15.163693 5.765087-20.961848 0L46 66.961531M25.038152 45.999323L10.895169 31.857452c-5.764987-5.798255-5.764987-15.163954 0-20.962208 5.798155-5.765087 15.163693-5.765087 20.961848 0L46 25.038469"
stroke="#163A40" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
<path d="M40.740147 61.959184l-10.69933-10.680056M51.19952 30.040816l10.759663 10.740272" stroke="#163A40"
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<circle fill="#163A40" fill-rule="nonzero" opacity=".16" transform="rotate(-45 46.355824 36.069412)"
cx="46.355823" cy="36.069412" r="1.352941" />
<circle fill="#163A40" fill-rule="nonzero" opacity=".16" transform="rotate(-45 55.92478 45.635663)"
cx="55.92478" cy="45.635663" r="1.352941" />
<circle fill="#163A40" fill-rule="nonzero" opacity=".16" transform="rotate(-45 36.788616 45.637412)"
cx="36.788616" cy="45.637412" r="1.352941" />
<circle fill="#163A40" fill-rule="nonzero" opacity=".16" transform="rotate(-45 46.357176 45.636619)"
cx="46.357177" cy="45.636619" r="1.352941" />
<circle fill="#163A40" fill-rule="nonzero" opacity=".16" transform="rotate(-45 46.35622 55.203663)"
cx="46.35622" cy="55.203663" r="1.352941" />
<circle stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"
transform="rotate(-45 46.355824 36.069412)" cx="46.355823" cy="36.069412" r="1.352941" />
<circle stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"
transform="rotate(-45 55.92478 45.635663)" cx="55.92478" cy="45.635663" r="1.352941" />
<circle stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"
transform="rotate(-45 36.788616 45.637412)" cx="36.788616" cy="45.637412" r="1.352941" />
<circle stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"
transform="rotate(-45 46.357176 45.636619)" cx="46.357177" cy="45.636619" r="1.352941" />
<circle stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"
transform="rotate(-45 46.35622 55.203663)" cx="46.35622" cy="55.203663" r="1.352941" />
</g>
</symbol>
<symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 86" id="dropper">
<title>Dropper</title>
<desc>A medical dropper with a drop</desc>
<g fill="none" fill-rule="evenodd">
<path
d="M7.734638 68.530484c2.522502 2.992576 4.04951 6.693644 4.369463 10.590435.116078 2.843274-1.89967 5.331497-4.710914 5.815116-1.600957.244765-3.229244-.220017-4.458052-1.272517C1.706327 82.611018.999526 81.075746 1 79.460134c0-3.876745 2.900947-8.570374 4.509653-10.872884.25289-.357122.660032-.574105 1.098213-.585284.438181-.01118.85591.184758 1.126772.528518zm6.10448-8.308694l-.508014.502592c-.951183.948011-1.38491 2.29584-1.164572 3.618966.220337 1.323125 1.06762 2.458692 2.274983 3.049034 1.683277.781687 3.67845.41068 4.966309-.923495l.378927-.37383c3.690052-3.784275 8.380166-6.447301 13.526183-7.680107 1.807415-.391286 3.465327-1.289023 4.778927-2.587726L45 49H21.004038c-1.465395 4.252994-3.920866 8.098783-7.16492 11.22179z"
fill="#35D78C" fill-rule="nonzero" />
<path
d="M24.227987 41.980894c-1.31287 1.317611-2.22395 2.991661-2.62413 4.821661C21.437193 47.544399 21.235677 48.277719 21 49h24.054065L56 37.990164 42.100179 24 24.227987 41.980894z"
fill="#92E4CF" fill-rule="nonzero" />
<path
d="M77.058918 4.884709c-1.747668-2.265473-4.37254-3.670812-7.2139-3.862271-2.841359-.19146-5.628568.849195-7.660047 2.860017L42 24.024921 55.995548 38 75.91854 18.120097c3.624418-3.49742 4.112393-9.160922 1.140378-13.235388z"
fill="#35D78C" fill-rule="nonzero" />
<path
d="M77.065313 5.036591c-.286115-.366893-.597324-.713265-.93136-1.036591.370275 3.17398-.73595 6.342279-2.997943 8.586292L53.27865 32.367211 42.288051 43.310415l-6.95657 6.92887c-1.319913 1.315315-2.985165 2.224973-4.800619 2.622379-5.178737 1.249275-9.89903 3.950425-13.612925 7.789887l-.3812.37924c-1.101373 1.123588-2.70641 1.586479-4.23231 1.220594-.818867 2.03907.066467 4.368154 2.028884 5.337463 1.693377.793003 3.70052.416625 4.996107-.936865l.3812-.379241c3.713547-3.840489 8.433874-6.542632 13.612926-7.792696 1.81826-.39695 3.486118-1.307684 4.8076-2.625189l6.949588-6.92606 10.985012-10.943204 19.862946-19.779514c3.612479-3.480006 4.098846-9.115308 1.136622-13.169488z"
fill="#163A40" fill-rule="nonzero" opacity=".16" />
<path
d="M39.219801 20.85821l19.881652 19.798094M45.159779 48.59962l30.775326-30.621107c3.60441-3.468126 4.09023-9.08482 1.135338-13.125931-1.73781-2.246737-4.347875-3.640453-7.173206-3.83033-2.825331-.189876-5.596818.842173-7.616837 2.836365L24.308562 41.64607c-1.314453 1.305305-2.226634 2.96372-2.627298 4.77663a23.72274 23.72274 0 01-.604585 2.176921M7.759093 68.347316c2.531663 3.025858 4.064217 6.768088 4.38533 10.708217.1165 2.874897-1.906568 5.390793-4.72802 5.87979-1.60677.247488-3.24097-.222463-4.47424-1.28667C1.708891 82.584449.999523 81.032104 1 79.398522c0-3.91986 2.91148-8.66569 4.52603-10.993808.253808-.361094.662427-.58049 1.1022-.591794.439772-.011303.859018.186813 1.130863.534397zM13.734718 60.342578l-.509714.508002c-.95437.958215-1.38955 2.320552-1.168475 3.657919.221076 1.337367 1.071198 2.485157 2.282605 3.081854 1.688917.7901 3.690774.4151 4.982948-.933436l.380197-.377853c3.702414-3.825009 8.408242-6.516699 13.5715-7.762774 1.81347-.395497 3.476936-1.302898 4.794938-2.61558L45 49H20.923644c-1.470305 4.298772-3.934003 8.185956-7.188926 11.342578h0z"
stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
</g>
</symbol>
<symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 86 101" id="drugs">
<title>Drugs</title>
<desc>Two medication pills</desc>
<g transform="translate(1 1)" fill="none" fill-rule="evenodd">
<path
d="M56.065217 54.434783c-15.308152 0-27.71739 7.39076-27.71739 16.508152V81.94837c0 9.11739 12.409238 16.508152 27.71739 16.508152 15.308153 0 27.717392-7.390761 27.717392-16.508152V70.942935c0-9.117392-12.40924-16.508152-27.717392-16.508152z"
fill="#35D78C" fill-rule="nonzero" />
<path
d="M40.475 57.296196L68.833152 85.58587a33.629353 33.629353 0 004.809783-1.881522L45.544022 55.673913A36.629347 36.629347 0 0040.475 57.296196z"
fill="#163A40" fill-rule="nonzero" opacity=".16" />
<path
d="M56.065217 87.451087c-15.308152 0-27.71739-7.39076-27.71739-16.508152V81.94837c0 9.11739 12.409238 16.508152 27.71739 16.508152 15.308153 0 27.717392-7.390761 27.717392-16.508152V70.942935c0 9.117391-12.40924 16.508152-27.717392 16.508152z"
fill="#163A40" fill-rule="nonzero" opacity=".16" />
<path
d="M6.369565 45.325544c-6.720148 6.713294-7.683147 17.269763-2.288637 25.088201s15.605395 10.66523 24.266898 6.765603v-6.236413c0-8.455435 10.680978-15.415761 24.443478-16.382609v-.009783l.877174-.877173L25.84837 25.84674 6.369565 45.325543z"
fill="#92E4CF" fill-rule="nonzero" />
<path
d="M28.347826 77.179348v-6.236413c0-6.510326 6.342391-12.120652 15.536413-14.805979-14.183152.725544-25.319022 7.801631-25.319022 16.436414v6.236413c3.346347.294272 6.712586-.266768 9.78261-1.630435z"
fill="#163A40" fill-rule="nonzero" opacity=".16" />
<path
d="M73.152174 6.369565c-7.695901-7.655597-20.13073-7.655597-27.82663 0L25.84837 25.84674 53.675 53.67337l19.477174-19.477173c7.655597-7.695901 7.655597-20.13073 0-27.82663z"
fill="#35D78C" fill-rule="nonzero" />
<path
d="M9.630435 51.847283l19.478804-19.478805 19.477174-19.477174c7.6959-7.655597 20.13073-7.655597 27.82663 0a19.516308 19.516308 0 011.72663 2.010326c-.901924-3.22526-2.619636-6.163733-4.9875-8.532065-7.6959-7.655597-20.130729-7.655597-27.82663 0L25.84837 25.84674 6.369565 45.325544c-6.926171 6.973825-7.66243 17.982252-1.72663 25.816304-1.94938-6.860213-.042178-14.238386 4.9875-19.294565z"
fill="#FFF" fill-rule="nonzero" opacity=".4" />
<path
d="M59.326087 3.855435c-12.022826.229891-15.269022 11.654348-11.639674 12.63587 3.213587 1.20326 7.928804-.679892 11.639674-.233153 3.71087-.446739 8.427717 1.436413 11.639674.233152 3.629348-.981521.383152-12.405978-11.639674-12.63587z"
fill="#FFF" fill-rule="nonzero" opacity=".5" />
<path
d="M25.84837 25.84837l27.825 27.825m-.869022.877174l20.347826-20.354348c7.655597-7.695901 7.655597-20.13073 0-27.82663-7.695901-7.655598-20.13073-7.655598-27.82663 0L6.369565 45.325543c-7.655597 7.6959-7.655597 20.130729 0 27.82663 5.789905 5.755452 14.524317 7.355249 21.978261 4.025543M40.47174 57.292935l28.372826 28.302717M45.493478 55.62337l28.151087 28.082608"
stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<path
d="M28.347826 70.942935V81.94837c0 9.11739 12.40924 16.508152 27.717391 16.508152 15.308153 0 27.717392-7.390761 27.717392-16.508152V70.942935"
stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<ellipse stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" cx="56.065217"
cy="70.942935" rx="27.717391" ry="16.508152" />
</g>
</symbol>
</svg>
</div>
{% if not request.user.is_authenticated and not request.GET.oh_id %}
{% if request.GET.consent_withdrawn %}
<div class="alert alert-info">{% trans "Your consent has been withdrawn, you will not receive any more daily emails." %}
</div>
{% endif %}
<section id="content" class="questions">
<h2>
{% trans "We will ask you about:" %}
</h2>
<ul class="questions__list">
<li class="question-item">
<div class="question__icon">
<svg width="89" height="93" focusable="false" aria-hidden="true">
<use xlink:href="#bandaid" />
</svg>
</div>
<h3>{% trans "Your physical health" %}</h3>
</li>
<li class="question-item">
<div class="question__icon">
<svg width="88" height="88" focusable="false" aria-hidden="true">
<use xlink:href="#brain" />
</svg>
</div>
<h3>{% trans "Your mental wellbeing" %}</h3>
</li>
<li class="question-item">
<div class="question__icon">
<svg width="80" height="86" focusable="false" aria-hidden="true">
<use xlink:href="#dropper" />
</svg>
</div>
<h3>{% trans "Transmission properties of the virus" %}</h3>
</li>
<li class="question-item">
<div class="question__icon">
<svg width="86" height="101" focusable="false" aria-hidden="true">
<use xlink:href="#drugs" />
</svg>
</div>
<h3>{% trans "Medication repurposing" %}</h3>
</li>
</ul>
<a href="{{ request.openhumans_login_url }}" class="button button--orange questions__button">{% trans "Take the survey" %}</a>
</section>
<section class="approach">
<h2 class="approach__title">{% trans "Our approach" %}</h2>
<div class="approach__cards">
<div class="card">
<h3><a href="{% url "about" %}">{% trans "Citizen Science" %}</a></h3>
<p>
{% blocktrans %}
When it comes to science, we believe in harnessing the ingenuity of all citizens. We want you to contribute your
own survey items according to your research questions and interests.
{% endblocktrans %}
</p>
<a class="card__link" href="{% url "about" %}">{% trans "Become a Citizen Scientist" %}</a>
</div>
<div class="card">
<h3><a href="{% url "data" %}">{% trans "Shared Data, Shared Knowledge" %}</a></h3>
<p>
{% blocktrans %}
De-identified data will be made available to the scientific community, and will be distributed with any
publications that arise from this study.
{% endblocktrans %}
</p>
<a class="card__link" href="{% url "data" %}">{% trans "Access the data" %}</a>
</div>
</div>
</section>
{% else %}
{% include "main/includes/consent.html" %}
{% include "main/includes/daily_emails_activation.html" %}
{% endif %}
{% endblock main %}

View File

@ -0,0 +1,224 @@
{% load i18n %}
<section id="settings" class="consent">
<div>
{% if openhumansmember.surveyaccount.consent_given %}
<h2>{% trans "You have given your consent, however you can still withdraw it at any time." %}</h2>
<div>
<div>
{% else %}
<h2 class="alert alert-warning">
{% trans "You must first consent to the following before getting started with your survey" %}</h2>
{% endif %}
<ol class="consent__list">
<li>
<h3 data-collapse aria-expanded="false">{% trans "What the survey is about ?" %}
<svg xmlns="http://www.w3.org/2000/svg" height="12" width="20" viewbox="0 0 20 12" class="chevron chevron--closed">
<line x1="0" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
<line x1="20" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
</svg>
</h3>
<p class="collapse__item">
{% blocktrans %}
As part of this project, we are carrying out an ongoing survey to collect health data on the current
COVID-19
pandemic. We are doing this in an open and participatory setting, so that everyone can contribute
cooperatively and anonymously to support the global effort to contain the COVID-19 pandemic and learn
lessons
for the future. While most of the world is in a quarantine situation, the majority of COVID-19 patients
are at
home without regular medical monitoring of disease progression, symptoms, recovery or well-being. Data
from
patients reporting symptoms at a distance could provide scientists with indications of the different forms
of
the disease and possible links to parameters such as medical history, physical and mental health, social
distancing, etc. The data could also be used to develop a new approach to the management of the disease.
The survey includes volunteer participants aged 18 years and older. You will be asked to answer a survey
every
day for 2-5 minutes each day, during the pandemic period and until the end of May 2022, with questions
about
the symptoms you are experiencing, how you are doing and some details about your medical history and
demographics.
You will be able to access your data at any time, as well as all anonymized data acquired in this study.
In
addition, as a participant, you will be invited to suggest and discuss new survey questions in an
anonymous
participant forum. Neither answering the survey questions or participation in the forum discussions are
compulsory.
{% endblocktrans %}
</p>
</li>
<li>
<h3 data-collapse aria-expanded="false">{% trans "What are the expected benefits ?" %}
<svg xmlns="http://www.w3.org/2000/svg" height="12" width="20" viewbox="0 0 20 12" class="chevron">
<line x1="0" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
<line x1="20" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
</svg>
</h3>
<p class="collapse__item">
{% blocktrans %}
Participation in this study will not provide you with any direct personal benefit, but may provide
scientists
with new data. Although the risk is minimal, the individual survey questions can sometimes be intrusive.
You
may, of course, choose not to answer these questions, skip them, or terminate your participation. Your
involvement is voluntary; refusal to participate will not result in any penalties or loss of benefits to
which
you are entitled, and you can end your participation (and/or request that your previous data be deleted)
at
any time without consequence.
{% endblocktrans %}
</p>
</li>
<li>
<h3 data-collapse aria-expanded="false">{% trans "What is the survey schedule?" %}
<svg xmlns="http://www.w3.org/2000/svg" height="12" width="20" viewbox="0 0 20 12" class="chevron">
<line x1="0" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
<line x1="20" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
</svg>
</h3>
<p class="collapse__item">
{% blocktrans %}
The study takes place from 1 June 2020 to 31 May 2022. You can stop participating at any time before the
end
of the study.
The research is conducted via an online or SMS survey, a platform to access your data and an anonymous
forum
to discuss new survey items that should be added. Take as much time as you wish before making a decision.
We
will be happy to answer any questions you may have about this study. If you have any further questions
about
this project or if you have a problem with the research, you can contact the study coordinator, Anirudh
Krishnakumar, MSc, by phone at +33 1 84 25 68 04, or by e-mail, anirudh.krishnakumar@cri-paris.org.
{% endblocktrans %}
</p>
</li>
<li>
<h3 data-collapse aria-expanded="false">{% trans "Research Data Users." %}
<svg xmlns="http://www.w3.org/2000/svg" height="12" width="20" viewbox="0 0 20 12" class="chevron">
<line x1="0" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
<line x1="20" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
</svg>
</h3>
<p class="collapse__item">
{% blocktrans %}
All data will be stored on secure servers, protected by firewall and password, of Open Humans &
OpenClinica,
in accordance with European data protection regulations. This study does not collect individual
identifiers
such as name, physical or e-mail addresses. Instead, Open Humans assigns each participant a study
identification number upon registration. Only this study identification number will be accessible by
research
personnel. Finally, participants' data will not be sold and data sharing will be conducted under strict
protocol-based procedural guidelines. Participants will be able to remove their data from the study at any
time.
{% endblocktrans %}
<br/><br/>
<em>
{% blocktrans %}
Note : The governments in some countries / regions may monitor internet traffic.
In some countries / regions, monitoring of data transmitted over the internet may occur.
The researchers cannot control or protect you from risks associated with this monitoring during the submission of your survey responses.
If you are concerned that your personal or health data will be monitored and that this may put you at some risk,
then we recommend that you do not participate in this survey.
{% endblocktrans %}
</em>
</p>
</li>
<li>
<h3 data-collapse aria-expanded="false">
{% trans "What will happen to the data collected for the research ?" %}
<svg xmlns="http://www.w3.org/2000/svg" height="12" width="20" viewbox="0 0 20 12" class="chevron">
<line x1="0" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
<line x1="20" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
</svg>
</h3>
<p class="collapse__item">
{% blocktrans %}
The anonymised data will be made available to all participants and the scientific community, and will be
distributed with all publications resulting from this study. If necessary to protect the privacy of
participants, individual data may be deleted or only shared in aggregate form. This data cannot be used to
identify participants. In addition, each participant will receive a copy of his or her own data as part of
this study.
{% endblocktrans %}
</p>
</li>
<li>
<h3 data-collapse aria-expanded="false">{% trans "What rights do you have ?" %}
<svg xmlns="http://www.w3.org/2000/svg" height="12" width="20" viewbox="0 0 20 12" class="chevron">
<line x1="0" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
<line x1="20" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
</svg>
</h3>
<p class="collapse__item">
{% blocktrans %}
In accordance with the French Data Protection Act of 6 January 1978 as amended and with European
Regulation
n°2016/679/EU of 27 April 2016 ( effective as of 25 May 2018), you may at any time request access,
rectification, withdrawal or request that the data provided about you be communicated to you without
incurring
any liability or prejudice as a result.
Limitations to the exercise of these various rights will be examined in application of Article 89-2 of the
DPMR (European Data Protection Regulation) relating to exceptions in the field of research.
For further information on research, please contact Ariel Lindner (ariel.lindner@inserm.fr).
To exercise these rights or if you have any questions about the processing of your data in this system,
you
can contact our data protection officer, Lionel Devaux (lionel.devaux@cri-pari.org).
If you feel, after contacting us, that your rights to Information Technology and Liberties are not
respected,
you can send a complaint to the CNIL (Commission Nationale Informatique et Libertés www.cnil.fr).
{% endblocktrans %}
</p>
</li>
<li>
<h3 data-collapse aria-expanded="false">{% trans "Information on the results of the survey" %}
<svg xmlns="http://www.w3.org/2000/svg" height="12" width="20" viewbox="0 0 20 12" class="chevron">
<line x1="0" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
<line x1="20" y1="0" x2="10" y2="10" stroke="currentColor" stroke-width="2" />
</svg>
</h3>
<p class="collapse__item">
{% blocktrans %}
You have the right to see the results of this study. As soon as the results are available, we will publish
them openly on the project website on Open Humans and distribute them to all participants.
{% endblocktrans %}
</p>
</li>
</ol>
<ul>
<li>
{% trans "I have read the above information for participants and my questions regarding participation in the study have been answered satisfactorily." %}
</li>
<li>
{% trans "I know that I can print this information or request a copy at any time and that I can withdraw from the study at any time without giving reasons and without any negative consequences." %}
</li>
<li>
{% trans "I agree that the Principal Investigators and their collaborators may have access to the original data in strict compliance with the rules of confidentiality." %}
</li>
<li>
{% trans "I am aware that the investigator may, without mutual consent, exclude me from the study if I do not meet the inclusion criteria." %}
</li>
<li>
{% trans 'By clicking on the "ACCEPT" button, I certify that I accept all the above-mentioned points and that I am participating in this study on a voluntary basis.' %}
</li>
</ul>
{% if openhumansmember.surveyaccount.consent_given %}
</div>
</div>
{% endif %}
</div>
<form action="{% url "consent" %}" method="POST">
{% csrf_token %}
<button type="submit" class="button--orange" role="button">
{% if openhumansmember.surveyaccount.consent_given %}
{% trans "WITHDRAW MY CONSENT" %}
{% else %}
{% trans "ACCEPT" %}
{% endif %}
</button>
</form>
</section>

View File

@ -0,0 +1,22 @@
{% load i18n %}
<section class="daily-emails">
{% if openhumansmember.surveyaccount.daily_emails_activated %}
<p>{% blocktrans %}The daily emails are activated. You can choose to deactivate them, without withdrawing your consent to participate in the survey. Your past responses will stay usable.{% endblocktrans %}</p>
{% else %}
<p>{% blocktrans %}You have chosen to deactivate the daily emails. Your past responses will stay usable.{% endblocktrans %}</p>
{% endif %}
<form action="{% url "daily_emails" %}" method="POST">
{% csrf_token %}
<button type="submit" class="button--orange"
role="button"
>
{% if openhumansmember.surveyaccount.daily_emails_activated %}
{% trans "DEACTIVATE DAILY EMAILS" %}
{% else %}
{% trans "ACTIVATE DAILY EMAILS" %}
{% endif %}
</button>
</form>
</section>

View File

@ -0,0 +1,38 @@
{% extends 'base.html' %}
{% load static %}
{% load i18n %}
{% block intro %}
<section class="intro">
<div class="intro-content">
<h1>{% trans "Meet the Team!" %}</h1>
<h2>{% trans "Members from around the world" %}</h2>
<p>
{% blocktrans %}
Meet the team behind OpenCovid and learn a bit more about their background.
{% endblocktrans %}
</p>
</div>
</section>
{% endblock intro %}
{% block main %}
<section>
{% comment %}
<pre><code>{{ persons }}</code></pre> {% endcomment %}
<ul class="team__list">
{% for person in persons %}
<li class="card card--team">
{% if person.link%}
<h3><a href='{{person.link}}'>{{ person.name }}</a></h3>
{%else%}
<h3>{{ person.name }}</h3>
{%endif%}
<p>
{% trans person.description %}
</p>
</li>
{% endfor %}
</ul>
</section>
{% endblock main %}

3
main/tests.py Normal file
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

222
main/views.py Normal file
View File

@ -0,0 +1,222 @@
from django.views.i18n import set_language
from django.views.generic import TemplateView
from django.views.generic.base import View
from openhumans.models import OpenHumansMember
from .models import ReportToken
from django.contrib.auth import logout
from django.contrib import messages
from django.utils.translation import gettext_lazy as _
from django.shortcuts import redirect
from django.conf import settings
from django.urls import reverse
from django.views.decorators.http import require_POST
from django.contrib.auth.decorators import login_required
from django.contrib.auth import login as auth_login
from django.contrib.auth import logout as auth_logout
from django.http import HttpResponseForbidden
import datetime
import json
from .helpers import create_openclinica_event, get_openclinica_token, send_user_survey_link
import logging
logger = logging.getLogger(__name__)
class HomeView(TemplateView):
template_name = "main/home.html"
def dispatch(self, request, *args, **kwargs):
if self.request.user.is_authenticated:
try:
self.files = self.request.user.openhumansmember.list_files()
except Exception:
logout(request)
return redirect("/")
return super().dispatch(request, *args, **kwargs)
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
if self.request.user.is_authenticated:
openhumansmember = self.request.user.openhumansmember
context.update(
{
"openhumansmember": openhumansmember,
"files": self.files
}
)
# Not logged in.
else:
context.update({"openhumans_login_url": OpenHumansMember.get_auth_url()})
return context
def autologin(request, oh_id):
if not request.user.is_authenticated:
token_string = request.GET.get("login_token", None)
if token_string:
token = ReportToken.objects.get(token=token_string)
if token.is_valid():
try:
oh_member = OpenHumansMember.objects.get(oh_id=oh_id)
auth_login(request, oh_member.user)
except:
pass
if request.user.is_authenticated:
if request.GET.get('next'):
return redirect(request.GET['next'])
else:
return redirect('home')
else:
return HttpResponseForbidden()
@login_required()
@require_POST
def consent(request):
survey_member = request.user.openhumansmember.surveyaccount
if survey_member.consent_given == False:
survey_member.consent_given = True
survey_member.save()
if survey_member.last_email == datetime.date.today():
messages.add_message(request, messages.INFO, _("Your consent has been saved. You should already "
"have gotten an email earlier today to get started "
"with your survey!"))
else:
get_openclinica_token(survey_member)
send_user_survey_link(survey_member)
messages.add_message(request, messages.INFO, _("Your consent has been saved. You should now get "
"an email to get started with your survey!"))
else:
survey_member.consent_given = False
survey_member.save()
messages.add_message(request, messages.INFO, _("Your consent has been withdrawn, you will not "
"receive any more daily emails."))
return redirect("home")
@login_required()
@require_POST
def daily_emails(request):
survey_member = request.user.openhumansmember.surveyaccount
if survey_member.daily_emails_activated == False:
survey_member.daily_emails_activated = True
survey_member.save()
messages.add_message(request, messages.INFO, _("You have activated the daily emails."))
else:
survey_member.daily_emails_activated = False
survey_member.save()
messages.add_message(request, messages.INFO, _("You have deactivated the daily emails."))
return redirect("home")
@login_required()
def take_survey(request):
oh_member = request.user.openhumansmember
survey_member = oh_member.surveyaccount
if survey_member.consent_given:
if survey_member.last_survey != datetime.date.today():
create_openclinica_event(survey_member, "SE_DAILY", str(datetime.date.today()))
survey_member.last_survey = datetime.date.today()
survey_member.save()
return redirect(settings.OPENCLINICA_PARTICIPATE_LINK + "?accessCode={}".format(survey_member.survey_token))
else:
return redirect('home')
def logout_user(request):
"""
Logout user.
"""
if request.method == "POST":
logout(request)
redirect_url = settings.LOGOUT_REDIRECT_URL
if not redirect_url:
redirect_url = "home"
return redirect(redirect_url)
class FaqView(TemplateView):
template_name = "main/faq.html"
def dispatch(self, request, *args, **kwargs):
if self.request.user.is_authenticated:
try:
self.files = self.request.user.openhumansmember.list_files()
except Exception:
logout(request)
return redirect("/")
return super().dispatch(request, *args, **kwargs)
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
if self.request.user.is_authenticated:
context.update(
{
"files": self.files
}
)
return context
class TeamView(TemplateView):
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
with open('./src/_data/team.json') as team:
context["persons"] = json.load(team)
return context
template_name = "main/team.html"
class VisionView(TemplateView):
template_name = "main/vision.html"
class AboutView(TemplateView):
template_name = "main/about.html"
class DataView(TemplateView):
template_name = "main/data.html"
def set_language_custom(request):
if request.user.is_authenticated and request.POST.get('language'):
if request.POST['language'] in [lang[0] for lang in settings.LANGUAGES]:
request.user.openhumansmember.surveyaccount.language = request.POST['language']
request.user.openhumansmember.surveyaccount.save()
return set_language(request)
@login_required
def delete_all_openhuman_files(request):
oh_member = request.user.openhumansmember
oh_member.delete_all_files()
return redirect('faq')
@login_required
def delete_all(request):
oh_member = request.user.openhumansmember
oh_member.delete_all_files()
user = request.user
auth_logout(request)
user.delete()
return redirect('faq')

21
manage.py Executable file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'open_survey.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()

0
open_survey/__init__.py Normal file
View File

16
open_survey/asgi.py Normal file
View File

@ -0,0 +1,16 @@
"""
ASGI config for open_survey project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/3.0/howto/deployment/asgi/
"""
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'open_survey.settings')
application = get_asgi_application()

181
open_survey/settings.py Normal file
View File

@ -0,0 +1,181 @@
"""
Django settings for open_survey project.
Generated by 'django-admin startproject' using Django 3.0.6.
For more information on this file, see
https://docs.djangoproject.com/en/3.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.0/ref/settings/
"""
import os
import django_heroku
from django.utils.translation import gettext_lazy as _
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.getenv("SECRET_KEY")
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = os.getenv("DEBUG", "False").lower() == "true"
ALLOWED_HOSTS = ["*"]
ON_HEROKU = os.getenv("ON_HEROKU", "False").lower() == "true"
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'openhumans',
'main'
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'main.middleware.LoginLangMiddleware',
'main.middleware.OpenHumansLoginUrlMiddleware',
]
ROOT_URLCONF = 'open_survey.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'open_survey.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Password validation
# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/3.0/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
LANGUAGES = [
('en', _('English')),
('fr', _('French')),
('de', _('German')),
('es', _('Spanish'))
]
LOCALE_PATHS = (
'locale',
)
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/
STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
STATICFILES_DIRS = [os.path.join(BASE_DIR, "static")]
STATIC_URL = "/static/"
MEDIA_ROOT = os.path.join(BASE_DIR, "managedfiles")
MEDIA_URL = "/files/"
# Open Humans configuration
OPENHUMANS_APP_BASE_URL = os.getenv("OPENHUMANS_APP_BASE_URL", "http://localhost:5000")
OPENHUMANS_CLIENT_ID = os.getenv("OPENHUMANS_CLIENT_ID", "your_client_id")
OPENHUMANS_CLIENT_SECRET = os.getenv("OPENHUMANS_CLIENT_SECRET", "your_client_secret")
LOGIN_REDIRECT_URL = "/"
LOGOUT_REDIRECT_URL = "/"
# OC user for adding new participants & scheduling events
OPENCLINICA_SITE_USERNAME = os.getenv("OPENCLINICA_USERNAME", "OPENCLINICA_TOKEN")
OPENCLINICA_SITE_PASSWORD = os.getenv("OPENCLINICA_PASSWORD", "OPENCLINICA_TOKEN")
# OC user for exporting data from participants
OPENCLINICA_DATA_USERNAME = os.getenv("OPENCLINICA_DATA_USERNAME", "OPENCLINICA_TOKEN")
OPENCLINICA_DATA_PASSWORD = os.getenv("OPENCLINICA_DATA_PASSWORD", "OPENCLINICA_TOKEN")
OPENCLINICA_STUDY = os.getenv("OPENCLINICA_STUDY", "OPENCLINICA_STUDY ")
OPENCLINICA_SITE = os.getenv("OPENCLINICA_SITE", "OPENCLINICA_SITE")
OPENCLINICA_PARTICIPATE_LINK = os.getenv("OPENCLINICA_PARTICIPATE_LINK", "OPENCLINICA_PARTICIPATE_LINK")
if ON_HEROKU:
django_heroku.settings(locals())
REMOTE = os.getenv("REMOTE")
if REMOTE:
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True

26
open_survey/urls.py Normal file
View File

@ -0,0 +1,26 @@
from django.contrib import admin
from django.urls import path, include
from main.views import HomeView, consent, daily_emails, autologin, logout_user, take_survey, FaqView, VisionView, \
AboutView, DataView, TeamView, set_language_custom, delete_all_openhuman_files, delete_all
urlpatterns = [
path("admin/", admin.site.urls),
path("", HomeView.as_view(), name="home"),
path("autologin/<int:oh_id>/", autologin, name="autologin"),
path("consent/", consent, name="consent"),
path("daily_emails/", daily_emails, name="daily_emails"),
path("logout/", logout_user, name="logout"),
path("survey/", take_survey, name="take_survey"),
path("team/", TeamView.as_view(), name="team"),
path("faq/", FaqView.as_view(), name="faq"),
# path("vision/", VisionView.as_view(), name="vision"),
path("about/", AboutView.as_view(), name="about"),
path("data/", DataView.as_view(), name="data"),
path("delete-all-openhuman-files/", delete_all_openhuman_files, name="delete_all_openhuman_files"),
path("delete-all/", delete_all, name="delete_all"),
path("i18n/", set_language_custom, name="set_language_custom"),
]
urlpatterns += [path("openhumans/", include("openhumans.urls"))]

16
open_survey/wsgi.py Normal file
View File

@ -0,0 +1,16 @@
"""
WSGI config for open_survey project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/3.0/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'open_survey.settings')
application = get_wsgi_application()

20
package.json Normal file
View File

@ -0,0 +1,20 @@
{
"name": "co-op-postcss",
"version": "1.0.0",
"license": "MIT",
"scripts": {
"build:css": "postcss src/css/style.css -o static/css/style.min.css",
"watch:css": "postcss src/css/style.css -o static/css/style.min.css --watch",
"build": "npm run build:css",
"watch": "npm run watch:css"
},
"devDependencies": {
"autoprefixer": "^9.8.0",
"css-mqpacker": "^7.0.0",
"cssnano": "^4.1.10",
"postcss": "^7.0.32",
"postcss-cli": "^7.1.1",
"postcss-custom-properties": "^9.1.1",
"postcss-import": "^12.0.1"
}
}

17
postcss.config.js Normal file
View File

@ -0,0 +1,17 @@
const postcssAutoprefixer = require("autoprefixer");
const postcssCustomProperties = require("postcss-custom-properties");
const postcssMqpacker = require("css-mqpacker");
const postcssImport = require("postcss-import");
const postcssNANO = require("cssnano");
module.exports = {
plugins: [
postcssImport(),
postcssAutoprefixer(),
postcssCustomProperties(),
// postcssMqpacker(),
postcssNANO({
preset: "default",
}),
],
};

65
src/_data/team.json Normal file
View File

@ -0,0 +1,65 @@
[
{
"name": "Anneke Blackburn",
"link": "https://researchers.anu.edu.au/researchers/blackburn-ac",
"description": "Associate Professor at the Department of Cancer Biology and Therapy, John Curtin School of Medical Research, Australian National University."
},
{
"name": "Geoffrey Siwo",
"link": "https://www.siworesearch.com/",
"description": "Research Assistant Professor at the Center for Research Computing & Eck Institute for Global Health, University of Notre Dame, IN, USA"
},
{
"name": "Marc-Aurèle Chay",
"link": "https://www.linkedin.com/in/marc-aur%C3%A8le-marcus-chay-b16793a1/",
"description": "3rd year medical student at McGill University in Montreal. Did a Masters in human genetics before getting interested in global health."
},
{
"name": "Spark Yaddav",
"link": "http://ca.linkedin.com/in/spark-y",
"description": "Molecular Biology, Medical Biochemistry and Biophysics Researcher. CRI-affiliate. Previously: Researcher at SciLifeLab, KI, Stockholm, Sweden and Bionanoscience, TU Delft, The Netherlands."
},
{
"name": "Anirudh Krishnakumar",
"description": "PhD student at the INSERM U1284 unit at the Center for Interdisciplinary Research, University of Paris & the Child Mind Institute, New York."
},
{
"name": "Bastian Greshake Tzovaras",
"link": "https://tzovar.as",
"description": "Research fellow at the INSERM U1284 unit at the Center for Interdisciplinary Research, University of Paris and Director of Research / freelance consultant for OpenHumans.org."
},
{
"name": "Mad Price Ball",
"link": "http://www.madpriceball.net/",
"description": "Executive Director & Co-Founder of OpenHumans.org and started quantifiedflu.org with Bastian Greshake Tzovaras."
},
{
"name": "Ariel B. Lindner",
"link": "https://research.cri-paris.org/profile?id=c764de6f-735c-4164-beb7-6ec12e99a40c",
"description": "Co-Founder & Research Director at the INSERM U1284 unit at the Center for Interdisciplinary Research, University of Paris"
},
{
"name": "Natalia Norori",
"link": "https://www.linkedin.com/in/natalianorori/",
"description": "Medical Student. She also works for Open Access Button, a non-profit project that helps people get access to research."
},
{
"name": "Bastien Cohin",
"description": "Medical student at the Université de Caen-Normandie, he is concurrently doing a masters in Biology-Health."
},
{
"name": "Kseniia Konishcheva",
"link": "https://www.linkedin.com/in/kkonishcheva42/",
"description": "Life Sciences Master's student, intern at the Center for Interdisciplinary Research, University of Paris & the Child Mind Institute, New York."
},
{
"name": "Alice Motion",
"link": "https://www.sydney.edu.au/science/about/our-people/academic-staff/alice-motion.html",
"description": "Associate Professor at the School of Chemistry, University of Sydney, Australia. Director of SCOPE Research Group, CRI Research Fellow 2019."
},
{
"name": "Nico Arduin",
"link": "https://www.nardu.in/",
"description": "Freelance web designer and developer. Contributes to open source projects on the side."
}
]

349
src/css/_vendor/normalize.css vendored Normal file
View File

@ -0,0 +1,349 @@
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
/* Document
========================================================================== */
/**
* 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in iOS.
*/
html {
line-height: 1.15; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers.
*/
body {
margin: 0;
}
/**
* Render the `main` element consistently in IE.
*/
main {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/* Grouping content
========================================================================== */
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/* Text-level semantics
========================================================================== */
/**
* Remove the gray background on active links in IE 10.
*/
a {
background-color: transparent;
}
/**
* 1. Remove the bottom border in Chrome 57-
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none; /* 1 */
text-decoration: underline; /* 2 */
text-decoration: underline dotted; /* 2 */
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Remove the border on images inside links in IE 10.
*/
img {
border-style: none;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers.
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit; /* 1 */
font-size: 100%; /* 1 */
line-height: 1.15; /* 1 */
margin: 0; /* 2 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input { /* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select { /* 1 */
text-transform: none;
}
/**
* Correct the inability to style clickable types in iOS and Safari.
*/
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Correct the padding in Firefox.
*/
fieldset {
padding: 0.35em 0.75em 0.625em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box; /* 1 */
color: inherit; /* 2 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
white-space: normal; /* 1 */
}
/**
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
vertical-align: baseline;
}
/**
* Remove the default vertical scrollbar in IE 10+.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10.
* 2. Remove the padding in IE 10.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type="search"] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/**
* Remove the inner padding in Chrome and Safari on macOS.
*/
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in Edge, IE 10+, and Firefox.
*/
details {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
}
/* Misc
========================================================================== */
/**
* Add the correct display in IE 10+.
*/
template {
display: none;
}
/**
* Add the correct display in IE 10.
*/
[hidden] {
display: none;
}

308
src/css/parts/base.css Normal file
View File

@ -0,0 +1,308 @@
@font-face {
font-family: "Geomanist";
src: url("../fonts/geomanist-light.woff") format("woff"),
url("../fonts/geomanist-light.woff2") format("woff2");
font-weight: 300;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "Geomanist";
src: url("../fonts/geomanist-book.woff") format("woff"),
url("../fonts/geomanist-book.woff2") format("woff2");
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "Geomanist";
src: url("../fonts/geomanist-bold.woff") format("woff"),
url("../fonts/geomanist-bold.woff2") format("woff2");
font-weight: bold;
font-style: normal;
font-display: swap;
}
html {
/* switching to border-box model for all elements */
box-sizing: border-box;
/* set base font-size to equiv "10px", which is adapted to rem unit */
font-size: 62.5%;
/* IE9-IE11 math fixing. See http://bit.ly/1g4X0bX */
font-size: calc(1em * 0.625);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
scroll-behavior: smooth;
}
:root {
--dark: #042b32;
--light: #d5f1ea;
--green: #35d78c;
--blue: #00c4ac;
--yellow: #ffd13c;
--orange: #ffa318;
--white: #ffffff;
}
*,
*::before,
*::after {
box-sizing: inherit;
}
::placeholder {
color: gray;
}
body {
margin: 0;
position: relative;
font-size: 1.8rem;
color: var(--dark);
font-family: "Geomanist", "Helvetica", "Arial", sans-serif;
font-weight: normal;
line-height: 2.4rem;
text-rendering: optimizeLegibility;
overflow-x: hidden;
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 0;
padding: 0;
font-weight: bold;
line-height: 1.2;
}
h1 {
font-size: 4rem;
margin: 0 0 16px;
padding: 0;
position: relative;
}
h1::after {
content: "";
position: absolute;
bottom: 0;
left: 0;
width: 50px;
height: 4px;
background-color: var(--dark);
}
h2 {
font-size: 3.2rem;
}
h3 {
font-size: 2.4rem;
}
section {
margin: 60px 0;
}
article {
margin: 40px 0;
}
article h2 {
margin-bottom: 30px;
}
article h3 {
margin: 30px 0 16px;
}
article p {
margin: 12px 0;
}
article ul {
position: relative;
padding-left: 1em;
}
article ul > li::before {
content: "\2022";
display: inline-block;
margin-left: -1em;
width: 1em;
color: var(--blue);
vertical-align: baseline;
}
a,
a:visited {
text-decoration: underline;
color: inherit;
}
a:hover,
a:focus {
text-decoration: none;
}
p {
padding: 0;
margin: 0;
margin-top: 12px;
}
strong,
b {
font-weight: bold;
font-style: normal;
}
img {
max-width: 100%;
height: auto;
}
ul {
list-style-type: none;
padding: 0;
margin: 0;
}
ol {
padding: 0 0 0 1em;
margin: 0;
}
ul > li,
ol > li {
padding: 0;
margin: 1.4rem 0;
}
pre,
code,
kbd,
samp {
position: relative;
}
button,
.button {
margin: 12px 0;
padding: 16px 20px;
display: block;
max-width: 200px;
font-size: 2.2rem;
font-weight: bold;
text-align: center;
text-decoration: none;
color: var(--dark);
border: none;
border-radius: 2px;
cursor: pointer;
box-shadow: none;
}
button:focus,
.button:focus {
outline: solid 4px cornflowerblue;
}
.button--white {
background-color: white;
transition: background-color 0.3s ease, color 0.3s ease;
}
.button--white:focus {
outline: solid 4px var(--dark);
}
.button--white:hover {
color: white;
background-color: var(--dark);
}
.button--orange {
background-size: 200% auto;
background-image: linear-gradient(
to right,
var(--orange) 0%,
var(--yellow) 100%
);
transition: background-position 0.3s ease;
}
.button--orange:hover {
background-position: right center;
}
.no-btn {
padding: 0;
margin: 0;
background: transparent;
font-size: inherit;
font-weight: inherit;
line-height: inherit;
border: none;
border-radius: none;
color: inherit;
box-shadow: none;
}
.container {
padding: 0 10px;
margin-left: auto;
margin-right: auto;
max-width: 980px;
}
.chevron {
margin-left: 6px;
transition: transform 0.4s ease;
transform: rotate(0deg);
transform-origin: 50% 40%;
}
.collapse__item {
overflow: hidden;
max-height: 0;
opacity: 0;
transition: max-height 0.4s ease, opacity 0.2s ease;
}
[data-collapse] {
cursor: pointer;
}
.collapse--open + .collapse__item {
max-height: 1140px;
opacity: 1;
}
.collapse--open > .chevron {
transform: rotate(180deg);
}
.u-hidden {
border: 0 !important;
clip: rect(1px, 1px, 1px, 1px) !important;
height: 1px !important;
overflow: hidden !important;
padding: 0 !important;
position: absolute !important;
white-space: nowrap !important;
width: 1px !important;
}
@media screen and (min-width: 700px) {
h1 {
font-size: 6rem;
line-height: 1;
margin-bottom: 20px;
padding: 0;
}
h1::after {
width: 80px;
height: 8px;
bottom: -6px;
}
h2 {
font-size: 4rem;
}
h3 {
font-size: 2.8rem;
}
.container {
padding: 0 20px;
}
}
@media screen and (min-width: 1000px) {
section {
margin: 80px 0;
}
article {
margin: 60px 0;
}
}

14
src/css/parts/card.css Normal file
View File

@ -0,0 +1,14 @@
.card {
padding: 14px;
margin: 40px 0;
background: #ffffff;
box-shadow: 0 8px 20px 0 rgba(22, 58, 64, 0.2),
0 4px 12px 0 rgba(22, 58, 64, 0.1);
border-radius: 6px;
}
@media screen and (min-width: 700px) {
.card {
padding: 30px;
}
}

View File

@ -0,0 +1,3 @@
.consent__list {
margin: 40px 0;
}

56
src/css/parts/footer.css Normal file
View File

@ -0,0 +1,56 @@
.footer {
margin: 80px 0 0;
padding: 0;
color: white;
background-color: var(--dark);
}
.footer__content {
padding: 20px 10px;
display: flex;
flex-flow: column nowrap;
align-items: center;
}
.footer__logos,
.footer__nav,
.footer__links {
text-align: center;
}
.footer__logo {
margin: 10px;
display: inline-block;
}
.footer__link {
margin: 10px 5px;
display: inline-block;
}
@media screen and (min-width: 1000px) {
.footer__content {
flex-flow: row nowrap;
align-items: flex-start;
justify-content: space-between;
}
.footer__logos,
.footer__nav,
.footer__links {
text-align: left;
flex-grow: 1;
}
.footer__logos {
padding-right: 6px;
flex: 1 1 60%;
width: 60%;
align-self: center;
}
.footer__nav {
padding: 0 6px;
}
.footer__links {
padding-left: 6px;
}
.footer__link {
margin: 10px 0;
display: block;
}
}

148
src/css/parts/header.css Normal file
View File

@ -0,0 +1,148 @@
.header {
position: fixed;
top: 0;
left: 50%;
width: 100%;
margin: 0 auto 20px auto;
padding: 20px 10px 0 10px;
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
align-items: center;
max-width: 980px;
opacity: 0;
z-index: 99;
transform: translateX(-50%);
transition-property: opacity, background-color;
transition-duration: 0.3s;
transition-timing-function: ease;
}
.header.isVisible {
opacity: 1;
}
/* header.hasBackground {
background-color: var(--dark);
} */
.logo {
display: flex;
flex-flow: row nowrap;
align-items: center;
z-index: 10;
}
.logo-background {
fill: transparent;
transition: fill 0.3s ease;
}
.logo-chain {
fill: var(--dark);
transition: fill 0.3s ease;
}
.hasBackground .logo-chain {
fill: var(--white);
}
.burger-menu {
padding: 10px;
position: relative;
z-index: 10;
}
.navbar {
margin: 0;
padding: 20px 40px;
position: fixed;
top: 0;
left: 0;
bottom: 0;
visibility: hidden;
display: flex;
flex-flow: column nowrap;
justify-content: center;
align-items: center;
width: 100%;
background-color: var(--dark);
color: white;
pointer-events: none;
}
.navbar.isOpen {
height: 100vh;
visibility: visible;
pointer-events: all;
z-index: 9;
}
.header__link {
position: relative;
display: inline-block;
text-decoration: none;
text-align: center;
}
.header__link::after {
content: "";
position: absolute;
left: 0;
bottom: -2px;
width: 100%;
height: 2px;
text-decoration: none;
transform: scaleX(1);
transform-origin: 0% 50%;
background-color: var(--dark);
transition: transform 0.4s cubic-bezier(0.77, 0, 0.175, 1), color 0.3s ease;
}
.header__link:hover::after {
transform: scaleX(0);
}
.hasBackground .header__link::after {
background-color: white;
}
@media screen and (min-width: 700px) {
.header {
display: flex;
margin: 0;
padding: 20px;
flex-flow: row nowrap;
}
.header::before {
content: "";
position: absolute;
top: 0;
left: 50%;
height: 100%;
width: 100vw;
transform: translateX(-50%);
opacity: 0;
background-color: var(--dark);
transition: opacity 0.3s ease;
}
.header.hasBackground::before {
opacity: 1;
}
.header__nav {
flex-grow: 1;
}
.burger-menu {
display: none;
}
.navbar {
padding: 0;
position: relative;
flex-flow: row nowrap;
justify-content: flex-end;
visibility: visible;
font-size: 1.6rem;
background-color: transparent;
pointer-events: all;
color: var(--dark);
transition: color 0.3s ease;
}
.header.hasBackground .navbar {
color: white;
}
.navbar__item:not(:last-child) {
padding-right: 12px;
}
}

98
src/css/parts/home.css Normal file
View File

@ -0,0 +1,98 @@
/* intro */
.hp-intro__illustration {
display: none;
}
/* Question list */
.questions {
text-align: center;
}
.questions__list {
display: block;
}
.question-item {
margin: 40px 0;
}
.question__icon {
padding: 20px;
margin: 0 auto 16px;
display: flex;
justify-content: center;
align-items: center;
height: 140px;
width: 140px;
border-radius: 50%;
background-color: var(--light);
}
.questions__button {
margin-left: auto;
margin-right: auto;
}
/* Approach */
.approach__title {
text-align: center;
}
.card__link {
margin: 12px 0 0;
display: block;
}
@media screen and (min-width: 700px) {
.intro-content--hp {
max-width: 75%;
}
.questions__list {
display: flex;
flex-flow: row wrap;
align-items: center;
justify-content: space-between;
}
.question-item {
flex: 0 0 48%;
}
.approach__cards {
display: flex;
flex-flow: row wrap;
justify-content: space-between;
/* align-items: flex-start; */
}
.approach__cards .card {
flex: 0 0 0%;
/* IE 11 fix */
min-width: 48%;
}
}
@media screen and (min-width: 1000px) {
.hp-intro {
padding-right: 0;
min-height: initial;
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
align-items: center;
}
.hp-intro {
padding-top: 118px;
}
.hp-intro::before {
background-size: cover;
background-position: 20% 100%;
}
.hp-intro__illustration {
display: block;
}
.intro-content--hp,
.hp-intro__illustration {
flex: 0 0 48%;
}
.questions__list {
align-items: flex-start;
}
.question-item {
flex: 0 0 24%;
}
.questions__button {
margin-top: 20px;
}
}

46
src/css/parts/intro.css Normal file
View File

@ -0,0 +1,46 @@
.intro {
padding: 110px 0;
margin-bottom: 60px;
margin-top: 0;
min-height: 450px;
position: relative;
z-index: 9;
}
.intro::before {
content: "";
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
width: 100vw;
height: 100%;
z-index: -1;
background-image: url(../../static/img/wave-full.svg);
background-repeat: no-repeat;
background-size: cover;
background-position: 40% bottom;
}
.intro-content {
max-width: 90%;
}
@media screen and (min-width: 500px) {
.intro-content {
max-width: 75%;
}
}
@media screen and (min-width: 700px) {
.intro-content {
max-width: 50%;
}
}
@media screen and (min-width: 1200px) {
.intro::before {
background-size: 100vw;
background-position: bottom left;
}
.intro-content {
max-width: 460px;
}
}

10
src/css/parts/team.css Normal file
View File

@ -0,0 +1,10 @@
.team__list {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
/* justify-items: center; */
}
.card--team {
margin: 10px 0;
}

11
src/css/style.css Normal file
View File

@ -0,0 +1,11 @@
/* normalize */
@import "_vendor/normalize.css";
/* styles */
@import "parts/base.css";
@import "parts/card.css";
@import "parts/header.css";
@import "parts/footer.css";
@import "parts/intro.css";
@import "parts/home.css";
@import "parts/consent.css";
@import "parts/team.css";

1
static/css/style.min.css vendored Normal file

File diff suppressed because one or more lines are too long

BIN
static/fonts/geomanist-bold.woff Executable file

Binary file not shown.

BIN
static/fonts/geomanist-bold.woff2 Executable file

Binary file not shown.

BIN
static/fonts/geomanist-book.woff Executable file

Binary file not shown.

BIN
static/fonts/geomanist-book.woff2 Executable file

Binary file not shown.

BIN
static/fonts/geomanist-light.woff Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 B

BIN
static/img/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
static/img/icon-192x192.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

View File

@ -0,0 +1,22 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol viewBox="0 0 89 93" id="brain">
<title>Mental wellbeing</title>
<desc>A brain seen from above</desc>
<g fill="none" fill-rule="evenodd"><path d="M44.085106 4.331128c-.099239-.00055-.194073-.03983-.263127-.108982-.967876-.947996-4.79014-3.70241-15.12441-1.195819C16.309061 6.03155 1 20.266416 1 52.292255c0 32.025838 25.389438 38.815579 33.852584 38.815579 6.204255 0 8.275418-1.607861 8.937082-2.463297.068274-.092663.178044-.148132.29544-.14929" fill="#35D78C" fill-rule="nonzero"/><path d="M11.771277 44.703189c0-19.930047 5.898043-32.98472 13.33484-40.744775C13.540843 8.673724 1 23.123532 1 52.187809c0 32.112014 25.389438 38.920025 33.852584 38.920025 6.204255 0 8.275418-1.612187 8.937082-2.469925.068274-.092912.178044-.14853.29544-.149692v-4.93985c-9.623366-.748462-32.31383-8.487559-32.31383-38.845178z" fill="#163A40" fill-rule="nonzero" opacity=".16"/><path d="M59.472644 3.026366c-10.33427-2.50659-14.156535.247823-15.12441 1.194325-.068796.069703-.163663.109533-.263128.110475V88.50122c.117396.001159.227167.056628.295441.149291.661664.849464 2.732827 2.457324 8.937082 2.457324 8.463146 0 33.852584-6.789738 33.852584-38.815562 0-32.025825-15.309062-46.260686-27.697569-49.265906z" fill="#35D78C" fill-rule="nonzero"/><path d="M45.32192 4.220691c-.067352.069703-.160229.109533-.257607.110475V88.50122c.114933.001159.222402.056628.289243.149291.647783.849464 2.675495 2.457324 8.74959 2.457324 11.78068-.617525 22.417247-7.183249 28.171032-17.389372-23.049026 16.9415-26.664559-16.947472-26.664559-34.862346 0-15.26198 1.098218-33.760582 8.873122-34.29355-1.400003-.644803-2.857523-1.159087-4.353705-1.5362C50.011568.519776 46.26949 3.27419 45.32192 4.220691z" fill="#163A40" fill-rule="nonzero" opacity=".16"/><path d="M26.228418 3.958414c3.341717.510248 5.878359 3.200936 6.11543 6.48681M12.19962 14.9117c10.758572 2.541425 7.930185 11.983553 7.930185 11.983553m-4.60339 5.882347s.285896-7.444125 9.173145-5.9553M1.979207 47.378506c5.82189-8.137918 18.13378-6.465967 21.191496 3.955808m-7.644288 5.264485c3.057715-5.9553 10.702003-7.444125 15.288576-1.488825M24.699561 38.7329c4.988662 0 10.702003 2.97765 10.702003 10.421775m9.173146-11.9106c-4.586573-1.488825-10.468088-.461535-12.524402 4.019828m.29354-23.374553c4.586574 1.488825 6.115431 8.93295 3.057716 13.399425m9.173146-5.9553c-2.398234-1.054234-5.131875-1.121336-7.581605-.186103M7.59623 74.4647c6.16894-.334986 11.24322-5.57416 11.24322-10.018303m-7.899608-.403472c7.644288-1.488825 11.399162 1.122574 12.23086 5.9553M38.732946 68.2295c-10.702004-1.488825-18.0818 12.56866-8.237485 21.899127m1.848389-30.552178c6.11543 1.488825 9.173146 10.421775 3.057715 16.377075m-8.67321-61.914276c.83072-1.87231 2.587594-3.200392 4.656199-3.51978s4.161169.414348 5.545869 1.944603m25.99058-8.505657c-3.341718.510248-5.87836 3.200936-6.115431 6.48681M76.949799 14.9117c-10.75857 2.541425-7.930184 11.983553-7.930184 11.983553m4.60339 5.882347s-.285896-7.444125-9.173146-5.9553m22.720354 20.556207c-5.82189-8.137918-18.13378-6.465967-21.191496 3.955808m7.644288 5.264485c-3.057715-5.9553-10.702003-7.444125-15.288576-1.488825m6.11543-16.377075c-4.988662 0-10.702003 2.97765-10.702003 10.421775m-9.173146-11.9106c4.586573-1.488825 10.468088-.461535 12.524402 4.019828m-.293541-23.374553c-4.586573 1.488825-6.11543 8.93295-3.057715 13.399425m-9.173146-5.9553c2.398234-1.054234 5.131874-1.121336 7.581605-.186103M81.554719 74.4647c-6.168941-.334986-11.24322-5.57416-11.24322-10.018303m7.89808-.403472c-7.64429-1.488825-11.399164 1.122574-12.230862 5.9553M50.416475 68.2295c10.702003-1.488825 18.0818 12.56866 8.237485 21.899127M56.80557 59.576449c-6.11543 1.488825-9.173146 10.421775-3.057715 16.377075m8.67321-61.914276c-.83072-1.87231-2.587594-3.200392-4.6562-3.51978-2.068605-.319388-4.161168.414348-5.545868 1.944603" stroke="#163A40" stroke-linecap="round" stroke-linejoin="round"/><path d="M44.085106 4.331166c-.099239-.00055-.194073-.039829-.263127-.108982-.967876-.947995-4.79014-3.702407-15.12441-1.195818C16.309061 6.031586 1 20.266447 1 52.292272c0 32.025824 25.389438 38.815562 33.852584 38.815562 6.204255 0 8.275418-1.60786 8.937082-2.463296.068274-.092663.178044-.148132.29544-.14929M59.472644 3.026366c-10.33427-2.50659-14.156535.247823-15.12441 1.194325-.068796.069703-.163663.109533-.263128.110475V88.50122c.117396.001159.227167.056628.295441.149291.661664.849464 2.732827 2.457324 8.937082 2.457324 8.463146 0 33.852584-6.789738 33.852584-38.815562 0-32.025825-15.309062-46.260686-27.697569-49.265906z" stroke="#163A40" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></g>
</symbol>
<symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 88 88" id="bandaid">
<title>Bandaid</title>
<desc>A bandaid seen from above</desc>
<g transform="translate(-2 -2)" fill="none" fill-rule="evenodd"><path d="M6.272848 64.783183L64.7913 6.26473c3.204838-3.204838 8.400906-3.204838 11.605744 0l9.331064 9.331064c3.204837 3.204838 3.204837 8.400906 0 11.605744L27.209656 85.71999c-3.204838 3.204838-8.400906 3.204838-11.605744 0l-9.331064-9.331064c-3.204837-3.204837-3.204837-8.400906 0-11.605743z" fill="#35D78C" fill-rule="nonzero"/><path d="M33.106067 42.225736l14.538199-14.538198c.585786-.585787 1.535534-.585787 2.12132 0l14.538199 14.538198c.585786.585787.585786 1.535534 0 2.12132l-14.538199 14.5382c-.585786.585786-1.535534.585786-2.12132 0l-14.538199-14.5382c-.585786-.585786-.585786-1.535533 0-2.12132z" fill="#FFF" fill-rule="nonzero" opacity=".25"/><path d="M6.272848 64.783183L64.7913 6.26473c3.204838-3.204838 8.400906-3.204838 11.605744 0l9.331064 9.331064c3.204837 3.204838 3.204837 8.400906 0 11.605744L27.209656 85.71999c-3.204838 3.204838-8.400906 3.204838-11.605744 0l-9.331064-9.331064c-3.204837-3.204837-3.204837-8.400906 0-11.605743z" stroke="#163A40" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M46 66.961848l14.142983 14.142983c5.798155 5.764987 15.163693 5.764987 20.961848 0 5.764987-5.798155 5.764987-15.163693 0-20.961848L66.961848 46 46 66.961848z" fill="#35D78C" fill-rule="nonzero"/><path d="M46 66.961848l14.142983 14.142983c5.798155 5.764987 15.163693 5.764987 20.961848 0 5.764987-5.798155 5.764987-15.163693 0-20.961848L66.961848 46 46 66.961848z" fill="#163A40" fill-rule="nonzero" opacity=".2"/><path d="M25.038152 46L10.895169 31.857886c-5.764987-5.798354-5.764987-15.164214 0-20.962568 5.798155-5.765186 15.163693-5.765186 20.961848 0L46 25.038786 25.038152 46z" fill="#35D78C" fill-rule="nonzero"/><path fill="#163A40" fill-rule="nonzero" opacity=".2" d="M20.653061 41.324675l20.671614-20.671614L46 25.328386 25.328386 46z"/><path d="M66.961848 45.999323l14.142983 14.143225c5.764987 5.798255 5.764987 15.163954 0 20.962208-5.798155 5.765087-15.163693 5.765087-20.961848 0L46 66.961531M25.038152 45.999323L10.895169 31.857452c-5.764987-5.798255-5.764987-15.163954 0-20.962208 5.798155-5.765087 15.163693-5.765087 20.961848 0L46 25.038469" stroke="#163A40" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M40.740147 61.959184l-10.69933-10.680056M51.19952 30.040816l10.759663 10.740272" stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><circle fill="#163A40" fill-rule="nonzero" opacity=".16" transform="rotate(-45 46.355824 36.069412)" cx="46.355823" cy="36.069412" r="1.352941"/><circle fill="#163A40" fill-rule="nonzero" opacity=".16" transform="rotate(-45 55.92478 45.635663)" cx="55.92478" cy="45.635663" r="1.352941"/><circle fill="#163A40" fill-rule="nonzero" opacity=".16" transform="rotate(-45 36.788616 45.637412)" cx="36.788616" cy="45.637412" r="1.352941"/><circle fill="#163A40" fill-rule="nonzero" opacity=".16" transform="rotate(-45 46.357176 45.636619)" cx="46.357177" cy="45.636619" r="1.352941"/><circle fill="#163A40" fill-rule="nonzero" opacity=".16" transform="rotate(-45 46.35622 55.203663)" cx="46.35622" cy="55.203663" r="1.352941"/><circle stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" transform="rotate(-45 46.355824 36.069412)" cx="46.355823" cy="36.069412" r="1.352941"/><circle stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" transform="rotate(-45 55.92478 45.635663)" cx="55.92478" cy="45.635663" r="1.352941"/><circle stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" transform="rotate(-45 36.788616 45.637412)" cx="36.788616" cy="45.637412" r="1.352941"/><circle stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" transform="rotate(-45 46.357176 45.636619)" cx="46.357177" cy="45.636619" r="1.352941"/><circle stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" transform="rotate(-45 46.35622 55.203663)" cx="46.35622" cy="55.203663" r="1.352941"/></g>
</symbol>
<symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 86" id="dropper">
<title>Dropper</title>
<desc>A medical dropper with a drop</desc>
<g fill="none" fill-rule="evenodd"><path d="M7.734638 68.530484c2.522502 2.992576 4.04951 6.693644 4.369463 10.590435.116078 2.843274-1.89967 5.331497-4.710914 5.815116-1.600957.244765-3.229244-.220017-4.458052-1.272517C1.706327 82.611018.999526 81.075746 1 79.460134c0-3.876745 2.900947-8.570374 4.509653-10.872884.25289-.357122.660032-.574105 1.098213-.585284.438181-.01118.85591.184758 1.126772.528518zm6.10448-8.308694l-.508014.502592c-.951183.948011-1.38491 2.29584-1.164572 3.618966.220337 1.323125 1.06762 2.458692 2.274983 3.049034 1.683277.781687 3.67845.41068 4.966309-.923495l.378927-.37383c3.690052-3.784275 8.380166-6.447301 13.526183-7.680107 1.807415-.391286 3.465327-1.289023 4.778927-2.587726L45 49H21.004038c-1.465395 4.252994-3.920866 8.098783-7.16492 11.22179z" fill="#35D78C" fill-rule="nonzero"/><path d="M24.227987 41.980894c-1.31287 1.317611-2.22395 2.991661-2.62413 4.821661C21.437193 47.544399 21.235677 48.277719 21 49h24.054065L56 37.990164 42.100179 24 24.227987 41.980894z" fill="#92E4CF" fill-rule="nonzero"/><path d="M77.058918 4.884709c-1.747668-2.265473-4.37254-3.670812-7.2139-3.862271-2.841359-.19146-5.628568.849195-7.660047 2.860017L42 24.024921 55.995548 38 75.91854 18.120097c3.624418-3.49742 4.112393-9.160922 1.140378-13.235388z" fill="#35D78C" fill-rule="nonzero"/><path d="M77.065313 5.036591c-.286115-.366893-.597324-.713265-.93136-1.036591.370275 3.17398-.73595 6.342279-2.997943 8.586292L53.27865 32.367211 42.288051 43.310415l-6.95657 6.92887c-1.319913 1.315315-2.985165 2.224973-4.800619 2.622379-5.178737 1.249275-9.89903 3.950425-13.612925 7.789887l-.3812.37924c-1.101373 1.123588-2.70641 1.586479-4.23231 1.220594-.818867 2.03907.066467 4.368154 2.028884 5.337463 1.693377.793003 3.70052.416625 4.996107-.936865l.3812-.379241c3.713547-3.840489 8.433874-6.542632 13.612926-7.792696 1.81826-.39695 3.486118-1.307684 4.8076-2.625189l6.949588-6.92606 10.985012-10.943204 19.862946-19.779514c3.612479-3.480006 4.098846-9.115308 1.136622-13.169488z" fill="#163A40" fill-rule="nonzero" opacity=".16"/><path d="M39.219801 20.85821l19.881652 19.798094M45.159779 48.59962l30.775326-30.621107c3.60441-3.468126 4.09023-9.08482 1.135338-13.125931-1.73781-2.246737-4.347875-3.640453-7.173206-3.83033-2.825331-.189876-5.596818.842173-7.616837 2.836365L24.308562 41.64607c-1.314453 1.305305-2.226634 2.96372-2.627298 4.77663a23.72274 23.72274 0 01-.604585 2.176921M7.759093 68.347316c2.531663 3.025858 4.064217 6.768088 4.38533 10.708217.1165 2.874897-1.906568 5.390793-4.72802 5.87979-1.60677.247488-3.24097-.222463-4.47424-1.28667C1.708891 82.584449.999523 81.032104 1 79.398522c0-3.91986 2.91148-8.66569 4.52603-10.993808.253808-.361094.662427-.58049 1.1022-.591794.439772-.011303.859018.186813 1.130863.534397zM13.734718 60.342578l-.509714.508002c-.95437.958215-1.38955 2.320552-1.168475 3.657919.221076 1.337367 1.071198 2.485157 2.282605 3.081854 1.688917.7901 3.690774.4151 4.982948-.933436l.380197-.377853c3.702414-3.825009 8.408242-6.516699 13.5715-7.762774 1.81347-.395497 3.476936-1.302898 4.794938-2.61558L45 49H20.923644c-1.470305 4.298772-3.934003 8.185956-7.188926 11.342578h0z" stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></g>
</symbol>
<symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 86 101" id="drugs">
<title>Drugs</title>
<desc>Two medication pills</desc>
<g transform="translate(1 1)" fill="none" fill-rule="evenodd"><path d="M56.065217 54.434783c-15.308152 0-27.71739 7.39076-27.71739 16.508152V81.94837c0 9.11739 12.409238 16.508152 27.71739 16.508152 15.308153 0 27.717392-7.390761 27.717392-16.508152V70.942935c0-9.117392-12.40924-16.508152-27.717392-16.508152z" fill="#35D78C" fill-rule="nonzero"/><path d="M40.475 57.296196L68.833152 85.58587a33.629353 33.629353 0 004.809783-1.881522L45.544022 55.673913A36.629347 36.629347 0 0040.475 57.296196z" fill="#163A40" fill-rule="nonzero" opacity=".16"/><path d="M56.065217 87.451087c-15.308152 0-27.71739-7.39076-27.71739-16.508152V81.94837c0 9.11739 12.409238 16.508152 27.71739 16.508152 15.308153 0 27.717392-7.390761 27.717392-16.508152V70.942935c0 9.117391-12.40924 16.508152-27.717392 16.508152z" fill="#163A40" fill-rule="nonzero" opacity=".16"/><path d="M6.369565 45.325544c-6.720148 6.713294-7.683147 17.269763-2.288637 25.088201s15.605395 10.66523 24.266898 6.765603v-6.236413c0-8.455435 10.680978-15.415761 24.443478-16.382609v-.009783l.877174-.877173L25.84837 25.84674 6.369565 45.325543z" fill="#92E4CF" fill-rule="nonzero"/><path d="M28.347826 77.179348v-6.236413c0-6.510326 6.342391-12.120652 15.536413-14.805979-14.183152.725544-25.319022 7.801631-25.319022 16.436414v6.236413c3.346347.294272 6.712586-.266768 9.78261-1.630435z" fill="#163A40" fill-rule="nonzero" opacity=".16"/><path d="M73.152174 6.369565c-7.695901-7.655597-20.13073-7.655597-27.82663 0L25.84837 25.84674 53.675 53.67337l19.477174-19.477173c7.655597-7.695901 7.655597-20.13073 0-27.82663z" fill="#35D78C" fill-rule="nonzero"/><path d="M9.630435 51.847283l19.478804-19.478805 19.477174-19.477174c7.6959-7.655597 20.13073-7.655597 27.82663 0a19.516308 19.516308 0 011.72663 2.010326c-.901924-3.22526-2.619636-6.163733-4.9875-8.532065-7.6959-7.655597-20.130729-7.655597-27.82663 0L25.84837 25.84674 6.369565 45.325544c-6.926171 6.973825-7.66243 17.982252-1.72663 25.816304-1.94938-6.860213-.042178-14.238386 4.9875-19.294565z" fill="#FFF" fill-rule="nonzero" opacity=".4"/><path d="M59.326087 3.855435c-12.022826.229891-15.269022 11.654348-11.639674 12.63587 3.213587 1.20326 7.928804-.679892 11.639674-.233153 3.71087-.446739 8.427717 1.436413 11.639674.233152 3.629348-.981521.383152-12.405978-11.639674-12.63587z" fill="#FFF" fill-rule="nonzero" opacity=".5"/><path d="M25.84837 25.84837l27.825 27.825m-.869022.877174l20.347826-20.354348c7.655597-7.695901 7.655597-20.13073 0-27.82663-7.695901-7.655598-20.13073-7.655598-27.82663 0L6.369565 45.325543c-7.655597 7.6959-7.655597 20.130729 0 27.82663 5.789905 5.755452 14.524317 7.355249 21.978261 4.025543M40.47174 57.292935l28.372826 28.302717M45.493478 55.62337l28.151087 28.082608" stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M28.347826 70.942935V81.94837c0 9.11739 12.40924 16.508152 27.717391 16.508152 15.308153 0 27.717392-7.390761 27.717392-16.508152V70.942935" stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><ellipse stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" cx="56.065217" cy="70.942935" rx="27.717391" ry="16.508152"/></g>
</symbol>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1 @@
<svg width="88" height="88" viewBox="0 0 88 88" xmlns="http://www.w3.org/2000/svg"><g transform="translate(-2 -2)" fill="none" fill-rule="evenodd"><path d="M6.272848 64.783183L64.7913 6.26473c3.204838-3.204838 8.400906-3.204838 11.605744 0l9.331064 9.331064c3.204837 3.204838 3.204837 8.400906 0 11.605744L27.209656 85.71999c-3.204838 3.204838-8.400906 3.204838-11.605744 0l-9.331064-9.331064c-3.204837-3.204837-3.204837-8.400906 0-11.605743z" fill="#35D78C" fill-rule="nonzero"/><path d="M33.106067 42.225736l14.538199-14.538198c.585786-.585787 1.535534-.585787 2.12132 0l14.538199 14.538198c.585786.585787.585786 1.535534 0 2.12132l-14.538199 14.5382c-.585786.585786-1.535534.585786-2.12132 0l-14.538199-14.5382c-.585786-.585786-.585786-1.535533 0-2.12132z" fill="#FFF" fill-rule="nonzero" opacity=".25"/><path d="M6.272848 64.783183L64.7913 6.26473c3.204838-3.204838 8.400906-3.204838 11.605744 0l9.331064 9.331064c3.204837 3.204838 3.204837 8.400906 0 11.605744L27.209656 85.71999c-3.204838 3.204838-8.400906 3.204838-11.605744 0l-9.331064-9.331064c-3.204837-3.204837-3.204837-8.400906 0-11.605743z" stroke="#163A40" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M46 66.961848l14.142983 14.142983c5.798155 5.764987 15.163693 5.764987 20.961848 0 5.764987-5.798155 5.764987-15.163693 0-20.961848L66.961848 46 46 66.961848z" fill="#35D78C" fill-rule="nonzero"/><path d="M46 66.961848l14.142983 14.142983c5.798155 5.764987 15.163693 5.764987 20.961848 0 5.764987-5.798155 5.764987-15.163693 0-20.961848L66.961848 46 46 66.961848z" fill="#163A40" fill-rule="nonzero" opacity=".2"/><path d="M25.038152 46L10.895169 31.857886c-5.764987-5.798354-5.764987-15.164214 0-20.962568 5.798155-5.765186 15.163693-5.765186 20.961848 0L46 25.038786 25.038152 46z" fill="#35D78C" fill-rule="nonzero"/><path fill="#163A40" fill-rule="nonzero" opacity=".2" d="M20.653061 41.324675l20.671614-20.671614L46 25.328386 25.328386 46z"/><path d="M66.961848 45.999323l14.142983 14.143225c5.764987 5.798255 5.764987 15.163954 0 20.962208-5.798155 5.765087-15.163693 5.765087-20.961848 0L46 66.961531M25.038152 45.999323L10.895169 31.857452c-5.764987-5.798255-5.764987-15.163954 0-20.962208 5.798155-5.765087 15.163693-5.765087 20.961848 0L46 25.038469" stroke="#163A40" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M40.740147 61.959184l-10.69933-10.680056M51.19952 30.040816l10.759663 10.740272" stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><circle fill="#163A40" fill-rule="nonzero" opacity=".16" transform="rotate(-45 46.355824 36.069412)" cx="46.355823" cy="36.069412" r="1.352941"/><circle fill="#163A40" fill-rule="nonzero" opacity=".16" transform="rotate(-45 55.92478 45.635663)" cx="55.92478" cy="45.635663" r="1.352941"/><circle fill="#163A40" fill-rule="nonzero" opacity=".16" transform="rotate(-45 36.788616 45.637412)" cx="36.788616" cy="45.637412" r="1.352941"/><circle fill="#163A40" fill-rule="nonzero" opacity=".16" transform="rotate(-45 46.357176 45.636619)" cx="46.357177" cy="45.636619" r="1.352941"/><circle fill="#163A40" fill-rule="nonzero" opacity=".16" transform="rotate(-45 46.35622 55.203663)" cx="46.35622" cy="55.203663" r="1.352941"/><circle stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" transform="rotate(-45 46.355824 36.069412)" cx="46.355823" cy="36.069412" r="1.352941"/><circle stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" transform="rotate(-45 55.92478 45.635663)" cx="55.92478" cy="45.635663" r="1.352941"/><circle stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" transform="rotate(-45 36.788616 45.637412)" cx="36.788616" cy="45.637412" r="1.352941"/><circle stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" transform="rotate(-45 46.357176 45.636619)" cx="46.357177" cy="45.636619" r="1.352941"/><circle stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" transform="rotate(-45 46.35622 55.203663)" cx="46.35622" cy="55.203663" r="1.352941"/></g></svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -0,0 +1 @@
<svg width="89" height="93" viewBox="0 0 89 93" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M44.085106 4.331128c-.099239-.00055-.194073-.03983-.263127-.108982-.967876-.947996-4.79014-3.70241-15.12441-1.195819C16.309061 6.03155 1 20.266416 1 52.292255c0 32.025838 25.389438 38.815579 33.852584 38.815579 6.204255 0 8.275418-1.607861 8.937082-2.463297.068274-.092663.178044-.148132.29544-.14929" fill="#35D78C" fill-rule="nonzero"/><path d="M11.771277 44.703189c0-19.930047 5.898043-32.98472 13.33484-40.744775C13.540843 8.673724 1 23.123532 1 52.187809c0 32.112014 25.389438 38.920025 33.852584 38.920025 6.204255 0 8.275418-1.612187 8.937082-2.469925.068274-.092912.178044-.14853.29544-.149692v-4.93985c-9.623366-.748462-32.31383-8.487559-32.31383-38.845178z" fill="#163A40" fill-rule="nonzero" opacity=".16"/><path d="M59.472644 3.026366c-10.33427-2.50659-14.156535.247823-15.12441 1.194325-.068796.069703-.163663.109533-.263128.110475V88.50122c.117396.001159.227167.056628.295441.149291.661664.849464 2.732827 2.457324 8.937082 2.457324 8.463146 0 33.852584-6.789738 33.852584-38.815562 0-32.025825-15.309062-46.260686-27.697569-49.265906z" fill="#35D78C" fill-rule="nonzero"/><path d="M45.32192 4.220691c-.067352.069703-.160229.109533-.257607.110475V88.50122c.114933.001159.222402.056628.289243.149291.647783.849464 2.675495 2.457324 8.74959 2.457324 11.78068-.617525 22.417247-7.183249 28.171032-17.389372-23.049026 16.9415-26.664559-16.947472-26.664559-34.862346 0-15.26198 1.098218-33.760582 8.873122-34.29355-1.400003-.644803-2.857523-1.159087-4.353705-1.5362C50.011568.519776 46.26949 3.27419 45.32192 4.220691z" fill="#163A40" fill-rule="nonzero" opacity=".16"/><path d="M26.228418 3.958414c3.341717.510248 5.878359 3.200936 6.11543 6.48681M12.19962 14.9117c10.758572 2.541425 7.930185 11.983553 7.930185 11.983553m-4.60339 5.882347s.285896-7.444125 9.173145-5.9553M1.979207 47.378506c5.82189-8.137918 18.13378-6.465967 21.191496 3.955808m-7.644288 5.264485c3.057715-5.9553 10.702003-7.444125 15.288576-1.488825M24.699561 38.7329c4.988662 0 10.702003 2.97765 10.702003 10.421775m9.173146-11.9106c-4.586573-1.488825-10.468088-.461535-12.524402 4.019828m.29354-23.374553c4.586574 1.488825 6.115431 8.93295 3.057716 13.399425m9.173146-5.9553c-2.398234-1.054234-5.131875-1.121336-7.581605-.186103M7.59623 74.4647c6.16894-.334986 11.24322-5.57416 11.24322-10.018303m-7.899608-.403472c7.644288-1.488825 11.399162 1.122574 12.23086 5.9553M38.732946 68.2295c-10.702004-1.488825-18.0818 12.56866-8.237485 21.899127m1.848389-30.552178c6.11543 1.488825 9.173146 10.421775 3.057715 16.377075m-8.67321-61.914276c.83072-1.87231 2.587594-3.200392 4.656199-3.51978s4.161169.414348 5.545869 1.944603m25.99058-8.505657c-3.341718.510248-5.87836 3.200936-6.115431 6.48681M76.949799 14.9117c-10.75857 2.541425-7.930184 11.983553-7.930184 11.983553m4.60339 5.882347s-.285896-7.444125-9.173146-5.9553m22.720354 20.556207c-5.82189-8.137918-18.13378-6.465967-21.191496 3.955808m7.644288 5.264485c-3.057715-5.9553-10.702003-7.444125-15.288576-1.488825m6.11543-16.377075c-4.988662 0-10.702003 2.97765-10.702003 10.421775m-9.173146-11.9106c4.586573-1.488825 10.468088-.461535 12.524402 4.019828m-.293541-23.374553c-4.586573 1.488825-6.11543 8.93295-3.057715 13.399425m-9.173146-5.9553c2.398234-1.054234 5.131874-1.121336 7.581605-.186103M81.554719 74.4647c-6.168941-.334986-11.24322-5.57416-11.24322-10.018303m7.89808-.403472c-7.64429-1.488825-11.399164 1.122574-12.230862 5.9553M50.416475 68.2295c10.702003-1.488825 18.0818 12.56866 8.237485 21.899127M56.80557 59.576449c-6.11543 1.488825-9.173146 10.421775-3.057715 16.377075m8.67321-61.914276c-.83072-1.87231-2.587594-3.200392-4.6562-3.51978-2.068605-.319388-4.161168.414348-5.545868 1.944603" stroke="#163A40" stroke-linecap="round" stroke-linejoin="round"/><path d="M44.085106 4.331166c-.099239-.00055-.194073-.039829-.263127-.108982-.967876-.947995-4.79014-3.702407-15.12441-1.195818C16.309061 6.031586 1 20.266447 1 52.292272c0 32.025824 25.389438 38.815562 33.852584 38.815562 6.204255 0 8.275418-1.60786 8.937082-2.463296.068274-.092663.178044-.148132.29544-.14929M59.472644 3.026366c-10.33427-2.50659-14.156535.247823-15.12441 1.194325-.068796.069703-.163663.109533-.263128.110475V88.50122c.117396.001159.227167.056628.295441.149291.661664.849464 2.732827 2.457324 8.937082 2.457324 8.463146 0 33.852584-6.789738 33.852584-38.815562 0-32.025825-15.309062-46.260686-27.697569-49.265906z" stroke="#163A40" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></g></svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -0,0 +1 @@
<svg width="80" height="86" viewBox="0 0 80 86" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M7.734638 68.530484c2.522502 2.992576 4.04951 6.693644 4.369463 10.590435.116078 2.843274-1.89967 5.331497-4.710914 5.815116-1.600957.244765-3.229244-.220017-4.458052-1.272517C1.706327 82.611018.999526 81.075746 1 79.460134c0-3.876745 2.900947-8.570374 4.509653-10.872884.25289-.357122.660032-.574105 1.098213-.585284.438181-.01118.85591.184758 1.126772.528518zm6.10448-8.308694l-.508014.502592c-.951183.948011-1.38491 2.29584-1.164572 3.618966.220337 1.323125 1.06762 2.458692 2.274983 3.049034 1.683277.781687 3.67845.41068 4.966309-.923495l.378927-.37383c3.690052-3.784275 8.380166-6.447301 13.526183-7.680107 1.807415-.391286 3.465327-1.289023 4.778927-2.587726L45 49H21.004038c-1.465395 4.252994-3.920866 8.098783-7.16492 11.22179z" fill="#35D78C" fill-rule="nonzero"/><path d="M24.227987 41.980894c-1.31287 1.317611-2.22395 2.991661-2.62413 4.821661C21.437193 47.544399 21.235677 48.277719 21 49h24.054065L56 37.990164 42.100179 24 24.227987 41.980894z" fill="#92E4CF" fill-rule="nonzero"/><path d="M77.058918 4.884709c-1.747668-2.265473-4.37254-3.670812-7.2139-3.862271-2.841359-.19146-5.628568.849195-7.660047 2.860017L42 24.024921 55.995548 38 75.91854 18.120097c3.624418-3.49742 4.112393-9.160922 1.140378-13.235388z" fill="#35D78C" fill-rule="nonzero"/><path d="M77.065313 5.036591c-.286115-.366893-.597324-.713265-.93136-1.036591.370275 3.17398-.73595 6.342279-2.997943 8.586292L53.27865 32.367211 42.288051 43.310415l-6.95657 6.92887c-1.319913 1.315315-2.985165 2.224973-4.800619 2.622379-5.178737 1.249275-9.89903 3.950425-13.612925 7.789887l-.3812.37924c-1.101373 1.123588-2.70641 1.586479-4.23231 1.220594-.818867 2.03907.066467 4.368154 2.028884 5.337463 1.693377.793003 3.70052.416625 4.996107-.936865l.3812-.379241c3.713547-3.840489 8.433874-6.542632 13.612926-7.792696 1.81826-.39695 3.486118-1.307684 4.8076-2.625189l6.949588-6.92606 10.985012-10.943204 19.862946-19.779514c3.612479-3.480006 4.098846-9.115308 1.136622-13.169488z" fill="#163A40" fill-rule="nonzero" opacity=".16"/><path d="M39.219801 20.85821l19.881652 19.798094M45.159779 48.59962l30.775326-30.621107c3.60441-3.468126 4.09023-9.08482 1.135338-13.125931-1.73781-2.246737-4.347875-3.640453-7.173206-3.83033-2.825331-.189876-5.596818.842173-7.616837 2.836365L24.308562 41.64607c-1.314453 1.305305-2.226634 2.96372-2.627298 4.77663a23.72274 23.72274 0 01-.604585 2.176921M7.759093 68.347316c2.531663 3.025858 4.064217 6.768088 4.38533 10.708217.1165 2.874897-1.906568 5.390793-4.72802 5.87979-1.60677.247488-3.24097-.222463-4.47424-1.28667C1.708891 82.584449.999523 81.032104 1 79.398522c0-3.91986 2.91148-8.66569 4.52603-10.993808.253808-.361094.662427-.58049 1.1022-.591794.439772-.011303.859018.186813 1.130863.534397zM13.734718 60.342578l-.509714.508002c-.95437.958215-1.38955 2.320552-1.168475 3.657919.221076 1.337367 1.071198 2.485157 2.282605 3.081854 1.688917.7901 3.690774.4151 4.982948-.933436l.380197-.377853c3.702414-3.825009 8.408242-6.516699 13.5715-7.762774 1.81347-.395497 3.476936-1.302898 4.794938-2.61558L45 49H20.923644c-1.470305 4.298772-3.934003 8.185956-7.188926 11.342578h0z" stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></g></svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -0,0 +1 @@
<svg width="86" height="101" viewBox="0 0 86 101" xmlns="http://www.w3.org/2000/svg"><g transform="translate(1 1)" fill="none" fill-rule="evenodd"><path d="M56.065217 54.434783c-15.308152 0-27.71739 7.39076-27.71739 16.508152V81.94837c0 9.11739 12.409238 16.508152 27.71739 16.508152 15.308153 0 27.717392-7.390761 27.717392-16.508152V70.942935c0-9.117392-12.40924-16.508152-27.717392-16.508152z" fill="#35D78C" fill-rule="nonzero"/><path d="M40.475 57.296196L68.833152 85.58587a33.629353 33.629353 0 004.809783-1.881522L45.544022 55.673913A36.629347 36.629347 0 0040.475 57.296196z" fill="#163A40" fill-rule="nonzero" opacity=".16"/><path d="M56.065217 87.451087c-15.308152 0-27.71739-7.39076-27.71739-16.508152V81.94837c0 9.11739 12.409238 16.508152 27.71739 16.508152 15.308153 0 27.717392-7.390761 27.717392-16.508152V70.942935c0 9.117391-12.40924 16.508152-27.717392 16.508152z" fill="#163A40" fill-rule="nonzero" opacity=".16"/><path d="M6.369565 45.325544c-6.720148 6.713294-7.683147 17.269763-2.288637 25.088201s15.605395 10.66523 24.266898 6.765603v-6.236413c0-8.455435 10.680978-15.415761 24.443478-16.382609v-.009783l.877174-.877173L25.84837 25.84674 6.369565 45.325543z" fill="#92E4CF" fill-rule="nonzero"/><path d="M28.347826 77.179348v-6.236413c0-6.510326 6.342391-12.120652 15.536413-14.805979-14.183152.725544-25.319022 7.801631-25.319022 16.436414v6.236413c3.346347.294272 6.712586-.266768 9.78261-1.630435z" fill="#163A40" fill-rule="nonzero" opacity=".16"/><path d="M73.152174 6.369565c-7.695901-7.655597-20.13073-7.655597-27.82663 0L25.84837 25.84674 53.675 53.67337l19.477174-19.477173c7.655597-7.695901 7.655597-20.13073 0-27.82663z" fill="#35D78C" fill-rule="nonzero"/><path d="M9.630435 51.847283l19.478804-19.478805 19.477174-19.477174c7.6959-7.655597 20.13073-7.655597 27.82663 0a19.516308 19.516308 0 011.72663 2.010326c-.901924-3.22526-2.619636-6.163733-4.9875-8.532065-7.6959-7.655597-20.130729-7.655597-27.82663 0L25.84837 25.84674 6.369565 45.325544c-6.926171 6.973825-7.66243 17.982252-1.72663 25.816304-1.94938-6.860213-.042178-14.238386 4.9875-19.294565z" fill="#FFF" fill-rule="nonzero" opacity=".4"/><path d="M59.326087 3.855435c-12.022826.229891-15.269022 11.654348-11.639674 12.63587 3.213587 1.20326 7.928804-.679892 11.639674-.233153 3.71087-.446739 8.427717 1.436413 11.639674.233152 3.629348-.981521.383152-12.405978-11.639674-12.63587z" fill="#FFF" fill-rule="nonzero" opacity=".5"/><path d="M25.84837 25.84837l27.825 27.825m-.869022.877174l20.347826-20.354348c7.655597-7.695901 7.655597-20.13073 0-27.82663-7.695901-7.655598-20.13073-7.655598-27.82663 0L6.369565 45.325543c-7.655597 7.6959-7.655597 20.130729 0 27.82663 5.789905 5.755452 14.524317 7.355249 21.978261 4.025543M40.47174 57.292935l28.372826 28.302717M45.493478 55.62337l28.151087 28.082608" stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M28.347826 70.942935V81.94837c0 9.11739 12.40924 16.508152 27.717391 16.508152 15.308153 0 27.717392-7.390761 27.717392-16.508152V70.942935" stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><ellipse stroke="#163A40" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" cx="56.065217" cy="70.942935" rx="27.717391" ry="16.508152"/></g></svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

9
static/img/logo.svg Normal file
View File

@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 150 150">
<g>
<g>
<path fill="#042b32" d="M0 0h150v150H0z"/>
<path fill="#fff" d="M91.32 36.93c-.88 0-1.75 0-2.62.08h-.62c-.73.06-1.45.12-2.16.21h-.37a44 44 0 00-5.16 1l-.83.24a37.52 37.52 0 00-10.43 4.73l-.7.47c-.37.26-.73.51-1.09.78l-.73.58c-.46.36-.91.74-1.36 1.12s-.74.66-1.1 1l-.66.67c-.33.33-.65.66-1 1l-.57.64c-.38.44-.75.89-1.11 1.34l-.31.39c-.46.6-.9 1.21-1.31 1.84l-.32.49c-.32.49-.62 1-.91 1.49-.12.2-.24.41-.35.62-.31.54-.59 1.1-.87 1.66-.05.11-.11.21-.16.31v.09l-.06.12c-.14.29-.27.6-.4.9a37.47 37.47 0 00-1.8 5.06v.15c-.16.6-.31 1.21-.45 1.82 0 .16-.07.32-.1.48-.11.51-.2 1-.29 1.54 0 .21-.07.42-.1.63-.08.48-.14 1-.2 1.46 0 .23-.05.45-.08.68 0 .5-.08 1-.12 1.52v.63q-.06 1.07-.06 2.16t.06 2.19v.64c0 .51.07 1 .12 1.53 0 .24.05.46.08.69.06.5.12 1 .2 1.49 0 .21.06.42.1.62.09.54.19 1.06.3 1.59l.09.46c.14.63.29 1.26.46 1.88v.11A37.88 37.88 0 0055.62 90a14.56 14.56 0 003.06.34 13.09 13.09 0 0012.8-9.16 15.19 15.19 0 00.45-1.56c0-.12-.06-.25-.08-.38s0-.22 0-.34c-.09-.57-.17-1.15-.22-1.75s-.09-1.46-.09-2.2 0-1.46.09-2.17.13-1.2.23-1.79v-.27c0-.16.07-.32.1-.47.12-.64.27-1.27.44-1.88s.29-1 .47-1.54c.17-.48.36-1 .56-1.42l.12-.23c.18-.4.36-.8.56-1.18v-.06a19 19 0 0115.62-10.17q.78-.06 1.59-.06h1.13c.37 0 .67 0 1 .08a20.55 20.55 0 012.22.37l.67.14c.35.09.69.2 1 .31.54.16 1.06.35 1.58.56a18.53 18.53 0 014.59 2.66l.2.16c.35.29.69.59 1 .91l.28.28c.31.3.61.62.9.94.09.12.19.24.29.35.27.33.54.66.79 1 .08.1.15.22.22.32a20.35 20.35 0 011.23 2c.11.21.23.41.33.62s.26.57.38.85.26.59.38.9.2.55.29.83.23.67.32 1 .16.55.22.83.18.75.25 1.13.11.53.15.79c.07.44.12.88.17 1.33 0 .23.06.45.08.68 0 .68.08 1.37.08 2.08s0 1.43-.08 2.12c0 .24-.06.46-.08.69 0 .46-.1.92-.17 1.36 0 .28-.1.54-.15.81s-.16.78-.26 1.16-.14.56-.22.83-.21.7-.32 1-.19.56-.3.84-.25.61-.39.92-.24.57-.37.84-.25.47-.38.7a18.91 18.91 0 01-1.18 1.94l-.24.35c-.25.34-.52.67-.79 1l-.31.38c-.28.32-.58.63-.88.93l-.3.3c-.33.31-.66.6-1 .89a2.11 2.11 0 00-.23.19 18.56 18.56 0 01-4.65 2.65 41 41 0 01-15.5 17.51c.73.14 1.46.27 2.21.36h.35c.72.09 1.45.15 2.19.21h.61c.87.05 1.74.08 2.63.08 23.18 0 38.49-16.57 38.49-38.17.06-21.11-15.25-37.79-38.43-37.79z"/>
<path fill="#fff" d="M97.11 72.74v-.63c0-.51-.07-1-.12-1.52 0-.23 0-.45-.08-.68-.06-.49-.12-1-.2-1.46 0-.21-.06-.42-.1-.63-.09-.52-.18-1-.29-1.54 0-.16-.07-.32-.1-.48-.14-.61-.29-1.22-.45-1.82v-.15a39.68 39.68 0 00-1.26-3.77 15.05 15.05 0 00-3.11-.35 13.12 13.12 0 00-12.81 9.07q-.26.73-.45 1.5c0 .13.07.26.09.39v.27c.09.59.18 1.18.23 1.79s.09 1.43.09 2.17 0 1.48-.09 2.2-.13 1.18-.22 1.75v.34l-.09.4a23.27 23.27 0 01-.91 3.52 19 19 0 01-18.56 13.18 20.48 20.48 0 01-4.83-.58 18.37 18.37 0 01-2.69-.87 19 19 0 01-4.64-2.66 2.11 2.11 0 00-.23-.19c-.35-.29-.68-.58-1-.89l-.3-.3c-.3-.3-.6-.61-.88-.93l-.31-.38c-.27-.32-.54-.65-.79-1l-.24-.35a18.91 18.91 0 01-1.18-1.94c-.13-.23-.26-.46-.38-.7s-.25-.56-.37-.84-.27-.61-.39-.92-.2-.56-.3-.84-.22-.69-.32-1-.16-.55-.22-.83-.18-.77-.26-1.16l-.15-.81c-.07-.44-.12-.9-.17-1.36 0-.23-.06-.45-.08-.69 0-.69-.08-1.4-.08-2.12s0-1.4.08-2.08c0-.23.05-.45.08-.68 0-.45.1-.89.17-1.33 0-.26.09-.52.15-.79s.15-.76.25-1.13.14-.55.22-.83.2-.68.32-1 .19-.56.29-.83.25-.6.38-.9.24-.57.38-.85.22-.41.33-.62a22.45 22.45 0 011.23-2 3.62 3.62 0 01.22-.32c.25-.35.52-.68.79-1l.3-.35c.28-.32.58-.64.89-.94l.28-.28c.33-.32.67-.62 1-.91l.21-.16a18.24 18.24 0 014.7-2.71v-.07A41.07 41.07 0 0166.7 37.66q-1.11-.21-2.25-.36h-.37c-.71-.09-1.43-.15-2.16-.21h-.62c-.87 0-1.74-.08-2.62-.08-23.18 0-38.49 16.68-38.49 38 0 21.6 15.31 38.17 38.49 38.17.89 0 1.76 0 2.63-.08h.61c.74-.06 1.47-.12 2.19-.21h.35c.79-.1 1.56-.23 2.33-.37h.28l.42-.1c.7-.14 1.39-.29 2.07-.46h.09a35.54 35.54 0 0023.82-19.82c.34-.71.64-1.44.93-2.17.49-1.26.92-2.54 1.29-3.87v-.11c.17-.62.32-1.25.46-1.88l.09-.46c.11-.53.21-1.05.3-1.59 0-.2.07-.41.1-.62.08-.49.14-1 .2-1.49 0-.23 0-.45.08-.69 0-.5.08-1 .12-1.53v-.64q.06-1.09.06-2.19t.01-2.16z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
static/img/open-clinica.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
static/img/open-pharma.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

4
static/img/survey.svg Normal file
View File

@ -0,0 +1,4 @@
<svg width="457" height="418" viewBox="0 0 457 418" xmlns="http://www.w3.org/2000/svg">
<title>Survey</title>
<desc>Ilustration of a survey sheet.</desc>
<defs><linearGradient x1="50%" y1="100%" x2="50%" y2="0%" id="a"><stop stop-color="gray" stop-opacity=".25" offset="0%"/><stop stop-color="gray" stop-opacity=".12" offset="54%"/><stop stop-color="gray" stop-opacity=".1" offset="100%"/></linearGradient><linearGradient x1="50%" y1="99.981618%" x2="50%" y2="0%" id="b"><stop stop-color="gray" stop-opacity=".25" offset="0%"/><stop stop-color="gray" stop-opacity=".12" offset="54%"/><stop stop-color="gray" stop-opacity=".1" offset="100%"/></linearGradient><linearGradient x1="50%" y1="100%" x2="50%" y2="-.024845%" id="c"><stop stop-color="gray" stop-opacity=".25" offset="0%"/><stop stop-color="gray" stop-opacity=".12" offset="54%"/><stop stop-color="gray" stop-opacity=".1" offset="100%"/></linearGradient></defs><g transform="translate(1)" fill="none" fill-rule="evenodd"><path stroke="#163A40" fill="#FFF" fill-rule="nonzero" d="M128 31h202v280H128z"/><path fill="url(#a)" fill-rule="nonzero" d="M180 24h100v25H180z"/><path d="M230 0c-7.732681 0-14 6.493015-14 14.5S222.267319 29 230 29s14-6.493015 14-14.5S237.732681 0 230 0zm0 22.864154c-3.363309.088915-6.444663-1.891606-7.793123-5.008981-1.34846-3.117376-.695229-6.750199 1.652101-9.187858 2.347331-2.437659 5.920852-3.194239 9.037876-1.913484 3.117024 1.280755 5.156214 4.343543 5.157363 7.746169.052778 4.556254-3.549254 8.296897-8.054217 8.364154z" fill="url(#b)" fill-rule="nonzero"/><path d="M229.5 1c3.580423 0 7.0142 1.422317 9.545942 3.954058C241.577683 7.4858 243 10.919578 243 14.5c0 3.70519-1.492668 7.06175-3.909473 9.501148L279 24v23h-98V24l38.909473.001148C217.492668 21.56175 216 18.205191 216 14.5 216 7.044156 222.044156 1 229.5 1zm0 5.711538c-4.301449 0-7.788462 3.487014-7.788462 7.788462 0 4.301448 3.487013 7.788462 7.788462 7.788462s7.788462-3.487013 7.788462-7.788462c0-4.301448-3.487013-7.788462-7.788462-7.788462z" stroke="#163A40" fill="#FFA318" fill-rule="nonzero"/><path stroke="#163A40" fill="#35D78C" fill-rule="nonzero" d="M139 78h40v40h-40z"/><path stroke="#163A40" fill="#FFA318" fill-rule="nonzero" d="M139 163h40v40h-40zM139 248h40v40h-40z"/><path fill="#E0E0E0" fill-rule="nonzero" d="M206 90h54v4h-54zM206 96h90v4h-90zM206 102h84v4h-84zM206 175h54v4h-54zM206 181h90v4h-90zM206 187h84v4h-84zM206 260h54v4h-54zM206 266h90v4h-90zM206 271h84v4h-84z"/><path fill="url(#c)" fill-rule="nonzero" d="M150.125 95.394783L157.625 102l10.625-15 3.75 3-14.375 18L147 96.6z"/><path fill="#FFF" fill-rule="nonzero" d="M151.625 96.2l6.3 5.657143L166.85 89l3.15 2.571429L157.925 107 149 97.228571zM151.625 181.2l6.3 5.657143L166.85 174l3.15 2.571429L157.925 192 149 182.228571zM151.625 266.2l6.3 5.657143L166.85 259l3.15 2.571429L157.925 277 149 267.228571z"/><g stroke="#163A40" stroke-dasharray="11" stroke-width="5"><path d="M424.5 171.5v-63M339.5 174.5h88"/></g><path d="M119 96H49v67M160 322v38h105" stroke="#163A40" stroke-width="5" stroke-dasharray="12"/><path stroke="#163A40" fill="#FFF" fill-rule="nonzero" d="M455 100h-77V56.871972L416.238095 24 455 56.871972z"/><path fill="#E0E0E0" fill-rule="nonzero" d="M379 57l37.741497 22L455 57"/><path stroke="#979797" fill="#FAFAFA" fill-rule="nonzero" d="M416.764706 79.333333L394 94V39h45v27.971429z"/><path fill="#F5F5F5" fill-rule="nonzero" d="M379 99h76l-76-42z"/><path fill="#E0E0E0" fill-rule="nonzero" d="M400 46h32v2h-32zM400 50h32v2h-32z"/><path fill="#F9A826" fill-rule="nonzero" d="M400 54h32v2h-32z"/><path fill="#E0E0E0" fill-rule="nonzero" d="M400 59h32v2h-32z"/><path fill="#F9A826" fill-rule="nonzero" d="M400 63h32v2h-32z"/><path stroke="#163A40" d="M273 329h88v88h-88z"/><path fill="#FFF" fill-rule="nonzero" d="M278 331h77v68h-77z"/><path d="M355 377.176471c-21.280479 0-38.5-5.447647-38.5-12.176471-21.280479 0-38.5 4.738235-38.5 10.588235V401h77v-23.823529z" fill="#E0E0E0" fill-rule="nonzero"/><circle fill="#FFA318" fill-rule="nonzero" cx="342" cy="346" r="8"/><path stroke="#163A40" fill="#FFF" fill-rule="nonzero" d="M0 170h101v72H0z"/><path d="M53.5 189a19.652713 19.652713 0 00-2.52973.168649L53.5 208.5l-19.452568-1.296486C34.021082 207.630405 34 208.062568 34 208.5c0 10.769553 8.730447 19.5 19.5 19.5S73 219.269553 73 208.5 64.269553 189 53.5 189z" fill="#E0E0E0" fill-rule="nonzero"/><path d="M46.529125 186C37.524358 187.187466 30.605365 194.607353 30 203.725736L49 205l-2.470875-19z" fill="#FFA318" fill-rule="nonzero"/><path fill="#FFF" d="M454 57l-39 22 39 20z"/></g></svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

1
static/img/wave-full.svg Normal file
View File

@ -0,0 +1 @@
<svg width="1559" height="658" viewBox="0 0 1559 658" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient x1="50%" y1="13.758603%" x2="50%" y2="100%" id="a"><stop stop-color="#00C4AC" offset="0%"/><stop stop-color="#35D78C" offset="100%"/></linearGradient></defs><path d="M1559 217c-294 0-475.66667 32-545 96-104 96-331 345-585 345-169.333333 0-312.333333-65.666667-429-197V0h1559v217z" fill="url(#a)" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 434 B

4
static/img/wave.svg Normal file
View File

@ -0,0 +1,4 @@
<svg width="1440" height="682" viewBox="0 0 1440 682" xmlns="http://www.w3.org/2000/svg">
<title>wave</title>
<desc>A green graphic wave.</desc>
<defs><linearGradient x1="50%" y1="13.758603%" x2="50%" y2="100%" id="a"><stop stop-color="#00C4AC" offset="0%"/><stop stop-color="#35D78C" offset="100%"/></linearGradient></defs><path d="M1559 217c-272 0-453.66667 42-545 126-137 126-331 485-585 485-169.333333 0-312.333333-65.666667-429-197V0h1559v217z" transform="translate(-102 -146)" fill="url(#a)" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 525 B

63
static/js/main.js Normal file
View File

@ -0,0 +1,63 @@
// Toggle mobile menu
const burgerMenu = document.getElementById("burger-menu");
const logo = document.getElementById("logo");
const navbar = document.getElementById("navbar");
const body = document.body;
let navbarStatus = false;
burgerMenu.addEventListener("click", function toggleMenu() {
if (!navbarStatus) {
const scrollY = document.documentElement.style.getPropertyValue(
"--scroll-y"
);
navbar.classList.add("isOpen");
navbarStatus = true;
body.style.position = "fixed";
body.style.top = `-${scrollY}`;
} else {
const scrollY = body.style.top;
navbar.classList.remove("isOpen");
navbarStatus = false;
body.style.position = "";
body.style.top = "";
window.scrollTo(0, parseInt(scrollY || "0") * -1);
}
});
let prevScrollpos = window.pageYOffset;
const header = document.getElementById("header");
window.onscroll = function () {
// needed for scroll position after closing the popup
document.documentElement.style.setProperty(
"--scroll-y",
`${window.scrollY}px`
);
// Menu hide and show
let currentScrollPos = window.pageYOffset;
if (prevScrollpos > currentScrollPos) {
// When the user scrolls up, show the navbar
header.classList.add("isVisible");
if (prevScrollpos > 500) {
// Add a background to the navbar below 500px
logo.classList.add("hasBackground");
header.classList.add("hasBackground");
} else {
logo.classList.remove("hasBackground");
header.classList.remove("hasBackground");
}
} else if (!navbarStatus) {
// // When the user scrolls down, hide the navbar. Don't hide navbar when mobile menu is open.
header.classList.remove("isVisible");
}
prevScrollpos = currentScrollPos;
};
// collapsable item
const collapseToggles = document.querySelectorAll("[data-collapse]");
collapseToggles.forEach(function (item) {
item.addEventListener("click", function toggleCollapse() {
item.classList.toggle("collapse--open");
});
});

1677
yarn.lock Normal file

File diff suppressed because it is too large Load Diff