├── .all-contributorsrc ├── .coveragerc ├── .dockerignore ├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yaml │ ├── custom.md │ ├── feature_request.yaml │ ├── meetup.md │ └── newsletter.md └── workflows │ ├── continuous_integration.yml │ ├── coverage.yml │ ├── linting_formatting.yml │ └── push_docker.yml ├── .gitignore ├── .gitlab-ci.yml ├── 00-project-documentation ├── communication │ ├── README.md │ ├── applications │ │ ├── 2023-BOSC.md │ │ ├── 2023-EU-CS-Prize.md │ │ ├── 2024-EU-CS-Prize.md │ │ ├── GSoC │ │ │ ├── AR-GSoC-final-report │ │ │ │ └── README.md │ │ │ ├── AR-project-proposal.md │ │ │ ├── AR-weekly-updates │ │ │ │ ├── week1.md │ │ │ │ ├── week2.md │ │ │ │ ├── week3.md │ │ │ │ ├── week4.md │ │ │ │ ├── week5.md │ │ │ │ ├── week6.md │ │ │ │ ├── week7.md │ │ │ │ ├── week8.md │ │ │ │ ├── week9.md │ │ │ │ └── week_10.md │ │ │ ├── GSoC-2021.md │ │ │ └── KK-expression-of-interest.md │ │ ├── MozFest2022.md │ │ ├── PGSAUT-abstract.md │ │ ├── RRI_application.md │ │ ├── autistica-2021-abstract.md │ │ ├── autistica-festival-2022.md │ │ ├── cc-global-summit-2021.md │ │ ├── cri-internship │ │ │ ├── README.md │ │ │ └── SL-internship-final-report.md │ │ └── fast-stream │ │ │ ├── README.md │ │ │ └── lotty-objectives.md │ ├── newsletters │ │ ├── 00-TEMPLATE-NEWSLETTER.md │ │ ├── README.md │ │ ├── newsletter-20190805.md │ │ ├── newsletter-20190920.md │ │ ├── newsletter-20191125.md │ │ ├── newsletter-20200423.md │ │ ├── newsletter-20200529.md │ │ ├── newsletter-20200630.md │ │ ├── newsletter-20200731.md │ │ ├── newsletter-2021-06.md │ │ ├── newsletter-2021-07.md │ │ ├── newsletter-2021-08.md │ │ ├── newsletter-2021-09.md │ │ ├── newsletter-20210224.md │ │ ├── newsletter-20210430.md │ │ ├── newsletter-20211123.md │ │ ├── newsletter-2022-01.md │ │ ├── newsletter-2022-02.md │ │ ├── newsletter-2022-12.md │ │ ├── newsletter-2023-01.md │ │ ├── newsletter-2023-02.md │ │ ├── newsletter-2023-03.md │ │ ├── newsletter-2023-04.md │ │ ├── newsletter-2023-05.md │ │ ├── newsletter-2023-06.md │ │ ├── newsletter-2023-07.md │ │ ├── newsletter-2023-08.md │ │ ├── newsletter-2023-09.md │ │ ├── newsletter-2023-10.md │ │ ├── newsletter-2023-11.md │ │ ├── newsletter-2023-12.md │ │ ├── newsletter-2024-01.md │ │ ├── newsletter-2024-02.md │ │ ├── newsletter-2024-03.md │ │ ├── newsletter-2024-04.md │ │ ├── newsletter-2024-05.md │ │ ├── newsletter-2024-06.md │ │ ├── newsletter-2024-07.md │ │ └── newsletter-2024-08.md │ ├── presentations │ │ └── README.md │ └── reports │ │ ├── README.md │ │ ├── academic-updates │ │ ├── annual-health-programme-update.md │ │ └── researchfish-updates-2021.md │ │ ├── autistica │ │ └── 2023-post-project-report.md │ │ ├── sprint-reports │ │ ├── README.md │ │ ├── sprint-1.md │ │ ├── sprint-10.md │ │ ├── sprint-2.md │ │ ├── sprint-4.md │ │ ├── sprint-5.md │ │ ├── sprint-6.md │ │ ├── sprint-7.md │ │ ├── sprint-8.md │ │ └── sprint-9.md │ │ └── turing-health-quartery-updates │ │ ├── README.md │ │ ├── Turing-final-report.md │ │ ├── autistica-project-updates-q2-2019_20.md │ │ └── autistica-project-updates-q3-2019_20.md ├── community │ ├── AutSPACEs Platform Participant Information Sheet.docx │ ├── AutSPACEs Platform Participant Information Sheet.pdf │ ├── README.md │ ├── Safeguarding.md │ ├── focus-groups │ │ ├── 04-october-2019.md │ │ ├── 18-september-2019.md │ │ ├── 24-september-2019.md │ │ ├── README.md │ │ └── creation-of-summaries.md │ ├── images │ │ └── noun-project-icons │ │ │ ├── noun_Conversation_2041500.png │ │ │ ├── noun_Document_188540.png │ │ │ ├── noun_Eye_2040041.png │ │ │ ├── noun_online_1632606.png │ │ │ ├── noun_todolist_1128326.png │ │ │ └── noun_transcript_532343.png │ ├── meet-ups │ │ └── README.md │ ├── moderation-workshop │ │ ├── README.md │ │ ├── creation-of-report.md │ │ └── moderation-report.md │ └── user-tests │ │ ├── 2023-09-user-testing-prompts.md │ │ ├── AutSPACEs User Testing_ Participant Information Sheet.pdf │ │ ├── AutSPACEs-consent-form.pdf │ │ ├── README.md │ │ ├── user-test-notes.md │ │ └── user-testing-notes-2024.md ├── ethics │ ├── AutSPACEs_Platform_ParticipantInformationSheet_20240221.pdf │ └── TREx2-form-approved.pdf ├── moderation │ ├── README.md │ ├── moderation-decisions.md │ ├── moderation-review-guidelines.md │ └── moderator-guidelines.md └── platform-design │ ├── README.md │ └── platform-design │ ├── README.md │ ├── design-process │ ├── 15-11-21-AutSPACEs-Design-Process.pdf │ └── README.md │ ├── design-requirements │ ├── README.md │ ├── accessibility-checklist.md │ └── requirements-list.md │ ├── design-research │ ├── AutSPACES Feedback (19.10).pdf │ ├── Personas │ │ ├── Ali.md │ │ ├── August.md │ │ ├── Cameron.md │ │ ├── Jesse.md │ │ ├── Kendall.md │ │ ├── Persona-Template.md │ │ └── README.md │ ├── README.md │ └── feedback-linkspad.md │ ├── design-system │ ├── README.md │ └── design-code-20220222.md │ ├── platform-architecture │ ├── README.md │ ├── autspaces-ia-diagram-15-11-2021.md │ ├── autspaces-ia-diagram-15-11-2021.png │ ├── autspaces-ia-diagram-21-02-2022.png │ └── autspaces-ia-diagram-22-11-2021.png │ ├── platform-content │ ├── README.md │ ├── submit-experience.drawio │ └── what-is-autism.md │ └── wireframes │ └── README.md ├── Citscicartoon.png ├── Dockerfile ├── LICENSE ├── README.md ├── code-of-conduct.md ├── config ├── .env.actions ├── .env.template └── sshd_config ├── contributing-guidelines.md ├── dev_readme.md ├── docker-compose.override.yml ├── docker-compose.yml ├── docker-run.sh ├── docker ├── caddy │ └── Caddyfile ├── ci.sh ├── django │ ├── Dockerfile │ ├── entrypoint.sh │ └── gunicorn.sh └── docker-compose.prod.yml ├── docs ├── Makefile ├── _static │ └── .gitkeep ├── _templates │ └── moreinfo.html ├── conf.py ├── documents │ └── .gitkeep ├── index.rst ├── make.bat └── pages │ ├── project │ └── .gitkeep │ └── template │ ├── development.rst │ ├── django.rst │ ├── documentation.rst │ ├── faq.rst │ ├── gitlab-ci.rst │ ├── linters.rst │ ├── overview.rst │ ├── production-checklist.rst │ ├── production.rst │ ├── security.rst │ ├── testing.rst │ ├── troubleshooting.rst │ └── upgrading-template.rst ├── fly.toml ├── locale └── .gitkeep ├── manage.py ├── poetry.lock ├── pyproject.toml ├── server ├── README.md ├── __init__.py ├── apps │ ├── __init__.py │ ├── main │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── carousel.json │ │ ├── context_processors.py │ │ ├── feeds.py │ │ ├── forms.py │ │ ├── helpers.py │ │ ├── management │ │ │ └── commands │ │ │ │ ├── seed_db.py │ │ │ │ └── unseed_db.py │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ ├── 0002_add_fields_to_public_experiences.py │ │ │ ├── 0003_publicexperience_title_text.py │ │ │ ├── 0004_update_publicexperience_class.py │ │ │ ├── 0005_auto_20230105_1303.py │ │ │ ├── 0006_auto_20230123_1209.py │ │ │ ├── 0007_auto_20230123_1341.py │ │ │ ├── 0008_experiencehistory.py │ │ │ ├── 0009_auto_20230327_1226.py │ │ │ ├── 0010_experiencehistory_change_reply.py │ │ │ ├── 0011_publicexperience_authorship_relation_and_more.py │ │ │ └── __init__.py │ │ ├── mod_message.txt │ │ ├── models.py │ │ ├── templates │ │ │ └── main │ │ │ │ ├── about_us.html │ │ │ │ ├── application.html │ │ │ │ ├── confirmation_page.html │ │ │ │ ├── content_moderation_guidelines.html │ │ │ │ ├── deletion_confirmation.html │ │ │ │ ├── deletion_success.html │ │ │ │ ├── experiences_page.html │ │ │ │ ├── feed.html │ │ │ │ ├── help.html │ │ │ │ ├── home.html │ │ │ │ ├── moderate_experience.html │ │ │ │ ├── moderate_public_experiences.html │ │ │ │ ├── moderation_list.html │ │ │ │ ├── moderation_table.html │ │ │ │ ├── my_stories.html │ │ │ │ ├── new_confirmation_page.html │ │ │ │ ├── pagination.html │ │ │ │ ├── partials │ │ │ │ ├── dummy_stories.html │ │ │ │ ├── footer.html │ │ │ │ ├── jquery.html │ │ │ │ ├── moderatIon_status.html │ │ │ │ ├── navigation.html │ │ │ │ ├── template_moderation_dropdown.html │ │ │ │ ├── template_moderation_warnings.html │ │ │ │ └── upload_form.html │ │ │ │ ├── participant_information.html │ │ │ │ ├── registration.html │ │ │ │ ├── share_experiences.html │ │ │ │ ├── single_story.html │ │ │ │ ├── story_table.html │ │ │ │ ├── success_confirm.html │ │ │ │ ├── unused │ │ │ │ ├── complete.html │ │ │ │ ├── index.html │ │ │ │ ├── list.html │ │ │ │ ├── moderate_public_experiences_old.html │ │ │ │ ├── overview.html │ │ │ │ ├── public_experiences.html │ │ │ │ ├── signup.html │ │ │ │ ├── signup1.html │ │ │ │ └── upload.html │ │ │ │ └── what_autism_is.html │ │ ├── templatetags │ │ │ ├── __init__.py │ │ │ └── custom_tags.py │ │ ├── tests │ │ │ ├── __init__.py │ │ │ ├── carousel-test01.json │ │ │ ├── carousel-test02.json │ │ │ ├── carousel-test03.json │ │ │ ├── carousel-test04.json │ │ │ ├── fixtures │ │ │ │ ├── delete.yaml │ │ │ │ ├── delete_all.yaml │ │ │ │ ├── delete_exp.yaml │ │ │ │ ├── delete_single.yaml │ │ │ │ ├── edit_experience.yaml │ │ │ │ ├── edit_sharing.yaml │ │ │ │ ├── example_experiences_seed.csv │ │ │ │ ├── get_oh_combined.yaml │ │ │ │ ├── get_oh_file.yaml │ │ │ │ ├── helper-context.json │ │ │ │ ├── load_to_edit.yaml │ │ │ │ ├── load_to_edit_exists.yaml │ │ │ │ ├── load_to_edit_noreply.yaml │ │ │ │ ├── moderate_experience.yaml │ │ │ │ ├── my_stories.yaml │ │ │ │ ├── my_stories_duplicate_uuid.yaml │ │ │ │ ├── pag_mystories.yaml │ │ │ │ ├── share_experience.yaml │ │ │ │ ├── token_exchange_valid.yaml │ │ │ │ ├── upload_file.yaml │ │ │ │ └── view_exp.yaml │ │ │ ├── jh_tests.py │ │ │ ├── jh_tests_view.py │ │ │ ├── test_helpers.py │ │ │ ├── test_management_commands.py │ │ │ ├── test_models.py │ │ │ ├── test_moderate_views.py │ │ │ ├── test_my_stories.py │ │ │ ├── test_templatetags.py │ │ │ ├── test_views.py │ │ │ └── tests_2023.py │ │ ├── urls.py │ │ └── views.py │ └── users │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── forms.py │ │ ├── helpers.py │ │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_userprofile_refine_fields.py │ │ ├── 0003_alter_userprofile_autistic_identification.py │ │ └── __init__.py │ │ ├── models.py │ │ ├── templates │ │ └── users │ │ │ ├── delete.html │ │ │ ├── goodbye.html │ │ │ ├── profile.html │ │ │ └── select_option_disable_empty.html │ │ ├── tests │ │ ├── __init__.py │ │ ├── fixtures │ │ │ └── delete_user.yaml │ │ ├── test_helpers.py │ │ ├── test_models.py │ │ └── test_views.py │ │ ├── urls.py │ │ └── views.py ├── settings │ ├── __init__.py │ ├── components │ │ ├── __init__.py │ │ ├── caches.py │ │ ├── common.py │ │ ├── csp.py │ │ └── logging.py │ └── environments │ │ ├── __init__.py │ │ ├── development.py │ │ ├── local.py │ │ ├── local.py.template │ │ └── production.py ├── templates │ └── txt │ │ ├── humans.txt │ │ └── robots.txt ├── urls.py └── wsgi.py ├── setup.cfg ├── static ├── css │ ├── main.css │ └── navigation_dark.css ├── images │ ├── alanturing.png │ ├── animation_a.jpg │ ├── animation_b.jpg │ ├── animation_c.jpg │ ├── animation_d.jpg │ ├── autistica.png │ ├── heart-fill.svg │ ├── pencil-square.svg │ ├── pie-chart-fill.svg │ ├── send.svg │ ├── share-fill.svg │ ├── submit-experience.svg │ ├── submit-experience_grey.svg │ └── ui-checks.svg └── js │ ├── activate-profile.js │ ├── jquery.connections.js │ ├── main.js │ ├── menu-alignment.js │ ├── moderation-dialogue.js │ ├── moderation-replies.js │ ├── registration-connections.js │ ├── set_relationship_vis.js │ ├── shared-stories-filtering.js │ ├── store-tab.js │ ├── submit-warning.js │ └── theme-checker.js └── tests ├── conftest.py ├── test_apps └── test_main │ ├── test_models │ ├── test_blog_post_model.py │ └── test_migrations │ │ └── test_blog_post_migrations.py │ └── test_views │ └── test_index_view.py └── test_server └── test_urls.py /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | relative_files = True 3 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | 47 | # Translations 48 | *.mo 49 | *.pot 50 | 51 | # Django stuff: 52 | *.log 53 | 54 | # Sphinx documentation 55 | docs/_build/ 56 | 57 | # PyBuilder 58 | target/ 59 | 60 | # Docker 61 | Dockerfile 62 | docker-compose.yml 63 | docker-compose.override.yml 64 | docker/docker-compose.prod.yml 65 | 66 | # JetBrains 67 | .idea/ 68 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Check http://editorconfig.org for more information 2 | # This is the main config file for this project: 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | end_of_line = lf 8 | insert_final_newline = true 9 | indent_style = space 10 | indent_size = 2 11 | trim_trailing_whitespace = true 12 | 13 | [*.py] 14 | indent_style = space 15 | indent_size = 4 16 | 17 | [*.pyi] 18 | indent_style = space 19 | indent_size = 4 20 | 21 | [Makefile] 22 | indent_style = tab 23 | 24 | [*.md] 25 | trim_trailing_whitespace = false 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yaml: -------------------------------------------------------------------------------- 1 | name: Bug report 2 | description: Report an issue with using AutSPACEs 3 | title: "[BUG]: " 4 | labels: ["bug"] 5 | body: 6 | - type: textarea 7 | id: describe 8 | attributes: 9 | label: Describe the bug 10 | description: Please describe the bug, including any error messages you encounter. You can attach screenshots if available. 11 | - type: textarea 12 | id: reproduce 13 | attributes: 14 | label: Steps to reproduce 15 | description: Steps to reproduce this behaviour. 16 | placeholder: | 17 | 1. In this environment... 18 | 1. With this config... 19 | 1. Run '...' 20 | 1. See error... 21 | - type: textarea 22 | id: environment 23 | attributes: 24 | label: In which environment are you using AutSPACEs? 25 | description: What OS and browser are you running to run/access AutSPACEs? 26 | - type: textarea 27 | id: comment 28 | attributes: 29 | label: Other comments 30 | description: Add any other context about the problem here (e.g. expected behaviour) 31 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/custom.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: General issue 3 | about: 'General ' 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 13 | ### Summary 14 | 15 | 17 | 18 | ### Deadline 19 | 20 | ### What needs to be done? 21 | 22 | 23 | 24 | - [ ] 25 | - [ ] 26 | 27 | ### Who can help? 28 | 29 | 30 | 31 | * 32 | * 33 | 34 | --- 35 | 36 | ### Updates 37 | 38 | 40 | 41 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yaml: -------------------------------------------------------------------------------- 1 | name: Feature request 2 | description: Suggest a new feature for AutSPACEs 3 | title: "[FEATURE]: " 4 | labels: ["enhancement"] 5 | body: 6 | - type: dropdown 7 | attributes: 8 | label: Feature for… 9 | description: Is this a feature for the front-end or back-end? 10 | multiple: false 11 | options: 12 | - Frontend 13 | - Backend 14 | - Frontend and Backend 15 | - type: textarea 16 | id: problem 17 | attributes: 18 | label: What is the problem you want to solve? 19 | description: Give a brief and clear description of the problem you want to would solve. 20 | - type: textarea 21 | id: solution 22 | attributes: 23 | label: How do you want to solve the problem? 24 | description: What is the solution you have in mind to solve this problem? 25 | placeholder: | 26 | 1. I propose solving the problem by doing… 27 | 1. These are the alternative solutions… 28 | 1. This solution could be preferred because… 29 | - type: textarea 30 | id: comment 31 | attributes: 32 | label: Other comments 33 | description: Add any other context about the problem or solution here 34 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/meetup.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Meetup Planning 3 | about: 'Planning the monthly AutSPACEs meetup' 4 | title: 'Meetup: MONTH YEAR' 5 | labels: 'Community inclusion' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Summary 11 | 12 | 14 | 15 | ### Deadline 16 | 17 | End of month 18 | 19 | ### What needs to be done? 20 | 21 | 22 | 23 | - [ ] create a google doc, following the [template of previous meetups](https://github.com/alan-turing-institute/AutSPACEs/wiki/Meetups) (don't overwrite old meetup notes!) 24 | - [ ] update [AutSPACEs Wiki page on GH](https://github.com/alan-turing-institute/AutSPACEs/wiki/Meetups) with upcoming date & link to meetup notes document 25 | - [ ] collect topics for discussion and potential speakers if necessary 26 | - [ ] include topics etc in monthly newsletter 27 | - [ ] send out newsletter 28 | - [ ] run meetup 29 | - [ ] update Wiki page again to move notes into "past meetups" and announce next date 30 | 31 | --- 32 | 33 | ### Updates 34 | 35 | 37 | 38 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/newsletter.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Newsletter 3 | about: 'To-Do for writing the monthly newsletter' 4 | title: 'Newsletter MONTH YEAR' 5 | labels: 'Community inclusion' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Summary 11 | 12 | 14 | 15 | ### Deadline 16 | 17 | ### What needs to be done? 18 | 19 | 20 | 21 | - [ ] create _HackMD_ [from template](https://hackmd.io/@gedankenstuecke/BypHfzPEC) for drafting 22 | - [ ] add link to HackMD to this issue 23 | - [ ] collect topics & potential spotlight interview person 24 | - [ ] draft newsletter 25 | - [ ] get newsletter reviewed 26 | - [ ] send out newsletter 27 | - [ ] add newsletter to [GitHub Folder](https://github.com/alan-turing-institute/AutSPACEs/tree/main/00-project-documentation/communication/newsletters) 28 | 29 | --- 30 | 31 | ### Updates 32 | 33 | 35 | 36 | -------------------------------------------------------------------------------- /.github/workflows/coverage.yml: -------------------------------------------------------------------------------- 1 | name: Post coverage comment 2 | 3 | on: 4 | workflow_run: 5 | workflows: ["CI"] 6 | types: 7 | - completed 8 | 9 | jobs: 10 | test: 11 | name: Run tests & display coverage 12 | runs-on: ubuntu-latest 13 | if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success' 14 | permissions: 15 | # Gives the action the necessary permissions for publishing new 16 | # comments in pull requests. 17 | pull-requests: write 18 | # Gives the action the necessary permissions for editing existing 19 | # comments (to avoid publishing multiple comments in the same PR) 20 | contents: write 21 | # Gives the action the necessary permissions for looking up the 22 | # workflow that launched this workflow, and download the related 23 | # artifact that contains the comment to be published 24 | actions: read 25 | steps: 26 | # DO NOT run actions/checkout here, for security reasons 27 | # For details, refer to https://securitylab.github.com/research/github-actions-preventing-pwn-requests/ 28 | - name: Post comment 29 | uses: py-cov-action/python-coverage-comment-action@v3 30 | with: 31 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 32 | GITHUB_PR_RUN_ID: ${{ github.event.workflow_run.id }} 33 | # Update those if you changed the default values: 34 | # COMMENT_ARTIFACT_NAME: python-coverage-comment-action 35 | # COMMENT_FILENAME: python-coverage-comment-action.txt -------------------------------------------------------------------------------- /.github/workflows/linting_formatting.yml: -------------------------------------------------------------------------------- 1 | name: Linting and Formatting 2 | 3 | on: [push] 4 | 5 | jobs: 6 | ubuntu-tests: 7 | runs-on: ${{ matrix.os }} 8 | strategy: 9 | matrix: 10 | os: 11 | - ubuntu-20.04 12 | python-version: 13 | - 3.12.2 14 | fail-fast: false 15 | 16 | 17 | steps: 18 | - uses: actions/checkout@v3 19 | with: 20 | fetch-depth: 2 21 | 22 | - name: Set up Python ${{ matrix.python-version }} 23 | uses: actions/setup-python@v4 24 | with: 25 | python-version: ${{ matrix.python-version }} 26 | 27 | 28 | - name: Update pip 29 | run: | 30 | python -m ensurepip 31 | python -m pip install --upgrade pip 32 | 33 | - name: Install Tools 34 | run: | 35 | python -m pip install black flake8 36 | 37 | - name: Linting and Formatting 38 | run: | 39 | python -m flake8 ./server/apps/main/views.py --count --select=E9,F63,F7,F82, --ignore=F821 --show-source --statistics 40 | python -m black --diff ./server/apps/main/views.py -------------------------------------------------------------------------------- /.github/workflows/push_docker.yml: -------------------------------------------------------------------------------- 1 | name: Push to Docker 2 | 3 | on: 4 | push: 5 | branches: 6 | - 'main' 7 | 8 | jobs: 9 | docker: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - 13 | name: Set up QEMU 14 | uses: docker/setup-qemu-action@v3 15 | - 16 | name: Set up Docker Buildx 17 | uses: docker/setup-buildx-action@v3 18 | - 19 | name: Login to Docker Hub 20 | uses: docker/login-action@v3 21 | with: 22 | username: ${{ secrets.DOCKERHUB_USERNAME }} 23 | password: ${{ secrets.DOCKERHUB_TOKEN }} 24 | - 25 | name: Build and push 26 | uses: docker/build-push-action@v5 27 | with: 28 | push: true 29 | tags: gedankenstuecke/autspaces:v1 -------------------------------------------------------------------------------- /00-project-documentation/communication/README.md: -------------------------------------------------------------------------------- 1 | # Project communications 2 | 3 | You can find (nearly) all of the official communications done by and on the AutSPACEs project in this folder. 4 | 5 | ## Contents 6 | 7 | ### Applications 8 | This includes applications for funding, internships, conference presentations and so on. 9 | 10 | ### Newsletters 11 | We send regular updates to our community to keep them updated on how the project is progressing. 12 | This directory contains the original versions of these newsletters for our records and to make them easy to re-use in the future. 13 | 14 | ### Presentations 15 | When we deliver presentations, we publish our slides openly on Zenodo.org. This folder contains links to those slides. 16 | 17 | ### Reports 18 | Progress reports on AutSPACEs. These can be internal sprint updates or official reports we have written. 19 | 20 | ## Subscribe to the mailing list 21 | 22 | 📫 You can subscribe to receive the project newsletter by email at [https://tinyletter.com/AutisticaTuringCitizenScience](https://tinyletter.com/AutisticaTuringCitizenScience). 23 | 24 | ✉️ You can see all the archives of the newsletter at [https://tinyletter.com/AutisticaTuringCitizenScience/archive](https://tinyletter.com/AutisticaTuringCitizenScience/archive). 25 | -------------------------------------------------------------------------------- /00-project-documentation/communication/applications/GSoC/AR-weekly-updates/week1.md: -------------------------------------------------------------------------------- 1 | # Week 1 2 | This week I completed working on the landing page for the AutSPACEs website with reference to the simplified wire frames created with the needs of the autistic people in mind. I also pushed my work to the AutSPACEs repository. In addition to this, I attended a platform development co-working session where I explained to the new contributors how to solve issues from the repo and how the backend database Open Humans works. I also helped some contributors set up docker on their machine and build the website on the computer. I’ve also started working on the Share Experiences page. 3 | 4 | My plan for next week is to complete the Share Experiences page and integrate the pages made by me and another contributor into Django to implement the user flow of the website. I would also want to complete other static pages like the My Stories page which is part of Milestone 2 which we trying to complete as soon as possible. 5 | 6 | As of now, the only blocker I’ve faced is trying to build the documentation on my machine. There was an issue with installing a new version of Python which stopped my terminal from opening. However, I was able to fix that issue but had to revert back to my previous version. The documentation, unfortunately needs that new Python version to run a package called poetry which installs dependencies to build the documentation. I talked a lot to the lead developer regarding this and I’m planning to try using pyenv to do this. However, the documentation build isn’t a major priority as of now as the main code needs to be written first. I will definitely try pyenv later to see if that fixes the issue. -------------------------------------------------------------------------------- /00-project-documentation/communication/applications/GSoC/AR-weekly-updates/week2.md: -------------------------------------------------------------------------------- 1 | # Week 2 2 | This week I completed making the Share Experiences Page according to the simplified wireframes and sent a [PR](https://github.com/alan-turing-institute/AutSPACEs/pull/114) 3 | I also tried integrating the landing page into the site and connecting it with the existing sign in authorisation to Open Humans which worked. The View Experiences page handled by another contributor had a couple of issues regarding Bootstrap. I’ve helped her out with what needs to be done so that can be ready to integrate into the site. In addition to this, I helped other new contributors with building the site locally and explaining the entire code base to them so that they know where exactly to contribute. As of now, we’d almost be completing Milestone 2 and we’ll be starting Milestone 3. 4 | 5 | My plan for next week is to integrate all the static pages from Milestone 2 into the site so that I have the basic user flow in place. I will also create a small basic guide for Bootstrap in the repository for beginners to refer to it while contributing as instructed by the community manager. 6 | 7 | As of this week, no blockers have popped up. -------------------------------------------------------------------------------- /00-project-documentation/communication/applications/GSoC/AR-weekly-updates/week3.md: -------------------------------------------------------------------------------- 1 | # Week 3 (21st June - 27th June) 2 | This week I integrated my pages into Django where now you can enter experiences through that page and it will be stored in a local database for now. The landing page for now contains the sign in button which directs the user to Open Humans for project authorisation. By the end of this week, we should have an MVP of the site up and running. 3 | 4 | My plan for next week is to ensure that MVP is set up and presented to the community in the week after. 5 | 6 | One blocker I had was to completely finalise on a definite sign up flow for the site. I would be talking to Bastian who is a part of Open Humans to get some guidance on how to go about this and also get that finalised by next week. -------------------------------------------------------------------------------- /00-project-documentation/communication/applications/GSoC/AR-weekly-updates/week4.md: -------------------------------------------------------------------------------- 1 | # Week 4 (28th June - 4th July) 2 | 3 | **Done** 4 | 5 | * Made changes in PR [#114](https://github.com/alan-turing-institute/AutSPACEs/pull/114) and [#115](https://github.com/alan-turing-institute/AutSPACEs/pull/115) after review by James. They should be merged after James gives one final review. 6 | * Added some items to checklist in issue #119 and set a date to show the MVP to the community. 7 | 8 | **Planned** 9 | 10 | * Present MVP to the community 11 | * Add documentation for the code 12 | * List feedback from the community and make changes 13 | 14 | **Blockers** 15 | 16 | Missed out on a bit of time due to side effects from the vaccine. Will be covering up remaining work this weekend. 17 | 18 | -------------------------------------------------------------------------------- /00-project-documentation/communication/applications/GSoC/AR-weekly-updates/week5.md: -------------------------------------------------------------------------------- 1 | # Week 5 (5th July - 11th July) 2 | 3 | **Done** 4 | 5 | * PRs #114 and #115 got merged. 6 | * Integrated the pages of the site and created an MVP. 7 | * Presented the MVP to the autistic community in yesterday’s community call and got some feedback. 8 | 9 | **Planned** 10 | 11 | * Start integrating the sign up and moderation aspects which were still under development by their respective contributors. 12 | * Start adding documentation for the code 13 | * Start looking into Milestone 3 14 | 15 | **Blockers** 16 | 17 | None. -------------------------------------------------------------------------------- /00-project-documentation/communication/applications/GSoC/AR-weekly-updates/week6.md: -------------------------------------------------------------------------------- 1 | # Week 6 (12th July - 18th July) 2 | 3 | **Done** 4 | 5 | * Discussed about what the moderation process will be on site, how the moderators will be assigned, and what kind of communication will the moderator have with the user. It was decided to move the sign up process to Milestone 3 6 | * Completed first GSoC evaluation 7 | * Worked on PR [#117](https://github.com/alan-turing-institute/AutSPACEs/pull/117) and [#116](https://github.com/alan-turing-institute/AutSPACEs/pull/116) 8 | 9 | **Planned** 10 | 11 | * Push final changes to both PRs 12 | * Start adding documentation for the code 13 | 14 | **Blockers** 15 | 16 | None. -------------------------------------------------------------------------------- /00-project-documentation/communication/applications/GSoC/AR-weekly-updates/week7.md: -------------------------------------------------------------------------------- 1 | # Week 7 (19th July - 25th July) 2 | 3 | **Done** 4 | 5 | * Completed pushing changes to PR [#117](https://github.com/alan-turing-institute/AutSPACEs/pull/117) and [#116](https://github.com/alan-turing-institute/AutSPACEs/pull/116) and got merged 6 | * Started working on issue [#138](https://github.com/alan-turing-institute/AutSPACEs/issues/138) 7 | * Had productive discussions on moderation and decided how we’d be starting Milestone 3 8 | 9 | **Planned** 10 | 11 | * Complete issue #138 12 | * Take up issues in Milestone 3 13 | 14 | **Blockers** 15 | 16 | None. -------------------------------------------------------------------------------- /00-project-documentation/communication/applications/GSoC/AR-weekly-updates/week8.md: -------------------------------------------------------------------------------- 1 | # Week 8 (26th July - 1st August) 2 | 3 | **Done** 4 | 5 | * Pushed PRs [#146](https://github.com/alan-turing-institute/AutSPACEs/pull/146), [#147](https://github.com/alan-turing-institute/AutSPACEs/pull/147), [#143](https://github.com/alan-turing-institute/AutSPACEs/pull/143) 6 | * Started working on creating an issue for integrating the View Experiences page for Milestone 3 7 | * Had productive discussions on Open Humans and integrating the page with the backend. 8 | 9 | **Planned** 10 | 11 | * Complete writing up issue on View Experiences 12 | * Start looking into the moderation pages for the site 13 | 14 | **Blockers** 15 | 16 | None. -------------------------------------------------------------------------------- /00-project-documentation/communication/applications/GSoC/AR-weekly-updates/week9.md: -------------------------------------------------------------------------------- 1 | # Week 9 (2nd August - 8th August) 2 | 3 | **Done** 4 | 5 | * Made a couple of changes in PR [#151](https://github.com/alan-turing-institute/AutSPACEs/pull/151) 6 | * Made an issue for Milestone 3 regarding integration of the my_stories page 7 | 8 | **Planned** 9 | 10 | * Start planning the GSoC work report 11 | * Wrap up any pending work 12 | 13 | **Blockers** 14 | 15 | None. -------------------------------------------------------------------------------- /00-project-documentation/communication/applications/GSoC/AR-weekly-updates/week_10.md: -------------------------------------------------------------------------------- 1 | # Week 10 (9th August - 15th August) 2 | 3 | **Done** 4 | 5 | * Took up issue #157 1 regarding integration of the view experiences page 6 | * Issue that I made for my_stories got reviewed and verified and it’s taken up by another contributor 7 | * Completed half of my GSoC work report 8 | 9 | **Planned** 10 | 11 | * Complete work report 12 | 13 | **Blockers** 14 | 15 | None. 16 | 17 | -------------------------------------------------------------------------------- /00-project-documentation/communication/applications/autistica-2021-abstract.md: -------------------------------------------------------------------------------- 1 | # Autistica Research Festival 2021 - abstract proposal 2 | 3 | *This is an abstract submitted for the Autistica 2021 research festival by Susanna Fantoni, Georgia Aitkenhead, and James Scott.* 4 | 5 | We will present new research concerning a unique, co-created moderation process for a participatory citizen-science platform: AutSPACEs. 6 | AutSPACEs is a research platform being designed by and for autistic people and their allies, to share their experiences of sensory processing in their daily lives. 7 | The data collected can then be gathered to modify environments so that they are better suited to autistic people. 8 | 9 | Crucial to the success of the platform is an effective moderation process that allows autistic people to feel safe but not censored, heard but not misheard, and welcomed as individuals as part of a community. 10 | It is vital that a diverse group of neurodivergent people are both enabled and protected. 11 | Rather than a top-down approach where rules created by moderators are imposed on users, we demonstrate a participatory co-creative process in which all members are invited to take part in designing and maintaining a moderation process for autistic people in particular. 12 | 13 | 14 | The talk will be given by a non-autistic researcher and two autistic participant researchers. 15 | We will begin by briefly setting the context and describing the co-creation process, as well as highlighting some of the complexities and themes emerging. 16 | We will go on to discuss challenges, risks, and mitigation strategies identified. 17 | We will then consider the implications of allowing non-autistic people to speak for autistic people in special cases. 18 | Finally, we will invite attendees to participate in creating the moderation process themselves. 19 | -------------------------------------------------------------------------------- /00-project-documentation/communication/applications/cri-internship/README.md: -------------------------------------------------------------------------------- 1 | Saved for work by Sowmya Rajan. 2 | -------------------------------------------------------------------------------- /00-project-documentation/communication/applications/fast-stream/README.md: -------------------------------------------------------------------------------- 1 | # Civil Service Fast Stream 2 | 3 | Here you will find documentation associated with contributors from the Fast Stream. 4 | 5 | The Fast Stream is a leadership programme run by the Civil Service. 6 | The Alan Turing Institute recieves Fast Streamers on secondment to carry out roles in various projects. 7 | 8 | So far those who have worked on the project are: 9 | 10 | * Lotty Coupat - Community Manager - April 2021-September2021 11 | -------------------------------------------------------------------------------- /00-project-documentation/communication/newsletters/README.md: -------------------------------------------------------------------------------- 1 | ## Subscribe to the mailing list 2 | 3 | 📫 You can subscribe to receive the project newsletter by email at [https://tinyletter.com/AutisticaTuringCitizenScience](https://tinyletter.com/AutisticaTuringCitizenScience). 4 | 5 | ✉️ You can see all the archives of the newsletter at [https://tinyletter.com/AutisticaTuringCitizenScience/archive](https://tinyletter.com/AutisticaTuringCitizenScience/archive). 6 | 7 | You can find a template for making a newsletter at [00-TEMPLATE-NEWSLETTER.md](00-TEMPLATE-NEWSLETTER.md). 8 | 9 | ## Formatting the newsletter 10 | 11 | *This information is for members of the project team who have write access to the TinyLetter mailing list.* 12 | 13 | Rather than formatting the newsletter in the TinyLetter page, please use this markdown to html converter tool: [https://www.browserling.com/tools/markdown-to-html](https://www.browserling.com/tools/markdown-to-html). 14 | 15 | Combining free text and markdown can introduce strange layout changes (really large fonts and odd spacings) that are not easy to spot until you've sent the newsletter. 16 | You are more likely to successfully send a nicely formatted newsletter by converting markdown to raw html and entering that into TinyLetter dashboard. 17 | -------------------------------------------------------------------------------- /00-project-documentation/communication/reports/README.md: -------------------------------------------------------------------------------- 1 | # Reports 2 | 3 | This folder contains reports done about the AutSPACEs project, including: 4 | 5 | - academic reports, 6 | - older sprint reports, 7 | - Turing updates 8 | -------------------------------------------------------------------------------- /00-project-documentation/communication/reports/sprint-reports/sprint-6.md: -------------------------------------------------------------------------------- 1 | Sprint Report: 6 2 | 3 | Dates: 7 July 2020 – 22 July 2020 4 | 5 | This file contains reports of work completed during Fujitsu team sprints. 6 | 7 | More details about this process can be found in the agile-opensource-workflow.md and sprint-demo-requirements.md files in the project-management directory. 8 | Issues closed 9 | 10 | These tasks were closed during the sprint. 11 | 12 | #299: Prototype: Dashboard Notifcations 13 | #290: Prototype: Dashboard - Community Recommendations 14 | #297: Prototype: Screen Reader - review of focus groups 15 | #296: Prototype: Sound Submit Prompt 16 | #294: Prototype: Experience Submission 17 | #262: Prototype: Upload Image / Sound 18 | #188: Create a community involvement strategy 19 | 20 | Issues progressed 21 | 22 | Progress was made on these tasks but they were not closed during the sprint. 23 | 24 | #261: Short Detail Submission Wireframe Review 25 | #310: URL Specification 26 | #307: Translate focus group requirements into issues 27 | #311: Welcome Katharina Kloppenborg 28 | #274: Make it easier for contributors 29 | #305: Github Audit 30 | #273: Research Festival Q&A 31 | #292: Modular Alerts Defined by Data 32 | Design Considerations - liked to Research Festival Q&A Session and Re-Review of Focus Groups Findings 33 | 34 | 35 | Need Discussion: 36 | 37 | #307: Translate focus group requirements into issues 38 | #263: Sanctuary location categories 39 | #261: Short Detail Submission Wireframe Review 40 | #204: Gather feedback on videos each sprint 41 | 42 | Issues not progressed 43 | 44 | #263: Sanctuary location categories 45 | #173: Prototype: Develop paired down secured engagement component - add to about page 46 | 47 | Issues opened 48 | 49 | These tasks were opened during the sprint but no work was done to address them. 50 | 51 | #111: Moderation Features 52 | Further profile / demographic related works 53 | Interfacing with OH API's 54 | Progressing works for review - testing of functionality of coded components 55 | 56 | Challenges 57 | 58 | No challenges were highlighted in this sprint. 59 | Request for community feedback 60 | 61 | Feedback is requested from the community on the following tasks. 62 | 63 | #182: issue to collect feedback on sprints 64 | Link to video: https://youtu.be/UAon_KHBaMM 65 | -------------------------------------------------------------------------------- /00-project-documentation/communication/reports/sprint-reports/sprint-8.md: -------------------------------------------------------------------------------- 1 | # Sprint Report: 8 2 | 3 | **Dates: 13082020 - 31082020** 4 | 5 | This file contains links to the Autistica Presentation which was given by the team on the 26082020. It was agreed this would replace the need for a standard report and 6 | the standard Sprint Video Demos. 7 | 8 | 9 | ### Autistica Presentation 10 | Overview of Works Sprints 1 - 8 11 | 12 | ###Presentation of Design 13 | * Link to video: [https://youtu.be/pX66xqRZYW4] (https://youtu.be/pX66xqRZYW4) 14 | 15 | 16 | ###Presentation of Development Work 17 | * Link to video: [https://youtu.be/MY9nLqf8dtI] (https://youtu.be/MY9nLqf8dtI 18 | ) 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /00-project-documentation/communication/reports/turing-health-quartery-updates/README.md: -------------------------------------------------------------------------------- 1 | This folder contains reports from 2019, these reports are not done anymore. 2 | -------------------------------------------------------------------------------- /00-project-documentation/community/AutSPACEs Platform Participant Information Sheet.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/00-project-documentation/community/AutSPACEs Platform Participant Information Sheet.docx -------------------------------------------------------------------------------- /00-project-documentation/community/AutSPACEs Platform Participant Information Sheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/00-project-documentation/community/AutSPACEs Platform Participant Information Sheet.pdf -------------------------------------------------------------------------------- /00-project-documentation/community/README.md: -------------------------------------------------------------------------------- 1 | # Community 2 | 3 | This folder contains recommendations and feedback from the AutSPACEs commmunity, as well as information about community meet-up sessions. 4 | 5 | ## Contents 6 | 7 | * [Focus groups](focus-groups) 8 | * [Meet-up Sessions](meet-ups) 9 | * [Moderation workshop](moderation-workshop) 10 | * [User tests](user-tests) 11 | -------------------------------------------------------------------------------- /00-project-documentation/community/focus-groups/README.md: -------------------------------------------------------------------------------- 1 | # Focus groups 2 | 3 | This folder contains summaries and quotations from three focus group sessions held with autistic people, the relatives and carers of autistic people, researchers and developers, about the Autistica/Turing citizen science project in Autumn 2019. 4 | 5 | ## Contents of focus-groups folder 6 | 7 | * [Creation of focus group summary documents](creation-of-summaries.md) 8 | * Focus Group Summaries: 9 | * [18 September 2019](18-september-2019.md) 10 | * [24 September 2019](24-september-2019.md) 11 | * [4 October 2019](04-october-2019.md) 12 | 13 | ## Key 14 | 15 | The key below shows how the comments in the summaries have been labelled. 16 | They were co-designed with an autistic collaborator and are based on earlier informal scoping work with Autistica's Insight Group. 17 | More detail can be found in [creation-summary-documents.md](creation-summary-documents.md) file which describes in detail how the summary documents were developed in collaboration with focus group participants and autistic collaborators. 18 | 19 | #### Where From 20 | 21 | * *A* = Autistica 22 | * *T* = Turing 23 | * *F* = Fujitsu 24 | 25 | #### Specialist Role on Project 26 | 27 | * R = Researcher 28 | 29 | #### Connection to Autism 30 | 31 | * **A** = Autistic 32 | * **P** = Parent of someone autistic 33 | 34 | #### Connection to Experience 35 | 36 | * d = direct: experience, suggestion, or opinion of speaker 37 | * i = indirect: witnessed or reported on behalf of someone else by speaker 38 | * g = general comment 39 | -------------------------------------------------------------------------------- /00-project-documentation/community/images/noun-project-icons/noun_Conversation_2041500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/00-project-documentation/community/images/noun-project-icons/noun_Conversation_2041500.png -------------------------------------------------------------------------------- /00-project-documentation/community/images/noun-project-icons/noun_Document_188540.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/00-project-documentation/community/images/noun-project-icons/noun_Document_188540.png -------------------------------------------------------------------------------- /00-project-documentation/community/images/noun-project-icons/noun_Eye_2040041.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/00-project-documentation/community/images/noun-project-icons/noun_Eye_2040041.png -------------------------------------------------------------------------------- /00-project-documentation/community/images/noun-project-icons/noun_online_1632606.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/00-project-documentation/community/images/noun-project-icons/noun_online_1632606.png -------------------------------------------------------------------------------- /00-project-documentation/community/images/noun-project-icons/noun_todolist_1128326.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/00-project-documentation/community/images/noun-project-icons/noun_todolist_1128326.png -------------------------------------------------------------------------------- /00-project-documentation/community/images/noun-project-icons/noun_transcript_532343.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/00-project-documentation/community/images/noun-project-icons/noun_transcript_532343.png -------------------------------------------------------------------------------- /00-project-documentation/community/meet-ups/README.md: -------------------------------------------------------------------------------- 1 | # Community meet-up sessions 2 | 3 | This folder contains information and resources relating to AutSPACEs commmunity meet-up sessions, as well as previous notes. 4 | AutSPACEs meet-up sessions are open to everyone, and are a place to discuss anything relating to AutSPACEs and to work together on the project. 5 | They take place online via. Zoom and are hosted by AutSPACEs researchers. 6 | 7 | ## Meet-up Checklist 8 | 9 | * [ ] Inform community members via. newsletter 10 | * [ ] Create a Google Doc and agenda using the Google Doc Template(#google-doc-template) 11 | * [ ] Send out a calendar invite 12 | * [ ] Link to the Google Doc under [Notes from Previous Sessions](#notes-from-previous-sessions) 13 | 14 | ## Google Doc Template 15 | 16 | Please copy this [template Google Doc](https://docs.google.com/document/d/1utjgMS1HwADMtK5gz5EYOKdPW6vdeshxt9-XaZ4DONY/edit?usp=sharing) and use it to make a Google Doc for each meet-up session. 17 | 18 | ## Notes from Previous Sessions 19 | 20 | ### 2023 21 | 22 | * [12-01-2023](https://docs.google.com/document/d/1wu0LULOY6k-jbbYwZwuZmwDyI7cBa0zPc2shramRWkM/edit?usp=sharing) 23 | 24 | ### 2022 25 | 26 | * [24-03-2022](https://docs.google.com/document/d/1zlznkUp273-j3hot2YDvQVHj9h-fY-gMKyggNYSbdMY/edit?usp=sharing) 27 | * [10-03-2022](https://docs.google.com/document/d/1ohi4gwmj8BmxlHstahkX20WDCsxB-wJP60HRGSN4TJ8/edit?usp=sharing) 28 | * [24-02-2022](https://docs.google.com/document/d/1q0KBqx_X9Eh6i3x9kSzVVS8bIbBg6ucVkFLnkxLkDEQ/edit?usp=sharing) 29 | 30 | ### 2021 31 | 32 | * [25-11-2021](https://docs.google.com/document/d/1V8jYBZGhSLEcfTXfYGb-L-TtnXL7TqTa0KCK8eLMwSA/edit?usp=sharing) 33 | * [28-10-2021](https://docs.google.com/document/d/19gUHi1yKhVpcpDZwoS9AgWwGhbbM0vc-aemUzbSYhEs/edit?usp=sharing) 34 | * [08-07-2021](https://docs.google.com/document/d/13FaiZLn8bqsFhTeEAPooFGFxwndpSeuw2zQhsCLjS2E/edit?usp=sharing) 35 | * [27-05-2021](https://docs.google.com/document/d/18j6HjxW12UrIXlmmQJZGTPRvaDfpjBsdtvZFlLp6br0/edit?usp=sharing) 36 | * [13-05-2021](https://docs.google.com/document/d/1e6MablDYduDTTfY5E4C13XNWDPeUxrurV3U8sFivlIU/edit?usp=sharing) 37 | * [25-03-2021](https://docs.google.com/document/d/18dJqTmeENZNknrCYnydcNwc77hTeCfKlr1GH1lJWP7Q/edit?usp=sharing) 38 | * [22-02-2021](https://docs.google.com/document/d/1sI9S12DWwphEakTeYymrv6C868mYP12-LaOurRPOzZI/edit?usp=sharing) 39 | -------------------------------------------------------------------------------- /00-project-documentation/community/user-tests/2023-09-user-testing-prompts.md: -------------------------------------------------------------------------------- 1 | # User testing prompts 2 | 3 | Used for the virtual "over the shoulder" testing 4 | 5 | # Introduction 6 | 7 | ## Purpose of the study 8 | - What to expect from the session (ability to take breaks, leave at any time, etc) 9 | - Need for support during session (e.g. captions in zoom) 10 | - Consent for participation / recording 11 | 12 | ## Pre-usability interview questions 13 | - Prior experience with AutSPACEs in particular & citizen science broadly 14 | 15 | ##Usability testing with think-aloud 16 | 1. Browse to AutSPACEs and explore as you like: What do you think the goal and purpose of AutSPACEs is? 17 | 2. Please can you change the kinds of experiences you see to also include mental health issues (experience should be hidden by default for trigger warning) 18 | Explore if people understand _why_ they don’t see it (this is not a search); 19 | 3. Please can you add one yourself? create an account and login (or use the username and password we give you to login). 20 | 4. Can you fill in your profile (you can make one up if you prefer) 21 | 5. Please enter any experience (you can make one up if you prefer) 22 | 6. Optional: Can you make your experience be a public experience, a private experience, a research-only experience 23 | 24 | # Post-task questions 25 | 26 | - What do you expect will happen next after you submit this experience? 27 | - Do you think AutSPACEs could be useful to you/Would you use AutSPACEs to share your experiences? 28 | - Which parts could you see yourself using most? (sharing experience vs reading experiences) 29 | - Which aspects did you like about using AutSPACEs? Which things surprised you/ or were frustrating? What could have been better? 30 | - What concerns (if any) do you have about using AutSPACEs? 31 | - Which information would you have needed to better understand AutSPACEs? 32 | - What would bring you back to AutSPACEs after an initial visit? 33 | 34 | ## Demographics: 35 | - What is your relationship to Autism? 36 | - Do you mind sharing your age/gender identity/education/professional backgrounds with us? 37 | - How do you typically interact with digital tools (e.g. social media, websites, etc.) 38 | - Do you think you have special requirements around digital accessibility (e.g. visual, dyslexia) 39 | 40 | # Final debrief 41 | - Feedback on user testing itself? 42 | - No planned follow up, but we do meetups, newsletter etc 43 | - Ask if people would be interested to kept informed about progress of study (eg. publishing of paper, release of AutSPACEs) 44 | - (participant payment formalities, Will be in a few days as we are waiting on the admin for this) 45 | 46 | #End of study / stop recording 47 | -------------------------------------------------------------------------------- /00-project-documentation/community/user-tests/AutSPACEs User Testing_ Participant Information Sheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/00-project-documentation/community/user-tests/AutSPACEs User Testing_ Participant Information Sheet.pdf -------------------------------------------------------------------------------- /00-project-documentation/community/user-tests/AutSPACEs-consent-form.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/00-project-documentation/community/user-tests/AutSPACEs-consent-form.pdf -------------------------------------------------------------------------------- /00-project-documentation/community/user-tests/README.md: -------------------------------------------------------------------------------- 1 | # User Tests 2 | 3 | This folder contains feedback and observations from user testing the AutSPACEs platform with community members. 4 | -------------------------------------------------------------------------------- /00-project-documentation/ethics/AutSPACEs_Platform_ParticipantInformationSheet_20240221.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/00-project-documentation/ethics/AutSPACEs_Platform_ParticipantInformationSheet_20240221.pdf -------------------------------------------------------------------------------- /00-project-documentation/ethics/TREx2-form-approved.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/00-project-documentation/ethics/TREx2-form-approved.pdf -------------------------------------------------------------------------------- /00-project-documentation/moderation/README.md: -------------------------------------------------------------------------------- 1 | # Moderation 2 | 3 | This folder contains informations, resources and decisions relating to the moderation process for the AutSPACEs platform. You can find more details on this in the [archived AutisticaCitizenScience repository](https://github.com/alan-turing-institute/AutisticaCitizenScience/tree/master/Moderation). 4 | -------------------------------------------------------------------------------- /00-project-documentation/moderation/moderation-decisions.md: -------------------------------------------------------------------------------- 1 | > This file documents all the decisions that have been discussed during the community meet-ups from November 2021 to December 2021. 2 | 3 | > We will focus on **the moderation policy, training sessions and reflection sessions for moderation** to minimize the infrastructure work required from the AutSPACEs platform. 4 | 5 | 6 | * Each experience will be moderated by **1 moderator**. 7 | * If moderators are unsure about their decisions, they can **flag the experiences as ambiguous**. The ambiguous experiences will be moderated by reviewers. 8 | * Moderators remain **anonymous** to each other, but moderation decisions are **visible**. Only administrators can see moderators' names and decisions in the database. 9 | * Moderators will select experiences on their own for moderation. Once experiences are selected, moderators should moderate them within 24 hours. Otherwise, the experiences will be put back into the pool. 10 | * **Appeal requests** will be collected through Google Form and be sent to reviewers. 11 | * **Harmful reports** will be collected through Google Form and be sent to moderators. Moderators will re-label the mentioned experiences based on the reports. 12 | * Email should be avoided to use as the means of the communication in the platform as it is not user-friendly and can be quite hard to document. 13 | 14 | 15 | -------------------------------------------------------------------------------- /00-project-documentation/platform-design/README.md: -------------------------------------------------------------------------------- 1 | # AutSPACEs Project Documentation 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /00-project-documentation/platform-design/platform-design/design-process/15-11-21-AutSPACEs-Design-Process.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/00-project-documentation/platform-design/platform-design/design-process/15-11-21-AutSPACEs-Design-Process.pdf -------------------------------------------------------------------------------- /00-project-documentation/platform-design/platform-design/design-requirements/README.md: -------------------------------------------------------------------------------- 1 | # Design Requirements 2 | 3 | This folder contains key information on the requirements for the content and features of the AutSPACEs platform. 4 | 5 | It captures many of the important features for accessibility and usability of the platform. 6 | 7 | ### Contributing 8 | 9 | It is core to our Community Values that we work openly and with transparency. As a result, this folder will be a "work in progress" and content will be added as we move throughout the project. 10 | 11 | If you see something missing, want to contribute, or want to learn more: please read our [Contributing Guidelines](/contributing-guidelines.md) and familiarize yourself with the project and this repository, and then open an Issue, Pull Request, or comment on existing Issues. 12 | 13 | ## Contents 14 | * [accessibility-checklist](./accessibility-checklist.md) which summarizes the gov.uk reccomendations for making web pages accessible. 15 | * [requirements-list.md](./requirements-list.md) which summarizes the most important features that needed to go on each page of the platform. 16 | -------------------------------------------------------------------------------- /00-project-documentation/platform-design/platform-design/design-research/AutSPACES Feedback (19.10).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/00-project-documentation/platform-design/platform-design/design-research/AutSPACES Feedback (19.10).pdf -------------------------------------------------------------------------------- /00-project-documentation/platform-design/platform-design/design-research/Personas/Ali.md: -------------------------------------------------------------------------------- 1 | # Ali 2 | 3 | ### Short Biography 4 | Ali was diagnosed with autism and depression last year during COVID. They were struggling with their work and life recently and is keen on finding a community to support them. They have came across AutSPACEs through a random online search. 5 | 6 | Ali has no knowledge in participatory projects. They are interested in AutSPACEs community. They wants to contribute but is afraid of technology, like how to use GitHub. They do not use text based input systems and needs guidance in writing experiences out. 7 | 8 | ### Goals and Motivations 9 | 10 | | **Goals** | **Motivations** | 11 | | -------- | -------- | 12 | |Finds solutions for unpleasant sensory experiences|Get to know autism better and adaptive techniques shared by other members 13 | |Knows how to explain people around about their autism and how they experience the world|Shares adaptive techniques with their neurotypical friends so their friends can be better informed| 14 | |Joins an autism community to feel more understood and supported|Contributes to an autism community 15 | 16 | -------------------------------------------------------------------------------- /00-project-documentation/platform-design/platform-design/design-research/Personas/August.md: -------------------------------------------------------------------------------- 1 | # August 2 | 3 | ### Short Biography 4 | August works as a researcher in a data science lab and is part of the research team for AutSPACEs. Their background is in data science and human resources. 5 | 6 | August also works as a developer for the platform, as well as a public speaker in promoting participatory projects on autism research. 7 | 8 | ### Goals and Motivations 9 | | **Goals** | **Motivations** | 10 | | -------- | -------- | 11 | |Conduct keyword researches based on their interests in shared experiences databases |Make contributions to the current autism researches 12 | |Contact the core team for research discussions |Educates neurotypical people to better support their autistic friends, family and colleagues| 13 | View data consented to be used for research purposes | To understand what data can and can't be included in a research project | 14 | To read first hand experiences of autistic individuals and request research data | Make contributions to autism research that prioritizes the needs of autistic individuals 15 | | Understand how the AutSPACEs project was developed | Use/draw upon AutSPACEs resources such as code and project managemeent resource to create own open source project 16 | -------------------------------------------------------------------------------- /00-project-documentation/platform-design/platform-design/design-research/Personas/Cameron.md: -------------------------------------------------------------------------------- 1 | # Cameron 2 | 3 | ### Short Biography 4 | Cameron was diagnosed with autism in their teens. They have been working closely with and contributing to AutSPACEs for more than a year. They are interested in political science and acts as an active member for multiple neurodiversity communities. 5 | 6 | They work as a moderator for AutSPACEs platform. 7 | 8 | ### Goals and Motivations 9 | | **Goals** | **Motivations** | 10 | | -------- | -------- | 11 | |Uses AutSPACEs platform to document sensory experiences and adaptive techniques weekly to benefit viewers with similar experiences|Gains a better understanding of their own experience and gets new strategy ideas from others who have similar experiences 12 | |Be able to keep a self log of their own sensory experiences| Track patterns in their experiences and understand themselves better | 13 | |Introduces AutSPACEs platform to other neurodiversity communities | To grow the AutSPACEs community and have more experiences be shared | 14 | Use AutSPACEs moderator page to select experiences for publication based on whether they follow code of conduct or not | Builds a safe and supportive autistic community| -------------------------------------------------------------------------------- /00-project-documentation/platform-design/platform-design/design-research/Personas/Jesse.md: -------------------------------------------------------------------------------- 1 | # Jesse 2 | 3 | ### Short Biography 4 | Jesse is not autistic but is a carer to Erin, who is an autistic individual. Erin and Jesse have worked together and decided to share some of Erin's experiences on AutSPACEs. Jesse is also hoping to find ideas for how to better support Erin. 5 | 6 | ### Goals and Motivations 7 | | **Goals** | **Motivations** | 8 | | -------- | -------- | 9 | | View experiences and search for experiences that shared by people whose situations are similar to Erin | Get ideas for adaptive techniques to better support Erin 10 | | Help Erin's experience to be represented |Contributes to the knowledge base on autism and sensory processing| 11 | Support Erin in connecting with a supportive community of peers | Help Erin feel like they are part of a community | 12 | -------------------------------------------------------------------------------- /00-project-documentation/platform-design/platform-design/design-research/Personas/Kendall.md: -------------------------------------------------------------------------------- 1 | # Kendall 2 | 3 | ### Short Biography 4 | Kendall works as a community manager for an international NGO in the Netherlands. Kendall has no knowledge about open source, citizen science, or open science. They have heard about participatory projects before, but have never particiapted. They heard about AutSPACEs from Autistica through a forum. 5 | 6 | Kendall wants to learn from the experiences of autistic individuals so they pitch for policy changes in their organization that will enable building and interior design, working policies, and equipment support for their employees. 7 | 8 | ### Goals and Motivations 9 | | **Goals** | **Motivations** | 10 | | -------- | -------- | 11 | | To read first hand experiences from autistic individuals |Better understand what kind of problems people with autism may face in their daily life (:thought_balloon: internal motivation)| 12 | |Understand how AutSPACEs platform works and its impact |Advises organizations in building a safe and supportive work environment for colleagues with autism (:briefcase: external motivation) | 13 | -------------------------------------------------------------------------------- /00-project-documentation/platform-design/platform-design/design-research/Personas/Persona-Template.md: -------------------------------------------------------------------------------- 1 | # Persona Name: 2 | 3 | ### Short Biography 4 | > - this is a short biography about the Persona 5 | > - it should be specific to the autspace project, what their knowledge base is, what requirements they have, what their expectations are 6 | > - When creating the persona, think about 7 | > - (1) what the overall goals of AutSPACEs are (you can review this slide [here](https://github.com/alan-turing-institute/AutisticaCitizenScience/blob/master/images/Whitaker_OpenInnovationAutistica_November2019.jpg) from one of Kirstie Whitaker's talks which discuss the goals of the project) 8 | > - (2) what archetypes of people may be interested in using the platform 9 | 10 | ### Goals and Motivations 11 | | **Goals** | **Motivations** | 12 | | -------- | -------- | 13 | | a goal is something that someone can achieve | a motivation is why someone wants to achieve their goal | 14 | -------------------------------------------------------------------------------- /00-project-documentation/platform-design/platform-design/design-research/Personas/README.md: -------------------------------------------------------------------------------- 1 | # AutSPACEs Persona README 2 | 3 | ## What is a Persona 4 | - User personas are fictional users that represent the needs of user groups. 5 | - Identifying user personas can help us better understand the needs and pain points of users. 6 | - You can read more information on Personas at the Adobe website [here](https://xd.adobe.com/ideas/process/user-research/putting-personas-to-work-in-ux-design/) 7 | 8 | ## AutSPACEs Personas 9 | - For AutSPACEs, we have identified 5 user groups: **austistic users, coders, researchers, non-autistic users**,and **decision makers**. 10 | - These user groups have allowed us to develop 5 Personas: 11 | - [Ali](Ali.md) 12 | - [Cameron](Cameron.md) 13 | - [Kendall](Kendall.md) 14 | - [August](August.md) 15 | - [Jesse](Jesse.md) 16 | 17 | ## How to contribute 18 | - You can suggest a new Persona by creating an [Issue](https://github.com/alan-turing-institute/AutisticaCitizenScience/blob/master/.github/CONTRIBUTING.md#where-to-start-issues), or submitting a [Pull Request](https://github.com/alan-turing-institute/AutisticaCitizenScience/blob/master/.github/CONTRIBUTING.md#where-to-start-issues). For information on how to do this please refer to our [Contributors Guidelines](https://github.com/alan-turing-institute/AutisticaCitizenScience/blob/master/.github/CONTRIBUTING.md). If you do this please follow the template [here](https://github.com/alan-turing-institute/AutisticaCitizenScience/blob/sophia-relativelink-test/platform-designs/design-research/Personas/Persona-Template.md) and try to use gender neutral names and pronouns when creating a persona. 19 | - You can add suggestions to existing Personas by opening an Issue and linking to the Persona file you would like to make suggestions for. Refer to the [Contributors Guideline](https://github.com/alan-turing-institute/AutisticaCitizenScience/blob/master/.github/CONTRIBUTING.md#where-to-start-issues) for information on how to open an Issue. 20 | -------------------------------------------------------------------------------- /00-project-documentation/platform-design/platform-design/design-research/README.md: -------------------------------------------------------------------------------- 1 | # Design Research 2 | 3 | This folder acts to collate and point to information and feedback about the Design of the platform. 4 | 5 | ## Contents 6 | * [Personas](./Personas/) 7 | * [feedback-linkspad.md](./feedback-linkspad.md) 8 | * [feedback-summary(2021-10-09)](./AutSPACES%20Feedback%20(19.10).pdf) 9 | * The summary identified the "key" user needs for the platform's design, functions, and contents based on feeback for the previous prototypes. Detailed information can be found the feedback summary itself. 10 | 11 | ## How to Contribute 12 | There are many ways to get involved with this project and we would love to hear your thoughts! 13 | 14 | If you would like to contribute to this repository, please read the [Contributing Guidelines](/contributing-guidelines.md) and familiarize yourself with the project and this repository. You can also join our meetups which happen on the first and last thursday of every month (find out when the next one is happening by signing up to the mailing list [here](https://tinyletter.com/AutisticaTuringCitizenScience), or reach out to the team. 15 | -------------------------------------------------------------------------------- /00-project-documentation/platform-design/platform-design/design-research/feedback-linkspad.md: -------------------------------------------------------------------------------- 1 | # Feedback Links Pad 2 | 3 | This file contains links to files throughout the repository that capture or relate to research on usability and design for the platform. 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /00-project-documentation/platform-design/platform-design/design-system/README.md: -------------------------------------------------------------------------------- 1 | # Design System -------------------------------------------------------------------------------- /00-project-documentation/platform-design/platform-design/design-system/design-code-20220222.md: -------------------------------------------------------------------------------- 1 | # Design Code 20220222 2 | ## Colors: 3 | ![](https://i.imgur.com/wtlEL9O.png) 4 | * [How the colour palettes were generated](https://hackmd.io/VO3x77q2Td215fkKGLdegw) 5 | 6 | ## Font 7 | * Stlye 8 | * [Poppin](https://fonts.google.com/specimen/Poppins): Regular 400, Italic 400, Bold 700 9 | * Size 10 | * big heading: 5rem 11 | * section heading: 3rem 12 | * paragraph heading: 2rem 13 | * important contents: 1.5rem 14 | * Line height 15 | * 1.5 16 | 17 | ## Padding 18 | * Page: 2% 5% 19 | * Sections: 4% 5% 20 | -------------------------------------------------------------------------------- /00-project-documentation/platform-design/platform-design/platform-architecture/README.md: -------------------------------------------------------------------------------- 1 | # Design Architecture 2 | 3 | This folder contains key information about how the pages of the AutSPACEs platform fit together and how someone can navigate the platform. 4 | 5 | ## [Information Architecture](autspaces-ia-diagram-15-11-2021.md) 6 | 7 | Information Architecture(IA) is a diagram which shows the journey of how a user would interact with the platform. 8 | It's useful for oulining the relationship between pages on the AutSPACEs platform and to review if the features on each page correctly address user needs. 9 | IA focuses on two elements: **where a user is** and **where to find information a user needs**. 10 | 11 | ### How to read an IA Diagram 12 | The diagram reads as a hierarchy from top to bottom with each layer starting with a "parent" element that has corresponding "child" elements. 13 | 14 | #### Diagram Key 15 | * Orange color is for AutSPACEs platform 16 | * Blue color is for external pages/links. 17 | * We have 7 external pages/links in total. 18 | * Registration on Open Humans 19 | * Authentication on Open Humans 20 | * Link to TinyLetter, Slack, Twitter, and GitHub repos 21 | * Link to Autistica and the National Autistic Society 22 | * Link to harmful reports through google form 23 | * Link to conatct us through google form 24 | * Link to contact moderators 25 | * Green color is for AutSPACEs platform pages. 26 | * We have 8 separate pages in total. 27 | * Homepage 28 | * Registration page 29 | * What Autism Is Page 30 | * View Stories page 31 | * Share Stories page 32 | * Moderate Stories page 33 | * My Stories page 34 | * About Us page 35 | * Purple color is for features that need to be implemented. 36 | * Pages with features: 37 | * Registration page 38 | * View Stories page 39 | * Share Stories page 40 | * Moderate Stories page 41 | * My Stories page 42 | 43 | ### IA Diagram 44 | * Updated 21-02-2022: [Information Architecture Diagram](https://viewer.diagrams.net/?tags=%7B%7D&highlight=0000ff&edit=_blank&layers=1&nav=1&page-id=XndytNqcHWh8WrCRgyDL&title=IA_AutSPACEs.drawio#Uhttps%3A%2F%2Fdrive.google.com%2Fuc%3Fid%3D1THiziivGBr89J5x9oJahXuHtL7iib8J1%26export%3Ddownload) 45 | * Changelog: 46 | * Combined the two separate user journeys into one linear user journey 47 | * Fixed the broken pages on the frontend side 48 | * Updated the information per page 49 | * Added What Autism Is and About Us pages 50 | * Previous diagrams can be found on the same folder. 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /00-project-documentation/platform-design/platform-design/platform-architecture/autspaces-ia-diagram-15-11-2021.md: -------------------------------------------------------------------------------- 1 | # Information Architecture for AutSPACEs 2 | This is the IA for the AutSPACEs platform as it exists on 15/11/2021. 3 | 4 | ## Diagram Key 5 | Please refer to [link - how to read an IA diagram] for a guide on how to read IA diagrams. 6 | * Purple color is for AutSPACEs platform 7 | * Blue color is for external pages 8 | * Open Humans Authentication 9 | * Tiny Newsletter subscription 10 | * Green color is for AutSPACEs platform pages 11 | * We have 7 separate pages in total 12 | * Homepage for non-logged in user 13 | * Homepage for logged in user 14 | * Success in logging in page 15 | * View Experiences page 16 | * Share Experiences page 17 | * My Stories page 18 | * Moderator Page 19 | * Red color is for pages/features we have designed for, but not implemented. 20 | 21 | ### Relevant Documents 22 | * [Figma Link](https://www.figma.com/file/HxqTSdeyAUNMualnBV0PET/Autspace-(WIP)?node-id=172%3A641) 23 | 24 | ### Diagram 25 | ![IA Diagram](autspaces-ia-diagram-22-11-2021.png) 26 | [Diagram in Detail](https://viewer.diagrams.net/?tags=%7B%7D&highlight=0000ff&edit=_blank&layers=1&nav=1&title=IA_AutSPACEs.drawio#Uhttps%3A%2F%2Fdrive.google.com%2Fuc%3Fid%3D1THiziivGBr89J5x9oJahXuHtL7iib8J1%26export%3Ddownload) 27 | -------------------------------------------------------------------------------- /00-project-documentation/platform-design/platform-design/platform-architecture/autspaces-ia-diagram-15-11-2021.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/00-project-documentation/platform-design/platform-design/platform-architecture/autspaces-ia-diagram-15-11-2021.png -------------------------------------------------------------------------------- /00-project-documentation/platform-design/platform-design/platform-architecture/autspaces-ia-diagram-21-02-2022.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/00-project-documentation/platform-design/platform-design/platform-architecture/autspaces-ia-diagram-21-02-2022.png -------------------------------------------------------------------------------- /00-project-documentation/platform-design/platform-design/platform-architecture/autspaces-ia-diagram-22-11-2021.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/00-project-documentation/platform-design/platform-design/platform-architecture/autspaces-ia-diagram-22-11-2021.png -------------------------------------------------------------------------------- /00-project-documentation/platform-design/platform-design/platform-content/README.md: -------------------------------------------------------------------------------- 1 | # Design Content 2 | 3 | This folder will contains copy, assets, and other content related material for the AutSPACEs platform design. It's goal is to curate content that will be used for the platform. 4 | 5 | ## How to Contribute 6 | There are many ways to get involved with this project and we would love to hear your thoughts! 7 | 8 | If you would like to contribute, please read the [Contributing Guidelines](/contributing-guidelines.md) and familiarize yourself with the project and this repository. 9 | 10 | All the designs for the AutSPACEs platform and associated projects have been developed by the community, and we are always open to suggestions, feedback, and collaborations. 11 | 12 | If you would like to design something for AutSPACEs, please get in touch by submitting a `Pull Request` or an `Issue` (instructions on how to do that can be found [here][Contributing Guidelines](/contributing-guidelines.md). 13 | 14 | You can also join our meetups which happen on the first and last thursday of every month (find out when the next one is happening by signing up to the mailing list [here](https://tinyletter.com/AutisticaTuringCitizenScience), or reach out directly to the team. 15 | -------------------------------------------------------------------------------- /00-project-documentation/platform-design/platform-design/wireframes/README.md: -------------------------------------------------------------------------------- 1 | # Wireframes 2 | 3 | In this folder you will find the wireframes for the platform. 4 | We have used a platform called [figma]() to produce our wireframes and images of each page can be found here. 5 | 6 | To understand how each page fits in the the platform, you can use the "platform architecture" files to get an overview. 7 | 8 | ## How to Use the Wireframes 9 | 10 | These wireframes are for the AutSPACEs platform, you can find the code and development work for the platform throughout this repository. 11 | 12 | ## How to Contribute 13 | There are many ways to get involved with the AutSPACEs project and we would love to hear your feedback on the platform's design. 14 | 15 | #### There are 2 great ways to get involved in the platform's design: 16 | 1) join the discussion during our community calls which happen on the first and last thursday of every month (find out when the next one is happening by signing up to the mailing list [here](https://tinyletter.com/AutisticaTuringCitizenScience), or 17 | 2) opening an Issue or a Pull Request that explains: 18 | - the changes that you are suggesting 19 | - how these changes improve the usability and accessibility of the platform for the autistic community. 20 | 21 | You can find instructions on how to use Pull Requests and Issues in our [Contributing Guidelines](/contributing-guidelines.md) as well as other information about how to contribute to this project. -------------------------------------------------------------------------------- /Citscicartoon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/Citscicartoon.png -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ARG PYTHON_VERSION=3.12.2-slim-bullseye 2 | 3 | FROM python:${PYTHON_VERSION} 4 | 5 | ENV PYTHONDONTWRITEBYTECODE 1 6 | ENV PYTHONUNBUFFERED 1 7 | ENV TINI_VERSION=v0.19.0 8 | ENV DJANGO_ENV=production 9 | 10 | # install psycopg2 dependencies. 11 | RUN apt-get update && apt-get install -y \ 12 | libpq-dev \ 13 | gcc \ 14 | wget \ 15 | gettext \ 16 | && rm -rf /var/lib/apt/lists/* 17 | 18 | # install & setup sshd 19 | RUN apt-get update \ 20 | && apt-get install -y --no-install-recommends dialog \ 21 | && apt-get install -y --no-install-recommends openssh-server \ 22 | && echo "root:Docker!" | chpasswd 23 | COPY ./config/sshd_config /etc/ssh/ 24 | 25 | # Installing `tini` utility: 26 | # https://github.com/krallin/tini 27 | 28 | RUN wget -O /usr/local/bin/tini "https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini" \ 29 | && chmod +x /usr/local/bin/tini && tini --version 30 | 31 | RUN mkdir -p /code 32 | 33 | WORKDIR /code 34 | 35 | RUN pip install poetry 36 | COPY pyproject.toml poetry.lock /code/ 37 | RUN poetry config virtualenvs.create false 38 | RUN poetry install --no-root --no-interaction 39 | COPY . /code 40 | 41 | EXPOSE 8000 2222 42 | 43 | # load entrypoint script for launching guincorn 44 | COPY ./docker/django/gunicorn.sh /docker-entrypoint.sh 45 | 46 | # Setting up proper permissions: 47 | RUN chmod +x '/docker-entrypoint.sh' \ 48 | && groupadd -r web && useradd -d /code -r -g web web \ 49 | && chown web:web -R /code \ 50 | && mkdir -p /var/www/django/static /var/www/django/media \ 51 | && chown web:web /var/www/django/static /var/www/django/media 52 | 53 | #USER web 54 | 55 | # CMD ["gunicorn", "--bind", ":8000", "--workers", "1", "server.wsgi"] 56 | ENTRYPOINT ["tini", "--", "/docker-entrypoint.sh"] 57 | 58 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Georgia 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /config/.env.actions: -------------------------------------------------------------------------------- 1 | # Security Warning! Do not commit this file to any VCS! 2 | # This is a local file to speed up development process, 3 | # so you don't have to change your environment variables. 4 | # 5 | # This is not applied to `.env.template`! 6 | # Template files must be committed to the VCS, but must not contain 7 | # any secret values. 8 | 9 | 10 | # === General === 11 | 12 | DOMAIN_NAME=test.com 13 | TLS_EMAIL=webmaster@test.com 14 | 15 | 16 | # === Django === 17 | # Generate yours with: 18 | # python3 -c 'from django.utils.crypto import get_random_string; print(get_random_string(50))' 19 | 20 | DJANGO_SECRET_KEY=__CHANGEME__ 21 | 22 | 23 | # === Database === 24 | 25 | # These variables are special, since they are consumed 26 | # by both django and postgres docker image. 27 | # Cannot be renamed if you use postgres in docker. 28 | # See: https://hub.docker.com/_/postgres 29 | 30 | POSTGRES_DB=postgres 31 | POSTGRES_USER=postgres 32 | POSTGRES_PASSWORD=postgres 33 | 34 | # Used only by django: 35 | DJANGO_DATABASE_HOST=localhost 36 | DJANGO_DATABASE_PORT=5432 37 | 38 | # Used by OpenHumans 39 | # Refer to https://django-open-humans.readthedocs.io/en/latest/modules/getting-started.html for more information 40 | OPENHUMANS_CLIENT_ID=A_CLIENT_ID 41 | OPENHUMANS_CLIENT_SECRET=A_CLIENT_SECRET 42 | OPENHUMANS_APP_BASE_URL=http://localhost:8000 43 | OH_PROJ_PAGE="https://example.com" 44 | -------------------------------------------------------------------------------- /config/.env.template: -------------------------------------------------------------------------------- 1 | # Security Warning! Do not commit this file to any VCS! 2 | # This is a local file to speed up development process, 3 | # so you don't have to change your environment variables. 4 | # 5 | # This is not applied to `.env.template`! 6 | # Template files must be committed to the VCS, but must not contain 7 | # any secret values. 8 | 9 | 10 | # === General === 11 | 12 | DOMAIN_NAME=test.com 13 | TLS_EMAIL=webmaster@test.com 14 | 15 | 16 | # === Django === 17 | # Generate yours with: 18 | # python3 -c 'from django.utils.crypto import get_random_string; print(get_random_string(50))' 19 | 20 | # Or in case you don't have django installed, you can achieve the same with the following: 21 | # python3 -c 'import secrets, string; print("".join(secrets.choice(string.ascii_letters+string.digits) for i in range(50)))' 22 | 23 | DJANGO_SECRET_KEY=__CHANGEME__ 24 | 25 | 26 | # === Database === 27 | 28 | # These variables are special, since they are consumed 29 | # by both django and postgres docker image. 30 | # Cannot be renamed if you use postgres in docker. 31 | # See: https://hub.docker.com/_/postgres 32 | # The latest postgres version require setting a password, so POSTGRES_PASSWORD can not be empty either 33 | 34 | POSTGRES_DB=autspaces 35 | POSTGRES_USER=autspaces 36 | POSTGRES_PASSWORD=autspaces 37 | 38 | # Used only by django: 39 | DJANGO_DATABASE_HOST=localhost 40 | DJANGO_DATABASE_PORT=5432 41 | 42 | # Used by OpenHumans 43 | # Refer to https://django-open-humans.readthedocs.io/en/latest/modules/getting-started.html for more information 44 | OPENHUMANS_CLIENT_ID=A_CLIENT_ID 45 | OPENHUMANS_CLIENT_SECRET=A_CLIENT_SECRET 46 | OPENHUMANS_APP_BASE_URL=http://localhost:8000 47 | OH_PROJ_PAGE="https://example.com" 48 | -------------------------------------------------------------------------------- /config/sshd_config: -------------------------------------------------------------------------------- 1 | Port 2222 2 | ListenAddress 0.0.0.0 3 | LoginGraceTime 180 4 | X11Forwarding yes 5 | Ciphers aes128-cbc,3des-cbc,aes256-cbc,aes128-ctr,aes192-ctr,aes256-ctr 6 | MACs hmac-sha1,hmac-sha1-96 7 | StrictModes yes 8 | SyslogFacility DAEMON 9 | PasswordAuthentication yes 10 | PermitEmptyPasswords no 11 | PermitRootLogin yes 12 | Subsystem sftp internal-sftp 13 | -------------------------------------------------------------------------------- /docker-compose.override.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # This docker-compose file is required to bind ports in development, 4 | # since binding ports in regular compose file will ruin scaling 5 | # in production. Due to how `ports` directive is merged with two files. 6 | # 7 | # This file is ignored in production, but 8 | # it is automatically picked up in development with: 9 | # 10 | 11 | version: "3.6" 12 | services: 13 | web: 14 | ports: 15 | # We only bind ports directly in development: 16 | - "8000:8000" 17 | volumes: 18 | # We only mount source code in development: 19 | - .:/code 20 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # Default compose file for development and production. 4 | # Should be used directly in development. 5 | # Automatically loads `docker-compose.override.yml` if it exists. 6 | # No extra steps required. 7 | # Should be used together with `docker/docker-compose.prod.yml` 8 | # in production. 9 | 10 | version: "3.6.2" 11 | services: 12 | db: 13 | image: "postgres:15.2-alpine" 14 | restart: unless-stopped 15 | volumes: 16 | - pgdata:/var/lib/postgresql/data 17 | networks: 18 | - webnet 19 | env_file: ./config/.env 20 | 21 | web: 22 | <<: &web 23 | # Image name is changed in production: 24 | image: "autspaces:dev" 25 | build: 26 | target: development_build 27 | context: . 28 | dockerfile: ./docker/django/Dockerfile 29 | args: 30 | DJANGO_ENV: development 31 | cache_from: 32 | - "autspaces:dev" 33 | - "autspaces:latest" 34 | - "*" 35 | 36 | volumes: 37 | - django-static:/var/www/django/static 38 | depends_on: 39 | - db 40 | networks: 41 | - webnet 42 | env_file: ./config/.env 43 | environment: 44 | DJANGO_DATABASE_HOST: db 45 | 46 | command: python -Wd manage.py runserver 0.0.0.0:8000 47 | healthcheck: 48 | test: | 49 | /usr/bin/test $$( 50 | /usr/bin/curl --fail http://localhost:8000/health/?format=json 51 | --write-out "%{http_code}" --silent --output /dev/null 52 | ) -eq 200 53 | interval: 10s 54 | timeout: 5s 55 | retries: 5 56 | start_period: 30s 57 | 58 | networks: 59 | # Network for your internals, use it by default: 60 | webnet: 61 | 62 | volumes: 63 | pgdata: 64 | django-static: 65 | -------------------------------------------------------------------------------- /docker-run.sh: -------------------------------------------------------------------------------- 1 | # If this is an M1 mac, make sure we use docker QEMU amd64 2 | if [[ $(uname -m) == 'arm64' ]]; then 3 | echo "Running on an M1 mac; setting to use amd64 images under QEMU" 4 | export DOCKER_DEFAULT_PLATFORM=linux/amd64 5 | fi 6 | 7 | docker-compose build 8 | docker-compose run --rm web python manage.py migrate 9 | docker-compose up 10 | -------------------------------------------------------------------------------- /docker/caddy/Caddyfile: -------------------------------------------------------------------------------- 1 | # See https://caddyserver.com/docs 2 | 3 | # Email for Let's Encrypt expiration notices 4 | { 5 | email {$TLS_EMAIL} 6 | } 7 | 8 | # "www" redirect to "non-www" version 9 | www.{$DOMAIN_NAME} { 10 | redir https://{$DOMAIN_NAME}{uri} 11 | } 12 | 13 | {$DOMAIN_NAME} { 14 | # HTTPS options: 15 | header Strict-Transport-Security max-age=31536000; 16 | 17 | # Removing some headers for improved security: 18 | header -Server 19 | 20 | # Exclude matcher for Django assets 21 | @excludeDirs { 22 | not path /static/* /media/* 23 | } 24 | 25 | # Serving dynamic requests: 26 | reverse_proxy @excludeDirs web:8000 27 | 28 | # Serves static files, should be the same as `STATIC_ROOT` setting: 29 | file_server { 30 | root /var/www/django 31 | } 32 | 33 | # Allows to use `.gz` files when available: 34 | encode gzip 35 | 36 | # Logs: 37 | log { 38 | output stdout 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /docker/django/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | set -o errexit 4 | set -o nounset 5 | 6 | readonly cmd="$*" 7 | 8 | postgres_ready () { 9 | # Check that postgres is up and running on port `5432`: 10 | dockerize -wait 'tcp://db:5432' -timeout 5s 11 | } 12 | 13 | # We need this line to make sure that this container is started 14 | # after the one with postgres: 15 | until postgres_ready; do 16 | >&2 echo 'Postgres is unavailable - sleeping' 17 | done 18 | 19 | # It is also possible to wait for other services as well: redis, elastic, mongo 20 | >&2 echo 'Postgres is up - continuing...' 21 | 22 | # Evaluating passed command (do not touch): 23 | # shellcheck disable=SC2086 24 | exec $cmd 25 | -------------------------------------------------------------------------------- /docker/django/gunicorn.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | set -o errexit 4 | set -o nounset 5 | 6 | # We are using `gunicorn` for production, see: 7 | # http://docs.gunicorn.org/en/stable/configure.html 8 | 9 | # Check that $DJANGO_ENV is set to "production", 10 | # fail otherwise, since it may break things: 11 | echo "DJANGO_ENV is $DJANGO_ENV" 12 | if [ "$DJANGO_ENV" != 'production' ]; then 13 | echo 'Error: DJANGO_ENV is not set to "production".' 14 | echo 'Application will not start.' 15 | exit 1 16 | fi 17 | 18 | export DJANGO_ENV 19 | 20 | # start sshd 21 | set -e 22 | service ssh start 23 | 24 | # Run python specific scripts: 25 | # Running migrations in startup script might not be the best option, see: 26 | # docs/pages/template/production-checklist.rst 27 | python /code/manage.py migrate --noinput 28 | python /code/manage.py collectstatic --noinput 29 | python /code/manage.py compilemessages 30 | 31 | # Start gunicorn: 32 | # Docs: http://docs.gunicorn.org/en/stable/settings.html 33 | # Concerning `workers` setting see: 34 | # https://github.com/wemake-services/wemake-django-template/issues/1022 35 | /usr/local/bin/gunicorn server.wsgi \ 36 | --workers=2 `# Sync worker settings` \ 37 | --max-requests=2000 \ 38 | --max-requests-jitter=400 \ 39 | --bind='0.0.0.0:8000' `# Run Django on 8000 port` \ 40 | --chdir='/code' `# Locations` \ 41 | --log-file=- \ 42 | --worker-tmp-dir='/dev/shm' 43 | -------------------------------------------------------------------------------- /docker/docker-compose.prod.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # This compose-file is production only. So, it should not be called directly. 4 | # 5 | # Instead, it should be a part of your deploy strategy. 6 | # This setup is supposed to be used with `docker-swarm`. 7 | # See `./docs/pages/template/production.rst` docs. 8 | 9 | version: "3.6" 10 | services: 11 | caddy: 12 | image: "caddy:2.2.1" 13 | restart: unless-stopped 14 | env_file: ./config/.env 15 | volumes: 16 | - ./docker/caddy/Caddyfile:/etc/caddy/Caddyfile # configuration 17 | - caddy-config:/config # configuration autosaves 18 | - caddy-data:/data # saving certificates 19 | - django-static:/var/www/django/static # serving django's statics 20 | - django-media:/var/www/django/media # serving django's media 21 | ports: 22 | - "80:80" 23 | - "443:443" 24 | depends_on: 25 | - web 26 | networks: 27 | - proxynet 28 | 29 | web: 30 | <<: &web 31 | # Image for production: 32 | image: "registry.gitlab.com/Alan Turing Institute/autspaces:latest" 33 | build: 34 | target: production_build 35 | args: 36 | DJANGO_ENV: production 37 | 38 | restart: unless-stopped 39 | volumes: 40 | - django-media:/var/www/django/media # since in dev it is app's folder 41 | - django-locale:/code/locale # since in dev it is app's folder 42 | 43 | command: sh ./docker/django/gunicorn.sh 44 | networks: 45 | - proxynet 46 | expose: 47 | - 8000 48 | 49 | # This task is an example of how to extend existing ones: 50 | # some_wroker: 51 | # <<: *web 52 | # command: python manage.py worker_process 53 | # deploy: 54 | # replicas: 2 55 | 56 | networks: 57 | # Network for your proxy server and application to connect them, 58 | # do not use it for anything else! 59 | proxynet: 60 | 61 | volumes: 62 | django-media: 63 | django-locale: 64 | caddy-config: 65 | caddy-data: 66 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = python -msphinx 7 | SPHINXPROJ = wemake-django-template 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/_static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/docs/_static/.gitkeep -------------------------------------------------------------------------------- /docs/_templates/moreinfo.html: -------------------------------------------------------------------------------- 1 |

2 | Links 3 |

4 | 5 | 22 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /docs/documents/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/docs/documents/.gitkeep -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | set SPHINXPROJ=wemake-django-template 13 | 14 | if "%1" == "" goto help 15 | 16 | %SPHINXBUILD% >NUL 2>NUL 17 | if errorlevel 9009 ( 18 | echo. 19 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 20 | echo.installed, then set the SPHINXBUILD environment variable to point 21 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 22 | echo.may add the Sphinx directory to PATH. 23 | echo. 24 | echo.If you don't have Sphinx installed, grab it from 25 | echo.http://sphinx-doc.org/ 26 | exit /b 1 27 | ) 28 | 29 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 30 | goto end 31 | 32 | :help 33 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 34 | 35 | :end 36 | popd 37 | -------------------------------------------------------------------------------- /docs/pages/project/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/docs/pages/project/.gitkeep -------------------------------------------------------------------------------- /docs/pages/template/faq.rst: -------------------------------------------------------------------------------- 1 | Frequently asked questions 2 | ========================== 3 | 4 | Will you ever support drf / celery / flask / gevent? 5 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6 | 7 | No. This template is focused on bringing best practices to ``django`` 8 | projects. It only includes workflow and configuration for this framework. 9 | 10 | Other tools are not mandatory. And can easily be added by a developer. 11 | 12 | Will you have an build-time option to include or change anything? 13 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 14 | 15 | No, we believe that options bring inconsistencies to the project. 16 | You can also make the wrong choice. So, we are protecting you from that. 17 | 18 | You can only have options that are already present in this template. 19 | Fork it, if you do not agree with this policy. 20 | 21 | This code quality is unbearable! Can I turn it off? 22 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 23 | 24 | Of course, no one can stop you from that. 25 | But what the point in using this template then? 26 | 27 | Our code quality defined by this template is minimally acceptable. 28 | We know tools to make it even better. But they are not included. 29 | Since they are literally hardcore. 30 | -------------------------------------------------------------------------------- /docs/pages/template/gitlab-ci.rst: -------------------------------------------------------------------------------- 1 | Gitlab CI 2 | ========= 3 | 4 | We use ``Gitlab CI`` to build our containers, test it, 5 | and store them in the internal registry. 6 | 7 | These images are then pulled into the production servers. 8 | 9 | 10 | Configuration 11 | ------------- 12 | 13 | All configuration is done inside ``.gitlab-ci.yml``. 14 | 15 | 16 | Pipelines 17 | --------- 18 | 19 | We have two pipelines configured: for ``master`` and other branches. 20 | That's how it works: we only run testing for feature branches and do the whole 21 | building/testing/deploying process for the ``master`` branch. 22 | 23 | This allows us to speed up development process. 24 | 25 | 26 | Automatic dependencies update 27 | ----------------------------- 28 | 29 | You can use `dependabot `_ 30 | to enable automatic dependencies updates via Pull Requests to your repository. 31 | Similar to the original template repository: `list of pull requests `_. 32 | 33 | It is available to both Github and Gitlab. 34 | But, for Gitlab version you currently have to update your `.gitlab-ci.yml `_. 35 | 36 | 37 | Secret variables 38 | ---------------- 39 | 40 | If some real secret variables are required, then you can use `gitlab secrets `_. 41 | And these kind of variables are required *most* of the time. 42 | 43 | See :ref:`django` on how to use ``dump-env`` and ``gitlab-ci`` together. 44 | 45 | 46 | Documentation 47 | ------------- 48 | After each deploy from master branch this documentation compiles into nice looking html page. 49 | See `gitlab pages info `_. 50 | 51 | 52 | Further reading 53 | --------------- 54 | 55 | - `Container Registry `_ 56 | - `Gitlab CI/CD `_ 57 | -------------------------------------------------------------------------------- /docs/pages/template/production.rst: -------------------------------------------------------------------------------- 1 | Production 2 | ========== 3 | 4 | We use different tools and setup for production. 5 | We do not fully provide this part with the template. Why? 6 | 7 | 1. It requires a lot of server configuration 8 | 2. It heavily depends on your needs: performance, price, technology, etc 9 | 3. It is possible to show some vulnerable parts to possible attackers 10 | 11 | So, you will need to deploy your application by yourself. 12 | Here, we would like to cover some basic things that are not changed 13 | from deployment strategy. 14 | 15 | The easiest deployment strategy for small apps is ``docker-compose`` and 16 | ``systemd`` inside a host operating system. 17 | 18 | 19 | Production configuration 20 | ------------------------ 21 | 22 | You will need to specify extra configuration 23 | to run ``docker-compose`` in production. 24 | Since production build also uses ``caddy``, 25 | which is not required into the development build. 26 | 27 | .. code:: bash 28 | 29 | docker-compose -f docker-compose.yml -f docker/docker-compose.prod.yml config > docker-compose.deploy.yml 30 | 31 | 32 | Pulling pre-built images 33 | ------------------------ 34 | 35 | You will need to pull pre-built images from ``Gitlab`` to run them. 36 | How to do that? 37 | 38 | The first step is to create a personal access token for this service. 39 | Then, login into your registry with: 40 | 41 | .. code:: bash 42 | 43 | docker login registry.gitlab.your.domain 44 | 45 | And now you are ready to pull your images: 46 | 47 | .. code:: bash 48 | 49 | docker pull your-image:latest 50 | 51 | See `official Gitlab docs `_. 52 | 53 | 54 | Updating already running service 55 | -------------------------------- 56 | 57 | If you need to update an already running service, 58 | them you will have to use ``docker service update`` 59 | or ``docker stack deploy``. 60 | 61 | Updating existing `service `_. 62 | Updating existing `stack `_. 63 | 64 | Zero-Time Updates 65 | ~~~~~~~~~~~~~~~~~ 66 | 67 | Zero-Time Updates can be tricky. 68 | You need to create containers with the new code, update existing services, 69 | wait for the working sessions to be completed, and to shut down old 70 | containers. 71 | 72 | 73 | Further reading 74 | --------------- 75 | 76 | - Production with `docker-compose `_ 77 | - `Full tutorial `_ 78 | -------------------------------------------------------------------------------- /docs/pages/template/upgrading-template.rst: -------------------------------------------------------------------------------- 1 | Upgrading template 2 | ================== 3 | 4 | Upgrading your project to be up-to-date with this template is a primary goal. 5 | This is achieved by manually applying ``diff`` to your existing code. 6 | 7 | ``diff`` can be viewed from the project's ``README.md``. 8 | See `an example `_. 9 | 10 | When the upgrade is applied just change the commit hash in your template 11 | to the most recent one. 12 | 13 | 14 | Versions 15 | -------- 16 | 17 | Sometimes, when we break something heavily, we create a version. 18 | That's is required for our users, so they can use old releases to create 19 | projects as they used to be a long time ago. 20 | 21 | However, we do not officially support older versions. 22 | And we do not recommend to use them. 23 | 24 | A full list of versions can be `found here `_. 25 | 26 | 27 | Migration guides 28 | ---------------- 29 | 30 | Each time we create a new version, we also provide a migration guide. 31 | What is a migration guide? 32 | It is something you have to do to your project 33 | other than just copy-pasting diffs from new versions. 34 | 35 | Goodbye, pipenv! 36 | ~~~~~~~~~~~~~~~~ 37 | 38 | This version requires a manual migration step. 39 | 40 | 1. You need to install ``poetry`` 41 | 2. You need to create a new ``pyproject.toml`` file with ``poetry init`` 42 | 3. You need to adjust name, version, description, and authors meta fields 43 | 4. You need to copy-paste dependencies from ``Pipfile`` to ``pyproject.toml`` 44 | 5. You need to set correct version for each dependency in the list, 45 | use ``"^x.y"`` `notation `_ 46 | 6. You need to adjust ``[build-system]`` tag and ``POETRY_VERSION`` variable 47 | to fit your ``poetry`` version 48 | 7. Create ``poetry.lock`` file with ``poetry lock`` 49 | 50 | It should be fine! You may, however, experience some bugs related to different 51 | dependency version resolution mechanisms. But, ``poetry`` does it better. 52 | -------------------------------------------------------------------------------- /fly.toml: -------------------------------------------------------------------------------- 1 | # fly.toml app configuration file generated for weathered-darkness-2449 on 2023-08-31T09:19:36+01:00 2 | # 3 | # See https://fly.io/docs/reference/configuration/ for information about how to use this file. 4 | # 5 | 6 | app = "weathered-darkness-2449" 7 | primary_region = "cdg" 8 | console_command = "/code/manage.py shell" 9 | 10 | [build] 11 | 12 | [deploy] 13 | release_command = "python manage.py migrate" 14 | 15 | [env] 16 | PORT = "8000" 17 | 18 | [http_service] 19 | internal_port = 8000 20 | force_https = true 21 | auto_stop_machines = true 22 | auto_start_machines = true 23 | min_machines_running = 0 24 | processes = ["app"] 25 | 26 | [[statics]] 27 | guest_path = "/code/static" 28 | url_prefix = "/static/" 29 | -------------------------------------------------------------------------------- /locale/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/locale/.gitkeep -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import sys 5 | 6 | 7 | def main() -> None: 8 | """ 9 | Main function. 10 | 11 | It does several things: 12 | 1. Sets default settings module, if it is not set 13 | 2. Warns if Django is not installed 14 | 3. Executes any given command 15 | """ 16 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'server.settings') 17 | 18 | try: 19 | from django.core import management # noqa: WPS433 20 | except ImportError: 21 | raise ImportError( 22 | "Couldn't import Django. Are you sure it's installed and " + 23 | 'available on your PYTHONPATH environment variable? Did you ' + 24 | 'forget to activate a virtual environment?', 25 | ) 26 | 27 | management.execute_from_command_line(sys.argv) 28 | 29 | 30 | if __name__ == '__main__': 31 | main() 32 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["poetry-core>=1.0.0"] 3 | build-backend = "poetry.core.masonry.api" 4 | 5 | 6 | [tool.nitpick] 7 | style = "https://raw.githubusercontent.com/wemake-services/wemake-python-styleguide/master/styles/nitpick-style-wemake.toml" 8 | 9 | 10 | [tool.poetry] 11 | name = "autspaces" 12 | description = "Autistica Turing Citizen Science Platform" 13 | version = "0.1.0" 14 | readme = "README.md" 15 | authors = ["test.com"] 16 | 17 | 18 | [tool.poetry.dependencies] 19 | python = "3.12.2" 20 | 21 | django = "^5.0" 22 | django-split-settings = "^1.0" 23 | django-axes = "^5.10" 24 | django-csp = "^3.7" 25 | django-health-check = "^3.16" 26 | django-http-referrer-policy = "^1.1" 27 | django-feature-policy = "^3.6" 28 | django-stubs-ext = "^0.1" 29 | 30 | psycopg2-binary = "^2.8" 31 | gunicorn = "^20.0" 32 | python-decouple = "^3.3" 33 | bcrypt = "^3.2" 34 | structlog = "^20.1" 35 | django-open-humans = "^0.2.0" 36 | vcrpy = "^4.2.1" 37 | coverage = "^7.2.2" 38 | dj-database-url = "^2.1.0" 39 | whitenoise = "^6.6.0" 40 | 41 | 42 | [tool.poetry.dev-dependencies] 43 | django-debug-toolbar = "^3.2" 44 | django-querycount = "^0.7" 45 | django-migration-linter = "^2.4" 46 | django-extra-checks = "^0.8" 47 | django-coverage-plugin = "^1.8" 48 | nplusone = "^1.0" 49 | 50 | wemake-python-styleguide = "^0.18" 51 | flake8-pytest-style = "^1.3" 52 | flake8-django = "^1.1" 53 | flake8-logging-format = "^0.6" 54 | nitpick = "^0.23" 55 | 56 | pytest = "^6.2" 57 | pytest-django = "^4.1" 58 | pytest-cov = "^2.10" 59 | pytest-randomly = "^3.4" 60 | pytest-deadfixtures = "^2.2" 61 | pytest-testmon = "^2.0" 62 | pytest-timeout = "^1.4" 63 | django-test-migrations = "^1.1" 64 | hypothesis = "^5.43" 65 | 66 | mypy = "^1.8" 67 | django-stubs = "^1.7" 68 | 69 | sphinx = "^3.4" 70 | sphinx-autodoc-typehints = "^1.11" 71 | tomlkit = "^0.7" 72 | doc8 = "^0.8" 73 | 74 | yamllint = "^1.25" 75 | safety = "^1.10" 76 | dotenv-linter = "^0.4" 77 | polint = "^0.4" 78 | dennis = "^0.9" 79 | dump-env = "^1.2" 80 | ipython = "^8.10" 81 | -------------------------------------------------------------------------------- /server/README.md: -------------------------------------------------------------------------------- 1 | ### Server - AutSPACES Platform Code 2 | 3 | In this folder you will find the up to date code that is used to run the platform. 4 | 5 | > Prerequisits for running the code on Windows: 6 | - Python - Intermediate knowledge of writing in Python 7 | - Docker - Container which hosts the platform, need to have this downloaded 8 | - Visual Studio Code/Pycharm - tool for building your code 9 | - Open Humans project creation 10 | 11 | > Prerequisits for running the code on Mac: 12 | - Python - Intermediate knowledge of writing in Python 13 | - Open Humans project creation 14 | 15 | 16 | Follow the links beloe to the up to date code for the different aspect of the platform: 17 | - [landing-page]() 18 | 19 | 20 | Requirements and issues for each code and what needs to be done can be found in the [AutisticaCitizenScience Repository](https://github.com/alan-turing-institute/AutisticaCitizenScience) 21 | -------------------------------------------------------------------------------- /server/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/server/__init__.py -------------------------------------------------------------------------------- /server/apps/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/server/apps/__init__.py -------------------------------------------------------------------------------- /server/apps/main/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/server/apps/main/__init__.py -------------------------------------------------------------------------------- /server/apps/main/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from server.apps.main.models import PublicExperience, ExperienceHistory 3 | 4 | admin.site.register(PublicExperience) 5 | admin.site.register(ExperienceHistory) -------------------------------------------------------------------------------- /server/apps/main/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class Main(AppConfig): 5 | name = 'server.apps.main' 6 | -------------------------------------------------------------------------------- /server/apps/main/context_processors.py: -------------------------------------------------------------------------------- 1 | from openhumans.models import OpenHumansMember 2 | 3 | def create_auth_url(request): 4 | auth_url = OpenHumansMember.get_auth_url() 5 | return {'auth_url': auth_url} 6 | -------------------------------------------------------------------------------- /server/apps/main/feeds.py: -------------------------------------------------------------------------------- 1 | from .models import PublicExperience 2 | from django.contrib.syndication.views import Feed 3 | from django.urls import reverse 4 | from server.apps.main.helpers import extract_triggers_to_show, expand_filter 5 | from django.utils.feedgenerator import Atom1Feed 6 | 7 | class PublicExperienceFeed(Feed): 8 | description_template = "main/feed.html" 9 | 10 | def get_object(self, request): 11 | # check if 'all triggers' is in keys 12 | all_triggers = request.GET.get("all_triggers", False) 13 | # set all trigger labels if set 14 | if all_triggers: 15 | allowed_triggers = { 16 | "abuse", 17 | "violence", 18 | "drug", 19 | "mentalhealth", 20 | "negbody", 21 | "other", 22 | } 23 | else: 24 | # Check the allowed triggers 25 | allowed_triggers = set(request.GET.keys()) 26 | triggers_to_show = extract_triggers_to_show(allowed_triggers) 27 | return triggers_to_show 28 | 29 | def title(self, obj): 30 | return "AutSPACEs public experiences" 31 | 32 | def link(self, obj): 33 | return reverse("main:public_experiences") 34 | 35 | def description(self, obj): 36 | joined_triggers = ", ".join(obj) 37 | if joined_triggers: 38 | return "This feed includes potentially triggering stories related to %s" % joined_triggers 39 | else: 40 | return "No triggering content is included in this feed" 41 | 42 | def item_link(self, item): 43 | return reverse('main:single_story', args=[item.experience_id]) 44 | 45 | def item_title(self, item): 46 | return item.title_text 47 | 48 | def item_pubdate(self, item): 49 | return item.created_at 50 | 51 | def items(self, obj): 52 | experiences = PublicExperience.objects.filter(moderation_status="approved") 53 | experiences = expand_filter(experiences, obj) 54 | experiences = experiences.order_by("-created_at")[:10] 55 | return experiences 56 | 57 | class PublicExperienceAtomFeed(PublicExperienceFeed): 58 | feed_type = Atom1Feed 59 | subtitle = PublicExperienceFeed.description -------------------------------------------------------------------------------- /server/apps/main/management/commands/seed_db.py: -------------------------------------------------------------------------------- 1 | from django.core.management.base import BaseCommand 2 | from openhumans.models import OpenHumansMember 3 | from server.apps.main.models import PublicExperience 4 | import csv 5 | 6 | class Command(BaseCommand): 7 | help = 'Process so far unprocessed data sets' 8 | 9 | def add_arguments(self, parser): 10 | parser.add_argument( 11 | "-f, --file", 12 | dest="file", 13 | required=True, 14 | help="the CSV file with experiences to import", 15 | ) 16 | 17 | def handle(self, *args, **options): 18 | file_name = options["file"] 19 | 20 | # create OH member for public experience import 21 | data = {"access_token": 'foo', 22 | "refresh_token": 'bar', 23 | "expires_in": 36000} 24 | oh_member = OpenHumansMember.create(oh_id='999999999', 25 | data=data) 26 | oh_member.save() 27 | 28 | 29 | # iterate over CSV file, 30 | # expects first row to be header and then 4 columns 31 | # 1. title, 2. experience text, 3. difference text 32 | # 4. (optional entry): which trigger label applies 33 | 34 | with open(file_name, newline='') as csvfile: 35 | reader = csv.reader(csvfile, delimiter=',', quotechar='"') 36 | for i,row in enumerate(reader): 37 | if i > 0: 38 | pe_data = { 39 | "title_text": row[0], 40 | "experience_text": row[1], 41 | "difference_text": row[2], 42 | "moderation_status": "approved", 43 | "first_hand_authorship": "True", 44 | } 45 | if row[3]: 46 | pe_data[row[3]] = True 47 | PublicExperience.objects.create( 48 | open_humans_member=oh_member, experience_id=str(i), **pe_data) 49 | -------------------------------------------------------------------------------- /server/apps/main/management/commands/unseed_db.py: -------------------------------------------------------------------------------- 1 | from django.core.management.base import BaseCommand 2 | from server.apps.main.models import PublicExperience 3 | from server.apps.users.models import UserProfile 4 | from django.contrib.auth.models import User 5 | from server.apps.users.helpers import delete_user 6 | 7 | class Command(BaseCommand): 8 | help = "Restore DB and OH account to initial settings" 9 | 10 | def handle(self, *args, **options): 11 | 12 | # Delete user added stories from OH and DB and delete the user 13 | for u in User.objects.all(): 14 | if u.username == "999999999_openhumans": 15 | u.delete() 16 | else: 17 | delete_user(user=u, delete_oh_data=True) 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /server/apps/main/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.3 on 2019-07-15 12:14 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | initial = True 10 | 11 | dependencies = [ 12 | ('openhumans', '0001_initial'), 13 | ] 14 | 15 | operations = [ 16 | migrations.CreateModel( 17 | name='PublicExperience', 18 | fields=[ 19 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 20 | ('experience_text', models.TextField()), 21 | ('created_at', models.DateTimeField(auto_now=True)), 22 | ('open_humans_member', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='openhumans.OpenHumansMember')), 23 | ], 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /server/apps/main/migrations/0002_add_fields_to_public_experiences.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.17 on 2021-10-19 09:54 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('main', '0001_initial'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='PublicExperience', 15 | name='approved', 16 | field=models.CharField(default='not reviewed', max_length=50), 17 | ), 18 | migrations.AddField( 19 | model_name='PublicExperience', 20 | name='difference_text', 21 | field=models.TextField(default=''), 22 | ), 23 | migrations.AddField( 24 | model_name='PublicExperience', 25 | name='experience_id', 26 | field=models.TextField(default=''), 27 | preserve_default=False, 28 | ), 29 | ] 30 | -------------------------------------------------------------------------------- /server/apps/main/migrations/0003_publicexperience_title_text.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.17 on 2022-11-29 11:16 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('main', '0002_add_fields_to_public_experiences'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='publicexperience', 15 | name='title_text', 16 | field=models.TextField(default=''), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /server/apps/main/migrations/0004_update_publicexperience_class.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.17 on 2022-12-20 13:47 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('main', '0003_publicexperience_title_text'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='publicexperience', 15 | name='abuse', 16 | field=models.BooleanField(default=False), 17 | ), 18 | migrations.AddField( 19 | model_name='publicexperience', 20 | name='drug', 21 | field=models.BooleanField(default=False), 22 | ), 23 | migrations.AddField( 24 | model_name='publicexperience', 25 | name='mentalhealth', 26 | field=models.BooleanField(default=False), 27 | ), 28 | migrations.AddField( 29 | model_name='publicexperience', 30 | name='negbody', 31 | field=models.BooleanField(default=False), 32 | ), 33 | migrations.AddField( 34 | model_name='publicexperience', 35 | name='other', 36 | field=models.BooleanField(default=False), 37 | ), 38 | migrations.AddField( 39 | model_name='publicexperience', 40 | name='violence', 41 | field=models.BooleanField(default=False), 42 | ), 43 | ] 44 | -------------------------------------------------------------------------------- /server/apps/main/migrations/0005_auto_20230105_1303.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.17 on 2023-01-05 13:03 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('main', '0004_update_publicexperience_class'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RemoveField( 14 | model_name='publicexperience', 15 | name='id', 16 | ), 17 | migrations.AlterField( 18 | model_name='publicexperience', 19 | name='experience_id', 20 | field=models.TextField(primary_key=True, serialize=False), 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /server/apps/main/migrations/0006_auto_20230123_1209.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.17 on 2023-01-23 12:09 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('main', '0005_auto_20230105_1303'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='publicexperience', 15 | name='research', 16 | field=models.BooleanField(default=False), 17 | ), 18 | migrations.AlterField( 19 | model_name='publicexperience', 20 | name='other', 21 | field=models.TextField(default=''), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /server/apps/main/migrations/0007_auto_20230123_1341.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.17 on 2023-01-23 13:41 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('main', '0006_auto_20230123_1209'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RenameField( 14 | model_name='publicexperience', 15 | old_name='approved', 16 | new_name='moderation_status', 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /server/apps/main/migrations/0008_experiencehistory.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.17 on 2023-02-06 15:55 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('main', '0007_auto_20230123_1341'), 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='ExperienceHistory', 16 | fields=[ 17 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('change_type', models.TextField()), 19 | ('changed_at', models.DateTimeField(auto_now=True)), 20 | ('changed_by', models.TextField()), 21 | ('change_comments', models.TextField(default='')), 22 | ('experience', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='main.PublicExperience')), 23 | ], 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /server/apps/main/migrations/0009_auto_20230327_1226.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.17 on 2023-03-27 12:26 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('main', '0008_experiencehistory'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='experiencehistory', 16 | name='changed_by', 17 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='openhumans.OpenHumansMember'), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /server/apps/main/migrations/0010_experiencehistory_change_reply.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2 on 2023-05-02 10:48 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('main', '0009_auto_20230327_1226'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='experiencehistory', 15 | name='change_reply', 16 | field=models.TextField(default=''), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /server/apps/main/migrations/0011_publicexperience_authorship_relation_and_more.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.3 on 2023-08-30 15:28 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('main', '0010_experiencehistory_change_reply'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='publicexperience', 15 | name='authorship_relation', 16 | field=models.TextField(default=''), 17 | ), 18 | migrations.AddField( 19 | model_name='publicexperience', 20 | name='first_hand_authorship', 21 | field=models.BooleanField(choices=[(False, "Experience is someone else's"), (True, 'Experience is my own')], default=False), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /server/apps/main/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/server/apps/main/migrations/__init__.py -------------------------------------------------------------------------------- /server/apps/main/mod_message.txt: -------------------------------------------------------------------------------- 1 | Your story on AutSPACEs has been moderated 2 | Dear AutSPACEs community member, 3 | 4 | Thank you for submitting the following story to the AutSPACEs platform: 5 | 6 | "{title}" 7 | 8 | The moderation status of your story has changed. To see the latest information for your story, please visit the AutSPACEs site and navigate to the "My Stories" page. 9 | 10 | Alternatively, to go directly to the story, select this link: 11 | 12 | {story} 13 | 14 | Thank you again for contributing to the AutSPACES community. 15 | 16 | Best wishes from the AutSPACEs community. 17 | 18 | You can disable these alerts at any time from your profile page: 19 | 20 | {profile} 21 | 22 | -------------------------------------------------------------------------------- /server/apps/main/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from openhumans.models import OpenHumansMember 3 | 4 | 5 | class PublicExperience(models.Model): 6 | experience_text = models.TextField() 7 | difference_text = models.TextField(default="") 8 | title_text = models.TextField(default="") 9 | created_at = models.DateTimeField(auto_now=True) 10 | experience_id = models.TextField(primary_key=True) #if specified as primary key you cannot have duplicates. 11 | open_humans_member = models.ForeignKey(OpenHumansMember, 12 | blank=True, null=True, 13 | on_delete=models.CASCADE) 14 | moderation_status = models.CharField( 15 | blank=False, 16 | default='not reviewed', 17 | max_length=50) 18 | 19 | abuse = models.BooleanField(default=False) 20 | violence = models.BooleanField(default=False) 21 | drug = models.BooleanField(default=False) 22 | mentalhealth = models.BooleanField(default=False) 23 | negbody = models.BooleanField(default=False) 24 | other = models.TextField(default="") 25 | 26 | research = models.BooleanField(default=False) 27 | 28 | authorship_choices = ((False, "Experience is someone else's"), (True, "Experience is my own")) 29 | first_hand_authorship = models.BooleanField(choices=authorship_choices, default=False) 30 | authorship_relation = models.TextField(default="") 31 | 32 | def __str__(self): 33 | return self.experience_text 34 | 35 | class ExperienceHistory(models.Model): 36 | experience = models.ForeignKey(PublicExperience, on_delete=models.CASCADE) 37 | change_type = models.TextField() 38 | changed_at = models.DateTimeField(auto_now=True) 39 | changed_by = models.ForeignKey(OpenHumansMember, 40 | blank=False, 41 | null=False, 42 | on_delete=models.CASCADE) 43 | change_comments = models.TextField(default="") 44 | change_reply = models.TextField(default="") 45 | 46 | def __str__(self): 47 | return self.change_type -------------------------------------------------------------------------------- /server/apps/main/templates/main/confirmation_page.html: -------------------------------------------------------------------------------- 1 | {% extends 'main/application.html' %} 2 | 3 | {% block title %}AutSPACEs - Experience saved! 🎉 {% endblock %} 4 | 5 | {% load static %} 6 | {% load custom_tags %} 7 | {% load humanize %} 8 | 9 | {% block content %} 10 | 11 | 12 |
13 |
14 |
15 |

16 | Success! 17 |

18 | 19 |

20 | Thank you for sharing your experience. 21 |

22 |
23 |
24 |
25 |

26 | What happens now ?

27 |
28 |
    29 |
  • 30 | If you chose to share your experience with the world, a moderator 31 | will check that it follows our content moderation guidelines, and if it does, you will receive a confirmation and your 32 | experience 33 | will then be published on this website. 34 |

  • 35 | 36 |
  • 37 | If you chose to share it with researchers, it will be saved into a 38 | database, and researchers who follow 39 | our values will be able to use it for their research. 40 |

  • 41 |
42 |
43 |
44 | 45 |
46 |

47 | What would you like to do next ? 48 |

49 | 50 | 68 |
69 | 70 | 71 |
72 | 73 | 74 | {% endblock %} 75 | -------------------------------------------------------------------------------- /server/apps/main/templates/main/deletion_confirmation.html: -------------------------------------------------------------------------------- 1 | {% extends 'main/application.html' %} 2 | 3 | {% block title %}AutSPACEs - Delete experience {% endblock %} 4 | 5 | {% load static %} 6 | {% load custom_tags %} 7 | {% load humanize %} 8 | 9 | {% block content %} 10 | 11 | 12 |
13 |
14 |
15 |

16 | Are you sure? 17 |

18 |

19 | You are about to delete the experience: {{title|unquote_html}}. 20 |

21 |
22 | 23 | 24 |
25 |
26 |
{% csrf_token %} 27 | 28 |
29 |
30 | 35 |
36 |
37 |
38 | 39 | {% endblock %} 40 | -------------------------------------------------------------------------------- /server/apps/main/templates/main/deletion_success.html: -------------------------------------------------------------------------------- 1 | {% extends 'main/application.html' %} 2 | 3 | {% block title %}AutSPACEs - Delete experience {% endblock %} 4 | 5 | {% load static %} 6 | {% load custom_tags %} 7 | {% load humanize %} 8 | 9 | {% block content %} 10 | 11 |
12 |
13 |
14 |

Success!

15 |

Experience '{{title|unquote_html}}' deleted.

16 |
17 |
18 |
19 |

20 | What would you like to do next ? 21 |

22 | 23 | 41 |
42 | 43 | 44 |
45 | 46 | {% endblock %} 47 | -------------------------------------------------------------------------------- /server/apps/main/templates/main/feed.html: -------------------------------------------------------------------------------- 1 | 2 |

The experience

3 |

4 | {{ obj.experience_text }} 5 |

6 | 7 |

What would make a difference

8 |

9 | {{ obj.difference_text }} 10 |

-------------------------------------------------------------------------------- /server/apps/main/templates/main/new_confirmation_page.html: -------------------------------------------------------------------------------- 1 | {% extends 'main/application.html' %} 2 | 3 | {% block title %}AutSPACEs - Experience saved! 🎉 {% endblock %} 4 | 5 | {% load static %} 6 | {% load custom_tags %} 7 | {% load humanize %} 8 | 9 | {% block content %} 10 | 11 | 12 |
13 |
14 |
15 |

16 | Success! 17 |

18 | 19 |

20 | {% firstof request.session.confirm_story "unknown story action" %} 21 |

22 |
23 |
24 |
25 |

26 | What happens now ?

27 |
28 |
    29 |
  • 30 | {% firstof request.session.confirm_story_privacy "Your story privacy status is unknown" %} 31 |

  • 32 | 33 |
  • 34 | {% firstof request.session.confirm_story_research "Your decision to share your story with researchers is unknown"%} 35 |

  • 36 |
  • 37 | You can change your privacy and research settings for this story by editing it via "My Stories" and changing the "Sharing Options". 38 |

  • 39 |
40 |
41 |
42 | 43 |
44 |

45 | What would you like to do next ? 46 |

47 | 48 | 66 |
67 | 68 | 69 |
70 | 71 | 72 | {% endblock %} 73 | -------------------------------------------------------------------------------- /server/apps/main/templates/main/pagination.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 43 |
44 | -------------------------------------------------------------------------------- /server/apps/main/templates/main/partials/dummy_stories.html: -------------------------------------------------------------------------------- 1 | 2 | 1 3 | Traffic Lights 4 | Self 5 | 09-11-2021 6 | 14-11-2021 7 | Accepted 8 | 9 | 10 | 2 11 | Taking subways in London 12 | For autistic friend 13 | 09-11-2021 14 | 14-11-2021 15 | Moderating 16 | 17 | 18 | 3 19 | Shopping in a market 20 | Self 21 | 09-11-2021 22 | 14-11-2021 23 | Re-moderating 24 | -------------------------------------------------------------------------------- /server/apps/main/templates/main/partials/footer.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 |
4 | 9 | 15 | 16 | 22 | 23 | 29 |
30 | -------------------------------------------------------------------------------- /server/apps/main/templates/main/partials/jquery.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /server/apps/main/templates/main/partials/moderatIon_status.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/server/apps/main/templates/main/partials/moderatIon_status.html -------------------------------------------------------------------------------- /server/apps/main/templates/main/partials/template_moderation_dropdown.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /server/apps/main/templates/main/partials/template_moderation_warnings.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 9 | 10 | 13 | 14 | -------------------------------------------------------------------------------- /server/apps/main/templates/main/partials/upload_form.html: -------------------------------------------------------------------------------- 1 |

Add your Experience

2 | 3 |
4 | {% csrf_token %} 5 |
6 | 7 | 15 | 16 | 19 | 27 |
28 | 29 |
30 | 37 | 40 |
41 | 42 |
43 | 50 | 53 |
54 | 55 | 56 |
57 | -------------------------------------------------------------------------------- /server/apps/main/templates/main/unused/complete.html: -------------------------------------------------------------------------------- 1 | {% extends 'main/application.html' %} 2 | 3 | {% block content %} 4 | 5 |

Now you can uploading a file to Open Humans with your project!

6 |

7 | Thank you! We got your authorization to connect to Open Humans. 8 |

9 |
10 |
11 | Upload a file. 12 |
13 |
14 |
15 |
16 | {% include 'main/partials/upload_form.html' %} 17 |
18 |
19 |

20 | You can also visit this project's page on Open Humans 21 | to see any data you've previously uploaded. 22 |

23 |
24 |
25 | 26 | {% endblock %} 27 | -------------------------------------------------------------------------------- /server/apps/main/templates/main/unused/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'main/application.html' %} 2 | 3 | {% block content %} 4 | 5 |
6 |

Building Accessible Community Environment

7 |

Welcome to AutSPACE

8 |

9 | This website exists for autistic people to share stories about how our senses affect us in our daily lives. 10 | django-open-humans. 11 |

12 |
13 | 14 |
15 |
16 |

17 | Configure this app by copying the env.sample file to 18 | .env and setting these as needed. You will need to 19 | create a project in Open Humans to get a "Client ID" and 20 | "Client secret" for your own project, and put these in your local 21 | .env file. 22 |

23 |

24 | The code for this site can be found on Github at: 25 | https://github.com/OpenHumans/oh-app-demo. 26 | You're welcome to use it as a template or reference for how a 27 | Django-based website can connect and interact with Open Humans 28 | member accounts. 29 |

30 |
31 |
32 |

How it works (once configured)

33 |
    34 |
  1. Log in to your Open Humans account
  2. 35 |
  3. Authorize your version of this project on Open Humans
    36 | This authorizes this app to deposit your archive into your Open Humans account.
  4. 37 |
  5. Upload your data.
    38 | You will be redirected back to this site and can then 39 | upload your data. 40 | You'll be able to 41 | access & manage your data on 42 | Open Humans. 43 |
  6. 44 |
45 | 46 | {% if auth_url %} 47 | 49 | Get started / Login 50 | 51 | {% else %} 52 | 53 | But first you need to set up your .env! 54 | 55 | {% endif %} 56 |
57 |
58 | 59 | 60 | {%endblock%} 61 | -------------------------------------------------------------------------------- /server/apps/main/templates/main/unused/moderate_public_experiences_old.html: -------------------------------------------------------------------------------- 1 | {% extends 'main/application.html' %} 2 | 3 | {% block content %} 4 |

File List

5 |

This is a list of all public experiences

6 | 7 | 8 | {% for experience in experiences %} 9 | 10 |
11 |
{{experience.open_humans_member.oh_id}} - {{experience.created_at}}
12 |
13 |
Experience
14 | {{experience.experience_text}} 15 |
What would you have liked to be different?
16 | {{experience.difference_text}} 17 |
18 |
19 | 20 |

Approve

21 | 22 | {% endfor %} 23 | 24 | {% endblock %} 25 | -------------------------------------------------------------------------------- /server/apps/main/templates/main/unused/overview.html: -------------------------------------------------------------------------------- 1 | {% extends 'main/application.html' %} 2 | 3 | {% block content %} 4 | 5 |

Manage your {{config.project_title}} data.

6 |

7 | Thank you! We logged you in through Open Humans. 8 |

9 |
10 |
11 | You can now use this project to add or remove your Experiences. 12 |
13 |
14 |
15 |
16 | 17 | 18 | {% include 'main/partials/upload_form.html' %} 19 |
20 |
21 |

22 | You can also take a look at the file list. 23 |

24 |
25 |
26 | 27 | {% endblock %} 28 | -------------------------------------------------------------------------------- /server/apps/main/templates/main/unused/public_experiences.html: -------------------------------------------------------------------------------- 1 | {% extends 'main/application.html' %} 2 | 3 | {% block content %} 4 |

File List

5 |

This is a list of all public experiences

6 | 7 | 8 | {% for experience in experiences %} 9 | 10 |
11 |
{{experience.open_humans_member.oh_id}} - {{experience.created_at}}
12 |
13 |
Experience
14 | {{experience.experience_text}} 15 |
What would you have liked to be different?
16 | {{experience.difference_text}} 17 |
18 |
19 | 20 | {% endfor %} 21 | 22 | {% endblock %} 23 | -------------------------------------------------------------------------------- /server/apps/main/templates/main/unused/upload.html: -------------------------------------------------------------------------------- 1 | {% extends 'main/application.html' %} 2 | 3 | {% block content %} 4 | 5 |

Add your Experience

6 | 7 |
8 | {% csrf_token %} 9 |
10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 |
18 | 19 | 22 |
23 | 24 |
25 | 26 | 29 |
30 | 31 | 32 |
33 | 34 | {% endblock %} 35 | -------------------------------------------------------------------------------- /server/apps/main/templatetags/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/server/apps/main/templatetags/__init__.py -------------------------------------------------------------------------------- /server/apps/main/templatetags/custom_tags.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | # from django.contrib.auth.models import Group 3 | from ..views import is_moderator 4 | from django.template.defaultfilters import register 5 | from urllib.parse import unquote 6 | 7 | 8 | register = template.Library() 9 | 10 | @register.simple_tag 11 | def define(val=None): 12 | return val 13 | 14 | @register.simple_tag 15 | def toggle_story(val): 16 | if val == 1: 17 | return 'story' 18 | else: 19 | return 'stories' 20 | 21 | register.simple_tag(is_moderator) 22 | 23 | @register.filter 24 | def unquote_html(value): 25 | return unquote(value) 26 | 27 | # for keeping toggles while moving between pagination pages 28 | # idea is to replace only the page number in the url, keep the rest 29 | @register.simple_tag 30 | def url_replace(request, field, value): 31 | """Replace or add a specific query parameter to the current request's url""" 32 | query = request.GET.copy() 33 | query[field] = value 34 | return '?{}'.format(query.urlencode()) 35 | 36 | @register.filter 37 | def field_type(field): 38 | return field.__class__.__name__ 39 | 40 | -------------------------------------------------------------------------------- /server/apps/main/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/server/apps/main/tests/__init__.py -------------------------------------------------------------------------------- /server/apps/main/tests/carousel-test01.json: -------------------------------------------------------------------------------- 1 | { 2 | "number-to-display": 3, 3 | "max-chars-title": 14, 4 | "max-chars-experience": 24, 5 | "placeholders": [ 6 | { 7 | "title": "title01title01title01title01title01title01title01title01title01title01title01title01", 8 | "experience": "experience01experience01experience01experience01experience01experience01experience01experience01experience01experience01experience01experience01", 9 | "difference": "difference01difference01difference01difference01difference01difference01difference01difference01difference01difference01difference01difference01", 10 | "image": "animation_a.jpg" 11 | }, 12 | { 13 | "title": "title02title02title02title02title02title02title02title02title02title02title02title02", 14 | "experience": "experience02experience02experience02experience02experience02experience02experience02experience02experience02experience02experience02experience02", 15 | "difference": "difference02difference02difference02difference02difference02difference02difference02difference02difference02difference02difference02difference02", 16 | "image": "animation_b.jpg" 17 | }, 18 | { 19 | "title": "title03title03title03title03title03title03title03title03title03title03title03title03", 20 | "experience": "experience03experience03experience03experience03experience03experience03experience03experience03experience03experience03experience03experience03", 21 | "difference": "difference03difference03difference03difference03difference03difference03difference03difference03difference03difference03difference03difference03", 22 | "image": "animation_c.jpg" 23 | } 24 | ], 25 | "stories": [ 26 | { 27 | "uuid": "1234_1", 28 | "image": "animation_b.jpg" 29 | }, 30 | { 31 | "uuid": "", 32 | "image": "" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /server/apps/main/tests/carousel-test02.json: -------------------------------------------------------------------------------- 1 | { 2 | "number-to-display": 5, 3 | "max-chars-title": 14, 4 | "max-chars-experience": 24, 5 | "placeholders": [ 6 | { 7 | "title": "title01title01title01title01title01title01title01title01title01title01title01title01", 8 | "experience": "experience01experience01experience01experience01experience01experience01experience01experience01experience01experience01experience01experience01", 9 | "difference": "difference01difference01difference01difference01difference01difference01difference01difference01difference01difference01difference01difference01", 10 | "image": "animation_a.jpg" 11 | }, 12 | { 13 | "title": "title02title02title02title02title02title02title02title02title02title02title02title02", 14 | "experience": "experience02experience02experience02experience02experience02experience02experience02experience02experience02experience02experience02experience02", 15 | "difference": "difference02difference02difference02difference02difference02difference02difference02difference02difference02difference02difference02difference02", 16 | "image": "animation_b.jpg" 17 | } 18 | ], 19 | "stories": [ 20 | { 21 | "uuid": "1234_2", 22 | "image": "animation_b.jpg" 23 | }, 24 | { 25 | "uuid": "1234_2", 26 | "image": "animation_c.jpg" 27 | }, 28 | { 29 | "uuid": "", 30 | "image": "" 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /server/apps/main/tests/carousel-test03.json: -------------------------------------------------------------------------------- 1 | { 2 | "number-to-display": 3, 3 | "max-chars-title": 14, 4 | "max-chars-experience": 24, 5 | "placeholders": [ 6 | { 7 | "title": "title01title01title01title01title01title01title01title01title01title01title01title01", 8 | "experience": "experience01experience01experience01experience01experience01experience01experience01experience01experience01experience01experience01experience01", 9 | "difference": "difference01difference01difference01difference01difference01difference01difference01difference01difference01difference01difference01difference01", 10 | "image": "animation_a.jpg" 11 | }, 12 | { 13 | "experience": "experience02experience02experience02experience02experience02experience02experience02experience02experience02experience02experience02experience02", 14 | "difference": "difference02difference02difference02difference02difference02difference02difference02difference02difference02difference02difference02difference02", 15 | "image": "animation_b.jpg" 16 | }, 17 | { 18 | "title": "title03title03title03title03title03title03title03title03title03title03title03title03", 19 | "experience": "experience03experience03experience03experience03experience03experience03experience03experience03experience03experience03experience03experience03" 20 | } 21 | ], 22 | "stories": [ 23 | { 24 | "uuid": "1234_2", 25 | "image": "animation_b.jpg" 26 | }, 27 | { 28 | "uuid": "nonexistent", 29 | "image": "animation_c.jpg" 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /server/apps/main/tests/carousel-test04.json: -------------------------------------------------------------------------------- 1 | { 2 | "number-to-display": 1, 3 | "max-chars-title": 14, 4 | "max-chars-experience": 24, 5 | "placeholders": [ 6 | ], 7 | "stories": [ 8 | { 9 | "image": "animation_b.jpg" 10 | }, 11 | { 12 | "uuid": "1234_1", 13 | "image": "animation_b.jpg" 14 | }, 15 | { 16 | "uuid": "1234_2", 17 | "image": "animation_b.jpg" 18 | }, 19 | { 20 | "uuid": "1234_3", 21 | "image": "animation_b.jpg" 22 | }, 23 | { 24 | "uuid": "1234_1", 25 | "image": "animation_b.jpg" 26 | }, 27 | { 28 | "uuid": "1234_1", 29 | "image": "animation_b.jpg" 30 | }, 31 | { 32 | "uuid": "", 33 | "image": "" 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /server/apps/main/tests/fixtures/delete.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: project_member_id=40945085&file_basename=8b4770bc-bc45-11ed-ae3f-0242ac130003.json 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '82' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | User-Agent: 16 | - python-requests/2.25.1 17 | method: POST 18 | uri: https://www.openhumans.org/api/direct-sharing/project/files/delete/ 19 | response: 20 | body: 21 | string: '{"ids":[62938816]}' 22 | headers: 23 | Allow: 24 | - POST, OPTIONS 25 | Cache-Control: 26 | - max-age=0, no-cache, no-store, must-revalidate 27 | Connection: 28 | - keep-alive 29 | Content-Length: 30 | - '18' 31 | Content-Type: 32 | - application/json 33 | Date: 34 | - Tue, 14 Mar 2023 12:06:41 GMT 35 | Expires: 36 | - Tue, 14 Mar 2023 12:06:41 GMT 37 | Server: 38 | - gunicorn/20.0.4 39 | Vary: 40 | - Accept, Authorization, Cookie, Origin 41 | Via: 42 | - 1.1 vegur 43 | X-Frame-Options: 44 | - SAMEORIGIN 45 | status: 46 | code: 200 47 | message: OK 48 | version: 1 49 | -------------------------------------------------------------------------------- /server/apps/main/tests/fixtures/delete_all.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: project_member_id=1234&all_files=True 4 | headers: 5 | Accept: ['*/*'] 6 | Accept-Encoding: ['gzip, deflate'] 7 | Connection: [keep-alive] 8 | Content-Length: ['41'] 9 | Content-Type: [application/x-www-form-urlencoded] 10 | User-Agent: [python-requests/2.18.4] 11 | method: POST 12 | uri: https://www.openhumans.org/api/direct-sharing/project/files/delete/?access_token=foo 13 | response: 14 | body: {string: '{"ids":[1337]}'} 15 | headers: 16 | Allow: ['POST, OPTIONS'] 17 | Cache-Control: ['must-revalidate, no-store, no-cache, max-age=0'] 18 | Connection: [close] 19 | Content-Language: [en] 20 | Content-Type: [application/json] 21 | Date: ['Tue, 06 Mar 2018 04:22:46 GMT'] 22 | Expires: ['Tue, 06 Mar 2018 04:22:46 GMT'] 23 | Last-Modified: ['Tue, 06 Mar 2018 04:22:46 GMT'] 24 | Server: [Cowboy] 25 | Vary: ['Accept, Accept-Language, Cookie'] 26 | Via: [1.1 vegur] 27 | X-Frame-Options: [SAMEORIGIN] 28 | status: {code: 200, message: OK} 29 | version: 1 30 | -------------------------------------------------------------------------------- /server/apps/main/tests/fixtures/delete_exp.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: project_member_id=40945085&file_basename=3653328c-f956-11ed-9803-0242ac140003.json 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '82' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | User-Agent: 16 | - python-requests/2.29.0 17 | method: POST 18 | uri: https://www.openhumans.org/api/direct-sharing/project/files/delete/ 19 | response: 20 | body: 21 | string: '{"ids":[66141444]}' 22 | headers: 23 | Allow: 24 | - POST, OPTIONS 25 | Cache-Control: 26 | - max-age=0, no-cache, no-store, must-revalidate 27 | Connection: 28 | - keep-alive 29 | Content-Length: 30 | - '18' 31 | Content-Type: 32 | - application/json 33 | Date: 34 | - Tue, 23 May 2023 16:01:54 GMT 35 | Expires: 36 | - Tue, 23 May 2023 16:01:54 GMT 37 | Server: 38 | - gunicorn/20.0.4 39 | Vary: 40 | - Accept, Authorization, Cookie, Origin 41 | Via: 42 | - 1.1 vegur 43 | X-Frame-Options: 44 | - SAMEORIGIN 45 | status: 46 | code: 200 47 | message: OK 48 | version: 1 49 | -------------------------------------------------------------------------------- /server/apps/main/tests/fixtures/delete_single.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: project_member_id=1234&file_id=1337 4 | headers: 5 | Accept: ['*/*'] 6 | Accept-Encoding: ['gzip, deflate'] 7 | Connection: [keep-alive] 8 | Content-Length: ['40'] 9 | Content-Type: [application/x-www-form-urlencoded] 10 | User-Agent: [python-requests/2.18.4] 11 | method: POST 12 | uri: https://www.openhumans.org/api/direct-sharing/project/files/delete/?access_token=foo 13 | response: 14 | body: {string: '{"ids":[1337]}'} 15 | headers: 16 | Allow: ['POST, OPTIONS'] 17 | Cache-Control: ['no-store, no-cache, max-age=0, must-revalidate'] 18 | Connection: [close] 19 | Content-Language: [en] 20 | Content-Type: [application/json] 21 | Date: ['Tue, 06 Mar 2018 04:33:37 GMT'] 22 | Expires: ['Tue, 06 Mar 2018 04:33:38 GMT'] 23 | Last-Modified: ['Tue, 06 Mar 2018 04:33:38 GMT'] 24 | Server: [Cowboy] 25 | Vary: ['Accept, Accept-Language, Cookie'] 26 | Via: [1.1 vegur] 27 | X-Frame-Options: [SAMEORIGIN] 28 | status: {code: 200, message: OK} 29 | - request: 30 | body: null 31 | headers: 32 | Accept: ['*/*'] 33 | Accept-Encoding: ['gzip, deflate'] 34 | Connection: [keep-alive] 35 | User-Agent: [python-requests/2.18.4] 36 | method: GET 37 | uri: https://www.openhumans.org/api/direct-sharing/project/exchange-member/?access_token=foo 38 | response: 39 | body: {string: '{"created":"2018-01-19T21:55:40.049169Z","project_member_id":"12345678","message_permission":true,"sources_shared":[],"data":[{"id":12345,"basename":"file_1","created":"2018-03-05T18:39:09.932067Z","download_url":"https://mytest.s3.amazonaws.com/member-files/direct-sharing-1337/7e3a0b60-20a4-11e8-8e3d-4a700bd48bfa/file_1?Signature=mysignature&Expires=1520291000&AWSAccessKeyId=ABCDEFGHIJ","metadata":{"tags":["foo","bar","baz"],"description":"foo"},"source":"direct-sharing-73"}]}'} 40 | headers: 41 | Allow: ['GET, HEAD, OPTIONS'] 42 | Cache-Control: ['must-revalidate, no-store, no-cache, max-age=0'] 43 | Connection: [close] 44 | Content-Language: [en] 45 | Content-Type: [application/json] 46 | Date: ['Mon, 05 Mar 2018 22:15:42 GMT'] 47 | Expires: ['Mon, 05 Mar 2018 22:15:42 GMT'] 48 | Last-Modified: ['Mon, 05 Mar 2018 22:15:42 GMT'] 49 | Server: [Cowboy] 50 | Vary: ['Accept, Accept-Language, Cookie'] 51 | Via: [1.1 vegur] 52 | X-Frame-Options: [SAMEORIGIN] 53 | status: {code: 200, message: OK} 54 | version: 1 55 | -------------------------------------------------------------------------------- /server/apps/main/tests/fixtures/get_oh_file.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | User-Agent: 12 | - python-requests/2.25.1 13 | method: GET 14 | uri: https://www.openhumans.org/data-management/datafile-download/63968911/?key=8859abff-0967-4a0d-8196-cbda2dc8224f 15 | response: 16 | body: 17 | string: '' 18 | headers: 19 | Connection: 20 | - keep-alive 21 | Content-Length: 22 | - '0' 23 | Content-Type: 24 | - text/html; charset=utf-8 25 | Date: 26 | - Tue, 04 Apr 2023 13:18:35 GMT 27 | Location: 28 | - https://open-humans-production.s3.amazonaws.com/member-files/direct-sharing-1330/01234567-89ab-cdef-0123-456789abcdef/01234567-89ab-cdef-0123-456789abcdef.json?AWSAccessKeyId=ABCDEFGHIJKLMNOPQRST&Signature=43gw66thjfgdget34DFe1b%2F5G6FDd7H%3D&Expires=1680617915&x-oh-key=01234567-89ab-cdef-0123-456789abcdef 29 | Server: 30 | - gunicorn/20.0.4 31 | Vary: 32 | - Authorization, Cookie 33 | Via: 34 | - 1.1 vegur 35 | X-Frame-Options: 36 | - SAMEORIGIN 37 | status: 38 | code: 302 39 | message: Found 40 | - request: 41 | body: null 42 | headers: 43 | Accept: 44 | - '*/*' 45 | Accept-Encoding: 46 | - gzip, deflate 47 | Connection: 48 | - keep-alive 49 | User-Agent: 50 | - python-requests/2.25.1 51 | method: GET 52 | uri: https://open-humans-production.s3.amazonaws.com/member-files/direct-sharing-1330/01234567-89ab-cdef-0123-456789abcdef/01234567-89ab-cdef-0123-456789abcdef.json?AWSAccessKeyId=ABCDEFGHIJKLMNOPQRST&Signature=43gw66thjfgdget34DFe1b%2F5G6FDd7H%3D&Expires=1680617915&x-oh-key=01234567-89ab-cdef-0123-456789abcdef 53 | response: 54 | body: 55 | string: '{"data": {"experience_text": "Experience text", "difference_text": 56 | "Difference text", "title_text": "Title text", "abuse": false, "violence": 57 | false, "drug": false, "mentalhealth": false, "negbody": false, "other": "Topic", 58 | "viewable": false, "research": false, "moderation_status": "not reviewed"}, 59 | "timestamp": "2023-04-04 13:16:18.647417"}' 60 | headers: 61 | Accept-Ranges: 62 | - bytes 63 | Content-Length: 64 | - '341' 65 | Content-Type: 66 | - binary/octet-stream 67 | Date: 68 | - Tue, 04 Apr 2023 13:18:36 GMT 69 | Last-Modified: 70 | - Tue, 04 Apr 2023 13:16:20 GMT 71 | Server: 72 | - AmazonS3 73 | status: 74 | code: 200 75 | message: OK 76 | version: 1 77 | -------------------------------------------------------------------------------- /server/apps/main/tests/jh_tests.py: -------------------------------------------------------------------------------- 1 | from unittest.mock import mock_open, patch 2 | from urllib.error import HTTPError 3 | 4 | from django.test import TestCase, Client, RequestFactory 5 | from django.conf import settings 6 | from openhumans.models import OpenHumansMember 7 | from openhumans.settings import openhumans_settings 8 | import requests_mock 9 | import vcr 10 | 11 | 12 | OH_BASE_URL = openhumans_settings['OPENHUMANS_OH_BASE_URL'] 13 | OH_API_BASE = OH_BASE_URL + '/api/direct-sharing' 14 | OH_DIRECT_UPLOAD = OH_API_BASE + '/project/files/upload/direct/' 15 | OH_DIRECT_UPLOAD_COMPLETE = OH_API_BASE + '/project/files/upload/complete/' 16 | OH_OAUTH2_REDIRECT_URI = '{}/complete'.format(settings.OPENHUMANS_APP_BASE_URL) 17 | OH_GET_URL = OH_API_BASE + '/project/exchange-member/' 18 | 19 | 20 | class LoginTestCase(TestCase): 21 | """ 22 | Tests for index page and upload feature 23 | """ 24 | 25 | def setUp(self): 26 | """ 27 | Set up the app for following tests 28 | """ 29 | settings.DEBUG = True 30 | self.factory = RequestFactory() 31 | data = {"access_token": 'foo', 32 | "refresh_token": 'bar', 33 | "expires_in": 36000} 34 | self.oh_member = OpenHumansMember.create(oh_id='12345678', 35 | data=data) 36 | self.oh_member.save() 37 | self.user = self.oh_member.user 38 | self.user.set_password('foobar') 39 | self.user.save() 40 | 41 | def test_index_logged_out(self): 42 | """ 43 | Test index page when logged out 44 | """ 45 | c = Client() 46 | response = c.get("/") 47 | self.assertEqual(response.status_code, 200) 48 | 49 | def test_index_logged_in(self): 50 | """ 51 | Test if redirection happens when user logs in. 52 | """ 53 | c = Client() 54 | c.login(username=self.user.username, password='foobar') 55 | response = c.get("/") 56 | self.assertRedirects(response, '/overview') 57 | 58 | def test_list_files_logged_out(self): 59 | """ 60 | Test the list_files function when logged out. 61 | """ 62 | c = Client() 63 | response = c.get("/list") 64 | self.assertRedirects(response, '/') 65 | -------------------------------------------------------------------------------- /server/apps/main/tests/jh_tests_view.py: -------------------------------------------------------------------------------- 1 | from io import BytesIO 2 | 3 | from django.test import TestCase, Client 4 | from django.core.management import call_command 5 | from django.conf import settings 6 | from openhumans.models import OpenHumansMember 7 | import vcr 8 | 9 | 10 | class IndexPageTestCase(TestCase): 11 | """ 12 | Test cases for the index page. 13 | """ 14 | 15 | def setUp(self): 16 | """ 17 | Set up the app for following tests. 18 | """ 19 | settings.DEBUG = True 20 | 21 | def test_index_page_content(self): 22 | """ 23 | Test whether content is rendered properly. 24 | """ 25 | c = Client() 26 | response = c.get('/') 27 | self.assertEqual(response.status_code, 200) 28 | 29 | 30 | class LoginTestCase(TestCase): 31 | """ 32 | Test the login logic of the OH API 33 | """ 34 | 35 | def setUp(self): 36 | settings.DEBUG = True 37 | settings.OPENHUMANS_APP_BASE_URL = "http://127.0.0.1" 38 | 39 | def test_log_out_logged_out(self): 40 | """ 41 | Tests logout function 42 | """ 43 | c = Client() 44 | response = c.get('/logout') 45 | self.assertEqual(response.status_code, 302) 46 | self.assertRedirects(response, "/") 47 | 48 | def test_overview_logged_out(self): 49 | """ 50 | Tests overview function when logged out 51 | """ 52 | c = Client() 53 | response = c.get("/overview") 54 | self.assertEqual(response.status_code, 302) 55 | self.assertRedirects(response, "/") 56 | 57 | def test_log_out(self): 58 | """ 59 | Tests logout function 60 | """ 61 | data = {"access_token": 'foo', 62 | "refresh_token": 'bar', 63 | "expires_in": 36000} 64 | self.oh_member = OpenHumansMember.create(oh_id='1234567890abcdef', 65 | data=data) 66 | self.oh_member.save() 67 | self.user = self.oh_member.user 68 | self.user.set_password('foobar') 69 | self.user.save() 70 | c = Client() 71 | c.login(username=self.user.username, password='foobar') 72 | response = c.post('/logout') 73 | self.assertEqual(response.wsgi_request.user.username, '') 74 | self.assertRedirects(response, "/") 75 | 76 | def test_upload_logged_out(self): 77 | c = Client() 78 | response = c.get("/upload/") 79 | self.assertEqual(response.status_code, 302) 80 | self.assertRedirects(response, '/') 81 | -------------------------------------------------------------------------------- /server/apps/main/tests/test_models.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from django.conf import settings 3 | from server.apps.main.models import PublicExperience 4 | 5 | from openhumans.models import OpenHumansMember 6 | 7 | 8 | class ModelsTest(TestCase): 9 | """ 10 | Tests the views function 11 | """ 12 | 13 | def setUp(self): 14 | """ 15 | Set-up for test with two users 16 | """ 17 | settings.DEBUG = True 18 | # One user 19 | data = {"access_token": 'foo', 20 | "refresh_token": 'bar', 21 | "expires_in": 36000} 22 | self.placeholder_user = OpenHumansMember.create(oh_id=12345678,data=data) 23 | self.placeholder_user.save() 24 | pe_data = {"experience_text": "a", 25 | "difference_text": "b", 26 | "title_text": "c"} 27 | PublicExperience.objects.create(open_humans_member = self.placeholder_user, **pe_data) 28 | 29 | def test_model_str(self): 30 | story_a = PublicExperience.objects.get(title_text = "c") 31 | assert story_a.__str__() == "a" 32 | 33 | def test_model_defaults(self): 34 | story_a = PublicExperience.objects.get(title_text = "c") 35 | assert story_a.abuse == False 36 | assert story_a.drug == False 37 | assert story_a.mentalhealth == False 38 | assert story_a.negbody == False 39 | assert story_a.violence == False 40 | assert story_a.research == False 41 | assert story_a.other == "" 42 | assert story_a.moderation_status == "not reviewed" 43 | 44 | -------------------------------------------------------------------------------- /server/apps/main/tests/test_my_stories.py: -------------------------------------------------------------------------------- 1 | from django.test import RequestFactory, TestCase, Client 2 | from django.core.paginator import Paginator 3 | from server.apps.main.helpers import filter_by_tag, filter_by_moderation_status, filter_in_review, paginate_stories 4 | 5 | # ------ test story filters -------- # 6 | 7 | class StoryFiltersTestCase(TestCase): 8 | def setUp(self): 9 | self.files = [ 10 | { 11 | 'metadata': { 12 | 'tags': ['tag1', 'tag2'], 13 | 'data': {'moderation_status': 'approved'} 14 | } 15 | }, 16 | { 17 | 'metadata': { 18 | 'tags': ['tag2', 'tag3'], 19 | 'data': {'moderation_status': 'pending'} 20 | } 21 | }, 22 | { 23 | 'metadata': { 24 | 'tags': ['tag3', 'tag4'], 25 | 'data': {'moderation_status': 'rejected'} 26 | } 27 | }, 28 | { 29 | 'metadata': { 30 | 'tags': ['public'], 31 | 'data': {'moderation_status': 'not reviewed'} 32 | } 33 | }, 34 | { 35 | 'metadata': { 36 | 'tags': ['tag5'], 37 | 'data': {'moderation_status': 'in review'} 38 | } 39 | }, 40 | { 41 | 'metadata': { 42 | 'tags': ['tag6'], 43 | 'data': {'moderation_status': 'not reviewed'} 44 | } 45 | }, 46 | { 47 | 'metadata': { 48 | 'tags': ['tag7'], 49 | 'data': {'moderation_status': 'approved'} 50 | } 51 | }, 52 | ] 53 | 54 | def test_filter_by_tag(self): 55 | filtered_files = filter_by_tag(self.files, 'tag2') 56 | self.assertEqual(len(filtered_files), 2) 57 | 58 | def test_filter_by_moderation_status(self): 59 | filtered_files = filter_by_moderation_status(self.files, 'approved') 60 | self.assertEqual(len(filtered_files), 2) 61 | 62 | def test_filter_in_review(self): 63 | filtered_files = filter_in_review(self.files) 64 | self.assertEqual(len(filtered_files), 2) 65 | -------------------------------------------------------------------------------- /server/apps/main/tests/test_templatetags.py: -------------------------------------------------------------------------------- 1 | from django.test import RequestFactory, TestCase 2 | from server.apps.main.templatetags.custom_tags import url_replace 3 | 4 | class UrlReplaceTest(TestCase): 5 | 6 | def setUp(self): 7 | # Create a request instance with some GET parameters 8 | self.factory = RequestFactory() 9 | self.request = self.factory.get('/example', {'param1': 'value1', 'param2': 'value2'}) 10 | 11 | def test_url_replace(self): 12 | # Use the template tag to change 'param1' to 'newvalue' 13 | result = url_replace(self.request, 'param1', 'newvalue') 14 | 15 | # Check that the output URL has the correct parameters 16 | self.assertEqual(result, '?param1=newvalue¶m2=value2') 17 | 18 | def test_url_replace_new_param(self): 19 | # Use the template tag to add 'param3' 20 | result = url_replace(self.request, 'param3', 'value3') 21 | 22 | # Check that the output URL has the correct parameters 23 | self.assertEqual(result, '?param1=value1¶m2=value2¶m3=value3') 24 | -------------------------------------------------------------------------------- /server/apps/main/tests/tests_2023.py: -------------------------------------------------------------------------------- 1 | import vcr 2 | import urllib.request 3 | import json 4 | 5 | 6 | @vcr.use_cassette("server/apps/main/tests/fixtures/share_experience.yaml") 7 | def test_share_experience(): 8 | """ 9 | Check the details and warnings are as expected 10 | """ 11 | r = ( 12 | urllib.request.urlopen( 13 | "https://www.openhumans.org/api/direct-sharing/project/exchange-member/" 14 | ) 15 | .read() 16 | .decode() 17 | ) 18 | response = json.loads(r)["data"][0]["metadata"]["data"] 19 | 20 | assert response["title_text"] == "Story the first" 21 | assert ( 22 | "However little known the feelings or views of such a man" 23 | in response["difference_text"] 24 | ) 25 | assert "It is a truth universally acknowledged" in response["experience_text"] 26 | assert [ 27 | response["drug"], 28 | response["abuse"], 29 | response["other"], 30 | response["negbody"], 31 | response["violence"], 32 | response["mentalhealth"], 33 | ] == [False, False, "", False, False, False] 34 | 35 | assert [response["research"], response['viewable']] == [True, True] 36 | -------------------------------------------------------------------------------- /server/apps/main/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path, re_path 2 | from server.apps.main import views 3 | from server.apps.main import feeds 4 | 5 | app_name = "main" 6 | 7 | urlpatterns = [ 8 | re_path(r"^$", views.index, name="index"), 9 | re_path(r"^signup/?$", views.signup, name="signup"), 10 | re_path(r"^login/?$", views.login_user, name="login"), 11 | re_path(r"^logout/?$", views.logout_user, name="logout"), 12 | re_path( 13 | r"^public_experiences/?$", 14 | views.list_public_experiences, 15 | name="public_experiences", 16 | ), 17 | re_path( 18 | r"^moderate_public_experiences/?$", 19 | views.moderate_public_experiences, 20 | name="moderate_public_experiences", 21 | ), 22 | re_path(r"moderation_list/?$", views.moderation_list, name="moderation_list"), 23 | path("delete//", views.delete_experience, name="delete_exp"), 24 | path("share_exp/", views.share_experience, name="share_exp"), 25 | path("edit//", views.share_experience, name="edit_exp"), 26 | path("moderate//", views.moderate_experience, name="moderate_exp"), 27 | path("view//", views.view_experience, name="view_exp"), 28 | path("my_stories/", views.my_stories, name="my_stories"), 29 | path("about_us/", views.about_us, name="about_us"), 30 | path("what_autism_is/", views.what_autism_is, name="what_autism_is"), 31 | path("help/", views.help, name="help"), 32 | path("content_moderation_guidelines/", views.content_moderation_guidelines, name="content_moderation_guidelines"), 33 | path("participant_information/", views.participant_information, name="participant_information"), 34 | path("registration/", views.registration, name="registration"), 35 | path("single_story//",views.single_story,name="single_story"), 36 | path("success_confirm/", views.success_confirm, name="success_confirm"), 37 | path("public_experiences/rss.xml", feeds.PublicExperienceFeed(), name='rss_feed'), 38 | path("public_experiences/atom.xml", feeds.PublicExperienceAtomFeed(), name='atom_feed'), 39 | ] 40 | -------------------------------------------------------------------------------- /server/apps/users/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/server/apps/users/__init__.py -------------------------------------------------------------------------------- /server/apps/users/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from .models import UserProfile 3 | 4 | admin.site.register(UserProfile) 5 | 6 | -------------------------------------------------------------------------------- /server/apps/users/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class UsersConfig(AppConfig): 5 | name = 'server.apps.users' 6 | -------------------------------------------------------------------------------- /server/apps/users/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2 on 2023-06-30 14:48 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | import django.db.models.deletion 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 12 | ] 13 | 14 | operations = [ 15 | migrations.CreateModel( 16 | name='UserProfile', 17 | fields=[ 18 | ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to=settings.AUTH_USER_MODEL)), 19 | ('age_bracket', models.TextField(default='unspecified')), 20 | ('description', models.TextField(default='')), 21 | ('gender', models.TextField(default='unspecified')), 22 | ('autistic_identification', models.TextField(default='unspecified')), 23 | ('location', models.TextField(default='')), 24 | ('abuse', models.BooleanField(default=False)), 25 | ('drug', models.BooleanField(default=False)), 26 | ('mentalhealth', models.BooleanField(default=False)), 27 | ('negbody', models.BooleanField(default=False)), 28 | ('violence', models.BooleanField(default=False)), 29 | ('other', models.BooleanField(default=False)), 30 | ('comms_review', models.BooleanField(default=False)), 31 | ('profile_submitted', models.BooleanField(default=False)), 32 | ], 33 | ), 34 | ] 35 | -------------------------------------------------------------------------------- /server/apps/users/migrations/0002_userprofile_refine_fields.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.3 on 2023-07-26 16:01 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('users', '0001_initial'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='userprofile', 15 | name='age_public', 16 | field=models.BooleanField(default=False), 17 | ), 18 | migrations.AddField( 19 | model_name='userprofile', 20 | name='description_public', 21 | field=models.BooleanField(default=False), 22 | ), 23 | migrations.AddField( 24 | model_name='userprofile', 25 | name='gender_public', 26 | field=models.BooleanField(default=False), 27 | ), 28 | migrations.RemoveField( 29 | model_name='userprofile', 30 | name='location', 31 | ), 32 | migrations.AddField( 33 | model_name='userprofile', 34 | name='gender_self_identification', 35 | field=models.TextField(default=''), 36 | ), 37 | ] 38 | -------------------------------------------------------------------------------- /server/apps/users/migrations/0003_alter_userprofile_autistic_identification.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.3 on 2023-08-30 16:38 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('users', '0002_userprofile_refine_fields'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='userprofile', 15 | name='autistic_identification', 16 | field=models.TextField(default=''), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /server/apps/users/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/server/apps/users/migrations/__init__.py -------------------------------------------------------------------------------- /server/apps/users/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.contrib.auth.models import User 3 | 4 | class UserProfile(models.Model): 5 | """ 6 | Holds profile information about a user 7 | """ 8 | user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True) 9 | profile_submitted = models.BooleanField(default=False) 10 | autistic_identification = models.TextField(default="") 11 | age_bracket = models.TextField(default="unspecified") 12 | age_public = models.BooleanField(default=False) 13 | gender = models.TextField(default="unspecified") 14 | gender_self_identification = models.TextField(default="") 15 | gender_public = models.BooleanField(default=False) 16 | description = models.TextField(default="") 17 | description_public = models.BooleanField(default=False) 18 | comms_review = models.BooleanField(default=False) 19 | 20 | abuse = models.BooleanField(default=False) 21 | violence = models.BooleanField(default=False) 22 | drug = models.BooleanField(default=False) 23 | mentalhealth = models.BooleanField(default=False) 24 | negbody = models.BooleanField(default=False) 25 | other = models.BooleanField(default=False) 26 | 27 | def __str__(self): 28 | return "Profile for {}".format(self.user.username) 29 | 30 | 31 | -------------------------------------------------------------------------------- /server/apps/users/templates/users/delete.html: -------------------------------------------------------------------------------- 1 | {% extends 'main/application.html' %} 2 | 3 | {% block title %}AutSPACEs - {{title}} {% endblock %} 4 | 5 | {% load static %} 6 | {% load custom_tags %} 7 | {% load humanize %} 8 | 9 | {% block content %} 10 | 11 | 12 |
13 |
14 |

15 |

OpenHumans ID: {{ oh_id }} 16 | 17 |

Are you sure you want to delete your AutSPACEs account? 18 |

This will remove all your data from the AutSPACEs platform. This process cannot be undone. 19 |

Select the switch below to also remove your stories from OpenHumans. 20 |

21 | {% csrf_token %} 22 |
23 | {% for field in form %} 24 |
25 |
26 |
27 | {{ field }} 28 | 29 |
30 |
31 |
32 | {% endfor %} 33 |
34 |
35 | 36 | Cancel 37 |
38 |
39 |
40 |
41 | 42 | {% endblock %} 43 | 44 | 45 | -------------------------------------------------------------------------------- /server/apps/users/templates/users/goodbye.html: -------------------------------------------------------------------------------- 1 | {% extends 'main/application.html' %} 2 | 3 | {% block title %}AutSPACEs - {{title}} {% endblock %} 4 | 5 | {% load static %} 6 | {% load custom_tags %} 7 | {% load humanize %} 8 | 9 | {% block content %} 10 | 11 | 12 |
13 |
14 |

15 | 16 |

We're sorry to see you go, but are grateful for your contribution to AutSPACEs. 17 | {% if delete_oh_data %} 18 |

All of your personal data has been removed from the AutSPACEs platform and your stories have been removed from OpenHumans. This won't affect any other data you may have stored on the OpenHumans platform. 19 | {% else %} 20 |

All of your personal data has been removed from the AutSPACEs platform, but please be aware that stories you entered here may still be stored on OpenHumans. You'll need to delete these separately. 21 | {% endif %} 22 |

If you'd like to contribute to AutSPACEs again in the future, please feel free to create a new account. 23 |

26 |
27 |
28 | 29 | {% endblock %} 30 | 31 | 32 | -------------------------------------------------------------------------------- /server/apps/users/templates/users/select_option_disable_empty.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /server/apps/users/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/server/apps/users/tests/__init__.py -------------------------------------------------------------------------------- /server/apps/users/tests/fixtures/delete_user.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: project_member_id=39896706&all_files=True 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '41' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | User-Agent: 16 | - python-requests/2.31.0 17 | method: POST 18 | uri: https://www.openhumans.org/api/direct-sharing/project/files/delete/ 19 | response: 20 | body: 21 | string: '{"ids":[69072773]}' 22 | headers: 23 | Allow: 24 | - POST, OPTIONS 25 | Cache-Control: 26 | - max-age=0, no-cache, no-store, must-revalidate 27 | Connection: 28 | - keep-alive 29 | Content-Length: 30 | - '18' 31 | Content-Type: 32 | - application/json 33 | Date: 34 | - Fri, 28 Jul 2023 15:06:45 GMT 35 | Expires: 36 | - Fri, 28 Jul 2023 15:06:45 GMT 37 | Server: 38 | - gunicorn/20.0.4 39 | Vary: 40 | - Accept, Authorization, Cookie, Origin 41 | Via: 42 | - 1.1 vegur 43 | X-Frame-Options: 44 | - SAMEORIGIN 45 | status: 46 | code: 200 47 | message: OK 48 | - request: 49 | body: null 50 | headers: 51 | Accept: 52 | - '*/*' 53 | Accept-Encoding: 54 | - gzip, deflate 55 | Connection: 56 | - keep-alive 57 | Content-Length: 58 | - '0' 59 | User-Agent: 60 | - python-requests/2.31.0 61 | method: POST 62 | uri: https://www.openhumans.org/api/direct-sharing/project/remove-members/ 63 | response: 64 | body: 65 | string: '"success"' 66 | headers: 67 | Allow: 68 | - POST, OPTIONS 69 | Cache-Control: 70 | - max-age=0, no-cache, no-store, must-revalidate 71 | Connection: 72 | - keep-alive 73 | Content-Length: 74 | - '9' 75 | Content-Type: 76 | - application/json 77 | Date: 78 | - Fri, 28 Jul 2023 15:06:46 GMT 79 | Expires: 80 | - Fri, 28 Jul 2023 15:06:46 GMT 81 | Server: 82 | - gunicorn/20.0.4 83 | Vary: 84 | - Accept, Authorization, Cookie, Origin 85 | Via: 86 | - 1.1 vegur 87 | X-Frame-Options: 88 | - SAMEORIGIN 89 | status: 90 | code: 200 91 | message: OK 92 | version: 1 93 | -------------------------------------------------------------------------------- /server/apps/users/tests/test_helpers.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from server.apps.users.helpers import update_session_success_or_confirm 3 | 4 | class UserHelper(TestCase): 5 | """ 6 | Tests for the user profile helpers 7 | """ 8 | 9 | def setUp(self): 10 | ''' 11 | Set-up for test with basic variables etc. 12 | ''' 13 | pass 14 | 15 | def test_update_session_success_or_confirm(self): 16 | """ 17 | Test that correct answers are fed to session 18 | """ 19 | response = update_session_success_or_confirm('experience', None, False, None, None) 20 | self.assertEqual("Your experience will not be publicly accessible on AutSPACEs", response['s_or_c_whn_1']) 21 | 22 | response = update_session_success_or_confirm('experience', None, False, True, "message goes here") 23 | self.assertEqual("message goes here", response['s_or_c_whn_2']) 24 | 25 | -------------------------------------------------------------------------------- /server/apps/users/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path, re_path 2 | from server.apps.users import views 3 | 4 | app_name = "servers.apps.users" 5 | 6 | urlpatterns = [ 7 | path("profile/", views.user_profile, name="profile"), 8 | path("greetings/", views.user_profile, {"first_visit": True}, name="greetings"), 9 | path("delete/", views.user_profile_delete, name="delete"), 10 | ] 11 | -------------------------------------------------------------------------------- /server/settings/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | This is a django-split-settings main file. 3 | 4 | For more information read this: 5 | https://github.com/sobolevn/django-split-settings 6 | https://sobolevn.me/2017/04/managing-djangos-settings 7 | 8 | To change settings file: 9 | `DJANGO_ENV=production python manage.py runserver` 10 | """ 11 | 12 | from os import environ 13 | 14 | import django_stubs_ext 15 | from split_settings.tools import include, optional 16 | 17 | # Monkeypatching Django, so stubs will work for all generics, 18 | # see: https://github.com/typeddjango/django-stubs 19 | django_stubs_ext.monkeypatch() 20 | 21 | # Managing environment via `DJANGO_ENV` variable: 22 | environ.setdefault('DJANGO_ENV', 'development') 23 | _ENV = environ['DJANGO_ENV'] 24 | 25 | _base_settings = ( 26 | 'components/common.py', 27 | 'components/logging.py', 28 | 'components/csp.py', 29 | 'components/caches.py', 30 | 31 | # Select the right env: 32 | 'environments/{0}.py'.format(_ENV), 33 | 34 | # Optionally override some settings: 35 | optional('environments/local.py'), 36 | ) 37 | 38 | # Include settings: 39 | include(*_base_settings) 40 | -------------------------------------------------------------------------------- /server/settings/components/__init__.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | 3 | from decouple import AutoConfig 4 | 5 | # Build paths inside the project like this: BASE_DIR.joinpath('some') 6 | # `pathlib` is better than writing: dirname(dirname(dirname(__file__))) 7 | BASE_DIR = Path(__file__).parent.parent.parent.parent 8 | 9 | # Loading `.env` files 10 | # See docs: https://gitlab.com/mkleehammer/autoconfig 11 | config = AutoConfig(search_path=BASE_DIR.joinpath('config')) 12 | -------------------------------------------------------------------------------- /server/settings/components/caches.py: -------------------------------------------------------------------------------- 1 | # Caching 2 | # https://docs.djangoproject.com/en/2.2/topics/cache/ 3 | 4 | CACHES = { 5 | 'default': { 6 | # TODO: use some other cache in production, 7 | # like https://github.com/jazzband/django-redis 8 | 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', 9 | }, 10 | } 11 | 12 | 13 | # django-axes 14 | # https://django-axes.readthedocs.io/en/latest/4_configuration.html#configuring-caches 15 | 16 | AXES_CACHE = 'default' 17 | -------------------------------------------------------------------------------- /server/settings/components/csp.py: -------------------------------------------------------------------------------- 1 | """ 2 | This file contains a definition for Content-Security-Policy headers. 3 | 4 | Read more about it: 5 | https://developer.mozilla.org/ru/docs/Web/HTTP/Headers/Content-Security-Policy 6 | 7 | We are using `django-csp` to provide these headers. 8 | Docs: https://github.com/mozilla/django-csp 9 | """ 10 | 11 | CSP_SCRIPT_SRC = ("'self'",) 12 | CSP_IMG_SRC = ("'self'",) 13 | CSP_FONT_SRC = ("'self'",) 14 | CSP_STYLE_SRC = ("'self'",) 15 | CSP_DEFAULT_SRC = ("'none'",) 16 | -------------------------------------------------------------------------------- /server/settings/environments/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | """Overriding settings based on the environment.""" 3 | -------------------------------------------------------------------------------- /server/settings/environments/local.py: -------------------------------------------------------------------------------- 1 | """Override any custom settings here.""" 2 | -------------------------------------------------------------------------------- /server/settings/environments/local.py.template: -------------------------------------------------------------------------------- 1 | """Override any custom settings here.""" 2 | -------------------------------------------------------------------------------- /server/templates/txt/humans.txt: -------------------------------------------------------------------------------- 1 | # The humans responsible & technology colophon 2 | # http://humanstxt.org/ 3 | 4 | 5 | ## Alan Turing Institute 6 | 7 | Team: 8 | 9 | 10 | ## Technologies 11 | 12 | Language: English 13 | Doctype: HTML5 14 | Technologies: Python, Django 15 | -------------------------------------------------------------------------------- /server/templates/txt/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /server/urls.py: -------------------------------------------------------------------------------- 1 | """ 2 | Main URL mapping configuration file. 3 | 4 | Include other URLConfs from external apps using method `include()`. 5 | 6 | It is also a good practice to keep a single URL to the root index page. 7 | 8 | This examples uses Django's default media 9 | files serving technique in development. 10 | """ 11 | 12 | from django.conf import settings 13 | from django.contrib import admin 14 | from django.contrib.admindocs import urls as admindocs_urls 15 | from django.urls import include, path 16 | from django.views.generic import TemplateView 17 | from health_check import urls as health_urls 18 | 19 | from server.apps.main import urls as main_urls 20 | from server.apps.main.views import index 21 | from server.apps.users import urls as users_urls 22 | 23 | admin.autodiscover() 24 | 25 | urlpatterns = [ 26 | # Apps: 27 | path('main/', include(main_urls, namespace='main')), 28 | path('users/', include(users_urls, namespace='users')), 29 | 30 | # Health checks: 31 | path('health/', include(health_urls)), # noqa: DJ05 32 | 33 | # django-admin: 34 | path('admin/doc/', include(admindocs_urls)), # noqa: DJ05 35 | path('admin/', admin.site.urls), 36 | 37 | # Text and xml static files: 38 | path('robots.txt', TemplateView.as_view( 39 | template_name='txt/robots.txt', 40 | content_type='text/plain', 41 | )), 42 | path('humans.txt', TemplateView.as_view( 43 | template_name='txt/humans.txt', 44 | content_type='text/plain', 45 | )), 46 | 47 | # It is a good practice to have explicit index view: 48 | path('', index, name='index'), 49 | ] 50 | 51 | # Appending url patterns for the prototype 52 | urlpatterns += [ 53 | path('openhumans/', include('openhumans.urls')), 54 | ] 55 | 56 | if settings.DEBUG: # pragma: no cover 57 | import debug_toolbar # noqa: WPS433 58 | from django.conf.urls.static import static # noqa: WPS433 59 | 60 | urlpatterns = [ 61 | # URLs specific only to django-debug-toolbar: 62 | path('__debug__/', include(debug_toolbar.urls)), # noqa: DJ05 63 | ] + urlpatterns + static( # type: ignore 64 | # Serving media files in development only: 65 | settings.MEDIA_URL, 66 | document_root=settings.MEDIA_ROOT, 67 | ) 68 | -------------------------------------------------------------------------------- /server/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for server project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'server.settings') 15 | application = get_wsgi_application() 16 | -------------------------------------------------------------------------------- /static/css/navigation_dark.css: -------------------------------------------------------------------------------- 1 | /*Navigation*/ 2 | * { 3 | font-family: 'Poppins', 'PT-Serif'; 4 | font-weight: 400; 5 | } 6 | .nav-section { 7 | padding-top: 1%; 8 | background: #F1806F; 9 | filter: saturate(80%); 10 | 11 | } 12 | 13 | .nav-content { 14 | font-weight: bold; 15 | font-size: 1.3rem; 16 | } 17 | 18 | .nav-item { 19 | padding: 0 25px; 20 | } 21 | 22 | .nav-link:hover { 23 | color:#000 !important; 24 | } 25 | -------------------------------------------------------------------------------- /static/images/alanturing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/static/images/alanturing.png -------------------------------------------------------------------------------- /static/images/animation_a.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/static/images/animation_a.jpg -------------------------------------------------------------------------------- /static/images/animation_b.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/static/images/animation_b.jpg -------------------------------------------------------------------------------- /static/images/animation_c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/static/images/animation_c.jpg -------------------------------------------------------------------------------- /static/images/animation_d.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/static/images/animation_d.jpg -------------------------------------------------------------------------------- /static/images/autistica.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alan-turing-institute/AutSPACEs/bdeee01b42d4514557687c2598a14d88f0003479/static/images/autistica.png -------------------------------------------------------------------------------- /static/images/heart-fill.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /static/images/pencil-square.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/images/pie-chart-fill.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /static/images/send.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /static/images/share-fill.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /static/images/ui-checks.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /static/js/activate-profile.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | // Activate the help popovers 3 | $('[data-toggle="popover"]').popover() 4 | 5 | // Control the visibility of a field 6 | function set_visibility(visible, field_id, instant) { 7 | duration = instant ? 0 : 200; 8 | $(field_id).prop('disabled', !visible); 9 | if (visible) { 10 | $(field_id).parent().show(duration); 11 | } 12 | else { 13 | $(field_id).parent().hide(duration); 14 | } 15 | } 16 | 17 | // Set the initial visibility 18 | set_visibility($('#id_gender').val() == 'self_identify', '#id_gender_self_identification', true) 19 | 20 | // Update the visibility when the selection changes 21 | $('#id_gender').on('change', function() { 22 | set_visibility( 23 | this.value == 'self_identify', '#id_gender_self_identification', false); 24 | } 25 | ); 26 | }); 27 | 28 | // JavaScript for disabling form submissions if there are invalid fields 29 | (function() { 30 | 'use strict'; 31 | window.addEventListener('load', function() { 32 | // Fetch all the forms we want to apply custom Bootstrap validation styles to 33 | var forms = document.getElementsByClassName('needs-validation'); 34 | // Loop over them and prevent submission 35 | var validation = Array.prototype.filter.call(forms, function(form) { 36 | form.addEventListener('submit', function(event) { 37 | if (form.checkValidity() === false) { 38 | event.preventDefault(); 39 | event.stopPropagation(); 40 | } 41 | form.classList.add('was-validated'); 42 | }, false); 43 | }); 44 | }, false); 45 | })(); -------------------------------------------------------------------------------- /static/js/main.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | function selectTheme(media) { 3 | $("html").attr("data-bs-theme", media.matches ? "dark" : "light"); 4 | } 5 | 6 | const media = window.matchMedia('(prefers-color-scheme: dark)'); 7 | selectTheme(media); 8 | media.addListener(selectTheme); 9 | }); -------------------------------------------------------------------------------- /static/js/menu-alignment.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | above = false; 3 | menu = $("#content-bar") 4 | // Determine at which viewport height the menu should move to the top 5 | threshold = menu.position().top + menu.height() + 100 6 | 7 | // Moves the menu to the top or left 8 | // set_above: true to move the menu to the top 9 | // false to move it to the left 10 | function force_above(set_above) { 11 | if (set_above) { 12 | $("#menu-container").addClass("col-lg-12").removeClass("col-lg-3") 13 | $("#text-container").addClass("col-lg-12").removeClass("col-lg-9") 14 | menu.addClass("col-lg-12").removeClass("col-lg-3") 15 | menu.css("position", "relative") 16 | } else { 17 | $("#menu-container").removeClass("col-lg-12").addClass("col-lg-3") 18 | $("#text-container").removeClass("col-lg-12").addClass("col-lg-9") 19 | menu.removeClass("col-lg-12").addClass("col-lg-3") 20 | menu.css("position", "") 21 | } 22 | above = set_above; 23 | } 24 | 25 | // Function for checking whether the menu needs to be moved 26 | function test_threshold() { 27 | height = window.innerHeight; 28 | if (height >= threshold && above) { 29 | force_above(false); 30 | } else if (height < threshold && !above) { 31 | force_above(true); 32 | } 33 | } 34 | 35 | // Call the check whenever the window is resized 36 | $(window).on("resize", function() { 37 | test_threshold(); 38 | }); 39 | 40 | // Call the check on document ready 41 | test_threshold(); 42 | }); 43 | -------------------------------------------------------------------------------- /static/js/moderation-dialogue.js: -------------------------------------------------------------------------------- 1 | $(() => { 2 | let submitModal = new bootstrap.Modal($('#submitModal').get(0)); 3 | 4 | // Attach the dialogue check to the submit button 5 | $('#submitBtn').on('click', (event) => { 6 | let moderation_status = $('#id_moderation_status').val(); 7 | let shouldShowModal = false; 8 | let text = "" 9 | let reasons = []; 10 | try { 11 | let moderation_reply = $("#id_moderation_reply").val() 12 | if (moderation_reply) { 13 | reasons = JSON.parse(moderation_reply) || [] 14 | } 15 | } catch(e) { 16 | console.log('Error parsing submitted moderation reasons JSON: ' + e.message) 17 | } 18 | let reason_count = reasons.length; 19 | let red_count = 0; 20 | reasons.forEach((item) => {if (item.severity == 'red') {red_count +=1;}}); 21 | 22 | if ((reason_count > 0) && (moderation_status == 'not reviewed')) { 23 | // The user is trying to set the story to 'not reviewed' but added moderation comments 24 | text = $('#template-text-not-reviewed-comments'); 25 | $('#closeModal').show(); 26 | $('#cancelModal,#submitForm').hide(); 27 | shouldShowModal = true; 28 | } 29 | else if ((reason_count == 0) && (moderation_status == 'rejected')) { 30 | // The user is trying reject a story without giving any reasons 31 | text = $('#template-text-reject-no-comments'); 32 | $('#closeModal').hide(); 33 | $('#cancelModal,#submitForm').show(); 34 | shouldShowModal = true; 35 | } 36 | else if ((red_count > 0) && (moderation_status == 'approved')) { 37 | // Check whether there are any "Red" reasons/ 38 | // The user is trying reject a story without giving any reasons 39 | text = $('#template-text-approve-comments'); 40 | $('#closeModal').show(); 41 | $('#cancelModal,#submitForm').hide(); 42 | shouldShowModal = true; 43 | } 44 | 45 | if (shouldShowModal) { 46 | // Show the dialogue box 47 | $('#modal-text').empty().append(text.clone().prop('content')); 48 | 49 | event.preventDefault(); 50 | submitModal.show(); 51 | } 52 | else { 53 | // Skip the dialogue box and just submit the form 54 | $('.form-context').submit(); 55 | } 56 | }); 57 | 58 | // When the submit button is clicked in the modal popup, submit the form 59 | $('#submitForm').on('click', function () { 60 | submitModal.hide(); 61 | $('.form-context').submit(); 62 | }); 63 | }); 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /static/js/registration-connections.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | // Create arrows between the steps in the diagram 3 | $('#step1').connections({ to: "#step2" }); 4 | $('#step2').connections({ to: "#step3" }); 5 | $('#step3').connections({ to: "#step4" }); 6 | $('#step4').connections({ to: "#step5" }); 7 | 8 | var c = $('connection'); 9 | 10 | // Arrange the initial arrows 11 | c.connections('update'); 12 | 13 | // Rearrange the arrows whenever the window is resized 14 | $(window).on("resize", function() { 15 | c.connections('update'); 16 | }); 17 | }); 18 | 19 | -------------------------------------------------------------------------------- /static/js/set_relationship_vis.js: -------------------------------------------------------------------------------- 1 | document.addEventListener("DOMContentLoaded", function() { 2 | change_viz(chk_radio(), 'id_authorship_relation'); 3 | check_checkbox('id_other'); 4 | } 5 | ); 6 | 7 | $(function() { 8 | $('input:radio').on('change', function() { 9 | change_viz(chk_radio(), 'id_authorship_relation'); 10 | })}); 11 | 12 | function chk_radio(){ 13 | var rb = document.querySelectorAll('input[name="first_hand_authorship"]'); 14 | if (rb[1].checked){ return true } else {return false} 15 | } 16 | 17 | function change_viz (viz, field_id) { 18 | r = document.getElementById(field_id) 19 | if (viz == true) { 20 | r.parentElement.style.visibility = ""} 21 | else { 22 | r.parentElement.style.visibility = "hidden" 23 | r.value = "" 24 | } 25 | } 26 | 27 | $("#id_other").on("keyup", function(e){ 28 | if(this.value!=""){ 29 | $("#id_other_trigger").prop("checked", "checked"); 30 | }else{ 31 | $("#id_other_trigger").prop('checked', ""); 32 | } 33 | }); 34 | 35 | function check_checkbox (field_id) { 36 | r = document.getElementById(field_id) 37 | if (r.value != "") { 38 | $("#id_other_trigger").prop("checked", "checked");} 39 | else { 40 | $("#id_other_trigger").prop("checked", ""); 41 | } 42 | } -------------------------------------------------------------------------------- /static/js/shared-stories-filtering.js: -------------------------------------------------------------------------------- 1 | let all_check = document.getElementById("all-checkbox") 2 | let trigger_array = ["abuse-checkbox", 3 | "drug-checkbox", 4 | "negbody-checkbox", 5 | "violence-checkbox", 6 | "mentalhealth-checkbox", "other-checkbox"] 7 | 8 | 9 | $(all_check).change(function(){ 10 | // If the all-trigger checkbox is checked ensure all single triggers are checked 11 | // If the all-trigger checkbox is unchecked, ensure all single triggers are unchecked 12 | if (all_check.checked == true) { 13 | for (let i = 0; i < trigger_array.length; i++) { 14 | document.getElementById(trigger_array[i]).checked = true 15 | } 16 | } else { 17 | for (let i = 0; i < trigger_array.length; i++) { 18 | document.getElementById(trigger_array[i]).checked = false 19 | } 20 | } 21 | modal(); 22 | }) 23 | 24 | $("#single_trigger_warnings :checkbox").change(function(){ 25 | // check if all the single trigger warnings are checked 26 | // if so check the "all" checkbox 27 | 28 | var all_sing = []; 29 | for (let i = 0; i < trigger_array.length; i++) { 30 | all_sing.push(document.getElementById(trigger_array[i]).checked) 31 | } 32 | 33 | if (all_sing.includes(false)) { 34 | document.getElementById("all-checkbox").checked = false 35 | } else { 36 | document.getElementById("all-checkbox").checked = true 37 | } 38 | modal(); 39 | 40 | }); 41 | 42 | document.addEventListener("DOMContentLoaded", function(event) { 43 | var scrollpos = localStorage.getItem('scrollpos'); 44 | if (scrollpos) window.scrollTo({left: 0, top: scrollpos, behavior: "instant"}); 45 | }); 46 | 47 | window.onbeforeunload = function(e) { 48 | localStorage.setItem('scrollpos', window.scrollY); 49 | }; 50 | 51 | function modal(){ 52 | $('.modal').modal('show'); 53 | setTimeout(function () { 54 | $("#search-form").submit(); 55 | //$('.modal').modal('hide'); 56 | }, 450); 57 | } 58 | 59 | document.getElementById("modalbutton").addEventListener("click", modal); -------------------------------------------------------------------------------- /static/js/store-tab.js: -------------------------------------------------------------------------------- 1 | // This file is used to store the last active tab in the browser's local storage 2 | $(function() { 3 | // generate a simple unique deterministic ID for the page 4 | const pageid = window.location.pathname.replaceAll('/','_') 5 | 6 | // when a tab is clicked 7 | $('a[data-bs-toggle="tab"]').on('shown.bs.tab', function (e) { 8 | // save the latest tab using a cookie 9 | localStorage.setItem('lastTab' + pageid, $(this).attr('id')); 10 | }); 11 | 12 | // get the last tab if it exists 13 | var lastTabStories = localStorage.getItem('lastTab' + pageid); 14 | 15 | if (lastTabStories) { 16 | $('#' + lastTabStories).tab('show'); 17 | } else { 18 | // Set the first tab to active if no active tab exists 19 | $('a[data-bs-toggle="tab"]:first').tab('show'); 20 | } 21 | }); 22 | -------------------------------------------------------------------------------- /static/js/submit-warning.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function () { 2 | let form = $('.form-context'); 3 | let submitFormButton = $('#submitForm'); 4 | let viewableCheckbox = $('#shareOnAutSPACEs'); 5 | 6 | let submitModal = new bootstrap.Modal($('#submitModal').get(0)); 7 | 8 | // Check whether Share Experience checkbox is ticked 9 | let shareExperience = () => { 10 | return viewableCheckbox.prop('checked'); 11 | }; 12 | 13 | let submitButton = $('#submitBtn'); 14 | // when submit button is clicked, check if the Share Experience checkbox is ticked, 15 | // and the story exists (uuid) and has been moderated (approved) 16 | submitButton.on('click', (event) => { 17 | const uuid = submitButton.data('uuid'); 18 | const moderation_status = submitButton.data('moderation-status'); 19 | const shouldShowModal = uuid && moderation_status === 'approved'; 20 | 21 | if (shareExperience() && shouldShowModal) { 22 | event.preventDefault(); // Prevent default button action 23 | submitModal.show(); // Show the modal if conditions are met 24 | } else { 25 | form.submit(); // Submit the form if conditions are not met 26 | } 27 | }); 28 | 29 | 30 | // When the submit button is clicked in the modal popup, submit the form 31 | submitFormButton.on('click', function () { 32 | submitModal.hide(); 33 | form.submit(); 34 | }); 35 | 36 | }); 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /static/js/theme-checker.js: -------------------------------------------------------------------------------- 1 | 2 | document.addEventListener('DOMContentLoaded', (event) => { 3 | // Check if the user has set a theme before 4 | let storedTheme = localStorage.getItem('theme'); 5 | 6 | if (storedTheme !== null) { 7 | document.body.setAttribute('data-bs-theme', storedTheme); 8 | footer.setAttribute('data-bs-theme', storedTheme); 9 | } else { 10 | // Get the system theme 11 | let systemTheme = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; 12 | document.body.setAttribute('data-bs-theme', systemTheme); 13 | footer.setAttribute('data-bs-theme', systemTheme); 14 | } 15 | }); 16 | 17 | 18 | document.getElementById('theme-toggle').addEventListener('click', function() { 19 | let currentTheme = document.body.getAttribute('data-bs-theme'); 20 | if (currentTheme === 'dark') { 21 | document.body.setAttribute('data-bs-theme', 'light'); 22 | footer.setAttribute('data-bs-theme', 'light'); 23 | localStorage.setItem('theme', 'light'); 24 | } else { 25 | document.body.setAttribute('data-bs-theme', 'dark'); 26 | footer.setAttribute('data-bs-theme', 'dark'); 27 | localStorage.setItem('theme', 'dark'); 28 | } 29 | }); 30 | -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- 1 | """ 2 | This module is used to provide configuration, fixtures, and plugins for pytest. 3 | 4 | It may be also used for extending doctest's context: 5 | 1. https://docs.python.org/3/library/doctest.html 6 | 2. https://docs.pytest.org/en/latest/doctest.html 7 | """ 8 | 9 | import pytest 10 | 11 | 12 | @pytest.fixture(autouse=True) 13 | def _media_root(settings, tmpdir_factory) -> None: 14 | """Forces django to save media files into temp folder.""" 15 | settings.MEDIA_ROOT = tmpdir_factory.mktemp('media', numbered=True) 16 | 17 | 18 | @pytest.fixture(autouse=True) 19 | def _password_hashers(settings) -> None: 20 | """Forces django to use fast password hashers for tests.""" 21 | settings.PASSWORD_HASHERS = [ 22 | 'django.contrib.auth.hashers.MD5PasswordHasher', 23 | ] 24 | 25 | 26 | @pytest.fixture(autouse=True) 27 | def _auth_backends(settings) -> None: 28 | """Deactivates security backend from Axes app.""" 29 | settings.AUTHENTICATION_BACKENDS = ( 30 | 'django.contrib.auth.backends.ModelBackend', 31 | ) 32 | 33 | 34 | @pytest.fixture(autouse=True) 35 | def _debug(settings) -> None: 36 | """Sets proper DEBUG and TEMPLATE debug mode for coverage.""" 37 | settings.DEBUG = False 38 | for template in settings.TEMPLATES: 39 | template['OPTIONS']['debug'] = True 40 | 41 | 42 | @pytest.fixture() 43 | def main_heading() -> str: 44 | """An example fixture containing some html fragment.""" 45 | return '

wemake-django-template

' 46 | -------------------------------------------------------------------------------- /tests/test_apps/test_main/test_models/test_blog_post_model.py: -------------------------------------------------------------------------------- 1 | from hypothesis import given 2 | from hypothesis.extra import django 3 | 4 | from server.apps.main.models import BlogPost 5 | 6 | 7 | class TestBlogPost(django.TestCase): 8 | """This is a property-based test that ensures model correctness.""" 9 | 10 | @given(django.from_model(BlogPost)) 11 | def test_model_properties(self, instance: BlogPost) -> None: 12 | """Tests that instance can be saved and has correct representation.""" 13 | instance.save() 14 | 15 | assert instance.id > 0 16 | assert len(str(instance)) <= 20 17 | -------------------------------------------------------------------------------- /tests/test_apps/test_main/test_models/test_migrations/test_blog_post_migrations.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from django_test_migrations.migrator import Migrator 3 | 4 | from server.apps.main.urls import app_name 5 | 6 | 7 | def test_initial0001(migrator: Migrator) -> None: 8 | """Tests the initial migration forward application.""" 9 | old_state = migrator.apply_initial_migration((app_name, None)) 10 | with pytest.raises(LookupError): 11 | # This model does not exist before this migration: 12 | old_state.apps.get_model(app_name, 'BlogPost') 13 | 14 | new_state = migrator.apply_tested_migration((app_name, '0001_initial')) 15 | model = new_state.apps.get_model(app_name, 'BlogPost') 16 | 17 | assert model.objects.create(title='test', body='some body') 18 | -------------------------------------------------------------------------------- /tests/test_apps/test_main/test_views/test_index_view.py: -------------------------------------------------------------------------------- 1 | from django.test import Client 2 | from django.urls import reverse 3 | 4 | 5 | def test_main_page(client: Client, main_heading: str) -> None: 6 | """This test ensures that main page works.""" 7 | response = client.get('/') 8 | 9 | assert response.status_code == 200 10 | assert main_heading in str(response.content) 11 | 12 | 13 | def test_hello_page(client: Client, main_heading: str) -> None: 14 | """This test ensures that hello page works.""" 15 | response = client.get(reverse('main:hello')) 16 | 17 | assert response.status_code == 200 18 | assert main_heading in str(response.content) 19 | -------------------------------------------------------------------------------- /tests/test_server/test_urls.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from django.test import Client 3 | 4 | 5 | @pytest.mark.django_db 6 | def test_health_check(client: Client) -> None: 7 | """This test ensures that health check is accessible.""" 8 | response = client.get('/health/') 9 | 10 | assert response.status_code == 200 11 | 12 | 13 | def test_admin_unauthorized(client: Client) -> None: 14 | """This test ensures that admin panel requires auth.""" 15 | response = client.get('/admin/') 16 | 17 | assert response.status_code == 302 18 | 19 | 20 | def test_admin_authorized(admin_client: Client) -> None: 21 | """This test ensures that admin panel is accessible.""" 22 | response = admin_client.get('/admin/') 23 | 24 | assert response.status_code == 200 25 | 26 | 27 | def test_admin_docs_unauthorized(client: Client) -> None: 28 | """This test ensures that admin panel docs requires auth.""" 29 | response = client.get('/admin/doc/') 30 | 31 | assert response.status_code == 302 32 | 33 | 34 | def test_admin_docs_authorized(admin_client: Client) -> None: 35 | """This test ensures that admin panel docs are accessible.""" 36 | response = admin_client.get('/admin/doc/') 37 | 38 | assert response.status_code == 200 39 | assert b'docutils' not in response.content 40 | 41 | 42 | def test_robots_txt(client: Client) -> None: 43 | """This test ensures that `robots.txt` is accessible.""" 44 | response = client.get('/robots.txt') 45 | 46 | assert response.status_code == 200 47 | assert response.get('Content-Type') == 'text/plain' 48 | 49 | 50 | def test_humans_txt(client: Client) -> None: 51 | """This test ensures that `humans.txt` is accessible.""" 52 | response = client.get('/humans.txt') 53 | 54 | assert response.status_code == 200 55 | assert response.get('Content-Type') == 'text/plain' 56 | --------------------------------------------------------------------------------