diff --git a/.coveragerc b/.coveragerc index 0a5fbc3..4a08d6a 100644 --- a/.coveragerc +++ b/.coveragerc @@ -3,3 +3,5 @@ show_missing = True [run] omit = */migrations/* + */admin.py + */translation.py diff --git a/.env.dev b/.env.dev new file mode 100644 index 0000000..92c89ca --- /dev/null +++ b/.env.dev @@ -0,0 +1,10 @@ +HOST=api.dev.sahkoinsinoorikilta.fi +DEBUG=True +SECRET_KEY=7p$85^4ibb^p4-=vs44b7!y0e-zemugze18@a#30&71=a8)dp( +TG_BOT_TOKEN= +EMAIL_HOST= +EMAIL_PASSWD= +DB_USER=postgres +DB_PASSWD=postgres +DB_HOST=db +DB_PORT=5432 \ No newline at end of file diff --git a/.env.sample b/.env.sample new file mode 100644 index 0000000..65ab9dd --- /dev/null +++ b/.env.sample @@ -0,0 +1,10 @@ +HOST=localhost +DEBUG=True +SECRET_KEY=7p$85^4ibb^p4-=vs44b7!y0e-zemugze18@a#30&71=a8)dp( +TG_BOT_TOKEN= +EMAIL_HOST= +EMAIL_PASSWD= +DB_USER=postgres +DB_PASSWD=postgres +DB_HOST=db +DB_PORT=5432 \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json index c8aec53..a55ff8b 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -4,11 +4,10 @@ "jquery": true }, "globals": { - "angular": 1, - "noty": 1, - "app": 1, - "_": 1, - "moment": 1 + "angular": true, + "noty": true, + "_": true, + "moment": true }, "extends": "eslint:recommended", "rules": { diff --git a/.gitignore b/.gitignore index b264155..68bbb03 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ *.swp -sikweb/settings.py +.env *~ *.pyc *.sqlite3 @@ -10,7 +10,7 @@ members/logs/* logs/ /media/ node_modules/ -/.coverage +.coverage db.sqlite3 requirements_henu.txt /collected_static/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3eef15e..2a58095 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,102 +1,117 @@ stages: - - test + - setup - lint + - test - publish - deploy +install: + image: node:14 + stage: setup + script: + - npm ci + artifacts: + paths: + - node_modules + expire_in: 1 week + test: - image: python:3.5 + image: python:3.7 stage: test + needs: [] services: - - postgres:latest + - postgres:12 variables: POSTGRES_DB: ci POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres DATABASE_URL: "postgresql://postgres:postgres@postgres:5432/$POSTGRES_DB" + DB_HOST: postgres script: - python -V - pip install -r requirements.txt - - cp sikweb/settings-sample.py sikweb/default_settings.py - - cp sikweb/.ci-settings.py sikweb/settings.py - python manage.py migrate --noinput - python manage.py createdefaultadmin - python manage.py test -pycodestyle: - image: python:3.5 +lint:py: + image: python:3.7 stage: lint + needs: [] script: - pip install pycodestyle - - pycodestyle --config=setup.cfg --count . + - pycodestyle --config=pycodestyle.cfg --count . -eslint: - image: node:alpine +lint:js: + image: node:14 stage: lint - before_script: - - npm install + needs: ["install"] script: - - npm run eslint + - npm run lint:js -remark: - image: node:alpine +lint:md: + image: node:14 stage: lint - before_script: - - npm install + needs: ["install"] script: - - npm run remark + - npm run lint:md publish: stage: publish image: docker:stable + needs: ["test", "lint:py", "lint:js", "lint:md"] services: - docker:stable-dind only: - develop + - master script: - docker info - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY - docker build . -t "$IMAGE_NAME" - docker push "$IMAGE_NAME" -deploy_dev: +deploy:dev: stage: deploy - image: alpine:latest - environment: - name: dev - url: http://web.sik.party:8000 + image: docker:stable only: - develop - before_script: - - pwd - - apk add --update openssh - - ssh -V - - mkdir -p ~/.ssh - - echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa - - chmod 600 ~/.ssh/id_rsa - - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config' - 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: - stage: deploy - image: alpine:latest environment: - name: production - url: https://sika.sahkoinsinoorikilta.fi - when: manual + name: dev + url: http://api.dev.sahkoinsinoorikilta.fi + variables: + DOCKER_HOST: $DEV_CI_DOCKER_HOST + DOCKER_TLS_VERIFY: 1 + before_script: + - mkdir -p ~/.docker + - echo "$DEV_TLSCACERT" > ~/.docker/ca.pem + - echo "$DEV_TLSCERT" > ~/.docker/cert.pem + - echo "$DEV_TLSKEY" > ~/.docker/key.pem + - docker login -u gitlab-ci-token -p "$CI_BUILD_TOKEN" "$CI_REGISTRY" + script: + - docker stack deploy --with-registry-auth -c stack-compose-dev.yml "$SERVICE_NAME" + after_script: + - docker logout "$CI_REGISTRY" + +deploy:production: + stage: deploy + image: docker:stable only: - master + environment: + name: production + url: api.sahkoinsinoorikilta.fi + when: manual + variables: + DOCKER_HOST: $CI_DOCKER_HOST + DOCKER_TLS_VERIFY: 1 before_script: - - pwd - - apk add --update openssh - - ssh -V - - mkdir -p ~/.ssh - - echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa - - chmod 600 ~/.ssh/id_rsa - - echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config + - mkdir -p ~/.docker + - echo "$TLSCACERT" > ~/.docker/ca.pem + - echo "$TLSCERT" > ~/.docker/cert.pem + - echo "$TLSKEY" > ~/.docker/key.pem + - docker login -u gitlab-ci-token -p "$CI_BUILD_TOKEN" "$CI_REGISTRY" script: - - ssh $PROD_SSH_USER@$PROD_SSH_HOST "zsh ~/deploy.sh" + - docker stack deploy --with-registry-auth -c stack-compose.yml "$SERVICE_NAME" + after_script: + - docker logout "$CI_REGISTRY" \ No newline at end of file diff --git a/.husky/.gitignore b/.husky/.gitignore new file mode 100644 index 0000000..31354ec --- /dev/null +++ b/.husky/.gitignore @@ -0,0 +1 @@ +_ diff --git a/scripts/git/pre-push b/.husky/pre-push similarity index 69% rename from scripts/git/pre-push rename to .husky/pre-push index 32e81dc..07e64c7 100755 --- a/scripts/git/pre-push +++ b/.husky/pre-push @@ -1,9 +1,10 @@ -#!/bin/bash +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" PURPLE='\033[0;35m' NC='\033[0m' # No Color -. "${VIRTUAL_ENV}/bin/activate" +source "${VIRTUAL_ENV}/bin/activate" if [ $? -ne 0 ] then @@ -14,10 +15,8 @@ fi set -e printf "${PURPLE}Running pre-push tests.${NC}\n" -printf "${PURPLE}npm tests...${NC}\n" -npm test -printf "${PURPLE}pycodestyle tests...${NC}\n" -pycodestyle . +printf "${PURPLE}linters...${NC}\n" +npm run lint printf "${PURPLE}unit tests...${NC}\n" python -Wall manage.py test --noinput set +e diff --git a/.python-version b/.python-version index 424e179..0833a98 100644 --- a/.python-version +++ b/.python-version @@ -1 +1 @@ -3.6.8 +3.7.4 diff --git a/Dockerfile b/Dockerfile index 7533761..a82b6ad 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,20 @@ -FROM python:3.5 +FROM python:3.7-alpine ENV PYTHONUNBUFFERED 1 -ENV IS_DOCKER 1 -RUN mkdir /code -WORKDIR /code -ADD requirements.txt /code/ -RUN env -ADD . /code/ +WORKDIR /app +COPY requirements.txt ./ +COPY requirements.production.txt ./ +COPY . ./ + +# uWSGI, gunicorn etc. +RUN apk add --no-cache python3-dev build-base linux-headers pcre-dev openssl bash \ + # PSQL + && apk add --no-cache postgresql-dev \ + # Pillow + && apk add --no-cache jpeg-dev zlib-dev \ + && pip install --upgrade pip \ + && pip install -r requirements.txt \ + && pip install -r requirements.production.txt + +RUN python manage.py collectstatic --noinput + +CMD ["sh", "-c", "./production_entrypoint.sh"] diff --git a/Pipfile b/Pipfile deleted file mode 100644 index 7d61345..0000000 --- a/Pipfile +++ /dev/null @@ -1,52 +0,0 @@ -[[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" diff --git a/Pipfile.lock b/Pipfile.lock deleted file mode 100644 index 26ffd23..0000000 --- a/Pipfile.lock +++ /dev/null @@ -1,706 +0,0 @@ -{ - "_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" - } - } -} diff --git a/coffee_scale/__init__.py b/coffee_scale/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/coffee_scale/admin.py b/coffee_scale/admin.py deleted file mode 100644 index 8c38f3f..0000000 --- a/coffee_scale/admin.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.contrib import admin - -# Register your models here. diff --git a/coffee_scale/migrations/__init__.py b/coffee_scale/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/coffee_scale/models.py b/coffee_scale/models.py deleted file mode 100644 index 71a8362..0000000 --- a/coffee_scale/models.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.db import models - -# Create your models here. diff --git a/coffee_scale/static/coffee_scale/css/coffee.css b/coffee_scale/static/coffee_scale/css/coffee.css deleted file mode 100644 index e090c2a..0000000 --- a/coffee_scale/static/coffee_scale/css/coffee.css +++ /dev/null @@ -1,124 +0,0 @@ -body { - background-color: white; - font-family: monospace; - color: black; -} -#container{ - position:relative; - width:95%; - margin-left:auto; - margin-right:auto; - height:100%; - overflow:hidden; - -} -#upper{ - background-size: contain; - background-repeat: no-repeat; - background-position: bottom center; - background-image: url("/static/coffee_scale/img/smokes.png"); - transform-origin: bottom; - animation: smokes 8s ease-in-out 0s infinite; - opacity:0; - height:40%; -} -#lower{ - position:relative; - background-size: contain; - background-repeat: no-repeat; - background-position: top center; - background-image: url("/static/coffee_scale/img/coffeecup3.png"); - height:60%; -} -#scale{ - position:absolute; - top:80%; - width:90%; - height:10%; - margin: 0% 5% 0% 5%; - background: lightgrey; - border-radius: 10px; - overflow:hidden; -} -#scale2{ - width: 0%; - transition: width 2s; - height:100%; - background: green; - border-radius: 10px; -} -.brewtime{ - text-align:right; - position:absolute; - right:0px; - z-index:5; - font-size:10vw; -} -#address{ - text-align:left; - position:absolute; - left:0px; - z-index:5; - font-size:4vw; - color: #333; -} -.layertwo{ - display: None; -} -noscript{ - color:red; -} -.text{ - color:green; - position:absolute; - top:50%; - left:50%; -} -.brewing{ - animation: brewing 5s ease-in-out 0s infinite; -} -.hurry{ - color:red !important; -} -.unknown{ - color:orange !important; - animation: unknown 5s ease-in-out 0s infinite; -} -.friday{ - animation: friday 20s ease-in-out 0s infinite; -} -.normal{ - animation: normal 1000s ease-in-out 0s infinite; -} -.coffeeready{ - animation: coffeeready 10s ease-in-out 0s; -} -@keyframes smokes { - 0% {transform: skewX(-10deg);} - 50% {transform: skewX(10deg);} - 100% {transform: skewX(-10deg);} -} -@keyframes brewing { - 0% {color:green;} - 50% {color: transparent;} - 100% {color:green;} -} -@keyframes coffeeready { - 0% {background-color:white;} - 25% {background-color:rgb(100, 255, 100);} - 50% {background-color:white;} - 75% {background-color:rgb(100, 255, 100);} - 100% {background-color:white;} -} -@keyframes unknown { - 0%,40% {transform: rotate(0deg);} - 60%,100% {transform: rotate(360deg);} -} -@keyframes friday { - 0% {transform: rotate(0deg);} - 100% {transform: rotate(360deg);} -} -@keyframes normal { - 0%,49% {transform: rotate(0deg);} - 50%,100% {transform: rotate(360deg);} -} diff --git a/coffee_scale/static/coffee_scale/img/coffeecup3.png b/coffee_scale/static/coffee_scale/img/coffeecup3.png deleted file mode 100644 index 5170d5f..0000000 Binary files a/coffee_scale/static/coffee_scale/img/coffeecup3.png and /dev/null differ diff --git a/coffee_scale/static/coffee_scale/img/smokes.png b/coffee_scale/static/coffee_scale/img/smokes.png deleted file mode 100644 index cb19720..0000000 Binary files a/coffee_scale/static/coffee_scale/img/smokes.png and /dev/null differ diff --git a/coffee_scale/static/coffee_scale/js/coffee.js b/coffee_scale/static/coffee_scale/js/coffee.js deleted file mode 100644 index 025387d..0000000 --- a/coffee_scale/static/coffee_scale/js/coffee.js +++ /dev/null @@ -1,183 +0,0 @@ -//Inner state -var lastBrew = new Date(0); -var brewing = false; -var backoff = 2000; - -//MQTT client config -var username = "coffee-user-"+ Math.random(); -// eslint-disable-next-line no-undef -var client = new Paho.MQTT.Client("sika.sahkoinsinoorikilta.fi", 9001, username); -client.onMessageArrived = function (message) { - // eslint-disable-next-line no-console - console.log("Topic: "+message.destinationName+" msg: "+message.payloadString); - var ev = new CustomEvent(message.destinationName, {'detail': message.payloadString}); - window.dispatchEvent(ev); -} - -function reconnect(responseObject){ - if (responseObject.errorCode !== 0) { - console.log("connection lost! Reason: "+responseObject.errorMessage); // eslint-disable-line no-console - setTimeout(function(){ - client.connect({onSuccess:onConnect, useSSL:true, onFailure: reconnect}); - }, backoff); - } -} - -function onConnect() { - console.log("MQTT connected"); // eslint-disable-line no-console - //set and reset reconnector - client.onConnectionLost = reconnect - // subscribe to topics - client.subscribe("sik/kiltahuone/kahvivaaka/cups"); - client.subscribe("sik/kiltahuone/kahvivaaka/brewing"); - client.subscribe("sik/kiltahuone/kahvivaaka/brewtime"); - } - -// data update and parse functions -function parseCups(ev){ - var cups = parseFloat(ev.detail).toFixed(1) - - function makeEvent(cups) { - return (String(cups) !== '-1.0') - ? new CustomEvent("cupsChanged", {'detail': cups}) - : new CustomEvent("cupsError", {'detail': 'Error: unable to fetch cups :('}); - } - - window.dispatchEvent(makeEvent(cups)); -} -function updateCups(ev){ - $("#text").text(ev.detail); -} -function showCupsError(ev) { - $('#text').text(ev.detail); - $('#text').css({ - 'font-size': '7vh', - 'left': '0', - 'top': '40%', - 'width': '100%', - 'text-align': 'center', - 'color': 'red', - }); - $('#lower').css({'background-image': 'none'}); -} -function updateScale(ev){ - $("#scale2").css({width: Math.min(ev.detail/9*100,100) + '%'}); -} - -function tick(){ - var ev = new CustomEvent("tick", {'detail': new Date()}); - window.dispatchEvent(ev); -} - -function updateTime(ev){ - var now = ev.detail; - $("#time").html(formatTime(now.getHours(),now.getMinutes(),now.getSeconds())); -} - -function coffeeLowEffect(ev){ - ev.detail <= 2 ? $("#text").addClass("hurry") : $("#text").removeClass("hurry"); -} -function coffeeReadyEffect(){ - $("body").addClass("coffeeready"); - // autoclear animation class in 10s - setTimeout(function(){$("body").removeClass("coffeeready");}, 10000); -} -function hotEffect(ev){ - var opa = Math.max(100 - ev.detail / 90000,0); - $("#upper").css({opacity: opa/100}); -} -function brewAnimStart(){ - $(".text").addClass("brewing"); - $(".layerone").hide(); - $(".layertwo").show(); -} -function brewAnimEnd(){ - $(".text").removeClass("brewing"); - $(".layertwo").hide(); - $(".layerone").show(); -} -function brewNotifier(ev){ - var new_brewing = parseInt(ev.detail); - if (new_brewing == 1 && brewing == 0){ - window.dispatchEvent(new Event("brewStart")); - } else if (new_brewing == 0 && brewing == 1){ - window.dispatchEvent(new Event("brewEnd")); - } - brewing = new_brewing; -} -function brewTimeParser(ev){ - lastBrew = new Date(parseInt(ev.detail)*1000.0); -} -function updateBrewDiff(){ - var now = new Date(); - var timeDiff = Math.max(now.getTime() - lastBrew.getTime(), 0); - var eve = new CustomEvent("dtUpdate", {'detail': timeDiff}); - window.dispatchEvent(eve); -} -function updateBrewTime(ev){ - var timeDiff = ev.detail; - var timeStr; - if (timeDiff < 3600000){ - timeStr = Math.round(timeDiff / 60000) + ' min' - } else if (timeDiff < 10000* 3600 * 1000){ // 1000h - timeStr = '~' + Math.round(timeDiff / 3600000 * 2) / 2 + ' h'; - } else { - timeStr = "???" - } - $("#brewtime").html(timeStr); -} - -// Helpers - -function nToS(num){ - return num < 10 ? "0" + num : "" + num; -} - -function formatTime(hours, minutes, seconds){ - return nToS(hours)+":"+nToS(minutes)+":"+nToS(seconds) -} - -function resize(){ - var w = $("#container").width(); - var h = $("#container").height(); - var s = w > h ? h : w; - var font = s * 0.8 * 0.38/Math.sqrt(3); - $(".text").css({ top: s*0.16-font/2 + 'px', - fontSize: font + 'px', - marginLeft: -font*3*3/10 + 'px'}); -} - -// Init everything - -$(document).ready(function(){ - client.connect({onSuccess:onConnect, useSSL:true, onFailure:reconnect}); - - //connect MQTT event listeners - window.addEventListener("sik/kiltahuone/kahvivaaka/cups", parseCups); - window.addEventListener("sik/kiltahuone/kahvivaaka/brewing", brewNotifier); - window.addEventListener("sik/kiltahuone/kahvivaaka/brewtime", brewTimeParser); - - //connect other event listeners - window.addEventListener("cupsChanged", updateCups); - window.addEventListener("cupsChanged", coffeeLowEffect); - window.addEventListener("cupsChanged", updateScale); - window.addEventListener("cupsChanged", resize); - - window.addEventListener("cupsError", showCupsError); - window.addEventListener("cupsError", coffeeLowEffect); - window.addEventListener("cupsError", updateScale); - - window.addEventListener("brewStart", brewAnimStart); - window.addEventListener("brewEnd", brewAnimEnd); - window.addEventListener("brewEnd", coffeeReadyEffect); - window.addEventListener("tick", updateTime); - window.addEventListener("tick", updateBrewDiff); - window.addEventListener("dtUpdate", updateBrewTime); - window.addEventListener("dtUpdate", hotEffect); - - //start time based events - setInterval(tick, 100); - tick(); - -}); -$(window).resize(resize); diff --git a/coffee_scale/templates/coffee.html b/coffee_scale/templates/coffee.html deleted file mode 100644 index b4800c6..0000000 --- a/coffee_scale/templates/coffee.html +++ /dev/null @@ -1,41 +0,0 @@ -{% load i18n %} -{% load static %} - - -
-- {% blocktrans %}Muista, että kaehmyn lähettäminen on kiinnostuksen ilmaus + {% blocktrans %}(HUOM! Kaehmytekstin maksimipituus on 300 merkkiä. Tarvittaessa voit kirjoittaa lisätietoja kommenteihin.){% endblocktrans %} +
++ {% blocktrans %}Muista, että kaehmyn lähettäminen on kiinnostuksen ilmaus eikä siis missään nimessä sitova ilmoittautumien mihinkään tehtävään!{% endblocktrans %}