306 Commits

Author SHA1 Message Date
Leo Kivikunnas 06723e3f69 Styling claim form 2019-11-10 14:32:16 +02:00
Leo Kivikunnas ba9b5d02b2 Add attachment to emails 2019-09-09 20:29:00 +03:00
Leo Kivikunnas 242d143a5e Expenses claim should now send dummy email on POST 2019-06-03 20:33:28 +03:00
Leo Kivikunnas 2bf19d357e Fixed IBAN validation and amount field in exenses claim and added some tests 2019-06-03 19:35:08 +03:00
Aarni Halinen 7e31f72301 Update docker image to new registry 2019-05-27 23:40:27 +03:00
Aarni Halinen 68bb003411 Fix .md file style warnings 2019-05-27 23:38:54 +03:00
Antti Mäki 7133f36e5d cd: web2.0: No such file or directory 2019-05-27 18:01:39 +00:00
Leo Kivikunnas c9962c4d8e Fixed style errors 2019-05-27 20:46:56 +03:00
Leo Kivikunnas 5832bd1765 Added venv got .eslintignore 2019-05-27 20:35:45 +03:00
Leo Kivikunnas 4046d2c753 Started work on expenses claim 2019-05-27 20:32:18 +03:00
Aarni Halinen 93298618ae Add docker login to deploy dev 2019-05-27 17:48:48 +03:00
Aarni Halinen 709a637ae2 Update repo url 2019-05-23 19:07:33 +03:00
Aarni Halinen a88bb30b62 Revert "Use same registry as frontend"
This reverts commit 38527207ac.
2019-05-23 19:03:57 +03:00
Aarni Halinen 38527207ac Use same registry as frontend 2019-05-23 15:40:39 +00:00
Aarni Halinen 6f90fcc016 Fix docker login on publish 2019-05-23 05:09:09 +00:00
Aarni Halinen 1e633ded31 Use gitlab-deploy-token
https://docs.gitlab.com/ee/user/project/deploy_tokens/
2019-05-22 03:51:15 +00:00
Aarni Halinen 4b3b8be4e4 Update publish in gitlab-ci.yml 2019-05-22 03:03:26 +00:00
Aarni Halinen effd58a424 Remove ilmotunkki 2019-04-02 15:16:23 +03:00
Aarni Halinen 850587006c Merge branch 'feature-infoscreen-lunch' into 'develop'
Feature infoscreen lunch

See merge request vtmk/web2.0!136
2019-03-26 17:39:19 +02:00
Aarni Halinen 423b574cca Add Today's lunch infoscreen 2019-03-26 17:33:09 +02:00
Aarni Halinen 7bb4a6cfc1 Fix webapp tests 2019-03-26 17:10:25 +02:00
Aarni Halinen 94f392ab87 Set pipenv and pyenv support 2019-03-26 15:44:50 +02:00
Aarni Halinen ccef40e63f Fix pycodestyle on webapp 2019-03-26 14:41:11 +02:00
Aarni Halinen 1c51b666ab Clean old infoscreen code and statics 2019-03-26 14:39:51 +02:00
Jan Tuomi b5462d5757 Turn questions field into a text field 2019-03-13 16:45:18 +02:00
Jan Tuomi 587632d7a3 Rename signup form fields and add title 2019-03-13 15:54:23 +02:00
Jan Tuomi 11c92cdd5f Fix feed serializer and view 2019-03-13 13:53:06 +02:00
Jan Tuomi e4577e13e0 Add autohide_enabled field to Feed 2019-03-13 13:52:44 +02:00
Jan Tuomi 6365e0c63e Allow POST requests to event API 2019-03-12 15:17:07 +02:00
Aarni Halinen 4735541344 Add missing migration 2019-03-12 15:16:08 +02:00
Aarni Halinen 8e40434867 Update favicon 2019-03-12 15:14:09 +02:00
Aarni Halinen 8194ab43cd Add location to Event object 2019-03-12 15:10:52 +02:00
Jan Tuomi a708a6377d Fix JWT auth settings in base.py 2019-03-11 20:51:29 +02:00
Aarni Halinen 3fc810697a Merge branch 'feature-heevibotti' into 'develop'
Add barebones to better tgbot

See merge request vtmk/web2.0!134
2019-02-08 19:25:10 +02:00
Aarni Halinen 3305704926 Fix pycodestyle 2019-02-08 19:10:36 +02:00
okalintu 206ec80a9a Remove f-word 2019-02-08 19:05:22 +02:00
okalintu dce19b8d38 Ensure that unnecessary tg messages will not crash anything useful 2019-02-08 18:31:45 +02:00
okalintu 8a8751ce66 Add barebones to better tgbot
Also send tg spam from ohlhafv challenges!
2019-02-08 18:26:06 +02:00
Aarni Halinen 0f0389b8ff Merge branch 'develop' into 'master'
Ohlhafv hotfix: email

See merge request vtmk/web2.0!133
2019-02-04 18:38:34 +02:00
Aarni Halinen 061c9c8483 Fix Ohlhafv email date 2019-02-04 18:24:49 +02:00
Aarni Halinen 005d34daf5 Add EOF blank line base.py 2019-01-29 13:35:59 +02:00
Aarni Halinen 95e028d546 Revert "Remove underscore.js"
This reverts commit 50268b98a9.
2019-01-29 12:53:26 +02:00
Jan Tuomi 95c29d8528 Increase JWT expiration time to 1 week 2019-01-28 21:39:45 +02:00
Jan Tuomi bda342b05b Add gunicorn to production requirements 2019-01-28 21:39:30 +02:00
Aarni Halinen 889ad4f980 Merge branch 'develop' into 'master'
Ohlhafv and dependency fixes

Closes #117

See merge request vtmk/web2.0!132
2019-01-28 16:01:56 +02:00
Jan Tuomi a5bca8eab1 Add JWT verify endpoint 2019-01-17 15:48:49 +02:00
Aarni Halinen 2dfb53bd5e Use node:alpine 2019-01-15 20:04:21 +02:00
jaine 474df33a99 Fix borders in ohlhafv form 2019-01-15 16:42:08 +02:00
Aarni Halinen a2906966ba Use node latest on CI 2019-01-15 16:06:04 +02:00
Aarni Halinen a81096fa13 Update pyexcel to most recent version
Updating openpyxl or pyexcel-xlsx results error in tablib dependency
2019-01-15 16:02:55 +02:00
Aarni Halinen b56ff6c5cd Rollback pyexcel dependencies 2019-01-15 15:49:25 +02:00
Jan Tuomi 168de8088b Update Django to 2.1.5 and setup JWT auth 2019-01-15 15:41:40 +02:00
Aarni Halinen e7862df57c Use Python 3.5 image consistently 2019-01-15 15:25:40 +02:00
Jan Tuomi ec829a5683 Update .gitignore and requirements.txt 2019-01-15 14:00:20 +02:00
jaine bb3476a8ad Updated ohlhafv page css and img 2019-01-14 19:55:04 +02:00
jaine bab5c88061 Add help in error case in mac installation instruction 2019-01-14 19:15:02 +02:00
Aarni Halinen 7431aadfba Merge branch 'feature-API-filtering' into 'develop'
Feature api filtering

See merge request vtmk/web2.0!131
2018-11-18 19:05:14 +02:00
Aarni Halinen 1ecf3c368b Add authentication for post test 2018-11-18 18:58:12 +02:00
Aarni Halinen d3e6013840 Fix API test by getting results from json 2018-11-18 18:12:41 +02:00
Aarni Halinen e1220d17bb Add filtering to REST API 2018-11-18 17:56:32 +02:00
Aarni Halinen 55fdf8f60d Add filtering for Event and Signup ViewSets 2018-11-18 17:54:11 +02:00
Aarni Halinen 65aac3daf1 Add LimitOffsetPagination 2018-11-18 17:54:11 +02:00
Joel Lavikainen 1f8e9e582a Make tag tests more generic 2018-11-18 17:52:34 +02:00
Aarni Halinen 97e6ce3d8d Fix webapp migrations 2018-11-18 13:46:31 +02:00
Aarni Halinen 316ab679f8 Remove webapp migration 0048 2018-11-18 13:33:30 +02:00
Aarni Halinen bf5620c3b6 Revert "Remove PK slug from ancient migration"
This reverts commit 90f430c95c.
2018-11-18 13:31:48 +02:00
Joel Lavikainen 642aa9847f Revert model change 2018-11-18 04:58:59 +02:00
Aarni Halinen 90f430c95c Remove PK slug from ancient migration 2018-11-18 04:50:34 +02:00
Joel Lavikainen bf4c5bf3d9 Fix feed testcase 2018-11-18 04:43:49 +02:00
Joel Lavikainen b7beb72409 Fix linting errors 2018-11-18 04:39:31 +02:00
Joel Lavikainen 0617dd6a93 Add generation of field data 2018-11-18 04:29:04 +02:00
Joel Lavikainen d99f9c53f7 Add migration with fix 2018-11-18 04:21:01 +02:00
Joel Lavikainen 3cfa0df43b Add missing lines to coverage report 2018-11-17 22:40:43 +02:00
Joel Lavikainen dc2982965e Add migration related to tag change 2018-11-17 22:30:03 +02:00
Joel Lavikainen 3c58d764bd Fix Feed link to Tag 2018-11-17 21:46:17 +02:00
Joel Lavikainen 4d2584dee4 Change Tag primary key to id 2018-11-17 21:45:26 +02:00
Joel Lavikainen 3294d6ffa0 Fix Tag serializer 2018-11-17 20:41:45 +02:00
Joel Lavikainen 8398928a97 Add dummy data generation for tag objects 2018-11-17 20:40:42 +02:00
Joel Lavikainen 09a2e09c1b Add tests for Tag REST api 2018-11-17 20:40:08 +02:00
Joel Lavikainen d0f5bc223b Add id to Tag data 2018-11-17 17:57:06 +02:00
Joel Lavikainen 7a58fb0af5 Add tag id support for Feed in REST 2018-11-17 17:52:35 +02:00
Joel Lavikainen 395c597a7f Add tags to REST API 2018-11-17 17:34:36 +02:00
Aarni Halinen e43734e32e Fix naive dates to aware datetimes 2018-10-25 14:36:51 +03:00
Aarni Halinen eb5659d0da Minor cleanup of infoscreen 2018-10-24 20:54:31 +03:00
Aarni Halinen 50268b98a9 Remove underscore.js 2018-10-24 20:54:08 +03:00
Aarni Halinen 4a2a5f9d76 Bugfix #117: API Event tags
Add API for tags so events can get the related field.
2018-10-23 14:45:08 +03:00
Aarni Halinen ef6b8ed5a5 Merge branch 'develop' into 'master'
Kaehmy translations

See merge request vtmk/web2.0!129
2018-10-20 23:24:04 +03:00
Aarni Halinen b1eda70e7a Kaehmy translations 2018-10-20 23:14:48 +03:00
Aarni Halinen 2ae9ee7352 Merge branch 'develop' into 'master'
GDPR kaehmy

See merge request vtmk/web2.0!128
2018-10-20 23:00:59 +03:00
Aarni Halinen f7b00ab3cc Add GDPR checkbox 2018-10-20 22:51:42 +03:00
Aarni Halinen 9cad12d879 Login required for kaehmy export page 2018-10-20 22:39:22 +03:00
Aarni Halinen 5967d0f7b3 Merge branch 'develop' into 'master'
Replace kahmyopas.pdf

See merge request vtmk/web2.0!127
2018-10-19 13:50:51 +03:00
Aarni Halinen d4800c449d Replace kahmyopas.pdf 2018-10-19 13:41:27 +03:00
Aarni Halinen 8f9c504bec Merge branch 'develop' into 'master'
Update kaehmy banner

See merge request vtmk/web2.0!126
2018-10-18 23:31:30 +03:00
Aarni Halinen d3d4ce5e5d Real update to kaehmy banner 2018-10-18 23:22:04 +03:00
Aarni Halinen 9dbc2424b1 Update kaehmy banner 2018-10-18 23:02:16 +03:00
Aarni Halinen 32771493f3 Merge branch 'develop' into 'master'
Remove culture category

See merge request vtmk/web2.0!125
2018-10-18 22:43:14 +03:00
Aarni Halinen 5b38065f13 Remove culture category 2018-10-18 21:21:29 +03:00
Aarni Halinen 1879c265cd Update kaehmy dates 2018-10-18 21:20:37 +03:00
Aarni Halinen c654c41380 Merge branch 'develop' into 'master'
Update final kaehmy date

See merge request vtmk/web2.0!124
2018-10-16 19:04:12 +03:00
Aarni Halinen 4273b95b70 Update final kaehmy date 2018-10-16 18:53:29 +03:00
Aarni Halinen e4cffd5667 Merge branch 'develop' into 'master'
Update Kaehmy pages

See merge request vtmk/web2.0!123
2018-10-15 20:01:21 +03:00
Aarni Halinen e96698ef2e Update kaehmy translations 2018-10-15 18:33:14 +03:00
Aarni Halinen e04b8ddb9b Update kaehmy dates 2018-10-15 18:30:08 +03:00
Aarni Halinen 6fe3e69cd9 Update package-lock 2018-10-03 14:38:50 +03:00
Aarni Halinen 7d1a8bd284 Ignore sik_test 2018-10-03 14:38:30 +03:00
Aarni Halinen 5b44d2e4c7 Fix favicon 2018-09-10 21:08:37 +03:00
Aarni Halinen fa0954e8ca Merge branch 'develop' into 'master'
Sosso infocreen fix, Django 2.0, Rest Framework

See merge request vtmk/web2.0!121
2018-09-10 13:35:12 +03:00
Aarni Halinen 8552bde245 Fix members static file paths 2018-09-10 13:16:51 +03:00
Aarni Halinen 9a4d7fc498 Fix Sosso containers 2018-09-10 12:04:50 +03:00
Aarni Halinen 6dea241408 Add missing import 2018-09-10 11:43:59 +03:00
Aarni Halinen b3b1bec12c Add special characters to Sosso infoscreen 2018-09-10 11:40:57 +03:00
Aarni Halinen 02cc305abf Fix indentation 2018-09-02 22:27:14 +03:00
Aarni Halinen ffe0c45eea Fix few kaehmy problems
- Fix variable naming in statistics
- Add scope for html files to fix rendering of errors
- Fix footer.css path and remove duplicate
2018-09-02 22:23:52 +03:00
Aarni Halinen 499ddc0979 New kaehmy BaseRole class 2018-09-02 22:03:54 +03:00
Aarni Halinen b154ffb79e Add normal permissions to DRF root 2018-08-21 19:27:18 +03:00
Aarni Halinen 87dfab0e57 Change dev server port on gitlab-ci.yml 2018-08-15 23:37:40 +03:00
Aarni Halinen 92ec8b1b4e Dev server docker and host ports to 8000 2018-08-15 23:32:41 +03:00
Aarni Halinen ac8fb0bfe3 Set authentication to webapp DRF 2018-07-24 19:09:42 +03:00
Aarni Halinen 0ce6af8f7c Fix import and redefinition issues 2018-07-24 18:30:21 +03:00
Aarni Halinen 053b705cc1 Merge branch 'Django2.0' into 'develop'
:Django2.0

See merge request vtmk/web2.0!115
2018-07-24 18:29:00 +03:00
Aarni Halinen 3676f23f65 Fix payment autocomplete permissions and remove test skips
Fixed decorators in urls.py. Moved to method_decorators on view class
2018-07-24 18:19:57 +03:00
Aarni Halinen 7e821f277f Fix pycodestyle 2018-07-23 12:38:14 +03:00
Aarni Halinen 91cbdef71f Merge branch 'develop' into 'Django2.0'
# Conflicts:
#   webapp/urls.py
2018-07-18 20:44:23 +03:00
Aarni Halinen 0cfb78bc69 Remove not used api_view 2018-07-18 20:40:44 +03:00
Aarni Halinen 01c20b1a6e Add contacts API 2018-07-18 20:40:19 +03:00
Aarni Halinen 1711aca5ec Add templatequestions API 2018-07-18 20:39:08 +03:00
Aarni Halinen c536899cc9 Bring about page back 2018-07-18 20:12:06 +03:00
Aarni Halinen 60da9d8256 Add event update serializer 2018-07-18 20:11:24 +03:00
Aarni Halinen a923e225e8 API root to /api 2018-07-18 18:41:20 +03:00
Aarni Halinen 2d7c9d779a Feed API added 2018-07-18 18:37:01 +03:00
Aarni Halinen aea9898563 Skip failing autocomplete test 2018-07-17 22:00:39 +03:00
Aarni Halinen 4e3f71ea43 Remove duplicate imports 2018-07-17 22:00:08 +03:00
Aarni Halinen 6acbdbc760 Update to Django 2.0.7 for sqlite bugfix 2018-07-17 21:37:23 +03:00
Aarni Halinen 11b6e68fe1 Remove password_reset and own login, redirect to admin/login
Django admin login to be used. Thus we should be able to upgrade to
Django2.0
2018-07-17 20:58:13 +03:00
Aarni Halinen cc3aa66e49 Merge branch 'develop' into Django2.0 2018-07-17 20:57:58 +03:00
Aarni Halinen 563344e8b4 Merge branch 'feature-events' into 'develop'
Basic API for events

See merge request vtmk/web2.0!120
2018-07-17 18:43:01 +03:00
Aarni Halinen 129b8e4601 Use id instead of url for SignUpSerializer 2018-07-10 22:42:37 +03:00
Aarni Halinen efde69984d Revert changes to base.py 2018-07-10 22:42:05 +03:00
Aarni Halinen c66c8e7367 Rest framework for Event and SignupForm 2018-07-10 22:33:26 +03:00
Aarni Halinen c31f454c78 Move signup models back to webapp 2018-07-05 18:58:33 +03:00
Aarni Halinen 18926d16d1 Create new signup related models 2018-06-19 20:46:06 +03:00
Aarni Halinen 4e8adebb2d Move Event and Registration model to own app 2018-06-05 19:33:35 +03:00
Aarni Halinen 0207bdf22b Upgrade psycopg2 2018-05-31 17:26:49 +03:00
Aarni Halinen 5caacd8f44 Add and fix translations 2018-05-22 23:54:58 +03:00
Aarni Halinen d7a3433d2c Merge branch 'feature-contacts' into develop
Conflicts:
	webapp/admin.py
	webapp/models.py
	webapp/views.py
2018-05-16 22:49:38 +03:00
Aarni Halinen 6e68e106aa Update contact models and template 2018-05-16 22:39:43 +03:00
Aarni Halinen aeda06374d Merge branch 'develop' into 'master'
Filter paid member fees by date

See merge request vtmk/web2.0!118
2018-05-14 01:45:07 +03:00
Aarni Halinen 9225ff5967 Filter paid member fees by date 2018-05-14 01:36:11 +03:00
Aarni Halinen ac64a1766f Merge branch 'develop' into 'master'
Member features into master

Closes #103

See merge request vtmk/web2.0!117
2018-05-13 13:35:50 +03:00
Aarni Halinen 6996bb8015 Merge branch 'feature-number-of-members' into 'develop'
Show number of paid members in member list

See merge request vtmk/web2.0!116
2018-05-13 13:15:30 +03:00
Aarni Halinen 7aff7c46ee Fix pycodestyle 2018-05-13 13:06:19 +03:00
Aarni Halinen 882732d054 Show number of paid members in member list
Member filtering also applies to this feature. Moved 'last_paid' Subquery to Member method
2018-05-13 13:02:27 +03:00
Aarni Halinen 9e0d911f7b Fix date rendering 2018-05-09 22:16:40 +03:00
Aarni Halinen ab6b7d19fb Update pyexcel 2018-05-09 21:24:36 +03:00
Aarni Halinen b95be67051 Fix pycodestyle 2018-05-09 20:24:16 +03:00
Aarni Halinen 48b6ed5b69 Update Django 2.0 2018-05-09 20:05:20 +03:00
Aarni Halinen e25041d38d Update django-nose 2018-05-09 18:57:29 +03:00
Aarni Halinen 7bc77ef232 Update django-suit 2018-05-09 18:49:01 +03:00
Aarni Halinen 0f8a7d76da Update auditlog 2018-05-09 18:46:35 +03:00
Aarni Halinen ecf34d9039 Fix deprecations in project 2018-05-09 18:33:59 +03:00
Aarni Halinen a9cf253c83 Silence pyexcel DEBUG logs
Close issue #103
2018-05-07 01:12:54 +03:00
Aarni Halinen 884c2552a8 Merge branch 'develop' into 'master'
Merge sorting fix

Closes #105

See merge request vtmk/web2.0!114
2018-03-26 18:09:27 +03:00
Aarni Halinen 45e98e0220 Fix uncommited code 2018-03-02 02:57:26 +02:00
Aarni Halinen d8ea26c777 Pycodestyle fixes 2018-03-02 02:48:18 +02:00
Aarni Halinen c398e53750 Add translations 2018-03-02 02:45:59 +02:00
Aarni Halinen 9ce0eccfce Move member specific error to member app 2018-03-02 02:43:02 +02:00
Aarni Halinen 17e6bb86ed Fix last paid sorting
Bug #105. Rendering needs better formatting.
2018-03-02 02:40:42 +02:00
Aarni Halinen a1b85b3c6c Merge branch 'bugfix-members-sort' into 'develop'
Bugfix: #105

See merge request vtmk/web2.0!113
2018-03-02 00:40:28 +02:00
Aarni Halinen fafc988a60 Fix sorting bug #105
Also removed unneeded code
2018-03-02 00:32:11 +02:00
Elias 55bcc78670 Sorted roles by committees and some basic layout 2018-03-02 00:31:10 +02:00
Elias 7bc277a978 korjauksia 2018-03-01 20:53:31 +02:00
Elias 780e2d6acb Committee model 2018-03-01 19:28:27 +02:00
Aarni Halinen bbc5743c39 Add VSCode workspace files to gitignore 2018-03-01 19:27:51 +02:00
Aarni Halinen f9082237e6 Merge branch 'develop' into 'master'
Develop

See merge request vtmk/web2.0!112
2018-02-26 16:13:05 +02:00
Jan Tuomi 3298e55fb0 Fix password reset form error 2018-02-25 20:34:39 +02:00
Aarni Halinen 2b2d20f796 Remove references to deleted css files 2018-02-22 16:31:12 +02:00
Aarni Halinen a72b313b83 Merge branch 'develop' into 'master'
Revert deletion of footer-padder element

See merge request vtmk/web2.0!111
2018-02-22 01:51:53 +02:00
Aarni Halinen 117802bf10 Revert deletion on footer-padder element 2018-02-22 01:43:15 +02:00
Aarni Halinen 94f8a92e65 Merge branch 'develop' into 'master'
Merge footer fix

See merge request vtmk/web2.0!110
2018-02-22 00:48:16 +02:00
Aarni Halinen 8bd53ba897 Fix footer bug #104 2018-02-21 22:18:43 +02:00
Aarni Halinen 5114b2ef85 Revert "Remove bugging footer from infoscreen"
This reverts commit d7f53b9700.
2018-02-06 20:47:43 +02:00
Aarni Halinen f80cbd7457 Merge branch 'develop' into 'master'
Hide bugging infoscreen footer

See merge request vtmk/web2.0!109
2018-02-06 19:40:53 +02:00
Aarni Halinen d7f53b9700 Remove bugging footer from infoscreen 2018-02-06 19:32:28 +02:00
Aarni Halinen 1ab3180c0d Add 'Wall' flag to pre-push hook
This should help noticing deprecations
2018-02-05 10:25:01 +02:00
Aarni Halinen 009495b11b Merge branch 'develop' into 'master'
Add message to Ohlhafv email

See merge request vtmk/web2.0!108
2018-02-01 22:36:28 +02:00
Aarni Halinen b8a8cb2c6d Add message to Ohlhafv email 2018-02-01 22:23:02 +02:00
Aarni Halinen f9bb4bba25 Merge branch 'develop' into 'master'
ABB infoscreen fixes

See merge request vtmk/web2.0!107
2018-02-01 22:22:02 +02:00
Aarni Halinen a56e8ef241 Fix typo 2018-02-01 22:11:50 +02:00
Aarni Halinen d5d11edbe7 Fix remark issues in ilmotunkki readme 2018-02-01 16:32:14 +02:00
Aarni Halinen f7c2516cd7 Fix ABB.css header height issue 2018-02-01 16:26:57 +02:00
Aarni Halinen 45b27e3ac9 Fix ABB.html empty jobs path 2018-02-01 15:53:04 +02:00
Aarni Halinen fe71f24ced Merge branch 'develop' into 'master'
Fix ABB css in infoscreen

See merge request vtmk/web2.0!106
2018-01-30 17:36:35 +02:00
Aarni Halinen 52613ba7d4 Fix ABB css in infoscreen 2018-01-30 17:28:14 +02:00
Aarni Halinen af2719082e Merge branch 'develop' into 'master'
Develop

See merge request vtmk/web2.0!105
2018-01-30 17:10:52 +02:00
Aarni Halinen f136b34b6c Merge branch 'hotfix-ohlhafv-form' into 'develop'
Remove unneeded challenger email field

See merge request vtmk/web2.0!104
2018-01-30 17:00:56 +02:00
Aarni Halinen 4d90454cf8 Remove unneeded challenger email field 2018-01-30 16:48:41 +02:00
Aarni Halinen 82e0c5c995 Merge branch 'feature-ohlhafv-mail' into 'develop'
Feature ohlhafv mail

See merge request vtmk/web2.0!103
2018-01-30 16:44:03 +02:00
Aarni Halinen dec3bf5ccf Remove old code 2018-01-30 16:34:53 +02:00
Aarni Halinen 23c00ce167 Add Email sending to Ohlhafv 2018-01-30 16:23:19 +02:00
Aarni Halinen bdc21f79e8 Fix missing settings import 2018-01-30 14:50:32 +02:00
Aarni Halinen 2fc71eabe3 Merge branch 'feature-refactor-webapp' into 'develop'
Feature refactor webapp

See merge request vtmk/web2.0!102
2018-01-30 11:38:58 +02:00
Jan Tuomi 3debd4b1ec Fix comment data migration 2018-01-30 10:51:20 +02:00
Jan Tuomi b765ae37e8 Remove unused print 2018-01-28 23:45:40 +02:00
Jan Tuomi 9eae16110c Write data migration for ohlhafv challenges 2018-01-28 23:39:27 +02:00
Jan Tuomi ce1f4eb7c9 Write data migrations for kaehmys 2018-01-28 23:30:22 +02:00
Jan Tuomi 661dc84973 Fix pycodestyle 2018-01-28 21:19:19 +02:00
Jan Tuomi 6b21ea4af8 Move postgres init to own script 2018-01-28 21:14:00 +02:00
Jan Tuomi 37ab278086 Refactor member register 2018-01-28 20:59:15 +02:00
Jan Tuomi 509b157d65 Refactor coffee scale app 2018-01-28 20:32:07 +02:00
Jan Tuomi 253f720043 Restructure webapp and infoscreen 2018-01-28 20:23:56 +02:00
Jan Tuomi bdf6b469ad Move ohlhafv to its own app 2018-01-28 18:54:45 +02:00
Jan Tuomi 7dc9fac597 Fix kaehmy styles and templates 2018-01-28 16:56:51 +02:00
Jan Tuomi 77330dffe9 Refactor how url loading works for static files 2018-01-26 08:22:48 +02:00
Jan Tuomi f0ea3505e4 Move and rename a lot of stuff into kaehmy app 2018-01-26 01:15:35 +02:00
Jan Tuomi 06c2a2b9a6 Rename kaehmy templates 2018-01-25 23:28:49 +02:00
Jan Tuomi c671206e8a Rename pre-commit to pre-push 2018-01-25 22:36:38 +02:00
Jan Tuomi cf50050eba Update pre-commit script 2018-01-25 22:23:51 +02:00
Aarni Halinen f8e68acd4d Fix pydcodestyle warnings 2018-01-25 21:57:23 +02:00
Jan Tuomi 9b6fc5e687 Fix openpyxl version conflict by downgrading to 2.4.11 2018-01-25 21:52:34 +02:00
Aarni Halinen 7d17d8a84f Add Ohlhafv to admin and auditlog 2018-01-25 21:36:10 +02:00
Jan Tuomi b2aa6d1a3e Bump django-import-export version 2018-01-25 21:33:40 +02:00
Jan Tuomi 5a2c6d9aaa Bump pyexcel and pyexcel-xlsx versions 2018-01-25 21:25:15 +02:00
Aarni Halinen 1ecbda0731 Update ilmotunkki readme 2018-01-25 21:21:12 +02:00
Jan Tuomi 9e9049709b Fix display issue in charfield 2018-01-25 20:55:03 +02:00
Jan Tuomi ac9a5db356 Add missing translations 2018-01-25 20:54:37 +02:00
Aarni Halinen 67ed7edefb Merge branch 'feature-ohlhafv' into develop 2018-01-25 20:19:47 +02:00
Aarni Halinen 181be6b80c Fix bug in Ohlhafv model regarding translation 2018-01-25 20:10:54 +02:00
Aarni Halinen 1e2bf10494 Allow blank Ohlhafv messages 2018-01-25 20:06:17 +02:00
Jan Tuomi a219b930b3 Make a title black 2018-01-25 18:33:04 +02:00
Jan Tuomi 78ba2d7afa Add hot new designs to Ohlhafv 🔥 2018-01-25 18:31:06 +02:00
Jan Tuomi 6fe01dadf1 Add a couple missing translations 2018-01-25 16:30:05 +02:00
Aarni Halinen 9df62a1247 Fix translations 2018-01-24 19:09:51 +02:00
Aarni Halinen a9164f8c6e Construct Ohlhafv page based on kaehmy 2018-01-24 19:02:44 +02:00
Aarni Halinen 6e5074f8fe Rearrange html files to folders 2018-01-24 18:12:21 +02:00
Elias efe8808e79 Yhteystiedot alustava 2018-01-24 17:48:14 +02:00
Aarni Halinen 77cdce714a Add translations to Ohlhafv page 2018-01-24 17:37:15 +02:00
Aarni Halinen 69c1b2dcb2 Add team challenge option 2018-01-24 17:20:55 +02:00
Aarni Halinen 2a50f7ef43 Pycodestyle whitepsace fixes 2018-01-24 16:46:34 +02:00
Jan Tuomi 0c93446b81 Add some translations 2018-01-24 16:32:29 +02:00
Jan Tuomi 0e52efb449 Fix footer pos and add placeholder content 2018-01-24 16:24:54 +02:00
Elias 283d5b566e Except handling for 'Git not found' in about page 2018-01-24 16:14:29 +02:00
Jan Tuomi a4367bbc9d Merge branch feature-refactor-login 2018-01-10 19:54:08 +02:00
Jan Tuomi 935f7a38f1 Fix login styles 2018-01-10 19:49:59 +02:00
henu 9973057051 Add new styles to main web page 2018-01-10 19:42:20 +02:00
Jan Tuomi 9527e6de5f Skip pre-commit if virtualenv is not found 2017-11-26 00:10:46 +02:00
Jan Tuomi 86e2827f3b Merge branch 'develop' into 'master'
Develop

See merge request vtmk/web2.0!100
2017-11-25 23:37:45 +02:00
Jan Tuomi a519d51309 Fix style issues in kaehmy list 2017-11-25 23:29:20 +02:00
Jan Tuomi 9ee4d600a7 Update setup.sh 2017-11-25 22:18:41 +02:00
Jan Tuomi 2b2d635cb0 Update readme and pre-commit 2017-11-25 21:56:07 +02:00
Jan Tuomi ec6051d3d6 Add pre-commit hook 2017-11-25 21:49:30 +02:00
Jan Tuomi 5479f0e1a7 Merge branch 'develop' into 'master'
Develop

Closes #87

See merge request vtmk/web2.0!99
2017-11-08 18:20:08 +02:00
Jan Tuomi c219f32266 Merge branch 'develop' into 'master'
Develop

See merge request vtmk/web2.0!98
2017-11-04 20:04:38 +02:00
Jan Tuomi e111d1884c Merge branch 'develop' into 'master'
Develop

Closes #91

See merge request vtmk/web2.0!96
2017-11-01 14:22:31 +02:00
Jan Tuomi 7554750883 Merge branch 'develop' into 'master'
Split board and non-board applications to 2 tables

See merge request vtmk/web2.0!89
2017-10-30 14:50:55 +02:00
Jan Tuomi e75f0cfc67 Merge branch 'develop' into 'master'
Develop

See merge request vtmk/web2.0!88
2017-10-30 13:33:07 +02:00
Jan Tuomi 7d3208651a Merge branch 'develop' into 'master'
Fix multiple form and table issues

See merge request vtmk/web2.0!87
2017-10-29 12:25:12 +02:00
Jan Tuomi e949e93799 Merge branch 'develop' into 'master'
Hotfix

See merge request vtmk/web2.0!86
2017-10-26 13:52:36 +03:00
Jan Tuomi f544cf6183 Merge branch 'develop' into 'master'
Fix even more CI

See merge request vtmk/web2.0!85
2017-10-25 22:45:51 +03:00
Jan Tuomi 197c7b0a8b Merge branch 'develop' into 'master'
Fix more Gitlab CI

See merge request vtmk/web2.0!84
2017-10-25 22:36:15 +03:00
Jan Tuomi abb3f6659d Merge branch 'develop' into 'master'
Fix typo in .gitlab-ci.yml

See merge request vtmk/web2.0!83
2017-10-25 22:21:19 +03:00
Jan Tuomi 8141ccfa13 Merge branch 'develop' into 'master'
Develop

Closes #78

See merge request vtmk/web2.0!82
2017-10-25 22:08:02 +03:00
Jan Tuomi f395e8de06 Merge branch 'develop' into 'master'
Fix newlines in comments and sort filter values

See merge request vtmk/web2.0!79
2017-10-23 15:51:32 +03:00
Jan Tuomi 7614c127ba Merge branch 'develop' into 'master'
Update kaehmyopas

See merge request vtmk/web2.0!78
2017-10-20 17:46:25 +03:00
Jan Tuomi b2cc29f6af Merge branch 'develop' into 'master'
Add custom kaehmys to filter list

See merge request !77
2017-10-19 20:02:02 +03:00
Jan Tuomi 7efb8d3e7b Merge branch 'develop' into 'master'
Add translation for role models and remove summary field from PresetRole

See merge request !76
2017-10-19 14:26:35 +03:00
Jan Tuomi 48fa13e37b Merge branch 'develop' into 'master'
Develop

See merge request !75
2017-10-18 12:17:03 +03:00
Jan Tuomi d5ead73869 Merge branch 'develop' into 'master'
Also list custom roles in kaehmy form

See merge request !74
2017-10-17 21:48:46 +03:00
Jan Tuomi a81f305e54 Merge branch 'develop' into 'master'
Add tooltip about kaehmys to statistics page

See merge request !73
2017-10-17 21:15:13 +03:00
Jan Tuomi dcef7aa49a Merge branch 'develop' into 'master'
Fix footer styles on Safari

See merge request !72
2017-10-17 20:38:57 +03:00
Jan Tuomi e0f571a201 Merge branch 'develop' into 'master'
Develop

See merge request !71
2017-10-17 20:30:25 +03:00
Jan Tuomi e5e9774681 Merge branch 'develop' into 'master'
Fix typo

See merge request !70
2017-10-17 13:33:26 +03:00
Jan Tuomi 6f18fa0aea Merge branch 'develop' into 'master'
Develop

See merge request !69
2017-10-17 13:31:04 +03:00
Jan Tuomi 9a918da2f0 Merge branch 'develop' into 'master'
Fix tooltip styles

See merge request !68
2017-10-17 13:07:38 +03:00
Jan Tuomi 17d1d4fea2 Merge branch 'develop' into 'master'
Develop

See merge request !67
2017-10-17 12:48:54 +03:00
Jan Tuomi 85fcf6feb9 Merge branch 'develop' into 'master'
Implement nice navbar styles

See merge request !66
2017-10-16 18:42:18 +03:00
Jan Tuomi 89665d2b48 Merge branch 'develop' into 'master'
Edit labels on form fields

See merge request !65
2017-10-16 18:13:39 +03:00
Jan Tuomi c3478ff47c Merge branch 'develop' into 'master'
Develop

See merge request !64
2017-10-16 17:42:00 +03:00
Jan Tuomi b77dd3f50e Merge branch 'develop' into 'master'
Fix tg posting problem

See merge request !63
2017-10-16 14:42:28 +03:00
Jan Tuomi 7009f38652 Merge branch 'develop' into 'master'
Make form nicer

See merge request !62
2017-10-16 14:17:11 +03:00
Jan Tuomi 4ff426327b Merge branch 'develop' into 'master'
Fix kaehmy form error

See merge request !61
2017-10-16 12:43:43 +03:00
Jan Tuomi d7d0b377f2 Merge branch 'develop' into 'master'
Add category to role model

See merge request !60
2017-10-16 12:42:36 +03:00
Jan Tuomi 4f499af4cf Merge branch 'develop' into 'master'
Develop

See merge request !59
2017-10-16 11:23:05 +03:00
Jan Tuomi d9ed6e7b17 Merge branch 'develop' into 'master'
Develop

See merge request !58
2017-10-16 11:14:04 +03:00
Jan Tuomi efbfe64d1e Merge branch 'develop' into 'master'
Kaehmy

See merge request !56
2017-10-12 10:30:02 +03:00
Jan Tuomi cc9794d6a8 Merge branch 'develop' into 'master'
Fix pagination for 'add many' confirm view

See merge request !55
2017-10-03 14:40:29 +03:00
Jan Tuomi 19ff70d0bd Merge branch 'develop' into 'master'
Develop

See merge request !54
2017-10-02 21:07:34 +03:00
Jan Tuomi d82e3ec4d9 Merge branch 'develop' into 'master'
Develop

See merge request !52
2017-09-26 15:39:43 +03:00
Jan Tuomi d0825e96bc Merge branch 'develop' into 'master'
Fix search logic for full names

See merge request !51
2017-09-25 23:33:05 +03:00
Jan Tuomi a981f6a31f Merge branch 'develop' into 'master'
Search bar implementation

See merge request !50
2017-09-25 22:49:13 +03:00
Jan Tuomi 524c6bbb9e Merge branch 'develop' into 'master'
Fix for NaN message when coffee is brewing

See merge request !49
2017-09-25 12:21:19 +03:00
Jan Tuomi ac4902f867 Merge branch 'develop' into 'master'
Develop

See merge request !48
2017-09-24 16:31:08 +03:00
Jan Tuomi 416be8e2cd Merge branch 'develop' into 'master'
Develop

See merge request !47
2017-09-24 15:05:46 +03:00
Jan Tuomi 4cee5582da Merge branch 'develop' into 'master'
Develop

See merge request !46
2017-09-20 23:47:25 +03:00
Jan Tuomi 160f5adc59 Merge branch 'develop' into 'master'
Add filtering to coffee data

See merge request !43
2017-09-19 21:05:07 +03:00
Jan Tuomi b8267e411c Merge branch 'develop' into 'master'
Fix logging in all modules

See merge request !42
2017-09-19 19:32:06 +03:00
Jan Tuomi ab2fcf04eb Merge branch 'develop' into 'master'
Attempt to hotfix coffee scale crash

See merge request !41
2017-09-19 17:02:36 +03:00
Jan Tuomi 4a79ed341e Merge branch 'develop' into 'master'
Develop

See merge request !40
2017-09-19 00:06:29 +03:00
Jan Tuomi 7b8c5f3d8f Merge branch 'develop' into 'master'
Move coffee scale to web2.0

See merge request !39
2017-09-18 23:17:11 +03:00
Jan Tuomi 170635a8db Merge branch 'develop' into 'master'
Fix translation import issue

See merge request !38
2017-09-18 20:21:58 +03:00
Jan Tuomi a86f71b422 Merge branch 'develop' into 'master'
Develop

Closes #71 and #72

See merge request !37
2017-09-18 19:10:09 +03:00
Jan Tuomi 2585c4885b Merge branch 'develop' into 'master'
Develop

Closes #54

See merge request !34
2017-06-01 19:47:59 +03:00
Jan Tuomi 1cba13f4ff Merge branch 'develop' into 'master'
Develop

See merge request !33
2017-05-27 14:32:55 +03:00
Jan Tuomi 63e669ff0c Merge branch 'develop' into 'master'
HSL fix to master

See merge request !30
2017-05-27 12:40:35 +03:00
Jan Tuomi 2d95dbb0f1 Merge branch 'develop' into 'master'
Add about.html because Jopi forgot

See merge request !29
2017-05-24 20:12:46 +03:00
Jan Tuomi 8f50a6e0bf Merge branch 'develop' into 'master'
Develop

Closes #49, #5, #48, and #50

See merge request !28
2017-05-24 19:44:46 +03:00
300 changed files with 11547 additions and 3744 deletions
+2
View File
@@ -1,3 +1,5 @@
[report]
show_missing = True
[run]
omit =
*/migrations/*
+1
View File
@@ -3,3 +3,4 @@ infoscreen/static/js/lib
webapp/static/js/lib
static/js/lib
collected_static
venv
+5 -2
View File
@@ -5,7 +5,6 @@ sikweb/settings.py
*.sqlite3
uwsgi.ini
uwsgi.log
infoscreen/static/js/hsl.json
members/logs/*
.idea/
logs/
@@ -17,4 +16,8 @@ requirements_henu.txt
/collected_static/
mydatabase
settings.json
.vscode/
.vscode/
.DS_Store
*.code-workspace
sik_test
venv/
+9 -8
View File
@@ -31,7 +31,7 @@ pycodestyle:
- pycodestyle --config=setup.cfg --count .
eslint:
image: node:7.10.0
image: node:alpine
stage: lint
before_script:
- npm install
@@ -39,7 +39,7 @@ eslint:
- npm run eslint
remark:
image: node:7.10.0
image: node:alpine
stage: lint
before_script:
- npm install
@@ -48,13 +48,14 @@ remark:
publish:
stage: publish
image: docker:latest
image: docker:stable
services:
- docker:stable-dind
only:
- develop
before_script:
- docker info
- docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $REGISTRY_URL
script:
- docker info
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
- docker build . -t "$IMAGE_NAME"
- docker push "$IMAGE_NAME"
@@ -63,7 +64,7 @@ deploy_dev:
image: alpine:latest
environment:
name: dev
url: http://web.sik.party:8080
url: http://web.sik.party:8000
only:
- develop
before_script:
@@ -77,6 +78,7 @@ deploy_dev:
script:
- scp docker-compose.yml $DEV_SSH_USER@$DEV_SSH_HOST:~/deployment/docker-compose.yml
- scp .deploy_dev.sh $DEV_SSH_USER@$DEV_SSH_HOST:~/deployment/deploy_dev.sh
- ssh $DEV_SSH_USER@$DEV_SSH_HOST "docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY"
- ssh $DEV_SSH_USER@$DEV_SSH_HOST "bash ~/deployment/deploy_dev.sh \"$IMAGE_NAME\""
deploy_production:
@@ -98,4 +100,3 @@ deploy_production:
- echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config
script:
- ssh $PROD_SSH_USER@$PROD_SSH_HOST "zsh ~/deploy.sh"
+1
View File
@@ -0,0 +1 @@
3.6.8
+1 -1
View File
@@ -1,4 +1,4 @@
FROM python:3
FROM python:3.5
ENV PYTHONUNBUFFERED 1
ENV IS_DOCKER 1
RUN mkdir /code
+52
View File
@@ -0,0 +1,52 @@
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
flake8 = "*"
autopep8 = "*"
[packages]
decorator = "==4.0.9"
ipython = "==4.2.0"
pexpect = "==4.1.0"
pickleshare = "==0.7.2"
ptyprocess = "==0.5.1"
pytz = "==2016.4"
simplegeneric = "==0.8.1"
traitlets = "==4.2.1"
requests = "==2.11.1"
django-nocaptcha-recaptcha = "==0.0.19"
django-cors-headers = "==2.0.1"
djangorestframework = "==3.8.2"
djangorestframework-jwt = "==1.11.0"
coverage = "==4.3.4"
django-nose = "==1.4.5"
nose-exclude = "==0.5.0"
psycopg2-binary = "==2.7.6.1"
django-bootstrap3 = "==8.2.3"
django-tables2 = "==1.6.1"
pycodestyle = "==2.3.1"
dealer = "==2.0.5"
django-modeltranslation = "==0.13b1"
django-auditlog = "==0.4.5"
django-phonenumber-field = "==1.3.0"
django-autocomplete-light = "==3.2.10"
six = "==1.10.0"
django-suit = "==0.2.26"
telepot = "==12.3"
pyexcel = "==0.5.10"
pyexcel-xlsx = "==0.5.5"
django-import-export = "==0.7.0"
openpyxl = "==2.4.11"
django-app-namespace-template-loader = "==0.4.1"
django-filter = "==2.0.0"
"backports.shutil_get_terminal_size" = "==1.0.0"
Django = "==2.1.5"
ipython_genutils = "==0.1.0"
Pillow = "==5.4.1"
PyJWT = "==1.6.4"
[requires]
python_version = "3.6"
Generated
+706
View File
@@ -0,0 +1,706 @@
{
"_meta": {
"hash": {
"sha256": "fd7aa96e8c4fc9e3fa88b6f3b28a1101d7efd8b58e964fbece854850acf8bcea"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.6"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"aiohttp": {
"hashes": [
"sha256:00d198585474299c9c3b4f1d5de1a576cc230d562abc5e4a0e81d71a20a6ca55",
"sha256:0155af66de8c21b8dba4992aaeeabf55503caefae00067a3b1139f86d0ec50ed",
"sha256:09654a9eca62d1bd6d64aa44db2498f60a5c1e0ac4750953fdd79d5c88955e10",
"sha256:199f1d106e2b44b6dacdf6f9245493c7d716b01d0b7fbe1959318ba4dc64d1f5",
"sha256:296f30dedc9f4b9e7a301e5cc963012264112d78a1d3094cd83ef148fdf33ca1",
"sha256:368ed312550bd663ce84dc4b032a962fcb3c7cae099dbbd48663afc305e3b939",
"sha256:40d7ea570b88db017c51392349cf99b7aefaaddd19d2c78368aeb0bddde9d390",
"sha256:629102a193162e37102c50713e2e31dc9a2fe7ac5e481da83e5bb3c0cee700aa",
"sha256:6d5ec9b8948c3d957e75ea14d41e9330e1ac3fed24ec53766c780f82805140dc",
"sha256:87331d1d6810214085a50749160196391a712a13336cd02ce1c3ea3d05bcf8d5",
"sha256:9a02a04bbe581c8605ac423ba3a74999ec9d8bce7ae37977a3d38680f5780b6d",
"sha256:9c4c83f4fa1938377da32bc2d59379025ceeee8e24b89f72fcbccd8ca22dc9bf",
"sha256:9cddaff94c0135ee627213ac6ca6d05724bfe6e7a356e5e09ec57bd3249510f6",
"sha256:a25237abf327530d9561ef751eef9511ab56fd9431023ca6f4803f1994104d72",
"sha256:a5cbd7157b0e383738b8e29d6e556fde8726823dae0e348952a61742b21aeb12",
"sha256:a97a516e02b726e089cffcde2eea0d3258450389bbac48cbe89e0f0b6e7b0366",
"sha256:acc89b29b5f4e2332d65cd1b7d10c609a75b88ef8925d487a611ca788432dfa4",
"sha256:b05bd85cc99b06740aad3629c2585bda7b83bd86e080b44ba47faf905fdf1300",
"sha256:c2bec436a2b5dafe5eaeb297c03711074d46b6eb236d002c13c42f25c4a8ce9d",
"sha256:cc619d974c8c11fe84527e4b5e1c07238799a8c29ea1c1285149170524ba9303",
"sha256:d4392defd4648badaa42b3e101080ae3313e8f4787cb517efd3f5b8157eaefd6",
"sha256:e1c3c582ee11af7f63a34a46f0448fca58e59889396ffdae1f482085061a2889"
],
"version": "==3.5.4"
},
"async-timeout": {
"hashes": [
"sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f",
"sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"
],
"version": "==3.0.1"
},
"attrs": {
"hashes": [
"sha256:69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79",
"sha256:f0b870f674851ecbfbbbd364d6b5cbdff9dcedbc7f3f5e18a6891057f21fe399"
],
"version": "==19.1.0"
},
"babel": {
"hashes": [
"sha256:6778d85147d5d85345c14a26aada5e478ab04e39b078b0745ee6870c2b5cf669",
"sha256:8cba50f48c529ca3fa18cf81fa9403be176d374ac4d60738b839122dfaaa3d23"
],
"version": "==2.6.0"
},
"backports.csv": {
"hashes": [
"sha256:1277dfff73130b2e106bf3dd347adb3c5f6c4340882289d88f31240da92cbd6d",
"sha256:21f6e09bab589e6c1f877edbc40277b65e626262a86e69a70137db714eaac5ce"
],
"version": "==1.0.7"
},
"backports.shutil-get-terminal-size": {
"hashes": [
"sha256:0975ba55054c15e346944b38956a4c9cbee9009391e41b86c68990effb8c1f64",
"sha256:713e7a8228ae80341c70586d1cc0a8caa5207346927e23d09dcbcaf18eadec80"
],
"index": "pypi",
"version": "==1.0.0"
},
"chardet": {
"hashes": [
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
],
"version": "==3.0.4"
},
"coverage": {
"hashes": [
"sha256:01406019418aabb2d4741647cc79b0e0deb0b8c5a6f936936c303e2f82ec8e5b",
"sha256:01a07b2b9212d4da3a1294436b58ac53f1d7aa445bda666648a5357048dc7ef3",
"sha256:024682371464c6e3caa975aba12b4d5428f35613489340fce1334c74d590a057",
"sha256:07c15c4a2287116a41d5966f1f5a7be765640c2e5a1917f882850a24615db6d3",
"sha256:1d23dea598fb4d61a8577d0eb0cb2b7932db0c8d2e1394088ad5f64e3fe1febf",
"sha256:1eeb9de833c3b976ee118a8d838af437bfa596bf60a5bf0705f4370e6d181a52",
"sha256:229ab9c0d53c55d698b8784d53077bef7a5f1fb5d27e90dc7b6f91243b024513",
"sha256:2f5a8bf29bdc69976d0913745daab11f8265e46ec41153f5e1e1794088019dad",
"sha256:2f959bc1b40a3ef2c5f0c7bc282226d6d4bd585b239bcce321013afc18ff0a0f",
"sha256:36407249a0b6669c6ad4425b0f29685579df745480c03afa70f101f09f4eead3",
"sha256:3efa49e3da8f32071ee3d5d464cc6b6f8818524d4099b4a94b86a70b8c88d4f5",
"sha256:422bcc6270e1c0cd9043048ce244f49072e9bd78a2c028c2ad2cfd58c79f5936",
"sha256:4fa2b181c3bf94cfdf841148d5d9abcab1890188dd908a639bcf7a38c50092bc",
"sha256:57c0c217270e628380f4befbbf8c5312b88ba7d81fd3d1b2218a25a2608f603c",
"sha256:6ae76a6cd594107ad45525278e8addeae4628a59c8cde3999548d7fe1646465b",
"sha256:6d3c762c87062a29771015f942752caef42fcc7fe4be2b03186f96788242290c",
"sha256:8a82664931a071399d703d65af2521e2202b34f2d8db20fa22a922fec0339022",
"sha256:8b282292973a1dc4eccfcc0776e0fde75b5b3de2e35164c2d854f7dd80149e4b",
"sha256:9a7874ca91cee8714277cd6d1b52374809ab925bf6ae92607bf02509019caadb",
"sha256:9c3e6551597593c1afedcbccf1371995f94457aea82cac726d1f3a25f4507386",
"sha256:a791068e1bbe443fcd3179b1c180c27a7fc58c1554b0d10311b7659d2d2d76f5",
"sha256:adf04843188418b012dd1974e397a7ac3faa1855cbcd69083e3af4da6de9dd81",
"sha256:adfbbd4a1d22fd77b13ff992946b19873407e035504abe9ba537494fe013300f",
"sha256:b25aa3531220faaf1727fc29bc000798476b4a30f429dc07898d5da48caefa15",
"sha256:c12f34c0b50e9e8bf8c049b6c8ca59929c33cea4b1c48362c99c36838c1ee025",
"sha256:c736faa1688222a6c8a5d8be4b66ec373ad6dab27fced8ca0d2c80fed70ac6e3",
"sha256:ca36d83cd591d027952e5019149c4386e7058cd674bf8cb52dc622f768d689e9",
"sha256:e1fb21a807aa0b5cc79806d8ef09078acaa83f994e15f0f7277489ca8eda51b7",
"sha256:e53199ae110cb7e250dd5505fde34452514f4eb2f1fb7532270d2ea037454b09",
"sha256:ea9808001dcf34d368cbef430e7885fdc76a2cf8ea96a8ed8b653797dd9555bb",
"sha256:eaaefe0f6aa33de5a65f48dd0040d7fe08cac9ac6c35a56d0a7db109c3e733df",
"sha256:f27772c9ee88ed3f2a784181f3d1724561499e7e448ed1706153336baa706bd5",
"sha256:f99066d76274800145a2e658026b30962eb5079346249197e88b55c9a7855e6a",
"sha256:fd3373ccd561b79932d12a986674e642816cfc4db4507b6a22ab30c318a85429"
],
"index": "pypi",
"version": "==4.3.4"
},
"dealer": {
"hashes": [
"sha256:0a5a536fdecd9c7679534a19c59392cd21989037c14782328970a185b39e7560",
"sha256:baaac37a4c7928545cb8b0335f48abd0ea51a0274159a9a989afb8b71f8b11c3"
],
"index": "pypi",
"version": "==2.0.5"
},
"decorator": {
"hashes": [
"sha256:90022e83316363788a55352fe39cfbed357aa3a71d90e5f2803a35471de4bba8",
"sha256:f4718552326c99544a6ec602d96b7d03ef61180cf4a492c515ecb2438dd14ccc"
],
"index": "pypi",
"version": "==4.0.9"
},
"defusedxml": {
"hashes": [
"sha256:24d7f2f94f7f3cb6061acb215685e5125fbcdc40a857eff9de22518820b0a4f4",
"sha256:702a91ade2968a82beb0db1e0766a6a273f33d4616a6ce8cde475d8e09853b20"
],
"version": "==0.5.0"
},
"diff-match-patch": {
"hashes": [
"sha256:a809a996d0f09b9bbd59e9bbd0b71eed8c807922512910e05cbd3f9480712ddb"
],
"version": "==20181111"
},
"django": {
"hashes": [
"sha256:a32c22af23634e1d11425574dce756098e015a165be02e4690179889b207c7a8",
"sha256:d6393918da830530a9516bbbcbf7f1214c3d733738779f06b0f649f49cc698c3"
],
"index": "pypi",
"version": "==2.1.5"
},
"django-app-namespace-template-loader": {
"hashes": [
"sha256:356539413b5d1de0eff91aea7a03806b5ef6874ee5420ea8c273f72bbc601d74",
"sha256:7a450985479a2e07fe8a1e4e8208fc9e1d8b35503526dd28eba5f8ad4ba31d4e"
],
"index": "pypi",
"version": "==0.4.1"
},
"django-auditlog": {
"hashes": [
"sha256:70bfc673e7023d91ab8449d745425e7a4ce5eaaf2bdcbfb9b1a2209a7af60b03"
],
"index": "pypi",
"version": "==0.4.5"
},
"django-autocomplete-light": {
"hashes": [
"sha256:5ccb1c8c4b75cf72bc5dabd920190ea1ca3a340f56fb6b12d07a62202837fa75"
],
"index": "pypi",
"version": "==3.2.10"
},
"django-bootstrap3": {
"hashes": [
"sha256:6f7946d513d6340bb70f25d8ec047bf3bf37bab9e499d3baca99b1aa0ec92a52"
],
"index": "pypi",
"version": "==8.2.3"
},
"django-cors-headers": {
"hashes": [
"sha256:638aaba85f96af62557656ec559672f03d7c61769685acc405eacfaba9d4e93f",
"sha256:c766daf9eefcb9536af9817703ea29124fffee06870f9e523b75144b4d39a694"
],
"index": "pypi",
"version": "==2.0.1"
},
"django-filter": {
"hashes": [
"sha256:6f4e4bc1a11151178520567b50320e5c32f8edb552139d93ea3e30613b886f56",
"sha256:86c3925020c27d072cdae7b828aaa5d165c2032a629abbe3c3a1be1edae61c58"
],
"index": "pypi",
"version": "==2.0.0"
},
"django-import-export": {
"hashes": [
"sha256:6e748fcc647fe2a82a55136ebcbe806a45fd7fb5b1e32b33759181f1e67eeb1b",
"sha256:7e7ebeb40702eafeb2e770914c01b9961063f472b3b395eeffbea5f39efa7257"
],
"index": "pypi",
"version": "==0.7.0"
},
"django-jsonfield": {
"hashes": [
"sha256:25e53eae8bda165721773145ee0f8ae53b746bb3051b32f2821ba84d79aa77ef",
"sha256:813c52463fbbb548fe0d85bf935d0bf72e933fae2bb00ce3ba27bf69ff6fd2ad",
"sha256:cacf5a21e7c2490109a60f1122c05aa3858a8dc06952ad764831b4428164fc8e"
],
"version": "==1.1.0"
},
"django-modeltranslation": {
"hashes": [
"sha256:254ebda6caea5683407e1fb3e45ceaa2275778c6dc2db2b9d4fec3df373c2cdd"
],
"index": "pypi",
"version": "==0.13b1"
},
"django-nocaptcha-recaptcha": {
"hashes": [
"sha256:d2512d5035d5f62aba5009082db28b28995a7e6f4a46713292e0f4f350f337da"
],
"index": "pypi",
"version": "==0.0.19"
},
"django-nose": {
"hashes": [
"sha256:5df2df802c607daeeab8ac1e93abf54508ed6133eb93852310f512000124b4a5",
"sha256:87663f18cb25f01d56c84ac1ff8a0e6e6a6246264b2549b751cb239d0642e76a"
],
"index": "pypi",
"version": "==1.4.5"
},
"django-phonenumber-field": {
"hashes": [
"sha256:8db9d2dc833678b163adabd593cda7ad1dede81a1c18f67c895701fc44dc44f1"
],
"index": "pypi",
"version": "==1.3.0"
},
"django-suit": {
"hashes": [
"sha256:19ed865a478dfca81cb5f50a70317700dd70da92c465093251d0e14330a2b92b"
],
"index": "pypi",
"version": "==0.2.26"
},
"django-tables2": {
"hashes": [
"sha256:d5d3ad99580121f7ec46ea9e2420069bbd6d2f33b4fde73a376c6bf27d551146"
],
"index": "pypi",
"version": "==1.6.1"
},
"djangorestframework": {
"hashes": [
"sha256:b6714c3e4b0f8d524f193c91ecf5f5450092c2145439ac2769711f7eba89a9d9",
"sha256:c375e4f95a3a64fccac412e36fb42ba36881e52313ec021ef410b40f67cddca4"
],
"index": "pypi",
"version": "==3.8.2"
},
"djangorestframework-jwt": {
"hashes": [
"sha256:5efe33032f3a4518a300dc51a51c92145ad95fb6f4b272e5aa24701db67936a7",
"sha256:ab15dfbbe535eede8e2e53adaf52ef0cf018ee27dbfad10cbc4cbec2ab63d38c"
],
"index": "pypi",
"version": "==1.11.0"
},
"et-xmlfile": {
"hashes": [
"sha256:614d9722d572f6246302c4491846d2c393c199cfa4edc9af593437691683335b"
],
"version": "==1.0.1"
},
"idna": {
"hashes": [
"sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407",
"sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"
],
"version": "==2.8"
},
"ipython": {
"hashes": [
"sha256:0480354f25b2f443e4ef1456b48f28ad1caaa6d316fca5a5eaa9ca7745ae7923",
"sha256:98452af6450e28c9c742d567d75eb6e3a7b391ad4ce8abd5679c5f85ce7fad00",
"sha256:d852fed59da67c7e45cb2192027da8bfd920a7856d295c247a45105968d24d5a",
"sha256:dba42f182b5f6f26630d2202efd30383712d9f7d8d8d9896b37ae2145deca616"
],
"index": "pypi",
"version": "==4.2.0"
},
"ipython-genutils": {
"hashes": [
"sha256:0c43fa84e93ad0e4dbecaffc6656ac1caf1a48359b2bb0a5da3af84164e3f49b",
"sha256:3a0624a251a26463c9dfa0ffa635ec51c4265380980d9a50d65611c3c2bd82a6",
"sha256:6218e9abd612fb5acfb175ea7c7b026006de4df9691d9a73c9b390cfa1a41c2b"
],
"index": "pypi",
"version": "==0.1.0"
},
"jdcal": {
"hashes": [
"sha256:948fb8d079e63b4be7a69dd5f0cd618a0a57e80753de8248fd786a8a20658a07",
"sha256:ea0a5067c5f0f50ad4c7bdc80abad3d976604f6fb026b0b3a17a9d84bb9046c9"
],
"version": "==1.4"
},
"lml": {
"hashes": [
"sha256:b1bef669dc077a1075fa64b99229b6341085b3b3a98d29c66df1853cc14e6c1a",
"sha256:ea5ba817b4adc9e9f5c21725cd2475f912933b7e2dfdf0792aed80077154f63f"
],
"version": "==0.0.9"
},
"multidict": {
"hashes": [
"sha256:024b8129695a952ebd93373e45b5d341dbb87c17ce49637b34000093f243dd4f",
"sha256:041e9442b11409be5e4fc8b6a97e4bcead758ab1e11768d1e69160bdde18acc3",
"sha256:045b4dd0e5f6121e6f314d81759abd2c257db4634260abcfe0d3f7083c4908ef",
"sha256:047c0a04e382ef8bd74b0de01407e8d8632d7d1b4db6f2561106af812a68741b",
"sha256:068167c2d7bbeebd359665ac4fff756be5ffac9cda02375b5c5a7c4777038e73",
"sha256:148ff60e0fffa2f5fad2eb25aae7bef23d8f3b8bdaf947a65cdbe84a978092bc",
"sha256:1d1c77013a259971a72ddaa83b9f42c80a93ff12df6a4723be99d858fa30bee3",
"sha256:1d48bc124a6b7a55006d97917f695effa9725d05abe8ee78fd60d6588b8344cd",
"sha256:31dfa2fc323097f8ad7acd41aa38d7c614dd1960ac6681745b6da124093dc351",
"sha256:34f82db7f80c49f38b032c5abb605c458bac997a6c3142e0d6c130be6fb2b941",
"sha256:3d5dd8e5998fb4ace04789d1d008e2bb532de501218519d70bb672c4c5a2fc5d",
"sha256:4a6ae52bd3ee41ee0f3acf4c60ceb3f44e0e3bc52ab7da1c2b2aa6703363a3d1",
"sha256:4b02a3b2a2f01d0490dd39321c74273fed0568568ea0e7ea23e02bd1fb10a10b",
"sha256:4b843f8e1dd6a3195679d9838eb4670222e8b8d01bc36c9894d6c3538316fa0a",
"sha256:5de53a28f40ef3c4fd57aeab6b590c2c663de87a5af76136ced519923d3efbb3",
"sha256:61b2b33ede821b94fa99ce0b09c9ece049c7067a33b279f343adfe35108a4ea7",
"sha256:6a3a9b0f45fd75dc05d8e93dc21b18fc1670135ec9544d1ad4acbcf6b86781d0",
"sha256:76ad8e4c69dadbb31bad17c16baee61c0d1a4a73bed2590b741b2e1a46d3edd0",
"sha256:7ba19b777dc00194d1b473180d4ca89a054dd18de27d0ee2e42a103ec9b7d014",
"sha256:7c1b7eab7a49aa96f3db1f716f0113a8a2e93c7375dd3d5d21c4941f1405c9c5",
"sha256:7fc0eee3046041387cbace9314926aa48b681202f8897f8bff3809967a049036",
"sha256:8ccd1c5fff1aa1427100ce188557fc31f1e0a383ad8ec42c559aabd4ff08802d",
"sha256:8e08dd76de80539d613654915a2f5196dbccc67448df291e69a88712ea21e24a",
"sha256:c18498c50c59263841862ea0501da9f2b3659c00db54abfbf823a80787fde8ce",
"sha256:c49db89d602c24928e68c0d510f4fcf8989d77defd01c973d6cbe27e684833b1",
"sha256:ce20044d0317649ddbb4e54dab3c1bcc7483c78c27d3f58ab3d0c7e6bc60d26a",
"sha256:d1071414dd06ca2eafa90c85a079169bfeb0e5f57fd0b45d44c092546fcd6fd9",
"sha256:d3be11ac43ab1a3e979dac80843b42226d5d3cccd3986f2e03152720a4297cd7",
"sha256:db603a1c235d110c860d5f39988ebc8218ee028f07a7cbc056ba6424372ca31b"
],
"version": "==4.5.2"
},
"nose": {
"hashes": [
"sha256:9ff7c6cc443f8c51994b34a667bbcf45afd6d945be7477b52e97516fd17c53ac",
"sha256:dadcddc0aefbf99eea214e0f1232b94f2fa9bd98fa8353711dacb112bfcbbb2a",
"sha256:f1bffef9cbc82628f6e7d7b40d7e255aefaa1adb6a1b1d26c69a8b79e6208a98"
],
"version": "==1.3.7"
},
"nose-exclude": {
"hashes": [
"sha256:f78fa8b41eeb815f0486414f710f1eea0949e346cfb11d59ba6295ed69e84304"
],
"index": "pypi",
"version": "==0.5.0"
},
"odfpy": {
"hashes": [
"sha256:596021f0519623ca8717331951c95e3b8d7b21e86edc7efe8cb650a0d0f59a2b"
],
"version": "==1.4.0"
},
"openpyxl": {
"hashes": [
"sha256:626d38647c063d55803ef4971c4d43226538d4e95cb6260c094e363ee33e10c7"
],
"index": "pypi",
"version": "==2.4.11"
},
"pexpect": {
"hashes": [
"sha256:09b0a7727ce012e0fa668ef848591102d6667521655f4e72d51197c872cb9fb9",
"sha256:c381c60f1987355b65df8f08a27f428831914c8a81091bd1778ac336fa2f27e7"
],
"index": "pypi",
"version": "==4.1.0"
},
"phonenumberslite": {
"hashes": [
"sha256:2cb034b158314ca3dc034b417a64777c14b74f27f47b451270686e22eefd57d3",
"sha256:fb9212bb8f27ec4bd5ff9a109d4309deed31b45ae5a7216bacc6644759fac82d"
],
"version": "==8.10.8"
},
"pickleshare": {
"hashes": [
"sha256:92ee3b0e21632542ecc9a0a245e69a126f62e5114081bdb0d32e0edd10410033",
"sha256:b58cf7d70658a091621c0d8cc35143c8569f3827496b27ed896918c237d05d96"
],
"index": "pypi",
"version": "==0.7.2"
},
"pillow": {
"hashes": [
"sha256:051de330a06c99d6f84bcf582960487835bcae3fc99365185dc2d4f65a390c0e",
"sha256:0ae5289948c5e0a16574750021bd8be921c27d4e3527800dc9c2c1d2abc81bf7",
"sha256:0b1efce03619cdbf8bcc61cfae81fcda59249a469f31c6735ea59badd4a6f58a",
"sha256:163136e09bd1d6c6c6026b0a662976e86c58b932b964f255ff384ecc8c3cefa3",
"sha256:18e912a6ccddf28defa196bd2021fe33600cbe5da1aa2f2e2c6df15f720b73d1",
"sha256:24ec3dea52339a610d34401d2d53d0fb3c7fd08e34b20c95d2ad3973193591f1",
"sha256:267f8e4c0a1d7e36e97c6a604f5b03ef58e2b81c1becb4fccecddcb37e063cc7",
"sha256:3273a28734175feebbe4d0a4cde04d4ed20f620b9b506d26f44379d3c72304e1",
"sha256:4c678e23006798fc8b6f4cef2eaad267d53ff4c1779bd1af8725cc11b72a63f3",
"sha256:4d4bc2e6bb6861103ea4655d6b6f67af8e5336e7216e20fff3e18ffa95d7a055",
"sha256:505738076350a337c1740a31646e1de09a164c62c07db3b996abdc0f9d2e50cf",
"sha256:5233664eadfa342c639b9b9977190d64ad7aca4edc51a966394d7e08e7f38a9f",
"sha256:5d95cb9f6cced2628f3e4de7e795e98b2659dfcc7176ab4a01a8b48c2c2f488f",
"sha256:7eda4c737637af74bac4b23aa82ea6fbb19002552be85f0b89bc27e3a762d239",
"sha256:801ddaa69659b36abf4694fed5aa9f61d1ecf2daaa6c92541bbbbb775d97b9fe",
"sha256:825aa6d222ce2c2b90d34a0ea31914e141a85edefc07e17342f1d2fdf121c07c",
"sha256:9c215442ff8249d41ff58700e91ef61d74f47dfd431a50253e1a1ca9436b0697",
"sha256:a3d90022f2202bbb14da991f26ca7a30b7e4c62bf0f8bf9825603b22d7e87494",
"sha256:a631fd36a9823638fe700d9225f9698fb59d049c942d322d4c09544dc2115356",
"sha256:a6523a23a205be0fe664b6b8747a5c86d55da960d9586db039eec9f5c269c0e6",
"sha256:a756ecf9f4b9b3ed49a680a649af45a8767ad038de39e6c030919c2f443eb000",
"sha256:b117287a5bdc81f1bac891187275ec7e829e961b8032c9e5ff38b70fd036c78f",
"sha256:ba04f57d1715ca5ff74bb7f8a818bf929a204b3b3c2c2826d1e1cc3b1c13398c",
"sha256:cd878195166723f30865e05d87cbaf9421614501a4bd48792c5ed28f90fd36ca",
"sha256:cee815cc62d136e96cf76771b9d3eb58e0777ec18ea50de5cfcede8a7c429aa8",
"sha256:d1722b7aa4b40cf93ac3c80d3edd48bf93b9208241d166a14ad8e7a20ee1d4f3",
"sha256:d7c1c06246b05529f9984435fc4fa5a545ea26606e7f450bdbe00c153f5aeaad",
"sha256:e9c8066249c040efdda84793a2a669076f92a301ceabe69202446abb4c5c5ef9",
"sha256:f227d7e574d050ff3996049e086e1f18c7bd2d067ef24131e50a1d3fe5831fbc",
"sha256:fc9a12aad714af36cf3ad0275a96a733526571e52710319855628f476dcb144e"
],
"index": "pypi",
"version": "==5.4.1"
},
"psycopg2-binary": {
"hashes": [
"sha256:036bcb198a7cc4ce0fe43344f8c2c9a8155aefa411633f426c8c6ed58a6c0426",
"sha256:1d770fcc02cdf628aebac7404d56b28a7e9ebec8cfc0e63260bd54d6edfa16d4",
"sha256:1fdc6f369dcf229de6c873522d54336af598b9470ccd5300e2f58ee506f5ca13",
"sha256:21f9ddc0ff6e07f7d7b6b484eb9da2c03bc9931dd13e36796b111d631f7135a3",
"sha256:247873cda726f7956f745a3e03158b00de79c4abea8776dc2f611d5ba368d72d",
"sha256:3aa31c42f29f1da6f4fd41433ad15052d5ff045f2214002e027a321f79d64e2c",
"sha256:475f694f87dbc619010b26de7d0fc575a4accf503f2200885cc21f526bffe2ad",
"sha256:4b5e332a24bf6e2fda1f51ca2a57ae1083352293a08eeea1fa1112dc7dd542d1",
"sha256:570d521660574aca40be7b4d532dfb6f156aad7b16b5ed62d1534f64f1ef72d8",
"sha256:59072de7def0690dd13112d2bdb453e20570a97297070f876fbbb7cbc1c26b05",
"sha256:5f0b658989e918ef187f8a08db0420528126f2c7da182a7b9f8bf7f85144d4e4",
"sha256:649199c84a966917d86cdc2046e03d536763576c0b2a756059ae0b3a9656bc20",
"sha256:6645fc9b4705ae8fbf1ef7674f416f89ae1559deec810f6dd15197dfa52893da",
"sha256:6872dd54d4e398d781efe8fe2e2d7eafe4450d61b5c4898aced7610109a6df75",
"sha256:6ce34fbc251fc0d691c8d131250ba6f42fd2b28ef28558d528ba8c558cb28804",
"sha256:73920d167a0a4d1006f5f3b9a3efce6f0e5e883a99599d38206d43f27697df00",
"sha256:8a671732b87ae423e34b51139628123bc0306c2cb85c226e71b28d3d57d7e42a",
"sha256:8d517e8fda2efebca27c2018e14c90ed7dc3f04d7098b3da2912e62a1a5585fe",
"sha256:9475a008eb7279e20d400c76471843c321b46acacc7ee3de0b47233a1e3fa2cf",
"sha256:96947b8cd7b3148fb0e6549fcb31258a736595d6f2a599f8cd450e9a80a14781",
"sha256:abf229f24daa93f67ac53e2e17c8798a71a01711eb9fcdd029abba8637164338",
"sha256:b1ab012f276df584beb74f81acb63905762c25803ece647016613c3d6ad4e432",
"sha256:b22b33f6f0071fe57cb4e9158f353c88d41e739a3ec0d76f7b704539e7076427",
"sha256:b3b2d53274858e50ad2ffdd6d97ce1d014e1e530f82ec8b307edd5d4c921badf",
"sha256:bab26a729befc7b9fab9ded1bba9c51b785188b79f8a2796ba03e7e734269e2e",
"sha256:daa1a593629aa49f506eddc9d23dc7f89b35693b90e1fbcd4480182d1203ea90",
"sha256:dd111280ce40e89fd17b19c1269fd1b74a30fce9d44a550840e86edb33924eb8",
"sha256:e0b86084f1e2e78c451994410de756deba206884d6bed68d5a3d7f39ff5fea1d",
"sha256:eb86520753560a7e89639500e2a254bb6f683342af598088cb72c73edcad21e6",
"sha256:ff18c5c40a38d41811c23e2480615425c97ea81fd7e9118b8b899c512d97c737"
],
"index": "pypi",
"version": "==2.7.6.1"
},
"ptyprocess": {
"hashes": [
"sha256:0530ce63a9295bfae7bd06edc02b6aa935619f486f0f1dc0972f516265ee81a6",
"sha256:464cb76f7a7122743dd25507650db89cd447c51f38e4671602b3eaa2e38e05ae"
],
"index": "pypi",
"version": "==0.5.1"
},
"pycodestyle": {
"hashes": [
"sha256:682256a5b318149ca0d2a9185d365d8864a768a28db66a84a2ea946bcc426766",
"sha256:6c4245ade1edfad79c3446fadfc96b0de2759662dc29d07d80a6f27ad1ca6ba9"
],
"index": "pypi",
"version": "==2.3.1"
},
"pyexcel": {
"hashes": [
"sha256:2a32accc28aea3994922606ecf7bef00ef058b56b1bea6af119ae3bb56468333",
"sha256:f1ffe613f09285edf42132b9afc14f81adbd0f56797e5fe05e98307d00ce175f"
],
"index": "pypi",
"version": "==0.5.10"
},
"pyexcel-io": {
"hashes": [
"sha256:55b2aa4ef81ba6e3285edfb1a3f3c3c69f9f4d52b6867318ae2381f88741143f",
"sha256:de9de0d6bf9a8906c94e3b5dbe0b3a3e0a9bc893201d6a5c5b3cf84e5119d60d"
],
"version": "==0.5.16"
},
"pyexcel-xlsx": {
"hashes": [
"sha256:488783c3f5195bed8638f6064b11d97f706641b0f065a5416297a01db6cec5ea",
"sha256:b3566162f7232336ebe0d40dd298145c18715009b020dddc210890cf6436ffb2"
],
"index": "pypi",
"version": "==0.5.5"
},
"pyjwt": {
"hashes": [
"sha256:30b1380ff43b55441283cc2b2676b755cca45693ae3097325dea01f3d110628c",
"sha256:4ee413b357d53fd3fb44704577afac88e72e878716116270d722723d65b42176"
],
"index": "pypi",
"version": "==1.6.4"
},
"python-dateutil": {
"hashes": [
"sha256:3acbef017340600e9ff8f2994d8f7afd6eacb295383f286466a6df3961e486f0",
"sha256:537bf2a8f8ce6f6862ad705cd68f9e405c0b5db014aa40fa29eab4335d4b1716",
"sha256:62a2f8df3d66f878373fd0072eacf4ee52194ba302e00082828e0d263b0418d2"
],
"version": "==2.6.0"
},
"pytz": {
"hashes": [
"sha256:8781cdd3ca70f5a536884e051797ca213b9ff479a5c1cc57240adf37cc1eff1b",
"sha256:be2ff04e94a2b5454ddcfbebb81ee8e46162734d4c2fcc90c422d16ab51f810b",
"sha256:c823de61ff40d1996fe087cec343e0503881ca641b897e0f9b86c7683a0bfee1",
"sha256:ee7c751544e35a7b7fb5e3fb25a49dade37d51e70a93e5107f10575d7102c311"
],
"index": "pypi",
"version": "==2016.4"
},
"pyyaml": {
"hashes": [
"sha256:1adecc22f88d38052fb787d959f003811ca858b799590a5eaa70e63dca50308c",
"sha256:436bc774ecf7c103814098159fbb84c2715d25980175292c648f2da143909f95",
"sha256:460a5a4248763f6f37ea225d19d5c205677d8d525f6a83357ca622ed541830c2",
"sha256:5a22a9c84653debfbf198d02fe592c176ea548cccce47553f35f466e15cf2fd4",
"sha256:7a5d3f26b89d688db27822343dfa25c599627bc92093e788956372285c6298ad",
"sha256:9372b04a02080752d9e6f990179a4ab840227c6e2ce15b95e1278456664cf2ba",
"sha256:a5dcbebee834eaddf3fa7366316b880ff4062e4bcc9787b78c7fbb4a26ff2dd1",
"sha256:aee5bab92a176e7cd034e57f46e9df9a9862a71f8f37cad167c6fc74c65f5b4e",
"sha256:c51f642898c0bacd335fc119da60baae0824f2cde95b0330b56c0553439f0673",
"sha256:c68ea4d3ba1705da1e0d85da6684ac657912679a649e8868bd850d2c299cce13",
"sha256:e23d0cc5299223dcc37885dae624f382297717e459ea24053709675a976a3e19"
],
"version": "==5.1"
},
"requests": {
"hashes": [
"sha256:545c4855cd9d7c12671444326337013766f4eea6068c3f0307fb2dc2696d580e",
"sha256:5acf980358283faba0b897c73959cecf8b841205bb4b2ad3ef545f46eae1a133"
],
"index": "pypi",
"version": "==2.11.1"
},
"simplegeneric": {
"hashes": [
"sha256:dc972e06094b9af5b855b3df4a646395e43d1c9d0d39ed345b7393560d0b9173"
],
"index": "pypi",
"version": "==0.8.1"
},
"six": {
"hashes": [
"sha256:0ff78c403d9bccf5a425a6d31a12aa6b47f1c21ca4dc2573a7e2f32a97335eb1",
"sha256:105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a"
],
"index": "pypi",
"version": "==1.10.0"
},
"tablib": {
"hashes": [
"sha256:0f88a9cebdaa1a2cc29ae57387082ee81015d1149ecd34e48a8c8d3b4dd21670",
"sha256:5f33c079b07eb10cf9c4b4696add2ecf32c89db7729240546ecdcd5c92f67e13"
],
"version": "==0.13.0"
},
"telepot": {
"hashes": [
"sha256:8910fd6fb708e2c3ded7ca82cc945a645b717699d9f82ddff5123bb2e05f780f"
],
"index": "pypi",
"version": "==12.3"
},
"texttable": {
"hashes": [
"sha256:2b60a5304ccfbeac80ffae7350d7c2f5d7a24e9aab5036d0f82489746419d9b2"
],
"version": "==1.6.1"
},
"traitlets": {
"hashes": [
"sha256:05a66843c96a320eec09df674c16ff330a43cb07f731cf2bd88aa3645a180541",
"sha256:76eba33c89723b8fc024f950cacaf5bf2ef37999642cc9a61f4e7c1ca5cf0ac0",
"sha256:d6db3201395f9b955786d25a1817c07291e2bcb96eb7f41683ae3836836179d7"
],
"index": "pypi",
"version": "==4.2.1"
},
"urllib3": {
"hashes": [
"sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39",
"sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22"
],
"version": "==1.24.1"
},
"xlrd": {
"hashes": [
"sha256:546eb36cee8db40c3eaa46c351e67ffee6eeb5fa2650b71bc4c758a29a1b29b2",
"sha256:e551fb498759fa3a5384a94ccd4c3c02eb7c00ea424426e212ac0c57be9dfbde"
],
"version": "==1.2.0"
},
"xlwt": {
"hashes": [
"sha256:a082260524678ba48a297d922cc385f58278b8aa68741596a87de01a9c628b2e",
"sha256:c59912717a9b28f1a3c2a98fd60741014b06b043936dcecbc113eaaada156c88"
],
"version": "==1.3.0"
},
"yarl": {
"hashes": [
"sha256:024ecdc12bc02b321bc66b41327f930d1c2c543fa9a561b39861da9388ba7aa9",
"sha256:2f3010703295fbe1aec51023740871e64bb9664c789cba5a6bdf404e93f7568f",
"sha256:3890ab952d508523ef4881457c4099056546593fa05e93da84c7250516e632eb",
"sha256:3e2724eb9af5dc41648e5bb304fcf4891adc33258c6e14e2a7414ea32541e320",
"sha256:5badb97dd0abf26623a9982cd448ff12cb39b8e4c94032ccdedf22ce01a64842",
"sha256:73f447d11b530d860ca1e6b582f947688286ad16ca42256413083d13f260b7a0",
"sha256:7ab825726f2940c16d92aaec7d204cfc34ac26c0040da727cf8ba87255a33829",
"sha256:b25de84a8c20540531526dfbb0e2d2b648c13fd5dd126728c496d7c3fea33310",
"sha256:c6e341f5a6562af74ba55205dbd56d248daf1b5748ec48a0200ba227bb9e33f4",
"sha256:c9bb7c249c4432cd47e75af3864bc02d26c9594f49c82e2a28624417f0ae63b8",
"sha256:e060906c0c585565c718d1c3841747b61c5439af2211e185f6739a9412dfbde1"
],
"version": "==1.3.0"
}
},
"develop": {
"autopep8": {
"hashes": [
"sha256:33d2b5325b7e1afb4240814fe982eea3a92ebea712869bfd08b3c0393404248c"
],
"index": "pypi",
"version": "==1.4.3"
},
"entrypoints": {
"hashes": [
"sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19",
"sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451"
],
"version": "==0.3"
},
"flake8": {
"hashes": [
"sha256:859996073f341f2670741b51ec1e67a01da142831aa1fdc6242dbf88dffbe661",
"sha256:a796a115208f5c03b18f332f7c11729812c8c3ded6c46319c59b53efd3819da8"
],
"index": "pypi",
"version": "==3.7.7"
},
"mccabe": {
"hashes": [
"sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42",
"sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"
],
"version": "==0.6.1"
},
"pycodestyle": {
"hashes": [
"sha256:682256a5b318149ca0d2a9185d365d8864a768a28db66a84a2ea946bcc426766",
"sha256:6c4245ade1edfad79c3446fadfc96b0de2759662dc29d07d80a6f27ad1ca6ba9"
],
"index": "pypi",
"version": "==2.3.1"
},
"pyflakes": {
"hashes": [
"sha256:17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0",
"sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2"
],
"version": "==2.1.1"
}
}
}
@@ -1,74 +0,0 @@
from django.core.management.base import BaseCommand, CommandError
from django.utils import timezone
from django.conf import settings
from coffee_scale.models import Brewing
import paho.mqtt.client as mqtt
import random
brewing = False
lastbrew = timezone.now()
lastcups = 0
def on_connect(client, userdata, flags, rc):
if rc != 0:
print("Failed to connect with result code: {}".format(rc))
print("Connected with result code: {}".format(rc))
client.subscribe(settings.MQTT_SETTINGS.HOST.TOPICS.CUPS)
client.subscribe(settings.MQTT_SETTINGS.HOST.TOPICS.BREWING)
client.subscribe(settings.MQTT_SETTINGS.HOST.TOPICS.BREW_TIME)
def on_message(client, userdata, message):
print("%s %s".format(message.topic, message.payload.decode()))
def on_message_cups(client, userdata, message):
cups = int(message.payload.decode())
print("cups: {}".format(cups))
print("{}".format(timezone.now()))
# checks if new coffee was brewed so we don't add the same brewing again to db
global lastcups # ;/ have to use global to store state instead of class
if cups > lastcups:
new_brew = Brewing(cups=cups, time=timezone.now())
print(new_brew.time)
new_brew.save()
lastcups = cups
def on_message_brewtime(client, userdata, message):
brewtime = datetime.fromtimestamp(int(message.payload.decode()))
print("brewtime: {}".format(brewtime))
def on_message_brewing(client, userdata, message):
brewing = bool(int(message.payload.decode()))
print("brewing: {}".format(brewing))
class Command(BaseCommand):
help = "Fetches coffee mqtt messages"
def add_arquments(self, parser):
pass
def handle(self, *args, **options):
self.username = "coffee-user-%d".format(random.randint(0, 100))
self.client = mqtt.Client("coffee")
self.client.username_pw_set(self.username, password=None)
self.client.tls_set()
# callbacks for different topics
self.client.message_callback_add(settings.MQTT_SETTINGS.HOST.TOPICS.BREW_TIME, on_message_brewtime)
self.client.message_callback_add(settings.MQTT_SETTINGS.HOST.TOPICS.CUPS, on_message_cups)
self.client.message_callback_add(settings.MQTT_SETTINGS.HOST.TOPICS.BREWING, on_message_brewing)
# self.client.connect("localhost", port=1883) # used for local testing
self.client.connect(settings.MQTT_SETTINGS.HOST, port=settings.MQTT_SETTINGS.PORT)
self.client.on_message = on_message
self.client.on_connect = on_connect
while True:
self.client.loop()
-24
View File
@@ -1,24 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2017-11-19 10:55
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Brewing',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('cups', models.PositiveSmallIntegerField()),
('time', models.DateTimeField()),
],
),
]
+1 -4
View File
@@ -1,6 +1,3 @@
from django.db import models
class Brewing(models.Model):
cups = models.PositiveSmallIntegerField()
time = models.DateTimeField()
# Create your models here.
@@ -16,7 +16,7 @@ body {
background-size: contain;
background-repeat: no-repeat;
background-position: bottom center;
background-image: url("/static/img/smokes.png");
background-image: url("/static/coffee_scale/img/smokes.png");
transform-origin: bottom;
animation: smokes 8s ease-in-out 0s infinite;
opacity:0;
@@ -27,7 +27,7 @@ body {
background-size: contain;
background-repeat: no-repeat;
background-position: top center;
background-image: url("/static/img/coffeecup3.png");
background-image: url("/static/coffee_scale/img/coffeecup3.png");
height:60%;
}
#scale{

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

+5 -2
View File
@@ -1,3 +1,6 @@
{% load i18n %}
{% load static %}
<html>
<head>
<title>Coffee Cups @Guild Room - AYY SIK ry</title>
@@ -12,8 +15,8 @@
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.2/mqttws31.js"
type="text/javascript"></script>
<link rel="stylesheet" href="/static/css/coffee.css" />
<script src="/static/js/coffee.js"></script>
<link rel="stylesheet" href="{% static "coffee_scale/css/coffee.css" %}">
<script src="{% static "coffee_scale/js/coffee.js" %}"></script>
</head>
<body>
+5 -5
View File
@@ -1,12 +1,12 @@
from django.conf.urls import url
from django.views.generic.base import RedirectView
from django.conf import settings
from .views import coffee_view
favicon_view = RedirectView.as_view(url='static/img/favicon.ico', permanent=True)
urlpatterns = [
# landing page
url(r'^$', coffee_view),
]
if settings.DEBUG:
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns += staticfiles_urlpatterns()
+1 -1
View File
@@ -8,4 +8,4 @@ from django.conf import settings
def coffee_view(request):
return render(request, 'coffee.html')
return render(request, 'coffee_scale:coffee.html')
+3 -3
View File
@@ -5,9 +5,9 @@ services:
image: postgres
web:
build: .
image: git.sahkoinsinoorikilta.fi:4567/vtmk/web2.0
command: ["bash", "-c", "cd /code && ./wait-for-it.sh db:5432 -- bash setup.sh --no-input --no-npm && python manage.py runserver 0.0.0.0:8080"]
image: registry.gitlab.com/sahkoinsinoorikilta/vtmk/web2.0-backend
command: ["bash", "-c", "cd /code && ./wait-for-it.sh db:5432 -- bash setup.sh --no-input --no-npm && python manage.py runserver 0.0.0.0:8000"]
ports:
- "8080:8080"
- "8000:8000"
depends_on:
- db
+5
View File
@@ -0,0 +1,5 @@
from django.apps import AppConfig
class ExpensesClaimConfig(AppConfig):
name = 'expenses_claim'
+32
View File
@@ -0,0 +1,32 @@
"""Expenses claim form."""
from django import forms
from string import ascii_uppercase
class ExpensesClaim(forms.Form):
"""Expenses claim form."""
name = forms.CharField(label='Nimi', max_length=100)
iban = forms.CharField(label='IBAN', max_length=100)
email = forms.EmailField(label='Sähköposti', max_length=100)
amount = forms.DecimalField(label='Yhteensä', decimal_places=2)
def clean_iban(self):
"""Validate IBAN."""
orig_iban = self.cleaned_data['iban']
# Remove spaces.
cleaned_iban = orig_iban.replace(' ', '')
# Move first 4 symbols to the end of the string.
cleaned_iban = cleaned_iban[4:] + cleaned_iban[0:4]
LETTERS = {letter: str(index) for index,
letter in enumerate(ascii_uppercase, start=10)}
cleaned_iban = cleaned_iban.upper()
# Replace all letters with numbers, so that A=10, B=11, ..., Z=35.
cleaned_iban = [LETTERS[char] if char in LETTERS
else char for char in cleaned_iban]
cleaned_iban = ''.join(cleaned_iban)
# If cleaned_iban modulo 97 != 1 the IBAN number is invalid.
if int(cleaned_iban) % 97 != 1:
raise forms.ValidationError('Invalid IBAN number!')
return orig_iban
+3
View File
@@ -0,0 +1,3 @@
from django.db import models
# Create your models here.
@@ -0,0 +1,169 @@
* {
margin: 0;
padding: 0;
}
.heading {
padding: 20px 10px;
text-align: center;
}
.claim-form {
display: flex;
flex-direction: column;
align-items: center;
width: 100%
}
.form {
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
padding: 10px 20px;
width: 60%;
}
.table {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: space-between;
padding: 20px 10px;
}
.scrollarea {
display: flex;
flex-direction: column;
justify-content: flex-start;
overflow-y: scroll;
}
.tablerow {
display: flex;
flex-direction: row;
justify-content: space-between;
flex-wrap: wrap;
padding: 10px 5px;
}
.fieldscolumn {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-end;
}
.fieldsrow {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-items: stretch;
padding: 5px 10px;
}
.submit {
align-self: center;
width: 30%;
margin: 20px 10px;
}
.imageupload > input {
display: none;
}
.fieldsrow > div {
margin: 10px 20px;
}
.fieldscolumn > div {
margin: 10px 20px;
}
.fieldscolumn > div > label {
margin-right: 20px;
}
.money > input {
width: 100px;
}
#addreceipt {
height: 40px;
}
#total {
display: flex;
flex-direction: row;
justify-content: flex-end;
padding: 20px 10px;
}
#receiptslist {
height: 20rem;
}
#info2 {
justify-content: flex-end;
}
#textbox > textarea {
align-self: flex-end;
}
#id_iban {
width: 18rem;
}
.fieldscolumn > #textbox > textarea {
height: 8rem;
width: 18rem;
}
@media only screen and (max-width: 768px) {
.heading {
font-size: 18px;
padding: 5px 5px;
}
h1.heading {
visibility: hidden;
height: 0px;
}
.table {
padding: 5px 5px
}
#total {
justify-content: center;
}
.fieldsrow {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-around;
padding: 5px 5px
}
#receiptslist {
width: 12rem;
}
}
@media only screen and (max-height: 741px) {
#receiptslist {
height: 17rem;
}
}
@media only screen and (max-height: 569px) {
#receiptslist {
height: 10rem;
}
}
@@ -0,0 +1,27 @@
function addReceipt(event) {
event.preventDefault();
var receipts = document.getElementById("receiptslist");
var div2append = document.createElement("div");
var newrow = receipts.appendChild(div2append);
newrow.classList.add("tablerow");
div2append = document.createElement("div");
var div1 = newrow.appendChild(div2append);
div1.classList.add("imageupload");
div2append = document.createElement("div");
var div2 = newrow.appendChild(div2append);
div2.classList.add("desc");
div2append = document.createElement("div");
var div3 = newrow.appendChild(div2append);
div3.classList.add("money");
var file = document.getElementById("newreceipt");
var desc = document.getElementById("adddescription");
var sum = document.getElementById("addsum");
div1.appendChild(file.cloneNode(true));
div2.appendChild(document.createTextNode(desc.value));
div3.appendChild(document.createTextNode(sum.value));
var total = document.getElementById("totalsum");
total.value = Number(total.value) + Number(sum.value);
}
+19
View File
@@ -0,0 +1,19 @@
{% extends "project.html" %}
{% load static %}
{% load i18n %}
{% block styles %}
<script src="{% static "claim_form/js/addReceipt.js" %}"></script>
<link rel="stylesheet" href="{% static "claim_form/css/base.css" %}"></script>
{% endblock styles %}
{% block body %}
<div class="claim-form">
{% block content %}
{% include "expenses_claim:form.html" %}
{% endblock %}
</div>
{% endblock body %}
+20
View File
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<title>Raha-anomus</title>
</head>
<body>
<h1>Raha-anomus</h1>
<div>
<div>
{{ name }}
</div>
<div>
{{ iban }}
</div>
<div>
{{ amount }}
</div>
</div>
</body>
</html>
+72
View File
@@ -0,0 +1,72 @@
{% load i18n %}
{% load static %}
{% block content %}
<form class="form" id="claim" action="" method="post">
<h1 class="heading">Aalto Yliopiston Sähköinsinöörikilta ry Raha-anomuslomake</h1>
<div class="fieldsrow">
<div class="imageupload" id="newreceipt">
<label for="newreceipt">
Kuitti
<img class="thumbnail" src="{% static "claim_form/img/icon.png" %}"/>
</label>
<input id="selectreceipt" type="file"/>
</div>
<div>
<label for="adddescription">
Kuvaus
</label>
<input id="adddescription" type="text">
</div>
<div class="money">
<label for="addsum">
Summa
</label>
<input type="number" id="addsum" maxlength=100/>
</div>
<div>
<button id="addreceipt" onclick="addReceipt(event)">Lisää kuitti</button>
</div>
</div>
<div class="table">
<div class="scrollarea" id="receiptslist">
<div class="tablerow">
<div class="tableelement">Kuitti</div>
<div class="tableelement">Kuvaus</div>
<div class="tableelement">Summa</div>
</div>
</div>
<div class="money" id="total">
<label for="id_amount">Yhteensä</label>
{{ form.amount }}
</div>
</div>
<div class="fieldscolumn">
<div class="fieldsrow">
<div class="fieldscolumn" id="info1">
<div id="textbox">
<label for="selite">Selite</label>
<textarea id="selite"></textarea>
</div>
<div>
<label for="id_iban">{{ form.iban.label }}</label>
{{ form.iban }}
</div>
</div>
<div class="fieldscolumn" id="info2">
<div>
<label for="id_name">{{ form.name.label }}</label>
{{ form.name }}
</div>
<div>
<label for="id_email">{{ form.email.label }}</label>
{{ form.email }}
</div>
<input class="submit" id="submitclaim" type="submit" value="Submit"/>
</div>
</div>
</div>
{% csrf_token %}
</form>
{% endblock content %}
+60
View File
@@ -0,0 +1,60 @@
from django.test import TestCase
from .forms import ExpensesClaim
class ExpensesClaimTest(TestCase):
"""Test expenses claim form."""
def test_valid_data1(self):
form = ExpensesClaim({
'name': "John Doe",
'email': 'john@doe.com',
'iban': "FI37 1590 3000 0007 76",
'amount': 12.54
})
self.assertTrue(form.is_valid())
def test_valid_data2(self):
form = ExpensesClaim({
'name': "John Cena",
'email': 'john@cena.com',
'iban': "AL35202111090000000001234567",
'amount': 12
})
self.assertTrue(form.is_valid())
def test_valid_data3(self):
form = ExpensesClaim({
'name': "John Wayne",
'email': 'john@wayne.com',
'iban': "BR1500000000000010932840814P2",
'amount': 12.0
})
self.assertTrue(form.is_valid())
def test_invalid_iban(self):
form = ExpensesClaim({
'name': "John Lennon",
'email': 'john@lennon.com',
'iban': "FI3734 1590 3000 0007 76",
'amount': 12.54
})
self.assertFalse(form.is_valid())
def test_invalid_amount(self):
form = ExpensesClaim({
'name': "John Kenedy",
'email': 'john@kenedy.com',
'iban': "FI37 1590 3000 0007 76",
'amount': "asd"
})
self.assertFalse(form.is_valid())
def test_invalid_amount_decimal_places(self):
form = ExpensesClaim({
'name': "John Travolta",
'email': 'john@travolta.com',
'iban': "FI37 1590 3000 0007 76",
'amount': 12.544
})
self.assertFalse(form.is_valid())
+9
View File
@@ -0,0 +1,9 @@
"""Expenses claim urls."""
from django.conf.urls import url
from .views import claim
urlpatterns = [
url(r'^new', claim)
]
+41
View File
@@ -0,0 +1,41 @@
"""Expenses claim views."""
from django.shortcuts import render
from django.views.decorators.http import require_http_methods
from django.http import HttpResponse
from webapp.utils import send_email_with_attachment
from django.template.loader import render_to_string
from weasyprint import HTML
from .forms import ExpensesClaim
@require_http_methods(["GET", "POST"])
def claim(request):
"""Render expenses claim form."""
if request.method == 'POST':
form = ExpensesClaim(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
amount = form.cleaned_data['amount']
iban = form.cleaned_data['iban']
html_string = render_to_string('expenses_claim:claim2pdf.html',
{'name': name, 'iban': iban,
'amount': amount}).encode('UTF-8')
html = HTML(string=html_string)
attachment = html.write_pdf()
response = HttpResponse(
attachment, content_type='application/pdf;'
)
response['Content-Disposition'] = 'filename=claim.pdf'
email = "leo.kivikunnas@aalto.fi"
subject = "Test expenses claim"
body = "Test"
send_email_with_attachment(email, subject, body, attachment)
return response
elif request.method == 'GET':
form = ExpensesClaim()
return render(request, 'expenses_claim:base.html', {'form': form})
-45
View File
@@ -1,45 +0,0 @@
# Ilmotunkki
## Terms
- Signup, Form with collection of questions
- Response, One answer to some signup
- Quota, Amount of people allowed to respond with some option selected.
- In generic case there is no option and quota is just max number of people.
## Requirements
- Officials may generate signups forms
- Officials may see results from signups
- Officials may see some stats from their signups
- for example distributions of multiple choice answers
- Officials should be able to edit signups wherever possible
- Propably not possible to edit after first response
- Officials should be able to delete responses
- Officials should be able to embed payment information to the signup?
- TODO: is there need for unique reference numbers for every response?
- Officials should be able to save a signup to a reusable template.
- Signup may be attached to an event
- multiple signups to a single event?
- Signup should support custom quotas
- Atleast quotas from multiple choices and checkboxes
- Text quotas are risky (typos everywhere!!)
- Signup should have start and end times
- signup should support atleast following questiontypes
- Text
- multiple choice (select one)
- checkbox (boolean yes/no)
- Signup should support reserve slots.
TODO: quota based reserves or generic? or both?
- Responding should send confirm email
- Response should be editable by responder and only by the responder until the closing of the signup
- TODO: is there need to custom edit period or disable?
- Responders should see amount of quotas left.
- Responders should see some information about other responses
- TODO: names? should this be editable by officials?
- NOTE: Quota related info is exposed if any info is printed
-5
View File
@@ -1,5 +0,0 @@
from django.apps import AppConfig
class IlmotunkkiConfig(AppConfig):
name = 'ilmotunkki'
-16
View File
@@ -1,16 +0,0 @@
from django.db import models
from django.utils import timezone
class Signup(models.Model):
start = models.DateTimeField()
end = models.DateTimeField()
class Question(models.Model):
pass
class Answer(models.Model):
signup = models.ForeignKey(Signup, on_delete=models.CASCADE)
question = models.ForeignKey(Question, on_delete=models.PROTECT)
-3
View File
@@ -1,3 +0,0 @@
from django.shortcuts import render
# Create your views here.
+3 -6
View File
@@ -1,11 +1,9 @@
"""Admin site registers."""
from django.contrib import admin
from infoscreen.models import Rotation, InfoItem, InfoInstance
from infoscreen.models import ImageInfoItem, ExternalImageInfoItem, ABBInfoItem
from infoscreen.models import ExternalWebsiteInfoItem
from infoscreen.models import VideoInfoItem
from infoscreen.models import CoffeeStatsInfoItem
from infoscreen.models import (
Rotation, InfoItem, InfoInstance, ImageInfoItem,
ExternalImageInfoItem, ABBInfoItem, ExternalWebsiteInfoItem, VideoInfoItem)
# Register your models here.
admin.site.register(Rotation)
@@ -16,4 +14,3 @@ admin.site.register(ABBInfoItem)
admin.site.register(InfoInstance)
admin.site.register(ExternalWebsiteInfoItem)
admin.site.register(VideoInfoItem)
admin.site.register(CoffeeStatsInfoItem)
-70
View File
@@ -1,70 +0,0 @@
"""File containing Infoscreen HSL data fetcher classes."""
import requests
import json
import logging
import os
import pytz
from datetime import timedelta, datetime
from django.utils import timezone, dateparse
from django.utils.dateformat import format
from django.conf import settings
with open(os.path.join(settings.BASE_DIR, 'infoscreen', 'hsl_stops.graphql')) as stops_file:
STOPS_QUERY = stops_file.read()
with open(os.path.join(settings.BASE_DIR, 'infoscreen', 'hsl_stops_variables.json')) as vars_file:
STOPS_VARS = json.loads(vars_file.read())
API_URL = 'https://api.digitransit.fi/routing/v1/routers/hsl/index/graphql'
API_HEADERS = {'Content-Type': 'application/json'}
def fetch():
"""Fetch data from HSL API."""
query_vars = STOPS_VARS.copy()
query_vars['startTime_6'] = format(timezone.now(), 'U')
post_data = json.dumps({
'operationName': 'NearestRoutesContainer',
'query': STOPS_QUERY,
'variables': query_vars,
})
resp = requests.post(API_URL, data=post_data, headers=API_HEADERS)
data = resp.json()
items = data['data']['viewer']['_nearest']['edges']
places = map(lambda item: item['node']['place'], items)
schedule = []
for place in places:
route = place['pattern']['route']['shortName']
stop_times = place['_stoptimes']
for stop_time in stop_times:
timestamp = time_utc = stop_time['serviceDay'] + stop_time['realtimeArrival']
headsign = stop_time['stopHeadsign']
stop_name = stop_time['stop']['name']
time_diff = (timestamp - timezone.now().timestamp()) / 60 # minutes
if time_diff < settings.HSL_DEPARTURE_THRESHOLD:
continue
elif time_diff < settings.HSL_HURRY_THRESHOLD:
time = '{} min'.format(int(time_diff))
else:
time = pytz.utc.localize(datetime.fromtimestamp(timestamp)).strftime('%H:%M')
schedule.append({
'route': route,
'headsign': headsign,
'timestamp': time,
'stop': stop_name,
'utc': time_utc,
})
return schedule
-71
View File
@@ -1,71 +0,0 @@
query NearestRoutesContainer($lat_0: Float!, $lon_1: Float!, $maxDistance_2: Int!, $maxResults_3: Int!, $timeRange_7: Int!, $numberOfDepartures_8: Int!, $filterByModes_4: [Mode]!, $filterByPlaceTypes_5: [FilterPlaceType]!, $startTime_6: Long!) {
viewer {
...F5
}
}
fragment F0 on DepartureRow {
_stoptimes4caEfh: stoptimes(startTime: $startTime_6, timeRange: $timeRange_7, numberOfDepartures: $numberOfDepartures_8) {
pickupType
serviceDay
realtimeDeparture
}
id
}
fragment F1 on DepartureRow {
pattern {
route {
shortName
}
}
_stoptimes: stoptimes(startTime: $startTime_6, timeRange: $timeRange_7, numberOfDepartures: $numberOfDepartures_8) {
realtimeArrival
serviceDay
stopHeadsign
stop {
name
}
}
}
fragment F2 on BikeRentalStation {
id
}
fragment F3 on placeAtDistance {
distance
place {
id
__typename
...F1
...F2
}
id
}
fragment F4 on placeAtDistanceConnection {
edges {
node {
distance
place {
id
__typename
...F0
}
id
...F3
}
cursor
}
pageInfo {
hasNextPage
hasPreviousPage
}
}
fragment F5 on QueryType {
_nearest: nearest(lat: $lat_0, lon: $lon_1, maxDistance: $maxDistance_2, maxResults: $maxResults_3, first: $maxResults_3, filterByModes: $filterByModes_4, filterByPlaceTypes: $filterByPlaceTypes_5) {
...F4
}
}
-10
View File
@@ -1,10 +0,0 @@
{
"lat_0": 60.190480099999995,
"lon_1": 24.8275665,
"maxDistance_2": 1000,
"maxResults_3": 50,
"numberOfDepartures_8": 2,
"timeRange_7": 7200,
"filterByModes_4": ["BUS"],
"filterByPlaceTypes_5": ["DEPARTURE_ROW"]
}
-10
View File
@@ -1,10 +0,0 @@
from django.core.management.base import BaseCommand
from infoscreen.hsl_fetcher import HSLFetcher
class Command(BaseCommand):
help = 'Loads HSL timetables and save to json file.'
def handle(self, *args, **options):
fetcher = HSLFetcher()
fetcher.fetch()
@@ -15,4 +15,7 @@ class Migration(migrations.Migration):
migrations.DeleteModel(
name='HSLDataModel',
),
migrations.DeleteModel(
name='HslInfoItem',
),
]
@@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2017-11-19 14:41
from __future__ import unicode_literals
# Generated by Django 2.1.5 on 2019-03-26 12:49
from django.db import migrations, models
import django.db.models.deletion
@@ -14,7 +12,7 @@ class Migration(migrations.Migration):
operations = [
migrations.CreateModel(
name='CoffeeStatsInfoItem',
name='LunchItem',
fields=[
('infoitem_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='infoscreen.InfoItem')),
],
+30 -47
View File
@@ -98,12 +98,12 @@ class ABBInfoItem(InfoItem):
def get_template_url(self):
"""Return ABB infoitem template url."""
return "/static/html/abb.html"
return "/static/infoscreen/html/abb.html"
@staticmethod
def get_create_template_url():
"""Call create ABB infoitem template url command."""
return "/static/html/abb_create.html"
return "/static/infoscreen/html/abb_create.html"
class ApyInfoItem(InfoItem):
@@ -113,12 +113,12 @@ class ApyInfoItem(InfoItem):
def get_template_url(self):
"""Return APY infoitem template url."""
return "/static/html/apy.html"
return "/static/infoscreen/html/apy.html"
@staticmethod
def get_create_template_url():
"""Call create APY infoitem template url command."""
return "/static/html/apy_create.html"
return "/static/infoscreen/html/apy_create.html"
class ExternalWebsiteInfoItem(InfoItem):
@@ -129,12 +129,12 @@ class ExternalWebsiteInfoItem(InfoItem):
def get_template_url(self):
"""Return external website infoitem template url."""
return "/static/html/external_website.html?url={}".format(self.name)
return "/static/infoscreen/html/external_website.html?url={}".format(self.name)
@staticmethod
def get_create_template_url():
"""Call create external website infoitem template url command."""
return "/static/html/external_website_create.html"
return "/static/infoscreen/html/external_website_create.html"
def get_dict(self):
"""Convert django model to dict and return it."""
@@ -185,12 +185,25 @@ class SossoInfoItem(InfoItem):
def get_template_url(self):
"""Return Sosso infoitem template url."""
return "/static/html/sosso.html"
return "/static/infoscreen/html/sosso.html"
@staticmethod
def get_create_template_url():
"""Call create Sosso infoitem template url command."""
return "/static/html/sosso_create.html"
return "/static/infoscreen/html/sosso_create.html"
class LunchItem(InfoItem):
"""Class for Lunch Infoscreen item."""
display_name = _("Today's lunch")
def get_template_url(self):
return "/static/infoscreen/html/lunch.html"
@staticmethod
def get_create_template_url():
return "/static/infoscreen/html/lunch_create.html"
class EventInfoItem(InfoItem):
@@ -200,12 +213,12 @@ class EventInfoItem(InfoItem):
def get_template_url(self):
"""Return Event infoitem template url."""
return "/static/html/events.html"
return "/static/infoscreen/html/events.html"
@staticmethod
def get_create_template_url():
"""Call create Event infoitem template url command."""
return "/static/html/events_create.html"
return "/static/infoscreen/html/events_create.html"
class ImageInfoItem(InfoItem):
@@ -218,12 +231,12 @@ class ImageInfoItem(InfoItem):
"""Return Image infoitem template url."""
# get param to avoid angular from optimizing same template
# with different options
return "/static/html/generic_image.html?img={}".format(self.name)
return "/static/infoscreen/html/generic_image.html?img={}".format(self.name)
@staticmethod
def get_create_template_url():
"""Call create Image infoitem template url command."""
return "/static/html/generic_image_create.html"
return "/static/infoscreen/html/generic_image_create.html"
def get_dict(self):
"""Convert django model to dict and return it."""
@@ -240,12 +253,12 @@ class VideoInfoItem(InfoItem):
def get_template_url(self):
"""Return Video infoitem template url."""
return "/static/html/generic_video.html?video={}".format(self.name)
return "/static/infoscreen/html/generic_video.html?video={}".format(self.name)
@staticmethod
def get_create_template_url():
"""Call create Video infoitem template url command."""
return "/static/html/generic_video_create.html"
return "/static/infoscreen/html/generic_video_create.html"
def get_dict(self):
"""Convert django model to dict and return it."""
@@ -254,36 +267,6 @@ class VideoInfoItem(InfoItem):
return d
class HslInfoItem(InfoItem):
"""Class for HSL Infoscreen item."""
display_name = _("HSL timetables")
def get_template_url(self):
"""Return HSL infoitem template url."""
return "/static/html/hsl.html"
@staticmethod
def get_create_template_url():
"""Call create HSL infoitem template url command."""
return "/static/html/hsl_create.html"
class CoffeeStatsInfoItem(InfoItem):
"""Class for Coffee statistics Infoscreen item."""
display_name = _("Coffee statistics")
def get_template_url(self):
"""Return HSL infoitem template url."""
return "/static/html/coffee_stats.html"
@staticmethod
def get_create_template_url():
"""Call create HSL infoitem template url command."""
return "/static/html/coffee_stats_create.html"
class ExternalImageInfoItem(InfoItem):
"""Class for External Image Infoscreen item."""
@@ -292,12 +275,12 @@ class ExternalImageInfoItem(InfoItem):
def get_template_url(self):
"""Return External Image infoitem template url."""
return "/static/html/generic_image.html?img={}".format(self.name)
return "/static/infoscreen/html/generic_image.html?img={}".format(self.name)
@staticmethod
def get_create_template_url():
"""Call create External Image infoitem template url command."""
return "/static/html/generic_external_image_create.html"
return "/static/infoscreen/html/generic_external_image_create.html"
def get_dict(self):
"""Convert django model to dict and return it."""
@@ -336,7 +319,7 @@ class ExternalImageInfoItem(InfoItem):
class InfoInstance(models.Model):
"""Class for Info instance in Infoscreen."""
rotation = models.ForeignKey('Rotation', related_name='instances')
rotation = models.ForeignKey('Rotation', related_name='instances', on_delete=models.CASCADE)
duration = models.FloatField(default=15.0) # seconds
# generic relation to some kind of InfoItem
item_id = models.PositiveIntegerField()
-74
View File
@@ -1,74 +0,0 @@
table {
font-size: 4vh;
font-family: 'Droid Sans Mono', monospace;
}
.red {
color: red;
-webkit-animation-name: blinker;
-webkit-animation-duration: 2s;
-webkit-animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-name: blinker;
-moz-animation-duration: 2s;
-moz-animation-timing-function: linear;
-moz-animation-iteration-count: infinite;
animation-name: blinker;
animation-duration: 2s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
.black {
color: black;
}
@-moz-keyframes blinker {
0% { opacity: 1.0; }
50% { opacity: 0.1; }
100% { opacity: 1.0; }
}
@-webkit-keyframes blinker {
0% { opacity: 1.0; }
50% { opacity: 0.1; }
100% { opacity: 1.0; }
}
@keyframes blinker {
0% { opacity: 1.0; }
50% { opacity: 0.1; }
100% { opacity: 1.0; }
}
thead{
background: #f0f0f0;
}
.header-row{
background: #f0f0f0;
font-size: 7vh;
font-family: 'Droid Sans Mono', monospace;
text-align: center;
}
.container {
width: 100vw;
padding: 0 0 0 0;
}
.container .table {
margin-left: 0;
margin-right: 0;
}
.repeat-item.ng-leave {
}
.repeat-item.ng-leave.ng-leave-active {
opacity: 0;
font-size: 0vh;
}
.repeat-item.ng-leave{
opacity: 1;
font-size: 5vh;
}
-4
View File
@@ -1,4 +0,0 @@
<link rel="stylesheet" href="/static/css/coffee.css">
<iframe src="https://host2.kilta.aalto.fi/kahvi/cups" allowfullscreen=true sandbox="allow-scripts allow-pointer-lock allow-same-origin">
<p>Your browser does not support iframes.</p>
</iframe>
-9
View File
@@ -1,9 +0,0 @@
<link rel="stylesheet" href="/static/css/hsl.css">
<link href="https://fonts.googleapis.com/css?family=Droid+Sans+Mono" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.19.1/locale/fi.js"></script>
<script type="text/javascript" src="dygraph.js"></script>
<link rel="stylesheet" src="dygraph.css" /></head>
<div class="container" ng-controller="CoffeeStatsController">
<div id="div_g"></div>
</div>
@@ -1,11 +0,0 @@
<div ng-controller="infoadmin_coffeestatsitem_create" style="margin-top:20px;">
<div>
Create new item to show coffee statistics. Name is used only as identifier
</div>
<div class="form-group">
<label>Name:</label>
<input type="text" ng-model="item.name"></input>
</div>
<input type="button" class="btn btn-success" ng-click="send()" value="create"></input>
</div>
<!--maybe later add option to choose data range, daily, monthly...etc.
-41
View File
@@ -1,41 +0,0 @@
<link rel="stylesheet" href="/static/css/hsl.css">
<link href="https://fonts.googleapis.com/css?family=Droid+Sans+Mono" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.19.1/locale/fi.js"></script>
<div class="container" ng-app="myApp" ng-controller="timetableCtrl">
<div class="header-row row">
<div class="col-sm-2"><p>{{clock | date:'HH:mm'}}</p></div>
<div class="col-sm-8">HSL-Aikataulut</div>
<div class="col-sm-2 time"></div>
</div>
<h1 style="font-size: 10vh; text-align: center" ng-if="error">
{{error}}
</h1>
<table ng-if="!error" class="table table-striped row">
<thead>
<tr>
<th>
Aika
</th>
<th>
Linja
</th>
<th>
Pys&#228;kki
</th>
</tr>
</thead>
<tbody>
<tr class="repeat-item" ng-repeat="x in stoptimes | orderBy: ['utc'] | limitTo: 11">
<td style="min-width: 300px">
{{x.timestamp}}
</td>
<td>
<strong>{{x.route}}</strong>, {{x.headsign}}
</td>
<td>
{{x.stop}}
</td>
</tr>
</tbody>
</table>
</div>
-10
View File
@@ -1,10 +0,0 @@
<div ng-controller="infoadmin_hslitem_create" style="margin-top:20px;">
<div>
Create new item to show hsl ttimetables. Name is used only as identifier
</div>
<div class="form-group">
<label>Name:</label>
<input type="text" ng-model="item.name"></input>
</div>
<input type="button" class="btn btn-success" ng-click="send()" value="create"></input>
</div>
-20
View File
@@ -1,20 +0,0 @@
<link rel="stylesheet" href="/static/css/sosso.css">
<div ng-controller="SossoController">
<div id="header">
<img id="header-image" src="/static/img/sossoheader.png" >
</div>
<div id="container">
<div class="article-row row" ng-repeat="post in data.posts">
<div class="article-thumb-col col-md-6">
<img class="thumbnail" ng-src="{{ post.thumbnail_images['mh-edition-lite-medium'].url }}">
</div>
<div>
<h1 class="col-md-6">
<div class="article-title-col">
{{ post.title }}
</div>
</h1>
</div>
</div>
</div>
</div>
-1
View File
@@ -1 +0,0 @@
<h1>testi2</h1>
-1
View File
@@ -1 +0,0 @@
<h1>testi3</h1>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 736 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

@@ -2,7 +2,10 @@ body {
font-family: 'Open Sans', sans-serif;
}
#header {
#header:after {
content: " ";
display: block;
clear: both;
}
#header-logo {
@@ -5,6 +5,7 @@ html {
body {
padding: 1.5rem;
margin: 0.5rem;
height: 100%;
}
tbody {
@@ -49,7 +50,18 @@ td {
}
}
#header {
max-width: 100%;
display: flex;
justify-content: flex-end;
}
.tab-content {
margin-top: 1rem;
}
.rotation-title-row {
display: flex;
justify-content: space-between;
align-items: center;
}
@@ -0,0 +1,53 @@
#header {
height: 30%;
width: 100%;
background-color:#7c1330;
text-align: center;
}
#header-image {
display: block;
margin-left: auto;
margin-right: auto;
max-width: 100%;
}
.article-row {
min-height: 20vh;
margin: 10px 10px 10px 10px;
}
.article-thumb-col {
max-height: 200px;
text-align: left;
}
.article-title-col {
font-size: 3vw;
}
.thumbnail {
max-width: 355px;
max-height: 200px;
}
#sossoimage {
height: 300px;
position: relative;
left: 0px;
top: 0px;
}
.stretch {
width:100%;
height:100%;
}
#post {
height: 540px;
border:2px solid black;
}
#container {
max-height: 70%;
}
@@ -19,7 +19,7 @@
.article-thumb-col {
max-height: 200px;
text-align: right;
text-align: left;
}
.article-title-col {
@@ -1,10 +1,10 @@
<link rel="stylesheet" href="/static/css/abb.css">
<link rel="stylesheet" href="/static/infoscreen/css/abb.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet">
<div ng-controller="ABBController">
<!-- Only show the job listing if there are any jobs, i.e, the jobs list is non-empty -->
<div id="header" class="row" ng-if="jobs.length > 0">
<div id="header-logo">
<img src="/static/img/ABB_logo.png">
<img src="/static/infoscreen/img/ABB_logo.png">
</div>
<div id="header-title">
TYÖPAIKAT
@@ -28,6 +28,6 @@
<!-- If there are no jobs, show a static image -->
<div class="row" ng-if="jobs.length == 0">
<img src="/static/img/ABB_uralle.png" style="position:absolute;left:0;top:0;width:100vw;">
<img src="/static/infoscreen/img/ABB_uralle.png" style="position:absolute;left:0;top:0;width:100vw;">
</div>
</div>
@@ -4,7 +4,7 @@
</div>
<div class="form-group">
<label>Name:</label>
<input type="text" ng-model="item.name"></input>
<input class="form-control" type="text" ng-model="item.name"></input>
</div>
<input type="button" class="btn btn-success" ng-click="send()" value="create"></input>
</div>
@@ -1,4 +1,4 @@
<link rel="stylesheet" href="/static/css/apy.css">
<link rel="stylesheet" href="/static/infoscreen/css/apy.css">
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro" rel="stylesheet">
<div id="bg">
<div class="container " ng-controller="ApyController">
@@ -1,10 +1,10 @@
<div ng-controller="infoadmin_apyitem_create" style="margin-top:20px;">
<div>
create apyitem
Create new ÄPY statistics item
</div>
<div class="form-group">
<label>Name:</label>
<input type="text" ng-model="item.name"></input>
<input class="form-control" type="text" ng-model="item.name"></input>
</div>
<input type="button" class="btn btn-success" ng-click="send()" value="create"></input>
</div>
@@ -1,4 +1,4 @@
<link rel="stylesheet" href="/static/css/events.css">
<link rel="stylesheet" href="/static/infoscreen/css/events.css">
<link href="https://fonts.googleapis.com/css?family=Droid+Sans+Mono" rel="stylesheet">
<div class="container" ng-app="myApp" ng-controller="EventController">
<div class="header-row row">
@@ -4,7 +4,7 @@
</div>
<div class="form-group">
<label>Name:</label>
<input type="text" ng-model="item.name"></input>
<input type="text" class="form-control" ng-model="item.name"></input>
</div>
<input type="button" class="btn btn-success" ng-click="send()" value="create"></input>
</div>
@@ -1,4 +1,4 @@
<link rel="stylesheet" href="/static/css/external_website.css">
<link rel="stylesheet" href="/static/infoscreen/css/external_website.css">
<iframe ng-src="{{ url | trusted_url }}" allowfullscreen=true sandbox="allow-scripts allow-pointer-lock allow-same-origin">
<p>Your browser does not support iframes.</p>
</iframe>
@@ -1,14 +1,14 @@
<div ng-controller="infoadmin_websiteitem_create" style="margin-top:20px;">
<div>
Create new item to show external website. For example "ka.dy.fi".
Create new item to show external website. For example "https://ka.dy.fi".
</div>
<div class="form-group">
<label>Name:</label>
<input type="text" ng-model="item.name"></input>
<input type="text" class="form-control" ng-model="item.name"></input>
</div>
<div class="form-group">
<label>Url:</label>
<input type="text" ng-model="item.url"></input>
<input type="text" class="form-control" ng-model="item.url"></input>
</div>
<input type="button" class="btn btn-success" ng-click="send()" value="create"></input>
</div>
@@ -4,11 +4,11 @@
</div>
<div class="form-group">
<label>Name:</label>
<input type="text" ng-model="item.name"></input>
<input type="text" class="form-control" ng-model="item.name"></input>
</div>
<div class="form-group">
<label>Url:</label>
<input type="text" ng-model="item.url"></input>
<input type="text" class="form-control" ng-model="item.url"></input>
</div>
<input type="button" class="btn btn-success" ng-click="send()" value="create"></input>
</div>
@@ -4,7 +4,7 @@
</div>
<div class="form-group">
<label>Name:</label>
<input type="text" ng-model="imagename"></input>
<input type="text" class="form-control" ng-model="imagename"></input>
</div>
<div class="form-group">
<input type="file" ngf-select ng-model="img" name="file" required>
@@ -1,4 +1,4 @@
<link rel="stylesheet" href="/static/css/video.css">
<link rel="stylesheet" href="/static/infoscreen/css/video.css">
<div class="fullscreen-bg">
@@ -4,7 +4,7 @@
</div>
<div class="form-group">
<label>Name:</label>
<input type="text" ng-model="name"></input>
<input type="text" class="form-control" ng-model="name"></input>
</div>
<div class="form-group">
<input type="file" ngf-select ng-model="video" name="file" required>
@@ -0,0 +1,11 @@
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
<link rel="stylesheet" href="/static/infoscreen/css/lunch.css">
<div ng-controller="LunchController">
<div id="container">
<div class="restaurant row" ng-repeat="restaurant in data">
<div class="lunch-option" ng-repeat="l in lunch">
<h3 ng-bind-html="l.title | unsafe"></h3>
</div>
</div>
</div>
</div>
@@ -0,0 +1,10 @@
<div ng-controller="infoadmin_lunchitem_create" style="margin-top:20px;">
<div>
Create new item to show restaurants. Name is used only as identifier
</div>
<div class="form-group">
<label>Name:</label>
<input type="text" class="form-control" ng-model="item.name"></input>
</div>
<input type="button" class="btn btn-success" ng-click="send()" value="create"></input>
</div>
@@ -0,0 +1,17 @@
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
<link rel="stylesheet" href="/static/infoscreen/css/sosso.css">
<div ng-controller="SossoController">
<div id="header">
<img id="header-image" src="/static/infoscreen/img/sossoheader.png" >
</div>
<div id="container">
<div class="article-row row" ng-repeat="post in data.posts">
<div class="article-thumb-col col-md-4">
<img class="thumbnail" ng-src="{{ post.thumbnail_images['mh-edition-lite-medium'].url }}">
</div>
<div class="col-md-8 article-title-col">
<h1 ng-bind-html="post.title | unsafe"></h1>
</div>
</div>
</div>
</div>
@@ -4,7 +4,7 @@
</div>
<div class="form-group">
<label>Name:</label>
<input type="text" ng-model="item.name"></input>
<input type="text" class="form-control" ng-model="item.name"></input>
</div>
<input type="button" class="btn btn-success" ng-click="send()" value="create"></input>
</div>

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 80 KiB

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

@@ -182,10 +182,9 @@ var simple_controllers = [
"external_image",
"abbitem",
"sossoitem",
"lunchitem",
"eventitem",
"hslitem",
"websiteitem",
"apyitem",
"coffeestatsitem",
];
_.each(simple_controllers, controllerGenerator);
@@ -46,6 +46,13 @@ app.filter('trusted_url', ['$sce', function ($sce) {
};
}]);
//Used for special characters in Sosso. This may open up XSS, so we need to trust that sosso.fi doesn't get compromised...
app.filter('unsafe', function($sce) {
return function(val) {
return $sce.trustAsHtml(val);
};
});
app.controller('ABBController', function($scope, $http){
$scope.jobs = [];
var min_date = moment().subtract(30,'days').format("YYYY-MM-DD%20HH:mm:ss");
@@ -75,6 +82,21 @@ app.controller('SossoController', function($scope, $http) {
})
});
app.controller('LunchController', function ($scope, $http) {
$scope.data = [];
var restaurants = [42];
var restaurant_names = ["TUAS"]
var cur_date = new Date().toISOString().split("T")[0]
$http.get("https://kitchen.kanttiinit.fi/menus?restaurants=" + restaurants.join(",") + "&days=" + cur_date).then(function (response) {
$scope.data = restaurant_names.map(function(n, idx) {
return {
name: n,
lunch: response[idx][cur_date],
}
});
})
});
app.controller('ApyController', function($scope, $http) {
$scope.items = [];
$http.get("/infoscreen/apyjson").then(function(response)
@@ -112,49 +134,3 @@ app.filter('unixTimeToDifference', function() {
return res;
}
})
app.controller('timetableCtrl',
function($scope, $http, $interval) {
function load() {
$http.get('/infoscreen/hsl_data')
.then(function(data, status, headers, config) { //eslint-disable-line no-unused-vars
$scope.stoptimes = data.data;
$scope.error = data.data.error || null;
});
$http.get('/infoscreen/hsl_data/settings')
.then(function(data, status, headers, config) { //eslint-disable-line no-unused-vars
$scope.departureThreshold = data.data['departure_threshold'];
$scope.hurryThreshold = data.data['hurry_threshold'];
});
}
function update_clock() {
$scope.clock = Date.now();
}
$scope.$on('$destroy', function() {
$interval.cancel(load_interval);
$interval.cancel(clock_interval);
});
var load_interval = $interval(load, 5000);
var clock_interval = $interval(update_clock, 1000);
update_clock();
load();
});
app.controller('CoffeeStatsController', function($scope, $http) {
function load() {
$http.get('/infoscreen/coffee_data')
.then(function(response) {
const g = new Dygraph(document.getElementById('div_g'), response.data, {
drawPoints: true,
valueRange: [0, 10],
labels: ['Time', 'Cups']
});
});
}
load();
});
+44
View File
@@ -0,0 +1,44 @@
{% load i18n %}
{% load static %}
{% load staticfiles %}
<!DOCTYPE html>
{% block html %}
<html ng-app="{% block appname %}{% endblock appname %}">
<head>
<meta charset="utf-8" name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1" />
<title>
{% block title %}
{% endblock title %}
</title>
{% block libraries %}
<script src="{% static "js/lib/angular.js" %}"></script>
<script src="{% static "js/lib/ng-file-upload-bower-12.2.11/ng-file-upload-all.js" %}"></script>
<script src="{% static "js/lib/jquery-3.1.0.min.js" %}"></script>
<script src="{% static "js/lib/underscore-min.js" %}"></script>
<script src="{% static "js/lib/moment.js" %}"></script>
<script src="{% static "js/lib/angular-route.js" %}"></script>
<script src="{% static "js/lib/angular-animate.js" %}"></script>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
{% endblock libraries %}
{% block styles %}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link rel="stylesheet" href="{% static "webapp/css/footer.css" %}">
{% endblock styles %}
{% block controllers %}
<script src="{% static "infoscreen/js/infoadmin_controllers.js" %}"></script>
{% endblock controllers %}
</head>
<body>
{% block body %}
{% endblock body %}
</body>
</html>
{% endblock html %}
+7
View File
@@ -0,0 +1,7 @@
{% load i18n %}
{% load static %}
<div class="header-content">
<div class="logo">
<a href="/"><img src="{% static "webapp/img/logo_header.png" %}" alt="Aalto-yliopiston Sähköinsinöörikilta ry"></a>
</div>
</div>
+39 -148
View File
@@ -1,154 +1,45 @@
{% extends "infoscreen:base.html" %}
{% load i18n %}
{% load static %}
{% load staticfiles %}
<!DOCTYPE html>
<html ng-app="infoAdmin">
<head>
<meta charset="utf-8" name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1" />
<title>Infoscreen admin</title>
<script src="{% static "js/lib/angular.js" %}"></script>
<script src="{% static "js/lib/ng-file-upload-bower-12.2.11/ng-file-upload-all.js" %}"></script>
<script src="{% static "js/lib/jquery-3.1.0.min.js" %}"></script>
<script src="{% static "js/lib/bootstrap.min.js" %}"></script>
<script src="{% static "js/lib/underscore-min.js" %}"></script>
<script src="{% static "js/infoadmin_controllers.js" %}"></script>
<link rel="stylesheet" href="{% static "css/lib/bootstrap.min.css" %}"></link>
<link rel="stylesheet" href="{% static "css/base.css" %}"></link>
<link rel="stylesheet" href="{% static "css/infoscreen_admin.css" %}"></link>
</head>
<body>
<div id="header" class="row">
<div class="logout-button">
<form action="/logout" method="post"> {% csrf_token %}
<input type="Submit" value="{% trans "Log out" %}" name="Logout" class="btn btn-danger"/>
</form>
</div>
{% block appname %}infoAdmin{% endblock appname %}
{% block title %}
{% trans "Infoscreen admin" %}
{% endblock title %}
{% block styles %}
{{ block.super }}
<link rel="stylesheet" href="{% static "infoscreen/css/admin.css" %}"></link>
{% endblock styles %}
{% block controllers %}
<script src="{% static "infoscreen/js/infoadmin_controllers.js" %}"></script>
{% endblock controllers %}
{% block body %}
<div id="header" class="row">
<div class="logout-button">
<form action="/admin/logout/" method="post"> {% csrf_token %}
<input type="Submit" value="{% trans "Log out" %}" name="Logout" class="btn btn-danger"/>
</form>
</div>
</div>
<div class="container" ng-controller="infoadmin_ctrl">
<div class="row">
<div class="col">
<h1>{% trans "Infoscreen Admin Pane" %}</h1>
</div>
<div class="container" ng-controller="infoadmin_ctrl">
<div class="row">
<div class="col-md-12">
<h1>{% trans "Infoscreen Admin Pane" %}</h1>
</div>
</div>
<ul class="nav nav-tabs" role="tablist">
<li class="active"><a data-toggle="tab" href="#slides" role="tab">{% trans "Manage Slides" %}</a></li>
<li class="dropdown">
<a data-toggle="dropdown" href="#">{% trans "Manage Rotations" %}<span class="caret"></span></a>
<ul class="dropdown-menu">
<li ng-repeat="r in rotations"><a href="#rotations" ng-click="selectRotation(r.id)" data-toggle="tab">{$ r.name $}</a></li>
<li class="divider">
<li class="nav-item"><a data-toggle="tab" href="#deleterot" role="tab">{% trans "Create/Delete" %}</a></li>
</ul>
</ul>
<div class="tab-content row">
<div id="slides" class="tab-pane active">
<div ng-controller="infoadmin_ctrl">
<div class="col-xs-12 col-md-6">
<h2>{% trans "Create new item" %}</h2>
<div>{% trans "Create a new item by type" %}</div>
<table class="table table-striped">
<tr>
<td>{% trans "Item type" %}</td>
<td>
<select class="form-control form-control-sm" ng-model="createtype", ng-options="t.name for t in infotypes | orderBy: 'name'">
<option value=""></option>
</select>
</td>
</tr>
</table>
<div ng-include="createtype.create_template_url"></div>
</div>
<div class="col-xs-12 col-md-6">
<h2>{% trans "Info items" %}</h2>
<div>{% trans "Infoitems available for rotations" %}</div>
<table class="table table-striped">
<tr>
<th>{% trans "Item" %}</th>
<th>{% trans "Type" %}</th>
<th>{% trans "Delete" %}</th>
</tr>
<tr ng-repeat="i in infoitems | orderBy:['display_name','name']">
<td>{$ i.name $}</td>
<td>{$ i.display_name $}</td>
<td><input type="button" class="btn btn-danger" ng-click="deleteItem(i.item_type, i.id);" value="{% trans "Delete" %}"></input></td>
</tr>
</table>
</div>
{% include "infoscreen:nav.html" %}
<div class="tab-content" id="tabContent">
{% include "infoscreen:tabs/slides.html" %}
{% include "infoscreen:tabs/rotations.html" %}
{% include "infoscreen:tabs/add_remove.html" %}
</div>
</div>
</div>
</div>
</div>
<div id="rotations" class="tab-pane" ng-controller="infoadmin_ctrl">
<div class="col-xs-12 col-md-6">
<h2>{% trans "Info items" %}</h2>
<div>{% trans "Infoitems available for rotations" %}</div>
<table class="table table-striped">
<tr>
<th>{% trans "Item" %}</th>
<th>{% trans "Type" %}</th>
<th>{% trans "Set duration" %}</th>
<th>{% trans "Add to rotation" %}</th>
<th>{% trans "Delete" %}</th>
</tr>
<tr ng-repeat="i in infoitems | orderBy:['display_name','name']">
<td>{$ i.name $}</td>
<td>{$ i.display_name $}</td>
<td><input type="number" min="1" max="60" class="form-control" ng-model="i.duration"></input></td>
<td><input type="button" class="btn btn-success" ng-click="createInstance(selected_rot.id, i.id, i.item_type, i.duration);" value="{% trans "Add" %}"></input></td>
<td><input type="button" class="btn btn-danger" ng-click="deleteItem(i.item_type, i.id);" value="{% trans "Delete" %}"></input></td>
</tr>
</table>
</div>
<div class="col-xs-12 col-md-6">
<h2>{% trans "Rotation" %}: {$ selected_rot.name $}<a href="/infoscreen/{$ selected_rot.id $}"><input type="button" class="btn btn-primary pull-right" value="{% trans "Preview" %}"></a></h2>
<div>{% trans "Instances in currently selected rotation" %}:</div>
<table class="table table-striped">
<tr>
<th>{% trans "Instance" %}</th>
<th>{% trans "Duration" %}</th>
<th>{% trans "Delete" %}</th>
</tr>
<tr ng-repeat="i in selected_rot.instances">
<td>{$ i.item.name $}</td><td>{$ i.duration $} s</td>
<td><input type="button" ng-click="deleteInstance(i.id);" value="{% trans "Delete" %}" class="btn btn-danger"></input></td>
</tr>
</table>
</div>
</div>
<div id="deleterot" class="tab-pane">
<div class="col-xs-12 " ng-controller="infoadmin_ctrl">
<h2>{% trans "Rotations" %}</h2>
<div>
{% trans "Select rotation to edit" %}:
</div>
<table class="table table-striped">
<tr>
<th>{% trans "Rotation" %}</th>
<th>{% trans "id" %}</th>
<th>{% trans "Preview" %}</th>
<th>{% trans "Delete" %}</th>
</tr>
<tr ng-repeat="r in rotations">
<td>{$ r.name $}</td>
<td>{$ r.id $}</td>
<td><a href="/infoscreen/{$ r.id $}"><input type="button" class="btn btn-primary" value="{% trans "Preview" %}"></a></td>
<td><input type="button" class="btn btn-danger" ng-click="deleteRotation(r.id)" value="{% trans "Delete" %}"></input></td>
</tr>
<tr>
<td><input type="text" class="form-control" ng-model="r.name" placeholder="{% trans "Name" %}"></input></td>
<td><input type="button" class="btn btn-success" ng-click="createRotation(r.name)" value="{% trans "Create new" %}"></input></td>
<td></td>
<td></td>
</tr>
</table>
</div>
</div>
</div>
<div style="margin-top: 100px;">
{% include "footer.html" %}
</div>
</div>
</body>
</html>
{% include "webapp:footer.html" %}
{% endblock body %}
+21 -25
View File
@@ -1,29 +1,25 @@
{% extends "infoscreen:base.html" %}
{% load static %}
{% load i18n %}
<!DOCTYPE html>
<html ng-app="infoApp">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
{% block appname %}infoApp{% endblock appname %}
<title>Infoscreen</title>
<script src="{% static "js/lib/moment.js" %}"></script>
<script src="{% static "js/lib/angular.js" %}"></script>
<script src="{% static "js/lib/angular-route.js" %}"></script>
<script src="{% static "js/lib/angular-animate.js" %}"></script>
<script src="{% static "js/lib/jquery-3.1.0.min.js" %}"></script>
<script src="{% static "js/lib/bootstrap.min.js" %}"></script>
<script src="{% static "js/lib/underscore-min.js" %}"></script>
<script src="{% static "js/infoscreen_controllers.js" %}"></script>
{% block title %}
{% trans "Infoscreen" %}
{% endblock title %}
<link rel="stylesheet" href="{% static "css/lib/bootstrap.min.css" %}"></link>
<link rel="stylesheet" href="{% static "css/infoscreen.css" %}"></link>
</head>
<body>
<div class="container ng-scope" ng-controller="infoscreen_main" ng-init="init({{ rotation }})">
<div ng-animate-swap="index" class="cell swap-animation">
<div id="infocontent" ng-include="active.template" onload="active.onload()"></div>
</div>
</div>
</body>
</html>
{% block controllers %}
<script src="{% static "infoscreen/js/infoscreen_controllers.js" %}"></script>
{% endblock controllers %}
{% block styles %}
<link rel="stylesheet" href="{% static "infoscreen/css/infoscreen.css" %}"></link>
{% endblock styles %}
{% block body %}
<div class="container ng-scope" ng-controller="infoscreen_main" ng-init="init({{ rotation }})">
<div ng-animate-swap="index" class="cell swap-animation">
<div id="infocontent" ng-include="active.template" onload="active.onload()"></div>
</div>
</div>
{% endblock body %}
+17
View File
@@ -0,0 +1,17 @@
{% load i18n %}
<ul class="nav nav-tabs" id="tabs" role="tablist">
<li class="nav-item">
<a class="nav-link active" data-toggle="tab" role="tab" href="#slides">{% trans "Manage Slides" %}</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" role="button" data-toggle="dropdown" href="#" aria-haspopup="true" aria-expanded="false">
{% trans "Manage Rotations" %}<span class="caret"></span>
</a>
<div class="dropdown-menu">
<a class="dropdown-item" role="tab" href="#rotations" ng-repeat="r in rotations" ng-click="selectRotation(r.id)" data-toggle="tab">{$ r.name $}</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" data-toggle="tab" href="#deleterot" role="tab">{% trans "Create/Delete" %}</a>
</div>
</li>
</ul>
+30
View File
@@ -0,0 +1,30 @@
{% load i18n %}
<div id="deleterot" class="tab-pane fade" role="tabpanel">
<div class="col" ng-controller="infoadmin_ctrl">
<h2>{% trans "Rotations" %}</h2>
<div>
{% trans "Select rotation to edit" %}:
</div>
<table class="table table-striped">
<tr>
<th>{% trans "Rotation" %}</th>
<th>{% trans "id" %}</th>
<th>{% trans "Preview" %}</th>
<th>{% trans "Delete" %}</th>
</tr>
<tr ng-repeat="r in rotations">
<td>{$ r.name $}</td>
<td>{$ r.id $}</td>
<td><a class="btn btn-primary" href="/infoscreen/{$ r.id $}">{% trans "Preview" %}</a></td>
<td><a class="btn btn-danger" href="#" ng-click="deleteRotation(r.id)">{% trans "Delete" %}</a></td>
</tr>
<tr>
<td><input type="text" class="form-control" ng-model="r.name" placeholder="{% trans "Name" %}"></input></td>
<td><input type="button" class="btn btn-success" ng-click="createRotation(r.name)" value="{% trans "Create new" %}"></input></td>
<td></td>
<td></td>
</tr>
</table>
</div>
</div>
+44
View File
@@ -0,0 +1,44 @@
{% load i18n %}
<div id="rotations" class="tab-pane fade" role="tabpanel" ng-controller="infoadmin_ctrl">
<div class="col">
<h2>{% trans "Info items" %}</h2>
<div>{% trans "Infoitems available for rotations" %}</div>
<table class="table table-striped">
<tr>
<th>{% trans "Item" %}</th>
<th>{% trans "Type" %}</th>
<th>{% trans "Set duration" %}</th>
<th>{% trans "Add to rotation" %}</th>
<th>{% trans "Delete" %}</th>
</tr>
<tr ng-repeat="i in infoitems | orderBy:['display_name','name']">
<td>{$ i.name $}</td>
<td>{$ i.display_name $}</td>
<td><input type="number" min="1" max="60" class="form-control" ng-model="i.duration"></input></td>
<td><input type="button" class="btn btn-success" ng-click="createInstance(selected_rot.id, i.id, i.item_type, i.duration);" value="{% trans "Add" %}"></input></td>
<td><input type="button" class="btn btn-danger" ng-click="deleteItem(i.item_type, i.id);" value="{% trans "Delete" %}"></input></td>
</tr>
</table>
</div>
<div class="col">
<div class="rotation-title-row">
<h2>{% trans "Rotation" %}: {$ selected_rot.name $}</h2>
<a class="btn btn-primary" href="/infoscreen/{$ selected_rot.id $}">{% trans "Preview" %}</a>
</div>
<div>{% trans "Instances in currently selected rotation" %}:</div>
<table class="table table-striped">
<tr>
<th>{% trans "Instance" %}</th>
<th>{% trans "Duration" %}</th>
<th>{% trans "Delete" %}</th>
</tr>
<tr ng-repeat="i in selected_rot.instances">
<td>{$ i.item.name $}</td><td>{$ i.duration $} s</td>
<td><input type="button" ng-click="deleteInstance(i.id);" value="{% trans "Delete" %}" class="btn btn-danger"></input></td>
</tr>
</table>
</div>
</div>
+37
View File
@@ -0,0 +1,37 @@
{% load i18n %}
<div id="slides" class="tab-pane fade show active" role="tabpanel">
<div ng-controller="infoadmin_ctrl">
<div class="col">
<h2>{% trans "Create new item" %}</h2>
<div>{% trans "Create a new item by type" %}</div>
<table class="table table-striped">
<tr>
<td>{% trans "Item type" %}</td>
<td>
<select class="form-control form-control-sm" ng-model="createtype", ng-options="t.name for t in infotypes | orderBy: 'name'">
<option value=""></option>
</select>
</td>
</tr>
</table>
<div ng-include="createtype.create_template_url"></div>
</div>
<div class="col">
<h2>{% trans "Info items" %}</h2>
<div>{% trans "Infoitems available for rotations" %}</div>
<table class="table table-striped">
<tr>
<th>{% trans "Item" %}</th>
<th>{% trans "Type" %}</th>
<th>{% trans "Delete" %}</th>
</tr>
<tr ng-repeat="i in infoitems | orderBy:['display_name','name']">
<td>{$ i.name $}</td>
<td>{$ i.display_name $}</td>
<td><input type="button" class="btn btn-danger" ng-click="deleteItem(i.item_type, i.id);" value="{% trans "Delete" %}"></input></td>
</tr>
</table>
</div>
</div>
</div>

Some files were not shown because too many files have changed in this diff Show More