├── .coveragerc ├── .github ├── ISSUE_TEMPLATE.md ├── ISSUE_TEMPLATE │ └── NEW_FEATURES.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile.dev ├── ENVIRONMENT.md ├── MANIFEST.in ├── README.md ├── __init__.lib.py ├── __init__.py ├── docker-compose-dev.yml ├── docker-entrypoint-dev.sh ├── docker └── etc │ └── nginx │ ├── nginx.conf │ └── tola.conf ├── factories ├── __init__.py ├── django_models.py ├── formlibrary_models.py ├── indicators_models.py ├── oauth2_models.py └── workflow_models.py ├── formlibrary ├── __init__.py ├── admin.py ├── forms.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_auto_20171019_0107.py │ ├── 0003_auto_20171019_0107.py │ ├── 0004_customform_created_by.py │ ├── 0005_auto_20171204_0203.py │ ├── 0006_auto_20171206_0942.py │ ├── 0007_customform_status.py │ ├── 0008_customform_is_template.py │ ├── 0009_auto_20180514_0732.py │ ├── 0010_customform_public.py │ ├── 0011_set_customform_public.py │ ├── 0012_remove_customform_public.py │ ├── 0013_auto_20180807_0436.py │ ├── 0014_set_customform_public.py │ └── __init__.py ├── mixins.py ├── models.py ├── serializers.py ├── test.py ├── tests │ ├── __init__.py │ └── test_models.py ├── urls.py └── views.py ├── gladmap ├── Readme.md ├── __init__.py ├── admin.py ├── apps.py ├── disabled-tests.py ├── fixtures │ └── single-boundary.json ├── geo.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_auto_20190306_0136.py │ ├── 0003_auto_20190311_2249.py │ └── __init__.py ├── models.py ├── scripts │ ├── __init__.py │ ├── convert_to_geojson.py │ ├── createfixture.py │ ├── download_boundaries.py │ └── find_boundary.py ├── serializers.py ├── templates │ └── leaflet test │ │ └── src │ │ ├── Control.Draw.js │ │ ├── Leaflet.Draw.Event.js │ │ ├── Leaflet.draw.js │ │ ├── Toolbar.js │ │ ├── Tooltip.js │ │ ├── copyright.js │ │ ├── draw │ │ ├── DrawToolbar.js │ │ └── handler │ │ │ ├── Draw.Circle.js │ │ │ ├── Draw.Feature.js │ │ │ ├── Draw.Marker.js │ │ │ ├── Draw.Polygon.js │ │ │ ├── Draw.Polyline.js │ │ │ ├── Draw.Rectangle.js │ │ │ └── Draw.SimpleShape.js │ │ ├── edit │ │ ├── EditToolbar.js │ │ └── handler │ │ │ ├── Edit.Circle.js │ │ │ ├── Edit.Marker.js │ │ │ ├── Edit.Poly.js │ │ │ ├── Edit.Rectangle.js │ │ │ ├── Edit.SimpleShape.js │ │ │ ├── EditToolbar.Delete.js │ │ │ └── EditToolbar.Edit.js │ │ ├── ext │ │ ├── GeometryUtil.js │ │ ├── LatLngUtil.js │ │ ├── LineUtil.Intersect.js │ │ ├── Polygon.Intersect.js │ │ ├── Polyline.Intersect.js │ │ └── TouchEvents.js │ │ ├── images │ │ ├── spritesheet-2x.png │ │ ├── spritesheet.png │ │ └── spritesheet.svg │ │ ├── jquery.min.js │ │ └── leaflet.draw.css └── views.py ├── indicators ├── __init__.py ├── admin.py ├── export.py ├── forms.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_auto_20171019_0107.py │ ├── 0003_auto_20171101_0151.py │ ├── 0004_auto_20180204_2219.py │ ├── 0005_auto_20180211_0410.py │ ├── 0006_auto_20180226_0031.py │ ├── 0007_auto_20180423_0516.py │ ├── 0008_disaggregationvalue_indicator.py │ ├── 0009_auto_20180509_0140.py │ ├── 0010_auto_20180607_0716.py │ ├── 0011_auto_20180613_0232.py │ ├── 0012_auto_20180704_0256.py │ ├── 0013_set_all_calculation_type_to_numeric.py │ ├── 0014_tolatable_formula.py │ ├── 0015_auto_20190116_0452.py │ ├── 0016_auto_20190118_0500.py │ ├── 0017_auto_20190118_0601.py │ ├── 0018_auto_20190124_0624.py │ ├── 0019_auto_20190125_0117.py │ ├── 0020_auto_20190128_1307.py │ ├── 0021_auto_20190220_0254.py │ ├── 0022_auto_20190403_0257.py │ └── __init__.py ├── models.py ├── test_models.py ├── urls.py └── views.py ├── manage.py ├── requirements ├── base.txt ├── ci.txt ├── dev.txt ├── pkg.txt └── production.txt ├── search ├── Readme.md ├── __init__.py ├── admin.py ├── apps.py ├── exceptions.py ├── fixtures │ └── words.txt ├── jobs │ ├── __init__.py │ ├── daily │ │ └── __init__.py │ ├── hourly │ │ ├── __init__.py │ │ └── search_update.py │ ├── monthly │ │ └── __init__.py │ ├── sample.py │ ├── weekly │ │ └── __init__.py │ └── yearly │ │ └── __init__.py ├── management │ ├── __init__.py │ └── commands │ │ ├── __init__.py │ │ ├── create-dummy.py │ │ ├── search-index.py │ │ └── update-uuid.py ├── migrations │ ├── 0001_initial.py │ └── __init__.py ├── models.py ├── tests │ ├── __init__.py │ ├── test_utils.py │ └── test_views.py ├── urls.py ├── utils.py └── views.py ├── setup.py ├── tcp-port-wait.sh ├── templates ├── 400.html ├── 403.html ├── 404.html ├── 500.html ├── base.html ├── contact.html ├── customdashboard │ ├── charts │ │ ├── bar_graph.html │ │ ├── doughnut.html │ │ ├── evidence_line_donought_chart.html │ │ ├── horizontal_bar_graph.html │ │ ├── indicator_map.html │ │ ├── indicator_sparklines.html │ │ ├── line_graph_with_slider.html │ │ ├── polar.html │ │ ├── projects_map.html │ │ ├── public_Kpi_bar.html │ │ ├── public_horizontal_bar.html │ │ ├── public_indicator_pie.html │ │ ├── public_program_bar.html │ │ ├── public_radar.html │ │ └── radar.html │ ├── custom_base_layout.html │ ├── customdashboard │ │ └── visual_dashboard.html │ ├── notebook.html │ ├── program_list.html │ ├── publicdashboard │ │ ├── public_dashboard.html │ │ └── workflowlevel1_dashboard.html │ ├── publicdashboards.html │ ├── rrima_components │ │ ├── context_pane.html │ │ ├── rrima_map.html │ │ ├── rrima_notebook.html │ │ ├── sidebar_events.html │ │ ├── sidebar_gallery.html │ │ └── sidebar_news.html │ ├── rrima_dashboard.html │ ├── survey_public_dashboard.html │ └── survey_talk_public_dashboard.html ├── datepicker.html ├── dateslider.html ├── documentation.html ├── faq.html ├── feed │ ├── delete.html │ ├── json.html │ ├── list.html │ ├── stores.html │ └── xml.html ├── filefield.html ├── form_guidance.html ├── formlibrary │ ├── beneficiary_form.html │ ├── beneficiary_list.html │ ├── distribution_confirm_delete.html │ ├── distribution_form.html │ ├── distribution_list.html │ ├── filter.html │ ├── formlibrary_list.html │ ├── training_confirm_delete.html │ ├── training_list.html │ └── trainingattendance_form.html ├── formset.html ├── google_analytics.html ├── index.html ├── indicators │ ├── collected_data_report_table.html │ ├── collected_data_table.html │ ├── collecteddata_confirm_delete.html │ ├── collecteddata_form.html │ ├── collecteddata_form_modal.html │ ├── collecteddata_import.html │ ├── collecteddata_list.html │ ├── dashboard.html │ ├── data_report.html │ ├── disaggregation_print.html │ ├── disaggregation_report.html │ ├── filter.html │ ├── grid_report.html │ ├── home.html │ ├── indicator_confirm_delete.html │ ├── indicator_create.html │ ├── indicator_form.html │ ├── indicator_form_common_js.html │ ├── indicator_form_modal.html │ ├── indicator_graphs.html │ ├── indicator_list.html │ ├── report.html │ ├── site_profile_map.html │ ├── tool.html │ ├── tva_print.html │ ├── tva_report.html │ └── workflowlevel1_indicators_table.html ├── pop_up.html ├── registration │ ├── bookmark_confirm_delete.html │ ├── bookmark_form.html │ ├── bookmark_list.html │ ├── login.html │ ├── profile.html │ └── register.html ├── report_base.html ├── small_site_profile_map.html └── workflow │ ├── approval_confirm_delete.html │ ├── approval_form.html │ ├── approvalworkflow_confirm_delete.html │ ├── benchmarks_confirm_delete.html │ ├── budget_confirm_delete.html │ ├── budget_form.html │ ├── contact_confirm_delete.html │ ├── contact_form.html │ ├── contact_list.html │ ├── documentation_agreement_confirm_delete.html │ ├── documentation_confirm_delete.html │ ├── documentation_form.html │ ├── documentation_list.html │ ├── documentation_popup_form.html │ ├── documentation_popup_list.html │ ├── filter.html │ ├── import_form.html │ ├── level1dashboard_list.html │ ├── program_projects_table.html │ ├── projectdashboard_list.html │ ├── quantitativeoutputs_confirm_delete.html │ ├── quantitativeoutputs_form.html │ ├── report.html │ ├── site_indicatordata.html │ ├── site_profile_list.html │ ├── site_profile_map.html │ ├── site_profile_report.html │ ├── site_projectcomplete.html │ ├── siteprofile_confirm_delete.html │ ├── siteprofile_form.html │ ├── stakeholder_confirm_delete.html │ ├── stakeholder_form.html │ ├── stakeholder_list.html │ ├── workflowlevel1_form.html │ ├── workflowlevel1_list.html │ ├── workflowlevel2_confirm_delete.html │ ├── workflowlevel2_detail.html │ ├── workflowlevel2_form.html │ ├── workflowlevel2_import.html │ ├── workflowlevel2_list.html │ └── workflowlevel3_form.html ├── templates2 ├── 400.html ├── 403.html ├── 404.html ├── 500.html ├── base.html ├── contact.html ├── dev.html ├── feed │ ├── delete.html │ ├── json.html │ ├── list.html │ ├── stores.html │ └── xml.html ├── index.html ├── maintenance │ └── index.html ├── registration │ ├── login.html │ ├── privacy_policy.html │ ├── profile.html │ └── register.html └── unauthorized.html ├── tola ├── __init__.py ├── management │ ├── __init__.py │ └── commands │ │ ├── __init__.py │ │ ├── loadinitialdata.py │ │ ├── synctrack.py │ │ └── tests │ │ ├── __init__.py │ │ ├── test_loadinitialdata.py │ │ └── test_synctrack.py ├── pkg_testrunner.py ├── settings │ ├── __init__.py │ ├── base.py │ ├── dev.py │ ├── local.py │ ├── test.py │ └── test_pkg.py ├── tests │ ├── __init__.py │ ├── test_track_sync.py │ └── test_utils.py ├── track_sync.py ├── urls.py ├── utils.py └── wsgi.py └── workflow ├── __init__.py ├── admin.py ├── apps.py ├── migrations ├── 0001_initial.py ├── 0002_auto_20171024_0208.py ├── 0003_auto_20171101_0151.py ├── 0004_auto_20171109_0242.py ├── 0005_siteprofile_workflowlevel1.py ├── 0006_auto_20171122_0105.py ├── 0007_auto_20171204_0203.py ├── 0008_tolasites_whitelisted_domains.py ├── 0009_auto_20180109_0626.py ├── 0010_auto_20180109_0650.py ├── 0011_auto_20180110_0509.py ├── 0012_widget_changed.py ├── 0013_auto_20180122_1057.py ├── 0014_organization_oauth_domains.py ├── 0015_auto_20180214_2128.py ├── 0016_auto_20180209_0529.py ├── 0017_auto_20180226_0031.py ├── 0018_auto_20180302_0814.py ├── 0019_auto_20180309_0423.py ├── 0020_product.py ├── 0021_auto_20180323_0215.py ├── 0022_organization_allow_budget_decimal.py ├── 0023_auto_20180425_0136.py ├── 0024_auto_20180620_0537.py ├── 0025_auto_20180620_0557.py ├── 0026_organization_phone.py ├── 0027_auto_20180814_0045.py ├── 0028_auto_20180816_0141.py ├── 0029_auto_20180831_0452.py ├── 0030_auto_20180907_0704.py ├── 0031_auto_20181024_0217.py ├── 0032_auto_20181206_0228.py ├── 0033_auto_20190213_0302.py ├── 0034_dashboard_tola_user_uuid.py ├── 0034_office_organization.py ├── 0035_auto_20190226_2147.py ├── 0036_merge_20190226_2343.py ├── 0037_auto_20190306_0136.py ├── 0038_auto_20190308_0542.py ├── 0038_auto_20190311_2249.py ├── 0039_auto_20190308_0546.py ├── 0040_merge_20190312_0047.py └── __init__.py ├── models.py ├── signals.py ├── templates └── email │ └── organization │ ├── exceed_seats.html │ └── exceed_seats.txt └── tests ├── __init__.py ├── test_models.py └── test_signals.py /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | omit = 3 | manage.py 4 | */tests/* 5 | */test_* 6 | */migrations/* 7 | src/* 8 | tola/settings/* 9 | tola/wsgi.py 10 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Current behavior 2 | 3 | 4 | 5 | ### Expected behavior 6 | 7 | 8 | 9 | ### Steps to reproduce the behavior 10 | 11 | 1. 12 | 2. 13 | 3. 14 | 15 | ### Additional details 16 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/NEW_FEATURES.md: -------------------------------------------------------------------------------- 1 | ### Story 2 | 3 | 4 | 5 | ### Acceptance Criteria 6 | 7 | GIVEN 8 | WHEN 9 | THEN 10 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Purpose 2 | _Describe the problem or feature_ 3 | 4 | ## Approach 5 | _How does this change address the problem?_ 6 | 7 | ### Open Questions and Pre-Merge TODOs 8 | - [ ] Use github checklists. When solved, check the box and explain the answer. 9 | 10 | ### Furter Info 11 | _@mentions of the person or team responsible for reviewing proposed changes._ 12 | 13 | _Related ticket: #999_ 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | *.pot 3 | *.pyc 4 | # Python bytecode: 5 | *.py[co] 6 | 7 | # Packaging files: 8 | *.egg* 9 | 10 | # Editor temp files: 11 | *.swp 12 | *~ 13 | 14 | # Sphinx docs: 15 | build 16 | 17 | # SQLite3 database files: 18 | *.db 19 | 20 | # Logs: 21 | *.log 22 | 23 | #allvritualenv 24 | venv/ 25 | venv-ta/ 26 | 27 | docs/api/conf/config.json 28 | docs/api/conf/config.json/awstats.conf 29 | 30 | #Misc. 31 | .idea/ 32 | .DS_Store 33 | .coverage 34 | media/ 35 | client_secrets.json 36 | *.crt 37 | *.key 38 | error.log 39 | *.secret 40 | *.secret.yml 41 | assets/ 42 | src/ 43 | 44 | docker-compose.yml 45 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | cache: pip 3 | python: 4 | - "2.7" 5 | services: 6 | - elasticsearch 7 | - postgresql 8 | addons: 9 | postgresql: "9.6" 10 | before_script: 11 | - sleep 10 12 | - psql -c 'create database tolaactivity;' -U postgres 13 | install: 14 | - cat requirements/base.txt | grep "^Django==\|^psycopg2" | xargs pip install 15 | - pip install -r requirements/pkg.txt 16 | script: 17 | - python manage.py test --tag=pkg 18 | - pip install -r requirements/ci.txt 19 | - TOLA_DB_NAME=tolaactivity python manage.py makemigrations --check --dry-run 20 | - coverage run --source='.' manage.py test -v 2 21 | - coverage report 22 | after_success: 23 | - coveralls 24 | env: 25 | global: 26 | - TOLA_DB_ENGINE=django.db.backends.postgresql_psycopg2 27 | - TOLA_DB_NAME=test 28 | - TOLA_DB_USER=postgres 29 | - TOLA_DB_PASS= 30 | - TOLA_DB_PORT=5432 31 | - TOLA_TRACK_SYNC_ENABLED=False 32 | - ELASTICSEARCH_URL=http://127.0.0.1:9200/ 33 | - COVERALLS_REPO_TOKEN=e4x1YSoHzZd9c7lmIu880ghTMniH24YLq 34 | - DEFAULT_ORG=TolaData 35 | -------------------------------------------------------------------------------- /Dockerfile.dev: -------------------------------------------------------------------------------- 1 | FROM python:2.7 2 | 3 | WORKDIR /code 4 | 5 | COPY ./requirements/pkg.txt requirements/pkg.txt 6 | COPY ./requirements/base.txt requirements/base.txt 7 | COPY ./requirements/dev.txt requirements/dev.txt 8 | 9 | RUN pip install -r requirements/dev.txt 10 | 11 | ADD . /code 12 | 13 | ENTRYPOINT ["/code/docker-entrypoint-dev.sh"] 14 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-exclude tests * 2 | recursive-include workflow/templates *.txt *.html 3 | -------------------------------------------------------------------------------- /__init__.lib.py: -------------------------------------------------------------------------------- 1 | # DO NOT REMOVE 2 | # File necessary to install tola-activity as a lib. 3 | import os 4 | import sys 5 | 6 | sys.path.append(os.path.join(os.path.dirname(__file__))) 7 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'glind' 2 | -------------------------------------------------------------------------------- /docker-entrypoint-dev.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Migrate" 4 | python manage.py migrate 5 | 6 | echo "Creating admin user" 7 | python manage.py shell -c "from django.contrib.auth.models import User; User.objects.filter(email='admin@humanitec.com').delete(); User.objects.create_superuser('admin', 'admin@humanitec.com', 'admin')" 8 | 9 | echo "Loading basic initial data" 10 | python manage.py loadinitialdata 11 | 12 | echo "Running the server" 13 | PYTHONUNBUFFERED=1 python manage.py runserver 0.0.0.0:8080 14 | -------------------------------------------------------------------------------- /docker/etc/nginx/nginx.conf: -------------------------------------------------------------------------------- 1 | worker_processes 1; 2 | 3 | events { 4 | worker_connections 1024; 5 | } 6 | 7 | http { 8 | sendfile on; 9 | access_log off; 10 | error_log off; 11 | server_tokens off; 12 | 13 | include mime.types; 14 | 15 | server { 16 | listen 0.0.0.0:8000; 17 | 18 | location /static/ { 19 | root /code; 20 | } 21 | 22 | location = /favicon.ico { 23 | root /code/static/img; 24 | } 25 | 26 | location / { 27 | proxy_redirect off; 28 | proxy_pass_request_headers on; 29 | proxy_pass http://127.0.0.1:8888; 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /docker/etc/nginx/tola.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 8000; 3 | server_name localhost; 4 | 5 | location /static/ { 6 | autoindex off; 7 | alias /static/; 8 | } 9 | 10 | location = /favicon.ico { 11 | root /static/img; 12 | } 13 | 14 | location / { 15 | proxy_redirect off; 16 | proxy_pass_request_headers on; 17 | proxy_pass http://127.0.0.1:8080; 18 | proxy_set_header Host $host; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /factories/__init__.py: -------------------------------------------------------------------------------- 1 | # flake8: noqa 2 | from .django_models import * 3 | from .formlibrary_models import * 4 | from .indicators_models import * 5 | from .oauth2_models import * 6 | from .workflow_models import * 7 | -------------------------------------------------------------------------------- /factories/django_models.py: -------------------------------------------------------------------------------- 1 | from django.template.defaultfilters import slugify 2 | from factory import DjangoModelFactory, lazy_attribute 3 | 4 | from workflow.models import ROLE_PROGRAM_ADMIN 5 | 6 | 7 | class User(DjangoModelFactory): 8 | class Meta: 9 | model = 'auth.User' 10 | django_get_or_create = ('username',) 11 | 12 | first_name = 'Thom' 13 | last_name = 'Yorke' 14 | username = lazy_attribute(lambda o: slugify(o.first_name + '.' + 15 | o.last_name)) 16 | email = lazy_attribute(lambda o: o.username + "@testenv.com") 17 | 18 | 19 | class Group(DjangoModelFactory): 20 | class Meta: 21 | model = 'auth.Group' 22 | django_get_or_create = ('name',) 23 | 24 | name = ROLE_PROGRAM_ADMIN 25 | 26 | 27 | class Site(DjangoModelFactory): 28 | class Meta: 29 | model = 'sites.Site' 30 | django_get_or_create = ('name',) 31 | 32 | name = 'toladata.io' 33 | domain = 'toladata.io' 34 | -------------------------------------------------------------------------------- /factories/formlibrary_models.py: -------------------------------------------------------------------------------- 1 | from factory import DjangoModelFactory, post_generation, SubFactory 2 | 3 | from formlibrary.models import ( 4 | Beneficiary as BeneficiaryM, 5 | CustomForm as CustomFormM 6 | ) 7 | from .workflow_models import (Organization,) 8 | 9 | 10 | class Beneficiary(DjangoModelFactory): 11 | class Meta: 12 | model = BeneficiaryM 13 | 14 | beneficiary_name = 'Julian Lennon' 15 | father_name = 'John Lennon' 16 | 17 | @post_generation 18 | def workflowlevel1(self, create, extracted, **kwargs): 19 | if not create: 20 | # Simple build, do nothing. 21 | return 22 | 23 | if extracted: 24 | # A list of workflowlevel1 were passed in, use them 25 | for workflowlevel1 in extracted: 26 | self.workflowlevel1.add(workflowlevel1) 27 | 28 | 29 | class CustomForm(DjangoModelFactory): 30 | class Meta: 31 | model = CustomFormM 32 | 33 | name = 'Custom Form A' 34 | organization = SubFactory(Organization) 35 | public = {'org': False, 'url': False} 36 | -------------------------------------------------------------------------------- /factories/oauth2_models.py: -------------------------------------------------------------------------------- 1 | from django.utils import timezone 2 | from factory import DjangoModelFactory, SubFactory 3 | 4 | from oauth2_provider.models import ( 5 | Application as ApplicationM, 6 | Grant as GrantM 7 | ) 8 | from .django_models import User 9 | 10 | 11 | class Application(DjangoModelFactory): 12 | class Meta: 13 | model = ApplicationM 14 | 15 | client_id = 'CXGVOGFnTAt5cQW6m5AxbGrRq1lzKNSrou31dWm9' 16 | user = SubFactory(User) 17 | client_type = 'confidential' 18 | authorization_grant_type = 'authorization-code' 19 | client_secret = 'TOkNUHXShMasJzmY6aLeTey49lFvqHOcIQAhZMrc9Ax1gkSo6MUxjdRnXzfEghCwSROlj2bG6I5ksZ2D6QrYipETOqIDcrZKSm7h0wNfurxqzbIxr1F1tFbeeipkHRVC' 20 | name = 'TolaActivity' 21 | skip_authorization = False 22 | redirect_uris = 'http://testserver' 23 | 24 | 25 | class Grant(DjangoModelFactory): 26 | class Meta: 27 | model = GrantM 28 | 29 | user = SubFactory(User) 30 | code = 'stRZ5ctBN8BUlZUTmRGK1EqIgs242K' 31 | application = SubFactory(Application) 32 | scope = 'read write' 33 | expires = timezone.now() + timezone.timedelta(days=1) 34 | redirect_uri = 'http://testserver' 35 | 36 | -------------------------------------------------------------------------------- /formlibrary/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/formlibrary/__init__.py -------------------------------------------------------------------------------- /formlibrary/admin.py: -------------------------------------------------------------------------------- 1 | from .models import * 2 | 3 | admin.site.register(TrainingAttendance, TrainingAttendanceAdmin) 4 | admin.site.register(Distribution, DistributionAdmin) 5 | admin.site.register(Beneficiary, BeneficiaryAdmin) 6 | admin.site.register(FieldType, FieldTypeAdmin) 7 | admin.site.register(CustomForm, CustomFormAdmin) 8 | admin.site.register(CustomFormField, CustomFormFieldAdmin) 9 | -------------------------------------------------------------------------------- /formlibrary/migrations/0002_auto_20171019_0107.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2017-10-19 08:07 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | initial = True 12 | 13 | dependencies = [ 14 | ('formlibrary', '0001_initial'), 15 | ('indicators', '0001_initial'), 16 | ] 17 | 18 | operations = [ 19 | migrations.AddField( 20 | model_name='trainingattendance', 21 | name='disaggregation_value', 22 | field=models.ManyToManyField(blank=True, to='indicators.DisaggregationValue'), 23 | ), 24 | migrations.AddField( 25 | model_name='trainingattendance', 26 | name='training_indicator', 27 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='indicators.Indicator'), 28 | ), 29 | ] 30 | -------------------------------------------------------------------------------- /formlibrary/migrations/0004_customform_created_by.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2017-11-01 08:51 3 | from __future__ import unicode_literals 4 | 5 | from django.conf import settings 6 | from django.db import migrations, models 7 | import django.db.models.deletion 8 | 9 | 10 | class Migration(migrations.Migration): 11 | 12 | dependencies = [ 13 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 14 | ('formlibrary', '0003_auto_20171019_0107'), 15 | ] 16 | 17 | operations = [ 18 | migrations.AddField( 19 | model_name='customform', 20 | name='created_by', 21 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='customforms', to=settings.AUTH_USER_MODEL), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /formlibrary/migrations/0005_auto_20171204_0203.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2017-12-04 10:03 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('workflow', '0007_auto_20171204_0203'), 13 | ('formlibrary', '0004_customform_created_by'), 14 | ] 15 | 16 | operations = [ 17 | migrations.AddField( 18 | model_name='customform', 19 | name='form_uuid', 20 | field=models.CharField(default='', max_length=255, verbose_name='CustomForm UUID'), 21 | ), 22 | migrations.AddField( 23 | model_name='customform', 24 | name='silo_id', 25 | field=models.IntegerField(default=0), 26 | ), 27 | migrations.AddField( 28 | model_name='customform', 29 | name='workflowlevel1', 30 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='workflow.WorkflowLevel1'), 31 | ), 32 | ] 33 | -------------------------------------------------------------------------------- /formlibrary/migrations/0006_auto_20171206_0942.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2017-12-06 09:42 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | import uuid 7 | 8 | 9 | def set_form_uuid(apps, schema_editor): 10 | CustomForm = apps.get_model('formlibrary', 'CustomForm') 11 | for customform in CustomForm.objects.all(): 12 | customform.form_uuid = uuid.uuid4() 13 | customform.save() 14 | 15 | 16 | class Migration(migrations.Migration): 17 | 18 | dependencies = [ 19 | ('formlibrary', '0005_auto_20171204_0203'), 20 | ] 21 | 22 | operations = [ 23 | migrations.RunPython(set_form_uuid), 24 | migrations.AlterField( 25 | model_name='customform', 26 | name='form_uuid', 27 | field=models.CharField(default=uuid.uuid4, max_length=255, unique=True, verbose_name='CustomForm UUID'), 28 | ), 29 | ] 30 | -------------------------------------------------------------------------------- /formlibrary/migrations/0007_customform_status.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-02-26 14:14 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('formlibrary', '0006_auto_20171206_0942'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='customform', 17 | name='status', 18 | field=models.CharField(blank=True, choices=[('new', 'New'), ('published', 'Published')], default='new', max_length=15, null=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /formlibrary/migrations/0008_customform_is_template.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-05-09 13:42 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('formlibrary', '0007_customform_status'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='customform', 17 | name='is_template', 18 | field=models.BooleanField(default=0), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /formlibrary/migrations/0009_auto_20180514_0732.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-05-14 14:32 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('formlibrary', '0008_customform_is_template'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='customform', 17 | name='status', 18 | field=models.CharField(blank=True, choices=[('archived', 'Archived'), ('new', 'New'), ('published', 'Published'), ('unpublished', 'Unpublished')], default='new', max_length=15, null=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /formlibrary/migrations/0010_customform_public.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-07-24 14:02 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('formlibrary', '0009_auto_20180514_0732'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='customform', 17 | name='public', 18 | field=models.CharField(blank=True, choices=[('all', 'ALL'), ('url', 'URL')], max_length=5, null=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /formlibrary/migrations/0011_set_customform_public.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-07-24 14:02 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations 6 | from ..models import CustomForm 7 | 8 | 9 | def set_form_public(apps, schema_editor): 10 | CustomForm.objects.filter(is_public=True).update( 11 | public=CustomForm.PUBLIC_ALL) 12 | 13 | 14 | class Migration(migrations.Migration): 15 | 16 | dependencies = [ 17 | ('formlibrary', '0010_customform_public'), 18 | ] 19 | 20 | operations = [ 21 | migrations.RunPython(set_form_public), 22 | ] 23 | -------------------------------------------------------------------------------- /formlibrary/migrations/0012_remove_customform_public.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-08-06 15:08 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('formlibrary', '0011_set_customform_public'), 12 | ] 13 | 14 | operations = [ 15 | migrations.RemoveField( 16 | model_name='customform', 17 | name='public', 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /formlibrary/migrations/0013_auto_20180807_0436.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-08-07 11:36 3 | from __future__ import unicode_literals 4 | 5 | import django.contrib.postgres.fields.jsonb 6 | from django.db import migrations 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('formlibrary', '0012_remove_customform_public'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AddField( 17 | model_name='customform', 18 | name='public', 19 | field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, help_text='Public information with the structure:{org: (bool), url: (bool)}', null=True), 20 | ), 21 | migrations.AlterField( 22 | model_name='customform', 23 | name='fields', 24 | field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, null=True), 25 | ), 26 | ] 27 | -------------------------------------------------------------------------------- /formlibrary/migrations/0014_set_customform_public.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-08-07 14:02 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations 6 | from ..models import CustomForm 7 | 8 | 9 | def set_form_public(apps, schema_editor): 10 | CustomForm.objects.filter(is_public=True).update( 11 | public={'org': True, 'url': False}) 12 | 13 | 14 | class Migration(migrations.Migration): 15 | 16 | dependencies = [ 17 | ('formlibrary', '0013_auto_20180807_0436'), 18 | ] 19 | 20 | operations = [ 21 | migrations.RunPython(set_form_public), 22 | ] 23 | -------------------------------------------------------------------------------- /formlibrary/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/formlibrary/migrations/__init__.py -------------------------------------------------------------------------------- /formlibrary/mixins.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.decorators import login_required 2 | from django.http import JsonResponse 3 | from django.utils.decorators import method_decorator 4 | 5 | 6 | class LoggedInMixin(object): 7 | @method_decorator(login_required) 8 | def dispatch(self, *args, **kwargs): 9 | return super(LoggedInMixin, self).dispatch(*args, **kwargs) 10 | 11 | 12 | class AjaxableResponseMixin(object): 13 | """ 14 | Mixin to add AJAX support to a form. 15 | Must be used with an object-based FormView (e.g. CreateView) 16 | """ 17 | def form_invalid(self, form): 18 | response = super(AjaxableResponseMixin, self).form_invalid(form) 19 | if self.request.is_ajax(): 20 | return JsonResponse(form.errors, status=400) 21 | else: 22 | return response 23 | 24 | def form_valid(self, form): 25 | # We make sure to call the parent's form_valid() method because 26 | # it might do some processing (in the case of CreateView, it will 27 | # call form.save() for example). 28 | response = super(AjaxableResponseMixin, self).form_valid(form) 29 | if self.request.is_ajax(): 30 | data = { 31 | 'pk': self.object.pk, 32 | } 33 | return JsonResponse(data) 34 | else: 35 | return response 36 | -------------------------------------------------------------------------------- /formlibrary/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from formlibrary.models import BinaryField 4 | 5 | 6 | class BinaryFieldSerializer(serializers.ModelSerializer): 7 | 8 | class Meta: 9 | model = BinaryField 10 | fields = ('id', 'name') 11 | 12 | 13 | class BinaryFieldImageSerializer(serializers.ModelSerializer): 14 | 15 | class Meta: 16 | model = BinaryField 17 | fields = '__all__' 18 | 19 | -------------------------------------------------------------------------------- /formlibrary/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/formlibrary/tests/__init__.py -------------------------------------------------------------------------------- /formlibrary/tests/test_models.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from django.core.exceptions import ValidationError 3 | from django.test import TestCase, tag 4 | 5 | import factories 6 | from formlibrary.models import CustomForm 7 | 8 | 9 | @tag('pkg') 10 | class CustomFormTest(TestCase): 11 | def setUp(self): 12 | self.organization = factories.Organization() 13 | self.user = factories.User() 14 | 15 | def test_save_without_public_info(self): 16 | custom_form = CustomForm( 17 | organization=self.organization, 18 | name="Humanitec's Survey", 19 | fields="{}", 20 | public={} 21 | ) 22 | 23 | self.assertRaises(ValidationError, custom_form.save) 24 | 25 | def test_save_without_public_org_info(self): 26 | custom_form = CustomForm( 27 | organization=self.organization, 28 | name="Humanitec's Survey", 29 | fields="{}", 30 | public={'url': True} 31 | ) 32 | 33 | self.assertRaises(ValidationError, custom_form.save) 34 | 35 | def test_save_without_public_url_info(self): 36 | custom_form = CustomForm( 37 | organization=self.organization, 38 | name="Humanitec's Survey", 39 | fields="{}", 40 | public={'org': True} 41 | ) 42 | 43 | self.assertRaises(ValidationError, custom_form.save) 44 | 45 | def test_save_with_public_info(self): 46 | custom_form = CustomForm.objects.create( 47 | organization=self.organization, 48 | name="Humanitec's Survey", 49 | fields="{}", 50 | public={'org': True, 'url': True} 51 | ) 52 | 53 | self.assertEqual(custom_form.name, "Humanitec's Survey") 54 | self.assertEqual(custom_form.public, {'org': True, 'url': True}) 55 | -------------------------------------------------------------------------------- /formlibrary/urls.py: -------------------------------------------------------------------------------- 1 | from .views import * 2 | 3 | from django.conf.urls import * 4 | 5 | # place app url patterns here 6 | 7 | urlpatterns = [ 8 | 9 | url(r'^training_list/(?P\w+)/$', TrainingList.as_view(), name='training_list'), 10 | url(r'^training_objects/(?P\w+)/(?P\w+)/$', TrainingListObjects.as_view(), name='training_objects'), 11 | url(r'^training_add/(?P\w+)/$', TrainingCreate.as_view(), name='training_add'), 12 | url(r'^training_update/(?P\w+)/$', TrainingUpdate.as_view(), name='training_update'), 13 | url(r'^training_delete/(?P\w+)/$', TrainingDelete.as_view(), name='training_delete'), 14 | 15 | url(r'^beneficiary_list/(?P\w+)/$', BeneficiaryList.as_view(), name='beneficiary_list'), 16 | url(r'^beneficiary_objects/(?P\w+)/(?P\w+)/$', BeneficiaryListObjects.as_view(), name='beneficiary_objects'), 17 | url(r'^beneficiary_add/(?P\w+)/$', BeneficiaryCreate.as_view(), name='beneficiary_add'), 18 | url(r'^beneficiary_update/(?P\w+)/$', BeneficiaryUpdate.as_view(), name='beneficiary_update'), 19 | url(r'^beneficiary_delete/(?P\w+)/$', BeneficiaryDelete.as_view(), name='beneficiary_delete'), 20 | 21 | url(r'^distribution_list/(?P\w+)/$', DistributionList.as_view(), name='distribution_list'), 22 | url(r'^distribution_objects/(?P\w+)/(?P\w+)/$', DistributionListObjects.as_view(), name='distribution_list'), 23 | url(r'^distribution_add/(?P\w+)/$', DistributionCreate.as_view(), name='distribution_add'), 24 | url(r'^distribution_update/(?P\w+)/$', DistributionUpdate.as_view(), name='distribution_update'), 25 | url(r'^distribution_delete/(?P\w+)/$', DistributionDelete.as_view(), name='distribution_delete'), 26 | 27 | url(r'^getagreements/(?P\w+)/(?P\w+)/$', GetAgreements.as_view(), name='getagreements'), 28 | 29 | ] 30 | -------------------------------------------------------------------------------- /gladmap/Readme.md: -------------------------------------------------------------------------------- 1 | # GLADMap 2 | 3 | The GLADMap Django application for TolaActivity is based on the previous 4 | project ([GitHub Repo](https://github.com/toladata/GLADMap)). 5 | It has the goal to integrate Global Administrative Boundaries into Tola [GADM](http://www.gadm.org/). 6 | 7 | **This project is currently in development and incomplete.** 8 | 9 | Core of the GLADMap tool is a collection of scripts to download gadm files and convert them into GeoJSON to add them to 10 | our database. 11 | 12 | * Step 1: run `scripts/download_boundaries.py` before doing so adjust the `list_country` list to contain the required 13 | companies. 14 | * Step 2: run `scripts/convert_to_geojson.py` to convert the downloaded files and add them to the Django db 15 | 16 | ### Todo 17 | Several steps are open to make GLADMap a fully usable tool for Tola. 18 | 19 | * Re-evaluate data storage. PostGres JSON storage offers significant performance improvements compared to binary storage 20 | in postgres or mysql but it still lacks effiency when doing geographic calculations. Other systems like [PostGIS](http://postgis.net/) might offer 21 | improvement. 22 | * Improve APIs. A first implementation for some geo calculations can be found in `geo.py`. This scripts need to be improved and extended for future applications as 23 | the performance is currently not optimized. There is also an API to create new boundaries from a leaflet drawing 24 | which can be found in `views.py`. 25 | * Check frontend. A first frontend for visualizing boundaries and drawing new shapes can be found under 26 | `templates/leaflet test` -------------------------------------------------------------------------------- /gladmap/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/gladmap/__init__.py -------------------------------------------------------------------------------- /gladmap/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from .models import Boundary, Country, State 3 | 4 | # Register your models here. 5 | admin.site.register(Boundary) 6 | admin.site.register(Country) 7 | admin.site.register(State) -------------------------------------------------------------------------------- /gladmap/apps.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from django.apps import AppConfig 4 | 5 | 6 | class GladmapConfig(AppConfig): 7 | name = 'gladmap' 8 | -------------------------------------------------------------------------------- /gladmap/disabled-tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from gladmap.models import Boundary 3 | from gladmap.geo import Geo 4 | # Create your tests here. 5 | 6 | 7 | class GladmapTests(TestCase): 8 | fixtures = ['single-boundary'] 9 | 10 | def testFixtureIsLoaded(self): 11 | b = Boundary.objects.all() 12 | self.assertEqual(len(b), 1) 13 | 14 | -------------------------------------------------------------------------------- /gladmap/geo.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class Geo(): 4 | """ 5 | 6 | """ 7 | def in_boundary(self, point, geo_boundary): 8 | i=0 9 | for feature in geo_boundary["features"]: 10 | #if i > 0: continue 11 | i += 1 12 | print feature["properties"] 13 | #print feature["geometry"] 14 | print feature["geometry"]["type"] 15 | for coords in feature["geometry"]["coordinates"]: 16 | return self.in_coords(point, coords) 17 | #for geo_coord in coords: 18 | # print(geo_coord[0],geo_coord[1]) 19 | 20 | 21 | def in_coords(self, point, corners): 22 | result = False 23 | n = len(corners) 24 | if (n == 0 25 | or len(corners[0]) == 0 26 | or corners[0][0] is None 27 | or corners[0][1] is None 28 | or type(corners[0][0]) == list): 29 | return False 30 | #print type(corners[0][0]) 31 | #if type(corners[0][0]) == list: 32 | # print corners[0][0] 33 | 34 | p1x = float(corners[0][0]) 35 | p1y = float(corners[0][1]) 36 | for i in range(n + 1): 37 | p2x = float(corners[i % n][0]) 38 | p2y = float(corners[i % n][1]) 39 | if point[1] > min(p1y, p2y): 40 | if point[0] <= max(p1x, p2x): 41 | if p1y != p2y: 42 | xinters = (point[1] - p1y) * (p2x - p1x) / (p2y - p1y) + p1x 43 | if p1x == p2x or point[0] <= xinters: 44 | result = not result 45 | p1x, p1y = p2x, p2y 46 | return result 47 | -------------------------------------------------------------------------------- /gladmap/migrations/0002_auto_20190306_0136.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.17 on 2019-03-06 09:36 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('gladmap', '0001_initial'), 12 | ] 13 | 14 | operations = [] 15 | 16 | -------------------------------------------------------------------------------- /gladmap/migrations/0003_auto_20190311_2249.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.17 on 2019-03-12 05:49 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('gladmap', '0002_auto_20190306_0136'), 12 | ] 13 | 14 | operations = [ 15 | migrations.RemoveField( 16 | model_name='feature', 17 | name='b_id', 18 | ), 19 | migrations.DeleteModel( 20 | name='Feature', 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /gladmap/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/gladmap/migrations/__init__.py -------------------------------------------------------------------------------- /gladmap/models.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from django.db import models 4 | from django.contrib.postgres.fields import JSONField 5 | 6 | class Boundary(models.Model): 7 | geo_json = JSONField() 8 | country = models.CharField(max_length=100, default="None") 9 | level = models.IntegerField(default=0) 10 | 11 | def __str__(self): 12 | return self.country+" "+str(self.level) 13 | 14 | 15 | class Country(models.Model): 16 | boundary = JSONField() # level 0 boundary geojson 17 | code = models.CharField(max_length=100, default="None", unique=True) # DEU, USA, AFG etc 18 | 19 | def __str__(self): 20 | return self.code 21 | 22 | 23 | class State(models.Model): 24 | boundary = JSONField() # level 1 boundary geojson 25 | name = models.CharField(max_length=150, default="None") # Hessen, Florida, Kunduz 26 | code = models.CharField(max_length=100, default="None", unique=True) # AF.KD, DE.HE 27 | country = models.ForeignKey(Country, on_delete=models.CASCADE) 28 | 29 | def __str__(self): 30 | return self.name.encode('ascii', 'ignore').decode('ascii') + " " + self.code 31 | -------------------------------------------------------------------------------- /gladmap/scripts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/gladmap/scripts/__init__.py -------------------------------------------------------------------------------- /gladmap/scripts/createfixture.py: -------------------------------------------------------------------------------- 1 | from django.core import serializers 2 | from gladmap.models import Boundary 3 | 4 | def run(): 5 | data = serializers.serialize("json", Boundary.objects.all().filter(id=1)) 6 | 7 | out = open("gladmap/fixtures/single-boundary.json", "w") 8 | out.write(data) 9 | out.close() 10 | -------------------------------------------------------------------------------- /gladmap/scripts/find_boundary.py: -------------------------------------------------------------------------------- 1 | """ 2 | converts all .shp in ./tmp/ to geojson and places it in data directory 3 | Example command - ogr2ogr -f "GeoJSON" ../../AFG_adm2.json AFG_adm2.shp 4 | """ 5 | import django.db 6 | from gladmap.models import Boundary 7 | 8 | cursor = django.db.connection.cursor() 9 | geo_data_dir = "/home/leon/projects/Pycharm/TolaActivity/gladmap/tmp/" 10 | ## {0} -> destination geojson {1} - source shape 11 | cmd_template = 'ogr2ogr -f "GeoJSON" {0} {1}' 12 | 13 | def run(): 14 | print("Finding Boundary test") 15 | country = "SSD" 16 | gadm = Boundary.objects.all().filter(country=country) 17 | print gadm.count() 18 | #print type(gadm[0].geo_json) 19 | gj = gadm[0].geo_json 20 | #print(gj) 21 | i = 0 22 | for feature in gj["features"]: 23 | if i > 0: continue 24 | i += 1 25 | print feature["properties"] 26 | #print feature["geometry"] 27 | print feature["geometry"]["type"] 28 | for coords in feature["geometry"]["coordinates"]: 29 | print len(coords) 30 | print in_coords((32.0622291564942, 5.211561203002987), coords) 31 | #for geo_coord in coords: 32 | # print(geo_coord[0],geo_coord[1]) 33 | 34 | def in_coords(point, corners): 35 | result = False 36 | n = len(corners) 37 | p1x = float(corners[0][0]) 38 | p1y = float(corners[0][1]) 39 | for i in range(n + 1): 40 | p2x = float(corners[i % n][0]) 41 | p2y = float(corners[i % n][1]) 42 | if point[1] > min(p1y, p2y): 43 | if point[0] <= max(p1x, p2x): 44 | if p1y != p2y: 45 | xinters = (point[1] - p1y) * (p2x - p1x) / (p2y - p1y) + p1x 46 | if p1x == p2x or point[0] <= xinters: 47 | result = not result 48 | p1x, p1y = p2x, p2y 49 | return result 50 | 51 | 52 | -------------------------------------------------------------------------------- /gladmap/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | from models import Boundary, Country, State 3 | 4 | 5 | class BoundarySerializer(serializers.HyperlinkedModelSerializer): 6 | 7 | class Meta: 8 | model = Boundary 9 | fields = '__all__' 10 | 11 | 12 | class BoundaryListSerializer(serializers.HyperlinkedModelSerializer): 13 | 14 | class Meta: 15 | model = Boundary 16 | fields = ('url','country','level') 17 | 18 | 19 | class CountrySerializer(serializers.HyperlinkedModelSerializer): 20 | class Meta: 21 | model = Country 22 | fields = '__all__' 23 | 24 | 25 | class CountryListSerializer(serializers.HyperlinkedModelSerializer): 26 | class Meta: 27 | model = Country 28 | fields = ('url','code') 29 | 30 | 31 | class StateSerializer(serializers.HyperlinkedModelSerializer): 32 | class Meta: 33 | model = State 34 | fields = '__all__' 35 | 36 | 37 | class StateListSerializer(serializers.HyperlinkedModelSerializer): 38 | class Meta: 39 | model = State 40 | fields = ('name', 'code', 'country', 'url') 41 | 42 | -------------------------------------------------------------------------------- /gladmap/templates/leaflet test/src/copyright.js: -------------------------------------------------------------------------------- 1 | /* 2 | Leaflet.draw {VERSION}, a plugin that adds drawing and editing tools to Leaflet powered maps. 3 | (c) 2012-2017, Jacob Toye, Jon West, Smartrak, Leaflet 4 | 5 | https://github.com/Leaflet/Leaflet.draw 6 | http://leafletjs.com 7 | */ 8 | -------------------------------------------------------------------------------- /gladmap/templates/leaflet test/src/draw/handler/Draw.Rectangle.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @class L.Draw.Rectangle 3 | * @aka Draw.Rectangle 4 | * @inherits L.Draw.SimpleShape 5 | */ 6 | L.Draw.Rectangle = L.Draw.SimpleShape.extend({ 7 | statics: { 8 | TYPE: 'rectangle' 9 | }, 10 | 11 | options: { 12 | shapeOptions: { 13 | stroke: true, 14 | color: '#3388ff', 15 | weight: 4, 16 | opacity: 0.5, 17 | fill: true, 18 | fillColor: null, //same as color by default 19 | fillOpacity: 0.2, 20 | showArea: true, 21 | clickable: true 22 | }, 23 | metric: true // Whether to use the metric measurement system or imperial 24 | }, 25 | 26 | // @method initialize(): void 27 | initialize: function (map, options) { 28 | // Save the type so super can fire, need to do this as cannot do this.TYPE :( 29 | this.type = L.Draw.Rectangle.TYPE; 30 | 31 | this._initialLabelText = L.drawLocal.draw.handlers.rectangle.tooltip.start; 32 | 33 | L.Draw.SimpleShape.prototype.initialize.call(this, map, options); 34 | }, 35 | 36 | _drawShape: function (latlng) { 37 | if (!this._shape) { 38 | this._shape = new L.Rectangle(new L.LatLngBounds(this._startLatLng, latlng), this.options.shapeOptions); 39 | this._map.addLayer(this._shape); 40 | } else { 41 | this._shape.setBounds(new L.LatLngBounds(this._startLatLng, latlng)); 42 | } 43 | }, 44 | 45 | _fireCreatedEvent: function () { 46 | var rectangle = new L.Rectangle(this._shape.getBounds(), this.options.shapeOptions); 47 | L.Draw.SimpleShape.prototype._fireCreatedEvent.call(this, rectangle); 48 | }, 49 | 50 | _getTooltipText: function () { 51 | var tooltipText = L.Draw.SimpleShape.prototype._getTooltipText.call(this), 52 | shape = this._shape, 53 | showArea = this.options.showArea, 54 | latLngs, area, subtext; 55 | 56 | if (shape) { 57 | latLngs = this._shape._defaultShape ? this._shape._defaultShape() : this._shape.getLatLngs(); 58 | area = L.GeometryUtil.geodesicArea(latLngs); 59 | subtext = showArea ? L.GeometryUtil.readableArea(area, this.options.metric) : '' 60 | } 61 | 62 | return { 63 | text: tooltipText.text, 64 | subtext: subtext 65 | }; 66 | } 67 | }); 68 | -------------------------------------------------------------------------------- /gladmap/templates/leaflet test/src/edit/handler/Edit.Circle.js: -------------------------------------------------------------------------------- 1 | L.Edit = L.Edit || {}; 2 | /** 3 | * @class L.Edit.Circle 4 | * @aka Edit.Circle 5 | * @inherits L.Edit.SimpleShape 6 | */ 7 | L.Edit.Circle = L.Edit.SimpleShape.extend({ 8 | _createMoveMarker: function () { 9 | var center = this._shape.getLatLng(); 10 | 11 | this._moveMarker = this._createMarker(center, this.options.moveIcon); 12 | }, 13 | 14 | _createResizeMarker: function () { 15 | var center = this._shape.getLatLng(), 16 | resizemarkerPoint = this._getResizeMarkerPoint(center); 17 | 18 | this._resizeMarkers = []; 19 | this._resizeMarkers.push(this._createMarker(resizemarkerPoint, this.options.resizeIcon)); 20 | }, 21 | 22 | _getResizeMarkerPoint: function (latlng) { 23 | // From L.shape.getBounds() 24 | var delta = this._shape._radius * Math.cos(Math.PI / 4), 25 | point = this._map.project(latlng); 26 | return this._map.unproject([point.x + delta, point.y - delta]); 27 | }, 28 | 29 | _move: function (latlng) { 30 | var resizemarkerPoint = this._getResizeMarkerPoint(latlng); 31 | 32 | // Move the resize marker 33 | this._resizeMarkers[0].setLatLng(resizemarkerPoint); 34 | 35 | // Move the circle 36 | this._shape.setLatLng(latlng); 37 | 38 | this._map.fire(L.Draw.Event.EDITMOVE, { layer: this._shape }); 39 | }, 40 | 41 | _resize: function (latlng) { 42 | var moveLatLng = this._moveMarker.getLatLng(), 43 | radius = moveLatLng.distanceTo(latlng); 44 | 45 | this._shape.setRadius(radius); 46 | 47 | this._map.fire(L.Draw.Event.EDITRESIZE, { layer: this._shape }); 48 | } 49 | }); 50 | 51 | L.Circle.addInitHook(function () { 52 | if (L.Edit.Circle) { 53 | this.editing = new L.Edit.Circle(this); 54 | 55 | if (this.options.editable) { 56 | this.editing.enable(); 57 | } 58 | } 59 | 60 | this.on('add', function () { 61 | if (this.editing && this.editing.enabled()) { 62 | this.editing.addHooks(); 63 | } 64 | }); 65 | 66 | this.on('remove', function () { 67 | if (this.editing && this.editing.enabled()) { 68 | this.editing.removeHooks(); 69 | } 70 | }); 71 | }); -------------------------------------------------------------------------------- /gladmap/templates/leaflet test/src/ext/LatLngUtil.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @class L.LatLngUtil 3 | * @aka LatLngUtil 4 | */ 5 | L.LatLngUtil = { 6 | // Clones a LatLngs[], returns [][] 7 | 8 | // @method cloneLatLngs(LatLngs[]): L.LatLngs[] 9 | // Clone the latLng point or points or nested points and return an array with those points 10 | cloneLatLngs: function (latlngs) { 11 | var clone = []; 12 | for (var i = 0, l = latlngs.length; i < l; i++) { 13 | // Check for nested array (Polyline/Polygon) 14 | if (Array.isArray(latlngs[i])) { 15 | clone.push(L.LatLngUtil.cloneLatLngs(latlngs[i])); 16 | } else { 17 | clone.push(this.cloneLatLng(latlngs[i])); 18 | } 19 | } 20 | return clone; 21 | }, 22 | 23 | // @method cloneLatLng(LatLng): L.LatLng 24 | // Clone the latLng and return a new LatLng object. 25 | cloneLatLng: function (latlng) { 26 | return L.latLng(latlng.lat, latlng.lng); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /gladmap/templates/leaflet test/src/ext/LineUtil.Intersect.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @class L.LineUtil 3 | * @aka Util 4 | * @aka L.Utils 5 | */ 6 | L.Util.extend(L.LineUtil, { 7 | 8 | // @method segmentsIntersect(): boolean 9 | // Checks to see if two line segments intersect. Does not handle degenerate cases. 10 | // http://compgeom.cs.uiuc.edu/~jeffe/teaching/373/notes/x06-sweepline.pdf 11 | segmentsIntersect: function (/*Point*/ p, /*Point*/ p1, /*Point*/ p2, /*Point*/ p3) { 12 | return this._checkCounterclockwise(p, p2, p3) !== 13 | this._checkCounterclockwise(p1, p2, p3) && 14 | this._checkCounterclockwise(p, p1, p2) !== 15 | this._checkCounterclockwise(p, p1, p3); 16 | }, 17 | 18 | // check to see if points are in counterclockwise order 19 | _checkCounterclockwise: function (/*Point*/ p, /*Point*/ p1, /*Point*/ p2) { 20 | return (p2.y - p.y) * (p1.x - p.x) > (p1.y - p.y) * (p2.x - p.x); 21 | } 22 | }); -------------------------------------------------------------------------------- /gladmap/templates/leaflet test/src/ext/Polygon.Intersect.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @class L.Polygon 3 | * @aka Polygon 4 | */ 5 | L.Polygon.include({ 6 | 7 | // @method intersects(): boolean 8 | // Checks a polygon for any intersecting line segments. Ignores holes. 9 | intersects: function () { 10 | var polylineIntersects, 11 | points = this._getProjectedPoints(), 12 | len, firstPoint, lastPoint, maxIndex; 13 | 14 | if (this._tooFewPointsForIntersection()) { 15 | return false; 16 | } 17 | 18 | polylineIntersects = L.Polyline.prototype.intersects.call(this); 19 | 20 | // If already found an intersection don't need to check for any more. 21 | if (polylineIntersects) { 22 | return true; 23 | } 24 | 25 | len = points.length; 26 | firstPoint = points[0]; 27 | lastPoint = points[len - 1]; 28 | maxIndex = len - 2; 29 | 30 | // Check the line segment between last and first point. Don't need to check the first line segment (minIndex = 1) 31 | return this._lineSegmentsIntersectsRange(lastPoint, firstPoint, maxIndex, 1); 32 | } 33 | }); 34 | -------------------------------------------------------------------------------- /gladmap/templates/leaflet test/src/images/spritesheet-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/gladmap/templates/leaflet test/src/images/spritesheet-2x.png -------------------------------------------------------------------------------- /gladmap/templates/leaflet test/src/images/spritesheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/gladmap/templates/leaflet test/src/images/spritesheet.png -------------------------------------------------------------------------------- /gladmap/templates/leaflet test/src/images/spritesheet.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /indicators/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/indicators/__init__.py -------------------------------------------------------------------------------- /indicators/migrations/0003_auto_20171101_0151.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2017-11-01 08:51 3 | from __future__ import unicode_literals 4 | 5 | from django.conf import settings 6 | from django.db import migrations, models 7 | import django.db.models.deletion 8 | 9 | 10 | class Migration(migrations.Migration): 11 | 12 | dependencies = [ 13 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 14 | ('indicators', '0002_auto_20171019_0107'), 15 | ] 16 | 17 | operations = [ 18 | migrations.AddField( 19 | model_name='collecteddata', 20 | name='created_by', 21 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='collecteddata', to=settings.AUTH_USER_MODEL), 22 | ), 23 | migrations.AddField( 24 | model_name='historicalcollecteddata', 25 | name='created_by', 26 | field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to=settings.AUTH_USER_MODEL), 27 | ), 28 | migrations.AddField( 29 | model_name='historicalindicator', 30 | name='created_by', 31 | field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to=settings.AUTH_USER_MODEL), 32 | ), 33 | migrations.AddField( 34 | model_name='indicator', 35 | name='created_by', 36 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='indicators', to=settings.AUTH_USER_MODEL), 37 | ), 38 | migrations.AddField( 39 | model_name='level', 40 | name='created_by', 41 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='levels', to=settings.AUTH_USER_MODEL), 42 | ), 43 | migrations.AddField( 44 | model_name='objective', 45 | name='created_by', 46 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='objectives', to=settings.AUTH_USER_MODEL), 47 | ), 48 | ] 49 | -------------------------------------------------------------------------------- /indicators/migrations/0004_auto_20180204_2219.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-02-05 06:19 3 | from __future__ import unicode_literals 4 | 5 | from decimal import Decimal 6 | from django.db import migrations, models 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('indicators', '0003_auto_20171101_0151'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterField( 17 | model_name='historicalindicator', 18 | name='lop_target', 19 | field=models.DecimalField(blank=True, decimal_places=2, default=Decimal('0.00'), max_digits=20, verbose_name=b'LOP Target'), 20 | ), 21 | migrations.AlterField( 22 | model_name='indicator', 23 | name='lop_target', 24 | field=models.DecimalField(blank=True, decimal_places=2, default=Decimal('0.00'), max_digits=20, verbose_name=b'LOP Target'), 25 | ), 26 | ] 27 | -------------------------------------------------------------------------------- /indicators/migrations/0006_auto_20180226_0031.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-02-26 08:31 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('indicators', '0005_auto_20180211_0410'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterField( 17 | model_name='collecteddata', 18 | name='description', 19 | field=models.TextField(blank=True, help_text=b'How was this data collected', null=True, verbose_name=b'Remarks/comments'), 20 | ), 21 | migrations.AlterField( 22 | model_name='collecteddata', 23 | name='periodic_target', 24 | field=models.ForeignKey(blank=True, help_text=b'Relate this collection to a periodic target', null=True, on_delete=django.db.models.deletion.CASCADE, to='indicators.PeriodicTarget'), 25 | ), 26 | migrations.AlterField( 27 | model_name='historicalcollecteddata', 28 | name='description', 29 | field=models.TextField(blank=True, help_text=b'How was this data collected', null=True, verbose_name=b'Remarks/comments'), 30 | ), 31 | migrations.AlterField( 32 | model_name='indicator', 33 | name='indicator_type', 34 | field=models.ManyToManyField(blank=True, help_text=b'If indicator was pulled from a service select one here', to='indicators.IndicatorType'), 35 | ), 36 | migrations.AlterField( 37 | model_name='indicator', 38 | name='workflowlevel1', 39 | field=models.ManyToManyField(help_text=b'Related workflowlevel1 or project/program etc.', to='workflow.WorkflowLevel1'), 40 | ), 41 | ] 42 | -------------------------------------------------------------------------------- /indicators/migrations/0007_auto_20180423_0516.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-04-23 12:16 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('indicators', '0006_auto_20180226_0031'), 12 | ] 13 | 14 | operations = [ 15 | migrations.RemoveField( 16 | model_name='disaggregationtype', 17 | name='default_global', 18 | ), 19 | migrations.RemoveField( 20 | model_name='disaggregationtype', 21 | name='standard', 22 | ), 23 | migrations.AddField( 24 | model_name='disaggregationtype', 25 | name='availability', 26 | field=models.CharField(blank=True, choices=[(b'org', b'Organization Level'), (b'wfl1', b'Only for this WFL1')], max_length=5, null=True), 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /indicators/migrations/0008_disaggregationvalue_indicator.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-05-07 12:38 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('indicators', '0007_auto_20180423_0516'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AddField( 17 | model_name='disaggregationvalue', 18 | name='indicator', 19 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='indicators.Indicator'), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /indicators/migrations/0009_auto_20180509_0140.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-05-09 08:40 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('indicators', '0008_disaggregationvalue_indicator'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterField( 17 | model_name='disaggregationlabel', 18 | name='disaggregation_type', 19 | field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='indicators.DisaggregationType'), 20 | ), 21 | migrations.AlterField( 22 | model_name='disaggregationvalue', 23 | name='disaggregation_label', 24 | field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='indicators.DisaggregationLabel'), 25 | ), 26 | ] 27 | -------------------------------------------------------------------------------- /indicators/migrations/0010_auto_20180607_0716.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-06-07 14:16 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('indicators', '0009_auto_20180509_0140'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='historicalindicator', 17 | name='actual_formula', 18 | field=models.CharField(blank=True, choices=[(b'average', b'Average'), (b'user_defined', b'User defined')], max_length=15, null=True), 19 | ), 20 | migrations.AddField( 21 | model_name='historicalindicator', 22 | name='calculation_type', 23 | field=models.CharField(blank=True, choices=[(b'numeric', b'Numeric'), (b'percentage', b'Percentage')], max_length=15, null=True), 24 | ), 25 | migrations.AddField( 26 | model_name='historicalindicator', 27 | name='direction', 28 | field=models.CharField(blank=True, choices=[(b'increasing', b'Increasing'), (b'decreasing', b'Decreasing')], max_length=15, null=True), 29 | ), 30 | migrations.AddField( 31 | model_name='indicator', 32 | name='actual_formula', 33 | field=models.CharField(blank=True, choices=[(b'average', b'Average'), (b'user_defined', b'User defined')], max_length=15, null=True), 34 | ), 35 | migrations.AddField( 36 | model_name='indicator', 37 | name='calculation_type', 38 | field=models.CharField(blank=True, choices=[(b'numeric', b'Numeric'), (b'percentage', b'Percentage')], max_length=15, null=True), 39 | ), 40 | migrations.AddField( 41 | model_name='indicator', 42 | name='direction', 43 | field=models.CharField(blank=True, choices=[(b'increasing', b'Increasing'), (b'decreasing', b'Decreasing')], max_length=15, null=True), 44 | ), 45 | ] 46 | -------------------------------------------------------------------------------- /indicators/migrations/0011_auto_20180613_0232.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-06-13 09:32 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('indicators', '0010_auto_20180607_0716'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AddField( 17 | model_name='historicalindicator', 18 | name='total_actual', 19 | field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='indicators.CollectedData'), 20 | ), 21 | migrations.AddField( 22 | model_name='indicator', 23 | name='total_actual', 24 | field=models.ForeignKey(blank=True, help_text=b'The collected data selected to be used in the actual formula', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='indicator_total_actual', to='indicators.CollectedData', verbose_name=b'Total Actual'), 25 | ), 26 | ] 27 | -------------------------------------------------------------------------------- /indicators/migrations/0012_auto_20180704_0256.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-07-04 09:56 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('workflow', '0025_auto_20180620_0557'), 13 | ('indicators', '0011_auto_20180613_0232'), 14 | ] 15 | 16 | operations = [ 17 | migrations.RemoveField( 18 | model_name='reportingperiod', 19 | name='frequency', 20 | ), 21 | migrations.RemoveField( 22 | model_name='reportingperiod', 23 | name='organization', 24 | ), 25 | migrations.AddField( 26 | model_name='reportingperiod', 27 | name='period', 28 | field=models.CharField(blank=True, help_text=b'Predefined reporting period for a workflowlevel1', max_length=255, null=True), 29 | ), 30 | migrations.AddField( 31 | model_name='reportingperiod', 32 | name='sort', 33 | field=models.IntegerField(blank=True, null=True), 34 | ), 35 | migrations.AddField( 36 | model_name='reportingperiod', 37 | name='workflowlevel1', 38 | field=models.ForeignKey(blank=True, help_text=b'Related workflowlevel1 or project/program etc.', null=True, on_delete=django.db.models.deletion.CASCADE, to='workflow.WorkflowLevel1'), 39 | ), 40 | ] 41 | -------------------------------------------------------------------------------- /indicators/migrations/0013_set_all_calculation_type_to_numeric.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-07-04 09:56 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations 6 | from ..models import Indicator 7 | 8 | 9 | def set_calculation_type(apps, schema_editor): 10 | Indicator.objects.all().update( 11 | calculation_type=Indicator.CALC_TYPE_NUMERIC) 12 | 13 | 14 | class Migration(migrations.Migration): 15 | 16 | dependencies = [ 17 | ('indicators', '0012_auto_20180704_0256'), 18 | ] 19 | 20 | operations = [ 21 | migrations.RunPython(set_calculation_type), 22 | ] 23 | -------------------------------------------------------------------------------- /indicators/migrations/0014_tolatable_formula.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-08-27 12:15 3 | from __future__ import unicode_literals 4 | 5 | import django.contrib.postgres.fields.jsonb 6 | from django.db import migrations 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('indicators', '0013_set_all_calculation_type_to_numeric'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AddField( 17 | model_name='tolatable', 18 | name='formula', 19 | field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, null=True), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /indicators/migrations/0016_auto_20190118_0500.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.17 on 2019-01-18 13:00 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('indicators', '0015_auto_20190116_0452'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='historicalindicator', 17 | name='actual_formula', 18 | field=models.CharField(blank=True, max_length=15, null=True), 19 | ), 20 | migrations.AlterField( 21 | model_name='indicator', 22 | name='actual_formula', 23 | field=models.CharField(blank=True, max_length=15, null=True), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /indicators/migrations/0017_auto_20190118_0601.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.17 on 2019-01-18 14:01 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('indicators', '0016_auto_20190118_0500'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='historicalindicator', 17 | name='actuals', 18 | field=models.DecimalField(blank=True, decimal_places=2, help_text=b'Sum of collected datas achieved', max_digits=20, null=True), 19 | ), 20 | migrations.AddField( 21 | model_name='indicator', 22 | name='actuals', 23 | field=models.DecimalField(blank=True, decimal_places=2, help_text=b'Sum of collected datas achieved', max_digits=20, null=True), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /indicators/migrations/0018_auto_20190124_0624.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.17 on 2019-01-24 14:24 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('indicators', '0017_auto_20190118_0601'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='disaggregationvalue', 17 | name='column_name', 18 | field=models.CharField(blank=True, max_length=24), 19 | ), 20 | migrations.AddField( 21 | model_name='disaggregationvalue', 22 | name='column_value', 23 | field=models.CharField(blank=True, max_length=24), 24 | ), 25 | migrations.AddField( 26 | model_name='disaggregationvalue', 27 | name='table_uuid', 28 | field=models.CharField(blank=True, max_length=36), 29 | ), 30 | ] 31 | -------------------------------------------------------------------------------- /indicators/migrations/0019_auto_20190125_0117.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.17 on 2019-01-25 09:17 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('indicators', '0018_auto_20190124_0624'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='collecteddata', 17 | name='cell_value', 18 | field=models.CharField(blank=True, max_length=24, null=True), 19 | ), 20 | migrations.AddField( 21 | model_name='historicalcollecteddata', 22 | name='cell_value', 23 | field=models.CharField(blank=True, max_length=24, null=True), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /indicators/migrations/0020_auto_20190128_1307.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.17 on 2019-01-28 21:07 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('indicators', '0019_auto_20190125_0117'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='collecteddata', 17 | name='evidence_url', 18 | field=models.CharField(blank=True, help_text=b'Evidence Document url', max_length=255, null=True, verbose_name=b'Evidence Document url'), 19 | ), 20 | migrations.AddField( 21 | model_name='historicalcollecteddata', 22 | name='evidence_url', 23 | field=models.CharField(blank=True, help_text=b'Evidence Document url', max_length=255, null=True, verbose_name=b'Evidence Document url'), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /indicators/migrations/0022_auto_20190403_0257.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.17 on 2019-04-03 09:57 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('indicators', '0021_auto_20190220_0254'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='disaggregationvalue', 17 | name='value', 18 | field=models.CharField(blank=True, max_length=765, null=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /indicators/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/indicators/migrations/__init__.py -------------------------------------------------------------------------------- /indicators/test_models.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase, tag 2 | 3 | from indicators.models import Level 4 | from workflow.models import WorkflowLevel1, Organization 5 | 6 | 7 | @tag('pkg') 8 | class LevelModelTest(TestCase): 9 | def test_save_level_org_same_as_wflvl1(self): 10 | self.wflvl1 = WorkflowLevel1.objects.create(name='WorkflowLevel1') 11 | self.organization = Organization.objects.create(name='Org') 12 | org = Organization.objects.first() 13 | self.wflvl1.organization = self.organization 14 | self.wflvl1.save() 15 | level = Level.objects.create(name='TestIndicator', workflowlevel1=self.wflvl1) 16 | level.save() 17 | self.assertEqual(level.organization, self.organization) 18 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | if 'test' in sys.argv and '--tag=pkg' in sys.argv: 7 | settings = 'tola.settings.test_pkg' 8 | os.environ['DJANGO_SETTINGS_MODULE'] = settings 9 | elif 'test' in sys.argv: 10 | settings = 'tola.settings.test' 11 | os.environ['DJANGO_SETTINGS_MODULE'] = settings 12 | elif os.environ.get("DJANGO_SETTINGS_MODULE"): 13 | settings = os.environ.get("DJANGO_SETTINGS_MODULE") 14 | else: 15 | settings = 'tola.settings.local' 16 | 17 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", settings) 18 | 19 | from django.core.management import execute_from_command_line 20 | 21 | execute_from_command_line(sys.argv) 22 | -------------------------------------------------------------------------------- /requirements/base.txt: -------------------------------------------------------------------------------- 1 | Django==1.11.17 2 | djangorestframework==3.6.3 3 | psycopg2>=2.7,<=2.8 4 | git+https://github.com/toladata/social-core#egg=social-core 5 | social-auth-app-django==1.2.0 6 | -r pkg.txt 7 | -------------------------------------------------------------------------------- /requirements/ci.txt: -------------------------------------------------------------------------------- 1 | -r base.txt 2 | 3 | coveralls==1.2.0 4 | mock==2.0.0 5 | -------------------------------------------------------------------------------- /requirements/dev.txt: -------------------------------------------------------------------------------- 1 | -r base.txt 2 | 3 | flake8==3.5.0 4 | mock==2.0.0 5 | vulture==0.26 6 | -------------------------------------------------------------------------------- /requirements/pkg.txt: -------------------------------------------------------------------------------- 1 | django_admin_report==0.4 2 | django-import-export==0.5.1 3 | django-oauth-toolkit==1.1.2 4 | django-simple-history==1.9.0 5 | elasticsearch==5.4.0 6 | factory_boy==2.9.2 7 | urllib3>1.22<1.3 8 | voluptuous==0.11.1 9 | chargebee>=2,<3 10 | -------------------------------------------------------------------------------- /requirements/production.txt: -------------------------------------------------------------------------------- 1 | -r base.txt 2 | gunicorn==19.7.1 3 | -------------------------------------------------------------------------------- /search/Readme.md: -------------------------------------------------------------------------------- 1 | # Search 2 | 3 | ### Configuration 4 | 5 | The following environment variables are required to run with search enabled. 6 | 7 | * `ELASTICSEARCH_ENABLED` decides whether objects saved to the database will also be indexed in elasticsearch. The search will work without it but only with existing data. This can be used if a lot of data is imported that should not be immediately indexed in ES. 8 | * `ELASTICSEARCH_URL` sets the URL for connecting with the ES cluster. 9 | * `ELASTICSEARCH_INDEX_PREFIX` sets a prefix for each index. There will be many indices for our instances and its important that we don't mix them up. Each index in the background will be created and named automatically, but we can set the prefix to separate between the servers. 10 | 11 | ### Updating the index 12 | The search index automatically updates itself whenever an object is saved. In a freshly configured, clean environment 13 | there is no need to manually update the search index. 14 | 15 | If the search index was corrupted or the database is build upon an import of old data the index has to be manually 16 | populated. 17 | 18 | To do this first make sure that no index exists for the configured environment. 19 | 20 | Check ElasticSearch that no index exists with the index prefix defined in ```$ELASTICSEARCH_INDEX_PREFIX``` 21 | Run ```GET /_cat/indices?v``` on the cluster to see existing indices. If the prefix is already in use check the 22 | configuration of other instances for conflicting settings and, if safe, 23 | delete the indices by running ```DELETE /prefix_*``` where prefix is the index prefix defined in the environment 24 | variables. 25 | 26 | Finally run 27 | ``` 28 | python manage.py search-index _all 29 | ``` 30 | on the container to recreate the index. 31 | -------------------------------------------------------------------------------- /search/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/search/__init__.py -------------------------------------------------------------------------------- /search/admin.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | from .models import SearchIndexLog, SearchIndexLogAdmin 4 | 5 | from django.contrib import admin 6 | 7 | # Register your models here. 8 | SearchIndexLog 9 | 10 | admin.site.register(SearchIndexLog, SearchIndexLogAdmin) 11 | -------------------------------------------------------------------------------- /search/apps.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.apps import AppConfig 5 | 6 | 7 | class SearchConfig(AppConfig): 8 | name = 'search' 9 | -------------------------------------------------------------------------------- /search/exceptions.py: -------------------------------------------------------------------------------- 1 | class ValueNotFoundError(Exception): 2 | pass 3 | -------------------------------------------------------------------------------- /search/jobs/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/search/jobs/__init__.py -------------------------------------------------------------------------------- /search/jobs/daily/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/search/jobs/daily/__init__.py -------------------------------------------------------------------------------- /search/jobs/hourly/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/search/jobs/hourly/__init__.py -------------------------------------------------------------------------------- /search/jobs/hourly/search_update.py: -------------------------------------------------------------------------------- 1 | from django_extensions.management.jobs import BaseJob 2 | from django.core.management import call_command 3 | 4 | 5 | class SearchJob(BaseJob): 6 | help = "Search index update job." 7 | 8 | def execute(self): 9 | # executing Search index update job 10 | call_command('search-index', '_all') 11 | 12 | -------------------------------------------------------------------------------- /search/jobs/monthly/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/search/jobs/monthly/__init__.py -------------------------------------------------------------------------------- /search/jobs/sample.py: -------------------------------------------------------------------------------- 1 | from django_extensions.management.jobs import BaseJob 2 | 3 | class Job(BaseJob): 4 | help = "My sample job." 5 | 6 | def execute(self): 7 | # executing empty sample job 8 | pass 9 | -------------------------------------------------------------------------------- /search/jobs/weekly/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/search/jobs/weekly/__init__.py -------------------------------------------------------------------------------- /search/jobs/yearly/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/search/jobs/yearly/__init__.py -------------------------------------------------------------------------------- /search/management/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/search/management/__init__.py -------------------------------------------------------------------------------- /search/management/commands/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/search/management/commands/__init__.py -------------------------------------------------------------------------------- /search/management/commands/update-uuid.py: -------------------------------------------------------------------------------- 1 | from django.core.management.base import BaseCommand 2 | import random 3 | 4 | from model_mommy import mommy 5 | from model_mommy.recipe import Recipe, foreign_key 6 | 7 | from indicators.models import Indicator, IndicatorType 8 | from workflow.models import * 9 | import traceback 10 | 11 | 12 | class Command(BaseCommand): 13 | help = "Add unique TolaUser and Organization UUIDS after model update." 14 | 15 | def handle(self, *args, **options): 16 | count = 0 17 | users = TolaUser.objects.all() 18 | for u in users: 19 | if len(u.tola_user_uuid) == 0: 20 | u.tola_user_uuid = uuid.uuid4() 21 | u.save() 22 | count += 1 23 | 24 | orgs = Organization.objects.all() 25 | for org in orgs: 26 | if len(org.organization_uuid) == 0: 27 | org.organization_uuid = uuid.uuid4() 28 | org.save() 29 | count += 1 30 | 31 | print "Updated "+str(count)+" objects" 32 | -------------------------------------------------------------------------------- /search/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2017-08-15 09:28 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | initial = True 11 | 12 | dependencies = [ 13 | ] 14 | 15 | operations = [ 16 | migrations.CreateModel( 17 | name='SearchIndexLog', 18 | fields=[ 19 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 20 | ('create_date', models.DateTimeField(blank=True, null=True)), 21 | ('document_count', models.IntegerField(default=0)), 22 | ], 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /search/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/search/migrations/__init__.py -------------------------------------------------------------------------------- /search/models.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.contrib import admin 5 | from django.db import models 6 | from django.utils import timezone 7 | 8 | 9 | class SearchIndexLog(models.Model): 10 | create_date = models.DateTimeField(null=True, blank=True) 11 | document_count = models.IntegerField(default=0) 12 | 13 | # on save add create date or update edit date 14 | def save(self, *args, **kwargs): 15 | if self.create_date is None: 16 | self.create_date = timezone.now() 17 | super(SearchIndexLog, self).save() 18 | 19 | # displayed in admin templates 20 | def __unicode__(self): 21 | return unicode("Search Index log "+str(self.id)) 22 | 23 | 24 | class SearchIndexLogAdmin(admin.ModelAdmin): 25 | list_display = ('document_count',) 26 | display = 'Search' 27 | -------------------------------------------------------------------------------- /search/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/search/tests/__init__.py -------------------------------------------------------------------------------- /search/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | from .views import * 3 | 4 | urlpatterns = [ 5 | url(r'^get/(?P\w+)/(?P\w+)', search), 6 | ] -------------------------------------------------------------------------------- /tcp-port-wait.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | apt update 3 | apt install -y netcat 4 | set -e 5 | 6 | if [ -z "$1" -o -z "$2" ] 7 | then 8 | echo "tcp-port-wait - block until specified TCP port becomes available" 9 | echo "Usage: ntcp-port-wait HOST PORT" 10 | exit 1 11 | fi 12 | echo Waiting for port $1:$2 to become available... 13 | while ! nc -z $1 $2 2>/dev/null 14 | do 15 | let elapsed=elapsed+1 16 | if [ "$elapsed" -gt 120 ] 17 | then 18 | echo "TIMED OUT !" 19 | exit 1 20 | fi 21 | sleep 1; 22 | done 23 | 24 | echo "READY !" 25 | -------------------------------------------------------------------------------- /templates/400.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Page Not found{% endblock %} 4 | 5 | {% block page_title %}Page Not found{% endblock page_title %} 6 | 7 | {% block content %} 8 |

This is not the page you were looking for, you may be lost.

9 | 10 | {% endblock content %} -------------------------------------------------------------------------------- /templates/403.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Addtional Permissions Required{% endblock %} 4 | 5 | {% block page_title %}You don't appear to have the proper permissions to access this page.{% endblock page_title %} 6 | 7 | {% block content %} 8 |

9 | Please check with your organization or country admin if you think you should have access to this section. 10 |
11 | Tola Work 12 |

13 | 14 | {% endblock content %} -------------------------------------------------------------------------------- /templates/404.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Page Not found{% endblock %} 4 | 5 | {% block page_title %}Page Not found{% endblock page_title %} 6 | 7 | {% block content %} 8 |

This is not the page you were looking for, you may be lost.

9 | 10 | {% endblock content %} -------------------------------------------------------------------------------- /templates/contact.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block page_title %}Feedback{% endblock %} 3 | 4 | {% if messages %} 5 |
    6 |

    Message:

    7 | {% for message in messages %} 8 | {{ message }} 9 | {% endfor %} 10 |
11 | {% endif %} 12 | 13 | {% block content %} 14 |

Let us know if you are having a problem or would like to see something change.

15 | {% csrf_token %} 16 | {% load crispy_forms_tags %} 17 | {% crispy form form.helper %} 18 | 19 | {% endblock content %} -------------------------------------------------------------------------------- /templates/customdashboard/charts/doughnut.html: -------------------------------------------------------------------------------- 1 | 10 | 11 | -------------------------------------------------------------------------------- /templates/customdashboard/charts/horizontal_bar_graph.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /templates/customdashboard/charts/public_horizontal_bar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /templates/customdashboard/charts/public_indicator_pie.html: -------------------------------------------------------------------------------- 1 | 10 | 11 | -------------------------------------------------------------------------------- /templates/customdashboard/charts/public_radar.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/customdashboard/charts/radar.html: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /templates/customdashboard/notebook.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% extends "customdashboard/custom_base_layout.html" %} 5 | {% load staticfiles %} 6 | 7 | 8 | {% load humanize %} 9 | 10 | 11 | 12 | {% block content %} 13 | 14 | 15 | {% block breadcrumb %} 16 | 20 | {% endblock %} 21 | 22 | 23 |
24 | 25 |
26 | {% endblock content %} 27 | -------------------------------------------------------------------------------- /templates/customdashboard/publicdashboards.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load staticfiles %} 3 | {% load crispy_forms_tags %} 4 | 5 | {% block content %} 6 | 7 | 8 | 9 | {% endblock content %} -------------------------------------------------------------------------------- /templates/customdashboard/rrima_components/context_pane.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /templates/customdashboard/rrima_components/rrima_map.html: -------------------------------------------------------------------------------- 1 |
2 | 38 | -------------------------------------------------------------------------------- /templates/customdashboard/rrima_components/rrima_notebook.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% extends "customdashboard/custom_base_layout.html" %} 5 | {% load staticfiles %} 6 | 7 | 8 | {% load humanize %} 9 | 10 | 11 | 12 | {% block content %} 13 | 14 | 15 | {% block breadcrumb %} 16 | 20 | {% endblock %} 21 | 22 | 23 |
24 | 25 |
26 | {% endblock content %} 27 | -------------------------------------------------------------------------------- /templates/customdashboard/rrima_components/sidebar_events.html: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /templates/customdashboard/rrima_components/sidebar_gallery.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 32 | -------------------------------------------------------------------------------- /templates/customdashboard/rrima_components/sidebar_news.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /templates/datepicker.html: -------------------------------------------------------------------------------- 1 | {# datepicker.html #} 2 | 3 | -------------------------------------------------------------------------------- /templates/dateslider.html: -------------------------------------------------------------------------------- 1 | {# dateslider.html #} 2 | 3 | 14 | 15 |
16 | 17 |
18 | 19 |
-------------------------------------------------------------------------------- /templates/documentation.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block page_title %}Documentation{% endblock %} 3 | 4 | {% block content %} 5 |
    6 | {% for item in getDocumentation %} 7 |
  • {{ item.name }}

    8 |
    9 |

    {{ item.documentation}}

    10 |
    11 |
  • 12 | {% empty %} 13 |
  • No Documentation yet.
  • 14 | {% endfor %} 15 |
16 | 17 | {% endblock content %} 18 | -------------------------------------------------------------------------------- /templates/faq.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block page_title %} Frequently Asked Questions {% endblock %} 3 | 4 | {% block content %} 5 |
    6 | {% for item in getFAQ %} 7 |
  • {{ item.question }}

    8 |
    9 |

    {{ item.answer}}

    10 |
    11 |
  • 12 | {% empty %} 13 |
  • No FAQ's yet.
  • 14 | {% endfor %} 15 |
16 | 17 | {% endblock content %} 18 | -------------------------------------------------------------------------------- /templates/feed/delete.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block page_title %}Delete Share{% endblock %} 3 | 4 | {% block content %} 5 |
6 |

Share Has Been Deleted

7 |
8 | {% endblock content %} -------------------------------------------------------------------------------- /templates/feed/json.html: -------------------------------------------------------------------------------- 1 | {{ jsonData|safe }} -------------------------------------------------------------------------------- /templates/feed/list.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block page_title %}Shareable Data{% endblock %} 3 | 4 | {% block content %} 5 | {% for item in getSilos %} 6 | {{ item.name }} 7 | 14 | 15 | 16 | {% endfor %} 17 | 18 | 19 | {% endblock content %} 20 | -------------------------------------------------------------------------------- /templates/feed/stores.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/templates/feed/stores.html -------------------------------------------------------------------------------- /templates/feed/xml.html: -------------------------------------------------------------------------------- 1 | {{ xmlData }} -------------------------------------------------------------------------------- /templates/filefield.html: -------------------------------------------------------------------------------- 1 | {% load crispy_forms_field %} 2 | 3 |
4 | {% if field.label %} 5 | 8 | {% endif %} 9 | 10 |
11 |
12 |
13 |
14 | Select imageChange 15 | Remove 16 |
17 | {% include 'bootstrap/layout/help_text_and_errors.html' %} 18 |
19 |
-------------------------------------------------------------------------------- /templates/form_guidance.html: -------------------------------------------------------------------------------- 1 | 2 | {% if view.guidance %} 3 | {% if view.guidance.guidance_link %} 4 | Form Help/Guidance 5 | {% endif %} 6 | {% if view.guidance.guidance %} 7 | Form Help/Guidance 8 | 21 | 22 | {{ view.guidance.guidance }} 23 |
24 | Close 25 |
26 | {% endif %} 27 | {% else %} 28 | No Guidance for this Form. 29 | {% endif %} 30 | -------------------------------------------------------------------------------- /templates/formlibrary/beneficiary_form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block bread_crumb %} 3 | 14 | {% endblock %} 15 | {% block page_title %}Beneficiary Form{% endblock %} 16 | 17 | {% block content %} 18 | {% if form.errors %} 19 |
20 | {% for field in form %} 21 | {% for error in field.errors %} 22 | {{ field.label }} - {{ error|escape }}  23 | {% endfor %} 24 | {% endfor %} 25 |
26 | {% for error in form.non_field_errors %} 27 |
28 | {{ error|escape }} 29 |
30 | {% endfor %} 31 | {% endif %} 32 | {% csrf_token %} 33 | {% load crispy_forms_tags %} 34 | {% crispy form %} 35 | 36 | {% endblock content %} 37 | -------------------------------------------------------------------------------- /templates/formlibrary/distribution_confirm_delete.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block page_title %}Distribution Confirm Delete{% endblock %} 3 | 4 | {% block content %} 5 | 6 |
{% csrf_token %} 7 |

Are you sure you want to delete "{{ object }}"?

8 | 9 |
10 | 11 | 12 | {% endblock content %} -------------------------------------------------------------------------------- /templates/formlibrary/distribution_form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block bread_crumb %} 3 | 8 | {% endblock %} 9 | {% block page_title %}Distribution Form{% endblock %} 10 | 11 | {% block content %} 12 | {% if form.errors %} 13 |
14 | {% for field in form %} 15 | {% for error in field.errors %} 16 | {{ field.label }} - {{ error|escape }}  17 | {% endfor %} 18 | {% endfor %} 19 |
20 | {% for error in form.non_field_errors %} 21 |
22 | {{ error|escape }} 23 |
24 | {% endfor %} 25 | {% endif %} 26 | {% csrf_token %} 27 | {% load crispy_forms_tags %} 28 | {% crispy form %} 29 | 30 | {% endblock content %} 31 | -------------------------------------------------------------------------------- /templates/formlibrary/filter.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 10 |
11 | -------------------------------------------------------------------------------- /templates/formlibrary/formlibrary_list.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block bread_crumb %} 3 | 10 | {% endblock %} 11 | {% load group_tag %} 12 | {% block page_title %}Form Library{% endblock %} 13 | 14 | {% block content %} 15 | 16 |
    17 | {% for item in getForms %} 18 |
  • {{ item.create_date|date }} - {{ item.name }} 19 |
  • 20 | 21 | {% empty %} 22 |
  • No forms yet.
  • 23 | {% endfor %} 24 |
25 | 26 | 27 | 33 | {% endblock content %} 34 | -------------------------------------------------------------------------------- /templates/formlibrary/training_confirm_delete.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block page_title %}Training Confirm Delete{% endblock %} 3 | 4 | {% block content %} 5 | 6 |
{% csrf_token %} 7 |

Are you sure you want to delete "{{ object }}"?

8 | 9 |
10 | 11 | 12 | {% endblock content %} 13 | -------------------------------------------------------------------------------- /templates/formlibrary/trainingattendance_form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block bread_crumb %} 3 | 14 | {% endblock %} 15 | {% block page_title %}Training Attendance Form{% endblock %} 16 | 17 | {% block content %} 18 | {% if form.errors %} 19 |
20 | {% for field in form %} 21 | {% for error in field.errors %} 22 | {{ field.label }} - {{ error|escape }}  23 | {% endfor %} 24 | {% endfor %} 25 |
26 | {% for error in form.non_field_errors %} 27 |
28 | {{ error|escape }} 29 |
30 | {% endfor %} 31 | {% endif %} 32 | {% csrf_token %} 33 | {% load crispy_forms_tags %} 34 | {% crispy form %} 35 | 36 | {% endblock content %} 37 | -------------------------------------------------------------------------------- /templates/formset.html: -------------------------------------------------------------------------------- 1 | {% load crispy_forms_tags %} 2 | 3 |
4 | {% crispy formset %} 5 |
-------------------------------------------------------------------------------- /templates/google_analytics.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/indicators/collected_data_report_table.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | {% for item in collected %} 11 | 12 | 13 | 14 | 15 | 16 | 17 | {% endfor %} 18 | 19 | 20 | 21 | 22 | 23 | 24 |
Date CollectedEvidenceTargetActual
{{ item.date_collected|date:"d-m-Y" }}{{ item.evidence }} {{ item.tola_table}}{{ item.targeted }}{{ item.achieved }}
Sum:{{ collected_sum.targeted__sum }}{{ collected_sum.achieved__sum }} 
25 | 26 | -------------------------------------------------------------------------------- /templates/indicators/collected_data_table.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | {% if collecteddata %} 11 | {% for item in collecteddata %} 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | {% endfor %} 24 | 25 | 26 | 27 | 28 | 29 | 30 | {% else %} 31 | 32 | 33 | 34 | 35 | {% endif %} 36 |
Date CollectedProjectEvidenceTargetActual 
14 | {{ item.date_collected|date:"m-d-Y" }} 15 | {{item.agreement}}{% if item.evidence %}{% if item.evidence.url%}{% endif %}{{ item.evidence }} {% if item.evidence.url%}{% endif %}{%endif%} {% if item.tola_table %} {{ item.tola_table }} {% endif %}{{ item.periodic_target.target }}{{ item.achieved }}EditDelete
Sum:{{ collected_sum.periodic_target__target__sum }}{{ collected_sum.achieved__sum }}New Data
No Data CollectedNew Data
37 | -------------------------------------------------------------------------------- /templates/indicators/collecteddata_confirm_delete.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block page_title %}Collected Indicator Data Confirm Delete{% endblock %} 3 | 4 | {% block content %} 5 | 6 |
{% csrf_token %} 7 |

Are you sure you want to delete the collected data ?

8 | 9 |
10 | 11 | 12 | {% endblock content %} -------------------------------------------------------------------------------- /templates/indicators/collecteddata_form_modal.html: -------------------------------------------------------------------------------- 1 | {% block content %} 2 | 3 | 4 | 5 | 6 | 29 | 30 | {% if form.errors %} 31 |
32 | {% for field in form %} 33 | {% for error in field.errors %} 34 | {{ field.label }} - {{ error|escape }}  35 | {% endfor %} 36 | {% endfor %} 37 |
38 | {% for error in form.non_field_errors %} 39 |
40 | {{ error|escape }} 41 |
42 | {% endfor %} 43 | {% endif %} 44 | {% csrf_token %} 45 | {% load crispy_forms_tags %} 46 | {% crispy form %} 47 | 48 | 49 | {% endblock content %} 50 | -------------------------------------------------------------------------------- /templates/indicators/dashboard.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block page_title %}Dashboard{% endblock %} 3 | 4 | {% block content %} 5 |

Dashboard report on indicator status by Country and {{ workflowlevel1 }}

6 | 7 | {% endblock content %} -------------------------------------------------------------------------------- /templates/indicators/filter.html: -------------------------------------------------------------------------------- 1 | 34 |
35 | 36 | -------------------------------------------------------------------------------- /templates/indicators/indicator_confirm_delete.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block page_title %}Indicator Confirm Delete{% endblock %} 3 | 4 | {% block content %} 5 | 6 |
{% csrf_token %} 7 |

Are you sure you want to delete?

8 | 9 |
10 | 11 | 12 | {% endblock content %} -------------------------------------------------------------------------------- /templates/indicators/indicator_form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block bread_crumb %} 3 | 7 | {% endblock %} 8 | {% block page_title %}Indicator{% endblock %} 9 | 10 | {% block content %} 11 | {% if i_name %} 12 |

({{i_name}})

13 | {% endif %} 14 | 15 | 16 | 26 | 27 | {% if form.errors %} 28 |
29 | {% for field in form %} 30 | {% for error in field.errors %} 31 | {{ field.label }} - {{ error|escape }}  32 | {% endfor %} 33 | {% endfor %} 34 |
35 | {% for error in form.non_field_errors %} 36 |
37 | {{ error|escape }} 38 |
39 | {% endfor %} 40 | {% endif %} 41 | 42 | {% csrf_token %} 43 |
44 | {% load crispy_forms_tags %} 45 | {% crispy form %} 46 |
47 | 48 | {% include 'indicators/indicator_form_common_js.html' %} 49 | 50 | {% endblock content %} 51 | -------------------------------------------------------------------------------- /templates/indicators/indicator_form_modal.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 14 | {% csrf_token %} 15 | {% load crispy_forms_tags %} 16 | {% crispy form %} 17 | 18 | 19 | -------------------------------------------------------------------------------- /templates/indicators/indicator_graphs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 68 | 69 | 70 | 71 |
72 |
73 |
74 |
75 |
76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /templates/indicators/tool.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block page_title %}Indicator Planning Tool{% endblock %} 3 | 4 | {% block content %} 5 |

Create Indicator Plans for Programs

6 | 7 | {% endblock content %} -------------------------------------------------------------------------------- /templates/indicators/workflowlevel1_indicators_table.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | {% for indicator in indicators|dictsort:"levels" %} 12 | 13 | 14 | 15 | 23 | 24 | 25 | 26 | 33 | 34 | 35 | 41 | 42 | {% endfor %} 43 |
Indicator TypeIndicator LevelIndicator NameIndicator NumberLOP TargetSector 
{{ indicator.indicator_types}}{{ indicator.levels }} 16 | 17 | {{ indicator.name}} 18 | 19 | {% if indicator.key_performance_indicator %} 20 | KPI 21 | {% endif %} 22 | {{ indicator.number}}{{ indicator.lop_target}}{{ indicator.sector}} 27 | 28 | Edit 29 | 30 | Data {{ indicator.data_count }} 31 | 32 | Delete
36 |
37 | 38 | {% include "indicators/collected_data_table.html" %} 39 |
40 |
44 | -------------------------------------------------------------------------------- /templates/registration/bookmark_confirm_delete.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block page_title %}Bookmark Confirm Delete{% endblock %} 3 | 4 | {% block content %} 5 | 6 |
{% csrf_token %} 7 |

Are you sure you want to delete "{{ object }}"?

8 | 9 |
10 | 11 | 12 | {% endblock content %} -------------------------------------------------------------------------------- /templates/registration/bookmark_form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block bread_crumb %} 3 |
4 | 9 |
10 | {% endblock %} 11 | {% block page_title %}Bookmark Form{% endblock %} 12 | 13 | 14 | {% block content %} 15 | {% if form.errors %} 16 |
17 | {% for field in form %} 18 | {% for error in field.errors %} 19 | {{ field.label }} - {{ error|escape }}  20 | {% endfor %} 21 | {% endfor %} 22 |
23 | {% for error in form.non_field_errors %} 24 |
25 | {{ error|escape }} 26 |
27 | {% endfor %} 28 | {% endif %} 29 | {% csrf_token %} 30 | {% load crispy_forms_tags %} 31 | {% crispy form %} 32 | 33 | {% endblock content %} 34 | -------------------------------------------------------------------------------- /templates/registration/bookmark_list.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block bread_crumb %} 3 | 7 | {% endblock %} 8 | {% block page_title %}Your Bookmarks List{% endblock %} 9 | 10 | {% block content %} 11 |
12 |
13 |
14 |

Bookmarks

15 | 16 |
    17 | {% for item in getBookmarks %} 18 | 19 |
  • {{ item.create_date|date }}  {{ item.name }}  Delete Bookmark
  • 20 | 21 | {% empty %} 22 |
  • No bookmarks yet.
  • 23 | {% endfor %} 24 |
25 | {% endblock content %} 26 | -------------------------------------------------------------------------------- /templates/registration/login.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Login{% endblock %} 4 | 5 | {% block content %} 6 |

Login

7 | 8 |
9 | {% csrf_token %} 10 | {{ form.as_p }} 11 | 12 | 13 | {% if non_ldap %} 14 | 17 | or 18 | Register a new Tola Account
19 | {% endif %} 20 |
21 | {% endblock %} -------------------------------------------------------------------------------- /templates/registration/profile.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Account Profile{% endblock %} 4 | 5 | 6 | {% block content %} 7 | 8 |

User Registration/Profile

9 | {% if form.errors %} 10 | {% for field in form %} 11 | {% for error in field.errors %} 12 |
13 | {{ error|escape }} 14 |
15 | {% endfor %} 16 | {% endfor %} 17 | {% for error in form.non_field_errors %} 18 |
19 | {{ error|escape }} 20 |
21 | {% endfor %} 22 | {% endif %} 23 | {% load crispy_forms_tags %} 24 | {% crispy form form.helper %} 25 | Bookmarks 26 | {% endblock content %} -------------------------------------------------------------------------------- /templates/registration/register.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Create an account{% endblock %} 4 | 5 | {% block content %} 6 |

Create an account

7 | 8 | {% if form.errors %} 9 | {% for field in form %} 10 | {% for error in field.errors %} 11 |
12 | {{ error|escape }} 13 |
14 | {% endfor %} 15 | {% endfor %} 16 | {% for error in form.non_field_errors %} 17 |
18 | {{ error|escape }} 19 |
20 | {% endfor %} 21 | {% endif %} 22 | 23 | 24 |
25 | {% csrf_token %} 26 | {% load crispy_forms_tags %} 27 | {{ userform|crispy }} 28 | {{ tolaform|crispy }} 29 |
30 |
Notice/Disclaimer:
31 | 32 |

33 | {{ privacy.privacy_disclaimer }} 34 |

35 | 36 |
37 |
38 |
39 | 40 |
41 |
42 | {% endblock %} -------------------------------------------------------------------------------- /templates/workflow/approval_confirm_delete.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Delete Budget Item 6 | 7 | 8 | 9 | 26 | 27 | 36 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /templates/workflow/approval_form.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 20 | 21 | 30 | 44 | 49 | 50 | -------------------------------------------------------------------------------- /templates/workflow/approvalworkflow_confirm_delete.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block page_title %}Project Initiation Confirm Delete{% endblock %} 3 | 4 | {% block content %} 5 | 6 |
{% csrf_token %} 7 |

Are you sure you want to delete "{{ object }}"?

8 | 9 |
10 | 11 | 12 | {% endblock content %} -------------------------------------------------------------------------------- /templates/workflow/benchmarks_confirm_delete.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Delete Component 6 | 7 | 8 | 9 | 26 | 27 | 36 | 42 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /templates/workflow/budget_confirm_delete.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Delete Budget Item 6 | 7 | 8 | 9 | 26 | 27 | 36 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /templates/workflow/contact_confirm_delete.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block page_title %}Stakeholder Confirm Delete{% endblock %} 3 | 4 | {% block content %} 5 | 6 |
{% csrf_token %} 7 |

Are you sure you want to delete "{{ object }}"?

8 | 9 |
10 | 11 | 12 | {% endblock content %} -------------------------------------------------------------------------------- /templates/workflow/contact_form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block bread_crumb %} 3 |
4 | 11 |
12 | {% endblock %} 13 | {% block page_title %}Contact Form{% endblock %} 14 | 15 | 16 | {% block content %} 17 | {% if form.errors %} 18 |
19 | {% for field in form %} 20 | {% for error in field.errors %} 21 | {{ field.label }} - {{ error|escape }}  22 | {% endfor %} 23 | {% endfor %} 24 |
25 | {% for error in form.non_field_errors %} 26 |
27 | {{ error|escape }} 28 |
29 | {% endfor %} 30 | {% endif %} 31 | {% csrf_token %} 32 | {% load crispy_forms_tags %} 33 | {% crispy form %} 34 | 35 | {% endblock content %} 36 | -------------------------------------------------------------------------------- /templates/workflow/contact_list.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block bread_crumb %} 3 | 8 | {% endblock %} 9 | {% block page_title %}Contact List{% endblock %} 10 | 11 | {% block content %} 12 |
13 | New Contact   14 |
15 |
16 |
17 |

Contacts

18 | 19 | {% if getStakeholder %} 20 |

Filtered by Stakeholder: [{{ getStakeholder.name }}]

21 | {% endif %} 22 | 23 | 34 | {% endblock content %} 35 | -------------------------------------------------------------------------------- /templates/workflow/documentation_agreement_confirm_delete.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Delete Documentation 6 | 7 | 8 | 9 | 26 | 27 | 36 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /templates/workflow/documentation_confirm_delete.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block page_title %}Document Confirm Delete{% endblock %} 3 | 4 | {% block content %} 5 | 6 |
{% csrf_token %} 7 |

Are you sure you want to delete "{{ object }}"?

8 | 9 |
10 | 11 | 12 | {% endblock content %} -------------------------------------------------------------------------------- /templates/workflow/filter.html: -------------------------------------------------------------------------------- 1 |
2 | 6 | 12 |
13 |
14 | 18 | 24 |
-------------------------------------------------------------------------------- /templates/workflow/program_projects_table.html: -------------------------------------------------------------------------------- 1 | 2 | {{ item.create_date|date:"d-m-Y" }} 3 | {{ item.name }}
4 | {{ WORKFLOWLEVEL2 }} Form 5 | Print View 6 | 7 | {{ item.office }} 8 | {% if item.short %} Short {% else %} Long {% endif %} 9 | {{ item.get_progress_display }} 10 | 11 | Project Dashboard 12 | 13 | 14 | -------------------------------------------------------------------------------- /templates/workflow/quantitativeoutputs_confirm_delete.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Add/Edit Quantitative Outputs 6 | 7 | 8 | 9 | 26 | 27 | 36 | 43 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /templates/workflow/quantitativeoutputs_form.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Add/Edit Quantitative Outputs 6 | 7 | 8 | 9 | 26 | 27 | 36 | 49 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /templates/workflow/site_indicatordata.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %}{% load i18n %} 2 | {% block bread_crumb %} 3 | 7 | {% endblock %} 8 | {% block page_title %}Indicator Data for {{ site }} {% endblock %} 9 | 10 | {% block content %} 11 | 12 | {% for d in collecteddata %} 13 | {% ifchanged d.workflowlevel1 %} 14 | {% if not forloop.first %} 15 | 16 | {% endif %} 17 |
18 |
{{ d.workflowlevel1 }}
19 |
20 | 21 | {% endifchanged %} 22 | 23 | 24 | {% ifchanged d.indicator %} 25 |

{{ d.indicator}}

26 | {% endifchanged %} 27 | 28 | {% ifchanged d.indicator %} 29 | 30 | 31 | 32 | 33 | {% endifchanged %} 34 | 35 | 36 | 37 | 38 |
AchievedPeriodic Target
{{ d.achieved }} {{ d.periodic_target }}
39 | 40 | {% if forloop.last %}{% endif %} 41 | {% endfor %} 42 | {% endblock content %} -------------------------------------------------------------------------------- /templates/workflow/site_profile_report.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block bread_crumb %} 3 | 8 | 9 | {% endblock bread_crumb %} 10 | 11 | {% block page_title %}{{ WORKFLOWLEVEL2 }} Report{% endblock %} 12 | 13 | {% block content %} 14 | 19 |

{{ proposal.name }}

20 | 23 | 24 |

{{ country.country }} Sites

25 |
26 | 27 | {% include "workflow/site_profile_map.html" %} 28 | 29 |
    30 | {% for item in getSiteProfile %} 31 |
  • {{ item.create_date|date }} - {{ item.name }} 32 |
    33 | Update Sites 34 |
    35 |
  • 36 | {% empty %} 37 |
  • No sites yet.
  • 38 | {% endfor %} 39 |
40 | {% endblock content %} 41 | -------------------------------------------------------------------------------- /templates/workflow/site_projectcomplete.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %}{% load i18n %} 2 | {% block bread_crumb %} 3 | 7 | {% endblock %} 8 | {% block page_title %}Project Data for {{ site }} {% endblock %} 9 | 10 | {% block content %} 11 | 12 | {% for item in projects %} 13 | {% ifchanged item.workflowlevel1 %} 14 | {% if not forloop.first %} 15 |
16 | {% endif %} 17 |
18 |
{{ item.workflowlevel1 }}
19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | {% endifchanged %} 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | {% if forloop.last %}
Date Created{{ WORKFLOWLEVEL1 }} Name{{ WORKFLOWLEVEL2 }} CodeOffice CodeForm VersionApproval Status
{{ item.create_date|date:"d-m-Y" }} {{ item.name }}{{ item.activity_code }}{{ item.office }}{% if item.short %} Short {% else %} Long {% endif %}{% if item.projectcomplete %} Tracking {% if item.projectcomplete.approval %}{{ item.projectcomplete.approval|capfirst }}{% else %}Open{% endif %}{% else %} Initiation {% if item.approval %}{{ item.approval|capfirst }}{% else %} Open {% endif %} {% endif %}
{% endif %} 39 | {% endfor %} 40 | {% endblock content %} -------------------------------------------------------------------------------- /templates/workflow/siteprofile_confirm_delete.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block page_title %}Communityonfirm Delete{% endblock %} 3 | 4 | {% block content %} 5 | 6 |
{% csrf_token %} 7 |

Are you sure you want to delete "{{ object }}"?

8 | 9 |
10 | 11 | 12 | {% endblock content %} -------------------------------------------------------------------------------- /templates/workflow/siteprofile_form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block bread_crumb %} 3 |
4 | 13 |
14 | {% endblock %} 15 | {% block page_title %}Site Profile Form{% endblock %} 16 | 17 | {% block content %} 18 | {% if form.errors %} 19 |
20 | {% for field in form %} 21 | {% for error in field.errors %} 22 | {{ field.label }} - {{ error|escape }}  23 | {% endfor %} 24 | {% endfor %} 25 |
26 | {% for error in form.non_field_errors %} 27 |
28 | {{ error|escape }} 29 |
30 | {% endfor %} 31 | {% endif %} 32 | {% csrf_token %} 33 | {% load crispy_forms_tags %} 34 | {% crispy form %} 35 | 36 | {% endblock content %} 37 | -------------------------------------------------------------------------------- /templates/workflow/stakeholder_confirm_delete.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block page_title %}Stakeholder Confirm Delete{% endblock %} 3 | 4 | {% block content %} 5 | 6 |
{% csrf_token %} 7 |

Are you sure you want to delete "{{ object }}"?

8 | 9 |
10 | 11 | 12 | {% endblock content %} -------------------------------------------------------------------------------- /templates/workflow/stakeholder_form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block bread_crumb %} 3 |
4 | 9 |
10 | {% endblock %} 11 | {% block page_title %}Stakeholder Form{% endblock %} 12 | 13 | 14 | {% block content %} 15 | 16 | 17 | 18 | 29 | 30 | Form Help/Guidance 31 | {% if form.errors %} 32 |
33 | {% for field in form %} 34 | {% for error in field.errors %} 35 | {{ field.label }} - {{ error|escape }}  36 | {% endfor %} 37 | {% endfor %} 38 |
39 | {% for error in form.non_field_errors %} 40 |
41 | {{ error|escape }} 42 |
43 | {% endfor %} 44 | {% endif %} 45 | {% csrf_token %} 46 | {% load crispy_forms_tags %} 47 | {% crispy form %} 48 | 49 | {% endblock content %} 50 | -------------------------------------------------------------------------------- /templates/workflow/workflowlevel1_form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block bread_crumb %} 3 | 10 | {% endblock %} 11 | 12 | {% block extra_js_in_body %} 13 | 14 | 15 | 16 | {% endblock %} 17 | 18 | {% block page_title %}{{ WORKFLOWLEVEL1 }} Form{% endblock %} 19 | {% block content %} 20 | {% if p_agreement%} 21 |

{{p_agreement|truncatechars:150}}

22 | {% endif %} 23 | {% if form.errors %} 24 |
25 | {% for field in form %} 26 | {% for error in field.errors %} 27 | {{ field.label }} - {{ error|escape }}  28 | {% endfor %} 29 | {% endfor %} 30 |
31 | {% for error in form.non_field_errors %} 32 |
33 | {{ error|escape }} 34 |
35 | {% endfor %} 36 | {% endif %} 37 | {% load crispy_forms_tags %} 38 |
39 | {% crispy form %} 40 | 41 |
42 | 43 | 44 | 51 | 52 | 53 | {% endblock content %} 54 | -------------------------------------------------------------------------------- /templates/workflow/workflowlevel1_list.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block bread_crumb %} 3 |
4 | 8 |
9 | {% endblock %} 10 | {% block page_title %}{{ WORKFLOWLEVEL1 }} List{% endblock %} 11 | 12 | {% block content %} 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | {% for item in getworkflowlevel1s %} 25 | 26 | 27 | 28 | 29 | 32 | 33 | {% empty %} 34 |
  • No {{ WORKFLOWLEVEL1 }}s yet.
  • 35 | {% endfor %} 36 |
    Date Created{{ WORKFLOWLEVEL1 }} NameFunding Status 
    {% if item.status %}{{ item.create_date}}{% else %}{{ item.create_date}}{% endif %}{% if item.status %} {{ item.name}}{% else %}{{ item.name}}{% endif %}{{ item.funding_status }} 30 | Delete 31 |
    37 | 38 | 39 | 45 | 46 | {% endblock content %} 47 | -------------------------------------------------------------------------------- /templates/workflow/workflowlevel2_confirm_delete.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block page_title %}Project Initiation Confirm Delete{% endblock %} 3 | 4 | {% block content %} 5 | 6 |
    {% csrf_token %} 7 |

    Are you sure you want to delete "{{ object }}"?

    8 | 9 |
    10 | 11 | 12 | {% endblock content %} -------------------------------------------------------------------------------- /templates2/400.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Page Not found{% endblock %} 4 | 5 | {% block page_title %}Page Not found{% endblock page_title %} 6 | 7 | {% block content %} 8 |

    This is not the page you were looking for, you may be lost.

    9 | 10 | {% endblock content %} -------------------------------------------------------------------------------- /templates2/403.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Addtional Permissions Required{% endblock %} 4 | 5 | {% block page_title %}You don't appear to have the proper permissions to access this page.{% endblock page_title %} 6 | 7 | {% block content %} 8 |

    9 | Please check with your organization or country admin if you think you should have access to this section. 10 |
    11 | Tola Work 12 |

    13 | 14 | {% endblock content %} -------------------------------------------------------------------------------- /templates2/404.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Page Not found{% endblock %} 4 | 5 | {% block page_title %}Page Not found{% endblock page_title %} 6 | 7 | {% block content %} 8 |

    This is not the page you were looking for, you may be lost.

    9 | 10 | {% endblock content %} -------------------------------------------------------------------------------- /templates2/contact.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block page_title %}Feedback{% endblock %} 3 | 4 | {% if messages %} 5 |
      6 |

      Message:

      7 | {% for message in messages %} 8 | {{ message }} 9 | {% endfor %} 10 |
    11 | {% endif %} 12 | 13 | {% block content %} 14 |

    Let us know if you are having a problem or would like to see something change.

    15 | {% csrf_token %} 16 | {% load crispy_forms_tags %} 17 | {% crispy form form.helper %} 18 | 19 | {% endblock content %} -------------------------------------------------------------------------------- /templates2/dev.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 | 5 | 6 | 7 |
    8 |
    9 |
    10 |
    11 |

    TolaActivity - Dev User

    12 |

    13 | {% for item in message.items %} 14 | {{ item }}
    15 | {% endfor %} 16 |

    17 |
    18 |
    19 |
    20 |
    21 | 22 | 23 | {% endblock content %} 24 | -------------------------------------------------------------------------------- /templates2/feed/delete.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block page_title %}Delete Share{% endblock %} 3 | 4 | {% block content %} 5 |
    6 |

    Share Has Been Deleted

    7 |
    8 | {% endblock content %} -------------------------------------------------------------------------------- /templates2/feed/json.html: -------------------------------------------------------------------------------- 1 | {{ jsonData|safe }} -------------------------------------------------------------------------------- /templates2/feed/list.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block page_title %}Shareable Data{% endblock %} 3 | 4 | {% block content %} 5 | {% for item in getSilos %} 6 | {{ item.name }} 7 | 14 | 15 | 16 | {% endfor %} 17 | 18 | 19 | {% endblock content %} 20 | -------------------------------------------------------------------------------- /templates2/feed/stores.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/templates2/feed/stores.html -------------------------------------------------------------------------------- /templates2/feed/xml.html: -------------------------------------------------------------------------------- 1 | {{ xmlData }} -------------------------------------------------------------------------------- /templates2/index.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 | 5 |
    6 | Log Out 7 |
    8 |
    9 | 10 | 11 |

    TolaData

    12 |

    13 | Welcome: {{ request.user}}!
    14 | You have successfuly logged in to TolaData. Now you can... 15 |

    16 | 17 | 34 | 35 |
    36 | {% if "demo" in request.build_absolute_uri %} 37 |

    This is a Demonstration server and account.

    38 |

    All data will be deleted from the server every 7 days.

    39 | {% endif %} 40 |
    41 |
    42 | 43 | {% endblock content %} 44 | -------------------------------------------------------------------------------- /templates2/maintenance/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Maintenance page | TolaData 6 | 14 | 15 | 16 |
    17 |

    We’ll be back soon!

    18 |
    19 |

    Sorry for the inconvenience but we’re performing some maintenance at the moment. If you need to you can always contact us, otherwise we’ll be back online shortly!

    20 |

    — TolaData Team

    21 |
    22 |
    23 | 24 | 25 | -------------------------------------------------------------------------------- /templates2/registration/profile.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Account Profile{% endblock %} 4 | 5 | 6 | {% block content %} 7 | 8 |

    User Registration/Profile

    9 | {% if form.errors %} 10 | {% for field in form %} 11 | {% for error in field.errors %} 12 |
    13 | {{ error|escape }} 14 |
    15 | {% endfor %} 16 | {% endfor %} 17 | {% for error in form.non_field_errors %} 18 |
    19 | {{ error|escape }} 20 |
    21 | {% endfor %} 22 | {% endif %} 23 | {% load crispy_forms_tags %} 24 | {% crispy form form.helper %} 25 | Bookmarks 26 | {% endblock content %} -------------------------------------------------------------------------------- /templates2/registration/register.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Create an account{% endblock %} 4 | 5 | {% block content %} 6 |
    7 | 8 |

    Create an account

    9 |
    10 | 11 | {% if form.errors %} 12 | {% for field in form %} 13 | {% for error in field.errors %} 14 |
    15 | {{ error|escape }} 16 |
    17 | {% endfor %} 18 | {% endfor %} 19 | {% for error in form.non_field_errors %} 20 |
    21 | {{ error|escape }} 22 |
    23 | {% endfor %} 24 | {% endif %} 25 | 26 | 27 |
    28 | {% csrf_token %} 29 | {% load crispy_forms_tags %} 30 | {{ form_user|crispy }} 31 | {% crispy form_tolauser %} 32 |
    33 |
    34 | 35 |
    36 |
    37 |
    38 |
    39 |

    40 | Already have an account? Login
    41 |

    42 |
    43 | {% endblock %} -------------------------------------------------------------------------------- /templates2/unauthorized.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 |
    5 | Go Back 6 |
    7 |
    8 | 9 | 10 |

    TolaData

    11 |
    12 |

    You don't appear to have permissions to access the system.

    13 |

    Please check with your organization to have access.

    14 |
    15 |
    16 | {% endblock content %} -------------------------------------------------------------------------------- /tola/__init__.py: -------------------------------------------------------------------------------- 1 | STAGING_BRANCH = 'staging' 2 | DEMO_BRANCH = 'demo' 3 | PRODUCTION_BRANCH = 'master' 4 | -------------------------------------------------------------------------------- /tola/management/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/tola/management/__init__.py -------------------------------------------------------------------------------- /tola/management/commands/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/tola/management/commands/__init__.py -------------------------------------------------------------------------------- /tola/management/commands/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/tola/management/commands/tests/__init__.py -------------------------------------------------------------------------------- /tola/pkg_testrunner.py: -------------------------------------------------------------------------------- 1 | from django.test.runner import DiscoverRunner 2 | from django.conf import settings 3 | 4 | 5 | class PackageTestSuiteRunner(DiscoverRunner): 6 | """ 7 | Runs only tests that belong to INSTALLED_APPS. 8 | """ 9 | def build_suite(self, *args, **kwargs): 10 | suite = super(PackageTestSuiteRunner, self).build_suite(*args, **kwargs) 11 | tests = [] 12 | for case in suite: 13 | app_module = case.__class__.__module__ 14 | add_tests_from_suite = False 15 | for app in settings.INSTALLED_APPS: 16 | if '{}.'.format(app) in app_module: 17 | add_tests_from_suite = True 18 | if add_tests_from_suite: 19 | tests.append(case) 20 | 21 | suite._tests = tests 22 | return suite 23 | -------------------------------------------------------------------------------- /tola/settings/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /tola/settings/dev.py: -------------------------------------------------------------------------------- 1 | from local import * 2 | 3 | DEBUG = True 4 | 5 | OFFLINE_MODE = True 6 | INTERNAL_IPS = ('127.0.0.1',) 7 | 8 | EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend' 9 | EMAIL_FILE_PATH = '/tmp/tola-messages' 10 | -------------------------------------------------------------------------------- /tola/settings/test.py: -------------------------------------------------------------------------------- 1 | from local import * 2 | 3 | ADMINS = ( 4 | ('admin_test', 'admin_test@test.com'), 5 | ) 6 | 7 | DEBUG = True 8 | 9 | EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend' 10 | EMAIL_FILE_PATH = '/tmp/tola-messages' 11 | 12 | ELASTICSEARCH_ENABLED = False 13 | -------------------------------------------------------------------------------- /tola/settings/test_pkg.py: -------------------------------------------------------------------------------- 1 | from test import * 2 | 3 | DJANGO_APPS = [ 4 | 'django.contrib.admin', 5 | 'django.contrib.auth', 6 | 'django.contrib.contenttypes', 7 | 'django.contrib.sites', 8 | ] 9 | 10 | THIRD_PARTY_APPS = [ 11 | 'oauth2_provider', 12 | ] 13 | 14 | LOCAL_APPS = [ 15 | 'formlibrary', 16 | 'indicators', 17 | 'search', 18 | 'tola', 19 | 'workflow', 20 | ] 21 | 22 | INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS 23 | 24 | TEST_RUNNER = 'tola.pkg_testrunner.PackageTestSuiteRunner' 25 | -------------------------------------------------------------------------------- /tola/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/tola/tests/__init__.py -------------------------------------------------------------------------------- /tola/urls.py: -------------------------------------------------------------------------------- 1 | urlpatterns = [] 2 | -------------------------------------------------------------------------------- /tola/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for frds_project project. 3 | 4 | This module contains the WSGI application used by Django's development server 5 | and any production WSGI deployments. It should expose a module-level variable 6 | named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover 7 | this application via the ``WSGI_APPLICATION`` setting. 8 | 9 | Usually you will have the standard Django WSGI application here, but it also 10 | might make sense to replace the whole Django WSGI application with a custom one 11 | that later delegates to the Django one. For example, you could introduce WSGI 12 | middleware here, or combine a Django application with an application of another 13 | framework. 14 | 15 | """ 16 | import os 17 | from os.path import abspath, dirname 18 | from sys import path 19 | 20 | SITE_ROOT = dirname(dirname(abspath(__file__))) 21 | path.append(SITE_ROOT) 22 | 23 | # We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks 24 | # if running multiple sites in the same mod_wsgi process. To fix this, use 25 | # mod_wsgi daemon mode with each site in its own daemon process, or use 26 | # os.environ["DJANGO_SETTINGS_MODULE"] = "jajaja.settings" 27 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tola.settings.local") 28 | 29 | # This application object is used by any WSGI server configured to use this 30 | # file. This includes Django's development server, if the WSGI_APPLICATION 31 | # setting points here. 32 | from django.core.wsgi import get_wsgi_application 33 | application = get_wsgi_application() 34 | 35 | # Apply WSGI middleware here. 36 | # from helloworld.wsgi import HelloWorldApplication 37 | # application = HelloWorldApplication(application) 38 | -------------------------------------------------------------------------------- /workflow/__init__.py: -------------------------------------------------------------------------------- 1 | default_app_config = 'workflow.apps.WorkflowAppConfig' 2 | -------------------------------------------------------------------------------- /workflow/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class WorkflowAppConfig(AppConfig): 5 | name = 'workflow' 6 | verbose_name = 'workflows' 7 | 8 | def ready(self): 9 | import workflow.signals # noqa 10 | -------------------------------------------------------------------------------- /workflow/migrations/0002_auto_20171024_0208.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2017-10-24 09:08 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('workflow', '0001_initial'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AddField( 17 | model_name='historicalsiteprofile', 18 | name='organization', 19 | field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='workflow.Organization'), 20 | ), 21 | migrations.AddField( 22 | model_name='siteprofile', 23 | name='organization', 24 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='workflow.Organization'), 25 | ), 26 | ] 27 | -------------------------------------------------------------------------------- /workflow/migrations/0005_siteprofile_workflowlevel1.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2017-11-14 08:13 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('workflow', '0004_auto_20171109_0242'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='siteprofile', 17 | name='workflowlevel1', 18 | field=models.ManyToManyField(blank=True, to='workflow.WorkflowLevel1'), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /workflow/migrations/0006_auto_20171122_0105.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2017-11-22 09:05 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('workflow', '0005_siteprofile_workflowlevel1'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterField( 17 | model_name='historicalworkflowlevel2', 18 | name='staff_responsible', 19 | field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='workflow.TolaUser'), 20 | ), 21 | migrations.AlterField( 22 | model_name='workflowlevel2', 23 | name='staff_responsible', 24 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='workflow.TolaUser'), 25 | ), 26 | ] 27 | -------------------------------------------------------------------------------- /workflow/migrations/0008_tolasites_whitelisted_domains.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2017-12-11 11:11 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('workflow', '0007_auto_20171204_0203'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='tolasites', 17 | name='whitelisted_domains', 18 | field=models.TextField(blank=True, null=True, verbose_name='Whitelisted Domains'), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /workflow/migrations/0010_auto_20180109_0650.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-01-09 14:50 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('workflow', '0009_auto_20180109_0626'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='dashboard', 17 | name='public_all', 18 | field=models.BooleanField(default=0), 19 | ), 20 | migrations.AddField( 21 | model_name='dashboard', 22 | name='public_in_org', 23 | field=models.BooleanField(default=0), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /workflow/migrations/0012_widget_changed.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-01-11 12:40 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('workflow', '0011_auto_20180110_0509'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='widget', 17 | name='changed', 18 | field=models.BooleanField(default=0), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /workflow/migrations/0013_auto_20180122_1057.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-01-22 10:57 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | dependencies = [ 10 | ('workflow', '0012_widget_changed'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='organization', 16 | name='chargebee_subscription_id', 17 | field=models.CharField(blank=True, max_length=50, null=True), 18 | ), 19 | migrations.AddField( 20 | model_name='organization', 21 | name='chargebee_used_seats', 22 | field=models.IntegerField(blank=True, default=0, null=True), 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /workflow/migrations/0014_organization_oauth_domains.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-02-13 08:30 3 | from __future__ import unicode_literals 4 | 5 | import django.contrib.postgres.fields 6 | from django.db import migrations, models 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('workflow', '0013_auto_20180122_1057'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AddField( 17 | model_name='organization', 18 | name='oauth_domains', 19 | field=django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, max_length=255, null=True, verbose_name='OAuth Domains'), blank=True, null=True, size=None), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /workflow/migrations/0015_auto_20180214_2128.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-02-15 05:28 3 | from __future__ import unicode_literals 4 | 5 | from decimal import Decimal 6 | from django.db import migrations, models 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('workflow', '0014_organization_oauth_domains'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterField( 17 | model_name='workflowlevel3', 18 | name='budget', 19 | field=models.DecimalField(blank=True, decimal_places=2, default=Decimal('0.00'), max_digits=12, null=True, verbose_name='Estimated Budget'), 20 | ), 21 | migrations.AlterField( 22 | model_name='workflowlevel3', 23 | name='cost', 24 | field=models.DecimalField(blank=True, decimal_places=2, default=Decimal('0.00'), max_digits=12, null=True, verbose_name='Actual Cost'), 25 | ), 26 | ] 27 | -------------------------------------------------------------------------------- /workflow/migrations/0017_auto_20180226_0031.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-02-26 08:31 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('workflow', '0016_auto_20180209_0529'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AddField( 17 | model_name='organization', 18 | name='currency_format', 19 | field=models.CharField(blank=True, default='Commas', max_length=50, verbose_name='Currency Format'), 20 | ), 21 | migrations.AddField( 22 | model_name='organization', 23 | name='date_format', 24 | field=models.CharField(blank=True, default='DD.MM.YYYY', max_length=50, verbose_name='Date Format'), 25 | ), 26 | migrations.AddField( 27 | model_name='organization', 28 | name='default_currency', 29 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='workflow.Currency'), 30 | ), 31 | ] 32 | -------------------------------------------------------------------------------- /workflow/migrations/0019_auto_20180309_0423.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-03-09 15:01 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('workflow', '0018_auto_20180302_0814'), 12 | ] 13 | 14 | operations = [ 15 | migrations.RemoveField( 16 | model_name='dashboard', 17 | name='public_all', 18 | ), 19 | migrations.RemoveField( 20 | model_name='dashboard', 21 | name='public_in_org', 22 | ), 23 | migrations.AddField( 24 | model_name='dashboard', 25 | name='public', 26 | field=models.CharField(blank=True, null=True, choices=[('org', 'Organization'), ('all', 'All')], max_length=5), 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /workflow/migrations/0020_product.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-03-20 11:01 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('workflow', '0019_auto_20180309_0423'), 13 | ] 14 | 15 | operations = [ 16 | migrations.CreateModel( 17 | name='Product', 18 | fields=[ 19 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 20 | ('name', models.CharField(max_length=255)), 21 | ('type', models.CharField(blank=True, max_length=255, null=True)), 22 | ('reference_id', models.CharField(blank=True, max_length=255, null=True, verbose_name='Product identifier')), 23 | ('create_date', models.DateTimeField(auto_now_add=True)), 24 | ('edit_date', models.DateTimeField(auto_now=True)), 25 | ('workflowlevel2', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='products', to='workflow.WorkflowLevel2')), 26 | ], 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /workflow/migrations/0022_organization_allow_budget_decimal.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-03-23 10:04 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('workflow', '0021_auto_20180323_0215'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='organization', 17 | name='allow_budget_decimal', 18 | field=models.BooleanField(default=True, verbose_name='Allow Budget in Decimal'), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /workflow/migrations/0024_auto_20180620_0537.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-06-20 12:37 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('workflow', '0023_auto_20180425_0136'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='dashboard', 17 | name='dashboard_uuid', 18 | field=models.UUIDField(blank=True, null=True, default=None, verbose_name='Dashboard UUID'), 19 | ), 20 | migrations.AddField( 21 | model_name='dashboard', 22 | name='public_url_token', 23 | field=models.CharField(blank=True, max_length=255, null=True), 24 | ), 25 | migrations.AlterField( 26 | model_name='dashboard', 27 | name='public', 28 | field=models.CharField(blank=True, choices=[('org', 'Organization'), ('url', 'URL'), ('all', 'All')], max_length=5, null=True), 29 | ), 30 | ] 31 | -------------------------------------------------------------------------------- /workflow/migrations/0025_auto_20180620_0557.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-06-20 12:57 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | import uuid 7 | 8 | 9 | def set_dashboard_uuid(apps, schema_editor): 10 | Dashboard = apps.get_model('workflow', 'Dashboard') 11 | for dashboard in Dashboard.objects.all(): 12 | dashboard.dashboard_uuid = uuid.uuid4() 13 | dashboard.save() 14 | 15 | 16 | class Migration(migrations.Migration): 17 | 18 | dependencies = [ 19 | ('workflow', '0024_auto_20180620_0537'), 20 | ] 21 | 22 | operations = [ 23 | migrations.RunPython(set_dashboard_uuid), 24 | migrations.AlterField( 25 | model_name='dashboard', 26 | name='dashboard_uuid', 27 | field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True, verbose_name='Dashboard UUID'), 28 | ), 29 | ] 30 | -------------------------------------------------------------------------------- /workflow/migrations/0026_organization_phone.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-06-25 08:41 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('workflow', '0025_auto_20180620_0557'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='organization', 17 | name='phone', 18 | field=models.CharField(blank=True, max_length=20, null=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /workflow/migrations/0027_auto_20180814_0045.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-08-14 11:45 3 | from __future__ import unicode_literals 4 | 5 | import django.contrib.postgres.fields.jsonb 6 | from django.db import migrations 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('workflow', '0026_organization_phone'), 13 | ] 14 | 15 | operations = [ 16 | migrations.RemoveField( 17 | model_name='dashboard', 18 | name='public', 19 | ), 20 | migrations.AddField( 21 | model_name='dashboard', 22 | name='public', 23 | field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, help_text='Public information with the structure:{all: (bool), org: (bool), url: (bool)}', null=True), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /workflow/migrations/0029_auto_20180831_0452.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-08-31 11:52 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('workflow', '0028_auto_20180816_0141'), 12 | ] 13 | 14 | operations = [ 15 | #migrations.RemoveField( 16 | # model_name='historicalworkflowlevel2', 17 | # name='address', 18 | #), 19 | #migrations.RemoveField( 20 | # model_name='workflowlevel2', 21 | # name='address', 22 | #), 23 | ] 24 | -------------------------------------------------------------------------------- /workflow/migrations/0030_auto_20180907_0704.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-09-07 14:04 3 | from __future__ import unicode_literals 4 | 5 | import django.contrib.postgres.fields.hstore 6 | from django.db import migrations 7 | from django.db.utils import ProgrammingError 8 | 9 | 10 | def create_fields(apps, schema_editor): 11 | # If fields are not there, add them. If they were added before, then 12 | # ignore the error. 13 | try: 14 | migrations.AddField( 15 | model_name='historicalworkflowlevel2', 16 | name='address', 17 | field=django.contrib.postgres.fields.hstore.HStoreField(blank=True, help_text='Address object with the structure: street (string), house_number (string), postal_code: (string), city (string), country (string)', null=True), 18 | ) 19 | migrations.AddField( 20 | model_name='workflowlevel2', 21 | name='address', 22 | field=django.contrib.postgres.fields.hstore.HStoreField(blank=True, help_text='Address object with the structure: street (string), house_number (string), postal_code: (string), city (string), country (string)', null=True), 23 | ) 24 | except ProgrammingError: 25 | pass 26 | 27 | 28 | class Migration(migrations.Migration): 29 | 30 | dependencies = [ 31 | ('workflow', '0029_auto_20180831_0452'), 32 | ] 33 | 34 | operations = [ 35 | migrations.RunPython(create_fields), 36 | ] 37 | -------------------------------------------------------------------------------- /workflow/migrations/0031_auto_20181024_0217.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-10-24 09:17 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('workflow', '0030_auto_20180907_0704'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='historicalsiteprofile', 17 | name='city', 18 | field=models.CharField(blank=True, max_length=85, null=True), 19 | ), 20 | migrations.AddField( 21 | model_name='siteprofile', 22 | name='city', 23 | field=models.CharField(blank=True, max_length=85, null=True), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /workflow/migrations/0032_auto_20181206_0228.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2018-12-06 10:28 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('workflow', '0031_auto_20181024_0217'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='historicalsiteprofile', 17 | name='notes', 18 | field=models.TextField(blank=True), 19 | ), 20 | migrations.AddField( 21 | model_name='siteprofile', 22 | name='notes', 23 | field=models.TextField(blank=True), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /workflow/migrations/0033_auto_20190213_0302.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.17 on 2019-02-13 11:02 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('workflow', '0032_auto_20181206_0228'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterField( 17 | model_name='approvalworkflow', 18 | name='approval_type', 19 | field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='approval_type', to='workflow.ApprovalType'), 20 | ), 21 | migrations.AlterField( 22 | model_name='siteprofile', 23 | name='type', 24 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='workflow.ProfileType'), 25 | ), 26 | ] 27 | -------------------------------------------------------------------------------- /workflow/migrations/0034_dashboard_tola_user_uuid.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.17 on 2019-02-27 05:11 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('workflow', '0033_auto_20190213_0302'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='dashboard', 17 | name='tola_user_uuid', 18 | field=models.CharField(blank=True, max_length=255, null=True, verbose_name='TolaUser UUID'), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /workflow/migrations/0034_office_organization.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.17 on 2019-02-22 11:04 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('workflow', '0033_auto_20190213_0302'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AddField( 17 | model_name='office', 18 | name='organization', 19 | field=models.ForeignKey(blank=True, help_text='Related Org to associate with', null=True, on_delete=django.db.models.deletion.CASCADE, to='workflow.Organization'), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /workflow/migrations/0035_auto_20190226_2147.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.17 on 2019-02-27 05:47 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('workflow', '0034_dashboard_tola_user_uuid'), 12 | ] 13 | 14 | operations = [ 15 | migrations.RenameField( 16 | model_name='dashboard', 17 | old_name='tola_user_uuid', 18 | new_name='created_by', 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /workflow/migrations/0036_merge_20190226_2343.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.17 on 2019-02-27 07:43 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('workflow', '0035_auto_20190226_2147'), 12 | ('workflow', '0034_office_organization'), 13 | ] 14 | 15 | operations = [ 16 | ] 17 | -------------------------------------------------------------------------------- /workflow/migrations/0037_auto_20190306_0136.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.17 on 2019-03-06 09:36 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('workflow', '0036_merge_20190226_2343'), 12 | ] 13 | 14 | operations = [ 15 | migrations.RemoveField( 16 | model_name='product', 17 | name='workflowlevel2', 18 | ), 19 | migrations.DeleteModel( 20 | name='Product', 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /workflow/migrations/0038_auto_20190308_0542.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.17 on 2019-03-08 13:42 3 | from __future__ import unicode_literals 4 | 5 | import django.contrib.postgres.fields 6 | from django.db import migrations, models 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('workflow', '0037_auto_20190306_0136'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AddField( 17 | model_name='dashboard', 18 | name='blacklist', 19 | field=django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=255), blank=True, default=[], size=None), 20 | preserve_default=False, 21 | ), 22 | migrations.AddField( 23 | model_name='dashboard', 24 | name='shared_wfl1_uuids', 25 | field=django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=255), blank=True, default=[], size=None), 26 | preserve_default=False, 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /workflow/migrations/0038_auto_20190311_2249.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.17 on 2019-03-12 05:49 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('workflow', '0037_auto_20190306_0136'), 12 | ] 13 | 14 | operations = [ 15 | migrations.RemoveField( 16 | model_name='organization', 17 | name='industry', 18 | ), 19 | migrations.DeleteModel( 20 | name='Industry', 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /workflow/migrations/0039_auto_20190308_0546.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.17 on 2019-03-08 13:46 3 | from __future__ import unicode_literals 4 | 5 | import django.contrib.postgres.fields 6 | from django.db import migrations, models 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('workflow', '0038_auto_20190308_0542'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterField( 17 | model_name='dashboard', 18 | name='blacklist', 19 | field=django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=255), blank=True, default=[], size=None), 20 | ), 21 | migrations.AlterField( 22 | model_name='dashboard', 23 | name='shared_wfl1_uuids', 24 | field=django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=255), blank=True, default=[], size=None), 25 | ), 26 | ] 27 | -------------------------------------------------------------------------------- /workflow/migrations/0040_merge_20190312_0047.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.17 on 2019-03-12 07:47 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('workflow', '0039_auto_20190308_0546'), 12 | ('workflow', '0038_auto_20190311_2249'), 13 | ] 14 | 15 | operations = [ 16 | ] 17 | -------------------------------------------------------------------------------- /workflow/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/workflow/migrations/__init__.py -------------------------------------------------------------------------------- /workflow/templates/email/organization/exceed_seats.txt: -------------------------------------------------------------------------------- 1 | Hi {{ org_admin_name }}, 2 | 3 | Your user numbers in our system don’t match 🤔 4 | 5 | Purchased user seats: {{ available_seats }} 6 | Current edit users in the system: {{ used_seats }} 7 | 8 | For all your edit users to continue using TolaData, please proceed to our payment portal [link below] and add seats to your subscription plan. 9 | 10 | {{ payment_portal_url }} 11 | 12 | Thank you from all of us at TolaData! 13 | -------------------------------------------------------------------------------- /workflow/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toladata/TolaActivity/364d5c214e4966ff739873addb32ab4071b2d9b8/workflow/tests/__init__.py --------------------------------------------------------------------------------