From 69467f1eeb8df6bedd69ca19d621293215f0adc0 Mon Sep 17 00:00:00 2001 From: Nathan Workman Date: Tue, 21 Jan 2020 22:17:32 -0500 Subject: [PATCH 1/2] Upgrade dependencies, fix docker setup, cleanup frontend. --- .editorconfig | 29 ++ .gitignore | 32 +- .travis.yml | 12 - Dockerfile | 18 + Makefile | 205 ++++++--- README.md | 90 +--- seeker/crawl.py => crawl.py | 0 docker-compose.yml | 61 ++- docker/web/Dockerfile | 15 - docker/web/web-entrypoint.sh | 6 - requirements.in | 87 ++-- requirements.txt | 110 ++--- scraper/spiders/greenhouse.py | 3 +- scraper/spiders/lever.py | 9 +- scraper/spiders/recruiterbox.py | 5 +- scraper/spiders/weworkremotely.py | 200 +++++++++ scraper/spiders/workable.py | 5 +- seeker/job/admin.py | 4 +- seeker/job/apps.py | 12 +- seeker/job/migrations/0003_company_logo.py | 18 + seeker/job/models.py | 15 +- seeker/job/serializers.py | 17 + seeker/job/templates/job_detail.html | 46 ++ seeker/job/templates/job_list.html | 85 ++++ seeker/job/templates/job_search_results.html | 26 ++ seeker/job/views.py | 61 +++ seeker/jobs.py | 43 ++ seeker/settings.py | 47 +- seeker/static/js/vendor/Chart.bundle.min.js | 10 - seeker/static/js/vendor/jquery-3.3.1.min.js | 2 - seeker/static/scss/flexboxgrid.scss | 1 - seeker/static/scss/styles.scss | 7 - .../vendor/bootstrap/bootstrap.bundle.min.js | 7 + .../static/vendor/bootstrap/bootstrap.min.css | 7 + .../static/vendor/chartjs/Chart.bundle.min.js | 7 + seeker/static/vendor/chartjs/Chart.min.css | 1 + .../vendor/datatables/datatables.min.css | 24 ++ .../vendor/datatables/datatables.min.js | 401 ++++++++++++++++++ seeker/static/vendor/jquery-3.4.1.min.js | 2 + seeker/templates/admin/base_site.html | 20 +- seeker/templates/admin/index.html | 84 ---- seeker/templates/admin/login.html | 6 - seeker/templates/base.html | 48 +++ seeker/templates/includes/navigation.html | 30 ++ seeker/templates/includes/pagination.html | 37 ++ seeker/urls.py | 18 +- tox.ini | 45 +- 47 files changed, 1528 insertions(+), 490 deletions(-) create mode 100644 .editorconfig delete mode 100644 .travis.yml create mode 100644 Dockerfile rename seeker/crawl.py => crawl.py (100%) delete mode 100644 docker/web/Dockerfile delete mode 100755 docker/web/web-entrypoint.sh create mode 100644 scraper/spiders/weworkremotely.py create mode 100644 seeker/job/migrations/0003_company_logo.py create mode 100644 seeker/job/serializers.py create mode 100644 seeker/job/templates/job_detail.html create mode 100644 seeker/job/templates/job_list.html create mode 100644 seeker/job/templates/job_search_results.html create mode 100644 seeker/jobs.py delete mode 100644 seeker/static/js/vendor/Chart.bundle.min.js delete mode 100644 seeker/static/js/vendor/jquery-3.3.1.min.js delete mode 100644 seeker/static/scss/flexboxgrid.scss create mode 100644 seeker/static/vendor/bootstrap/bootstrap.bundle.min.js create mode 100644 seeker/static/vendor/bootstrap/bootstrap.min.css create mode 100644 seeker/static/vendor/chartjs/Chart.bundle.min.js create mode 100644 seeker/static/vendor/chartjs/Chart.min.css create mode 100644 seeker/static/vendor/datatables/datatables.min.css create mode 100644 seeker/static/vendor/datatables/datatables.min.js create mode 100644 seeker/static/vendor/jquery-3.4.1.min.js delete mode 100644 seeker/templates/admin/index.html delete mode 100644 seeker/templates/admin/login.html create mode 100644 seeker/templates/base.html create mode 100644 seeker/templates/includes/navigation.html create mode 100644 seeker/templates/includes/pagination.html diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..7147d61 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,29 @@ +# EditorConfig helps developers define and maintain consistent +# coding styles between different editors and IDEs +# https://editorconfig.org +root = true + +[*] +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.{md,rst,txt}] +indent_style = space +indent_size = 4 + +[*.{ini,toml}] +indent_style = space +indent_size = 4 + +[*.{js,json,yml,yaml}] +indent_style = space +indent_size = 2 + +[*.{css,py,scss,html}] +indent_size = 4 +indent_style = space + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitignore b/.gitignore index dae04e3..8a7b501 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ # general things to ignore build/ -dist/ +# dist/ *.egg-info/ *.egg *.py[cod] @@ -23,9 +23,11 @@ __pycache__ /node_modules # project dist static files -/static/ -/media/ +/static +media +/finder/static/assets +.vscode # project secrets .env @@ -33,5 +35,25 @@ __pycache__ *.log *.retry -# local db backups -backups/ +# background process stuff +nohup.out + +# Ignore data dumps +fixtures/ +initial_data.dump + +# ignore scraper things +# Google Scraper specific +Drivers/chromedriver +Drivers/geckodriver +Private/ +keywords.txt +out.csv +# cache for GoogleScraper testings +.scrapecache/ +*.db +/results +*.log + + +# diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 83b7714..0000000 --- a/.travis.yml +++ /dev/null @@ -1,12 +0,0 @@ -language: python - -python: - - "3.7" - -install: - - pip install setuptools --upgrade - - pip install tox-travis - - pip install -r requirements.txt - -script: - # - tox diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..fa2319d --- /dev/null +++ b/Dockerfile @@ -0,0 +1,18 @@ +#!/bin/bash +FROM python:3.6.10-buster +LABEL Nathan Workman + +ENV PYTHONDONTWRITEBYTECODE 1 +ENV PYTHONUNBUFFERED 1 + +RUN apt-get update && apt-get -y upgrade && apt-get install -y sudo +RUN apt-get install -y git apt-utils build-essential + +RUN mkdir -p /usr/src/app +WORKDIR /usr/src/app +COPY . . + +RUN pip install --upgrade pip +RUN pip install --no-cache-dir -r requirements.txt + +EXPOSE 8000 diff --git a/Makefile b/Makefile index e5f04c4..605168e 100644 --- a/Makefile +++ b/Makefile @@ -2,99 +2,102 @@ PROJECT_NAME = seeker SHELL := /bin/sh help: @echo "Please use 'make ' where is one of" - @echo " reset Complete reset of database and migrations (Be Careful)" - @echo " migrate Run Django migrations" - @echo " migrations Create Django migrations" - @echo " user Create user account" - @echo " clean Remove all *.pyc, .DS_Store and temp files from the project" - @echo " collectstatic Collect static assets" - @echo " run Run Django Server" - @echo " crawl_spider Run Scrapy Spider" - @echo " crawl Run ALL Scrapy Spiders" - @echo " dump Create database dump/backup" + @echo "migrate Run database migrations" + @echo "collectstatic Collect static assets" + .PHONY: requirements # Command variables +COMPOSE = docker-compose +COMPOSE_CMD = exec app python manage.py MANAGE_CMD = python manage.py -PIP_INSTALL_CMD = pip install -PLAYBOOK = ansible-playbook -VIRTUALENV_NAME = venv -APP_NAME = seeker + # Helper functions to display messagse ECHO_BLUE = @echo "\033[33;34m $1\033[0m" ECHO_RED = @echo "\033[33;31m $1\033[0m" ECHO_GREEN = @echo "\033[33;32m $1\033[0m" -DATE= `date +'%m_%d_%y'` + # The default server host local development HOST ?= localhost:8000 -reset: dropdb createdb migrations migrate user run - migrate: -# Run django migrations +# Run django migrations inside docker $(call ECHO_GREEN, Running migrations... ) ( \ - $(MANAGE_CMD) migrate; \ + $(COMPOSE) $(COMPOSE_CMD) migrate --no-input; \ ) -user: -# Create user account - $(call ECHO_GREEN, Creating super user... ) +collectstatic: +# Run django migrations inside docker + $(call ECHO_GREEN, Collect static assets... ) ( \ - echo "from django.contrib.auth.models import User; User.objects.create_superuser('admin', 'admin@email.com', 'pass')" | ./manage.py shell; \ + $(COMPOSE) $(COMPOSE_CMD) collectstatic --no-input; \ ) -test: -# Run the test cases +migrations: +# Run django migrations inside docker + $(call ECHO_GREEN, Create new database migrations... ) ( \ - $(MANAGE_CMD) test; \ + $(COMPOSE) $(COMPOSE_CMD) makemigrations; \ ) -clean: -# Remove all *.pyc, .DS_Store and temp files from the project - $(call ECHO_BLUE,removing .pyc files...) - @find . -name '*.pyc' -exec rm -f {} \; - $(call ECHO_BLUE,removing static files...) - @rm -rf $(PROJECT_NAME)/_static/ - $(call ECHO_BLUE,removing temp files...) - @rm -rf $(PROJECT_NAME)/_tmp/ - $(call ECHO_BLUE,removing .DS_Store files...) - @find . -name '.DS_Store' -exec rm {} \; - -shell: -# Run a local shell for debugging +build: +# Run django migrations inside docker + $(call ECHO_GREEN, Building new images... ) ( \ - $(MANAGE_CMD) shell_plus; \ + $(COMPOSE) build; \ ) -migrations: -# Create database migrations +down: +# Run django migrations inside docker + $(call ECHO_GREEN, Tear down containers... ) ( \ - $(MANAGE_CMD) makemigrations; \ + $(COMPOSE) down; \ ) -collectstatic: -# Collect static assets - $(call ECHO_GREEN, Collecting static assets...) +up: +# Run django migrations inside docker + $(call ECHO_GREEN, Launching starship... ) ( \ - $(MANAGE_CMD) collectstatic; \ + $(COMPOSE) up; \ + ) + +visual: +# Generate visual representation of database + $(call ECHO_GREEN, Generating a pretty image...) + (\ + $(COMPOSE) $(COMPOSE_CMD) graph_models --pygraphviz -a -g -o visualized.png; \ + ) + +dumpdata: +# Dump database to fixture file + $(call ECHO_RED, Database dump...) + (\ + $(COMPOSE) $(COMPOSE_CMD) dumpdata --exclude auth.permission --exclude contenttypes > ./initial_data.json; \ ) -run: -# run django server - $(call ECHO_GREEN, Starting Django Server...) +shell: +# Run a local shell for debugging + $(call ECHO_GREEN, Opening iPython shell...) ( \ - $(MANAGE_CMD) runserver 0.0.0.0:8300 ; \ + $(COMPOSE) $(COMPOSE_CMD) shell; \ ) -crawl: + + +###################### +# OLD +###################### + +r_crawl: # Run ALL scrapy spiders - $(call ECHO_GREEN, Running spiders... ) + $(call ECHO_GREEN, Running Spiders Background Process... ) (\ - python seeker/crawl.py; \ + cd recognition; \ + nohup python crawl.py & \ ) crawl_spider: @@ -104,17 +107,99 @@ crawl_spider: scrapy crawl $(spider); \ ) -createdb: +r_crawl_spider: +# Run scrapy spider + $(call ECHO_GREEN, Running $(spider) spider as background process... ) + (\ + nohup scrapy crawl $(spider) & \ + ) + +delete_sqlite: +# delete project db ( \ - createdb -p 5433 $(APP_NAME); \ + rm -rf db.sqlite3;\ ) -dropdb: +reset_migrations: +# delete all migrations furing initial development ( \ - dropdb -p 5433 $(APP_NAME);\ + find . -path "*/migrations/*.py" -not -name "__init__.py" -delete; \ + find . -path "*/migrations/*.pyc" -delete; \ ) -dump: +map_points: ( \ - pg_dump -Fc seeker -p 5433 > backups/data_dump_$(DATE).dump; \ + python manage.py plot_lng_lat;\ ) + +r_map_points: + ( \= + nohup python manage.py plot_lng_lat & \ + ) + +validate_urls: + ( \ + python manage.py valid_url;\ + ) + +r_validate_urls: + ( \ + nohup python manage.py valid_url & \ + ) + +find_contacts: + ( \ + nohup python manage.py find_contacts & \ + ) + +map_locations: + ( \ + nohup python manage.py plot_lng_lat & \ + ) + +rank: + # Start ranking centers + (\ + python manage.py rank; \ + ) + +r_rank: + # Start ranking centers + (\ + nohup python manage.py rank & \ + ) + +sql_dump: + # dump to fixtures file + (\ + rm -rf recognition/fixtures/dump.json; \ + ./manage.py dumpdata --natural-primary --natural-foreign > fixtures/dump.json ; \ + ) + + +initial_data: +# load initial db data + ( \ + pg_restore -p 5433 -d recognition --verbose initial_data.dump; \ + ) + +r_initial_data: +# load initial db data in vm + ( \ + sudo -u postgres pg_restore -p 5433 -d recognition --verbose initial_data.dump; \ + ) + + +createuser: + + # docker exec -it seeker_app echo "from django.contrib.auth.models import User; User.objects.create_superuser('admin', 'admin@email.com', 'pass')" | ./manage.py shell; + ( \ + docker exec -it seeker_app python manage.py createsuperuser + ) + + + +# docker exec -it seeker_app python manage.py createsuperuser + + +# echo "from django.contrib.auth.models import User; User.objects.create_superuser('admin', 'admin@email.com', 'pass')" | ./manage.py shell; diff --git a/README.md b/README.md index 6da6a9d..5385323 100644 --- a/README.md +++ b/README.md @@ -3,16 +3,15 @@

Seeker

-[![Build Status](https://travis-ci.org/NathanWorkman/seeker.svg?branch=master)](https://travis-ci.org/NathanWorkman/seeker) +# Seeker -## What is Seeker? Seeker is just another job board aggregator. Check multiple job boards for positions you might be interested in and organize them all in one convenient location. ## Setup ### Docker -Docker installation should be fairly straight forward. +The easiest way to get started is to clone this repo and run docker-compose: ``` git clone git@github.com:NathanWorkman/seeker.git @@ -21,91 +20,18 @@ docker-compose build docker-compose up ``` -### The hard(er) way: - -You will need `yarn` and `virtualenv` installed on your machine. - -Install Yarn -``` -brew install yarn -``` - -Install virtualenv -``` -pip install virtualenv -``` - -### To run the project -``` -git clone git@github.com:NathanWorkman/seeker.git -cd seeker/ -virtualenv venv -p python3 -source venv/bin/activate -pip install -r requirements.txt -yarn -cd seeker/ -python manage.py migrate -python manage.py createsuperuser -make build -make run -``` - ### To run the spiders -From the root directory of the `seeker` project `cd` to the seeker app directory. -``` -cd seeker -``` -and then run the following to run the individual spiders, replacing `spidername` with the spider you wish to run. +Execute the individual spiders from inside the docker container -``` -scrapy crawl spidername +```shell +docker exec -it seeker_app scrapy crawl spidername ``` or run all the spiders at once: +```shell +docker exec -it seeker_app python crawl.py ``` -python crawl.py -``` - -Navigate to the django admin to view your results. - -## TODO - -### Boards -- [x] DjangoGigs -- [ ] Indeed -- [ ] PythonOrg -- [ ] RemotePython -- [ ] Stack Overflow -- [ ] Workable -- [ ] Lever -- [ ] Recruiter Box -- [ ] Greenhouse -- [ ] TBD -- [ ] https://hireremote.io -- [ ] https://weworkremotely.com -- [ ] https://remoteok.io/ -- [ ] https://jobspresso.co/ -- [ ] https://remotive.io/find-a-remote-job/#s=1 -- [ ] https://www.workingnomads.co/jobs -- [ ] https://www.mikesremotelist.com/ -- [ ] https://stackoverflow.com/jobs -- [ ] https://bestremotejob.com/ -- [ ] https://justremote.co/ -- [ ] https://whoishiring.io/ -- [ ] https://www.techjobsforgood.com/?search=remote -- [ ] https://rmtwrk.com/ -- [ ] https://remotepath.io/ -- [ ] https://www.hiringremote.ly/ -- [ ] https://www.honestlance.com/ - - -## Made Possible By -- [Django](https://www.djangoproject.com/) -- [Scrapy](https://scrapy.org/) -- [jQuery](https://jquery.com/) -- Icons - [Devicon](http://konpa.github.io/devicon/) -- Admin Theme - [Django Suit](https://github.com/darklow/django-suit) -- NLP - [SpaCy](https://spacy.io/) +Navigate to `0.0.0.0:8000` to view results. diff --git a/seeker/crawl.py b/crawl.py similarity index 100% rename from seeker/crawl.py rename to crawl.py diff --git a/docker-compose.yml b/docker-compose.yml index ff75b20..6ffccf7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,18 +1,45 @@ -version: '3' - +version: '3.3' +networks: + seeker: +volumes: + postgresql-data: services: - db: - image: postgres - web: - build: - context: . - dockerfile: ./docker/web/Dockerfile - entrypoint: ./docker/web/web-entrypoint.sh - volumes: - - .:/code:cached - ports: - - "8000:8000" - - "3000:3000" - - "3001:3001" - depends_on: - - db + postgres: + container_name: seeker_postgres + hostname: postgres + image: postgres:11.6 + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + - POSTGRES_DB=postgres + networks: + - seeker + expose: + - "5435" + ports: + - "5435:5435" + command: -p 5435 + # restart: on-failure + volumes: + - postgresql-data:/var/lib/postgresql/data + app: + build: + context: . + dockerfile: ./Dockerfile + container_name: seeker_app + command: sh -c "python manage.py collectstatic --no-input && python manage.py migrate && python manage.py runserver 0.0.0.0:8001" + # environment: + # - DJANGO_SETTINGS_MODULE=seeker.settings.local + image: seeker_image + hostname: app + depends_on: + - postgres + expose: + - "8001" + ports: + - "8001:8001" + volumes: + - .:/usr/src/app + networks: + - seeker + # restart: on-failure diff --git a/docker/web/Dockerfile b/docker/web/Dockerfile deleted file mode 100644 index 434fc52..0000000 --- a/docker/web/Dockerfile +++ /dev/null @@ -1,15 +0,0 @@ -FROM python:3.6 -MAINTAINER Nathan Workman - -ENV PYTHONUNBUFFERED 1 - -RUN mkdir /code -WORKDIR /code - -RUN apt-get update && apt-get -y upgrade && apt-get install -y sudo -ADD requirements.in /code/ - -RUN pip install pip==9.0.3 -RUN pip install -r requirements.in - -ADD . /code/ diff --git a/docker/web/web-entrypoint.sh b/docker/web/web-entrypoint.sh deleted file mode 100755 index 519ca8b..0000000 --- a/docker/web/web-entrypoint.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -cd seeker -python manage.py migrate -python manage.py collectstatic --no-input -python manage.py runserver diff --git a/requirements.in b/requirements.in index 137fcee..82a8779 100644 --- a/requirements.in +++ b/requirements.in @@ -1,57 +1,44 @@ - # Django framework -Django==2.1.7 - +Django==2.2.9 +# API +djangorestframework==3.11.0 +# Admin +django-grappelli==2.13.3 # Testing / Debug -django-debug-toolbar==1.11 -flake8==3.7.7 -tox==3.7.0 - -# Scrapy Framework -Scrapy==1.6.0 +django-debug-toolbar==2.1 +flake8==3.7.9 +tox==3.14.3 +pytest==5.3.2 +# Database +psycopg2-binary==2.8.4 +# Scheduler +APScheduler==3.6.3 +django-apscheduler==0.3.0 +# Scrapy +Scrapy==1.8.0 scrapy-djangoitem==1.1.1 - +scrapyd==1.2.1 +# Filter queryset from url params +django-filter==2.2.0 # Pip Tools -pip-tools==3.5.0 -pur==5.2.1 - -# Env -django-dotenv==1.4.2 - -# Mailer Utiliity -django-anymail==6.0 - -# Send and Recieve through SMTP -django-mailbox==4.7.1 - +pip-tools==4.3.0 +pur==5.3.0 # Sane HTTP -requests==2.21.0 - +requests==2.22.0 # Static Assets -django-compressor==2.2 -django-libsass==0.7 - -# Database -psycopg2==2.7.7 -psycopg2-binary==2.7.7 - -# PDF Generation -WeasyPrint==46 - -# Lazy Cron -django-cron==0.5.1 - -# Better filtering -django-filter==2.1.0 - -# Django-Suit Admin Theme --e git+https://github.com/darklow/django-suit.git@v2#egg=django_suit - -# NLP Library to get some insights -spacy==2.1.3 - +django-compressor==2.4 +django-libsass==0.8 # import export -django-import-export==1.2.0 - -# Admin WYSIWYG editor -django-summernote==0.8.11.4 +django-import-export==2.0 +# Gunicorn +gunicorn==20.0.4 +whitenoise==5.0.1 +# local flavor +django-localflavor==2.2 +# Python Excel +openpyxl==3.0.3 +xlsxwriter==1.2.7 +# NLP Library to get some insights +spacy==2.2.3 +# PIL +pillow==7.0.0 diff --git a/requirements.txt b/requirements.txt index b2b0df8..d5840ce 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,65 +4,63 @@ # # pip-compile requirements.in # --e git+https://github.com/darklow/django-suit.git@v2#egg=django_suit +apscheduler==3.6.3 asn1crypto==0.24.0 # via cryptography -attrs==18.1.0 # via automat, service-identity, twisted +attrs==18.1.0 # via automat, pytest, service-identity, twisted automat==0.7.0 # via twisted backports.csv==1.0.6 # via tablib -blis==0.2.4 # via spacy, thinc -cairocffi==0.9.0 # via cairosvg, weasyprint -cairosvg==2.2.1 # via weasyprint +blis==0.4.1 # via spacy, thinc +catalogue==1.0.0 # via spacy certifi==2018.8.24 # via requests -cffi==1.11.5 # via cairocffi, cryptography, weasyprint +cffi==1.11.5 # via cryptography chardet==3.0.4 # via requests click==6.7 # via pip-tools, pur constantly==15.1.0 # via twisted -cryptography==2.3.1 # via pyopenssl -cssselect2==0.2.1 # via cairosvg, weasyprint +cryptography==2.3.1 # via pyopenssl, scrapy cssselect==1.0.3 # via parsel, scrapy cymem==2.0.2 # via preshed, spacy, thinc -defusedxml==0.5.0 # via cairosvg, odfpy +defusedxml==0.5.0 # via odfpy diff-match-patch==20181111 # via django-import-export -django-anymail==6.0 -django-appconf==1.0.2 # via django-compressor -django-common-helpers==0.9.2 # via django-cron -django-compressor==2.2 -django-cron==0.5.1 -django-debug-toolbar==1.11 -django-dotenv==1.4.2 -django-filter==2.1.0 -django-import-export==1.2.0 -django-libsass==0.7 -django-mailbox==4.7.1 -django-summernote==0.8.11.4 -django==2.1.7 +django-appconf==1.0.3 # via django-compressor +django-apscheduler==0.3.0 +django-compressor==2.4 +django-debug-toolbar==2.1 +django-filter==2.2.0 +django-grappelli==2.13.3 +django-import-export==2.0 +django-libsass==0.8 +django-localflavor==2.2 +django==2.2.9 +djangorestframework==3.11.0 entrypoints==0.3 # via flake8 et-xmlfile==1.0.1 # via openpyxl filelock==3.0.10 # via tox -flake8==3.7.7 -html5lib==1.0.1 # via weasyprint +flake8==3.7.9 +gunicorn==20.0.4 hyperlink==18.0.0 # via twisted idna==2.7 # via cryptography, hyperlink, requests +importlib-metadata==1.4.0 # via catalogue, pluggy, pytest, tox incremental==17.5.0 # via twisted jdcal==1.4 # via openpyxl -jsonschema==2.6.0 # via spacy libsass==0.17.0 # via django-libsass lxml==4.2.4 # via parsel, scrapy mccabe==0.6.1 # via flake8 -murmurhash==1.0.2 # via spacy, thinc +more-itertools==8.0.2 # via pytest, zipp +murmurhash==1.0.2 # via preshed, spacy, thinc numpy==1.16.2 # via blis, spacy, thinc odfpy==1.4.0 # via tablib -openpyxl==2.6.1 # via tablib +openpyxl==3.0.3 +packaging==20.0 # via pytest, tox parsel==1.5.0 # via scrapy -pillow==5.4.1 # via cairosvg -pip-tools==3.5.0 +pillow==7.0.0 +pip-tools==4.3.0 plac==0.9.6 # via spacy, thinc -pluggy==0.8.1 # via tox -preshed==2.0.1 # via spacy, thinc -psycopg2-binary==2.7.7 -psycopg2==2.7.7 -pur==5.2.1 -py==1.5.4 # via tox +pluggy==0.13.1 # via pytest, tox +preshed==3.0.2 # via spacy, thinc +protego==0.1.16 # via scrapy +psycopg2-binary==2.8.4 +pur==5.3.0 +py==1.5.4 # via pytest, tox pyasn1-modules==0.2.2 # via service-identity pyasn1==0.4.4 # via pyasn1-modules, service-identity pycodestyle==2.5.0 # via flake8 @@ -71,33 +69,41 @@ pydispatcher==2.0.5 # via scrapy pyflakes==2.1.0 # via flake8 pyhamcrest==1.9.0 # via twisted pyopenssl==18.0.0 # via scrapy, service-identity -pyphen==0.9.5 # via weasyprint -pytz==2018.5 # via django +pyparsing==2.4.6 # via packaging +pytest==5.3.2 +python-stdnum==1.12 # via django-localflavor +pytz==2018.5 # via apscheduler, django, tzlocal pyyaml==3.13 # via tablib queuelib==1.5.0 # via scrapy rcssmin==1.0.6 # via django-compressor -requests==2.21.0 -rjsmin==1.0.12 # via django-compressor +requests==2.22.0 +rjsmin==1.1.0 # via django-compressor scrapy-djangoitem==1.1.1 -scrapy==1.6.0 +scrapy==1.8.0 +scrapyd==1.2.1 service-identity==17.0.0 # via scrapy -six==1.11.0 # via automat, cryptography, django-anymail, django-mailbox, html5lib, libsass, parsel, pip-tools, pyhamcrest, pyopenssl, scrapy, scrapy-djangoitem, tox, w3lib -spacy==2.1.3 -sqlparse==0.2.4 # via django-debug-toolbar -srsly==0.0.5 # via spacy, thinc +six==1.13.0 # via apscheduler, automat, cryptography, django-appconf, django-compressor, libsass, packaging, parsel, pip-tools, protego, pyhamcrest, pyopenssl, scrapy, scrapy-djangoitem, scrapyd, tox, w3lib +spacy==2.2.3 +sqlparse==0.2.4 # via django, django-debug-toolbar +srsly==1.0.1 # via spacy, thinc tablib==0.13.0 # via django-import-export -thinc==7.0.4 # via spacy -tinycss2==0.6.1 # via cairosvg, cssselect2, weasyprint +thinc==7.3.1 # via spacy toml==0.10.0 # via tox -tox==3.7.0 +tox==3.14.3 tqdm==4.31.1 # via thinc -twisted==18.7.0 # via scrapy +twisted==18.7.0 # via scrapy, scrapyd +tzlocal==2.0.0 # via apscheduler urllib3==1.23 # via requests virtualenv==16.0.0 # via tox w3lib==1.19.0 # via parsel, scrapy -wasabi==0.2.0 # via spacy, thinc -weasyprint==46 -webencodings==0.5.1 # via html5lib, tinycss2 +wasabi==0.6.0 # via spacy, thinc +wcwidth==0.1.8 # via pytest +whitenoise==5.0.1 xlrd==1.2.0 # via tablib +xlsxwriter==1.2.7 xlwt==1.3.0 # via tablib -zope.interface==4.5.0 # via twisted +zipp==1.0.0 # via importlib-metadata +zope.interface==4.5.0 # via scrapy, twisted + +# The following packages are considered to be unsafe in a requirements file: +# setuptools diff --git a/scraper/spiders/greenhouse.py b/scraper/spiders/greenhouse.py index 27a0ac1..593168d 100644 --- a/scraper/spiders/greenhouse.py +++ b/scraper/spiders/greenhouse.py @@ -34,8 +34,9 @@ def start_requests(self): def parse(self, response): """Extract job detail urls from response.""" hxs = Selector(response) - urls = hxs.xpath('//cite/text()').extract() + urls = hxs.xpath('//div[contains(@class, "r")]/a/@href').extract() for url in urls: + url = url.replace("/url?q=", "") yield Request(url, callback=self.parse_detail_pages, dont_filter=True) print(url) diff --git a/scraper/spiders/lever.py b/scraper/spiders/lever.py index 8eef0dc..a661fc6 100644 --- a/scraper/spiders/lever.py +++ b/scraper/spiders/lever.py @@ -34,11 +34,15 @@ def start_requests(self): def parse(self, response): """Extract job detail urls from response.""" hxs = Selector(response) - urls = hxs.xpath('//cite/text()').extract() + urls = hxs.xpath('//div[contains(@class, "r")]/a/@href').extract() for url in urls: + url = url.replace("/url?q=", "") + url = url.split("&")[0] + print(url) yield Request(url, callback=self.parse_detail_pages, dont_filter=True) print(url) + def parse_detail_pages(self, response): hxs = Selector(response) jobs = hxs.xpath('//div[contains(@class, "content")]') @@ -46,7 +50,8 @@ def parse_detail_pages(self, response): for job in jobs: item = JobItem() item["title"] = job.xpath('//div[contains(@class, "posting-headline")]/h2/text()').extract_first() - item["company"] = str('n/a') + item["company"] = job.xpath('//div[contains(@class, "main-footer-text page-centered")]/p/a/text()').extract() + item["company_url"] = job.xpath('//div[contains(@class, "main-footer-text page-centered")]/p/a/@href').extract() item["body"] = job.xpath('//div[contains(@class, "section page-centered")]').extract() item["location"] = job.xpath('//div[contains(@class, "sort-by-time posting-category medium-category-label")]').extract_first() item["url"] = response.request.url diff --git a/scraper/spiders/recruiterbox.py b/scraper/spiders/recruiterbox.py index d391d8b..ba6a05b 100644 --- a/scraper/spiders/recruiterbox.py +++ b/scraper/spiders/recruiterbox.py @@ -34,8 +34,9 @@ def start_requests(self): def parse(self, response): """Extract job detail urls from response.""" hxs = Selector(response) - urls = hxs.xpath('//cite/text()').extract() + urls = hxs.xpath('//div[contains(@class, "r")]/a/@href').extract() for url in urls: + url = url.replace("/url?q=", "") yield Request(url, callback=self.parse_detail_pages, dont_filter=True) print(url) @@ -48,7 +49,7 @@ def parse_detail_pages(self, response): item["title"] = job.xpath('//h1[contains(@class, "jobtitle")]/text()').extract_first() item["company"] = str('n/a') item["body"] = job.xpath('//div[contains(@class, "jobdesciption")]').extract() - item["location"] = job.xpath('//span[contains(@class, "meta-job-location-city")]').extract() + item["location"] = str('n/a') item["url"] = response.request.url item["pub_date"] = str('n/a') item["email"] = str('n/a') diff --git a/scraper/spiders/weworkremotely.py b/scraper/spiders/weworkremotely.py new file mode 100644 index 0000000..e166f7c --- /dev/null +++ b/scraper/spiders/weworkremotely.py @@ -0,0 +1,200 @@ +# # import scrapy +# from scrapy.spiders import Spider +# from scrapy.selector import Selector +# from scraper.items import OrganizationItem +# from scrapy.http import Request + +# from django.utils import timezone + +# from seeker.job.models import ZipCodes + +# search_terms = [ +# 'hvac', +# 'pest control', +# 'window washer', +# 'electrician', +# 'plumber', +# 'carpet cleaning', +# 'appliance repair', +# 'commercial cleaning', +# 'eletrical contracting', +# 'landscaping', +# 'lawn care', +# 'painters', +# 'pool and spa services', +# 'pressure washing', +# 'roofing', +# 'snow removal', +# 'tree removal' +# ] +# locations = [] +# generated_start_urls = [] + +# print(generated_start_urls) + + +# zip_codes = ZipCodes.objects.filter(yp_searched=False).order_by('id')[:50] +# for zip_code in zip_codes: +# search_location = zip_code.zip_code +# zip_id = zip_code.id +# obj = ZipCodes.objects.get(id=zip_id) +# obj.yp_searched = True +# obj.save() +# locations.append(search_location) + + +# for term in search_terms: +# for location in locations: +# url = "http://www.yellowpages.com/search?search_terms={}&geo_location_terms={}".format(term, location) +# generated_start_urls.append(url) + + +# class YellowPagesSpider(Spider): +# name = "yellowpages" +# base_url = 'http://www.yellowpages.com' +# start_urls = generated_start_urls + +# # print("*" * 200) +# # print(start_urls) +# # print("*" * 200) + +# def parse(self, response): +# """Extract job detail urls from response.""" +# hxs = Selector(response) +# urls = hxs.xpath('//a[contains(@class, "business-name")]/@href').extract() +# for url in urls: +# schema = '{}{}'.format('https://www.yellowpages.com', url) +# yield Request(schema, callback=self.parse_detail_pages, dont_filter=True) +# # print(url) + +# # pagination +# next_link = hxs.xpath('//a[contains(text(),"Next")]/@href').extract() +# if next_link: +# next_link = next_link[0] +# # print(next_link) +# yield Request(self.base_url + next_link, self.parse, dont_filter=True) + +# def parse_detail_pages(self, response): +# hxs = Selector(response) +# item = OrganizationItem() +# company = hxs.xpath('//div[@id="content-container"]') + +# name = company.xpath('.//div[contains(@class, "sales-info")]/h1/text()').extract() +# if name: +# name = name[0] +# item['name'] = name +# else: +# item['name'] = '' + +# email = company.xpath('.//a[contains(@class,"email-business")]/@href').extract() +# if email: +# email = email[0] +# item['email'] = email +# else: +# item['email'] = '' + +# full_address = company.xpath('.//h2[contains(@class, "address")]/text()').extract() +# if full_address: +# full_address = full_address[0] +# item['full_address'] = full_address +# else: +# item['full_address'] = '' + +# # check = company.xpath('.//p[contains(@class, "address")]/span[4]/text()').extract() + +# # if check: +# # address = company.xpath('.//p[contains(@class, "address")]/span[1]/text()').extract() +# # if address: +# # address = address[0] +# # item['address'] = address +# # else: +# # item['address'] = '' + +# # city = company.xpath('.//p[contains(@class, "address")]/span[2]/text()').extract() +# # if city: +# # city = city[0] +# # item['city'] = city +# # else: +# # item['city'] = '' + +# # state = company.xpath('.//p[contains(@class, "address")]/span[3]/text()').extract() +# # if state: +# # state = state[0] +# # item['state'] = state +# # else: +# # item['state'] = '' + +# # zip_code = company.xpath('.//p[contains(@class, "address")]/span[4]/text()').extract() +# # if zip_code: +# # zip_code = zip_code[0] +# # item['zip_code'] = zip_code +# # else: +# # item['zip_code'] = '' +# # else: +# # item['address'] = '' + +# # city = company.xpath('.//p[contains(@class, "address")]/span[1]/text()').extract() +# # if city: +# # city = city[0] +# # item['city'] = city +# # else: +# # item['city'] = '' + +# # state = company.xpath('.//p[contains(@class, "address")]/span[2]/text()').extract() +# # if state: +# # state = state[0] +# # item['state'] = state +# # else: +# # item['state'] = '' + +# # zip_code = company.xpath('.//p[contains(@class, "address")]/span[3]/text()').extract() +# # if zip_code: +# # zip_code = zip_code[0] +# # item['zip_code'] = zip_code +# # else: +# # item['zip_code'] = '' + +# phone = company.xpath('.//p[contains(@class, "phone")]/text()').extract() +# if phone: +# phone = phone[0] +# item['phone'] = phone +# else: +# item['phone'] = '' + +# url = company.xpath('.//a[contains(text(),"Visit Website")]/@href').extract() +# if url: +# url = url[0] +# item['url'] = url +# else: +# item['url'] = '' + +# description = company.xpath('.//dd[contains(@class, "general-info")]/text()').extract() +# if description: +# description = description[0] +# item['description'] = description +# else: +# item['description'] = '' + +# organization_type = company.xpath('.//dd[contains(@class, "categories")]/span[1]/a/text()').extract() +# if organization_type: +# organization_type = organization_type[0] +# item["organization_type"] = organization_type +# else: +# item["organization_type"] = '' + +# item["address"] = '' +# item["city"] = '' +# item["state"] = '' +# item["zip_code"] = '' +# item["rate"] = '' +# item["lat"] = '' +# item["lng"] = '' +# item["lat_lng"] = '' +# item["twitter"] = '' +# item["facebook"] = '' +# item["linkedin"] = '' +# item["instagram"] = '' +# item["source"] = 'Yellow Pages' +# item["scrape_date"] = timezone.now() +# # print(item) +# yield item diff --git a/scraper/spiders/workable.py b/scraper/spiders/workable.py index 2d6650d..5e23c95 100644 --- a/scraper/spiders/workable.py +++ b/scraper/spiders/workable.py @@ -32,8 +32,11 @@ def start_requests(self): def parse(self, response): """Extract job detail urls from response.""" hxs = Selector(response) - urls = hxs.xpath('//cite/text()').extract() + urls = hxs.xpath('//div[contains(@class, "r")]/a/@href').extract() for url in urls: + url = url.replace("/url?q=", "") + print(url) + url = url.split("&")[0] yield Request(url, callback=self.parse_detail_pages, dont_filter=True) print(url) diff --git a/seeker/job/admin.py b/seeker/job/admin.py index 091890f..81b4381 100644 --- a/seeker/job/admin.py +++ b/seeker/job/admin.py @@ -5,7 +5,6 @@ from django.db.models import Count from import_export.admin import ImportExportModelAdmin -from django_summernote.admin import SummernoteModelAdmin from ..util.actions import ExportCsvMixin @@ -22,8 +21,7 @@ @admin.register(Job) -class JobAdmin(ImportExportModelAdmin, ExportCsvMixin, SummernoteModelAdmin): - summernote_fields = ('body',) +class JobAdmin(ImportExportModelAdmin, ExportCsvMixin): list_select_related = True # save_on_top = True date_hierarchy = 'scrape_date' diff --git a/seeker/job/apps.py b/seeker/job/apps.py index 0eb55e4..32978b2 100644 --- a/seeker/job/apps.py +++ b/seeker/job/apps.py @@ -1,17 +1,7 @@ -from suit.menu import ParentItem -from suit.apps import DjangoSuitConfig from django.apps import AppConfig -class JobConfig(DjangoSuitConfig): - layout = 'horizontal' - menu = ( - ParentItem('Jobs', url='/job/job/'), - ParentItem('Companies', url='/job/company/'), - ParentItem('Job Boards', url='/job/board/'), - ParentItem('Cron Logs', url='/django_cron/cronjoblog/'), - ParentItem('Search Terms', url='/job/searchterms/'), - ) +class JobConfig(AppConfig): def ready(self): # import jobs.signals # noqa diff --git a/seeker/job/migrations/0003_company_logo.py b/seeker/job/migrations/0003_company_logo.py new file mode 100644 index 0000000..dac0071 --- /dev/null +++ b/seeker/job/migrations/0003_company_logo.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.9 on 2020-01-15 01:00 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('job', '0002_tag'), + ] + + operations = [ + migrations.AddField( + model_name='company', + name='logo', + field=models.ImageField(blank=True, null=True, upload_to=''), + ), + ] diff --git a/seeker/job/models.py b/seeker/job/models.py index dbc60d2..5563852 100644 --- a/seeker/job/models.py +++ b/seeker/job/models.py @@ -1,5 +1,4 @@ """Job Models.""" -from django.urls import reverse from django.db import models from django.utils.html import format_html @@ -16,7 +15,7 @@ class Meta: def __str__(self): """Set title.""" - return "%s" % self.title + return f"{self.title}" class Company(models.Model): @@ -25,6 +24,7 @@ class Company(models.Model): email = models.EmailField(blank=True) url = models.URLField() about = models.TextField() + logo = models.ImageField(blank=True, null=True) class Meta: """Order by title.""" @@ -32,7 +32,8 @@ class Meta: def __str__(self): """Set Title.""" - return "%s" % self.title + return f"{self.title}" + class Job(models.Model): title = models.CharField(max_length=255) @@ -59,16 +60,16 @@ class Meta: def __str__(self): """Set title.""" - return "%s" % self.title + return f"{self.title}" def short_url(self): """Return a clickable link.""" if self.url: - short_url = self.url[:25] + '...' + # short_url = self.url[:25] + '...' return format_html("View Post".format(self.url)) else: return self.url - + def get_count(self): "Total Number of Jobs" return self.objects.all().count() @@ -78,7 +79,7 @@ class SearchTerms(models.Model): term = models.CharField(max_length=55) def __str__(self): - return u"%s" % self.term + return f"{self.term}" class Tag(models.Model): diff --git a/seeker/job/serializers.py b/seeker/job/serializers.py new file mode 100644 index 0000000..3a02b4c --- /dev/null +++ b/seeker/job/serializers.py @@ -0,0 +1,17 @@ +"""Serializers.""" +from rest_framework import serializers + +from seeker.job.models import Job + + +class JobSerializer(serializers.ModelSerializer): + + id = serializers.HyperlinkedRelatedField( + view_name="job_detail", read_only=True + ) + + class Meta: + """Endpoint fields.""" + + model = Job + fields = '__all__' diff --git a/seeker/job/templates/job_detail.html b/seeker/job/templates/job_detail.html new file mode 100644 index 0000000..beec05c --- /dev/null +++ b/seeker/job/templates/job_detail.html @@ -0,0 +1,46 @@ +{% extends 'base.html' %} +{% load staticfiles %} +{% block page_title %}{{ job.title }} | Seeker{% endblock %} +{% block content %} +
+
+ < Back +
+
+
+
+ {{ job.company.name }} Logo +
+ +
{{ job.title }}
+
+ {{ job.company }} + {{ job.board }} +
+
+
+ {{ job.body | safe }} +
+
+
+
Job Overview
+
    +
  • Published: {{ job.pub_date }}
  • +
  • Scraped: {{ job.scrape_date | date }}
  • +
  • Salary: {{ job.salary }}
  • +
  • Job URL: View Original
  • +
+
+
+
Company Overview
+
    +
  • URL: Company Site
  • +
  • Glassdoor Rating:
  • +
  • Location: {{ job.company.location }}
  • +
+
+
+
+
+ +{% endblock content %} diff --git a/seeker/job/templates/job_list.html b/seeker/job/templates/job_list.html new file mode 100644 index 0000000..fcd5ece --- /dev/null +++ b/seeker/job/templates/job_list.html @@ -0,0 +1,85 @@ +{% extends 'base.html' %} +{% load staticfiles %} +{% block page_title %}Jobs | Seeker{% endblock %} +{% block content %} + +
+
+
+
    + {% for job in jobs %} +
  • + {{ job.company.name }} Logo +
    +
    {{ job.title }}
    + {{ job.company }} + {{ job.board }} + {{ job.salary }} +
    + Scraped: {{ job.scrape_date | date }} + {% if job.pub_date %} + | Published: {{ job.pub_date }} + {% endif %} + +
    + +
  • +
    + {% endfor %} +
+ {% include 'includes/pagination.html' %} +
+
+
+
Search
+
+
+ +
+
+
+
+
Skills
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
Salary Range
+
+
+ + +
+
+ + +
+
+
+
+
+
+ +{% endblock content %} diff --git a/seeker/job/templates/job_search_results.html b/seeker/job/templates/job_search_results.html new file mode 100644 index 0000000..a7c58be --- /dev/null +++ b/seeker/job/templates/job_search_results.html @@ -0,0 +1,26 @@ +{% extends 'base.html' %} +{% load staticfiles %} +{% block page_title %}Search Results | Seeker{% endblock %} +{% block content %} + +
+
+
+ +
+
+
+ +{% endblock content %} diff --git a/seeker/job/views.py b/seeker/job/views.py index e69de29..2de9372 100644 --- a/seeker/job/views.py +++ b/seeker/job/views.py @@ -0,0 +1,61 @@ +from django.views.generic.list import ListView +from django.views.generic.detail import DetailView +from django.db.models import Q +from django.contrib.syndication.views import Feed +from rest_framework import viewsets + +from .models import Job +from .serializers import JobSerializer + + +class JobListView(ListView): + model = Job + template_name = 'job_list.html' + context_object_name = 'jobs' + paginate_by = 6 + queryset = Job.objects.all().order_by('-id') + + +class JobDetailView(DetailView): + model = Job + context_object_name = 'job' + template_name = 'job_detail.html' + + +class SearchResultsView(ListView): + model = Job + template_name = 'job_search_results.html' + context_object_name = 'jobs' + + def get_queryset(self): + query = self.request.GET.get('q') + queryset = Job.objects.filter( + Q(title__icontains=query) | Q(body__icontains=query) + ) + + return queryset + + +class JobsFeed(Feed): + title = "Latest Jobs" + link = "/feed/" + description = "Latest jobs feed" + + def items(self): + return Job.objects.order_by('-scrape_date')[:100] + + def item_title(self, item): + return item.title + + def item_description(self, item): + return item.body + + def item_link(self, item): + return item.url + + +class JobViewSet(viewsets.ModelViewSet): + + model = Job + queryset = Job.objects.all() + serializer_class = JobSerializer diff --git a/seeker/jobs.py b/seeker/jobs.py new file mode 100644 index 0000000..b06000e --- /dev/null +++ b/seeker/jobs.py @@ -0,0 +1,43 @@ +import subprocess + +# import scrapy +# from scrapy.utils.project import get_project_settings +# from scrapy import spiderloader +# from scrapy.utils import project + +from apscheduler.schedulers.background import BackgroundScheduler +from django_apscheduler.jobstores import ( + DjangoJobStore, + register_events, + register_job +) + +scheduler = BackgroundScheduler() +scheduler.add_jobstore(DjangoJobStore(), 'default') + + +@register_job(scheduler, "interval", minutes=60) +def run_spiders(): + spiders = [ + 'djangogigs', + 'greenhouse', + 'indeed', + 'lever', + 'pythonorg', + 'recruiterbox', + 'remotepython', + 'stackoverflow', + 'workable' + ] + # settings = project.get_project_settings() + # spider_loader = spiderloader.SpiderLoader.from_settings(settings) + # spiders = spider_loader.list() + + for spider in spiders: + print(spider) + subprocess.run(["scrapy", "crawl", spider]) + # print(spiders) + # subprocess.run(["scrapy", "crawl", "greenhouse"]) + +register_events(scheduler) +scheduler.start() diff --git a/seeker/settings.py b/seeker/settings.py index 906122c..94d9e0e 100644 --- a/seeker/settings.py +++ b/seeker/settings.py @@ -32,7 +32,6 @@ # Application definition INSTALLED_APPS = [ - 'seeker.job.apps.JobConfig', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', @@ -43,9 +42,9 @@ 'debug_toolbar', # debug toolbar 'compressor', # compile static assets - 'django_cron', # recurring tasks without the task queue 'import_export', # import-export package - 'django_summernote', # summernote editor + 'django_apscheduler', # cron like service for django + 'rest_framework', # Django REST Framework 'seeker.job', ] @@ -53,6 +52,7 @@ MIDDLEWARE = [ 'debug_toolbar.middleware.DebugToolbarMiddleware', 'django.middleware.security.SecurityMiddleware', + 'whitenoise.middleware.WhiteNoiseMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', @@ -86,14 +86,15 @@ # Database # https://docs.djangoproject.com/en/2.0/ref/settings/#databases - DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.postgresql', - 'NAME': 'seeker', - 'USER': 'postgres', - 'HOST': 'localhost', - 'PORT': 5433, + "default": { + "ENGINE": "django.db.backends.postgresql", + "NAME": "postgres", + "USER": "postgres", + "PASSWORD": "postgres", + # 'HOST': 'localhost', + "HOST": "postgres", + "PORT": "5435", } } @@ -135,6 +136,8 @@ ('text/x-scss', 'django_libsass.SassCompiler'), ) +COMPRESS_ENABLED = True + # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/2.0/howto/static-files/ @@ -148,6 +151,8 @@ "seeker/static/", ] +STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' + STATICFILES_LOCATION = 'static' STATIC_ROOT = os.path.join(BASE_DIR, 'static') STATIC_URL = '/static/' @@ -157,7 +162,21 @@ MEDIA_URL = '/media/' -CRON_CLASSES = [ - # "job.jobs.RunSpidersCronJob", - # ... -] +# Django REST Framework Settings +REST_FRAMEWORK = { + "DEFAULT_PERMISSION_CLASSES": (), + "DEFAULT_AUTHENTICATION_CLASSES": (), + # "DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.IsAuthenticated",), + # "DEFAULT_AUTHENTICATION_CLASSES": ( + # "rest_framework_jwt.authentication.JSONWebTokenAuthentication", + # "rest_framework.authentication.SessionAuthentication", + # "rest_framework.authentication.BasicAuthentication", + # ), + "DATETIME_FORMAT": "%m-%d-%Y", + "DEFAULT_FILTER_BACKENDS": ( + "rest_framework.filters.SearchFilter", + "rest_framework.filters.OrderingFilter", + ), + # "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.LimitOffsetPagination", + # "PAGE_SIZE": 10, +} diff --git a/seeker/static/js/vendor/Chart.bundle.min.js b/seeker/static/js/vendor/Chart.bundle.min.js deleted file mode 100644 index 59afc3f..0000000 --- a/seeker/static/js/vendor/Chart.bundle.min.js +++ /dev/null @@ -1,10 +0,0 @@ -/*! - * Chart.js - * http://chartjs.org/ - * Version: 2.7.3 - * - * Copyright 2018 Chart.js Contributors - * Released under the MIT license - * https://github.com/chartjs/Chart.js/blob/master/LICENSE.md - */ -!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).Chart=t()}}(function(){return function r(o,s,l){function u(e,t){if(!s[e]){if(!o[e]){var n="function"==typeof require&&require;if(!t&&n)return n(e,!0);if(d)return d(e,!0);var i=new Error("Cannot find module '"+e+"'");throw i.code="MODULE_NOT_FOUND",i}var a=s[e]={exports:{}};o[e][0].call(a.exports,function(t){return u(o[e][1][t]||t)},a,a.exports,r,o,s,l)}return s[e].exports}for(var d="function"==typeof require&&require,t=0;t>>0,i=0;iwt(t)?(r=t+1,s-wt(t)):(r=t,s),{year:r,dayOfYear:o}}function Bt(t,e,n){var i,a,r=Vt(t.year(),e,n),o=Math.floor((t.dayOfYear()-r-1)/7)+1;return o<1?i=o+Et(a=t.year()-1,e,n):o>Et(t.year(),e,n)?(i=o-Et(t.year(),e,n),a=t.year()+1):(a=t.year(),i=o),{week:i,year:a}}function Et(t,e,n){var i=Vt(t,e,n),a=Vt(t+1,e,n);return(wt(t)-i+a)/7}B("w",["ww",2],"wo","week"),B("W",["WW",2],"Wo","isoWeek"),A("week","w"),A("isoWeek","W"),Y("week",5),Y("isoWeek",5),lt("w",J),lt("ww",J,G),lt("W",J),lt("WW",J,G),ft(["w","ww","W","WW"],function(t,e,n,i){e[i.substr(0,1)]=M(t)});B("d",0,"do","day"),B("dd",0,0,function(t){return this.localeData().weekdaysMin(this,t)}),B("ddd",0,0,function(t){return this.localeData().weekdaysShort(this,t)}),B("dddd",0,0,function(t){return this.localeData().weekdays(this,t)}),B("e",0,0,"weekday"),B("E",0,0,"isoWeekday"),A("day","d"),A("weekday","e"),A("isoWeekday","E"),Y("day",11),Y("weekday",11),Y("isoWeekday",11),lt("d",J),lt("e",J),lt("E",J),lt("dd",function(t,e){return e.weekdaysMinRegex(t)}),lt("ddd",function(t,e){return e.weekdaysShortRegex(t)}),lt("dddd",function(t,e){return e.weekdaysRegex(t)}),ft(["dd","ddd","dddd"],function(t,e,n,i){var a=n._locale.weekdaysParse(t,i,n._strict);null!=a?e.d=a:v(n).invalidWeekday=t}),ft(["d","e","E"],function(t,e,n,i){e[i]=M(t)});var jt="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_");var Ut="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_");var Gt="Su_Mo_Tu_We_Th_Fr_Sa".split("_");var qt=ot;var Zt=ot;var Xt=ot;function Jt(){function t(t,e){return e.length-t.length}var e,n,i,a,r,o=[],s=[],l=[],u=[];for(e=0;e<7;e++)n=p([2e3,1]).day(e),i=this.weekdaysMin(n,""),a=this.weekdaysShort(n,""),r=this.weekdays(n,""),o.push(i),s.push(a),l.push(r),u.push(i),u.push(a),u.push(r);for(o.sort(t),s.sort(t),l.sort(t),u.sort(t),e=0;e<7;e++)s[e]=dt(s[e]),l[e]=dt(l[e]),u[e]=dt(u[e]);this._weekdaysRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+s.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+o.join("|")+")","i")}function $t(){return this.hours()%12||12}function Kt(t,e){B(t,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),e)})}function Qt(t,e){return e._meridiemParse}B("H",["HH",2],0,"hour"),B("h",["hh",2],0,$t),B("k",["kk",2],0,function(){return this.hours()||24}),B("hmm",0,0,function(){return""+$t.apply(this)+W(this.minutes(),2)}),B("hmmss",0,0,function(){return""+$t.apply(this)+W(this.minutes(),2)+W(this.seconds(),2)}),B("Hmm",0,0,function(){return""+this.hours()+W(this.minutes(),2)}),B("Hmmss",0,0,function(){return""+this.hours()+W(this.minutes(),2)+W(this.seconds(),2)}),Kt("a",!0),Kt("A",!1),A("hour","h"),Y("hour",13),lt("a",Qt),lt("A",Qt),lt("H",J),lt("h",J),lt("k",J),lt("HH",J,G),lt("hh",J,G),lt("kk",J,G),lt("hmm",$),lt("hmmss",K),lt("Hmm",$),lt("Hmmss",K),ct(["H","HH"],vt),ct(["k","kk"],function(t,e,n){var i=M(t);e[vt]=24===i?0:i}),ct(["a","A"],function(t,e,n){n._isPm=n._locale.isPM(t),n._meridiem=t}),ct(["h","hh"],function(t,e,n){e[vt]=M(t),v(n).bigHour=!0}),ct("hmm",function(t,e,n){var i=t.length-2;e[vt]=M(t.substr(0,i)),e[bt]=M(t.substr(i)),v(n).bigHour=!0}),ct("hmmss",function(t,e,n){var i=t.length-4,a=t.length-2;e[vt]=M(t.substr(0,i)),e[bt]=M(t.substr(i,2)),e[yt]=M(t.substr(a)),v(n).bigHour=!0}),ct("Hmm",function(t,e,n){var i=t.length-2;e[vt]=M(t.substr(0,i)),e[bt]=M(t.substr(i))}),ct("Hmmss",function(t,e,n){var i=t.length-4,a=t.length-2;e[vt]=M(t.substr(0,i)),e[bt]=M(t.substr(i,2)),e[yt]=M(t.substr(a))});var te,ee=Ct("Hours",!0),ne={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:At,monthsShort:Ft,week:{dow:0,doy:6},weekdays:jt,weekdaysMin:Gt,weekdaysShort:Ut,meridiemParse:/[ap]\.?m?\.?/i},ie={},ae={};function re(t){return t?t.toLowerCase().replace("_","-"):t}function oe(t){var e=null;if(!ie[t]&&void 0!==jn&&jn&&jn.exports)try{e=te._abbr,En("./locale/"+t),se(e)}catch(t){}return ie[t]}function se(t,e){var n;return t&&((n=u(e)?ue(t):le(t,e))?te=n:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+t+" not found. Did you forget to load it?")),te._abbr}function le(t,e){if(null===e)return delete ie[t],null;var n,i=ne;if(e.abbr=t,null!=ie[t])C("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),i=ie[t]._config;else if(null!=e.parentLocale)if(null!=ie[e.parentLocale])i=ie[e.parentLocale]._config;else{if(null==(n=oe(e.parentLocale)))return ae[e.parentLocale]||(ae[e.parentLocale]=[]),ae[e.parentLocale].push({name:t,config:e}),null;i=n._config}return ie[t]=new O(T(i,e)),ae[t]&&ae[t].forEach(function(t){le(t.name,t.config)}),se(t),ie[t]}function ue(t){var e;if(t&&t._locale&&t._locale._abbr&&(t=t._locale._abbr),!t)return te;if(!s(t)){if(e=oe(t))return e;t=[t]}return function(t){for(var e,n,i,a,r=0;r=e&&o(a,n,!0)>=e-1)break;e--}r++}return te}(t)}function de(t){var e,n=t._a;return n&&-2===v(t).overflow&&(e=n[mt]<0||11Ot(n[gt],n[mt])?pt:n[vt]<0||24Et(n,r,o)?v(t)._overflowWeeks=!0:null!=l?v(t)._overflowWeekday=!0:(s=Ht(n,i,a,r,o),t._a[gt]=s.year,t._dayOfYear=s.dayOfYear)}(t),null!=t._dayOfYear&&(r=he(t._a[gt],i[gt]),(t._dayOfYear>wt(r)||0===t._dayOfYear)&&(v(t)._overflowDayOfYear=!0),n=zt(r,0,t._dayOfYear),t._a[mt]=n.getUTCMonth(),t._a[pt]=n.getUTCDate()),e=0;e<3&&null==t._a[e];++e)t._a[e]=o[e]=i[e];for(;e<7;e++)t._a[e]=o[e]=null==t._a[e]?2===e?1:0:t._a[e];24===t._a[vt]&&0===t._a[bt]&&0===t._a[yt]&&0===t._a[xt]&&(t._nextDay=!0,t._a[vt]=0),t._d=(t._useUTC?zt:function(t,e,n,i,a,r,o){var s=new Date(t,e,n,i,a,r,o);return t<100&&0<=t&&isFinite(s.getFullYear())&&s.setFullYear(t),s}).apply(null,o),a=t._useUTC?t._d.getUTCDay():t._d.getDay(),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),t._nextDay&&(t._a[vt]=24),t._w&&void 0!==t._w.d&&t._w.d!==a&&(v(t).weekdayMismatch=!0)}}var fe=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,ge=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,me=/Z|[+-]\d\d(?::?\d\d)?/,pe=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],ve=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],be=/^\/?Date\((\-?\d+)/i;function ye(t){var e,n,i,a,r,o,s=t._i,l=fe.exec(s)||ge.exec(s);if(l){for(v(t).iso=!0,e=0,n=pe.length;en.valueOf():n.valueOf()this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},un.isLocal=function(){return!!this.isValid()&&!this._isUTC},un.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},un.isUtc=Ve,un.isUTC=Ve,un.zoneAbbr=function(){return this._isUTC?"UTC":""},un.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},un.dates=n("dates accessor is deprecated. Use date instead.",nn),un.months=n("months accessor is deprecated. Use month instead",Lt),un.years=n("years accessor is deprecated. Use year instead",Dt),un.zone=n("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(t,e){return null!=t?("string"!=typeof t&&(t=-t),this.utcOffset(t,e),this):-this.utcOffset()}),un.isDSTShifted=n("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!u(this._isDSTShifted))return this._isDSTShifted;var t={};if(x(t,this),(t=Se(t))._a){var e=t._isUTC?p(t._a):Ce(t._a);this._isDSTShifted=this.isValid()&&0');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var r=0;r'),a[r]&&e.push(a[r]),e.push("");return e.push(""),e.join("")},legend:{labels:{generateLabels:function(l){var u=l.data;return u.labels.length&&u.datasets.length?u.labels.map(function(t,e){var n=l.getDatasetMeta(0),i=u.datasets[0],a=n.data[e],r=a&&a.custom||{},o=O.valueAtIndexOrDefault,s=l.options.elements.arc;return{text:t,fillStyle:r.backgroundColor?r.backgroundColor:o(i.backgroundColor,e,s.backgroundColor),strokeStyle:r.borderColor?r.borderColor:o(i.borderColor,e,s.borderColor),lineWidth:r.borderWidth?r.borderWidth:o(i.borderWidth,e,s.borderWidth),hidden:isNaN(i.data[e])||n.data[e].hidden,index:e}}):[]}},onClick:function(t,e){var n,i,a,r=e.index,o=this.chart;for(n=0,i=(o.data.datasets||[]).length;n=Math.PI?-1:f<-Math.PI?1:0))+c,m=Math.cos(f),p=Math.sin(f),v=Math.cos(g),b=Math.sin(g),y=f<=0&&0<=g||f<=2*Math.PI&&2*Math.PI<=g,x=f<=.5*Math.PI&&.5*Math.PI<=g||f<=2.5*Math.PI&&2.5*Math.PI<=g,_=f<=-Math.PI&&-Math.PI<=g||f<=Math.PI&&Math.PI<=g,k=f<=.5*-Math.PI&&.5*-Math.PI<=g||f<=1.5*Math.PI&&1.5*Math.PI<=g,w=h/100,M=_?-1:Math.min(m*(m<0?1:w),v*(v<0?1:w)),S=k?-1:Math.min(p*(p<0?1:w),b*(b<0?1:w)),D=y?1:Math.max(m*(0');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var r=0;r'),a[r]&&e.push(a[r]),e.push("");return e.push(""),e.join("")},legend:{labels:{generateLabels:function(s){var l=s.data;return l.labels.length&&l.datasets.length?l.labels.map(function(t,e){var n=s.getDatasetMeta(0),i=l.datasets[0],a=n.data[e].custom||{},r=_.valueAtIndexOrDefault,o=s.options.elements.arc;return{text:t,fillStyle:a.backgroundColor?a.backgroundColor:r(i.backgroundColor,e,o.backgroundColor),strokeStyle:a.borderColor?a.borderColor:r(i.borderColor,e,o.borderColor),lineWidth:a.borderWidth?a.borderWidth:r(i.borderWidth,e,o.borderWidth),hidden:isNaN(i.data[e])||n.data[e].hidden,index:e}}):[]}},onClick:function(t,e){var n,i,a,r=e.index,o=this.chart;for(n=0,i=(o.data.datasets||[]).length;n=e.numSteps?(r.callback(e.onAnimationComplete,[e],n),n.animating=!1,i.splice(a,1)):++a}}},{26:26,46:46}],24:[function(t,e,n){"use strict";var s=t(22),l=t(23),h=t(26),c=t(46),a=t(29),r=t(31),f=t(49),g=t(32),m=t(34),i=t(36);e.exports=function(u){function d(t){return"top"===t||"bottom"===t}u.types={},u.instances={},u.controllers={},c.extend(u.prototype,{construct:function(t,e){var n,i,a=this;(i=(n=(n=e)||{}).data=n.data||{}).datasets=i.datasets||[],i.labels=i.labels||[],n.options=c.configMerge(h.global,h[n.type],n.options||{}),e=n;var r=f.acquireContext(t,e),o=r&&r.canvas,s=o&&o.height,l=o&&o.width;a.id=c.uid(),a.ctx=r,a.canvas=o,a.config=e,a.width=l,a.height=s,a.aspectRatio=s?l/s:null,a.options=e.options,a._bufferedRender=!1,(a.chart=a).controller=a,u.instances[a.id]=a,Object.defineProperty(a,"data",{get:function(){return a.config.data},set:function(t){a.config.data=t}}),r&&o?(a.initialize(),a.update()):console.error("Failed to create chart: can't acquire context from the given item")},initialize:function(){var t=this;return g.notify(t,"beforeInit"),c.retinaScale(t,t.options.devicePixelRatio),t.bindEvents(),t.options.responsive&&t.resize(!0),t.ensureScalesHaveIDs(),t.buildOrUpdateScales(),t.initToolTip(),g.notify(t,"afterInit"),t},clear:function(){return c.canvas.clear(this),this},stop:function(){return l.cancelAnimation(this),this},resize:function(t){var e=this,n=e.options,i=e.canvas,a=n.maintainAspectRatio&&e.aspectRatio||null,r=Math.max(0,Math.floor(c.getMaximumWidth(i))),o=Math.max(0,Math.floor(a?r/a:c.getMaximumHeight(i)));if((e.width!==r||e.height!==o)&&(i.width=e.width=r,i.height=e.height=o,i.style.width=r+"px",i.style.height=o+"px",c.retinaScale(e,n.devicePixelRatio),!t)){var s={width:r,height:o};g.notify(e,"resize",[s]),e.options.onResize&&e.options.onResize(e,s),e.stop(),e.update({duration:e.options.responsiveAnimationDuration})}},ensureScalesHaveIDs:function(){var t=this.options,e=t.scales||{},n=t.scale;c.each(e.xAxes,function(t,e){t.id=t.id||"x-axis-"+e}),c.each(e.yAxes,function(t,e){t.id=t.id||"y-axis-"+e}),n&&(n.id=n.id||"scale")},buildOrUpdateScales:function(){var o=this,t=o.options,s=o.scales||{},e=[],l=Object.keys(s).reduce(function(t,e){return t[e]=!1,t},{});t.scales&&(e=e.concat((t.scales.xAxes||[]).map(function(t){return{options:t,dtype:"category",dposition:"bottom"}}),(t.scales.yAxes||[]).map(function(t){return{options:t,dtype:"linear",dposition:"left"}}))),t.scale&&e.push({options:t.scale,dtype:"radialLinear",isDefault:!0,dposition:"chartArea"}),c.each(e,function(t){var e=t.options,n=e.id,i=c.valueOrDefault(e.type,t.dtype);d(e.position)!==d(t.dposition)&&(e.position=t.dposition),l[n]=!0;var a=null;if(n in s&&s[n].type===i)(a=s[n]).options=e,a.ctx=o.ctx,a.chart=o;else{var r=m.getScaleConstructor(i);if(!r)return;a=new r({id:n,type:i,options:e,ctx:o.ctx,chart:o}),s[a.id]=a}a.mergeTicksOptions(),t.isDefault&&(o.scale=a)}),c.each(l,function(t,e){t||delete s[e]}),o.scales=s,m.addScalesToLayout(this)},buildOrUpdateControllers:function(){var r=this,o=[],s=[];return c.each(r.data.datasets,function(t,e){var n=r.getDatasetMeta(e),i=t.type||r.config.type;if(n.type&&n.type!==i&&(r.destroyDatasetMeta(e),n=r.getDatasetMeta(e)),n.type=i,o.push(n.type),n.controller)n.controller.updateIndex(e),n.controller.linkScales();else{var a=u.controllers[n.type];if(void 0===a)throw new Error('"'+n.type+'" is not a chart type.');n.controller=new a(r,e),s.push(n.controller)}},r),s},resetElements:function(){var n=this;c.each(n.data.datasets,function(t,e){n.getDatasetMeta(e).controller.reset()},n)},reset:function(){this.resetElements(),this.tooltip.initialize()},update:function(t){var e,n,i=this;if(t&&"object"==typeof t||(t={duration:t,lazy:arguments[1]}),n=(e=i).options,c.each(e.scales,function(t){r.removeBox(e,t)}),n=c.configMerge(u.defaults.global,u.defaults[e.config.type],n),e.options=e.config.options=n,e.ensureScalesHaveIDs(),e.buildOrUpdateScales(),e.tooltip._options=n.tooltips,e.tooltip.initialize(),g._invalidate(i),!1!==g.notify(i,"beforeUpdate")){i.tooltip._data=i.data;var a=i.buildOrUpdateControllers();c.each(i.data.datasets,function(t,e){i.getDatasetMeta(e).controller.buildOrUpdateElements()},i),i.updateLayout(),i.options.animation&&i.options.animation.duration&&c.each(a,function(t){t.reset()}),i.updateDatasets(),i.tooltip.initialize(),i.lastActive=[],g.notify(i,"afterUpdate"),i._bufferedRender?i._bufferedRequest={duration:t.duration,easing:t.easing,lazy:t.lazy}:i.render(t)}},updateLayout:function(){!1!==g.notify(this,"beforeLayout")&&(r.update(this,this.width,this.height),g.notify(this,"afterScaleUpdate"),g.notify(this,"afterLayout"))},updateDatasets:function(){if(!1!==g.notify(this,"beforeDatasetsUpdate")){for(var t=0,e=this.data.datasets.length;t=e[t].length&&e[t].push({}),!e[t][a].type||o.type&&o.type!==e[t][a].type?g.merge(e[t][a],[l.getScaleDefaults(r),o]):g.merge(e[t][a],o)}else g._merger(t,e,n,i)}})},g.where=function(t,e){if(g.isArray(t)&&Array.prototype.filter)return t.filter(e);var n=[];return g.each(t,function(t){e(t)&&n.push(t)}),n},g.findIndex=Array.prototype.findIndex?function(t,e,n){return t.findIndex(e,n)}:function(t,e,n){n=void 0===n?t:n;for(var i=0,a=t.length;i=t.length-1?t[0]:t[e+1]:e>=t.length-1?t[t.length-1]:t[e+1]},g.previousItem=function(t,e,n){return n?e<=0?t[t.length-1]:t[e-1]:e<=0?t[0]:t[e-1]},g.niceNum=function(t,e){var n=Math.floor(g.log10(t)),i=t/Math.pow(10,n);return(e?i<1.5?1:i<3?2:i<7?5:10:i<=1?1:i<=2?2:i<=5?5:10)*Math.pow(10,n)},g.requestAnimFrame="undefined"==typeof window?function(t){t()}:window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)},g.getRelativePosition=function(t,e){var n,i,a=t.originalEvent||t,r=t.target||t.srcElement,o=r.getBoundingClientRect(),s=a.touches;i=s&&0n.length){for(var l=0;le&&(e=t.length)}),e},g.color=i?function(t){return t instanceof CanvasGradient&&(t=a.global.defaultColor),i(t)}:function(t){return console.error("Color.js not found!"),t},g.getHoverColor=function(t){return t instanceof CanvasPattern?t:g.color(t).saturate(.5).darken(.1).rgbString()}}},{2:2,26:26,34:34,46:46}],29:[function(t,e,n){"use strict";var i=t(46);function s(t,e){return t.native?{x:t.x,y:t.y}:i.getRelativePosition(t,e)}function l(t,e){var n,i,a,r,o;for(i=0,r=t.data.datasets.length;it.maxHeight){r--;break}r++,l=o*s}t.labelRotation=r},afterCalculateTickRotation:function(){B.callback(this.options.afterCalculateTickRotation,[this])},beforeFit:function(){B.callback(this.options.beforeFit,[this])},fit:function(){var t=this,e=t.minSize={width:0,height:0},n=_(t._ticks),i=t.options,a=i.ticks,r=i.scaleLabel,o=i.gridLines,s=i.display,l=t.isHorizontal(),u=w(a),d=i.gridLines.tickMarkLength;if(e.width=l?t.isFullWidth()?t.maxWidth-t.margins.left-t.margins.right:t.maxWidth:s&&o.drawTicks?d:0,e.height=l?s&&o.drawTicks?d:0:t.maxHeight,r.display&&s){var h=M(r)+B.options.toPadding(r.padding).height;l?e.height+=h:e.width+=h}if(a.display&&s){var c=B.longestText(t.ctx,u.font,n,t.longestTextCache),f=B.numberOfLabelLines(n),g=.5*u.size,m=t.options.ticks.padding;if(l){t.longestLabelWidth=c;var p=B.toRadians(t.labelRotation),v=Math.cos(p),b=Math.sin(p)*c+u.size*f+g*(f-1)+g;e.height=Math.min(t.maxHeight,e.height+b+m),t.ctx.font=u.font;var y=k(t.ctx,n[0],u.font),x=k(t.ctx,n[n.length-1],u.font);0!==t.labelRotation?(t.paddingLeft="bottom"===i.position?v*y+3:v*g+3,t.paddingRight="bottom"===i.position?v*g+3:v*x+3):(t.paddingLeft=y/2+3,t.paddingRight=x/2+3)}else a.mirror?c=0:c+=m+g,e.width=Math.min(t.maxWidth,e.width+c),t.paddingTop=u.size/2,t.paddingBottom=u.size/2}t.handleMargins(),t.width=e.width,t.height=e.height},handleMargins:function(){var t=this;t.margins&&(t.paddingLeft=Math.max(t.paddingLeft-t.margins.left,0),t.paddingTop=Math.max(t.paddingTop-t.margins.top,0),t.paddingRight=Math.max(t.paddingRight-t.margins.right,0),t.paddingBottom=Math.max(t.paddingBottom-t.margins.bottom,0))},afterFit:function(){B.callback(this.options.afterFit,[this])},isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},isFullWidth:function(){return this.options.fullWidth},getRightValue:function(t){if(B.isNullOrUndef(t))return NaN;if("number"==typeof t&&!isFinite(t))return NaN;if(t)if(this.isHorizontal()){if(void 0!==t.x)return this.getRightValue(t.x)}else if(void 0!==t.y)return this.getRightValue(t.y);return t},getLabelForIndex:B.noop,getPixelForValue:B.noop,getValueForPixel:B.noop,getPixelForTick:function(t){var e=this,n=e.options.offset;if(e.isHorizontal()){var i=(e.width-(e.paddingLeft+e.paddingRight))/Math.max(e._ticks.length-(n?0:1),1),a=i*t+e.paddingLeft;n&&(a+=i/2);var r=e.left+Math.round(a);return r+=e.isFullWidth()?e.margins.left:0}var o=e.height-(e.paddingTop+e.paddingBottom);return e.top+t*(o/(e._ticks.length-1))},getPixelForDecimal:function(t){var e=this;if(e.isHorizontal()){var n=(e.width-(e.paddingLeft+e.paddingRight))*t+e.paddingLeft,i=e.left+Math.round(n);return i+=e.isFullWidth()?e.margins.left:0}return e.top+t*e.height},getBasePixel:function(){return this.getPixelForValue(this.getBaseValue())},getBaseValue:function(){var t=this.min,e=this.max;return this.beginAtZero?0:t<0&&e<0?e:0r.width-(r.paddingLeft+r.paddingRight)&&(e=1+Math.floor((h+s.autoSkipPadding)*l/(r.width-(r.paddingLeft+r.paddingRight)))),a&&al.height-e.height&&(h="bottom");var c=(u.left+u.right)/2,f=(u.top+u.bottom)/2;i="center"===h?(n=function(t){return t<=c},function(t){return c=l.width-e.width/2}),a=function(t){return t+e.width+s.caretSize+s.caretPadding>l.width},r=function(t){return t-e.width-s.caretSize-s.caretPadding<0},o=function(t){return t<=f?"top":"bottom"},n(s.x)?(d="left",a(s.x)&&(d="center",h=o(s.y))):i(s.x)&&(d="right",r(s.x)&&(d="center",h=o(s.y)));var g=t._options;return{xAlign:g.xAlign?g.xAlign:d,yAlign:g.yAlign?g.yAlign:h}}(this,T=function(t,e){var n=t._chart.ctx,i=2*e.yPadding,a=0,r=e.body,o=r.reduce(function(t,e){return t+e.before.length+e.lines.length+e.after.length},0);o+=e.beforeBody.length+e.afterBody.length;var s=e.title.length,l=e.footer.length,u=e.titleFontSize,d=e.bodyFontSize,h=e.footerFontSize;i+=s*u,i+=s?(s-1)*e.titleSpacing:0,i+=s?e.titleMarginBottom:0,i+=o*d,i+=o?(o-1)*e.bodySpacing:0,i+=l?e.footerMarginTop:0,i+=l*h,i+=l?(l-1)*e.footerSpacing:0;var c=0,f=function(t){a=Math.max(a,n.measureText(t).width+c)};return n.font=R.fontString(u,e._titleFontStyle,e._titleFontFamily),R.each(e.title,f),n.font=R.fontString(d,e._bodyFontStyle,e._bodyFontFamily),R.each(e.beforeBody.concat(e.afterBody),f),c=e.displayColors?d+2:0,R.each(r,function(t){R.each(t.before,f),R.each(t.lines,f),R.each(t.after,f)}),c=0,n.font=R.fontString(h,e._footerFontStyle,e._footerFontFamily),R.each(e.footer,f),{width:a+=2*e.xPadding,height:i}}(this,M)),i=M,a=T,r=C,o=_._chart,s=i.x,l=i.y,u=i.caretSize,d=i.caretPadding,h=i.cornerRadius,c=r.xAlign,f=r.yAlign,g=u+d,m=h+d,"right"===c?s-=a.width:"center"===c&&((s-=a.width/2)+a.width>o.width&&(s=o.width-a.width),s<0&&(s=0)),"top"===f?l+=g:l-="bottom"===f?a.height+g:a.height/2,"center"===f?"left"===c?s+=g:"right"===c&&(s-=g):"left"===c?s-=m:"right"===c&&(s+=m),P={x:s,y:l}}else M.opacity=0;return M.xAlign=C.xAlign,M.yAlign=C.yAlign,M.x=P.x,M.y=P.y,M.width=T.width,M.height=T.height,M.caretX=O.x,M.caretY=O.y,_._model=M,t&&k.custom&&k.custom.call(_,M),_},drawCaret:function(t,e){var n=this._chart.ctx,i=this._view,a=this.getCaretPosition(t,e,i);n.lineTo(a.x1,a.y1),n.lineTo(a.x2,a.y2),n.lineTo(a.x3,a.y3)},getCaretPosition:function(t,e,n){var i,a,r,o,s,l,u=n.caretSize,d=n.cornerRadius,h=n.xAlign,c=n.yAlign,f=t.x,g=t.y,m=e.width,p=e.height;if("center"===c)s=g+p/2,l="left"===h?(a=(i=f)-u,r=i,o=s+u,s-u):(a=(i=f+m)+u,r=i,o=s-u,s+u);else if(r=(i="left"===h?(a=f+d+u)-u:"right"===h?(a=f+m-d-u)-u:(a=n.caretX)-u,a+u),"top"===c)s=(o=g)-u,l=o;else{s=(o=g+p)+u,l=o;var v=r;r=i,i=v}return{x1:i,x2:a,x3:r,y1:o,y2:s,y3:l}},drawTitle:function(t,e,n,i){var a=e.title;if(a.length){n.textAlign=e._titleAlign,n.textBaseline="top";var r,o,s=e.titleFontSize,l=e.titleSpacing;for(n.fillStyle=c(e.titleFontColor,i),n.font=R.fontString(s,e._titleFontStyle,e._titleFontFamily),r=0,o=a.length;r=n.innerRadius&&r<=n.outerRadius;return l&&u}return!1},getCenterPoint:function(){var t=this._view,e=(t.startAngle+t.endAngle)/2,n=(t.innerRadius+t.outerRadius)/2;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},getArea:function(){var t=this._view;return Math.PI*((t.endAngle-t.startAngle)/(2*Math.PI))*(Math.pow(t.outerRadius,2)-Math.pow(t.innerRadius,2))},tooltipPosition:function(){var t=this._view,e=t.startAngle+(t.endAngle-t.startAngle)/2,n=(t.outerRadius-t.innerRadius)/2+t.innerRadius;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},draw:function(){var t=this._chart.ctx,e=this._view,n=e.startAngle,i=e.endAngle;t.beginPath(),t.arc(e.x,e.y,e.outerRadius,n,i),t.arc(e.x,e.y,e.innerRadius,i,n,!0),t.closePath(),t.strokeStyle=e.borderColor,t.lineWidth=e.borderWidth,t.fillStyle=e.backgroundColor,t.fill(),t.lineJoin="bevel",e.borderWidth&&t.stroke()}})},{26:26,27:27,46:46}],38:[function(t,e,n){"use strict";var i=t(26),a=t(27),d=t(46),h=i.global;i._set("global",{elements:{line:{tension:.4,backgroundColor:h.defaultColor,borderWidth:3,borderColor:h.defaultColor,borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",capBezierPoints:!0,fill:!0}}}),e.exports=a.extend({draw:function(){var t,e,n,i,a=this._view,r=this._chart.ctx,o=a.spanGaps,s=this._children.slice(),l=h.elements.line,u=-1;for(this._loop&&s.length&&s.push(s[0]),r.save(),r.lineCap=a.borderCapStyle||l.borderCapStyle,r.setLineDash&&r.setLineDash(a.borderDash||l.borderDash),r.lineDashOffset=a.borderDashOffset||l.borderDashOffset,r.lineJoin=a.borderJoinStyle||l.borderJoinStyle,r.lineWidth=a.borderWidth||l.borderWidth,r.strokeStyle=a.borderColor||h.defaultColor,r.beginPath(),u=-1,t=0;t=t.left&&1.01*t.right>=n.x&&n.y>=t.top&&1.01*t.bottom>=n.y)&&(i.strokeStyle=e.borderColor||h,i.lineWidth=d.valueOrDefault(e.borderWidth,u.global.elements.point.borderWidth),i.fillStyle=e.backgroundColor||h,d.canvas.drawPoint(i,a,o,s,l,r))}})},{26:26,27:27,46:46}],40:[function(t,e,n){"use strict";var i=t(26),a=t(27);function l(t){return void 0!==t._view.width}function r(t){var e,n,i,a,r=t._view;if(l(t)){var o=r.width/2;e=r.x-o,n=r.x+o,i=Math.min(r.y,r.base),a=Math.max(r.y,r.base)}else{var s=r.height/2;e=Math.min(r.x,r.base),n=Math.max(r.x,r.base),i=r.y-s,a=r.y+s}return{left:e,top:i,right:n,bottom:a}}i._set("global",{elements:{rectangle:{backgroundColor:i.global.defaultColor,borderColor:i.global.defaultColor,borderSkipped:"bottom",borderWidth:0}}}),e.exports=a.extend({draw:function(){var t,e,n,i,a,r,o,s=this._chart.ctx,l=this._view,u=l.borderWidth;if(o=l.horizontal?(t=l.base,e=l.x,n=l.y-l.height/2,i=l.y+l.height/2,a=t=i.left&&t<=i.right&&e>=i.top&&e<=i.bottom}return n},inLabelRange:function(t,e){if(!this._view)return!1;var n=r(this);return l(this)?t>=n.left&&t<=n.right:e>=n.top&&e<=n.bottom},inXRange:function(t){var e=r(this);return t>=e.left&&t<=e.right},inYRange:function(t){var e=r(this);return t>=e.top&&t<=e.bottom},getCenterPoint:function(){var t,e,n=this._view;return e=l(this)?(t=n.x,(n.y+n.base)/2):(t=(n.x+n.base)/2,n.y),{x:t,y:e}},getArea:function(){var t=this._view;return t.width*Math.abs(t.y-t.base)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y}}})},{26:26,27:27}],41:[function(t,e,n){"use strict";e.exports={},e.exports.Arc=t(37),e.exports.Line=t(38),e.exports.Point=t(39),e.exports.Rectangle=t(40)},{37:37,38:38,39:39,40:40}],42:[function(t,e,n){"use strict";var i=t(43);n=e.exports={clear:function(t){t.ctx.clearRect(0,0,t.width,t.height)},roundedRect:function(t,e,n,i,a,r){if(r){var o=Math.min(r,a/2-1e-7,i/2-1e-7);t.moveTo(e+o,n),t.lineTo(e+i-o,n),t.arcTo(e+i,n,e+i,n+o,o),t.lineTo(e+i,n+a-o),t.arcTo(e+i,n+a,e+i-o,n+a,o),t.lineTo(e+o,n+a),t.arcTo(e,n+a,e,n+a-o,o),t.lineTo(e,n+o),t.arcTo(e,n,e+o,n,o),t.closePath(),t.moveTo(e,n)}else t.rect(e,n,i,a)},drawPoint:function(t,e,n,i,a,r){var o,s,l,u,d,h;if(r=r||0,!e||"object"!=typeof e||"[object HTMLImageElement]"!==(o=e.toString())&&"[object HTMLCanvasElement]"!==o){if(!(isNaN(n)||n<=0)){switch(t.save(),t.translate(i,a),t.rotate(r*Math.PI/180),t.beginPath(),e){default:t.arc(0,0,n,0,2*Math.PI),t.closePath();break;case"triangle":d=(s=3*n/Math.sqrt(3))*Math.sqrt(3)/2,t.moveTo(-s/2,d/3),t.lineTo(s/2,d/3),t.lineTo(0,-2*d/3),t.closePath();break;case"rect":h=1/Math.SQRT2*n,t.rect(-h,-h,2*h,2*h);break;case"rectRounded":var c=n/Math.SQRT2,f=-c,g=-c,m=Math.SQRT2*n;this.roundedRect(t,f,g,m,m,.425*n);break;case"rectRot":h=1/Math.SQRT2*n,t.moveTo(-h,0),t.lineTo(0,h),t.lineTo(h,0),t.lineTo(0,-h),t.closePath();break;case"cross":t.moveTo(0,n),t.lineTo(0,-n),t.moveTo(-n,0),t.lineTo(n,0);break;case"crossRot":l=Math.cos(Math.PI/4)*n,u=Math.sin(Math.PI/4)*n,t.moveTo(-l,-u),t.lineTo(l,u),t.moveTo(-l,u),t.lineTo(l,-u);break;case"star":t.moveTo(0,n),t.lineTo(0,-n),t.moveTo(-n,0),t.lineTo(n,0),l=Math.cos(Math.PI/4)*n,u=Math.sin(Math.PI/4)*n,t.moveTo(-l,-u),t.lineTo(l,u),t.moveTo(-l,u),t.lineTo(l,-u);break;case"line":t.moveTo(-n,0),t.lineTo(n,0);break;case"dash":t.moveTo(0,0),t.lineTo(n,0)}t.fill(),t.stroke(),t.restore()}}else t.drawImage(e,i-e.width/2,a-e.height/2,e.width,e.height)},clipArea:function(t,e){t.save(),t.beginPath(),t.rect(e.left,e.top,e.right-e.left,e.bottom-e.top),t.clip()},unclipArea:function(t){t.restore()},lineTo:function(t,e,n,i){if(n.steppedLine)return"after"===n.steppedLine&&!i||"after"!==n.steppedLine&&i?t.lineTo(e.x,n.y):t.lineTo(n.x,e.y),void t.lineTo(n.x,n.y);n.tension?t.bezierCurveTo(i?e.controlPointPreviousX:e.controlPointNextX,i?e.controlPointPreviousY:e.controlPointNextY,i?n.controlPointNextX:n.controlPointPreviousX,i?n.controlPointNextY:n.controlPointPreviousY,n.x,n.y):t.lineTo(n.x,n.y)}};i.clear=n.clear,i.drawRoundedRectangle=function(t){t.beginPath(),n.roundedRect.apply(n,arguments)}},{43:43}],43:[function(t,e,n){"use strict";var i,d={noop:function(){},uid:(i=0,function(){return i++}),isNullOrUndef:function(t){return null==t},isArray:Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)},isObject:function(t){return null!==t&&"[object Object]"===Object.prototype.toString.call(t)},valueOrDefault:function(t,e){return void 0===t?e:t},valueAtIndexOrDefault:function(t,e,n){return d.valueOrDefault(d.isArray(t)?t[e]:t,n)},callback:function(t,e,n){if(t&&"function"==typeof t.call)return t.apply(n,e)},each:function(t,e,n,i){var a,r,o;if(d.isArray(t))if(r=t.length,i)for(a=r-1;0<=a;a--)e.call(n,t[a],a);else for(a=0;a
';var a=e.childNodes[0],r=e.childNodes[1];e._reset=function(){a.scrollLeft=1e6,a.scrollTop=1e6,r.scrollLeft=1e6,r.scrollTop=1e6};var o=function(){e._reset(),t()};return y(a,"scroll",o.bind(a,"expand")),y(r,"scroll",o.bind(r,"shrink")),e}((r=!(i=function(){if(h.resizer)return t(x("resize",n))}),o=[],function(){o=Array.prototype.slice.call(arguments),a=a||this,r||(r=!0,f.requestAnimFrame.call(window,function(){r=!1,i.apply(a,o)}))}));l=function(){if(h.resizer){var t=e.parentNode;t&&t!==c.parentNode&&t.insertBefore(c,t.firstChild),c._reset()}},u=(s=e)[g]||(s[g]={}),d=u.renderProxy=function(t){t.animationName===v&&l()},f.each(b,function(t){y(s,t,d)}),u.reflow=!!s.offsetParent,s.classList.add(p)}function r(t){var e,n,i,a=t[g]||{},r=a.resizer;delete a.resizer,n=(e=t)[g]||{},(i=n.renderProxy)&&(f.each(b,function(t){o(e,t,i)}),delete n.renderProxy),e.classList.remove(p),r&&r.parentNode&&r.parentNode.removeChild(r)}e.exports={_enabled:"undefined"!=typeof window&&"undefined"!=typeof document,initialize:function(){var t,e,n,i="from{opacity:0.99}to{opacity:1}";e="@-webkit-keyframes "+v+"{"+i+"}@keyframes "+v+"{"+i+"}."+p+"{-webkit-animation:"+v+" 0.001s;animation:"+v+" 0.001s;}",n=(t=this)._style||document.createElement("style"),t._style||(e="/* Chart.js */\n"+e,(t._style=n).setAttribute("type","text/css"),document.getElementsByTagName("head")[0].appendChild(n)),n.appendChild(document.createTextNode(e))},acquireContext:function(t,e){"string"==typeof t?t=document.getElementById(t):t.length&&(t=t[0]),t&&t.canvas&&(t=t.canvas);var n=t&&t.getContext&&t.getContext("2d");return n&&n.canvas===t?(function(t,e){var n=t.style,i=t.getAttribute("height"),a=t.getAttribute("width");if(t[g]={initial:{height:i,width:a,style:{display:n.display,height:n.height,width:n.width}}},n.display=n.display||"block",null===a||""===a){var r=l(t,"width");void 0!==r&&(t.width=r)}if(null===i||""===i)if(""===t.style.height)t.height=t.width/(e.options.aspectRatio||2);else{var o=l(t,"height");void 0!==r&&(t.height=o)}}(t,e),n):null},releaseContext:function(t){var n=t.canvas;if(n[g]){var i=n[g].initial;["height","width"].forEach(function(t){var e=i[t];f.isNullOrUndef(e)?n.removeAttribute(t):n.setAttribute(t,e)}),f.each(i.style||{},function(t,e){n.style[e]=t}),n.width=n.width,delete n[g]}},addEventListener:function(r,t,o){var e=r.canvas;if("resize"!==t){var n=o[g]||(o[g]={});y(e,t,(n.proxies||(n.proxies={}))[r.id+"_"+t]=function(t){var e,n,i,a;o((n=r,i=s[(e=t).type]||e.type,a=f.getRelativePosition(e,n),x(i,n,a.x,a.y,e)))})}else a(e,o,r)},removeEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var a=((n[g]||{}).proxies||{})[t.id+"_"+e];a&&o(i,e,a)}else r(i)}},f.addEvent=y,f.removeEvent=o},{46:46}],49:[function(t,e,n){"use strict";var i=t(46),a=t(47),r=t(48),o=r._enabled?r:a;e.exports=i.extend({initialize:function(){},acquireContext:function(){},releaseContext:function(){},addEventListener:function(){},removeEventListener:function(){}},o)},{46:46,47:47,48:48}],50:[function(t,e,n){"use strict";e.exports={},e.exports.filler=t(51),e.exports.legend=t(52),e.exports.title=t(53)},{51:51,52:52,53:53}],51:[function(t,e,n){"use strict";var u=t(26),c=t(41),d=t(46);u._set("global",{plugins:{filler:{propagate:!0}}});var f={dataset:function(t){var e=t.fill,n=t.chart,i=n.getDatasetMeta(e),a=i&&n.isDatasetVisible(e)&&i.dataset._children||[],r=a.length||0;return r?function(t,e){return e');for(var n=0;n'),t.data.datasets[n].label&&e.push(t.data.datasets[n].label),e.push("");return e.push(""),e.join("")}});var o=i.extend({initialize:function(t){C.extend(this,t),this.legendHitBoxes=[],this.doughnutMode=!1},beforeUpdate:r,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:r,beforeSetDimensions:r,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:r,beforeBuildLabels:r,buildLabels:function(){var e=this,n=e.options.labels||{},t=C.callback(n.generateLabels,[e.chart],e)||[];n.filter&&(t=t.filter(function(t){return n.filter(t,e.chart.data)})),e.options.reverse&&t.reverse(),e.legendItems=t},afterBuildLabels:r,beforeFit:r,fit:function(){var i=this,t=i.options,a=t.labels,e=t.display,r=i.ctx,n=D.global,o=C.valueOrDefault,s=o(a.fontSize,n.defaultFontSize),l=o(a.fontStyle,n.defaultFontStyle),u=o(a.fontFamily,n.defaultFontFamily),d=C.fontString(s,l,u),h=i.legendHitBoxes=[],c=i.minSize,f=i.isHorizontal();if(c.height=f?(c.width=i.maxWidth,e?10:0):(c.width=e?10:0,i.maxHeight),e)if(r.font=d,f){var g=i.lineWidths=[0],m=i.legendItems.length?s+a.padding:0;r.textAlign="left",r.textBaseline="top",C.each(i.legendItems,function(t,e){var n=P(a,s)+s/2+r.measureText(t.text).width;g[g.length-1]+n+a.padding>=i.width&&(m+=s+a.padding,g[g.length]=i.left),h[e]={left:0,top:0,width:n,height:s},g[g.length-1]+=n+a.padding}),c.height+=m}else{var p=a.padding,v=i.columnWidths=[],b=a.padding,y=0,x=0,_=s+p;C.each(i.legendItems,function(t,e){var n=P(a,s)+s/2+r.measureText(t.text).width;x+_>c.height&&(b+=y+a.padding,v.push(y),x=y=0),y=Math.max(y,n),x+=_,h[e]={left:0,top:0,width:n,height:s}}),b+=y,v.push(y),c.width+=b}i.width=c.width,i.height=c.height},afterFit:r,isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},draw:function(){var h=this,c=h.options,f=c.labels,g=D.global,m=g.elements.line,p=h.width,v=h.lineWidths;if(c.display){var b,y=h.ctx,x=C.valueOrDefault,t=x(f.fontColor,g.defaultFontColor),_=x(f.fontSize,g.defaultFontSize),e=x(f.fontStyle,g.defaultFontStyle),n=x(f.fontFamily,g.defaultFontFamily),i=C.fontString(_,e,n);y.textAlign="left",y.textBaseline="middle",y.lineWidth=.5,y.strokeStyle=t,y.fillStyle=t,y.font=i;var k=P(f,_),w=h.legendHitBoxes,M=h.isHorizontal();b=M?{x:h.left+(p-v[0])/2,y:h.top+f.padding,line:0}:{x:h.left+f.padding,y:h.top+f.padding,line:0};var S=_+f.padding;C.each(h.legendItems,function(t,e){var n,i,a,r,o,s=y.measureText(t.text).width,l=k+_/2+s,u=b.x,d=b.y;M?p<=u+l&&(d=b.y+=S,b.line++,u=b.x=h.left+(p-v[b.line])/2):d+S>h.bottom&&(u=b.x=u+h.columnWidths[b.line]+f.padding,d=b.y=h.top+f.padding,b.line++),function(t,e,n){if(!(isNaN(k)||k<=0)){y.save(),y.fillStyle=x(n.fillStyle,g.defaultColor),y.lineCap=x(n.lineCap,m.borderCapStyle),y.lineDashOffset=x(n.lineDashOffset,m.borderDashOffset),y.lineJoin=x(n.lineJoin,m.borderJoinStyle),y.lineWidth=x(n.lineWidth,m.borderWidth),y.strokeStyle=x(n.strokeStyle,g.defaultColor);var i=0===x(n.lineWidth,m.borderWidth);if(y.setLineDash&&y.setLineDash(x(n.lineDash,m.borderDash)),c.labels&&c.labels.usePointStyle){var a=_*Math.SQRT2/2,r=a/Math.SQRT2,o=t+r,s=e+r;C.canvas.drawPoint(y,n.pointStyle,a,o,s)}else i||y.strokeRect(t,e,k,_),y.fillRect(t,e,k,_);y.restore()}}(u,d,t),w[e].left=u,w[e].top=d,n=t,i=s,r=k+(a=_/2)+u,o=d+a,y.fillText(n.text,r,o),n.hidden&&(y.beginPath(),y.lineWidth=2,y.moveTo(r,o),y.lineTo(r+i,o),y.stroke()),M?b.x+=l+f.padding:b.y+=S})}},handleEvent:function(t){var e=this,n=e.options,i="mouseup"===t.type?"click":t.type,a=!1;if("mousemove"===i){if(!n.onHover)return}else{if("click"!==i)return;if(!n.onClick)return}var r=t.x,o=t.y;if(r>=e.left&&r<=e.right&&o>=e.top&&o<=e.bottom)for(var s=e.legendHitBoxes,l=0;l=u.left&&r<=u.left+u.width&&o>=u.top&&o<=u.top+u.height){if("click"===i){n.onClick.call(e,t.native,e.legendItems[l]),a=!0;break}if("mousemove"===i){n.onHover.call(e,t.native,e.legendItems[l]),a=!0;break}}}return a}});function s(t,e){var n=new o({ctx:t.ctx,options:e,chart:t});a.configure(t,n,e),a.addBox(t,n),t.legend=n}e.exports={id:"legend",_element:o,beforeInit:function(t){var e=t.options.legend;e&&s(t,e)},beforeUpdate:function(t){var e=t.options.legend,n=t.legend;e?(C.mergeIf(e,D.global.legend),n?(a.configure(t,n,e),n.options=e):s(t,e)):n&&(a.removeBox(t,n),delete t.legend)},afterEvent:function(t,e){var n=t.legend;n&&n.handleEvent(e)}}},{26:26,27:27,31:31,46:46}],53:[function(t,e,n){"use strict";var _=t(26),i=t(27),k=t(46),a=t(31),r=k.noop;_._set("global",{title:{display:!1,fontStyle:"bold",fullWidth:!0,lineHeight:1.2,padding:10,position:"top",text:"",weight:2e3}});var o=i.extend({initialize:function(t){k.extend(this,t),this.legendHitBoxes=[]},beforeUpdate:r,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:r,beforeSetDimensions:r,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:r,beforeBuildLabels:r,buildLabels:r,afterBuildLabels:r,beforeFit:r,fit:function(){var t=k.valueOrDefault,e=this.options,n=e.display,i=t(e.fontSize,_.global.defaultFontSize),a=this.minSize,r=k.isArray(e.text)?e.text.length:1,o=k.options.toLineHeight(e.lineHeight,i),s=n?r*o+2*e.padding:0;this.isHorizontal()?(a.width=this.maxWidth,a.height=s):(a.width=s,a.height=this.maxHeight),this.width=a.width,this.height=a.height},afterFit:r,isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},draw:function(){var t=this.ctx,e=k.valueOrDefault,n=this.options,i=_.global;if(n.display){var a,r,o,s=e(n.fontSize,i.defaultFontSize),l=e(n.fontStyle,i.defaultFontStyle),u=e(n.fontFamily,i.defaultFontFamily),d=k.fontString(s,l,u),h=k.options.toLineHeight(n.lineHeight,s),c=h/2+n.padding,f=0,g=this.top,m=this.left,p=this.bottom,v=this.right;t.fillStyle=e(n.fontColor,i.defaultFontColor),t.font=d,this.isHorizontal()?(r=m+(v-m)/2,o=g+c,a=v-m):(r="left"===n.position?m+c:v-c,o=g+(p-g)/2,a=p-g,f=Math.PI*("left"===n.position?-.5:.5)),t.save(),t.translate(r,o),t.rotate(f),t.textAlign="center",t.textBaseline="middle";var b=n.text;if(k.isArray(b))for(var y=0,x=0;xo.max&&(o.max=n))})});o.min=isFinite(o.min)&&!isNaN(o.min)?o.min:0,o.max=isFinite(o.max)&&!isNaN(o.max)?o.max:1,this.handleTickRangeOptions()},getTickLimit:function(){var t,e=this.options.ticks;if(this.isHorizontal())t=Math.min(e.maxTicksLimit?e.maxTicksLimit:11,Math.ceil(this.width/50));else{var n=h.valueOrDefault(e.fontSize,i.global.defaultFontSize);t=Math.min(e.maxTicksLimit?e.maxTicksLimit:11,Math.ceil(this.height/(2*n)))}return t},handleDirectionalChanges:function(){this.isHorizontal()||this.ticks.reverse()},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForValue:function(t){var e=this.start,n=+this.getRightValue(t),i=this.end-e;return this.isHorizontal()?this.left+this.width/i*(n-e):this.bottom-this.height/i*(n-e)},getValueForPixel:function(t){var e=this.isHorizontal(),n=e?this.width:this.height,i=(e?t-this.left:this.bottom-t)/n;return this.start+(this.end-this.start)*i},getPixelForTick:function(t){return this.getPixelForValue(this.ticksAsNumbers[t])}});a.registerScaleType("linear",n,e)}},{26:26,34:34,35:35,46:46}],56:[function(t,e,n){"use strict";var h=t(46),i=t(33);e.exports=function(t){var e=h.noop;t.LinearScaleBase=i.extend({getRightValue:function(t){return"string"==typeof t?+t:i.prototype.getRightValue.call(this,t)},handleTickRangeOptions:function(){var t=this,e=t.options.ticks;if(e.beginAtZero){var n=h.sign(t.min),i=h.sign(t.max);n<0&&i<0?t.max=0:0=t.max&&(a?t.max=t.min+1:t.min=t.max-1),t.min===t.max&&(t.max++,e.beginAtZero||t.min--)},getTickLimit:e,handleDirectionalChanges:e,buildTicks:function(){var t=this,e=t.options.ticks,n=t.getTickLimit(),i={maxTicks:n=Math.max(2,n),min:e.min,max:e.max,precision:e.precision,stepSize:h.valueOrDefault(e.fixedStepSize,e.stepSize)},a=t.ticks=function(t,e){var n,i,a,r=[];if(t.stepSize&&0o.max&&(o.max=n),0!==n&&(null===o.minNotZero||no.r&&(o.r=g.end,s.r=c),m.starto.b&&(o.b=m.end,s.b=c)}t.setReductions(r,o,s)}(this):(t=this,e=Math.min(t.height/2,t.width/2),t.drawingArea=Math.round(e),t.setCenterPoint(0,0,0,0))},setReductions:function(t,e,n){var i=e.l/Math.sin(n.l),a=Math.max(e.r-this.width,0)/Math.sin(n.r),r=-e.t/Math.cos(n.t),o=-Math.max(e.b-this.height,0)/Math.cos(n.b);i=s(i),a=s(a),r=s(r),o=s(o),this.drawingArea=Math.min(Math.round(t-(i+a)/2),Math.round(t-(r+o)/2)),this.setCenterPoint(i,a,r,o)},setCenterPoint:function(t,e,n,i){var a=this,r=a.width-e-a.drawingArea,o=t+a.drawingArea,s=n+a.drawingArea,l=a.height-i-a.drawingArea;a.xCenter=Math.round((o+r)/2+a.left),a.yCenter=Math.round((s+l)/2+a.top)},getIndexAngle:function(t){return t*(2*Math.PI/b(this))+(this.chart.options&&this.chart.options.startAngle?this.chart.options.startAngle:0)*Math.PI*2/360},getDistanceFromCenterForValue:function(t){if(null===t)return 0;var e=this.drawingArea/(this.max-this.min);return this.options.ticks.reverse?(this.max-t)*e:(t-this.min)*e},getPointPosition:function(t,e){var n=this.getIndexAngle(t)-Math.PI/2;return{x:Math.round(Math.cos(n)*e)+this.xCenter,y:Math.round(Math.sin(n)*e)+this.yCenter}},getPointPositionForValue:function(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))},getBasePosition:function(){var t=this.min,e=this.max;return this.getPointPositionForValue(0,this.beginAtZero?0:t<0&&e<0?e:0>1)-1]||null,r=t[i],!a)return{lo:null,hi:r};if(r[e]n))return{lo:a,hi:r};s=i-1}}return{lo:r,hi:null}}(t,e,n),r=a.lo?a.hi?a.lo:t[t.length-2]:t[0],o=a.lo?a.hi?a.hi:t[t.length-1]:t[1],s=o[e]-r[e],l=s?(n-r[e])/s:0,u=(o[i]-r[i])*l;return r[i]+u}function M(t,e){var n=e.parser,i=e.parser||e.format;return"function"==typeof n?n(t):"string"==typeof t&&"string"==typeof i?y(t,i):(t instanceof y||(t=y(t)),t.isValid()?t:"function"==typeof i?i(t):t)}function S(t,e){if(p.isNullOrUndef(t))return null;var n=e.options.time,i=M(e.getRightValue(t),n);return i.isValid()?(n.round&&i.startOf(n.round),i.valueOf()):null}function D(t){for(var e=_.indexOf(t)+1,n=_.length;e=_.indexOf(e);a--)if(r=_[a],x[r].common&&o.as(r)>=t.length)return r;return _[e?_.indexOf(e):0]}(b,p.minUnit,c.min,c.max),c._majorUnit=D(c._unit),c._table=function(t,e,n,i){if("linear"===i||!t.length)return[{time:e,pos:0},{time:n,pos:1}];var a,r,o,s,l,u=[],d=[e];for(a=0,r=t.length;a=0&&n0&&t-1 in e)}var E=function(e){var t,n,r,i,o,a,s,u,l,c,f,p,d,h,g,y,v,m,x,b="sizzle"+1*new Date,w=e.document,T=0,C=0,E=ae(),k=ae(),S=ae(),D=function(e,t){return e===t&&(f=!0),0},N={}.hasOwnProperty,A=[],j=A.pop,q=A.push,L=A.push,H=A.slice,O=function(e,t){for(var n=0,r=e.length;n+~]|"+M+")"+M+"*"),z=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),X=new RegExp(W),U=new RegExp("^"+R+"$"),V={ID:new RegExp("^#("+R+")"),CLASS:new RegExp("^\\.("+R+")"),TAG:new RegExp("^("+R+"|[*])"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+W),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+P+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},G=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Q=/^[^{]+\{\s*\[native \w/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,K=/[+~]/,Z=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ee=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},te=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ne=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},re=function(){p()},ie=me(function(e){return!0===e.disabled&&("form"in e||"label"in e)},{dir:"parentNode",next:"legend"});try{L.apply(A=H.call(w.childNodes),w.childNodes),A[w.childNodes.length].nodeType}catch(e){L={apply:A.length?function(e,t){q.apply(e,H.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function oe(e,t,r,i){var o,s,l,c,f,h,v,m=t&&t.ownerDocument,T=t?t.nodeType:9;if(r=r||[],"string"!=typeof e||!e||1!==T&&9!==T&&11!==T)return r;if(!i&&((t?t.ownerDocument||t:w)!==d&&p(t),t=t||d,g)){if(11!==T&&(f=J.exec(e)))if(o=f[1]){if(9===T){if(!(l=t.getElementById(o)))return r;if(l.id===o)return r.push(l),r}else if(m&&(l=m.getElementById(o))&&x(t,l)&&l.id===o)return r.push(l),r}else{if(f[2])return L.apply(r,t.getElementsByTagName(e)),r;if((o=f[3])&&n.getElementsByClassName&&t.getElementsByClassName)return L.apply(r,t.getElementsByClassName(o)),r}if(n.qsa&&!S[e+" "]&&(!y||!y.test(e))){if(1!==T)m=t,v=e;else if("object"!==t.nodeName.toLowerCase()){(c=t.getAttribute("id"))?c=c.replace(te,ne):t.setAttribute("id",c=b),s=(h=a(e)).length;while(s--)h[s]="#"+c+" "+ve(h[s]);v=h.join(","),m=K.test(e)&&ge(t.parentNode)||t}if(v)try{return L.apply(r,m.querySelectorAll(v)),r}catch(e){}finally{c===b&&t.removeAttribute("id")}}}return u(e.replace(B,"$1"),t,r,i)}function ae(){var e=[];function t(n,i){return e.push(n+" ")>r.cacheLength&&delete t[e.shift()],t[n+" "]=i}return t}function se(e){return e[b]=!0,e}function ue(e){var t=d.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function le(e,t){var n=e.split("|"),i=n.length;while(i--)r.attrHandle[n[i]]=t}function ce(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function fe(e){return function(t){return"input"===t.nodeName.toLowerCase()&&t.type===e}}function pe(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function de(e){return function(t){return"form"in t?t.parentNode&&!1===t.disabled?"label"in t?"label"in t.parentNode?t.parentNode.disabled===e:t.disabled===e:t.isDisabled===e||t.isDisabled!==!e&&ie(t)===e:t.disabled===e:"label"in t&&t.disabled===e}}function he(e){return se(function(t){return t=+t,se(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function ge(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}n=oe.support={},o=oe.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},p=oe.setDocument=function(e){var t,i,a=e?e.ownerDocument||e:w;return a!==d&&9===a.nodeType&&a.documentElement?(d=a,h=d.documentElement,g=!o(d),w!==d&&(i=d.defaultView)&&i.top!==i&&(i.addEventListener?i.addEventListener("unload",re,!1):i.attachEvent&&i.attachEvent("onunload",re)),n.attributes=ue(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ue(function(e){return e.appendChild(d.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=Q.test(d.getElementsByClassName),n.getById=ue(function(e){return h.appendChild(e).id=b,!d.getElementsByName||!d.getElementsByName(b).length}),n.getById?(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){return e.getAttribute("id")===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n=t.getElementById(e);return n?[n]:[]}}):(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){var n="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),r.find.TAG=n.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):n.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},r.find.CLASS=n.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&g)return t.getElementsByClassName(e)},v=[],y=[],(n.qsa=Q.test(d.querySelectorAll))&&(ue(function(e){h.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+P+")"),e.querySelectorAll("[id~="+b+"-]").length||y.push("~="),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+b+"+*").length||y.push(".#.+[+~]")}),ue(function(e){e.innerHTML="";var t=d.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),h.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(n.matchesSelector=Q.test(m=h.matches||h.webkitMatchesSelector||h.mozMatchesSelector||h.oMatchesSelector||h.msMatchesSelector))&&ue(function(e){n.disconnectedMatch=m.call(e,"*"),m.call(e,"[s!='']:x"),v.push("!=",W)}),y=y.length&&new RegExp(y.join("|")),v=v.length&&new RegExp(v.join("|")),t=Q.test(h.compareDocumentPosition),x=t||Q.test(h.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return f=!0,0;var r=!e.compareDocumentPosition-!t.compareDocumentPosition;return r||(1&(r=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!n.sortDetached&&t.compareDocumentPosition(e)===r?e===d||e.ownerDocument===w&&x(w,e)?-1:t===d||t.ownerDocument===w&&x(w,t)?1:c?O(c,e)-O(c,t):0:4&r?-1:1)}:function(e,t){if(e===t)return f=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===d?-1:t===d?1:i?-1:o?1:c?O(c,e)-O(c,t):0;if(i===o)return ce(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?ce(a[r],s[r]):a[r]===w?-1:s[r]===w?1:0},d):d},oe.matches=function(e,t){return oe(e,null,null,t)},oe.matchesSelector=function(e,t){if((e.ownerDocument||e)!==d&&p(e),t=t.replace(z,"='$1']"),n.matchesSelector&&g&&!S[t+" "]&&(!v||!v.test(t))&&(!y||!y.test(t)))try{var r=m.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(e){}return oe(t,d,null,[e]).length>0},oe.contains=function(e,t){return(e.ownerDocument||e)!==d&&p(e),x(e,t)},oe.attr=function(e,t){(e.ownerDocument||e)!==d&&p(e);var i=r.attrHandle[t.toLowerCase()],o=i&&N.call(r.attrHandle,t.toLowerCase())?i(e,t,!g):void 0;return void 0!==o?o:n.attributes||!g?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null},oe.escape=function(e){return(e+"").replace(te,ne)},oe.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},oe.uniqueSort=function(e){var t,r=[],i=0,o=0;if(f=!n.detectDuplicates,c=!n.sortStable&&e.slice(0),e.sort(D),f){while(t=e[o++])t===e[o]&&(i=r.push(o));while(i--)e.splice(r[i],1)}return c=null,e},i=oe.getText=function(e){var t,n="",r=0,o=e.nodeType;if(o){if(1===o||9===o||11===o){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=i(e)}else if(3===o||4===o)return e.nodeValue}else while(t=e[r++])n+=i(t);return n},(r=oe.selectors={cacheLength:50,createPseudo:se,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(Z,ee),e[3]=(e[3]||e[4]||e[5]||"").replace(Z,ee),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||oe.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&oe.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return V.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=a(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(Z,ee).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=E[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&E(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=oe.attr(r,e);return null==i?"!="===t:!t||(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i.replace($," ")+" ").indexOf(n)>-1:"|="===t&&(i===n||i.slice(0,n.length+1)===n+"-"))}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,p,d,h,g=o!==a?"nextSibling":"previousSibling",y=t.parentNode,v=s&&t.nodeName.toLowerCase(),m=!u&&!s,x=!1;if(y){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===v:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?y.firstChild:y.lastChild],a&&m){x=(d=(l=(c=(f=(p=y)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1])&&l[2],p=d&&y.childNodes[d];while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if(1===p.nodeType&&++x&&p===t){c[e]=[T,d,x];break}}else if(m&&(x=d=(l=(c=(f=(p=t)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1]),!1===x)while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===v:1===p.nodeType)&&++x&&(m&&((c=(f=p[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]=[T,x]),p===t))break;return(x-=i)===r||x%r==0&&x/r>=0}}},PSEUDO:function(e,t){var n,i=r.pseudos[e]||r.setFilters[e.toLowerCase()]||oe.error("unsupported pseudo: "+e);return i[b]?i(t):i.length>1?(n=[e,e,"",t],r.setFilters.hasOwnProperty(e.toLowerCase())?se(function(e,n){var r,o=i(e,t),a=o.length;while(a--)e[r=O(e,o[a])]=!(n[r]=o[a])}):function(e){return i(e,0,n)}):i}},pseudos:{not:se(function(e){var t=[],n=[],r=s(e.replace(B,"$1"));return r[b]?se(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),t[0]=null,!n.pop()}}),has:se(function(e){return function(t){return oe(e,t).length>0}}),contains:se(function(e){return e=e.replace(Z,ee),function(t){return(t.textContent||t.innerText||i(t)).indexOf(e)>-1}}),lang:se(function(e){return U.test(e||"")||oe.error("unsupported lang: "+e),e=e.replace(Z,ee).toLowerCase(),function(t){var n;do{if(n=g?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return(n=n.toLowerCase())===e||0===n.indexOf(e+"-")}while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===h},focus:function(e){return e===d.activeElement&&(!d.hasFocus||d.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:de(!1),disabled:de(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!r.pseudos.empty(e)},header:function(e){return Y.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:he(function(){return[0]}),last:he(function(e,t){return[t-1]}),eq:he(function(e,t,n){return[n<0?n+t:n]}),even:he(function(e,t){for(var n=0;n=0;)e.push(r);return e}),gt:he(function(e,t,n){for(var r=n<0?n+t:n;++r1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function be(e,t,n){for(var r=0,i=t.length;r-1&&(o[l]=!(a[l]=f))}}else v=we(v===a?v.splice(h,v.length):v),i?i(null,a,v,u):L.apply(a,v)})}function Ce(e){for(var t,n,i,o=e.length,a=r.relative[e[0].type],s=a||r.relative[" "],u=a?1:0,c=me(function(e){return e===t},s,!0),f=me(function(e){return O(t,e)>-1},s,!0),p=[function(e,n,r){var i=!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):f(e,n,r));return t=null,i}];u1&&xe(p),u>1&&ve(e.slice(0,u-1).concat({value:" "===e[u-2].type?"*":""})).replace(B,"$1"),n,u0,i=e.length>0,o=function(o,a,s,u,c){var f,h,y,v=0,m="0",x=o&&[],b=[],w=l,C=o||i&&r.find.TAG("*",c),E=T+=null==w?1:Math.random()||.1,k=C.length;for(c&&(l=a===d||a||c);m!==k&&null!=(f=C[m]);m++){if(i&&f){h=0,a||f.ownerDocument===d||(p(f),s=!g);while(y=e[h++])if(y(f,a||d,s)){u.push(f);break}c&&(T=E)}n&&((f=!y&&f)&&v--,o&&x.push(f))}if(v+=m,n&&m!==v){h=0;while(y=t[h++])y(x,b,a,s);if(o){if(v>0)while(m--)x[m]||b[m]||(b[m]=j.call(u));b=we(b)}L.apply(u,b),c&&!o&&b.length>0&&v+t.length>1&&oe.uniqueSort(u)}return c&&(T=E,l=w),x};return n?se(o):o}return s=oe.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=a(e)),n=t.length;while(n--)(o=Ce(t[n]))[b]?r.push(o):i.push(o);(o=S(e,Ee(i,r))).selector=e}return o},u=oe.select=function(e,t,n,i){var o,u,l,c,f,p="function"==typeof e&&e,d=!i&&a(e=p.selector||e);if(n=n||[],1===d.length){if((u=d[0]=d[0].slice(0)).length>2&&"ID"===(l=u[0]).type&&9===t.nodeType&&g&&r.relative[u[1].type]){if(!(t=(r.find.ID(l.matches[0].replace(Z,ee),t)||[])[0]))return n;p&&(t=t.parentNode),e=e.slice(u.shift().value.length)}o=V.needsContext.test(e)?0:u.length;while(o--){if(l=u[o],r.relative[c=l.type])break;if((f=r.find[c])&&(i=f(l.matches[0].replace(Z,ee),K.test(u[0].type)&&ge(t.parentNode)||t))){if(u.splice(o,1),!(e=i.length&&ve(u)))return L.apply(n,i),n;break}}}return(p||s(e,d))(i,t,!g,n,!t||K.test(e)&&ge(t.parentNode)||t),n},n.sortStable=b.split("").sort(D).join("")===b,n.detectDuplicates=!!f,p(),n.sortDetached=ue(function(e){return 1&e.compareDocumentPosition(d.createElement("fieldset"))}),ue(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||le("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),n.attributes&&ue(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||le("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ue(function(e){return null==e.getAttribute("disabled")})||le(P,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),oe}(e);w.find=E,w.expr=E.selectors,w.expr[":"]=w.expr.pseudos,w.uniqueSort=w.unique=E.uniqueSort,w.text=E.getText,w.isXMLDoc=E.isXML,w.contains=E.contains,w.escapeSelector=E.escape;var k=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&w(e).is(n))break;r.push(e)}return r},S=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},D=w.expr.match.needsContext;function N(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var A=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,t,n){return g(t)?w.grep(e,function(e,r){return!!t.call(e,r,e)!==n}):t.nodeType?w.grep(e,function(e){return e===t!==n}):"string"!=typeof t?w.grep(e,function(e){return u.call(t,e)>-1!==n}):w.filter(t,e,n)}w.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?w.find.matchesSelector(r,e)?[r]:[]:w.find.matches(e,w.grep(t,function(e){return 1===e.nodeType}))},w.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(w(e).filter(function(){for(t=0;t1?w.uniqueSort(n):n},filter:function(e){return this.pushStack(j(this,e||[],!1))},not:function(e){return this.pushStack(j(this,e||[],!0))},is:function(e){return!!j(this,"string"==typeof e&&D.test(e)?w(e):e||[],!1).length}});var q,L=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(w.fn.init=function(e,t,n){var i,o;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(i="<"===e[0]&&">"===e[e.length-1]&&e.length>=3?[null,e,null]:L.exec(e))||!i[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(i[1]){if(t=t instanceof w?t[0]:t,w.merge(this,w.parseHTML(i[1],t&&t.nodeType?t.ownerDocument||t:r,!0)),A.test(i[1])&&w.isPlainObject(t))for(i in t)g(this[i])?this[i](t[i]):this.attr(i,t[i]);return this}return(o=r.getElementById(i[2]))&&(this[0]=o,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):g(e)?void 0!==n.ready?n.ready(e):e(w):w.makeArray(e,this)}).prototype=w.fn,q=w(r);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};w.fn.extend({has:function(e){var t=w(e,this),n=t.length;return this.filter(function(){for(var e=0;e-1:1===n.nodeType&&w.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?w.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?u.call(w(e),this[0]):u.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(w.uniqueSort(w.merge(this.get(),w(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}w.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return k(e,"parentNode")},parentsUntil:function(e,t,n){return k(e,"parentNode",n)},next:function(e){return P(e,"nextSibling")},prev:function(e){return P(e,"previousSibling")},nextAll:function(e){return k(e,"nextSibling")},prevAll:function(e){return k(e,"previousSibling")},nextUntil:function(e,t,n){return k(e,"nextSibling",n)},prevUntil:function(e,t,n){return k(e,"previousSibling",n)},siblings:function(e){return S((e.parentNode||{}).firstChild,e)},children:function(e){return S(e.firstChild)},contents:function(e){return N(e,"iframe")?e.contentDocument:(N(e,"template")&&(e=e.content||e),w.merge([],e.childNodes))}},function(e,t){w.fn[e]=function(n,r){var i=w.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=w.filter(r,i)),this.length>1&&(O[e]||w.uniqueSort(i),H.test(e)&&i.reverse()),this.pushStack(i)}});var M=/[^\x20\t\r\n\f]+/g;function R(e){var t={};return w.each(e.match(M)||[],function(e,n){t[n]=!0}),t}w.Callbacks=function(e){e="string"==typeof e?R(e):w.extend({},e);var t,n,r,i,o=[],a=[],s=-1,u=function(){for(i=i||e.once,r=t=!0;a.length;s=-1){n=a.shift();while(++s-1)o.splice(n,1),n<=s&&s--}),this},has:function(e){return e?w.inArray(e,o)>-1:o.length>0},empty:function(){return o&&(o=[]),this},disable:function(){return i=a=[],o=n="",this},disabled:function(){return!o},lock:function(){return i=a=[],n||t||(o=n=""),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=[e,(n=n||[]).slice?n.slice():n],a.push(n),t||u()),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!r}};return l};function I(e){return e}function W(e){throw e}function $(e,t,n,r){var i;try{e&&g(i=e.promise)?i.call(e).done(t).fail(n):e&&g(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}w.extend({Deferred:function(t){var n=[["notify","progress",w.Callbacks("memory"),w.Callbacks("memory"),2],["resolve","done",w.Callbacks("once memory"),w.Callbacks("once memory"),0,"resolved"],["reject","fail",w.Callbacks("once memory"),w.Callbacks("once memory"),1,"rejected"]],r="pending",i={state:function(){return r},always:function(){return o.done(arguments).fail(arguments),this},"catch":function(e){return i.then(null,e)},pipe:function(){var e=arguments;return w.Deferred(function(t){w.each(n,function(n,r){var i=g(e[r[4]])&&e[r[4]];o[r[1]](function(){var e=i&&i.apply(this,arguments);e&&g(e.promise)?e.promise().progress(t.notify).done(t.resolve).fail(t.reject):t[r[0]+"With"](this,i?[e]:arguments)})}),e=null}).promise()},then:function(t,r,i){var o=0;function a(t,n,r,i){return function(){var s=this,u=arguments,l=function(){var e,l;if(!(t=o&&(r!==W&&(s=void 0,u=[e]),n.rejectWith(s,u))}};t?c():(w.Deferred.getStackHook&&(c.stackTrace=w.Deferred.getStackHook()),e.setTimeout(c))}}return w.Deferred(function(e){n[0][3].add(a(0,e,g(i)?i:I,e.notifyWith)),n[1][3].add(a(0,e,g(t)?t:I)),n[2][3].add(a(0,e,g(r)?r:W))}).promise()},promise:function(e){return null!=e?w.extend(e,i):i}},o={};return w.each(n,function(e,t){var a=t[2],s=t[5];i[t[1]]=a.add,s&&a.add(function(){r=s},n[3-e][2].disable,n[3-e][3].disable,n[0][2].lock,n[0][3].lock),a.add(t[3].fire),o[t[0]]=function(){return o[t[0]+"With"](this===o?void 0:this,arguments),this},o[t[0]+"With"]=a.fireWith}),i.promise(o),t&&t.call(o,o),o},when:function(e){var t=arguments.length,n=t,r=Array(n),i=o.call(arguments),a=w.Deferred(),s=function(e){return function(n){r[e]=this,i[e]=arguments.length>1?o.call(arguments):n,--t||a.resolveWith(r,i)}};if(t<=1&&($(e,a.done(s(n)).resolve,a.reject,!t),"pending"===a.state()||g(i[n]&&i[n].then)))return a.then();while(n--)$(i[n],s(n),a.reject);return a.promise()}});var B=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;w.Deferred.exceptionHook=function(t,n){e.console&&e.console.warn&&t&&B.test(t.name)&&e.console.warn("jQuery.Deferred exception: "+t.message,t.stack,n)},w.readyException=function(t){e.setTimeout(function(){throw t})};var F=w.Deferred();w.fn.ready=function(e){return F.then(e)["catch"](function(e){w.readyException(e)}),this},w.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--w.readyWait:w.isReady)||(w.isReady=!0,!0!==e&&--w.readyWait>0||F.resolveWith(r,[w]))}}),w.ready.then=F.then;function _(){r.removeEventListener("DOMContentLoaded",_),e.removeEventListener("load",_),w.ready()}"complete"===r.readyState||"loading"!==r.readyState&&!r.documentElement.doScroll?e.setTimeout(w.ready):(r.addEventListener("DOMContentLoaded",_),e.addEventListener("load",_));var z=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===x(n)){i=!0;for(s in n)z(e,t,s,n[s],!0,o,a)}else if(void 0!==r&&(i=!0,g(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(w(e),n)})),t))for(;s1,null,!0)},removeData:function(e){return this.each(function(){K.remove(this,e)})}}),w.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=J.get(e,t),n&&(!r||Array.isArray(n)?r=J.access(e,t,w.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=w.queue(e,t),r=n.length,i=n.shift(),o=w._queueHooks(e,t),a=function(){w.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return J.get(e,n)||J.access(e,n,{empty:w.Callbacks("once memory").add(function(){J.remove(e,[t+"queue",n])})})}}),w.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length\x20\t\r\n\f]+)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ge.optgroup=ge.option,ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td;function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&N(e,t)?w.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n-1)i&&i.push(o);else if(l=w.contains(o.ownerDocument,o),a=ye(f.appendChild(o),"script"),l&&ve(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}!function(){var e=r.createDocumentFragment().appendChild(r.createElement("div")),t=r.createElement("input");t.setAttribute("type","radio"),t.setAttribute("checked","checked"),t.setAttribute("name","t"),e.appendChild(t),h.checkClone=e.cloneNode(!0).cloneNode(!0).lastChild.checked,e.innerHTML="",h.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue}();var be=r.documentElement,we=/^key/,Te=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ce=/^([^.]*)(?:\.(.+)|)/;function Ee(){return!0}function ke(){return!1}function Se(){try{return r.activeElement}catch(e){}}function De(e,t,n,r,i,o){var a,s;if("object"==typeof t){"string"!=typeof n&&(r=r||n,n=void 0);for(s in t)De(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=ke;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return w().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=w.guid++)),e.each(function(){w.event.add(this,t,i,r,n)})}w.event={global:{},add:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.get(e);if(y){n.handler&&(n=(o=n).handler,i=o.selector),i&&w.find.matchesSelector(be,i),n.guid||(n.guid=w.guid++),(u=y.events)||(u=y.events={}),(a=y.handle)||(a=y.handle=function(t){return"undefined"!=typeof w&&w.event.triggered!==t.type?w.event.dispatch.apply(e,arguments):void 0}),l=(t=(t||"").match(M)||[""]).length;while(l--)d=g=(s=Ce.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=w.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=w.event.special[d]||{},c=w.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&w.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(e,r,h,a)||e.addEventListener&&e.addEventListener(d,a)),f.add&&(f.add.call(e,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),w.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.hasData(e)&&J.get(e);if(y&&(u=y.events)){l=(t=(t||"").match(M)||[""]).length;while(l--)if(s=Ce.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){f=w.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,y.handle)||w.removeEvent(e,d,y.handle),delete u[d])}else for(d in u)w.event.remove(e,d+t[l],n,r,!0);w.isEmptyObject(u)&&J.remove(e,"handle events")}},dispatch:function(e){var t=w.event.fix(e),n,r,i,o,a,s,u=new Array(arguments.length),l=(J.get(this,"events")||{})[t.type]||[],c=w.event.special[t.type]||{};for(u[0]=t,n=1;n=1))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n-1:w.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u\x20\t\r\n\f]*)[^>]*)\/>/gi,Ae=/\s*$/g;function Le(e,t){return N(e,"table")&&N(11!==t.nodeType?t:t.firstChild,"tr")?w(e).children("tbody")[0]||e:e}function He(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Oe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Pe(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(J.hasData(e)&&(o=J.access(e),a=J.set(t,o),l=o.events)){delete a.handle,a.events={};for(i in l)for(n=0,r=l[i].length;n1&&"string"==typeof y&&!h.checkClone&&je.test(y))return e.each(function(i){var o=e.eq(i);v&&(t[0]=y.call(this,i,o.html())),Re(o,t,n,r)});if(p&&(i=xe(t,e[0].ownerDocument,!1,e,r),o=i.firstChild,1===i.childNodes.length&&(i=o),o||r)){for(u=(s=w.map(ye(i,"script"),He)).length;f")},clone:function(e,t,n){var r,i,o,a,s=e.cloneNode(!0),u=w.contains(e.ownerDocument,e);if(!(h.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||w.isXMLDoc(e)))for(a=ye(s),r=0,i=(o=ye(e)).length;r0&&ve(a,!u&&ye(e,"script")),s},cleanData:function(e){for(var t,n,r,i=w.event.special,o=0;void 0!==(n=e[o]);o++)if(Y(n)){if(t=n[J.expando]){if(t.events)for(r in t.events)i[r]?w.event.remove(n,r):w.removeEvent(n,r,t.handle);n[J.expando]=void 0}n[K.expando]&&(n[K.expando]=void 0)}}}),w.fn.extend({detach:function(e){return Ie(this,e,!0)},remove:function(e){return Ie(this,e)},text:function(e){return z(this,function(e){return void 0===e?w.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Re(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Le(this,e).appendChild(e)})},prepend:function(){return Re(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Le(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(w.cleanData(ye(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return w.clone(this,e,t)})},html:function(e){return z(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!Ae.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=w.htmlPrefilter(e);try{for(;n=0&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))),u}function et(e,t,n){var r=$e(e),i=Fe(e,t,r),o="border-box"===w.css(e,"boxSizing",!1,r),a=o;if(We.test(i)){if(!n)return i;i="auto"}return a=a&&(h.boxSizingReliable()||i===e.style[t]),("auto"===i||!parseFloat(i)&&"inline"===w.css(e,"display",!1,r))&&(i=e["offset"+t[0].toUpperCase()+t.slice(1)],a=!0),(i=parseFloat(i)||0)+Ze(e,t,n||(o?"border":"content"),a,r,i)+"px"}w.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Fe(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=G(t),u=Xe.test(t),l=e.style;if(u||(t=Je(s)),a=w.cssHooks[t]||w.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"==(o=typeof n)&&(i=ie.exec(n))&&i[1]&&(n=ue(e,t,i),o="number"),null!=n&&n===n&&("number"===o&&(n+=i&&i[3]||(w.cssNumber[s]?"":"px")),h.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=G(t);return Xe.test(t)||(t=Je(s)),(a=w.cssHooks[t]||w.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=Fe(e,t,r)),"normal"===i&&t in Ve&&(i=Ve[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),w.each(["height","width"],function(e,t){w.cssHooks[t]={get:function(e,n,r){if(n)return!ze.test(w.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?et(e,t,r):se(e,Ue,function(){return et(e,t,r)})},set:function(e,n,r){var i,o=$e(e),a="border-box"===w.css(e,"boxSizing",!1,o),s=r&&Ze(e,t,r,a,o);return a&&h.scrollboxSize()===o.position&&(s-=Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-parseFloat(o[t])-Ze(e,t,"border",!1,o)-.5)),s&&(i=ie.exec(n))&&"px"!==(i[3]||"px")&&(e.style[t]=n,n=w.css(e,t)),Ke(e,n,s)}}}),w.cssHooks.marginLeft=_e(h.reliableMarginLeft,function(e,t){if(t)return(parseFloat(Fe(e,"marginLeft"))||e.getBoundingClientRect().left-se(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),w.each({margin:"",padding:"",border:"Width"},function(e,t){w.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];r<4;r++)i[e+oe[r]+t]=o[r]||o[r-2]||o[0];return i}},"margin"!==e&&(w.cssHooks[e+t].set=Ke)}),w.fn.extend({css:function(e,t){return z(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=$e(e),i=t.length;a1)}});function tt(e,t,n,r,i){return new tt.prototype.init(e,t,n,r,i)}w.Tween=tt,tt.prototype={constructor:tt,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||w.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(w.cssNumber[n]?"":"px")},cur:function(){var e=tt.propHooks[this.prop];return e&&e.get?e.get(this):tt.propHooks._default.get(this)},run:function(e){var t,n=tt.propHooks[this.prop];return this.options.duration?this.pos=t=w.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):tt.propHooks._default.set(this),this}},tt.prototype.init.prototype=tt.prototype,tt.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=w.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){w.fx.step[e.prop]?w.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[w.cssProps[e.prop]]&&!w.cssHooks[e.prop]?e.elem[e.prop]=e.now:w.style(e.elem,e.prop,e.now+e.unit)}}},tt.propHooks.scrollTop=tt.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},w.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},w.fx=tt.prototype.init,w.fx.step={};var nt,rt,it=/^(?:toggle|show|hide)$/,ot=/queueHooks$/;function at(){rt&&(!1===r.hidden&&e.requestAnimationFrame?e.requestAnimationFrame(at):e.setTimeout(at,w.fx.interval),w.fx.tick())}function st(){return e.setTimeout(function(){nt=void 0}),nt=Date.now()}function ut(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=oe[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function lt(e,t,n){for(var r,i=(pt.tweeners[t]||[]).concat(pt.tweeners["*"]),o=0,a=i.length;o1)},removeAttr:function(e){return this.each(function(){w.removeAttr(this,e)})}}),w.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?w.prop(e,t,n):(1===o&&w.isXMLDoc(e)||(i=w.attrHooks[t.toLowerCase()]||(w.expr.match.bool.test(t)?dt:void 0)),void 0!==n?null===n?void w.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=w.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!h.radioValue&&"radio"===t&&N(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(M);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),dt={set:function(e,t,n){return!1===t?w.removeAttr(e,n):e.setAttribute(n,n),n}},w.each(w.expr.match.bool.source.match(/\w+/g),function(e,t){var n=ht[t]||w.find.attr;ht[t]=function(e,t,r){var i,o,a=t.toLowerCase();return r||(o=ht[a],ht[a]=i,i=null!=n(e,t,r)?a:null,ht[a]=o),i}});var gt=/^(?:input|select|textarea|button)$/i,yt=/^(?:a|area)$/i;w.fn.extend({prop:function(e,t){return z(this,w.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[w.propFix[e]||e]})}}),w.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&w.isXMLDoc(e)||(t=w.propFix[t]||t,i=w.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=w.find.attr(e,"tabindex");return t?parseInt(t,10):gt.test(e.nodeName)||yt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),h.optSelected||(w.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),w.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){w.propFix[this.toLowerCase()]=this});function vt(e){return(e.match(M)||[]).join(" ")}function mt(e){return e.getAttribute&&e.getAttribute("class")||""}function xt(e){return Array.isArray(e)?e:"string"==typeof e?e.match(M)||[]:[]}w.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).addClass(e.call(this,t,mt(this)))});if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).removeClass(e.call(this,t,mt(this)))});if(!arguments.length)return this.attr("class","");if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])while(r.indexOf(" "+o+" ")>-1)r=r.replace(" "+o+" "," ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(e,t){var n=typeof e,r="string"===n||Array.isArray(e);return"boolean"==typeof t&&r?t?this.addClass(e):this.removeClass(e):g(e)?this.each(function(n){w(this).toggleClass(e.call(this,n,mt(this),t),t)}):this.each(function(){var t,i,o,a;if(r){i=0,o=w(this),a=xt(e);while(t=a[i++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else void 0!==e&&"boolean"!==n||((t=mt(this))&&J.set(this,"__className__",t),this.setAttribute&&this.setAttribute("class",t||!1===e?"":J.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&(" "+vt(mt(n))+" ").indexOf(t)>-1)return!0;return!1}});var bt=/\r/g;w.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=g(e),this.each(function(n){var i;1===this.nodeType&&(null==(i=r?e.call(this,n,w(this).val()):e)?i="":"number"==typeof i?i+="":Array.isArray(i)&&(i=w.map(i,function(e){return null==e?"":e+""})),(t=w.valHooks[this.type]||w.valHooks[this.nodeName.toLowerCase()])&&"set"in t&&void 0!==t.set(this,i,"value")||(this.value=i))});if(i)return(t=w.valHooks[i.type]||w.valHooks[i.nodeName.toLowerCase()])&&"get"in t&&void 0!==(n=t.get(i,"value"))?n:"string"==typeof(n=i.value)?n.replace(bt,""):null==n?"":n}}}),w.extend({valHooks:{option:{get:function(e){var t=w.find.attr(e,"value");return null!=t?t:vt(w.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r-1)&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),w.each(["radio","checkbox"],function(){w.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=w.inArray(w(e).val(),t)>-1}},h.checkOn||(w.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),h.focusin="onfocusin"in e;var wt=/^(?:focusinfocus|focusoutblur)$/,Tt=function(e){e.stopPropagation()};w.extend(w.event,{trigger:function(t,n,i,o){var a,s,u,l,c,p,d,h,v=[i||r],m=f.call(t,"type")?t.type:t,x=f.call(t,"namespace")?t.namespace.split("."):[];if(s=h=u=i=i||r,3!==i.nodeType&&8!==i.nodeType&&!wt.test(m+w.event.triggered)&&(m.indexOf(".")>-1&&(m=(x=m.split(".")).shift(),x.sort()),c=m.indexOf(":")<0&&"on"+m,t=t[w.expando]?t:new w.Event(m,"object"==typeof t&&t),t.isTrigger=o?2:3,t.namespace=x.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+x.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=i),n=null==n?[t]:w.makeArray(n,[t]),d=w.event.special[m]||{},o||!d.trigger||!1!==d.trigger.apply(i,n))){if(!o&&!d.noBubble&&!y(i)){for(l=d.delegateType||m,wt.test(l+m)||(s=s.parentNode);s;s=s.parentNode)v.push(s),u=s;u===(i.ownerDocument||r)&&v.push(u.defaultView||u.parentWindow||e)}a=0;while((s=v[a++])&&!t.isPropagationStopped())h=s,t.type=a>1?l:d.bindType||m,(p=(J.get(s,"events")||{})[t.type]&&J.get(s,"handle"))&&p.apply(s,n),(p=c&&s[c])&&p.apply&&Y(s)&&(t.result=p.apply(s,n),!1===t.result&&t.preventDefault());return t.type=m,o||t.isDefaultPrevented()||d._default&&!1!==d._default.apply(v.pop(),n)||!Y(i)||c&&g(i[m])&&!y(i)&&((u=i[c])&&(i[c]=null),w.event.triggered=m,t.isPropagationStopped()&&h.addEventListener(m,Tt),i[m](),t.isPropagationStopped()&&h.removeEventListener(m,Tt),w.event.triggered=void 0,u&&(i[c]=u)),t.result}},simulate:function(e,t,n){var r=w.extend(new w.Event,n,{type:e,isSimulated:!0});w.event.trigger(r,null,t)}}),w.fn.extend({trigger:function(e,t){return this.each(function(){w.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return w.event.trigger(e,t,n,!0)}}),h.focusin||w.each({focus:"focusin",blur:"focusout"},function(e,t){var n=function(e){w.event.simulate(t,e.target,w.event.fix(e))};w.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=J.access(r,t);i||r.addEventListener(e,n,!0),J.access(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=J.access(r,t)-1;i?J.access(r,t,i):(r.removeEventListener(e,n,!0),J.remove(r,t))}}});var Ct=e.location,Et=Date.now(),kt=/\?/;w.parseXML=function(t){var n;if(!t||"string"!=typeof t)return null;try{n=(new e.DOMParser).parseFromString(t,"text/xml")}catch(e){n=void 0}return n&&!n.getElementsByTagName("parsererror").length||w.error("Invalid XML: "+t),n};var St=/\[\]$/,Dt=/\r?\n/g,Nt=/^(?:submit|button|image|reset|file)$/i,At=/^(?:input|select|textarea|keygen)/i;function jt(e,t,n,r){var i;if(Array.isArray(t))w.each(t,function(t,i){n||St.test(e)?r(e,i):jt(e+"["+("object"==typeof i&&null!=i?t:"")+"]",i,n,r)});else if(n||"object"!==x(t))r(e,t);else for(i in t)jt(e+"["+i+"]",t[i],n,r)}w.param=function(e,t){var n,r=[],i=function(e,t){var n=g(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(Array.isArray(e)||e.jquery&&!w.isPlainObject(e))w.each(e,function(){i(this.name,this.value)});else for(n in e)jt(n,e[n],t,i);return r.join("&")},w.fn.extend({serialize:function(){return w.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=w.prop(this,"elements");return e?w.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!w(this).is(":disabled")&&At.test(this.nodeName)&&!Nt.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=w(this).val();return null==n?null:Array.isArray(n)?w.map(n,function(e){return{name:t.name,value:e.replace(Dt,"\r\n")}}):{name:t.name,value:n.replace(Dt,"\r\n")}}).get()}});var qt=/%20/g,Lt=/#.*$/,Ht=/([?&])_=[^&]*/,Ot=/^(.*?):[ \t]*([^\r\n]*)$/gm,Pt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Mt=/^(?:GET|HEAD)$/,Rt=/^\/\//,It={},Wt={},$t="*/".concat("*"),Bt=r.createElement("a");Bt.href=Ct.href;function Ft(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(M)||[];if(g(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function _t(e,t,n,r){var i={},o=e===Wt;function a(s){var u;return i[s]=!0,w.each(e[s]||[],function(e,s){var l=s(t,n,r);return"string"!=typeof l||o||i[l]?o?!(u=l):void 0:(t.dataTypes.unshift(l),a(l),!1)}),u}return a(t.dataTypes[0])||!i["*"]&&a("*")}function zt(e,t){var n,r,i=w.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&w.extend(!0,e,r),e}function Xt(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}function Ut(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}w.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Ct.href,type:"GET",isLocal:Pt.test(Ct.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":$t,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":w.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?zt(zt(e,w.ajaxSettings),t):zt(w.ajaxSettings,e)},ajaxPrefilter:Ft(It),ajaxTransport:Ft(Wt),ajax:function(t,n){"object"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,p,d,h=w.ajaxSetup({},n),g=h.context||h,y=h.context&&(g.nodeType||g.jquery)?w(g):w.event,v=w.Deferred(),m=w.Callbacks("once memory"),x=h.statusCode||{},b={},T={},C="canceled",E={readyState:0,getResponseHeader:function(e){var t;if(c){if(!s){s={};while(t=Ot.exec(a))s[t[1].toLowerCase()]=t[2]}t=s[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return c?a:null},setRequestHeader:function(e,t){return null==c&&(e=T[e.toLowerCase()]=T[e.toLowerCase()]||e,b[e]=t),this},overrideMimeType:function(e){return null==c&&(h.mimeType=e),this},statusCode:function(e){var t;if(e)if(c)E.always(e[E.status]);else for(t in e)x[t]=[x[t],e[t]];return this},abort:function(e){var t=e||C;return i&&i.abort(t),k(0,t),this}};if(v.promise(E),h.url=((t||h.url||Ct.href)+"").replace(Rt,Ct.protocol+"//"),h.type=n.method||n.type||h.method||h.type,h.dataTypes=(h.dataType||"*").toLowerCase().match(M)||[""],null==h.crossDomain){l=r.createElement("a");try{l.href=h.url,l.href=l.href,h.crossDomain=Bt.protocol+"//"+Bt.host!=l.protocol+"//"+l.host}catch(e){h.crossDomain=!0}}if(h.data&&h.processData&&"string"!=typeof h.data&&(h.data=w.param(h.data,h.traditional)),_t(It,h,n,E),c)return E;(f=w.event&&h.global)&&0==w.active++&&w.event.trigger("ajaxStart"),h.type=h.type.toUpperCase(),h.hasContent=!Mt.test(h.type),o=h.url.replace(Lt,""),h.hasContent?h.data&&h.processData&&0===(h.contentType||"").indexOf("application/x-www-form-urlencoded")&&(h.data=h.data.replace(qt,"+")):(d=h.url.slice(o.length),h.data&&(h.processData||"string"==typeof h.data)&&(o+=(kt.test(o)?"&":"?")+h.data,delete h.data),!1===h.cache&&(o=o.replace(Ht,"$1"),d=(kt.test(o)?"&":"?")+"_="+Et+++d),h.url=o+d),h.ifModified&&(w.lastModified[o]&&E.setRequestHeader("If-Modified-Since",w.lastModified[o]),w.etag[o]&&E.setRequestHeader("If-None-Match",w.etag[o])),(h.data&&h.hasContent&&!1!==h.contentType||n.contentType)&&E.setRequestHeader("Content-Type",h.contentType),E.setRequestHeader("Accept",h.dataTypes[0]&&h.accepts[h.dataTypes[0]]?h.accepts[h.dataTypes[0]]+("*"!==h.dataTypes[0]?", "+$t+"; q=0.01":""):h.accepts["*"]);for(p in h.headers)E.setRequestHeader(p,h.headers[p]);if(h.beforeSend&&(!1===h.beforeSend.call(g,E,h)||c))return E.abort();if(C="abort",m.add(h.complete),E.done(h.success),E.fail(h.error),i=_t(Wt,h,n,E)){if(E.readyState=1,f&&y.trigger("ajaxSend",[E,h]),c)return E;h.async&&h.timeout>0&&(u=e.setTimeout(function(){E.abort("timeout")},h.timeout));try{c=!1,i.send(b,k)}catch(e){if(c)throw e;k(-1,e)}}else k(-1,"No Transport");function k(t,n,r,s){var l,p,d,b,T,C=n;c||(c=!0,u&&e.clearTimeout(u),i=void 0,a=s||"",E.readyState=t>0?4:0,l=t>=200&&t<300||304===t,r&&(b=Xt(h,E,r)),b=Ut(h,b,E,l),l?(h.ifModified&&((T=E.getResponseHeader("Last-Modified"))&&(w.lastModified[o]=T),(T=E.getResponseHeader("etag"))&&(w.etag[o]=T)),204===t||"HEAD"===h.type?C="nocontent":304===t?C="notmodified":(C=b.state,p=b.data,l=!(d=b.error))):(d=C,!t&&C||(C="error",t<0&&(t=0))),E.status=t,E.statusText=(n||C)+"",l?v.resolveWith(g,[p,C,E]):v.rejectWith(g,[E,C,d]),E.statusCode(x),x=void 0,f&&y.trigger(l?"ajaxSuccess":"ajaxError",[E,h,l?p:d]),m.fireWith(g,[E,C]),f&&(y.trigger("ajaxComplete",[E,h]),--w.active||w.event.trigger("ajaxStop")))}return E},getJSON:function(e,t,n){return w.get(e,t,n,"json")},getScript:function(e,t){return w.get(e,void 0,t,"script")}}),w.each(["get","post"],function(e,t){w[t]=function(e,n,r,i){return g(n)&&(i=i||r,r=n,n=void 0),w.ajax(w.extend({url:e,type:t,dataType:i,data:n,success:r},w.isPlainObject(e)&&e))}}),w._evalUrl=function(e){return w.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},w.fn.extend({wrapAll:function(e){var t;return this[0]&&(g(e)&&(e=e.call(this[0])),t=w(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(e){return g(e)?this.each(function(t){w(this).wrapInner(e.call(this,t))}):this.each(function(){var t=w(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=g(e);return this.each(function(n){w(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(e){return this.parent(e).not("body").each(function(){w(this).replaceWith(this.childNodes)}),this}}),w.expr.pseudos.hidden=function(e){return!w.expr.pseudos.visible(e)},w.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},w.ajaxSettings.xhr=function(){try{return new e.XMLHttpRequest}catch(e){}};var Vt={0:200,1223:204},Gt=w.ajaxSettings.xhr();h.cors=!!Gt&&"withCredentials"in Gt,h.ajax=Gt=!!Gt,w.ajaxTransport(function(t){var n,r;if(h.cors||Gt&&!t.crossDomain)return{send:function(i,o){var a,s=t.xhr();if(s.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(a in t.xhrFields)s[a]=t.xhrFields[a];t.mimeType&&s.overrideMimeType&&s.overrideMimeType(t.mimeType),t.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");for(a in i)s.setRequestHeader(a,i[a]);n=function(e){return function(){n&&(n=r=s.onload=s.onerror=s.onabort=s.ontimeout=s.onreadystatechange=null,"abort"===e?s.abort():"error"===e?"number"!=typeof s.status?o(0,"error"):o(s.status,s.statusText):o(Vt[s.status]||s.status,s.statusText,"text"!==(s.responseType||"text")||"string"!=typeof s.responseText?{binary:s.response}:{text:s.responseText},s.getAllResponseHeaders()))}},s.onload=n(),r=s.onerror=s.ontimeout=n("error"),void 0!==s.onabort?s.onabort=r:s.onreadystatechange=function(){4===s.readyState&&e.setTimeout(function(){n&&r()})},n=n("abort");try{s.send(t.hasContent&&t.data||null)}catch(e){if(n)throw e}},abort:function(){n&&n()}}}),w.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),w.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return w.globalEval(e),e}}}),w.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),w.ajaxTransport("script",function(e){if(e.crossDomain){var t,n;return{send:function(i,o){t=w(" - - - - -{% endcompress %} - -{% compress css %} - -{% endcompress %} -{{ block.super }} -{% endblock %} - +{% load admin_static i18n staticfiles %} {% block branding %} -

{% trans 'Seeker' %}

+

{% trans 'Seeker' %}

{% endblock %} diff --git a/seeker/templates/admin/index.html b/seeker/templates/admin/index.html deleted file mode 100644 index 9188e5b..0000000 --- a/seeker/templates/admin/index.html +++ /dev/null @@ -1,84 +0,0 @@ -{% extends "admin/base_site.html" %} -{% load i18n static %} - -{% block extrastyle %} -{{ block.super }} - -{% endblock %} - -{% block coltype %}colMS{% endblock %} - -{% block bodyclass %}{{ block.super }} dashboard{% endblock %} - -{% block breadcrumbs %}{% endblock %} - -
- {% block content %} -
-
-
-

- Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the - industry's standard - dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to - make a type specimen - book. It has survived not only five centuries, but also the leap into electronic typesetting, - remaining essentially - unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem - Ipsum passages, and - more recently with desktop publishing software like Aldus PageMaker including versions of Lorem - Ipsum -

-
-
-
- {% endblock %} - - {% block sidebar %} -
-
-
-

{% trans 'Search Terms' %}

-
    - - - - - -
-
-
-
- -
-
- {% endblock %} -
diff --git a/seeker/templates/admin/login.html b/seeker/templates/admin/login.html deleted file mode 100644 index b4829fb..0000000 --- a/seeker/templates/admin/login.html +++ /dev/null @@ -1,6 +0,0 @@ -{% extends 'admin/login.html' %} -{% load i18n %} - -{% block branding %} -{{ block.super }} -{% endblock %} diff --git a/seeker/templates/base.html b/seeker/templates/base.html new file mode 100644 index 0000000..e32ea19 --- /dev/null +++ b/seeker/templates/base.html @@ -0,0 +1,48 @@ + + + + {% load compress cache staticfiles %} + + + {% block page_title %}Seeker{% endblock page_title %} + + + + + + {% compress css %} + + + + {% endcompress %} + +{% block body %} + + + {% include 'includes/navigation.html' %} + + {% block content %}{% endblock content %} + + + {% endblock body %} + + {% compress js %} + + + + + + + + + + + {% endcompress %} + + diff --git a/seeker/templates/includes/navigation.html b/seeker/templates/includes/navigation.html new file mode 100644 index 0000000..41b9c59 --- /dev/null +++ b/seeker/templates/includes/navigation.html @@ -0,0 +1,30 @@ +{% load staticfiles %} + diff --git a/seeker/templates/includes/pagination.html b/seeker/templates/includes/pagination.html new file mode 100644 index 0000000..fa8917c --- /dev/null +++ b/seeker/templates/includes/pagination.html @@ -0,0 +1,37 @@ +{% if is_paginated %} + +{% endif %} diff --git a/seeker/urls.py b/seeker/urls.py index 46a8fc5..f22ac34 100644 --- a/seeker/urls.py +++ b/seeker/urls.py @@ -15,8 +15,22 @@ """ from django.contrib import admin from django.urls import path, include +from django.views.generic.base import TemplateView +from rest_framework import routers + +from seeker.job import views as job_views + +router = routers.DefaultRouter(trailing_slash=False) +router.register('jobs', job_views.JobViewSet) urlpatterns = [ - path('', admin.site.urls), - path('summernote/', include('django_summernote.urls')), + path('admin/', admin.site.urls), + path('', TemplateView.as_view(template_name='dashboard.html'), name='dashboard'), + path('jobs/', job_views.JobListView.as_view(), name="jobs"), + path('jobs//', job_views.JobDetailView.as_view(), name="job_detail"), + path('search/', job_views.SearchResultsView.as_view(), name="search_results"), + path('feed/', job_views.JobsFeed(), name="rss"), + path('api/v1/', include(router.urls)), ] + +import seeker.jobs # noqa diff --git a/tox.ini b/tox.ini index 915e93a..76aea4e 100644 --- a/tox.ini +++ b/tox.ini @@ -3,28 +3,28 @@ # test suite on all supported python versions. To use it, "pip install tox" # and then run "tox" from this directory. -# [tox] -# envlist = python3.7,flake8 +[tox] +envlist = py38,flake8 -# [testenv:python3.7] -# testpaths = tests seeker -# deps = -r{toxinidir}/requirements.txt -# commands = pytest {posargs} -# setenv = -# PYTHONPATH = {toxinidir} +[testenv:py36] +testpaths = tests finder +deps = -r{toxinidir}/requirements.txt +commands = pytest {posargs} +setenv = + PYTHONPATH = {toxinidir} -# [testenv:flake8] -# commands = flake8 -# deps = flake8>=3.5.0 +[testenv:flake8] +commands = flake8 +deps = flake8>=3.7.0 -# [travis] -# python = -# 3.6: python3.7, flake8 +[travis] +python = + 3.8: py38, flake8 -# [pytest] -# addopts = --ignore=setup.py -# python_files = test_*.py -# python_functions = test_* +[pytest] +addopts = --ignore=setup.py +python_files = test_*.py +python_functions = test_* [flake8] # D100: Missing docstring in public module @@ -39,9 +39,14 @@ # E501: Line too long # N805: First argument of a method should be named 'self' # N806: Variable in function should be lowercase -ignore = D100,D101,D102,D103,D105,D200,D202,D400,D401,E501,N805,N806 +ignore = D100, D101, D102, D103, D105, D200, D202, D400, D401, E501, N805, N806 exclude = .git, .tox, build, dist +max-line-length = 130 [pycodestyle] -ignore = D100,D101,D102,D103,D105,D200,D202,D400,D401,E501,N805,N806 +ignore = D100, D101, D102, D103, D105, D200, D202, D400, D401, E501, N805, N806 +exclude = .git, .tox, build, dist + +[pydocstyle] +ignore = D100, D101, D102, D103, D105, D200, D202, D400, D401, E501, N805, N806 exclude = .git, .tox, build, dist From 39b03abba87e70cce7ad5c99f8734e8fe56f3010 Mon Sep 17 00:00:00 2001 From: Nathan Workman Date: Tue, 21 Jan 2020 22:20:49 -0500 Subject: [PATCH 2/2] Remove dead make commands. Change compose back to befault ports. --- .gitignore | 3 - Makefile | 140 --------------------------------------------- docker-compose.yml | 15 ++--- 3 files changed, 4 insertions(+), 154 deletions(-) diff --git a/.gitignore b/.gitignore index 8a7b501..de71a08 100644 --- a/.gitignore +++ b/.gitignore @@ -54,6 +54,3 @@ out.csv *.db /results *.log - - -# diff --git a/Makefile b/Makefile index 605168e..8927a89 100644 --- a/Makefile +++ b/Makefile @@ -63,143 +63,3 @@ up: ( \ $(COMPOSE) up; \ ) - -visual: -# Generate visual representation of database - $(call ECHO_GREEN, Generating a pretty image...) - (\ - $(COMPOSE) $(COMPOSE_CMD) graph_models --pygraphviz -a -g -o visualized.png; \ - ) - -dumpdata: -# Dump database to fixture file - $(call ECHO_RED, Database dump...) - (\ - $(COMPOSE) $(COMPOSE_CMD) dumpdata --exclude auth.permission --exclude contenttypes > ./initial_data.json; \ - ) - -shell: -# Run a local shell for debugging - $(call ECHO_GREEN, Opening iPython shell...) - ( \ - $(COMPOSE) $(COMPOSE_CMD) shell; \ - ) - - - - -###################### -# OLD -###################### - -r_crawl: -# Run ALL scrapy spiders - $(call ECHO_GREEN, Running Spiders Background Process... ) - (\ - cd recognition; \ - nohup python crawl.py & \ - ) - -crawl_spider: -# Run scrapy spider - $(call ECHO_GREEN, Running $(spider) spider... ) - (\ - scrapy crawl $(spider); \ - ) - -r_crawl_spider: -# Run scrapy spider - $(call ECHO_GREEN, Running $(spider) spider as background process... ) - (\ - nohup scrapy crawl $(spider) & \ - ) - -delete_sqlite: -# delete project db - ( \ - rm -rf db.sqlite3;\ - ) - -reset_migrations: -# delete all migrations furing initial development - ( \ - find . -path "*/migrations/*.py" -not -name "__init__.py" -delete; \ - find . -path "*/migrations/*.pyc" -delete; \ - ) - -map_points: - ( \ - python manage.py plot_lng_lat;\ - ) - -r_map_points: - ( \= - nohup python manage.py plot_lng_lat & \ - ) - -validate_urls: - ( \ - python manage.py valid_url;\ - ) - -r_validate_urls: - ( \ - nohup python manage.py valid_url & \ - ) - -find_contacts: - ( \ - nohup python manage.py find_contacts & \ - ) - -map_locations: - ( \ - nohup python manage.py plot_lng_lat & \ - ) - -rank: - # Start ranking centers - (\ - python manage.py rank; \ - ) - -r_rank: - # Start ranking centers - (\ - nohup python manage.py rank & \ - ) - -sql_dump: - # dump to fixtures file - (\ - rm -rf recognition/fixtures/dump.json; \ - ./manage.py dumpdata --natural-primary --natural-foreign > fixtures/dump.json ; \ - ) - - -initial_data: -# load initial db data - ( \ - pg_restore -p 5433 -d recognition --verbose initial_data.dump; \ - ) - -r_initial_data: -# load initial db data in vm - ( \ - sudo -u postgres pg_restore -p 5433 -d recognition --verbose initial_data.dump; \ - ) - - -createuser: - - # docker exec -it seeker_app echo "from django.contrib.auth.models import User; User.objects.create_superuser('admin', 'admin@email.com', 'pass')" | ./manage.py shell; - ( \ - docker exec -it seeker_app python manage.py createsuperuser - ) - - - -# docker exec -it seeker_app python manage.py createsuperuser - - -# echo "from django.contrib.auth.models import User; User.objects.create_superuser('admin', 'admin@email.com', 'pass')" | ./manage.py shell; diff --git a/docker-compose.yml b/docker-compose.yml index 6ffccf7..91e537d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -14,12 +14,8 @@ services: - POSTGRES_DB=postgres networks: - seeker - expose: - - "5435" ports: - - "5435:5435" - command: -p 5435 - # restart: on-failure + - "5432:5432" volumes: - postgresql-data:/var/lib/postgresql/data app: @@ -27,19 +23,16 @@ services: context: . dockerfile: ./Dockerfile container_name: seeker_app - command: sh -c "python manage.py collectstatic --no-input && python manage.py migrate && python manage.py runserver 0.0.0.0:8001" - # environment: - # - DJANGO_SETTINGS_MODULE=seeker.settings.local + command: sh -c "python manage.py collectstatic --no-input && python manage.py migrate && python manage.py runserver 0.0.0.0:8000" image: seeker_image hostname: app depends_on: - postgres expose: - - "8001" + - "8000" ports: - - "8001:8001" + - "8000:8000" volumes: - .:/usr/src/app networks: - seeker - # restart: on-failure